svn commit: [26100] branches/busybox_1_13_stable: archival archival/libunarchive coreutil etc...

vda at busybox.net vda at busybox.net
Wed Apr 15 00:11:23 UTC 2009


Author: vda
Date: 2009-04-15 00:11:22 +0000 (Wed, 15 Apr 2009)
New Revision: 26100

Log:
apply post-1.13.3 fixes, bump version to 1.13.4



Added:
   branches/busybox_1_13_stable/shell/ash_test/ash-read/read_ifs.right
   branches/busybox_1_13_stable/shell/ash_test/ash-read/read_ifs.tests

Modified:
   branches/busybox_1_13_stable/Makefile
   branches/busybox_1_13_stable/archival/libunarchive/get_header_tar.c
   branches/busybox_1_13_stable/archival/tar.c
   branches/busybox_1_13_stable/coreutils/tail.c
   branches/busybox_1_13_stable/shell/ash.c
   branches/busybox_1_13_stable/shell/hush.c
   branches/busybox_1_13_stable/shell/hush_test/hush-parsing/starquoted2.right
   branches/busybox_1_13_stable/shell/hush_test/hush-parsing/starquoted2.tests
   branches/busybox_1_13_stable/util-linux/volume_id/get_devname.c


Changeset:
Modified: branches/busybox_1_13_stable/Makefile
===================================================================
--- branches/busybox_1_13_stable/Makefile	2009-04-14 21:23:33 UTC (rev 26099)
+++ branches/busybox_1_13_stable/Makefile	2009-04-15 00:11:22 UTC (rev 26100)
@@ -1,6 +1,6 @@
 VERSION = 1
 PATCHLEVEL = 13
-SUBLEVEL = 3
+SUBLEVEL = 4
 EXTRAVERSION =
 NAME = Unnamed
 

Modified: branches/busybox_1_13_stable/archival/libunarchive/get_header_tar.c
===================================================================
--- branches/busybox_1_13_stable/archival/libunarchive/get_header_tar.c	2009-04-14 21:23:33 UTC (rev 26099)
+++ branches/busybox_1_13_stable/archival/libunarchive/get_header_tar.c	2009-04-15 00:11:22 UTC (rev 26100)
@@ -91,7 +91,7 @@
 
  again_after_align:
 
-#if ENABLE_DESKTOP
+#if ENABLE_DESKTOP || ENABLE_FEATURE_TAR_AUTODETECT
 	/* to prevent misdetection of bz2 sig */
 	*(uint32_t*)(&tar) = 0;
 	i = full_read(archive_handle->src_fd, &tar, 512);
@@ -142,7 +142,7 @@
 #if ENABLE_FEATURE_TAR_AUTODETECT
 		char FAST_FUNC (*get_header_ptr)(archive_handle_t *);
 
- USE_DESKTOP(autodetect:)
+ autodetect:
 		/* tar gz/bz autodetect: check for gz/bz2 magic.
 		 * If we see the magic, and it is the very first block,
 		 * we can switch to get_header_tar_gz/bz2/lzma().

Modified: branches/busybox_1_13_stable/archival/tar.c
===================================================================
--- branches/busybox_1_13_stable/archival/tar.c	2009-04-14 21:23:33 UTC (rev 26099)
+++ branches/busybox_1_13_stable/archival/tar.c	2009-04-15 00:11:22 UTC (rev 26100)
@@ -934,8 +934,10 @@
 			tar_handle->src_fd = fileno(tar_stream);
 			tar_handle->seek = seek_by_read;
 		} else {
-			if (ENABLE_FEATURE_TAR_AUTODETECT && flags == O_RDONLY) {
-				get_header_ptr = get_header_tar;
+			if (ENABLE_FEATURE_TAR_AUTODETECT
+			 && get_header_ptr == get_header_tar
+			 && flags == O_RDONLY
+			) {
 				tar_handle->src_fd = open_zipped(tar_filename);
 				if (tar_handle->src_fd < 0)
 					bb_perror_msg_and_die("can't open '%s'", tar_filename);

Modified: branches/busybox_1_13_stable/coreutils/tail.c
===================================================================
--- branches/busybox_1_13_stable/coreutils/tail.c	2009-04-14 21:23:33 UTC (rev 26099)
+++ branches/busybox_1_13_stable/coreutils/tail.c	2009-04-15 00:11:22 UTC (rev 26100)
@@ -104,7 +104,7 @@
 	if (argv[1] && (argv[1][0] == '+' || argv[1][0] == '-')
 	 && isdigit(argv[1][1])
 	) {
-		count = eat_num(&argv[1][1]);
+		count = eat_num(argv[1]);
 		argv++;
 		argc--;
 	}

Modified: branches/busybox_1_13_stable/shell/ash.c
===================================================================
--- branches/busybox_1_13_stable/shell/ash.c	2009-04-14 21:23:33 UTC (rev 26099)
+++ branches/busybox_1_13_stable/shell/ash.c	2009-04-15 00:11:22 UTC (rev 26100)
@@ -30,7 +30,7 @@
  */
 
 /*
- * The follow should be set to reflect the type of system you have:
+ * The following should be set to reflect the type of system you have:
  *      JOBS -> 1 if you have Berkeley job control, 0 otherwise.
  *      define SYSV if you are running under System V.
  *      define DEBUG=1 to compile in debugging ('set -o debug' to turn on)
@@ -40,6 +40,11 @@
  * a quit signal will generate a core dump.
  */
 #define DEBUG 0
