svn commit: trunk/busybox: include libbb shell

vda at busybox.net vda at busybox.net
Sat Apr 28 16:43:19 UTC 2007


Author: vda
Date: 2007-04-28 09:43:18 -0700 (Sat, 28 Apr 2007)
New Revision: 18521

Log:
hush: fix nofork + ctrl-Z clobbering of globals


Modified:
   trunk/busybox/include/libbb.h
   trunk/busybox/libbb/vfork_daemon_rexec.c
   trunk/busybox/shell/hush.c


Changeset:
Modified: trunk/busybox/include/libbb.h
===================================================================
--- trunk/busybox/include/libbb.h	2007-04-28 16:42:11 UTC (rev 18520)
+++ trunk/busybox/include/libbb.h	2007-04-28 16:43:18 UTC (rev 18521)
@@ -509,10 +509,20 @@
 #define wait_exitcode(w) ((w) >> 8)
 #define wait_stopsig(w) ((w) >> 8)
 #define wait_stopped(w) (((w) & 127) == 127)
+/* wait4pid(spawn(argv)) + NOFORK/NOEXEC (if configured) */
+int spawn_and_wait(char **argv);
+struct nofork_save_area {
+	const struct bb_applet *current_applet;
+	int xfunc_error_retval;
+	uint32_t option_mask32;
+	int die_sleep;
+	smallint saved;
+};
+void save_nofork_data(struct nofork_save_area *save);
+void restore_nofork_data(struct nofork_save_area *save);
 /* Does NOT check that applet is NOFORK, just blindly runs it */
 int run_nofork_applet(const struct bb_applet *a, char **argv);
-/* wait4pid(spawn(argv)) + NOFORK/NOEXEC (if configured) */
-int spawn_and_wait(char **argv);
+int run_nofork_applet_prime(struct nofork_save_area *old, const struct bb_applet *a, char **argv);
 
 /* Helpers for daemonization.
  *

Modified: trunk/busybox/libbb/vfork_daemon_rexec.c
===================================================================
--- trunk/busybox/libbb/vfork_daemon_rexec.c	2007-04-28 16:42:11 UTC (rev 18520)
+++ trunk/busybox/libbb/vfork_daemon_rexec.c	2007-04-28 16:43:18 UTC (rev 18521)
@@ -100,16 +100,29 @@
 	return r;
 }
 
-int run_nofork_applet(const struct bb_applet *a, char **argv)
+void save_nofork_data(struct nofork_save_area *save)
 {
+	save->current_applet = current_applet;
+	save->xfunc_error_retval = xfunc_error_retval;
+	save->option_mask32 = option_mask32;
+	save->die_sleep = die_sleep;
+	save->saved = 1;
+}
+
+void restore_nofork_data(struct nofork_save_area *save)
+{
+	current_applet = save->current_applet;
+	xfunc_error_retval = save->xfunc_error_retval;
+	option_mask32 = save->option_mask32;
+	die_sleep = save->die_sleep;
+
+	applet_name = current_applet->name;
+}
+
+int run_nofork_applet_prime(struct nofork_save_area *old, const struct bb_applet *a, char **argv)
+{
 	int rc, argc;
 
-	/* Save some shared globals */
-	const struct bb_applet *old_a = current_applet;
-	int old_x = xfunc_error_retval;
-	uint32_t old_m = option_mask32;
-	int old_sleep = die_sleep;
-
 	current_applet = a;
 	applet_name = a->name;
 	xfunc_error_retval = EXIT_FAILURE;
@@ -138,14 +151,18 @@
 	}
 
 	/* Restoring globals */
-	current_applet = old_a;
-	applet_name = old_a->name;
-	xfunc_error_retval = old_x;
-	option_mask32 = old_m;
-	die_sleep = old_sleep;
+	restore_nofork_data(old);
 	return rc;
 }
 
