svn commit: [26148] trunk/busybox/shell

vda at busybox.net vda at busybox.net
Sat Apr 18 12:58:19 UTC 2009


Author: vda
Date: 2009-04-18 12:58:19 +0000 (Sat, 18 Apr 2009)
New Revision: 26148

Log:
hush: fix "trap -- handler SIGs..."; escape handlers in "trap" output



Modified:
   trunk/busybox/shell/hush.c


Changeset:
Modified: trunk/busybox/shell/hush.c
===================================================================
--- trunk/busybox/shell/hush.c	2009-04-18 11:35:16 UTC (rev 26147)
+++ trunk/busybox/shell/hush.c	2009-04-18 12:58:19 UTC (rev 26148)
@@ -3246,14 +3246,16 @@
 					fg_pipe->alive_cmds--;
 					if (i == fg_pipe->num_cmds - 1) {
 						/* last process gives overall exitstatus */
+						/* Note: is WIFSIGNALED, WEXITSTATUS = sig + 128 */
 						rcode = WEXITSTATUS(status);
 						IF_HAS_KEYWORDS(if (fg_pipe->pi_inverted) rcode = !rcode;)
 						/* bash prints killing signal's name for *last*
 						 * process in pipe (prints just newline for SIGINT).
-						 * we just print newline for any sig:
+						 * Mimic this. Example: "sleep 5" + ^\
 						 */
 						if (WIFSIGNALED(status)) {
-							bb_putchar('\n');
+							int sig = WTERMSIG(status);
+							printf("%s\n", sig == SIGINT ? "" : get_signame(sig));
 						}
 					}
 				} else {
@@ -3489,6 +3491,7 @@
 					debug_printf_exec(": builtin '%s' '%s'...\n",
 						x->cmd, argv_expanded[1]);
 					rcode = x->function(argv_expanded) & 0xff;
+					fflush(NULL);
 				}
 #if ENABLE_HUSH_FUNCTIONS
 				else {
@@ -6251,81 +6254,6 @@
 /*
  * Built-ins
  */
-static int builtin_trap(char **argv)
-{
-	int i;
-	int sig;
-	char *new_cmd;
-
-	if (!G.traps)
-		G.traps = xzalloc(sizeof(G.traps[0]) * NSIG);
-
-	argv++;
-	if (!*argv) {
-		/* No args: print all trapped. This isn't 100% correct as we
-		 * should be escaping the cmd so that it can be pasted back in
-		 */
-		for (i = 0; i < NSIG; ++i)
-			if (G.traps[i])
-				printf("trap -- '%s' %s\n", G.traps[i], get_signame(i));
-		return EXIT_SUCCESS;
-	}
-
-	new_cmd = NULL;
-	i = 0;
-	/* If first arg is decimal: reset all specified signals */
-	sig = bb_strtou(*argv, NULL, 10);
-	if (errno == 0) {
-		int ret;
- set_all:
-		ret = EXIT_SUCCESS;
-		while (*argv) {
-			sig = get_signum(*argv++);
-			if (sig < 0 || sig >= NSIG) {
-				ret = EXIT_FAILURE;
-				/* Mimic bash message exactly */
-				bb_perror_msg("trap: %s: invalid signal specification", argv[i]);
-				continue;
-			}
-
-			free(G.traps[sig]);
-			G.traps[sig] = xstrdup(new_cmd);
-
-			debug_printf("trap: setting SIG%s (%i) to '%s'",
-				get_signame(sig), sig, G.traps[sig]);
-
-			/* There is no signal for 0 (EXIT) */
-			if (sig == 0)
-				continue;
-
-			if (new_cmd) {
-				sigaddset(&G.blocked_set, sig);
-			} else {
-				/* There was a trap handler, we are removing it
-				 * (if sig has non-DFL handling,
-				 * we don't need to do anything) */
-				if (sig < 32 && (G.non_DFL_mask & (1 << sig)))
-					continue;
-				sigdelset(&G.blocked_set, sig);
-			}
-			sigprocmask(SIG_SETMASK, &G.blocked_set, NULL);
-		}
-		return ret;
-	}
-
-	/* First arg is "-": reset all specified to default */
-	/* First arg is "": ignore all specified */
-	/* Everything else: execute first arg upon signal */
-	if (!argv[1]) {
-		bb_error_msg("trap: invalid arguments");
-		return EXIT_FAILURE;
-	}
-	if (NOT_LONE_DASH(*argv))
-		new_cmd = *argv;
-	argv++;
-	goto set_all;
-}
-
 static int builtin_true(char **argv UNUSED_PARAM)
 {
 	return 0;
@@ -6427,6 +6355,26 @@
 	hush_exit(xatoi(*argv) & 0xff);
 }
 
+static void print_escaped(const char *s)
+{
+	do {
+		if (*s != '\'') {
+			const char *p;
+
+			p = strchrnul(s, '\'');
+			/* print 'xxxx', possibly just '' */
+			printf("'%.*s'", (int)(p - s), s);
+			if (*p == '\0')
+				break;
+			s = p;
+		}
+		/* s points to '; print "'''...'''" */
+		putchar('"');
+		do putchar('\''); while (*++s == '\'');
+		putchar('"');
+	} while (*s);
+}
+
 static int builtin_export(char **argv)
 {
 	if (*++argv == NULL) {
@@ -6446,25 +6394,11 @@
 					continue;
 				/* export var= */
 				printf("export %.*s", (int)(p - s) + 1, s);
-				s = p + 1;
-				while (*s) {
-					if (*s != '\'') {
-						p = strchrnul(s, '\'');
-						/* print 'xxxx' */
-						printf("'%.*s'", (int)(p - s), s);
-						if (*p == '\0')
-							break;
-						s = p;
-					}
-					/* s points to '; print ''...'''" */
-					putchar('"');
-					do putchar('\''); while (*++s == '\'');
-					putchar('"');
-				}
+				print_escaped(p + 1);
 				putchar('\n');
 #endif
 			}
-			fflush(stdout);
+			/*fflush(stdout); - done after each builtin anyway */
 		}
 		return EXIT_SUCCESS;
 	}