+/* Tweak debug output verbosity here */
+#define DEBUG_TIME 0
+#define DEBUG_PID 1
+#define DEBUG_SIG 1
+
 #define PROFILE 0
 
 #define IFS_BROKEN
@@ -47,25 +52,25 @@
 #define JOBS ENABLE_ASH_JOB_CONTROL
 
 #if DEBUG
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
+# ifndef _GNU_SOURCE
+#  define _GNU_SOURCE
+# endif
 #endif
-#endif
 
 #include "busybox.h" /* for applet_names */
 #include <paths.h>
 #include <setjmp.h>
 #include <fnmatch.h>
 #if JOBS || ENABLE_ASH_READ_NCHARS
-#include <termios.h>
+# include <termios.h>
 #endif
 
 #ifndef PIPE_BUF
-#define PIPE_BUF 4096           /* amount of buffering in a pipe */
+# define PIPE_BUF 4096           /* amount of buffering in a pipe */
 #endif
 
 #if defined(__uClinux__)
-#error "Do not even bother, ash will not run on uClinux"
+# error "Do not even bother, ash will not run on uClinux"
 #endif
 
 
@@ -76,14 +81,6 @@
 #define CMDTABLESIZE 31         /* should be prime */
 
 
-/* ============ Misc helpers */
-
-#define xbarrier() do { __asm__ __volatile__ ("": : :"memory"); } while (0)
-
-/* C99 say: "char" declaration may be signed or unsigned default */
-#define signed_char2int(sc) ((int)((signed char)sc))
-
-
 /* ============ Shell options */
 
 static const char *const optletters_optnames[] = {
@@ -245,7 +242,30 @@
 } while (0)
 
 
+/* ============ DEBUG */
+#if DEBUG
+static void trace_printf(const char *fmt, ...);
+static void trace_vprintf(const char *fmt, va_list va);
+# define TRACE(param)    trace_printf param
+# define TRACEV(param)   trace_vprintf param
+# define close(f) do { \
+	int dfd = (f); \
+	if (close(dfd) < 0) \
+		bb_error_msg("bug on %d: closing %d(%x)", \
+			__LINE__, dfd, dfd); \
+} while (0)
+#else
+# define TRACE(param)
+# define TRACEV(param)
+#endif
+
+
 /* ============ Utility functions */
+#define xbarrier() do { __asm__ __volatile__ ("": : :"memory"); } while (0)
+
+/* C99 say: "char" declaration may be signed or unsigned by default */
+#define signed_char2int(sc) ((int)(signed char)(sc))
+
 static int isdigit_str9(const char *str)
 {
 	int maxlen = 9 + 1; /* max 9 digits: 999999999 */
@@ -284,6 +304,12 @@
 	exception = e;
 	longjmp(exception_handler->loc, 1);
 }
+#if DEBUG
+#define raise_exception(e) do { \
+	TRACE(("raising exception %d on line %d\n", (e), __LINE__)); \
+	raise_exception(e); \
+} while (0)
+#endif
 
 /*
  * Called from trap.c when a SIGINT is received.  (If the user specifies
@@ -316,6 +342,12 @@
 	raise_exception(i);
 	/* NOTREACHED */
 }
