We now buffer stdout and stderr to a file and flush that when running in parallel. RC_PARALLEL_STARTUP has been renamed to RC_PARALLEL.
This commit is contained in:
		@@ -1,6 +1,11 @@
 | 
			
		||||
# ChangeLog for Gentoo System Intialization ("rc") scripts
 | 
			
		||||
# Copyright 1999-2007 Gentoo Foundation; Distributed under the GPLv2
 | 
			
		||||
 | 
			
		||||
  24 Apr 2007; Roy Marples <uberlord@gentoo.org>:
 | 
			
		||||
 | 
			
		||||
    We now buffer stdout and stderr to a file and flush that when running in
 | 
			
		||||
	parallel. RC_PARALLEL_STARTUP has been renamed to RC_PARALLEL.
 | 
			
		||||
 | 
			
		||||
  20 Apr 2007; Mike Frysinger <vapier@gentoo.org>:
 | 
			
		||||
 | 
			
		||||
    Automatically mount selinuxfs on /selinux in localmount.
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
# Set to "yes" if you want the rc system to try and start services
 | 
			
		||||
# in parallel for a slight speed improvement. NOTE: When enabled
 | 
			
		||||
# init script output is buffered and displayed in one go when finished.
 | 
			
		||||
RC_PARALLEL_STARTUP="no"
 | 
			
		||||
RC_PARALLEL="no"
 | 
			
		||||
 | 
			
		||||
# 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
 | 
			
		||||
 
 | 
			
		||||
@@ -6,22 +6,14 @@
 | 
			
		||||
RC_GOT_FUNCTIONS="yes"
 | 
			
		||||
 | 
			
		||||
