Punt the dodgy ebuffer code. We now force prefixing for parallel starts which also reduces our variable pollution.
This commit is contained in:
parent
35d860710a
commit
356c41f77c
12
conf.d/rc
12
conf.d/rc
@ -1,16 +1,11 @@
|
|||||||
# /etc/conf.d/rc: Global config file for the Gentoo RC System
|
# /etc/conf.d/rc: Global config file for the Gentoo RC System
|
||||||
|
|
||||||
# Set to "yes" if you want the rc system to try and start services
|
# Set to "yes" if you want the rc system to try and start services
|
||||||
# in parallel for a slight speed improvement.
|
# in parallel for a slight speed improvement. When running in parallel we
|
||||||
|
# prefix the service output with it's name as the output will get
|
||||||
|
# jumbled up.
|
||||||
RC_PARALLEL="no"
|
RC_PARALLEL="no"
|
||||||
|
|
||||||
# If we're running in parallel then the output of each service is buffered
|
|
||||||
# until the service finishes. This is so the output one service is not mixed
|
|
||||||
# with the output of another service.
|
|
||||||
# To avoid buffering can prefix each line of output to see the service which
|
|
||||||
# it belongs to by setting the RC_PREFIX="yes".
|
|
||||||
RC_PREFIX="no"
|
|
||||||
|
|
||||||
# Set RC_INTERACTIVE to "yes" and you'll be able to press the I key during
|
# Set RC_INTERACTIVE to "yes" and you'll be able to press the I key during
|
||||||
# boot so you can choose to start specific services. Set to "no" to disable
|
# boot so you can choose to start specific services. Set to "no" to disable
|
||||||
# this feature.
|
# this feature.
|
||||||
@ -25,7 +20,6 @@ RC_VERBOSE="no"
|
|||||||
# output.
|
# output.
|
||||||
RC_QUIET="no"
|
RC_QUIET="no"
|
||||||
|
|
||||||
|
|
||||||
# Do we allow any started service in the runlevel to satisfy the depedency
|
# Do we allow any started service in the runlevel to satisfy the depedency
|
||||||
# or do we want all of them regardless of state? For example, if net.eth0
|
# or do we want all of them regardless of state? For example, if net.eth0
|
||||||
# and net.eth0 are in the default runlevel then with RC_STRICT_DEPEND="no"
|
# and net.eth0 are in the default runlevel then with RC_STRICT_DEPEND="no"
|
||||||
|
@ -67,20 +67,20 @@ _wait_for_carrier() {
|
|||||||
# Incase users don't want this nice feature ...
|
# Incase users don't want this nice feature ...
|
||||||
[ ${timeout} -le 0 ] && return 0
|
[ ${timeout} -le 0 ] && return 0
|
||||||
|
|
||||||
[ -n "${RC_EBUFFER}" -o "${RC_PREFIX}" = "yes" ] && efunc=einfo
|
[ "${RC_PARALLEL}" = "yes" ] && efunc=einfo
|
||||||
${efunc} "Waiting for carrier (${timeout} seconds) "
|
${efunc} "Waiting for carrier (${timeout} seconds) "
|
||||||
while [ ${timeout} -gt 0 ] ; do
|
while [ ${timeout} -gt 0 ] ; do
|
||||||
sleep 1
|
sleep 1
|
||||||
if _has_carrier ; then
|
if _has_carrier ; then
|
||||||
[ -z "${RC_EBUFFER}" ] && echo
|
[ "${efunc}" = "einfon" ] && echo
|
||||||
eend 0
|
eend 0
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
timeout=$((${timeout} - 1))
|
timeout=$((${timeout} - 1))
|
||||||
[ -z "${RC_EBUFFER}" -a "${RC_PREFIX}" != "yes" ] && printf "."
|
[ "${efunc}" = "einfon" ] && printf "."
|
||||||
done
|
done
|
||||||
|
|
||||||
[ -z "${RC_EBUFFER}" -a "${RC_PREFIX}" != "yes" ] && echo
|
[ "${efunc}" = "einfon" ] && echo
|
||||||
eend 1
|
eend 1
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@ SYS_WHITELIST = env_whitelist
|
|||||||
TARGET = $(LIB_TARGETS) $(BIN_TARGETS) $(SBIN_TARGETS) $(PRIV_BIN_TARGETS)
|
TARGET = $(LIB_TARGETS) $(BIN_TARGETS) $(SBIN_TARGETS) $(PRIV_BIN_TARGETS)
|
||||||
|
|
||||||
RCLINKS = einfon einfo ewarnn ewarn eerrorn eerror ebegin eend ewend \
|
RCLINKS = einfon einfo ewarnn ewarn eerrorn eerror ebegin eend ewend \
|
||||||
eindent eoutdent eflush eval_ecolors \
|
eindent eoutdent eval_ecolors \
|
||||||
veinfo vewarn vebegin veend vewend veindent veoutdent \
|
veinfo vewarn vebegin veend vewend veindent veoutdent \
|
||||||
service_starting service_inactive service_started \
|
service_starting service_inactive service_started \
|
||||||
service_stopping service_stopped \
|
service_stopping service_stopped \
|
||||||
|
@ -67,12 +67,4 @@ void eoutdentv (void);
|
|||||||
/* Pointer to a string that is always prefixed to einfo/ewarn/error */
|
/* Pointer to a string that is always prefixed to einfo/ewarn/error */
|
||||||
void eprefix (const char *prefix);
|
void eprefix (const char *prefix);
|
||||||
|
|
||||||
/* Handy utils to buffer stdout and stderr so our output is always
|
|
||||||
* sane when forking around.
|
|
||||||
* Don't depend on these being here though as we may take a different
|
|
||||||
* approach at a later date. */
|
|
||||||
void ebuffer (const char *file);
|
|
||||||
void eflush (void);
|
|
||||||
void eclose (void);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
131
src/libeinfo.c
131
src/libeinfo.c
@ -32,8 +32,6 @@ hidden_proto(eendv)
|
|||||||
hidden_proto(eerror)
|
hidden_proto(eerror)
|
||||||
hidden_proto(eerrorn)
|
hidden_proto(eerrorn)
|
||||||
hidden_proto(eerrorx)
|
hidden_proto(eerrorx)
|
||||||
hidden_proto(eflush)
|
|
||||||
hidden_proto(eclose)
|
|
||||||
hidden_proto(eindent)
|
hidden_proto(eindent)
|
||||||
hidden_proto(eindentv)
|
hidden_proto(eindentv)
|
||||||
hidden_proto(einfo)
|
hidden_proto(einfo)
|
||||||
@ -64,8 +62,6 @@ hidden_proto(ewendv)
|
|||||||
/* How wide can the indent go? */
|
/* How wide can the indent go? */
|
||||||
#define INDENT_MAX 40
|
#define INDENT_MAX 40
|
||||||
|
|
||||||
#define EBUFFER_LOCK RC_SVCDIR "ebuffer/.lock"
|
|
||||||
|
|
||||||
/* Default colours */
|
/* Default colours */
|
||||||
#define ECOLOR_GOOD "\033[32;01m"
|
#define ECOLOR_GOOD "\033[32;01m"
|
||||||
#define ECOLOR_WARN "\033[33;01m"
|
#define ECOLOR_WARN "\033[33;01m"
|
||||||
@ -120,10 +116,6 @@ static const char *color_terms[] = {
|
|||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
/* We use this array to save the stdout/stderr fd's for buffering */
|
|
||||||
static int stdfd[2] = {-1, -1};
|
|
||||||
static FILE *ebfp = NULL;
|
|
||||||
static char ebfile[PATH_MAX] = { '\0' };
|
|
||||||
static const char *term = NULL;
|
static const char *term = NULL;
|
||||||
static bool term_is_cons25 = false;
|
static bool term_is_cons25 = false;
|
||||||
|
|
||||||
@ -201,126 +193,6 @@ void eprefix (const char *prefix) {
|
|||||||
_eprefix = prefix;
|
_eprefix = prefix;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ebuffer (const char *file)
|
|
||||||
{
|
|
||||||
/* Don't ebuffer if we don't have a file or we already are */
|
|
||||||
if (! file || stdfd[0] >= 0 || ! isatty (fileno (stdout)))
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* Save the current fd's */
|
|
||||||
stdfd[0] = dup (fileno (stdout));
|
|
||||||
stdfd[1] = dup (fileno (stderr));
|
|
||||||
|
|
||||||
if (! (ebfp = fopen (file, "w+"))) {
|
|
||||||
fprintf (stderr, "fopen `%s': %s\n", file, strerror (errno));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
snprintf (ebfile, sizeof (ebfile), "%s", file);
|
|
||||||
|
|
||||||
fflush (stdout);
|
|
||||||
fflush (stderr);
|
|
||||||
|
|
||||||
/* Now redirect stdout and stderr */
|
|
||||||
if ((dup2 (fileno (ebfp), fileno (stdout))) < 0)
|
|
||||||
fprintf (stderr, "dup2: %s", strerror (errno));
|
|
||||||
if ((dup2 (fileno (ebfp), fileno (stderr))) < 0)
|
|
||||||
fprintf (stderr, "dup2: %s", strerror (errno));
|
|
||||||
|
|
||||||
/* Store the filename in our environment so scripts can tell if we're
|
|
||||||
* buffering or not */
|
|
||||||
unsetenv ("RC_EBUFFER");
|
|
||||||
setenv ("RC_EBUFFER", file, 1);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _eflush (bool reopen)
|
|
||||||
{
|
|
||||||
char buffer[RC_LINEBUFFER];
|
|
||||||
int serrno = errno;
|
|
||||||
|
|
||||||
/* eflush called from an init script? */
|
|
||||||
if (! ebfp) {
|
|
||||||
char *file = getenv ("RC_EBUFFER");
|
|
||||||
if (file)
|
|
||||||
ebfp = fopen (file, "a+");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! ebfp)
|
|
||||||
return;
|
|
||||||
|
|
||||||
fflush (stdout);
|
|
||||||
fflush (stderr);
|
|
||||||
|
|
||||||
/* Restore stdout and stderr now */
|
|
||||||
if (stdfd[0] >= 0) {
|
|
||||||
dup2 (stdfd[0], fileno (stdout));
|
|
||||||
dup2 (stdfd[1], fileno (stderr));
|
|
||||||
} else {
|
|
||||||
char *tty = getenv ("RC_TTY");
|
|
||||||
if (tty) {
|
|
||||||
freopen (tty, "w+", stdout);
|
|
||||||
dup2 (fileno (stdout), fileno (stderr));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Spin until we can lock the ebuffer */
|
|
||||||
while (true) {
|
|
||||||
struct timeval tv;
|
|
||||||
errno = 0;
|
|
||||||
if (mkfifo (EBUFFER_LOCK, 0700) == 0)
|
|
||||||
break;
|
|
||||||
if (errno != EEXIST)
|
|
||||||
eerror ("mkfifo `%s': %s\n", EBUFFER_LOCK, strerror (errno));
|
|
||||||
tv.tv_sec = 0;
|
|
||||||
tv.tv_usec = 20000;
|
|
||||||
select (0, NULL, NULL, NULL, &tv);
|
|
||||||
}
|
|
||||||
errno = serrno;
|
|
||||||
|
|
||||||
/* Dump the file to stdout */
|
|
||||||
memset (buffer, 0, RC_LINEBUFFER);
|
|
||||||
if (fseek (ebfp, (off_t) 0, SEEK_SET) < 0)
|
|
||||||
eerror ("fseek: %s", strerror (errno));
|
|
||||||
else {
|
|
||||||
while (fgets (buffer, RC_LINEBUFFER, ebfp))
|
|
||||||
printf ("%s", buffer);
|
|
||||||
}
|
|
||||||
fflush (stdout);
|
|
||||||
fflush (stderr);
|
|
||||||
|
|
||||||
if (unlink (EBUFFER_LOCK))
|
|
||||||
eerror ("unlink `%s': %s", EBUFFER_LOCK, strerror (errno));
|
|
||||||
|
|
||||||
if (reopen) {
|
|
||||||
ftruncate (fileno (ebfp), (off_t) 0);
|
|
||||||
fseek (ebfp, (off_t) 0, SEEK_SET);
|
|
||||||
dup2 (fileno (ebfp), fileno (stdout));
|
|
||||||
dup2 (fileno (ebfp), fileno (stderr));
|
|
||||||
} else {
|
|
||||||
stdfd[0] = -1;
|
|
||||||
stdfd[1] = -1;
|
|
||||||
fclose (ebfp);
|
|
||||||
ebfp = NULL;
|
|
||||||
unlink (ebfile);
|
|
||||||
ebfile[0] = '\0';
|
|
||||||
unsetenv ("RC_EBUFFER");
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void eflush () {
|
|
||||||
_eflush (true);
|
|
||||||
}
|
|
||||||
hidden_def(eflush)
|
|
||||||
|
|
||||||
void eclose () {
|
|
||||||
_eflush (false);
|
|
||||||
}
|
|
||||||
hidden_def(eclose)
|
|
||||||
|
|
||||||
static void elog (int level, const char *fmt, va_list ap)
|
static void elog (int level, const char *fmt, va_list ap)
|
||||||
{
|
{
|
||||||
char *e = getenv ("RC_ELOG");
|
char *e = getenv ("RC_ELOG");
|
||||||
@ -518,7 +390,6 @@ void ewarnx (const char *fmt, ...)
|
|||||||
int retval;
|
int retval;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
eclose ();
|
|
||||||
if (fmt && ! is_env ("RC_QUIET", "yes")) {
|
if (fmt && ! is_env ("RC_QUIET", "yes")) {
|
||||||
va_start (ap, fmt);
|
va_start (ap, fmt);
|
||||||
elog (LOG_WARNING, fmt, ap);
|
elog (LOG_WARNING, fmt, ap);
|
||||||
@ -544,7 +415,6 @@ int eerror (const char *fmt, ...)
|
|||||||
va_end (ap);
|
va_end (ap);
|
||||||
retval += fprintf (stderr, "\n");
|
retval += fprintf (stderr, "\n");
|
||||||
|
|
||||||
eflush ();
|
|
||||||
return (retval);
|
return (retval);
|
||||||
}
|
}
|
||||||
hidden_def(eerror)
|
hidden_def(eerror)
|
||||||
@ -553,7 +423,6 @@ void eerrorx (const char *fmt, ...)
|
|||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
eclose ();
|
|
||||||
if (fmt) {
|
if (fmt) {
|
||||||
va_start (ap, fmt);
|
va_start (ap, fmt);
|
||||||
elog (LOG_ERR, fmt, ap);
|
elog (LOG_ERR, fmt, ap);
|
||||||
|
@ -583,7 +583,6 @@ static const char *depdirs[] =
|
|||||||
RC_SVCDIR "options",
|
RC_SVCDIR "options",
|
||||||
RC_SVCDIR "exclusive",
|
RC_SVCDIR "exclusive",
|
||||||
RC_SVCDIR "scheduled",
|
RC_SVCDIR "scheduled",
|
||||||
RC_SVCDIR "ebuffer",
|
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -113,8 +113,6 @@ void rc_plugin_run (rc_hook_t hook, const char *value)
|
|||||||
if (rc_in_plugin)
|
if (rc_in_plugin)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
eflush ();
|
|
||||||
|
|
||||||
while (plugin) {
|
while (plugin) {
|
||||||
if (plugin->hook) {
|
if (plugin->hook) {
|
||||||
int i;
|
int i;
|
||||||
@ -186,8 +184,6 @@ void rc_plugin_run (rc_hook_t hook, const char *value)
|
|||||||
}
|
}
|
||||||
plugin = plugin->next;
|
plugin = plugin->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
eflush ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void rc_plugin_unload (void)
|
void rc_plugin_unload (void)
|
||||||
|
2
src/rc.c
2
src/rc.c
@ -211,8 +211,6 @@ static int do_e (int argc, char **argv)
|
|||||||
eindentv ();
|
eindentv ();
|
||||||
else if (strcmp (applet, "veoutdent") == 0)
|
else if (strcmp (applet, "veoutdent") == 0)
|
||||||
eoutdentv ();
|
eoutdentv ();
|
||||||
else if (strcmp (applet, "eflush") == 0)
|
|
||||||
eflush ();
|
|
||||||
else {
|
else {
|
||||||
eerror ("%s: unknown applet", applet);
|
eerror ("%s: unknown applet", applet);
|
||||||
retval = EXIT_FAILURE;
|
retval = EXIT_FAILURE;
|
||||||
|
@ -237,9 +237,6 @@ static void cleanup (void)
|
|||||||
if (! rc_in_plugin && prefix_locked)
|
if (! rc_in_plugin && prefix_locked)
|
||||||
unlink (PREFIX_LOCK);
|
unlink (PREFIX_LOCK);
|
||||||
|
|
||||||
/* Flush our buffered output if any */
|
|
||||||
eclose ();
|
|
||||||
|
|
||||||
if (hook_out)
|
if (hook_out)
|
||||||
rc_plugin_run (hook_out, applet);
|
rc_plugin_run (hook_out, applet);
|
||||||
rc_plugin_unload ();
|
rc_plugin_unload ();
|
||||||
@ -317,7 +314,7 @@ static int write_prefix (int fd, const char *buffer, size_t bytes, bool *prefixe
|
|||||||
ret += write (fd, ec, strlen (ec));
|
ret += write (fd, ec, strlen (ec));
|
||||||
ret += write (fd, prefix, strlen (prefix));
|
ret += write (fd, prefix, strlen (prefix));
|
||||||
ret += write (fd, ec_normal, strlen (ec_normal));
|
ret += write (fd, ec_normal, strlen (ec_normal));
|
||||||
ret += write (fd, "|", 2);
|
ret += write (fd, "|", 1);
|
||||||
*prefixed = true;
|
*prefixed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -335,12 +332,8 @@ static bool svc_exec (const char *arg1, const char *arg2)
|
|||||||
int stdout_pipes[2];
|
int stdout_pipes[2];
|
||||||
int stderr_pipes[2];
|
int stderr_pipes[2];
|
||||||
|
|
||||||
/* To ensure any output has hit our ebuffer */
|
|
||||||
fflush (stdout);
|
|
||||||
fflush (stderr);
|
|
||||||
|
|
||||||
/* Setup our pipes for prefixed output */
|
/* Setup our pipes for prefixed output */
|
||||||
if (rc_is_env ("RC_PREFIX", "yes")) {
|
if (prefix) {
|
||||||
if (pipe (stdout_pipes))
|
if (pipe (stdout_pipes))
|
||||||
eerror ("pipe: %s", strerror (errno));
|
eerror ("pipe: %s", strerror (errno));
|
||||||
if (pipe (stderr_pipes))
|
if (pipe (stderr_pipes))
|
||||||
@ -356,7 +349,7 @@ static bool svc_exec (const char *arg1, const char *arg2)
|
|||||||
if (service_pid == -1)
|
if (service_pid == -1)
|
||||||
eerrorx ("%s: vfork: %s", service, strerror (errno));
|
eerrorx ("%s: vfork: %s", service, strerror (errno));
|
||||||
if (service_pid == 0) {
|
if (service_pid == 0) {
|
||||||
if (rc_is_env ("RC_PREFIX", "yes")) {
|
if (prefix) {
|
||||||
int flags;
|
int flags;
|
||||||
|
|
||||||
if (dup2 (stdout_pipes[1], fileno (stdout)) == -1)
|
if (dup2 (stdout_pipes[1], fileno (stdout)) == -1)
|
||||||
@ -391,7 +384,7 @@ static bool svc_exec (const char *arg1, const char *arg2)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Prefix our piped output */
|
/* Prefix our piped output */
|
||||||
if (rc_is_env ("RC_PREFIX", "yes")) {
|
if (prefix) {
|
||||||
bool stdout_done = false;
|
bool stdout_done = false;
|
||||||
bool stdout_prefix_shown = false;
|
bool stdout_prefix_shown = false;
|
||||||
bool stderr_done = false;
|
bool stderr_done = false;
|
||||||
@ -958,9 +951,6 @@ static void svc_restart (bool deps)
|
|||||||
if (! rc_service_state (service, rc_service_stopped)) {
|
if (! rc_service_state (service, rc_service_stopped)) {
|
||||||
get_started_services ();
|
get_started_services ();
|
||||||
svc_stop (deps);
|
svc_stop (deps);
|
||||||
|
|
||||||
/* Flush our buffered output if any */
|
|
||||||
eflush ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
svc_start (deps);
|
svc_start (deps);
|
||||||
@ -1079,7 +1069,7 @@ int main (int argc, char **argv)
|
|||||||
setenv ("RC_RUNSCRIPT_PID", pid, 1);
|
setenv ("RC_RUNSCRIPT_PID", pid, 1);
|
||||||
|
|
||||||
/* eprefix is kinda klunky, but it works for our purposes */
|
/* eprefix is kinda klunky, but it works for our purposes */
|
||||||
if (rc_is_env ("RC_PREFIX", "yes")) {
|
if (rc_is_env ("RC_PARALLEL", "yes")) {
|
||||||
int l = 0;
|
int l = 0;
|
||||||
int ll;
|
int ll;
|
||||||
|
|
||||||
@ -1100,17 +1090,6 @@ int main (int argc, char **argv)
|
|||||||
eprefix (prefix);
|
eprefix (prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we're in parallel and we're not prefixing then we need the ebuffer */
|
|
||||||
if (rc_is_env ("RC_PARALLEL", "yes") && ! rc_is_env ("RC_PREFIX", "yes")) {
|
|
||||||
char ebname[PATH_MAX];
|
|
||||||
char *eb;
|
|
||||||
|
|
||||||
snprintf (ebname, sizeof (ebname), "%s.%s", applet, pid);
|
|
||||||
eb = rc_strcatpaths (RC_SVCDIR "ebuffer", ebname, (char *) NULL);
|
|
||||||
ebuffer (eb);
|
|
||||||
free (eb);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
/* Ok, we are ready to go, so setup selinux if applicable */
|
/* Ok, we are ready to go, so setup selinux if applicable */
|
||||||
setup_selinux (argc, argv);
|
setup_selinux (argc, argv);
|
||||||
@ -1265,9 +1244,6 @@ int main (int argc, char **argv)
|
|||||||
} else
|
} else
|
||||||
svc_exec (optarg, NULL);
|
svc_exec (optarg, NULL);
|
||||||
|
|
||||||
/* Flush our buffered output if any */
|
|
||||||
eflush ();
|
|
||||||
|
|
||||||
/* We should ensure this list is empty after an action is done */
|
/* We should ensure this list is empty after an action is done */
|
||||||
rc_strlist_free (restart_services);
|
rc_strlist_free (restart_services);
|
||||||
restart_services = NULL;
|
restart_services = NULL;
|
||||||
|
Loading…
Reference in New Issue
Block a user