+#if DEBUG
+#define raise_interrupt() do { \
+	TRACE(("raising interrupt on line %d\n", __LINE__)); \
+	raise_interrupt(); \
+} while (0)
+#endif
 
 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
 static void
@@ -334,7 +366,9 @@
 		raise_interrupt();
 }
 #define FORCE_INT_ON force_int_on()
-#else
+
+#else /* !ASH_OPTIMIZE_FOR_SIZE */
+
 #define INT_ON do { \
 	xbarrier(); \
 	if (--suppressint == 0 && intpending) \
@@ -346,7 +380,7 @@
 	if (intpending) \
 		raise_interrupt(); \
 } while (0)
-#endif /* ASH_OPTIMIZE_FOR_SIZE */
+#endif /* !ASH_OPTIMIZE_FOR_SIZE */
 
 #define SAVE_INT(v) ((v) = suppressint)
 
@@ -376,7 +410,6 @@
 onsig(int signo)
 {
 	gotsig[signo - 1] = 1;
-	pendingsig = signo;
 
 	if (/* exsig || */ (signo == SIGINT && !trap[SIGINT])) {
 		if (!suppressint) {
@@ -384,6 +417,8 @@
 			raise_interrupt(); /* does not return */
 		}
 		intpending = 1;
+	} else {
+		pendingsig = signo;
 	}
 }
 
@@ -684,6 +719,12 @@
 
 	if (debug != 1)
 		return;
+	if (DEBUG_TIME)
+		fprintf(tracefile, "%u ", (int) time(NULL));
+	if (DEBUG_PID)
+		fprintf(tracefile, "[%u] ", (int) getpid());
+	if (DEBUG_SIG)
+		fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pendingsig, intpending, suppressint);
 	va_start(va, fmt);
 	vfprintf(tracefile, fmt, va);
 	va_end(va);
@@ -694,6 +735,12 @@
 {
 	if (debug != 1)
 		return;
+	if (DEBUG_TIME)
+		fprintf(tracefile, "%u ", (int) time(NULL));
+	if (DEBUG_PID)
+		fprintf(tracefile, "[%u] ", (int) getpid());
+	if (DEBUG_SIG)
+		fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pendingsig, intpending, suppressint);
 	vfprintf(tracefile, fmt, va);
 }
 
@@ -998,14 +1045,6 @@
 	shtree(n, 1, NULL, stdout);
 }
 
-#define TRACE(param)    trace_printf param
-#define TRACEV(param)   trace_vprintf param
-
-#else
-
-#define TRACE(param)
-#define TRACEV(param)
-
 #endif /* DEBUG */
 
 
@@ -3779,7 +3818,7 @@
 	 * NB: _not_ safe_waitpid, we need to detect EINTR */
 	pid = waitpid(-1, &status,
 			(doing_jobctl ? (wait_flags | WUNTRACED) : wait_flags));
-	TRACE(("wait returns pid=%d, status=0x%x\n", pid, status));
+	TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n", pid, status, errno, strerror(errno)));
 
 	if (pid <= 0) {
 		/* If we were doing blocking wait and (probably) got EINTR,
@@ -5031,7 +5070,9 @@
 		if (newfd < 0) {
 			/* NTOFD/NFROMFD: copy redir->ndup.dupfd to fd */
 			if (redir->ndup.dupfd < 0) { /* "fd>&-" */
-				close(fd);
+				/* Don't want to trigger debugging */
+				if (fd != -1)
+					close(fd);
 			} else {
 				copyfd(redir->ndup.dupfd, fd | COPYFD_EXACT);
 			}
@@ -5084,7 +5125,7 @@
 				/*close(fd);*/
 				copyfd(copy, fd | COPYFD_EXACT);
 			}
-			close(copy);
+			close(copy & ~COPYFD_RESTORE);
 		}
 	}
 	redirlist = rp->next;
@@ -7871,20 +7912,30 @@
 	pendingsig = 0;
 	xbarrier();
 