@@ -6494,6 +6428,96 @@
 	return EXIT_SUCCESS;
 }
 
+static int builtin_trap(char **argv)
+{
+	int i;
+	int sig;
+	char *new_cmd;
+
+	if (!G.traps)
+		G.traps = xzalloc(sizeof(G.traps[0]) * NSIG);
+
+	argv++;
+	if (!*argv) {
+		/* No args: print all trapped */
+		for (i = 0; i < NSIG; ++i) {
+			if (G.traps[i]) {
+				printf("trap -- ");
+				print_escaped(G.traps[i]);
+				printf(" %s\n", get_signame(i));
+			}
+		}
+		/*fflush(stdout); - done after each builtin anyway */
+		return EXIT_SUCCESS;
+	}
+
+	new_cmd = NULL;
+	i = 0;
+	/* If first arg is a number: reset all specified signals */
+	sig = bb_strtou(*argv, NULL, 10);
+	if (errno == 0) {
+		int ret;
+ process_sig_list:
+		ret = EXIT_SUCCESS;
+		while (*argv) {
+			sig = get_signum(*argv++);
+			if (sig < 0 || sig >= NSIG) {
+				ret = EXIT_FAILURE;
+				/* Mimic bash message exactly */
+				bb_perror_msg("trap: %s: invalid signal specification", argv[i]);
+				continue;
+			}
+
+			free(G.traps[sig]);
+			G.traps[sig] = xstrdup(new_cmd);
+
+			debug_printf("trap: setting SIG%s (%i) to '%s'",
+				get_signame(sig), sig, G.traps[sig]);
+
+			/* There is no signal for 0 (EXIT) */
+			if (sig == 0)
+				continue;
+
+			if (new_cmd) {
+				sigaddset(&G.blocked_set, sig);
+			} else {
+				/* There was a trap handler, we are removing it
+				 * (if sig has non-DFL handling,
+				 * we don't need to do anything) */
+				if (sig < 32 && (G.non_DFL_mask & (1 << sig)))
+					continue;
+				sigdelset(&G.blocked_set, sig);
+			}
+			sigprocmask(SIG_SETMASK, &G.blocked_set, NULL);
+		}
+		return ret;
+	}
+
+	if (!argv[1]) { /* no second arg */
+		bb_error_msg("trap: invalid arguments");
+		return EXIT_FAILURE;
+	}
+
+	/* First arg is "-": reset all specified to default */
+	/* First arg is "--": skip it, the rest is "handler SIGs..." */
+	/* Everything else: set arg as signal handler
+	 * (includes "" case, which ignores signal) */
+	if (argv[0][0] == '-') {
+		if (argv[0][1] == '\0') { /* "-" */
+			/* new_cmd remains NULL: "reset these sigs" */
+			goto reset_traps;
+		}
+		if (argv[0][1] == '-' && argv[0][2] == '\0') { /* "--" */
+			argv++;
+		}
+		/* else: "-something", no special meaning */
+	}
+	new_cmd = *argv;
+ reset_traps:
+	argv++;
+	goto process_sig_list;
+}
+
 #if ENABLE_HUSH_JOB
 /* built-in 'fg' and 'bg' handler */
 static int builtin_fg_bg(char **argv)



More information about the busybox-cvs mailing list