+int run_nofork_applet(const struct bb_applet *a, char **argv)
+{
+	struct nofork_save_area old;
+	/* Saving globals */
+	save_nofork_data(&old);
+	return run_nofork_applet_prime(&old, a, argv);
+}
+
 int spawn_and_wait(char **argv)
 {
 	int rc;

Modified: trunk/busybox/shell/hush.c
===================================================================
--- trunk/busybox/shell/hush.c	2007-04-28 16:42:11 UTC (rev 18520)
+++ trunk/busybox/shell/hush.c	2007-04-28 16:43:18 UTC (rev 18521)
@@ -441,30 +441,28 @@
 	sigaction(sig, &sa, NULL);
 }
 
+struct nofork_save_area nofork_save;
 static sigjmp_buf nofork_jb;
-static smallint nofork_flag;
 static struct pipe *nofork_pipe;
 
 static void handler_ctrl_z(int sig)
 {
 	pid_t pid;
 
-	fprintf(stderr, "got tty sig %d\n", sig);
-	if (!nofork_flag)
-		return;
+	debug_jobs_printf("got tty sig %d\n", sig);
 	pid = fork();
 	if (pid < 0) /* can't fork. Pretend there were no Ctrl-Z */
 		return;
-	fprintf(stderr, "bg'ing nofork\n");
-	nofork_flag = 0;
+	debug_jobs_printf("bg'ing nofork\n");
+	nofork_save.saved = 0; /* flag the fact that Ctrl-Z was handled */
 	nofork_pipe->running_progs = 1;
 	nofork_pipe->stopped_progs = 0;
 	if (!pid) { /* child */
-		fprintf(stderr, "setting pgrp for child\n");
+		debug_jobs_printf("setting pgrp for child\n");
 		setpgrp();
-		signal(sig, SIG_DFL); /* make child do default action (stop) */
-		raise(sig); /* resend TSTP so that child will be stopped */
-		fprintf(stderr, "returning to child\n");
+		signal(SIGTSTP, SIG_DFL); /* make child do default action (stop) */
+		raise(SIGTSTP); /* resend TSTP so that child will be stopped */
+		debug_jobs_printf("returning to child\n");
 		/* return to nofork, it will eventually exit now,
 		 * not return back to shell */
 		return;
@@ -1588,25 +1586,23 @@
 			const struct bb_applet *a = find_applet_by_name(argv[i]);
 			if (a && a->nofork) {
 				setup_redirects(child, squirrel);
+				/* TSTP handler will store pid etc in pi */
+				nofork_pipe = pi;
+				save_nofork_data(&nofork_save);
 				if (sigsetjmp(nofork_jb, 1) == 0) {
-// enable ctrl_z here, not globally?
-					nofork_flag = 1;
-					/* TSTP handler will store pid there etc */
-					nofork_pipe = pi;
-					rcode = run_nofork_applet(a, argv + i);
-					if (--nofork_flag != 0)
+					signal_SA_RESTART(SIGTSTP, handler_ctrl_z);
+					rcode = run_nofork_applet_prime(&nofork_save, a, argv + i);
+					if (--nofork_save.saved != 0)
 						/* Ctrl-Z! forked, we are child */
 						exit(rcode);
 					restore_redirects(squirrel);
 					return rcode;
 				} else {
-					fprintf(stderr, "Exiting nofork early\n");
 					/* Ctrl-Z, forked, we are parent.
 					 * Sighandler has longjmped us here */
-//problem: run_nofork_applet did not do the
-// "restore" trick and globals are trashed:
-// for one, applet_name is not "hush" :)
-// need to split run_nofork_applet into setup/run/restore...
+					signal(SIGTSTP, SIG_IGN);
+					debug_jobs_printf("Exiting nofork early\n");
+					restore_nofork_data(&nofork_save);
 					restore_redirects(squirrel);
 					insert_bg_job(pi);
 					return 0;
@@ -3021,8 +3017,6 @@
 
 	/* Grab control of the terminal.  */
 	tcsetpgrp(interactive_fd, shell_pgrp);
-
-	signal_SA_RESTART(SIGTSTP, handler_ctrl_z);
 }
 
 int hush_main(int argc, char **argv);




More information about the busybox-cvs mailing list