+	TRACE(("dotrap entered\n"));
 	for (i = 1, q = gotsig; i < NSIG; i++, q++) {
 		if (!*q)
 			continue;
-		*q = '\0';
 
 		p = trap[i];
+		/* non-trapped SIGINT is handled separately by raise_interrupt,
+		 * don't upset it by resetting gotsig[SIGINT-1] */
+		if (i == SIGINT && !p)
+			continue;
+
+		TRACE(("sig %d is active, will run handler '%s'\n", i, p));
+		*q = '\0';
 		if (!p)
 			continue;
 		skip = evalstring(p, SKIPEVAL);
 		exitstatus = savestatus;
-		if (skip)
+		if (skip) {
+			TRACE(("dotrap returns %d\n", skip));
 			return skip;
+		}
 	}
 
+	TRACE(("dotrap returns 0\n"));
 	return 0;
 }
 
@@ -7906,28 +7957,32 @@
 static void
 evaltree(union node *n, int flags)
 {
-
 	struct jmploc *volatile savehandler = exception_handler;
 	struct jmploc jmploc;
 	int checkexit = 0;
 	void (*evalfn)(union node *, int);
 	int status;
+	int int_level;
 
+	SAVE_INT(int_level);
+
 	if (n == NULL) {
 		TRACE(("evaltree(NULL) called\n"));
 		goto out1;
 	}
-	TRACE(("pid %d, evaltree(%p: %d, %d) called\n",
-			getpid(), n, n->type, flags));
+	TRACE(("evaltree(%p: %d, %d) called\n",	n, n->type, flags));
 
 	exception_handler = &jmploc;
 	{
 		int err = setjmp(jmploc.loc);
 		if (err) {
 			/* if it was a signal, check for trap handlers */
-			if (exception == EXSIG)
+			if (exception == EXSIG) {
+				TRACE(("exception %d (EXSIG) in evaltree, err=%d\n", exception, err));
 				goto out;
+			}
 			/* continue on the way out */
+			TRACE(("exception %d in evaltree, propagating err=%d\n", exception, err));
 			exception_handler = savehandler;
 			longjmp(exception_handler->loc, err);
 		}
@@ -8010,7 +8065,8 @@
 		if (exitstatus == 0) {
 			n = n->nif.ifpart;
 			goto evaln;
-		} else if (n->nif.elsepart) {
+		}
+		if (n->nif.elsepart) {
 			n = n->nif.elsepart;
 			goto evaln;
 		}
@@ -8036,6 +8092,9 @@
  exexit:
 		raise_exception(EXEXIT);
 	}
+
+	RESTORE_INT(int_level);
+	TRACE(("leaving evaltree (no interrupts)\n"));
 }
 
 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
@@ -8281,7 +8340,9 @@
 		if (prevfd >= 0)
 			close(prevfd);
 		prevfd = pip[0];