eindent() {
 | 
			
		||||
	if [ -n "${RC_EBUFFER}" ] ; then
 | 
			
		||||
		"${RC_LIBDIR}"/bin/eindent
 | 
			
		||||
	else
 | 
			
		||||
		RC_EINDENT=$((${RC_EINDENT:-0} + 2))
 | 
			
		||||
		[ "${RC_EINDENT}" -gt 40 ] && RC_EINDENT=40
 | 
			
		||||
		export RC_EINDENT
 | 
			
		||||
	fi
 | 
			
		||||
	RC_EINDENT=$((${RC_EINDENT:-0} + 2))
 | 
			
		||||
	[ "${RC_EINDENT}" -gt 40 ] && RC_EINDENT=40
 | 
			
		||||
	export RC_EINDENT
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
eoutdent() {
 | 
			
		||||
	if [ -n "${RC_EBUFFER}" ] ; then
 | 
			
		||||
		"${RC_LIBDIR}"/bin/eoutdent
 | 
			
		||||
	else
 | 
			
		||||
		RC_EINDENT=$((${RC_EINDENT:-0} - 2))
 | 
			
		||||
		[ "${RC_EINDENT}" -lt 0 ] && RC_EINDENT=0
 | 
			
		||||
	fi
 | 
			
		||||
	RC_EINDENT=$((${RC_EINDENT:-0} - 2))
 | 
			
		||||
	[ "${RC_EINDENT}" -lt 0 ] && RC_EINDENT=0
 | 
			
		||||
	return 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										10
									
								
								src/einfo.h
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								src/einfo.h
									
									
									
									
									
								
							@@ -64,8 +64,12 @@ int ewendv (int retval, const char *fmt, ...) EINFO_PRINTF (2, 3);
 | 
			
		||||
void eindentv (void);
 | 
			
		||||
void eoutdentv (void);
 | 
			
		||||
 | 
			
		||||
/* If RC_EBUFFER is set, then we buffer all the above commands.
 | 
			
		||||
   As such, we need to flush the buffer when done. */
 | 
			
		||||
void eflush(void);
 | 
			
		||||
/* 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
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										320
									
								
								src/libeinfo.c
									
									
									
									
									
								
							
							
						
						
									
										320
									
								
								src/libeinfo.c
									
									
									
									
									
								
							@@ -8,6 +8,7 @@
 | 
			
		||||
#include <sys/ioctl.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <limits.h>
 | 
			
		||||
#include <stdarg.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
@@ -32,6 +33,7 @@ hidden_proto(eerror)
 | 
			
		||||
hidden_proto(eerrorn)
 | 
			
		||||
hidden_proto(eerrorx)
 | 
			
		||||
hidden_proto(eflush)
 | 
			
		||||
hidden_proto(eclose)
 | 
			
		||||
hidden_proto(eindent)
 | 
			
		||||
hidden_proto(eindentv)
 | 
			
		||||
hidden_proto(einfo)
 | 
			
		||||
@@ -118,6 +120,11 @@ static const char *color_terms[] = {
 | 
			
		||||
	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 bool is_env (const char *var, const char *val)
 | 
			
		||||
{
 | 
			
		||||
	char *v;
 | 
			
		||||
@@ -177,194 +184,125 @@ static int get_term_columns (void)
 | 
			
		||||
	return (DEFAULT_COLS);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int ebuffer (const char *cmd, int retval, const char *fmt, va_list ap)
 | 
			
		||||
void ebuffer (const char *file)
 | 
			
		||||
{
 | 
			
		||||
	char *file = getenv ("RC_EBUFFER");
 | 
			
		||||
	FILE *fp;
 | 
			
		||||
	char buffer[RC_LINEBUFFER];
 | 
			
		||||
	int l = 1;
 | 
			
		||||
	/* Don't ebuffer if we don't have a file or we already are */
 | 
			
		||||
	if (! file || stdfd[0] >= 0 || ! isatty (fileno (stdout)))
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	if (! file || ! cmd || strlen (cmd) < 4)
 | 
			
		||||
		return (0);
 | 
			
		||||
	/* Save the current fd's */
 | 
			
		||||
	stdfd[0] = dup (fileno (stdout));
 | 
			
		||||
	stdfd[1] = dup (fileno (stderr));
 | 
			
		||||
 | 
			
		||||
	if (! (fp = fopen (file, "a"))) {
 | 
			
		||||
	if (! (ebfp = fopen (file, "w+"))) {
 | 
			
		||||
		fprintf (stderr, "fopen `%s': %s\n", file, strerror (errno));
 | 
			
		||||
		return (0);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fprintf (fp, "%s %d ", cmd, retval);
 | 
			
		||||
	snprintf (ebfile, sizeof (ebfile), "%s", file);
 | 
			
		||||
 | 
			
		||||
	if (fmt) {
 | 
			
		||||
		va_list apc;
 | 
			
		||||
		va_copy (apc, ap);
 | 
			
		||||
		l = vsnprintf (buffer, sizeof (buffer), fmt, apc);
 | 
			
		||||
		fprintf (fp, "%d %s\n", l, buffer);
 | 
			
		||||
		va_end (apc);
 | 
			
		||||
	} else
 | 
			
		||||
		fprintf (fp, "0\n");
 | 
			
		||||
	fflush (stdout);
 | 
			
		||||
	fflush (stderr);
 | 
			
		||||
 | 
			
		||||
	fclose (fp);
 | 
			
		||||
	return (l);
 | 
			
		||||
	/* 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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
typedef struct func
 | 
			
		||||
static void _eflush (bool reopen)
 | 
			
		||||
{
 | 
			
		||||
	const char *name;
 | 
			
		||||
	int (*efunc) (const char *fmt, ...);
 | 
			
		||||
	int (*eefunc) (int retval, const char *fmt, ...);
 | 
			
		||||
	void (*eind) (void);
 | 
			
		||||
} func_t;
 | 
			
		||||
 | 
			
		||||
static const func_t funcmap[] = {
 | 
			
		||||
	{ "einfon", &einfon, NULL, NULL },
 | 
			
		||||
	{ "ewarnn", &ewarnn, NULL, NULL},
 | 
			
		||||
	{ "eerrorn", &eerrorn, NULL, NULL},
 | 
			
		||||
	{ "einfo", &einfo, NULL, NULL },
 | 
			
		||||
	{ "ewarn", &ewarn, NULL, NULL },
 | 
			
		||||
	{ "eerror", &eerror, NULL, NULL },
 | 
			
		||||
	{ "ebegin", &ebegin, NULL, NULL },
 | 
			
		||||
	{ "eend", NULL, &eend, NULL },
 | 
			
		||||
	{ "ewend", NULL, &ewend, NULL },
 | 
			
		||||
	{ "eindent", NULL, NULL, &eindent },
 | 
			
		||||
	{ "eoutdent", NULL, NULL, &eoutdent },
 | 
			
		||||
	{ "einfovn", &einfovn, NULL, NULL },
 | 
			
		||||
	{ "ewarnvn", &ewarnvn, NULL, NULL },
 | 
			
		||||
	{ "einfov", &einfov, NULL, NULL },
 | 
			
		||||
	{ "ewarnv", &ewarnv, NULL, NULL },
 | 
			
		||||
	{ "ebeginv", &ebeginv, NULL, NULL },
 | 
			
		||||
	{ "eendv", NULL, &eendv, NULL },
 | 
			
		||||
	{ "ewendv", NULL, &ewendv, NULL },
 | 
			
		||||
	{ "eindentv" ,NULL, NULL, &eindentv },
 | 
			
		||||
	{ "eoutdentv", NULL, NULL, &eoutdentv },
 | 
			
		||||
	{ NULL, NULL, NULL, NULL },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void eflush (void)
 | 
			
		||||
{
 | 
			
		||||
	FILE *fp;
 | 
			
		||||
	char *file = getenv ("RC_EBUFFER");
 | 
			
		||||
	char buffer[RC_LINEBUFFER];
 | 
			
		||||
	char *cmd;
 | 
			
		||||
	int retval = 0;
 | 
			
		||||
	int length = 0;
 | 
			
		||||
	char *token;
 | 
			
		||||
	char *p;
 | 
			
		||||
	struct stat buf;
 | 
			
		||||
	pid_t pid;
 | 
			
		||||
	char newfile[PATH_MAX];
 | 
			
		||||
	int i = 1;
 | 
			
		||||
 | 
			
		||||
	if (! file|| (stat (file, &buf) != 0)) {
 | 
			
		||||
		errno = 0;
 | 
			
		||||
		return;
 | 
			
		||||
	int serrno = errno;
 | 
			
		||||
	
 | 
			
		||||
	/* eflush called from an init script? */
 | 
			
		||||
	if (! ebfp) {
 | 
			
		||||
		char *file = getenv ("RC_EBUFFER");
 | 
			
		||||
		if (file)
 | 
			
		||||
			ebfp = fopen (file, "a+");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Find a unique name for our file */
 | 
			
		||||
	while (true) {
 | 
			
		||||
		snprintf (newfile, sizeof (newfile), "%s.%d", file, i);
 | 
			
		||||
		if (stat (newfile, &buf) != 0) {
 | 
			
		||||
			if (rename (file, newfile))
 | 
			
		||||
				fprintf (stderr, "rename `%s' `%s': %s\n", file, newfile,
 | 
			
		||||
						 strerror (errno));
 | 
			
		||||
			break;
 | 
			
		||||
	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));
 | 
			
		||||
		}
 | 
			
		||||
		i++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* We fork a child process here so we don't hold anything up */
 | 
			
		||||
	if ((pid = fork ()) == -1) {
 | 
			
		||||
		fprintf (stderr, "fork: %s", strerror (errno));
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (pid != 0)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	/* 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 = 0;
 | 
			
		||||
		if (link (newfile, EBUFFER_LOCK) == 0)
 | 
			
		||||
			break;
 | 
			
		||||
		if (errno != EEXIST)
 | 
			
		||||
			fprintf (stderr, "link `%s' `%s': %s\n", newfile, EBUFFER_LOCK,
 | 
			
		||||
					 strerror (errno));
 | 
			
		||||
	}
 | 
			
		||||
	errno = serrno;
 | 
			
		||||
 | 
			
		||||
	if (! (fp = fopen (newfile, "r"))) {
 | 
			
		||||
		fprintf (stderr, "fopen `%s': %s\n", newfile, strerror (errno));
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	unsetenv ("RC_EBUFFER");
 | 
			
		||||
 | 
			
		||||
	/* Dump the file to stdout */
 | 
			
		||||
	memset (buffer, 0, RC_LINEBUFFER);
 | 
			
		||||
	while (fgets (buffer, RC_LINEBUFFER, fp)) {
 | 
			
		||||
		i = strlen (buffer) - 1;
 | 
			
		||||
		if (i < 1)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		if (buffer[i] == '\n')
 | 
			
		||||
			buffer[i] = 0;
 | 
			
		||||
 | 
			
		||||
		p = buffer;
 | 
			
		||||
		cmd = strsep (&p, " ");
 | 
			
		||||
		token = strsep (&p, " ");
 | 
			
		||||
		if (sscanf (token, "%d", &retval) != 1) {
 | 
			
		||||
			fprintf (stderr, "eflush `%s': not a number", token);
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		token = strsep (&p, " ");
 | 
			
		||||
		if (sscanf (token, "%d", &length) != 1) {
 | 
			
		||||
			fprintf (stderr, "eflush `%s': not a number", token);
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		i = 0;
 | 
			
		||||
		while (funcmap[i].name) {
 | 
			
		||||
			if (strcmp (funcmap[i].name, cmd) == 0) {
 | 
			
		||||
				if (funcmap[i].efunc) {
 | 
			
		||||
					if (p)
 | 
			
		||||
						funcmap[i].efunc ("%s", p);
 | 
			
		||||
					else
 | 
			
		||||
						funcmap[i].efunc (NULL, NULL);
 | 
			
		||||
				} else if (funcmap[i].eefunc) {
 | 
			
		||||
					if (p)
 | 
			
		||||
						funcmap[i].eefunc (retval, "%s", p);
 | 
			
		||||
					else
 | 
			
		||||
						funcmap[i].eefunc (retval, NULL, NULL);
 | 
			
		||||
				} else if (funcmap[i].eind)
 | 
			
		||||
					funcmap[i].eind ();
 | 
			
		||||
				else
 | 
			
		||||
					fprintf (stderr, "eflush `%s': no function defined\n", cmd);
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
			i++;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (! funcmap[i].name)
 | 
			
		||||
			fprintf (stderr, "eflush `%s': invalid function\n", cmd);
 | 
			
		||||
	if (fseek (ebfp, (off_t) 0, SEEK_SET) < 0)
 | 
			
		||||
		eerror ("fseek: %s", strerror (errno));
 | 
			
		||||
	else {
 | 
			
		||||
		while (fgets (buffer, RC_LINEBUFFER, ebfp))
 | 
			
		||||
			printf ("%s", buffer);
 | 
			
		||||
	}
 | 
			
		||||
	fclose (fp);
 | 
			
		||||
 | 
			
		||||
	fflush (stdout);
 | 
			
		||||
	fflush (stderr);
 | 
			
		||||
	
 | 
			
		||||
	if (unlink (EBUFFER_LOCK))
 | 
			
		||||
		fprintf (stderr, "unlink `%s': %s", EBUFFER_LOCK, strerror (errno));
 | 
			
		||||
		eerror ("unlink `%s': %s", EBUFFER_LOCK, strerror (errno));
 | 
			
		||||
 | 
			
		||||
	if (unlink (newfile))
 | 
			
		||||
		fprintf (stderr, "unlink `%s': %s", newfile, 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");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_exit (EXIT_SUCCESS);
 | 
			
		||||
	return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void eflush () {
 | 
			
		||||
	_eflush (true);
 | 
			
		||||
}
 | 
			
		||||
hidden_def(eflush)
 | 
			
		||||
 | 
			
		||||
#define EBUFFER(_cmd, _retval, _fmt, _ap) { \
 | 
			
		||||
	int _i = ebuffer (_cmd, _retval, _fmt, _ap); \
 | 
			
		||||
	if (_i) \
 | 
			
		||||
	return (_i); \
 | 
			
		||||
void eclose () {
 | 
			
		||||
	_eflush (false);
 | 
			
		||||
}
 | 
			
		||||
hidden_def(eclose)
 | 
			
		||||
 | 
			
		||||
static void elog (int level, const char *fmt, va_list ap)
 | 
			
		||||
{
 | 
			
		||||
@@ -401,7 +339,6 @@ static int _eindent (FILE *stream)
 | 
			
		||||
 | 
			
		||||
	/* Terminate it */
 | 
			
		||||
	memset (indent + amount, 0, 1);
 | 
			
		||||
 | 
			
		||||
	return (fprintf (stream, "%s", indent));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -486,8 +423,7 @@ int einfon (const char *fmt, ...)
 | 
			
		||||
		return (0);
 | 
			
		||||
 | 
			
		||||
	va_start (ap, fmt);
 | 
			
		||||
	if (! (retval = ebuffer ("einfon", 0, fmt, ap)))
 | 
			
		||||
		retval = _einfovn (fmt, ap);
 | 
			
		||||
	retval = _einfovn (fmt, ap);
 | 
			
		||||
	va_end (ap);
 | 
			
		||||
 | 
			
		||||
	return (retval);
 | 
			
		||||
@@ -503,8 +439,7 @@ int ewarnn (const char *fmt, ...)
 | 
			
		||||
		return (0);
 | 
			
		||||
 | 
			
		||||
	va_start (ap, fmt);
 | 
			
		||||
	if (! (retval = ebuffer ("ewarnn", 0, fmt, ap)))
 | 
			
		||||
		retval = _ewarnvn (fmt, ap);
 | 
			
		||||
	retval = _ewarnvn (fmt, ap);
 | 
			
		||||
	va_end (ap);
 | 
			
		||||
 | 
			
		||||
	return (retval);
 | 
			
		||||
@@ -517,8 +452,7 @@ int eerrorn (const char *fmt, ...)
 | 
			
		||||
	va_list ap;
 | 
			
		||||
 | 
			
		||||
	va_start (ap, fmt);
 | 
			
		||||
	if (! (retval = ebuffer ("eerrorn", 0, fmt, ap)))
 | 
			
		||||
		retval = _eerrorvn (fmt, ap);
 | 
			
		||||
	retval = _eerrorvn (fmt, ap);
 | 
			
		||||
	va_end (ap);
 | 
			
		||||
 | 
			
		||||
	return (retval);
 | 
			
		||||
@@ -534,10 +468,8 @@ int einfo (const char *fmt, ...)
 | 
			
		||||
		return (0);
 | 
			
		||||
 | 
			
		||||
	va_start (ap, fmt);
 | 
			
		||||
	if (! (retval = ebuffer ("einfo", 0, fmt, ap))) {
 | 
			
		||||
		retval = _einfovn (fmt, ap);
 | 
			
		||||
		retval += printf ("\n");
 | 
			
		||||
	}
 | 
			
		||||
	retval = _einfovn (fmt, ap);
 | 
			
		||||
	retval += printf ("\n");
 | 
			
		||||
	va_end (ap);
 | 
			
		||||
 | 
			
		||||
	return (retval);
 | 
			
		||||
@@ -554,10 +486,8 @@ int ewarn (const char *fmt, ...)
 | 
			
		||||
 | 
			
		||||
	va_start (ap, fmt);
 | 
			
		||||
	elog (LOG_WARNING, fmt, ap);
 | 
			
		||||
	if (! (retval = ebuffer ("ewarn", 0, fmt, ap)))	{
 | 
			
		||||
		retval = _ewarnvn (fmt, ap);
 | 
			
		||||
		retval += printf ("\n");
 | 
			
		||||
	}
 | 
			
		||||
	retval = _ewarnvn (fmt, ap);
 | 
			
		||||
	retval += printf ("\n");
 | 
			
		||||
	va_end (ap);
 | 
			
		||||
 | 
			
		||||
	return (retval);
 | 
			
		||||
@@ -569,6 +499,7 @@ void ewarnx (const char *fmt, ...)
 | 
			
		||||
	int retval;
 | 
			
		||||
	va_list ap;
 | 
			
		||||
 | 
			
		||||
	eclose ();
 | 
			
		||||
	if (fmt && ! is_env ("RC_QUIET", "yes")) {
 | 
			
		||||
		va_start (ap, fmt);
 | 
			
		||||
		elog (LOG_WARNING, fmt, ap);
 | 
			
		||||
@@ -594,6 +525,7 @@ int eerror (const char *fmt, ...)
 | 
			
		||||
	va_end (ap);
 | 
			
		||||
	retval += fprintf (stderr, "\n");
 | 
			
		||||
 | 
			
		||||
	eflush ();
 | 
			
		||||
	return (retval);
 | 
			
		||||
}
 | 
			
		||||
hidden_def(eerror)
 | 
			
		||||
@@ -602,6 +534,7 @@ void eerrorx (const char *fmt, ...)
 | 
			
		||||
{
 | 
			
		||||
	va_list ap;
 | 
			
		||||
 | 
			
		||||
	eclose ();
 | 
			
		||||
	if (fmt) {
 | 
			
		||||
		va_start (ap, fmt);
 | 
			
		||||
		elog (LOG_ERR, fmt, ap);
 | 
			
		||||
@@ -609,6 +542,7 @@ void eerrorx (const char *fmt, ...)
 | 
			
		||||
		va_end (ap);
 | 
			
		||||
		printf ("\n");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	exit (EXIT_FAILURE);
 | 
			
		||||
}
 | 
			
		||||
hidden_def(eerrorx)
 | 
			
		||||
@@ -622,11 +556,6 @@ int ebegin (const char *fmt, ...)
 | 
			
		||||
		return (0);
 | 
			
		||||
 | 
			
		||||
	va_start (ap, fmt);
 | 
			
		||||
	if ((retval = ebuffer ("ebegin", 0, fmt, ap))) {
 | 
			
		||||
		va_end (ap);
 | 
			
		||||
		return (retval);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	retval = _einfovn (fmt, ap);
 | 
			
		||||
	va_end (ap);
 | 
			
		||||
	retval += printf (" ...");
 | 
			
		||||
@@ -667,15 +596,6 @@ static int _do_eend (const char *cmd, int retval, const char *fmt, va_list ap)
 | 
			
		||||
	int col = 0;
 | 
			
		||||
	FILE *fp;
 | 
			
		||||
	va_list apc;
 | 
			
		||||
	int eb;
 | 
			
		||||
 | 
			
		||||
	if (fmt) {
 | 
			
		||||
		va_copy (apc, ap);
 | 
			
		||||
		eb = ebuffer (cmd, retval, fmt, apc);
 | 
			
		||||
		va_end (apc);
 | 
			
		||||
		if (eb)
 | 
			
		||||
			return (retval);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (fmt && retval != 0)	{
 | 
			
		||||
		va_copy (apc, ap);
 | 
			
		||||
@@ -739,9 +659,6 @@ void eindent (void)
 | 
			
		||||
	int amount = 0;
 | 
			
		||||
	char num[10];
 | 
			
		||||
 | 
			
		||||
	if (ebuffer ("eindent", 0, NULL, NULL))
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	if (env) {
 | 
			
		||||
		errno = 0;
 | 
			
		||||
		amount = strtol (env, NULL, 0);
 | 
			
		||||
@@ -764,9 +681,6 @@ void eoutdent (void)
 | 
			
		||||
	int amount = 0;
 | 
			
		||||
	char num[10];
 | 
			
		||||
 | 
			
		||||
	if (ebuffer ("eoutdent", 0, NULL, NULL))
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	if (! env)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
@@ -797,8 +711,7 @@ int einfovn (const char *fmt, ...)
 | 
			
		||||
		return (0);
 | 
			
		||||
 | 
			
		||||
	va_start (ap, fmt);
 | 
			
		||||
	if (! (retval = ebuffer ("einfovn", 0, fmt, ap)))
 | 
			
		||||
		retval = _einfovn (fmt, ap);
 | 
			
		||||
	retval = _einfovn (fmt, ap);
 | 
			
		||||
	va_end (ap);
 | 
			
		||||
 | 
			
		||||
	return (retval);
 | 
			
		||||
@@ -816,8 +729,7 @@ int ewarnvn (const char *fmt, ...)
 | 
			
		||||
		return (0);
 | 
			
		||||
 | 
			
		||||
	va_start (ap, fmt);
 | 
			
		||||
	if (! (retval = ebuffer ("ewarnvn", 0, fmt, ap)))
 | 
			
		||||
		retval = _ewarnvn (fmt, ap);
 | 
			
		||||
	retval = _ewarnvn (fmt, ap);
 | 
			
		||||
	va_end (ap);
 | 
			
		||||
 | 
			
		||||
	return (retval);
 | 
			
		||||
@@ -835,10 +747,8 @@ int einfov (const char *fmt, ...)
 | 
			
		||||
		return (0);
 | 
			
		||||
 | 
			
		||||
	va_start (ap, fmt);
 | 
			
		||||
	if (! (retval = ebuffer ("einfov", 0, fmt, ap))) {
 | 
			
		||||
		retval = _einfovn (fmt, ap);
 | 
			
		||||
		retval += printf ("\n");
 | 
			
		||||
	}
 | 
			
		||||
	retval = _einfovn (fmt, ap);
 | 
			
		||||
	retval += printf ("\n");
 | 
			
		||||
	va_end (ap);
 | 
			
		||||
 | 
			
		||||
	return (retval);
 | 
			
		||||
@@ -856,10 +766,8 @@ int ewarnv (const char *fmt, ...)
 | 
			
		||||
		return (0);
 | 
			
		||||
 | 
			
		||||
	va_start (ap, fmt);
 | 
			
		||||
	if (! (retval = ebuffer ("ewarnv", 0, fmt, ap))) {
 | 
			
		||||
		retval = _ewarnvn (fmt, ap);
 | 
			
		||||
		retval += printf ("\n");
 | 
			
		||||
	}
 | 
			
		||||
	retval = _ewarnvn (fmt, ap);
 | 
			
		||||
	retval += printf ("\n");
 | 
			
		||||
	va_end (ap);
 | 
			
		||||
 | 
			
		||||
	return (retval);
 | 
			
		||||
@@ -877,12 +785,10 @@ int ebeginv (const char *fmt, ...)
 | 
			
		||||
		return (0);
 | 
			
		||||
 | 
			
		||||
	va_start (ap, fmt);
 | 
			
		||||
	if (! (retval = ebuffer ("ebeginv", 0, fmt, ap))) {
 | 
			
		||||
		retval = _einfovn (fmt, ap);
 | 
			
		||||
		retval += printf (" ...");
 | 
			
		||||
		if (colour_terminal ())
 | 
			
		||||
			retval += printf ("\n");
 | 
			
		||||
	}
 | 
			
		||||
	retval = _einfovn (fmt, ap);
 | 
			
		||||
	retval += printf (" ...");
 | 
			
		||||
	if (colour_terminal ())
 | 
			
		||||
		retval += printf ("\n");
 | 
			
		||||
	va_end (ap);
 | 
			
		||||
 | 
			
		||||
	return (retval);
 | 
			
		||||
 
 | 
			
		||||
@@ -644,6 +644,20 @@ char **rc_config_env (char **env)
 | 
			
		||||
	} else
 | 
			
		||||
		env = rc_strlist_add (env, "RC_DEFAULTLEVEL=" RC_LEVEL_DEFAULT);
 | 
			
		||||
 | 
			
		||||
	/* Store the name of the tty that stdout is connected to
 | 
			
		||||
	 * We do this so our init scripts can call eflush without any knowledge
 | 
			
		||||
	 * of our fd's */
 | 
			
		||||
	if (isatty (fileno (stdout))) {
 | 
			
		||||
		if ((p = rc_xstrdup (ttyname (fileno (stdout))))) {
 | 
			
		||||
			i = strlen ("RC_TTY=") + strlen (p) + 1;
 | 
			
		||||
			line = rc_xmalloc (sizeof (char *) * i);
 | 
			
		||||
			snprintf (line, i, "RC_TTY=%s", p);
 | 
			
		||||
			env = rc_strlist_add (env, line);
 | 
			
		||||
			free (p);
 | 
			
		||||
			free (line);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	memset (sys, 0, sizeof (sys));
 | 
			
		||||
 | 
			
		||||
	/* Linux can run some funky stuff like Xen, VServer, UML, etc
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										12
									
								
								src/rc.c
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								src/rc.c
									
									
									
									
									
								
							@@ -462,13 +462,7 @@ static void set_ksoftlevel (const char *runlevel)
 | 
			
		||||
static void wait_for_services ()
 | 
			
		||||
{
 | 
			
		||||
	int status = 0;
 | 
			
		||||
	struct timeval tv;
 | 
			
		||||
	while (wait (&status) != -1);
 | 
			
		||||
 | 
			
		||||
	/* Wait for a little bit to flush our ebuffer */
 | 
			
		||||
	tv.tv_usec = 50000;
 | 
			
		||||
	tv.tv_sec = 0;
 | 
			
		||||
	select (0, NULL, NULL, NULL, &tv);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void add_pid (pid_t pid)
 | 
			
		||||
@@ -1077,7 +1071,7 @@ int main (int argc, char **argv)
 | 
			
		||||
		/* We always stop the service when in these runlevels */
 | 
			
		||||
		if (going_down) {
 | 
			
		||||
			pid_t pid = rc_stop_service (service);
 | 
			
		||||
			if (pid > 0 && ! rc_is_env ("RC_PARALLEL_STARTUP", "yes"))
 | 
			
		||||
			if (pid > 0 && ! rc_is_env ("RC_PARALLEL", "yes"))
 | 
			
		||||
				rc_waitpid (pid);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@@ -1141,7 +1135,7 @@ int main (int argc, char **argv)
 | 
			
		||||
		/* After all that we can finally stop the blighter! */
 | 
			
		||||
		if (! found) {
 | 
			
		||||
			pid_t pid = rc_stop_service (service);
 | 
			
		||||
			if (pid > 0 && ! rc_is_env ("RC_PARALLEL_STARTUP", "yes"))
 | 
			
		||||
			if (pid > 0 && ! rc_is_env ("RC_PARALLEL", "yes"))
 | 
			
		||||
				rc_waitpid (pid);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@@ -1227,7 +1221,7 @@ interactive_option:
 | 
			
		||||
			if ((pid = rc_start_service (service)))
 | 
			
		||||
				add_pid (pid);
 | 
			
		||||
 | 
			
		||||
			if (! rc_is_env ("RC_PARALLEL_STARTUP", "yes")) {
 | 
			
		||||
			if (! rc_is_env ("RC_PARALLEL", "yes")) {
 | 
			
		||||
				rc_waitpid (pid);
 | 
			
		||||
				remove_pid (pid);
 | 
			
		||||
			}
 | 
			
		||||
 
 | 
			
		||||
@@ -199,7 +199,7 @@ static void uncoldplug (char *service)
 | 
			
		||||
static void cleanup (void)
 | 
			
		||||
{
 | 
			
		||||
	/* Flush our buffered output if any */
 | 
			
		||||
	eflush ();
 | 
			
		||||
	eclose ();
 | 
			
		||||
 | 
			
		||||
	if (hook_out)
 | 
			
		||||
		rc_plugin_run (hook_out, applet);
 | 
			
		||||
@@ -267,6 +267,10 @@ static bool svc_exec (const char *service, const char *arg1, const char *arg2)
 | 
			
		||||
{
 | 
			
		||||
	bool retval;
 | 
			
		||||
 | 
			
		||||
	/* To ensure any output has hit our ebuffer */
 | 
			
		||||
	fflush (stdout);
 | 
			
		||||
	fflush (stderr);
 | 
			
		||||
 | 
			
		||||
	/* We need to disable our child signal handler now so we block
 | 
			
		||||
	   until our script returns. */
 | 
			
		||||
	signal (SIGCHLD, NULL);
 | 
			
		||||
@@ -466,7 +470,7 @@ static void svc_start (const char *service, bool deps)
 | 
			
		||||
			STRLIST_FOREACH (services, svc, i)
 | 
			
		||||
				if (rc_service_state (svc, rc_service_stopped)) {
 | 
			
		||||
					pid_t pid = rc_start_service (svc);
 | 
			
		||||
					if (! rc_is_env ("RC_PARALLEL_STARTUP", "yes"))
 | 
			
		||||
					if (! rc_is_env ("RC_PARALLEL", "yes"))
 | 
			
		||||
						rc_waitpid (pid);
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
@@ -670,7 +674,7 @@ static void svc_stop (const char *service, bool deps)
 | 
			
		||||
					rc_service_state (svc, rc_service_inactive))
 | 
			
		||||
				{
 | 
			
		||||
					pid_t pid = rc_stop_service (svc);
 | 
			
		||||
					if (! rc_is_env ("RC_PARALLEL_STARTUP", "yes"))
 | 
			
		||||
					if (! rc_is_env ("RC_PARALLEL", "yes"))
 | 
			
		||||
						rc_waitpid (pid);
 | 
			
		||||
					tmplist = rc_strlist_add (tmplist, svc);
 | 
			
		||||
				}
 | 
			
		||||
@@ -883,7 +887,7 @@ int main (int argc, char **argv)
 | 
			
		||||
		softlevel = rc_get_runlevel ();
 | 
			
		||||
 | 
			
		||||
		/* If not called from RC or another service then don't be parallel */
 | 
			
		||||
		unsetenv ("RC_PARALLEL_STARTUP");
 | 
			
		||||
		unsetenv ("RC_PARALLEL");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	setenv ("RC_ELOG", service, 1);
 | 
			
		||||
@@ -895,13 +899,13 @@ int main (int argc, char **argv)
 | 
			
		||||
	snprintf (pid, sizeof (pid), "%d", (int) getpid ());
 | 
			
		||||
	setenv ("RC_RUNSCRIPT_PID", pid, 1);
 | 
			
		||||
 | 
			
		||||
	if (rc_is_env ("RC_PARALLEL_STARTUP", "yes")) {
 | 
			
		||||
	if (rc_is_env ("RC_PARALLEL", "yes")) {
 | 
			
		||||
		char ebname[PATH_MAX];
 | 
			
		||||
		char *eb;
 | 
			
		||||
 | 
			
		||||
		snprintf (ebname, sizeof (ebname), "%s.%s", applet, pid);
 | 
			
		||||
		eb = rc_strcatpaths (RC_SVCDIR "ebuffer", ebname, (char *) NULL);
 | 
			
		||||
		setenv ("RC_EBUFFER", eb, 1);
 | 
			
		||||
		ebuffer (eb);
 | 
			
		||||
		free (eb);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user