[118c546] | 1 | Submitted By: Jim Gifford (jim at cross-lfs dot org)
|
---|
| 2 | Date: 03-28-2009
|
---|
| 3 | Initial Package Version: 1.13.3
|
---|
| 4 | Origin: Upstream
|
---|
| 5 | Upstream Status: Applied
|
---|
| 6 | Description: This is a branch update for busybox-1.13.3, and should be
|
---|
| 7 | rechecked periodically.
|
---|
| 8 |
|
---|
| 9 | diff -Naur busybox-1.13.3.orig/coreutils/tail.c busybox-1.13.3/coreutils/tail.c
|
---|
| 10 | --- busybox-1.13.3.orig/coreutils/tail.c 2009-02-26 03:47:02.000000000 -0800
|
---|
| 11 | +++ busybox-1.13.3/coreutils/tail.c 2009-03-28 08:25:12.762859338 -0700
|
---|
| 12 | @@ -104,7 +104,7 @@
|
---|
| 13 | if (argv[1] && (argv[1][0] == '+' || argv[1][0] == '-')
|
---|
| 14 | && isdigit(argv[1][1])
|
---|
| 15 | ) {
|
---|
| 16 | - count = eat_num(&argv[1][1]);
|
---|
| 17 | + count = eat_num(argv[1]);
|
---|
| 18 | argv++;
|
---|
| 19 | argc--;
|
---|
| 20 | }
|
---|
| 21 | diff -Naur busybox-1.13.3.orig/shell/ash.c busybox-1.13.3/shell/ash.c
|
---|
| 22 | --- busybox-1.13.3.orig/shell/ash.c 2009-02-26 03:46:55.000000000 -0800
|
---|
| 23 | +++ busybox-1.13.3/shell/ash.c 2009-03-28 08:25:12.198825534 -0700
|
---|
| 24 | @@ -30,7 +30,7 @@
|
---|
| 25 | */
|
---|
| 26 |
|
---|
| 27 | /*
|
---|
| 28 | - * The follow should be set to reflect the type of system you have:
|
---|
| 29 | + * The following should be set to reflect the type of system you have:
|
---|
| 30 | * JOBS -> 1 if you have Berkeley job control, 0 otherwise.
|
---|
| 31 | * define SYSV if you are running under System V.
|
---|
| 32 | * define DEBUG=1 to compile in debugging ('set -o debug' to turn on)
|
---|
| 33 | @@ -40,6 +40,11 @@
|
---|
| 34 | * a quit signal will generate a core dump.
|
---|
| 35 | */
|
---|
| 36 | #define DEBUG 0
|
---|
| 37 | +/* Tweak debug output verbosity here */
|
---|
| 38 | +#define DEBUG_TIME 0
|
---|
| 39 | +#define DEBUG_PID 1
|
---|
| 40 | +#define DEBUG_SIG 1
|
---|
| 41 | +
|
---|
| 42 | #define PROFILE 0
|
---|
| 43 |
|
---|
| 44 | #define IFS_BROKEN
|
---|
| 45 | @@ -47,9 +52,9 @@
|
---|
| 46 | #define JOBS ENABLE_ASH_JOB_CONTROL
|
---|
| 47 |
|
---|
| 48 | #if DEBUG
|
---|
| 49 | -#ifndef _GNU_SOURCE
|
---|
| 50 | -#define _GNU_SOURCE
|
---|
| 51 | -#endif
|
---|
| 52 | +# ifndef _GNU_SOURCE
|
---|
| 53 | +# define _GNU_SOURCE
|
---|
| 54 | +# endif
|
---|
| 55 | #endif
|
---|
| 56 |
|
---|
| 57 | #include "busybox.h" /* for applet_names */
|
---|
| 58 | @@ -57,15 +62,15 @@
|
---|
| 59 | #include <setjmp.h>
|
---|
| 60 | #include <fnmatch.h>
|
---|
| 61 | #if JOBS || ENABLE_ASH_READ_NCHARS
|
---|
| 62 | -#include <termios.h>
|
---|
| 63 | +# include <termios.h>
|
---|
| 64 | #endif
|
---|
| 65 |
|
---|
| 66 | #ifndef PIPE_BUF
|
---|
| 67 | -#define PIPE_BUF 4096 /* amount of buffering in a pipe */
|
---|
| 68 | +# define PIPE_BUF 4096 /* amount of buffering in a pipe */
|
---|
| 69 | #endif
|
---|
| 70 |
|
---|
| 71 | #if defined(__uClinux__)
|
---|
| 72 | -#error "Do not even bother, ash will not run on uClinux"
|
---|
| 73 | +# error "Do not even bother, ash will not run on uClinux"
|
---|
| 74 | #endif
|
---|
| 75 |
|
---|
| 76 |
|
---|
| 77 | @@ -76,14 +81,6 @@
|
---|
| 78 | #define CMDTABLESIZE 31 /* should be prime */
|
---|
| 79 |
|
---|
| 80 |
|
---|
| 81 | -/* ============ Misc helpers */
|
---|
| 82 | -
|
---|
| 83 | -#define xbarrier() do { __asm__ __volatile__ ("": : :"memory"); } while (0)
|
---|
| 84 | -
|
---|
| 85 | -/* C99 say: "char" declaration may be signed or unsigned default */
|
---|
| 86 | -#define signed_char2int(sc) ((int)((signed char)sc))
|
---|
| 87 | -
|
---|
| 88 | -
|
---|
| 89 | /* ============ Shell options */
|
---|
| 90 |
|
---|
| 91 | static const char *const optletters_optnames[] = {
|
---|
| 92 | @@ -245,7 +242,30 @@
|
---|
| 93 | } while (0)
|
---|
| 94 |
|
---|
| 95 |
|
---|
| 96 | +/* ============ DEBUG */
|
---|
| 97 | +#if DEBUG
|
---|
| 98 | +static void trace_printf(const char *fmt, ...);
|
---|
| 99 | +static void trace_vprintf(const char *fmt, va_list va);
|
---|
| 100 | +# define TRACE(param) trace_printf param
|
---|
| 101 | +# define TRACEV(param) trace_vprintf param
|
---|
| 102 | +# define close(f) do { \
|
---|
| 103 | + int dfd = (f); \
|
---|
| 104 | + if (close(dfd) < 0) \
|
---|
| 105 | + bb_error_msg("bug on %d: closing %d(%x)", \
|
---|
| 106 | + __LINE__, dfd, dfd); \
|
---|
| 107 | +} while (0)
|
---|
| 108 | +#else
|
---|
| 109 | +# define TRACE(param)
|
---|
| 110 | +# define TRACEV(param)
|
---|
| 111 | +#endif
|
---|
| 112 | +
|
---|
| 113 | +
|
---|
| 114 | /* ============ Utility functions */
|
---|
| 115 | +#define xbarrier() do { __asm__ __volatile__ ("": : :"memory"); } while (0)
|
---|
| 116 | +
|
---|
| 117 | +/* C99 say: "char" declaration may be signed or unsigned by default */
|
---|
| 118 | +#define signed_char2int(sc) ((int)(signed char)(sc))
|
---|
| 119 | +
|
---|
| 120 | static int isdigit_str9(const char *str)
|
---|
| 121 | {
|
---|
| 122 | int maxlen = 9 + 1; /* max 9 digits: 999999999 */
|
---|
| 123 | @@ -284,6 +304,12 @@
|
---|
| 124 | exception = e;
|
---|
| 125 | longjmp(exception_handler->loc, 1);
|
---|
| 126 | }
|
---|
| 127 | +#if DEBUG
|
---|
| 128 | +#define raise_exception(e) do { \
|
---|
| 129 | + TRACE(("raising exception %d on line %d\n", (e), __LINE__)); \
|
---|
| 130 | + raise_exception(e); \
|
---|
| 131 | +} while (0)
|
---|
| 132 | +#endif
|
---|
| 133 |
|
---|
| 134 | /*
|
---|
| 135 | * Called from trap.c when a SIGINT is received. (If the user specifies
|
---|
| 136 | @@ -316,6 +342,12 @@
|
---|
| 137 | raise_exception(i);
|
---|
| 138 | /* NOTREACHED */
|
---|
| 139 | }
|
---|
| 140 | +#if DEBUG
|
---|
| 141 | +#define raise_interrupt() do { \
|
---|
| 142 | + TRACE(("raising interrupt on line %d\n", __LINE__)); \
|
---|
| 143 | + raise_interrupt(); \
|
---|
| 144 | +} while (0)
|
---|
| 145 | +#endif
|
---|
| 146 |
|
---|
| 147 | #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
|
---|
| 148 | static void
|
---|
| 149 | @@ -334,7 +366,9 @@
|
---|
| 150 | raise_interrupt();
|
---|
| 151 | }
|
---|
| 152 | #define FORCE_INT_ON force_int_on()
|
---|
| 153 | -#else
|
---|
| 154 | +
|
---|
| 155 | +#else /* !ASH_OPTIMIZE_FOR_SIZE */
|
---|
| 156 | +
|
---|
| 157 | #define INT_ON do { \
|
---|
| 158 | xbarrier(); \
|
---|
| 159 | if (--suppressint == 0 && intpending) \
|
---|
| 160 | @@ -346,7 +380,7 @@
|
---|
| 161 | if (intpending) \
|
---|
| 162 | raise_interrupt(); \
|
---|
| 163 | } while (0)
|
---|
| 164 | -#endif /* ASH_OPTIMIZE_FOR_SIZE */
|
---|
| 165 | +#endif /* !ASH_OPTIMIZE_FOR_SIZE */
|
---|
| 166 |
|
---|
| 167 | #define SAVE_INT(v) ((v) = suppressint)
|
---|
| 168 |
|
---|
| 169 | @@ -376,7 +410,6 @@
|
---|
| 170 | onsig(int signo)
|
---|
| 171 | {
|
---|
| 172 | gotsig[signo - 1] = 1;
|
---|
| 173 | - pendingsig = signo;
|
---|
| 174 |
|
---|
| 175 | if (/* exsig || */ (signo == SIGINT && !trap[SIGINT])) {
|
---|
| 176 | if (!suppressint) {
|
---|
| 177 | @@ -384,6 +417,8 @@
|
---|
| 178 | raise_interrupt(); /* does not return */
|
---|
| 179 | }
|
---|
| 180 | intpending = 1;
|
---|
| 181 | + } else {
|
---|
| 182 | + pendingsig = signo;
|
---|
| 183 | }
|
---|
| 184 | }
|
---|
| 185 |
|
---|
| 186 | @@ -684,6 +719,12 @@
|
---|
| 187 |
|
---|
| 188 | if (debug != 1)
|
---|
| 189 | return;
|
---|
| 190 | + if (DEBUG_TIME)
|
---|
| 191 | + fprintf(tracefile, "%u ", (int) time(NULL));
|
---|
| 192 | + if (DEBUG_PID)
|
---|
| 193 | + fprintf(tracefile, "[%u] ", (int) getpid());
|
---|
| 194 | + if (DEBUG_SIG)
|
---|
| 195 | + fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pendingsig, intpending, suppressint);
|
---|
| 196 | va_start(va, fmt);
|
---|
| 197 | vfprintf(tracefile, fmt, va);
|
---|
| 198 | va_end(va);
|
---|
| 199 | @@ -694,6 +735,12 @@
|
---|
| 200 | {
|
---|
| 201 | if (debug != 1)
|
---|
| 202 | return;
|
---|
| 203 | + if (DEBUG_TIME)
|
---|
| 204 | + fprintf(tracefile, "%u ", (int) time(NULL));
|
---|
| 205 | + if (DEBUG_PID)
|
---|
| 206 | + fprintf(tracefile, "[%u] ", (int) getpid());
|
---|
| 207 | + if (DEBUG_SIG)
|
---|
| 208 | + fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pendingsig, intpending, suppressint);
|
---|
| 209 | vfprintf(tracefile, fmt, va);
|
---|
| 210 | }
|
---|
| 211 |
|
---|
| 212 | @@ -998,14 +1045,6 @@
|
---|
| 213 | shtree(n, 1, NULL, stdout);
|
---|
| 214 | }
|
---|
| 215 |
|
---|
| 216 | -#define TRACE(param) trace_printf param
|
---|
| 217 | -#define TRACEV(param) trace_vprintf param
|
---|
| 218 | -
|
---|
| 219 | -#else
|
---|
| 220 | -
|
---|
| 221 | -#define TRACE(param)
|
---|
| 222 | -#define TRACEV(param)
|
---|
| 223 | -
|
---|
| 224 | #endif /* DEBUG */
|
---|
| 225 |
|
---|
| 226 |
|
---|
| 227 | @@ -3779,7 +3818,7 @@
|
---|
| 228 | * NB: _not_ safe_waitpid, we need to detect EINTR */
|
---|
| 229 | pid = waitpid(-1, &status,
|
---|
| 230 | (doing_jobctl ? (wait_flags | WUNTRACED) : wait_flags));
|
---|
| 231 | - TRACE(("wait returns pid=%d, status=0x%x\n", pid, status));
|
---|
| 232 | + TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n", pid, status, errno, strerror(errno)));
|
---|
| 233 |
|
---|
| 234 | if (pid <= 0) {
|
---|
| 235 | /* If we were doing blocking wait and (probably) got EINTR,
|
---|
| 236 | @@ -5031,7 +5070,9 @@
|
---|
| 237 | if (newfd < 0) {
|
---|
| 238 | /* NTOFD/NFROMFD: copy redir->ndup.dupfd to fd */
|
---|
| 239 | if (redir->ndup.dupfd < 0) { /* "fd>&-" */
|
---|
| 240 | - close(fd);
|
---|
| 241 | + /* Don't want to trigger debugging */
|
---|
| 242 | + if (fd != -1)
|
---|
| 243 | + close(fd);
|
---|
| 244 | } else {
|
---|
| 245 | copyfd(redir->ndup.dupfd, fd | COPYFD_EXACT);
|
---|
| 246 | }
|
---|
| 247 | @@ -5084,7 +5125,7 @@
|
---|
| 248 | /*close(fd);*/
|
---|
| 249 | copyfd(copy, fd | COPYFD_EXACT);
|
---|
| 250 | }
|
---|
| 251 | - close(copy);
|
---|
| 252 | + close(copy & ~COPYFD_RESTORE);
|
---|
| 253 | }
|
---|
| 254 | }
|
---|
| 255 | redirlist = rp->next;
|
---|
| 256 | @@ -7871,20 +7912,30 @@
|
---|
| 257 | pendingsig = 0;
|
---|
| 258 | xbarrier();
|
---|
| 259 |
|
---|
| 260 | + TRACE(("dotrap entered\n"));
|
---|
| 261 | for (i = 1, q = gotsig; i < NSIG; i++, q++) {
|
---|
| 262 | if (!*q)
|
---|
| 263 | continue;
|
---|
| 264 | - *q = '\0';
|
---|
| 265 |
|
---|
| 266 | p = trap[i];
|
---|
| 267 | + /* non-trapped SIGINT is handled separately by raise_interrupt,
|
---|
| 268 | + * don't upset it by resetting gotsig[SIGINT-1] */
|
---|
| 269 | + if (i == SIGINT && !p)
|
---|
| 270 | + continue;
|
---|
| 271 | +
|
---|
| 272 | + TRACE(("sig %d is active, will run handler '%s'\n", i, p));
|
---|
| 273 | + *q = '\0';
|
---|
| 274 | if (!p)
|
---|
| 275 | continue;
|
---|
| 276 | skip = evalstring(p, SKIPEVAL);
|
---|
| 277 | exitstatus = savestatus;
|
---|
| 278 | - if (skip)
|
---|
| 279 | + if (skip) {
|
---|
| 280 | + TRACE(("dotrap returns %d\n", skip));
|
---|
| 281 | return skip;
|
---|
| 282 | + }
|
---|
| 283 | }
|
---|
| 284 |
|
---|
| 285 | + TRACE(("dotrap returns 0\n"));
|
---|
| 286 | return 0;
|
---|
| 287 | }
|
---|
| 288 |
|
---|
| 289 | @@ -7906,28 +7957,32 @@
|
---|
| 290 | static void
|
---|
| 291 | evaltree(union node *n, int flags)
|
---|
| 292 | {
|
---|
| 293 | -
|
---|
| 294 | struct jmploc *volatile savehandler = exception_handler;
|
---|
| 295 | struct jmploc jmploc;
|
---|
| 296 | int checkexit = 0;
|
---|
| 297 | void (*evalfn)(union node *, int);
|
---|
| 298 | int status;
|
---|
| 299 | + int int_level;
|
---|
| 300 | +
|
---|
| 301 | + SAVE_INT(int_level);
|
---|
| 302 |
|
---|
| 303 | if (n == NULL) {
|
---|
| 304 | TRACE(("evaltree(NULL) called\n"));
|
---|
| 305 | goto out1;
|
---|
| 306 | }
|
---|
| 307 | - TRACE(("pid %d, evaltree(%p: %d, %d) called\n",
|
---|
| 308 | - getpid(), n, n->type, flags));
|
---|
| 309 | + TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags));
|
---|
| 310 |
|
---|
| 311 | exception_handler = &jmploc;
|
---|
| 312 | {
|
---|
| 313 | int err = setjmp(jmploc.loc);
|
---|
| 314 | if (err) {
|
---|
| 315 | /* if it was a signal, check for trap handlers */
|
---|
| 316 | - if (exception == EXSIG)
|
---|
| 317 | + if (exception == EXSIG) {
|
---|
| 318 | + TRACE(("exception %d (EXSIG) in evaltree, err=%d\n", exception, err));
|
---|
| 319 | goto out;
|
---|
| 320 | + }
|
---|
| 321 | /* continue on the way out */
|
---|
| 322 | + TRACE(("exception %d in evaltree, propagating err=%d\n", exception, err));
|
---|
| 323 | exception_handler = savehandler;
|
---|
| 324 | longjmp(exception_handler->loc, err);
|
---|
| 325 | }
|
---|
| 326 | @@ -8010,7 +8065,8 @@
|
---|
| 327 | if (exitstatus == 0) {
|
---|
| 328 | n = n->nif.ifpart;
|
---|
| 329 | goto evaln;
|
---|
| 330 | - } else if (n->nif.elsepart) {
|
---|
| 331 | + }
|
---|
| 332 | + if (n->nif.elsepart) {
|
---|
| 333 | n = n->nif.elsepart;
|
---|
| 334 | goto evaln;
|
---|
| 335 | }
|
---|
| 336 | @@ -8036,6 +8092,9 @@
|
---|
| 337 | exexit:
|
---|
| 338 | raise_exception(EXEXIT);
|
---|
| 339 | }
|
---|
| 340 | +
|
---|
| 341 | + RESTORE_INT(int_level);
|
---|
| 342 | + TRACE(("leaving evaltree (no interrupts)\n"));
|
---|
| 343 | }
|
---|
| 344 |
|
---|
| 345 | #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
|
---|
| 346 | @@ -8281,7 +8340,9 @@
|
---|
| 347 | if (prevfd >= 0)
|
---|
| 348 | close(prevfd);
|
---|
| 349 | prevfd = pip[0];
|
---|
| 350 | - close(pip[1]);
|
---|
| 351 | + /* Don't want to trigger debugging */
|
---|
| 352 | + if (pip[1] != -1)
|
---|
| 353 | + close(pip[1]);
|
---|
| 354 | }
|
---|
| 355 | if (n->npipe.pipe_backgnd == 0) {
|
---|
| 356 | exitstatus = waitforjob(jp);
|
---|
| 357 | @@ -8913,6 +8974,7 @@
|
---|
| 358 | if (forkshell(jp, cmd, FORK_FG) != 0) {
|
---|
| 359 | exitstatus = waitforjob(jp);
|
---|
| 360 | INT_ON;
|
---|
| 361 | + TRACE(("forked child exited with %d\n", exitstatus));
|
---|
| 362 | break;
|
---|
| 363 | }
|
---|
| 364 | FORCE_INT_ON;
|
---|
| 365 | @@ -13640,7 +13702,7 @@
|
---|
| 366 | exception_handler = &jmploc;
|
---|
| 367 | #if DEBUG
|
---|
| 368 | opentrace();
|
---|
| 369 | - trace_puts("Shell args: ");
|
---|
| 370 | + TRACE(("Shell args: "));
|
---|
| 371 | trace_puts_args(argv);
|
---|
| 372 | #endif
|
---|
| 373 | rootpid = getpid();
|
---|
| 374 | @@ -13692,8 +13754,14 @@
|
---|
| 375 | }
|
---|
| 376 | state3:
|
---|
| 377 | state = 4;
|
---|
| 378 | - if (minusc)
|
---|
| 379 | + if (minusc) {
|
---|
| 380 | + /* evalstring pushes parsefile stack.
|
---|
| 381 | + * Ensure we don't falsely claim that 0 (stdin)
|
---|
| 382 | + * is one of stacked source fds */
|
---|
| 383 | + if (!sflag)
|
---|
| 384 | + g_parsefile->fd = -1;
|
---|
| 385 | evalstring(minusc, 0);
|
---|
| 386 | + }
|
---|
| 387 |
|
---|
| 388 | if (sflag || minusc == NULL) {
|
---|
| 389 | #if ENABLE_FEATURE_EDITING_SAVEHISTORY
|
---|
| 390 | @@ -13720,14 +13788,6 @@
|
---|
| 391 | /* NOTREACHED */
|
---|
| 392 | }
|
---|
| 393 |
|
---|
| 394 | -#if DEBUG
|
---|
| 395 | -const char *applet_name = "debug stuff usage";
|
---|
| 396 | -int main(int argc, char **argv)
|
---|
| 397 | -{
|
---|
| 398 | - return ash_main(argc, argv);
|
---|
| 399 | -}
|
---|
| 400 | -#endif
|
---|
| 401 | -
|
---|
| 402 |
|
---|
| 403 | /*-
|
---|
| 404 | * Copyright (c) 1989, 1991, 1993, 1994
|
---|
| 405 | diff -Naur busybox-1.13.3.orig/shell/hush.c busybox-1.13.3/shell/hush.c
|
---|
| 406 | --- busybox-1.13.3.orig/shell/hush.c 2009-02-26 03:46:55.000000000 -0800
|
---|
| 407 | +++ busybox-1.13.3/shell/hush.c 2009-03-28 08:25:12.522843973 -0700
|
---|
| 408 | @@ -458,8 +458,11 @@
|
---|
| 409 | smallint fake_mode;
|
---|
| 410 | /* these three support $?, $#, and $1 */
|
---|
| 411 | smalluint last_return_code;
|
---|
| 412 | - char **global_argv;
|
---|
| 413 | + /* is global_argv and global_argv[1..n] malloced? (note: not [0]) */
|
---|
| 414 | + smalluint global_args_malloced;
|
---|
| 415 | + /* how many non-NULL argv's we have. NB: $# + 1 */
|
---|
| 416 | int global_argc;
|
---|
| 417 | + char **global_argv;
|
---|
| 418 | #if ENABLE_HUSH_LOOPS
|
---|
| 419 | unsigned depth_break_continue;
|
---|
| 420 | unsigned depth_of_loop;
|
---|
| 421 | @@ -633,7 +636,7 @@
|
---|
| 422 | return dst;
|
---|
| 423 | }
|
---|
| 424 |
|
---|
| 425 | -static char **add_strings_to_strings(char **strings, char **add)
|
---|
| 426 | +static char **add_strings_to_strings(char **strings, char **add, int need_to_dup)
|
---|
| 427 | {
|
---|
| 428 | int i;
|
---|
| 429 | unsigned count1;
|
---|
| 430 | @@ -658,7 +661,7 @@
|
---|
| 431 | v[count1 + count2] = NULL;
|
---|
| 432 | i = count2;
|
---|
| 433 | while (--i >= 0)
|
---|
| 434 | - v[count1 + i] = add[i];
|
---|
| 435 | + v[count1 + i] = (need_to_dup ? xstrdup(add[i]) : add[i]);
|
---|
| 436 | return v;
|
---|
| 437 | }
|
---|
| 438 |
|
---|
| 439 | @@ -667,7 +670,7 @@
|
---|
| 440 | char *v[2];
|
---|
| 441 | v[0] = add;
|
---|
| 442 | v[1] = NULL;
|
---|
| 443 | - return add_strings_to_strings(strings, v);
|
---|
| 444 | + return add_strings_to_strings(strings, v, /*dup:*/ 0);
|
---|
| 445 | }
|
---|
| 446 |
|
---|
| 447 | static void putenv_all(char **strings)
|
---|
| 448 | @@ -1213,8 +1216,13 @@
|
---|
| 449 | * Otherwise, just finish current list[] and start new */
|
---|
| 450 | static int o_save_ptr(o_string *o, int n)
|
---|
| 451 | {
|
---|
| 452 | - if (o->o_glob)
|
---|
| 453 | - return o_glob(o, n); /* o_save_ptr_helper is inside */
|
---|
| 454 | + if (o->o_glob) { /* if globbing is requested */
|
---|
| 455 | + /* If o->has_empty_slot, list[n] was already globbed
|
---|
| 456 | + * (if it was requested back then when it was filled)
|
---|
| 457 | + * so don't do that again! */
|
---|
| 458 | + if (!o->has_empty_slot)
|
---|
| 459 | + return o_glob(o, n); /* o_save_ptr_helper is inside */
|
---|
| 460 | + }
|
---|
| 461 | return o_save_ptr_helper(o, n);
|
---|
| 462 | }
|
---|
| 463 |
|
---|
| 464 | @@ -4279,6 +4287,11 @@
|
---|
| 465 | switch (opt) {
|
---|
| 466 | case 'c':
|
---|
| 467 | G.global_argv = argv + optind;
|
---|
| 468 | + if (!argv[optind]) {
|
---|
| 469 | + /* -c 'script' (no params): prevent empty $0 */
|
---|
| 470 | + *--G.global_argv = argv[0];
|
---|
| 471 | + optind--;
|
---|
| 472 | + } /* else -c 'script' PAR0 PAR1: $0 is PAR0 */
|
---|
| 473 | G.global_argc = argc - optind;
|
---|
| 474 | opt = parse_and_run_string(optarg, 0 /* parse_flag */);
|
---|
| 475 | goto final_return;
|
---|
| 476 | @@ -4639,17 +4652,68 @@
|
---|
| 477 | return set_local_var(string, 0);
|
---|
| 478 | }
|
---|
| 479 |
|
---|
| 480 | -/* built-in 'set [VAR=value]' handler */
|
---|
| 481 | +/* built-in 'set' handler
|
---|
| 482 | + * SUSv3 says:
|
---|
| 483 | + * set [-abCefmnuvx] [-h] [-o option] [argument...]
|
---|
| 484 | + * set [+abCefmnuvx] [+h] [+o option] [argument...]
|
---|
| 485 | + * set -- [argument...]
|
---|
| 486 | + * set -o
|
---|
| 487 | + * set +o
|
---|
| 488 | + * Implementations shall support the options in both their hyphen and
|
---|
| 489 | + * plus-sign forms. These options can also be specified as options to sh.
|
---|
| 490 | + * Examples:
|
---|
| 491 | + * Write out all variables and their values: set
|
---|
| 492 | + * Set $1, $2, and $3 and set "$#" to 3: set c a b
|
---|
| 493 | + * Turn on the -x and -v options: set -xv
|
---|
| 494 | + * Unset all positional parameters: set --
|
---|
| 495 | + * Set $1 to the value of x, even if it begins with '-' or '+': set -- "$x"
|
---|
| 496 | + * Set the positional parameters to the expansion of x, even if x expands
|
---|
| 497 | + * with a leading '-' or '+': set -- $x
|
---|
| 498 | + *
|
---|
| 499 | + * So far, we only support "set -- [argument...]" by ignoring all options
|
---|
| 500 | + * (also, "-o option" will be mishandled by taking "option" as parameter #1).
|
---|
| 501 | + */
|
---|
| 502 | static int builtin_set(char **argv)
|
---|
| 503 | {
|
---|
| 504 | - char *temp = argv[1];
|
---|
| 505 | struct variable *e;
|
---|
| 506 | + char **pp;
|
---|
| 507 | + char *arg = *++argv;
|
---|
| 508 |
|
---|
| 509 | - if (temp == NULL)
|
---|
| 510 | + if (arg == NULL) {
|
---|
| 511 | for (e = G.top_var; e; e = e->next)
|
---|
| 512 | puts(e->varstr);
|
---|
| 513 | - else
|
---|
| 514 | - set_local_var(xstrdup(temp), 0);
|
---|
| 515 | + } else {
|
---|
| 516 | + /* NB: G.global_argv[0] ($0) is never freed/changed */
|
---|
| 517 | +
|
---|
| 518 | + if (G.global_args_malloced) {
|
---|
| 519 | + pp = G.global_argv;
|
---|
| 520 | + while (*++pp)
|
---|
| 521 | + free(*pp);
|
---|
| 522 | + G.global_argv[1] = NULL;
|
---|
| 523 | + } else {
|
---|
| 524 | + G.global_args_malloced = 1;
|
---|
| 525 | + pp = xzalloc(sizeof(pp[0]) * 2);
|
---|
| 526 | + pp[0] = G.global_argv[0]; /* retain $0 */
|
---|
| 527 | + G.global_argv = pp;
|
---|
| 528 | + }
|
---|
| 529 | + do {
|
---|
| 530 | + if (arg[0] == '+')
|
---|
| 531 | + continue;
|
---|
| 532 | + if (arg[0] != '-')
|
---|
| 533 | + break;
|
---|
| 534 | + if (arg[1] == '-' && arg[2] == '\0') {
|
---|
| 535 | + argv++;
|
---|
| 536 | + break;
|
---|
| 537 | + }
|
---|
| 538 | + } while ((arg = *++argv) != NULL);
|
---|
| 539 | + /* Now argv[0] is 1st argument */
|
---|
| 540 | +
|
---|
| 541 | + /* This realloc's G.global_argv */
|
---|
| 542 | + G.global_argv = pp = add_strings_to_strings(G.global_argv, argv, /*dup:*/ 1);
|
---|
| 543 | + G.global_argc = 1;
|
---|
| 544 | + while (*++pp)
|
---|
| 545 | + G.global_argc++;
|
---|
| 546 | + }
|
---|
| 547 |
|
---|
| 548 | return EXIT_SUCCESS;
|
---|
| 549 | }
|
---|
| 550 | @@ -4661,9 +4725,14 @@
|
---|
| 551 | n = atoi(argv[1]);
|
---|
| 552 | }
|
---|
| 553 | if (n >= 0 && n < G.global_argc) {
|
---|
| 554 | - G.global_argv[n] = G.global_argv[0];
|
---|
| 555 | + if (G.global_args_malloced) {
|
---|
| 556 | + int m = 1;
|
---|
| 557 | + while (m <= n)
|
---|
| 558 | + free(G.global_argv[m++]);
|
---|
| 559 | + }
|
---|
| 560 | G.global_argc -= n;
|
---|
| 561 | - G.global_argv += n;
|
---|
| 562 | + memmove(&G.global_argv[1], &G.global_argv[n+1],
|
---|
| 563 | + G.global_argc * sizeof(G.global_argv[0]));
|
---|
| 564 | return EXIT_SUCCESS;
|
---|
| 565 | }
|
---|
| 566 | return EXIT_FAILURE;
|
---|
| 567 | diff -Naur busybox-1.13.3.orig/shell/hush_test/hush-parsing/starquoted2.right busybox-1.13.3/shell/hush_test/hush-parsing/starquoted2.right
|
---|
| 568 | --- busybox-1.13.3.orig/shell/hush_test/hush-parsing/starquoted2.right 2009-02-26 03:46:52.000000000 -0800
|
---|
| 569 | +++ busybox-1.13.3/shell/hush_test/hush-parsing/starquoted2.right 2009-03-28 08:25:12.526845928 -0700
|
---|
| 570 | @@ -1,2 +1,3 @@
|
---|
| 571 | Should be printed
|
---|
| 572 | Should be printed
|
---|
| 573 | +Empty:
|
---|
| 574 | diff -Naur busybox-1.13.3.orig/shell/hush_test/hush-parsing/starquoted2.tests busybox-1.13.3/shell/hush_test/hush-parsing/starquoted2.tests
|
---|
| 575 | --- busybox-1.13.3.orig/shell/hush_test/hush-parsing/starquoted2.tests 2009-02-26 03:46:52.000000000 -0800
|
---|
| 576 | +++ busybox-1.13.3/shell/hush_test/hush-parsing/starquoted2.tests 2009-03-28 08:25:12.526845928 -0700
|
---|
| 577 | @@ -12,3 +12,6 @@
|
---|
| 578 | for a in """$@"; do echo Should not be printed; done
|
---|
| 579 | for a in """$@"''"$@"''; do echo Should not be printed; done
|
---|
| 580 | for a in ""; do echo Should be printed; done
|
---|
| 581 | +
|
---|
| 582 | +# Bug 207: "$@" expands to nothing, and we erroneously glob "%s\\n" twice:
|
---|
| 583 | +printf "Empty:%s\\n" "$@"
|
---|