-		close(pip[1]);
+		/* Don't want to trigger debugging */
+		if (pip[1] != -1)
+			close(pip[1]);
 	}
 	if (n->npipe.pipe_backgnd == 0) {
 		exitstatus = waitforjob(jp);
@@ -8913,6 +8974,7 @@
 			if (forkshell(jp, cmd, FORK_FG) != 0) {
 				exitstatus = waitforjob(jp);
 				INT_ON;
+				TRACE(("forked child exited with %d\n", exitstatus));
 				break;
 			}
 			FORCE_INT_ON;
@@ -12391,7 +12453,7 @@
 #endif
 
 	status = 0;
-	startword = 1;
+	startword = 2;
 	backslash = 0;
 #if ENABLE_ASH_READ_TIMEOUT
 	if (timeout) /* NB: ensuring end_ms is nonzero */
@@ -12399,6 +12461,8 @@
 #endif
 	STARTSTACKSTR(p);
 	do {
+		const char *is_ifs;
+
 #if ENABLE_ASH_READ_TIMEOUT
 		if (end_ms) {
 			struct pollfd pfd[1];
@@ -12428,25 +12492,34 @@
 			continue;
 		}
 		if (!rflag && c == '\\') {
-			backslash++;
+			backslash = 1;
 			continue;
 		}
 		if (c == '\n')
 			break;
-		if (startword && *ifs == ' ' && strchr(ifs, c)) {
-			continue;
+		is_ifs = strchr(ifs, c);
+		if (startword && is_ifs) {
+			if (isspace(c))
+				continue;
+			/* non-space ifs char */
+			startword--;
+			if (startword == 1) /* first one? */
+				continue;
 		}
 		startword = 0;
-		if (ap[1] != NULL && strchr(ifs, c) != NULL) {
+		if (ap[1] != NULL && is_ifs) {
+			const char *beg;
 			STACKSTRNUL(p);
-			setvar(*ap, stackblock(), 0);
+			beg = stackblock();
+			setvar(*ap, beg, 0);
 			ap++;
-			startword = 1;
+			/* can we skip one non-space ifs? (2: yes) */
+			startword = isspace(c) ? 2 : 1;
 			STARTSTACKSTR(p);
-		} else {
+			continue;
+		}
  put:
-			STPUTC(c, p);
-		}
+		STPUTC(c, p);
 	}
 /* end of do {} while: */
 #if ENABLE_ASH_READ_NCHARS
@@ -12460,8 +12533,8 @@
 #endif
 
 	STACKSTRNUL(p);
-	/* Remove trailing blanks */
-	while ((char *)stackblock() <= --p && strchr(ifs, *p) != NULL)
+	/* Remove trailing space ifs chars */
+	while ((char *)stackblock() <= --p && isspace(*p) && strchr(ifs, *p) != NULL)
 		*p = '\0';
 	setvar(*ap, stackblock(), 0);
 	while (*++ap != NULL)
@@ -13640,7 +13713,7 @@
 	exception_handler = &jmploc;
 #if DEBUG
 	opentrace();
-	trace_puts("Shell args: ");
+	TRACE(("Shell args: "));
 	trace_puts_args(argv);
 #endif
 	rootpid = getpid();
@@ -13692,8 +13765,14 @@
 	}
  state3:
 	state = 4;
-	if (minusc)
+	if (minusc) {
+		/* evalstring pushes parsefile stack.
+		 * Ensure we don't falsely claim that 0 (stdin)
+		 * is one of stacked source fds */
+		if (!sflag)
+			g_parsefile->fd = -1;
 		evalstring(minusc, 0);
+	}
 
 	if (sflag || minusc == NULL) {
 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
@@ -13720,15 +13799,7 @@
 	/* NOTREACHED */
 }
 
-#if DEBUG
-const char *applet_name = "debug stuff usage";
-int main(int argc, char **argv)
-{
-	return ash_main(argc, argv);
-}
-#endif
 
-
 /*-
  * Copyright (c) 1989, 1991, 1993, 1994
  *      The Regents of the University of California.  All rights reserved.

Added: branches/busybox_1_13_stable/shell/ash_test/ash-read/read_ifs.right
===================================================================
--- branches/busybox_1_13_stable/shell/ash_test/ash-read/read_ifs.right	                        (rev 0)
+++ branches/busybox_1_13_stable/shell/ash_test/ash-read/read_ifs.right	2009-04-15 00:11:22 UTC (rev 26100)
@@ -0,0 +1,7 @@
+.a. .b. .c.
+.a. .b. .c.
+.a. .. .b,c.
+.a. .. .b,c.
+.a. .. .c.
+.a. .. .c. .d.
+.a. .. .b,c,d  ,  ,.

Added: branches/busybox_1_13_stable/shell/ash_test/ash-read/read_ifs.tests
===================================================================
--- branches/busybox_1_13_stable/shell/ash_test/ash-read/read_ifs.tests	                        (rev 0)
+++ branches/busybox_1_13_stable/shell/ash_test/ash-read/read_ifs.tests	2009-04-15 00:11:22 UTC (rev 26100)
@@ -0,0 +1,7 @@
+printf 'a\t\tb\tc\n' | ( IFS=$(printf "\t") read a b c; echo ".$a. .$b. .$c." )
+printf 'a\t\tb\tc\n' | ( IFS=$(printf " \t") read a b c; echo ".$a. .$b. .$c." )
+printf 'a,,b,c\n'    | ( IFS="," read a b c; echo ".$a. .$b. .$c." )
+printf 'a,,b,c\n'    | ( IFS=" ," read a b c; echo ".$a. .$b. .$c." )
+printf 'a ,, c\n'    | ( IFS=" ," read a b c; echo ".$a. .$b. .$c." )
+printf 'a ,, c d\n'  | ( IFS=" ," read a b c d; echo ".$a. .$b. .$c. .$d." )
+printf ' a,,b,c,d  ,  ,\n' | ( IFS=" ," read a b c; echo ".$a. .$b. .$c." )


Property changes on: branches/busybox_1_13_stable/shell/ash_test/ash-read/read_ifs.tests
___________________________________________________________________
Added: svn:executable
   + *

Modified: branches/busybox_1_13_stable/shell/hush.c
===================================================================
--- branches/busybox_1_13_stable/shell/hush.c	2009-04-14 21:23:33 UTC (rev 26099)
+++ branches/busybox_1_13_stable/shell/hush.c	2009-04-15 00:11:22 UTC (rev 26100)
@@ -458,8 +458,11 @@
 	smallint fake_mode;
 	/* these three support $?, $#, and $1 */
 	smalluint last_return_code;
+	/* is global_argv and global_argv[1..n] malloced? (note: not [0]) */
+	smalluint global_args_malloced;
+	/* how many non-NULL argv's we have. NB: $# + 1 */
+	int global_argc;
 	char **global_argv;
-	int global_argc;
 #if ENABLE_HUSH_LOOPS
 	unsigned depth_break_continue;
 	unsigned depth_of_loop;
@@ -633,7 +636,7 @@
 	return dst;
 }
 
