svn commit: [26145] trunk/busybox/shell

vda at busybox.net vda at busybox.net
Sat Apr 18 11:23:39 UTC 2009


Author: vda
Date: 2009-04-18 11:23:38 +0000 (Sat, 18 Apr 2009)
New Revision: 26145

Log:
hush: implement unset -f; beautify the handling of signal-killed pipe
 four TODOs are gone

function                                             old     new   delta
builtin_unset                                        271     364     +93
checkjobs                                            394     428     +34
builtin_exit                                          49      47      -2



Modified:
   trunk/busybox/shell/hush.c


Changeset:
Modified: trunk/busybox/shell/hush.c
===================================================================
--- trunk/busybox/shell/hush.c	2009-04-18 02:06:54 UTC (rev 26144)
+++ trunk/busybox/shell/hush.c	2009-04-18 11:23:38 UTC (rev 26145)
@@ -1185,7 +1185,6 @@
 //			G.count_SIGCHLD++;
 //			break;
 		case SIGINT:
-//TODO: add putchar('\n') also when we detect that child was killed (sleep 5 + ^C)
 			/* Builtin was ^C'ed, make it look prettier: */
 			bb_putchar('\n');
 			G.flag_SIGINT = 1;
@@ -2842,6 +2841,31 @@
 	return funcp;
 }
 
+static void unset_func(const char *name)
+{
+	struct function *funcp;
+	struct function **funcpp = &G.top_func;
+
+	while ((funcp = *funcpp) != NULL) {
+		if (strcmp(funcp->name, name) == 0) {
+			*funcpp = funcp->next;
+			/* funcp is unlinked now, deleting it */
+			free(funcp->name);
+			/* Note: if !funcp->body, do not free body_as_string!
+			 * This is a special case of "-F name body" function:
+			 * body_as_string was not malloced! */
+			if (funcp->body) {
+				free_pipe_list(funcp->body);
+#if !BB_MMU
+				free(funcp->body_as_string);
+#endif
+			}
+			free(funcp);
+			break;
+		}
+	}
+}
+
 #if BB_MMU
 #define exec_function(nommu_save, funcp, argv) \
 	exec_function(funcp, argv)
@@ -3223,6 +3247,13 @@
 						/* last process gives overall exitstatus */
 						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:
+						 */
+						if (WIFSIGNALED(status)) {
+							bb_putchar('\n');
+						}
 					}
 				} else {
 					fg_pipe->cmds[i].is_stopped = 1;
@@ -6372,12 +6403,20 @@
 static int builtin_exit(char **argv)
 {
 	debug_printf_exec("%s()\n", __func__);
-// TODO: bash does it ONLY on top-level sh exit (+interacive only?)
-	//puts("exit"); /* bash does it */
-// TODO: warn if we have background jobs: "There are stopped jobs"
-// On second consecutive 'exit', exit anyway.
-// perhaps use G.exiting = -1 as indicator "last cmd was exit"
 
+	/* interactive bash:
+	 * # trap "echo EEE" EXIT
+	 * # exit
+	 * exit
+	 * There are stopped jobs.
+	 * (if there are _stopped_ jobs, running ones don't count)
+	 * # exit
+	 * exit
+	 # EEE (then bash exits)
+	 *
+	 * we can use G.exiting = -1 as indicator "last cmd was exit"
+	 */
+
 	/* note: EXIT trap is run by hush_exit */
 	if (*++argv == NULL)
 		hush_exit(G.last_exitcode);
@@ -6776,28 +6815,34 @@
 {
 	int ret;
 	char var;
+	char *arg;
 
 	if (!*++argv)
 		return EXIT_SUCCESS;
 
-	var = 'v';
-	if (argv[0][0] == '-') {
-		switch (argv[0][1]) {
-		case 'v':
-		case 'f':
-			var = argv[0][1];
-			break;
-		default:
-			bb_error_msg("unset: %s: invalid option", *argv);
-			return EXIT_FAILURE;
+	var = 0;
+	while ((arg = *argv) != NULL && arg[0] == '-') {
+		while (*++arg) {
+			switch (*arg) {
+			case 'v':
+			case 'f':
+				if (var == 0 || var == *arg) {
+					var = *arg;
+					break;
+				}
+				/* else: unset -vf, which is illegal.
+				 * fall through */
+			default:
+				bb_error_msg("unset: %s: invalid option", *argv);
+				return EXIT_FAILURE;
+			}
 		}
-//TODO: disallow "unset -vf ..." too
 		argv++;
 	}
 
 	ret = EXIT_SUCCESS;
 	while (*argv) {
-		if (var == 'v') {
+		if (var != 'f') {
 			if (unset_local_var(*argv)) {
 				/* unset <nonexistent_var> doesn't fail.
 				 * Error is when one tries to unset RO var.
@@ -6805,11 +6850,11 @@
 				ret = EXIT_FAILURE;
 			}
 		}
-//#if ENABLE_HUSH_FUNCTIONS
-//		else {
-//			unset_local_func(*argv);
-//		}
-//#endif
+#if ENABLE_HUSH_FUNCTIONS
+		else {
+			unset_func(*argv);
+		}
+#endif
 		argv++;
 	}
 	return ret;



More information about the busybox-cvs mailing list