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