-static char **add_strings_to_strings(char **strings, char **add)
+static char **add_strings_to_strings(char **strings, char **add, int need_to_dup)
 {
 	int i;
 	unsigned count1;
@@ -658,7 +661,7 @@
 	v[count1 + count2] = NULL;
 	i = count2;
 	while (--i >= 0)
-		v[count1 + i] = add[i];
+		v[count1 + i] = (need_to_dup ? xstrdup(add[i]) : add[i]);
 	return v;
 }
 
@@ -667,7 +670,7 @@
 	char *v[2];
 	v[0] = add;
 	v[1] = NULL;
-	return add_strings_to_strings(strings, v);
+	return add_strings_to_strings(strings, v, /*dup:*/ 0);
 }
 
 static void putenv_all(char **strings)
@@ -1213,8 +1216,13 @@
  * Otherwise, just finish current list[] and start new */
 static int o_save_ptr(o_string *o, int n)
 {
-	if (o->o_glob)
-		return o_glob(o, n); /* o_save_ptr_helper is inside */
+	if (o->o_glob) { /* if globbing is requested */
+		/* If o->has_empty_slot, list[n] was already globbed
+		 * (if it was requested back then when it was filled)
+		 * so don't do that again! */
+		if (!o->has_empty_slot)
+			return o_glob(o, n); /* o_save_ptr_helper is inside */
+	}
 	return o_save_ptr_helper(o, n);
 }
 
@@ -4279,6 +4287,11 @@
 		switch (opt) {
 		case 'c':
 			G.global_argv = argv + optind;
+			if (!argv[optind]) {
+				/* -c 'script' (no params): prevent empty $0 */
+				*--G.global_argv = argv[0];
+				optind--;
+			} /* else -c 'script' PAR0 PAR1: $0 is PAR0 */
 			G.global_argc = argc - optind;
 			opt = parse_and_run_string(optarg, 0 /* parse_flag */);
 			goto final_return;
@@ -4639,18 +4652,69 @@
 	return set_local_var(string, 0);
 }
 
-/* built-in 'set [VAR=value]' handler */
+/* built-in 'set' handler
+ * SUSv3 says:
+ * set [-abCefmnuvx] [-h] [-o option] [argument...]
+ * set [+abCefmnuvx] [+h] [+o option] [argument...]
+ * set -- [argument...]
+ * set -o
+ * set +o
+ * Implementations shall support the options in both their hyphen and
+ * plus-sign forms. These options can also be specified as options to sh.
+ * Examples:
+ * Write out all variables and their values: set
+ * Set $1, $2, and $3 and set "$#" to 3: set c a b
+ * Turn on the -x and -v options: set -xv
+ * Unset all positional parameters: set --
+ * Set $1 to the value of x, even if it begins with '-' or '+': set -- "$x"
+ * Set the positional parameters to the expansion of x, even if x expands
+ * with a leading '-' or '+': set -- $x
+ *
+ * So far, we only support "set -- [argument...]" by ignoring all options
+ * (also, "-o option" will be mishandled by taking "option" as parameter #1).
+ */
 static int builtin_set(char **argv)
 {
-	char *temp = argv[1];
 	struct variable *e;
+	char **pp;
+	char *arg = *++argv;
 
-	if (temp == NULL)
+	if (arg == NULL) {
 		for (e = G.top_var; e; e = e->next)
 			puts(e->varstr);
-	else
-		set_local_var(xstrdup(temp), 0);
+	} else {
+		/* NB: G.global_argv[0] ($0) is never freed/changed */
 
+		if (G.global_args_malloced) {
+			pp = G.global_argv;
+			while (*++pp)
+				free(*pp);
+			G.global_argv[1] = NULL;
+		} else {
+			G.global_args_malloced = 1;
+			pp = xzalloc(sizeof(pp[0]) * 2);
+			pp[0] = G.global_argv[0]; /* retain $0 */
+			G.global_argv = pp;
+		}
+		do  {
+			if (arg[0] == '+')
+				continue;
+			if (arg[0] != '-')
+				break;
+			if (arg[1] == '-' && arg[2] == '\0') {
+				argv++;
+				break;
+			}
+		} while ((arg = *++argv) != NULL);
+		/* Now argv[0] is 1st argument */
+
+		/* This realloc's G.global_argv */
+		G.global_argv = pp = add_strings_to_strings(G.global_argv, argv, /*dup:*/ 1);
+		G.global_argc = 1;
+		while (*++pp)
+			G.global_argc++;
+	}
+
 	return EXIT_SUCCESS;
 }
 
@@ -4661,9 +4725,14 @@
 		n = atoi(argv[1]);
 	}
 	if (n >= 0 && n < G.global_argc) {
-		G.global_argv[n] = G.global_argv[0];
+		if (G.global_args_malloced) {
+			int m = 1;
+			while (m <= n)
+				free(G.global_argv[m++]);
+		}
 		G.global_argc -= n;
-		G.global_argv += n;
+		memmove(&G.global_argv[1], &G.global_argv[n+1],
+				G.global_argc * sizeof(G.global_argv[0]));
 		return EXIT_SUCCESS;
 	}
 	return EXIT_FAILURE;

Modified: branches/busybox_1_13_stable/shell/hush_test/hush-parsing/starquoted2.right
===================================================================
--- branches/busybox_1_13_stable/shell/hush_test/hush-parsing/starquoted2.right	2009-04-14 21:23:33 UTC (rev 26099)
+++ branches/busybox_1_13_stable/shell/hush_test/hush-parsing/starquoted2.right	2009-04-15 00:11:22 UTC (rev 26100)
@@ -1,2 +1,3 @@
 Should be printed
 Should be printed
+Empty:

Modified: branches/busybox_1_13_stable/shell/hush_test/hush-parsing/starquoted2.tests
===================================================================
--- branches/busybox_1_13_stable/shell/hush_test/hush-parsing/starquoted2.tests	2009-04-14 21:23:33 UTC (rev 26099)
+++ branches/busybox_1_13_stable/shell/hush_test/hush-parsing/starquoted2.tests	2009-04-15 00:11:22 UTC (rev 26100)
@@ -12,3 +12,6 @@
 for a in """$@"; do echo Should not be printed; done
 for a in """$@"''"$@"''; do echo Should not be printed; done
 for a in ""; do echo Should be printed; done
+
+# Bug 207: "$@" expands to nothing, and we erroneously glob "%s\\n" twice:
+printf "Empty:%s\\n" "$@"

Modified: branches/busybox_1_13_stable/util-linux/volume_id/get_devname.c
===================================================================
--- branches/busybox_1_13_stable/util-linux/volume_id/get_devname.c	2009-04-14 21:23:33 UTC (rev 26099)
+++ branches/busybox_1_13_stable/util-linux/volume_id/get_devname.c	2009-04-15 00:11:22 UTC (rev 26100)
@@ -223,13 +223,11 @@
 char *get_devname_from_label(const char *spec)
 {
 	struct uuidCache_s *uc;
-	int spec_len = strlen(spec);
 
 	uuidcache_init();
 	uc = uuidCache;
 	while (uc) {
-// FIXME: empty label ("LABEL=") matches anything??!
-		if (uc->label[0] && strncmp(spec, uc->label, spec_len) == 0) {
+		if (uc->label[0] && strcmp(spec, uc->label) == 0) {
 			return xstrdup(uc->device);
 		}
 		uc = uc->next;



More information about the busybox-cvs mailing list