Revision: 5568 Author: pebender Date: Mon Sep 28 16:52:59 2009 Log: - Updated busybox fixes.
http://code.google.com/p/minimyth/source/detail?r=5568 Added: /trunk/gar-minimyth/script/utils/busybox/files/busybox-1.15.1-lineedit.patch Modified: /trunk/gar-minimyth/script/utils/busybox/Makefile /trunk/gar-minimyth/script/utils/busybox/checksums /trunk/gar-minimyth/script/utils/busybox/files/busybox-1.15.1-ash.patch /trunk/gar-minimyth/script/utils/busybox/files/busybox-1.15.1-hush.patch ======================================= --- /dev/null +++ /trunk/gar-minimyth/script/utils/busybox/files/busybox-1.15.1-lineedit.patch Mon Sep 28 16:52:59 2009 @@ -0,0 +1,156 @@ +diff -urpN busybox-1.15.1/libbb/lineedit.c busybox-1.15.1-lineedit/libbb/lineedit.c +--- busybox-1.15.1/libbb/lineedit.c 2009-09-12 17:55:58.000000000 +0200 ++++ busybox-1.15.1-lineedit/libbb/lineedit.c 2009-09-28 23:56:03.000000000 +0200 +@@ -114,8 +114,8 @@ struct lineedit_statics { + unsigned cmdedit_prmt_len; /* length of prompt (without colors etc) */ + + unsigned cursor; +- unsigned command_len; +- /* *int* maxsize: we want x in "if (x > S.maxsize)" ++ int command_len; /* must be signed (^D returns -1 len) */ ++ /* signed maxsize: we want x in "if (x > S.maxsize)" + * to _not_ be promoted to unsigned */ + int maxsize; + CHAR_T *command_ps; +@@ -1095,15 +1095,15 @@ static void save_command_ps_at_cur_histo + int cur = state->cur_history; + free(state->history[cur]); + +-#if ENABLE_FEATURE_ASSUME_UNICODE ++# if ENABLE_FEATURE_ASSUME_UNICODE + { + char tbuf[MAX_LINELEN]; + save_string(tbuf, sizeof(tbuf)); + state->history[cur] = xstrdup(tbuf); + } +-#else ++# else + state->history[cur] = xstrdup(command_ps); +-#endif ++# endif + } + } + +@@ -1131,7 +1131,7 @@ static int get_next_history(void) + return 0; + } + +-#if ENABLE_FEATURE_EDITING_SAVEHISTORY ++# if ENABLE_FEATURE_EDITING_SAVEHISTORY + /* We try to ensure that concurrent additions to the history + * do not overwrite each other. + * Otherwise shell users get unhappy. +@@ -1256,10 +1256,10 @@ static void save_history(char *str) + free_line_input_t(st_temp); + } + } +-#else +-#define load_history(a) ((void)0) +-#define save_history(a) ((void)0) +-#endif /* FEATURE_COMMAND_SAVEHISTORY */ ++# else ++# define load_history(a) ((void)0) ++# define save_history(a) ((void)0) ++# endif /* FEATURE_COMMAND_SAVEHISTORY */ + + static void remember_in_history(char *str) + { +@@ -1290,15 +1290,15 @@ static void remember_in_history(char *st + /* i <= MAX_HISTORY */ + state->cur_history = i; + state->cnt_history = i; +-#if ENABLE_FEATURE_EDITING_SAVEHISTORY ++# if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY + if ((state->flags & SAVE_HISTORY) && state->hist_file) + save_history(str); +-#endif ++# endif + IF_FEATURE_EDITING_FANCY_PROMPT(num_ok_lines++;) + } + + #else /* MAX_HISTORY == 0 */ +-#define remember_in_history(a) ((void)0) ++# define remember_in_history(a) ((void)0) + #endif /* MAX_HISTORY */ + + +@@ -1476,11 +1476,11 @@ static void parse_and_put_prompt(const c + c = *prmt_ptr++; + + switch (c) { +-#if ENABLE_FEATURE_GETUSERNAME_AND_HOMEDIR ++# if ENABLE_FEATURE_GETUSERNAME_AND_HOMEDIR + case 'u': + pbuf = user_buf ? user_buf : (char*)""; + break; +-#endif ++# endif + case 'h': + pbuf = free_me = safe_gethostname(); + *strchrnul(pbuf, '.') = '\0'; +@@ -1488,7 +1488,7 @@ static void parse_and_put_prompt(const c + case '$': + c = (geteuid() == 0 ? '#' : '$'); + break; +-#if ENABLE_FEATURE_GETUSERNAME_AND_HOMEDIR ++# if ENABLE_FEATURE_GETUSERNAME_AND_HOMEDIR + case 'w': + /* /home/user[/something] -> ~[/something] */ + pbuf = cwd_buf; +@@ -1501,7 +1501,7 @@ static void parse_and_put_prompt(const c + pbuf = free_me = xasprintf("~%s", cwd_buf + l); + } + break; +-#endif ++# endif + case 'W': + pbuf = cwd_buf; + cp = strrchr(pbuf, '/'); +@@ -1688,13 +1688,15 @@ int FAST_FUNC read_line_input(const char + + /* With null flags, no other fields are ever used */ + state = st ? st : (line_input_t*) &const_int_0; +-#if ENABLE_FEATURE_EDITING_SAVEHISTORY ++#if MAX_HISTORY > 0 ++# if ENABLE_FEATURE_EDITING_SAVEHISTORY + if ((state->flags & SAVE_HISTORY) && state->hist_file) + if (state->cnt_history == 0) + load_history(state); +-#endif ++# endif + if (state->flags & DO_HISTORY) + state->cur_history = state->cnt_history; ++#endif + + /* prepare before init handlers */ + cmdedit_y = 0; /* quasireal y, not true if line > xt*yt */ +@@ -1716,7 +1718,7 @@ int FAST_FUNC read_line_input(const char + new_settings.c_cc[VTIME] = 0; + /* Turn off CTRL-C, so we can trap it */ + #ifndef _POSIX_VDISABLE +-#define _POSIX_VDISABLE '\0' ++# define _POSIX_VDISABLE '\0' + #endif + new_settings.c_cc[VINTR] = _POSIX_VDISABLE; + tcsetattr_stdin_TCSANOW(&new_settings); +@@ -2037,7 +2039,8 @@ int FAST_FUNC read_line_input(const char + rewrite_line: + /* Rewrite the line with the selected history item */ + /* change command */ +- command_len = load_string(state->history[state->cur_history] ? : "", maxsize); ++ command_len = load_string(state->history[state->cur_history] ? ++ state->history[state->cur_history] : "", maxsize); + /* redraw and go to eol (bol, in vi) */ + redraw(cmdedit_y, (state->flags & VI_MODE) ? 9999 : 0); + break; +@@ -2121,7 +2124,9 @@ int FAST_FUNC read_line_input(const char + #undef command + + #if ENABLE_FEATURE_ASSUME_UNICODE +- command_len = save_string(command, maxsize - 1); ++ command[0] = '\0'; ++ if (command_len > 0) ++ command_len = save_string(command, maxsize - 1); + free(command_ps); + #endif + ======================================= --- /trunk/gar-minimyth/script/utils/busybox/Makefile Wed Sep 23 17:40:21 2009 +++ /trunk/gar-minimyth/script/utils/busybox/Makefile Mon Sep 28 16:52:59 2009 @@ -2,6 +2,7 @@ GARVERSION = 1.15.1 CATEGORIES = utils MASTER_SITES = http://www.busybox.net/downloads/ +MASTER_SITES += http://www.busybox.net/downloads/fixes-1.15.1/ CONFIGFILE = $(DISTNAME).config DISTFILES = $(DISTNAME).tar.bz2 $(CONFIGFILE) PATCHFILES = \ @@ -9,6 +10,7 @@ $(DISTNAME)-buildsys.patch \ $(DISTNAME)-dd.patch \ $(DISTNAME)-hush.patch \ + $(DISTNAME)-lineedit.patch \ $(DISTNAME)-pidof_killall.patch \ $(DISTNAME)-sed.patch \ $(DISTNAME)-uniq.patch ======================================= --- /trunk/gar-minimyth/script/utils/busybox/checksums Wed Sep 23 17:40:21 2009 +++ /trunk/gar-minimyth/script/utils/busybox/checksums Mon Sep 28 16:52:59 2009 @@ -1,8 +1,9 @@ e67a98eef14212abfc265092e4683fbe download/busybox-1.15.1.tar.bz2 -72b570f49f21859d13c4afa7de719c6d download/busybox-1.15.1-ash.patch +4afc82f3a8ea0e68e22911798778bb31 download/busybox-1.15.1-ash.patch d08eef47dd53564af4c5c14a5c7cd85f download/busybox-1.15.1-buildsys.patch 51cc3dac2c8acacc767299e1f82cf189 download/busybox-1.15.1-dd.patch -9b6c6f6cac5cf4d85bf4c5c5cc627ed3 download/busybox-1.15.1-hush.patch +e8ddf6b30885021b33f1dbc570ac66bd download/busybox-1.15.1-hush.patch +b942f099aeae745805e06b2af27ea0c9 download/busybox-1.15.1-lineedit.patch 511acd6a114f78033bcab287a77d7339 download/busybox-1.15.1-pidof_killall.patch 47e0ce028132350407d8926a174bea30 download/busybox-1.15.1-sed.patch e6519fb93deb5bb427140f59a83d6ab8 download/busybox-1.15.1-uniq.patch ======================================= --- /trunk/gar-minimyth/script/utils/busybox/files/busybox-1.15.1-ash.patch Wed Sep 23 17:40:21 2009 +++ /trunk/gar-minimyth/script/utils/busybox/files/busybox-1.15.1-ash.patch Mon Sep 28 16:52:59 2009 @@ -1,11 +1,406 @@ diff -urpN busybox-1.15.1/shell/ash.c busybox-1.15.1-ash/shell/ash.c --- busybox-1.15.1/shell/ash.c 2009-09-12 17:56:11.000000000 +0200 -+++ busybox-1.15.1-ash/shell/ash.c 2009-09-23 03:27:09.000000000 +0200 -@@ -4560,7 +4560,52 @@ forkchild(struct job *jp, union node *n, ++++ busybox-1.15.1-ash/shell/ash.c 2009-09-27 02:46:54.000000000 +0200 +@@ -112,7 +112,7 @@ enum { NOPTS = ARRAY_SIZE(optletters_opt + + static const char homestr[] ALIGN1 = "HOME"; + static const char snlfmt[] ALIGN1 = "%s\n"; +-static const char illnum[] ALIGN1 = "Illegal number: %s"; ++static const char msg_illnum[] ALIGN1 = "Illegal number: %s"; + + /* + * We enclose jmp_buf in a structure so that we can declare pointers to +@@ -142,17 +142,10 @@ struct globals_misc { + + struct jmploc *exception_handler; + +-// disabled by vda: cannot understand how it was supposed to work - +-// cannot fix bugs. That's why you have to explain your non-trivial designs! +-// /* do we generate EXSIG events */ +-// int exsig; /* counter */ +- volatile int suppressint; /* counter */ +-// TODO: rename +-// pendingsig -> pending_sig +-// intpending -> pending_int +- volatile /*sig_atomic_t*/ smallint intpending; /* 1 = got SIGINT */ ++ volatile int suppress_int; /* counter */ ++ volatile /*sig_atomic_t*/ smallint pending_int; /* 1 = got SIGINT */ + /* last pending signal */ +- volatile /*sig_atomic_t*/ smallint pendingsig; ++ volatile /*sig_atomic_t*/ smallint pending_sig; + smallint exception_type; /* kind of exception (0..5) */ + /* exceptions */ + #define EXINT 0 /* SIGINT received */ +@@ -200,6 +193,7 @@ struct globals_misc { + /* indicates specified signal received */ + uint8_t gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */ + char *trap[NSIG]; ++ char **trap_ptr; /* used only by "trap hack" */ + + /* Rarely referenced stuff */ + #if ENABLE_ASH_RANDOM_SUPPORT +@@ -220,16 +214,16 @@ extern struct globals_misc *const ash_pt + #define arg0 (G_misc.arg0 ) + #define exception_handler (G_misc.exception_handler) + #define exception_type (G_misc.exception_type ) +-#define suppressint (G_misc.suppressint ) +-#define intpending (G_misc.intpending ) +-//#define exsig (G_misc.exsig ) +-#define pendingsig (G_misc.pendingsig ) ++#define suppress_int (G_misc.suppress_int ) ++#define pending_int (G_misc.pending_int ) ++#define pending_sig (G_misc.pending_sig ) + #define isloginsh (G_misc.isloginsh ) + #define nullstr (G_misc.nullstr ) + #define optlist (G_misc.optlist ) + #define sigmode (G_misc.sigmode ) + #define gotsig (G_misc.gotsig ) + #define trap (G_misc.trap ) ++#define trap_ptr (G_misc.trap_ptr ) + #define random_galois_LFSR (G_misc.random_galois_LFSR) + #define random_LCG (G_misc.random_LCG ) + #define backgndpid (G_misc.backgndpid ) +@@ -239,6 +233,7 @@ extern struct globals_misc *const ash_pt + barrier(); \ + curdir = nullstr; \ + physdir = nullstr; \ ++ trap_ptr = trap; \ + } while (0) + + +@@ -283,7 +278,7 @@ static int isdigit_str9(const char *str) + * more fun than worrying about efficiency and portability. :-)) + */ + #define INT_OFF do { \ +- suppressint++; \ ++ suppress_int++; \ + xbarrier(); \ + } while (0) + +@@ -324,11 +319,11 @@ raise_interrupt(void) + { + int ex_type; + +- intpending = 0; ++ pending_int = 0; + /* Signal is not automatically unmasked after it is raised, + * do it ourself - unmask all signals */ + sigprocmask_allsigs(SIG_UNBLOCK); +- /* pendingsig = 0; - now done in onsig() */ ++ /* pending_sig = 0; - now done in onsig() */ + + ex_type = EXSIG; + if (gotsig[SIGINT - 1] && !trap[SIGINT]) { +@@ -353,7 +348,7 @@ static IF_ASH_OPTIMIZE_FOR_SIZE(inline) + int_on(void) + { + xbarrier(); +- if (--suppressint == 0 && intpending) { ++ if (--suppress_int == 0 && pending_int) { + raise_interrupt(); + } + } +@@ -362,18 +357,18 @@ static IF_ASH_OPTIMIZE_FOR_SIZE(inline) + force_int_on(void) + { + xbarrier(); +- suppressint = 0; +- if (intpending) ++ suppress_int = 0; ++ if (pending_int) + raise_interrupt(); + } + #define FORCE_INT_ON force_int_on() + +-#define SAVE_INT(v) ((v) = suppressint) ++#define SAVE_INT(v) ((v) = suppress_int) + + #define RESTORE_INT(v) do { \ + xbarrier(); \ +- suppressint = (v); \ +- if (suppressint == 0 && intpending) \ ++ suppress_int = (v); \ ++ if (suppress_int == 0 && pending_int) \ + raise_interrupt(); \ + } while (0) + +@@ -461,15 +456,15 @@ out2str(const char *p) + /* ============ Parser structures */ + + /* control characters in argument strings */ +-#define CTLESC '\201' /* escape next character */ +-#define CTLVAR '\202' /* variable defn */ +-#define CTLENDVAR '\203' +-#define CTLBACKQ '\204' ++#define CTLESC ((unsigned char)'\201') /* escape next character */ ++#define CTLVAR ((unsigned char)'\202') /* variable defn */ ++#define CTLENDVAR ((unsigned char)'\203') ++#define CTLBACKQ ((unsigned char)'\204') + #define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */ + /* CTLBACKQ | CTLQUOTE == '\205' */ +-#define CTLARI '\206' /* arithmetic expression */ +-#define CTLENDARI '\207' +-#define CTLQUOTEMARK '\210' ++#define CTLARI ((unsigned char)'\206') /* arithmetic expression */ ++#define CTLENDARI ((unsigned char)'\207') ++#define CTLQUOTEMARK ((unsigned char)'\210') + + /* variable substitution byte (follows CTLVAR) */ + #define VSTYPE 0x0f /* type of variable substitution */ +@@ -685,7 +680,7 @@ trace_printf(const char *fmt, ...) + if (DEBUG_PID) + fprintf(tracefile, "[%u] ", (int) getpid()); + if (DEBUG_SIG) +- fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pendingsig, intpending, suppressint); ++ fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pending_sig, pending_int, suppress_int); + va_start(va, fmt); + vfprintf(tracefile, fmt, va); + va_end(va); +@@ -701,7 +696,7 @@ trace_vprintf(const char *fmt, va_list v + if (DEBUG_PID) + fprintf(tracefile, "[%u] ", (int) getpid()); + if (DEBUG_SIG) +- fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pendingsig, intpending, suppressint); ++ fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pending_sig, pending_int, suppress_int); + vfprintf(tracefile, fmt, va); + } + +@@ -1556,7 +1551,7 @@ static int + number(const char *s) + { + if (!is_number(s)) +- ash_msg_and_raise_error(illnum, s); ++ ash_msg_and_raise_error(msg_illnum, s); + return atoi(s); + } + +@@ -2351,8 +2346,6 @@ setprompt(int whichprompt) + #define CD_PHYSICAL 1 + #define CD_PRINT 2 + +-static int docd(const char *, int); +- + static int + cdopt(void) + { +@@ -2360,7 +2353,7 @@ cdopt(void) + int i, j; + + j = 'L'; +- while ((i = nextopt("LP"))) { ++ while ((i = nextopt("LP")) != '\0') { + if (i != j) { + flags ^= CD_PHYSICAL; + j = i; +@@ -2710,8 +2703,8 @@ SIT(int c, int syntax) + } else + #endif + { +- if ((unsigned char)c >= (unsigned char)(CTLESC) +- && (unsigned char)c <= (unsigned char)(CTLQUOTEMARK) ++ if ((unsigned char)c >= CTLESC ++ && (unsigned char)c <= CTLQUOTEMARK + ) { + return CCTL; + } +@@ -3240,9 +3233,9 @@ unaliascmd(int argc UNUSED_PARAM, char * + #define FORK_NOJOB 2 + + /* mode flags for showjob(s) */ +-#define SHOW_PGID 0x01 /* only show pgid - for jobs -p */ +-#define SHOW_PID 0x04 /* include process pid */ +-#define SHOW_CHANGED 0x08 /* only jobs whose state has changed */ ++#define SHOW_ONLY_PGID 0x01 /* show only pgid (jobs -p) */ ++#define SHOW_PIDS 0x02 /* show individual pids, not just one line per job */ ++#define SHOW_CHANGED 0x04 /* only jobs whose state has changed */ + + /* + * A job structure contains information about a job. A job is either a +@@ -3250,7 +3243,6 @@ unaliascmd(int argc UNUSED_PARAM, char * + * latter case, pidlist will be non-NULL, and will point to a -1 terminated + * array of pids. + */ +- + struct procstat { + pid_t pid; /* process id */ + int status; /* last process status from wait() */ +@@ -3316,14 +3308,14 @@ onsig(int signo) + { + gotsig[signo - 1] = 1; + +- if (/* exsig || */ (signo == SIGINT && !trap[SIGINT])) { +- if (!suppressint) { +- pendingsig = 0; ++ if (signo == SIGINT && !trap[SIGINT]) { ++ if (!suppress_int) { ++ pending_sig = 0; + raise_interrupt(); /* does not return */ + } +- intpending = 1; ++ pending_int = 1; + } else { +- pendingsig = signo; ++ pending_sig = signo; + } + } + +@@ -3546,7 +3538,6 @@ getjob(const char *name, int getctl) + } + + if (is_number(p)) { +-// TODO: number() instead? It does error checking... + num = atoi(p); + if (num < njobs) { + jp = jobtab + num - 1; +@@ -3918,7 +3909,7 @@ static int + blocking_wait_with_raise_on_sig(struct job *job) + { + pid_t pid = dowait(DOWAIT_BLOCK, job); +- if (pid <= 0 && pendingsig) ++ if (pid <= 0 && pending_sig) + raise_exception(EXSIG); + return pid; + } +@@ -3935,7 +3926,7 @@ showjob(FILE *out, struct job *jp, int m + + ps = jp->ps; + +- if (mode & SHOW_PGID) { ++ if (mode & SHOW_ONLY_PGID) { /* jobs -p */ + /* just output process (group) id of pipeline */ + fprintf(out, "%d\n", ps->pid); + return; +@@ -3945,11 +3936,11 @@ showjob(FILE *out, struct job *jp, int m + indent_col = col; + + if (jp == curjob) +- s[col - 2] = '+'; ++ s[col - 3] = '+'; + else if (curjob && jp == curjob->prev_job) +- s[col - 2] = '-'; ++ s[col - 3] = '-'; + +- if (mode & SHOW_PID) ++ if (mode & SHOW_PIDS) + col += fmtstr(s + col, 16, "%d ", ps->pid); + + psend = ps + jp->nprocs; +@@ -3963,25 +3954,32 @@ showjob(FILE *out, struct job *jp, int m + status = jp->stopstatus; + col += sprint_status(s + col, status, 0); + } ++ /* By now, "[JOBID]* [maybe PID] STATUS" is printed */ + ++ /* This loop either prints "<cmd1> | <cmd2> | <cmd3>" line ++ * or prints several "PID | <cmdN>" lines, ++ * depending on SHOW_PIDS bit. ++ * We do not print status of individual processes ++ * between PID and <cmdN>. bash does it, but not very well: ++ * first line shows overall job status, not process status, ++ * making it impossible to know 1st process status. ++ */ + goto start; +- +- do { ++ while (1) { + /* for each process */ +- col = fmtstr(s, 48, " |\n%*c%d ", indent_col, ' ', ps->pid) - 3; ++ s[0] = '\0'; ++ col = 33; ++ if (mode & SHOW_PIDS) ++ col = fmtstr(s, 48, "\n%*c%d ", indent_col, ' ', ps->pid) - 1; + start: +- fprintf(out, "%s%*c%s", +- s, 33 - col >= 0 ? 33 - col : 0, ' ', ps->cmd +- ); +- if (!(mode & SHOW_PID)) { +- showpipe(jp, out); +- break; +- } +- if (++ps == psend) { +- outcslow('\n', out); ++ fprintf(out, "%s%*c", s, 33 - col >= 0 ? 33 - col : 0, ' '); ++ if (ps != jp->ps) ++ fprintf(out, "| "); ++ fprintf(out, "%s", ps->cmd); ++ if (++ps == psend) + break; +- } +- } while (1); ++ } ++ outcslow('\n', out); + + jp->changed = 0; + +@@ -4019,17 +4017,17 @@ jobscmd(int argc UNUSED_PARAM, char **ar + int mode, m; + + mode = 0; +- while ((m = nextopt("lp"))) { ++ while ((m = nextopt("lp")) != '\0') { + if (m == 'l') +- mode = SHOW_PID; ++ mode |= SHOW_PIDS; + else +- mode = SHOW_PGID; ++ mode |= SHOW_ONLY_PGID; + } + + argv = argptr; + if (*argv) { + do +- showjob(stdout, getjob(*argv,0), mode); ++ showjob(stdout, getjob(*argv, 0), mode); + while (*++argv); + } else + showjobs(stdout, mode); +@@ -4073,9 +4071,7 @@ waitcmd(int argc UNUSED_PARAM, char **ar + int retval; + struct job *jp; + +-// exsig++; +-// xbarrier(); +- if (pendingsig) ++ if (pending_sig) + raise_exception(EXSIG); + + nextopt(nullstr); +@@ -4311,7 +4307,7 @@ cmdputs(const char *s) + if (!str) + continue; + dostr: +- while ((c = *str++)) { ++ while ((c = *str++) != '\0') { + USTPUTC(c, nextc); + } + } +@@ -4530,9 +4526,11 @@ clear_traps(void) + for (tp = trap; tp < &trap[NSIG]; tp++) { + if (*tp && **tp) { /* trap not NULL or "" (SIG_IGN) */ + INT_OFF; +- free(*tp); ++ if (trap_ptr == trap) ++ free(*tp); ++ /* else: it "belongs" to trap_ptr vector, don't free */ + *tp = NULL; +- if (tp != &trap[0]) ++ if ((tp - trap) != 0) + setsignal(tp - trap); + INT_ON; + } +@@ -4546,7 +4544,7 @@ static void closescript(void); + #if !JOBS + # define forkchild(jp, n, mode) forkchild(jp, mode) + #endif +-static void ++static NOINLINE void + forkchild(struct job *jp, union node *n, int mode) + { + int oldlvl; +@@ -4560,6 +4558,53 @@ forkchild(struct job *jp, union node *n, * Do we do it correctly? */ closescript(); -- clear_traps(); + + if (mode == FORK_NOJOB /* is it `xxx` ? */ + && n && n->type == NCMD /* is it single cmd? */ @@ -49,12 +444,13 @@ + * + * Our solution: ONLY bare $(trap) or `trap` is special. + */ -+ } else { -+ clear_traps(); ++ /* Save trap handler strings for trap builtin to print */ ++ trap_ptr = memcpy(xmalloc(sizeof(trap)), trap, sizeof(trap)); ++ /* Fall through into clearing traps */ + } + clear_traps(); #if JOBS /* do job control only in root shell */ - doing_jobctl = 0; @@ -4604,8 +4649,14 @@ forkchild(struct job *jp, union node *n, setsignal(SIGQUIT); } @@ -71,16 +467,354 @@ freejob(curjob); return; } -@@ -5553,7 +5604,7 @@ exptilde(char *startp, char *p, int flag +@@ -4998,7 +5049,7 @@ struct redirtab { + struct redirtab *next; + int nullredirs; + int pair_count; +- struct two_fd_t two_fd[0]; ++ struct two_fd_t two_fd[]; + }; + #define redirlist (G_var.redirlist) + +@@ -5309,7 +5360,7 @@ ash_arith(const char *s) + #define EXP_WORD 0x80 /* expand word in parameter expansion */ + #define EXP_QWORD 0x100 /* expand word in quoted parameter expansion */ + /* +- * _rmescape() flags ++ * rmescape() flags + */ + #define RMESCAPE_ALLOC 0x1 /* Allocate a new string */ + #define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */ +@@ -5363,7 +5414,7 @@ esclen(const char *start, const char *p) + { + size_t esc = 0; + +- while (p > start && *--p == CTLESC) { ++ while (p > start && (unsigned char)*--p == CTLESC) { + esc++; + } + return esc; +@@ -5373,19 +5424,19 @@ esclen(const char *start, const char *p) + * Remove any CTLESC characters from a string. + */ + static char * +-_rmescapes(char *str, int flag) ++rmescapes(char *str, int flag) + { + static const char qchars[] ALIGN1 = { CTLESC, CTLQUOTEMARK, '\0' }; + + char *p, *q, *r; + unsigned inquotes; +- int notescaped; +- int globbing; ++ unsigned protect_against_glob; ++ unsigned globbing; + + p = strpbrk(str, qchars); +- if (!p) { ++ if (!p) + return str; +- } ++ + q = p; + r = str; + if (flag & RMESCAPE_ALLOC) { +@@ -5404,28 +5455,33 @@ _rmescapes(char *str, int flag) + q = (char *)memcpy(q, str, len) + len; + } + } ++ + inquotes = (flag & RMESCAPE_QUOTED) ^ RMESCAPE_QUOTED; + globbing = flag & RMESCAPE_GLOB; +- notescaped = globbing; ++ protect_against_glob = globbing; + while (*p) { + if (*p == CTLQUOTEMARK) { ++// TODO: if no RMESCAPE_QUOTED in flags, inquotes never becomes 0 ++// (alternates between RMESCAPE_QUOTED and ~RMESCAPE_QUOTED). Is it ok? ++// Note: both inquotes and protect_against_glob only affect whether ++// CTLESC,<ch> gets converted to <ch> or to \<ch> + inquotes = ~inquotes; + p++; +- notescaped = globbing; ++ protect_against_glob = globbing; + continue; + } + if (*p == '\\') { + /* naked back slash */ +- notescaped = 0; ++ protect_against_glob = 0; + goto copy; + } + if (*p == CTLESC) { + p++; +- if (notescaped && inquotes && *p != '/') { ++ if (protect_against_glob && inquotes && *p != '/') { + *q++ = '\\'; + } + } +- notescaped = globbing; ++ protect_against_glob = globbing; + copy: + *q++ = *p++; + } +@@ -5436,8 +5492,6 @@ _rmescapes(char *str, int flag) + } + return r; + } +-#define rmescapes(p) _rmescapes((p), 0) +- + #define pmatch(a, b) !fnmatch((a), (b), 0) + + /* +@@ -5452,7 +5506,7 @@ preglob(const char *pattern, int quoted, + if (quoted) { + flag |= RMESCAPE_QUOTED; + } +- return _rmescapes((char *)pattern, flag); ++ return rmescapes((char *)pattern, flag); + } + + /* +@@ -5463,14 +5517,17 @@ memtodest(const char *p, size_t len, int + { + char *q = expdest; + +- q = makestrspace(len * 2, q); ++ q = makestrspace(quotes ? len * 2 : len, q); + + while (len--) { + int c = signed_char2int(*p++); + if (!c) + continue; +- if (quotes && (SIT(c, syntax) == CCTL || SIT(c, syntax) == CBACK)) +- USTPUTC(CTLESC, q); ++ if (quotes) { ++ int n = SIT(c, syntax); ++ if (n == CCTL || n == CBACK) ++ USTPUTC(CTLESC, q); ++ } + USTPUTC(c, q); + } + +@@ -5547,13 +5604,13 @@ removerecordregions(int endoff) + } + + static char * +-exptilde(char *startp, char *p, int flag) ++exptilde(char *startp, char *p, int flags) + { + char c; char *name; struct passwd *pw; const char *home; - int quotes = flag & (EXP_FULL | EXP_CASE); -+ int quotes = flag & (EXP_FULL | EXP_CASE | EXP_REDIR); ++ int quotes = flags & (EXP_FULL | EXP_CASE | EXP_REDIR); int startloc; name = p + 1; -@@ -6321,7 +6372,7 @@ varvalue(char *name, int varflags, int f +@@ -5565,7 +5622,7 @@ exptilde(char *startp, char *p, int flag + case CTLQUOTEMARK: + return startp; + case ':': +- if (flag & EXP_VARTILDE) ++ if (flags & EXP_VARTILDE) + goto done; + break; + case '/': +@@ -5770,7 +5827,7 @@ expari(int quotes) + expdest = p; + + if (quotes) +- rmescapes(p + 2); ++ rmescapes(p + 2, 0); + + len = cvtnum(ash_arith(p + 2)); + +@@ -5780,7 +5837,7 @@ expari(int quotes) + #endif + + /* argstr needs it */ +-static char *evalvar(char *p, int flag, struct strlist *var_str_list); ++static char *evalvar(char *p, int flags, struct strlist *var_str_list); + + /* + * Perform variable and command substitution. If EXP_FULL is set, output CTLESC +@@ -5792,7 +5849,7 @@ static char *evalvar(char *p, int flag, + * for correct expansion of "B=$A" word. + */ + static void +-argstr(char *p, int flag, struct strlist *var_str_list) ++argstr(char *p, int flags, struct strlist *var_str_list) + { + static const char spclchars[] ALIGN1 = { + '=', +@@ -5810,42 +5867,44 @@ argstr(char *p, int flag, struct strlist + }; + const char *reject = spclchars; + int c; +- int quotes = flag & (EXP_FULL | EXP_CASE | EXP_REDIR); /* do CTLESC */ +- int breakall = flag & EXP_WORD; ++ int quotes = flags & (EXP_FULL | EXP_CASE | EXP_REDIR); /* do CTLESC */ ++ int breakall = flags & EXP_WORD; + int inquotes; + size_t length; + int startloc; + +- if (!(flag & EXP_VARTILDE)) { ++ if (!(flags & EXP_VARTILDE)) { + reject += 2; +- } else if (flag & EXP_VARTILDE2) { ++ } else if (flags & EXP_VARTILDE2) { + reject++; + } + inquotes = 0; + length = 0; +- if (flag & EXP_TILDE) { ++ if (flags & EXP_TILDE) { + char *q; + +- flag &= ~EXP_TILDE; ++ flags &= ~EXP_TILDE; + tilde: + q = p; +- if (*q == CTLESC && (flag & EXP_QWORD)) ++ if (*q == CTLESC && (flags & EXP_QWORD)) + q++; + if (*q == '~') +- p = exptilde(p, q, flag); ++ p = exptilde(p, q, flags); + } + start: + startloc = expdest - (char *)stackblock(); + for (;;) { + length += strcspn(p + length, reject); +- c = p[length]; +- if (c && (!(c & 0x80) ++ c = (unsigned char) p[length]; ++ if (c) { ++ if (!(c & 0x80) + #if ENABLE_SH_MATH_SUPPORT +- || c == CTLENDARI ++ || c == CTLENDARI + #endif +- )) { +- /* c == '=' || c == ':' || c == CTLENDARI */ +- length++; ++ ) { ++ /* c == '=' || c == ':' || c == CTLENDARI */ ++ length++; ++ } + } + if (length > 0) { + int newloc; +@@ -5863,11 +5922,11 @@ argstr(char *p, int flag, struct strlist + case '\0': + goto breakloop; + case '=': +- if (flag & EXP_VARTILDE2) { ++ if (flags & EXP_VARTILDE2) { + p--; + continue; + } +- flag |= EXP_VARTILDE2; ++ flags |= EXP_VARTILDE2; + reject++; + /* fall through */ + case ':': +@@ -5886,15 +5945,13 @@ argstr(char *p, int flag, struct strlist + goto breakloop; + case CTLQUOTEMARK: + /* "$@" syntax adherence hack */ +- if ( +- !inquotes && +- !memcmp(p, dolatstr, 4) && +- (p[4] == CTLQUOTEMARK || ( +- p[4] == CTLENDVAR && +- p[5] == CTLQUOTEMARK +- )) ++ if (!inquotes ++ && memcmp(p, dolatstr, 4) == 0 ++ && ( p[4] == CTLQUOTEMARK ++ || (p[4] == CTLENDVAR && p[5] == CTLQUOTEMARK) ++ ) + ) { +- p = evalvar(p + 1, flag, /* var_str_list: */ NULL) + 1; ++ p = evalvar(p + 1, flags, /* var_str_list: */ NULL) + 1; + goto start; + } + inquotes = !inquotes; +@@ -5910,10 +5967,10 @@ argstr(char *p, int flag, struct strlist + length++; + goto addquote; + case CTLVAR: +- p = evalvar(p, flag, var_str_list); ++ p = evalvar(p, flags, var_str_list); + goto start; + case CTLBACKQ: +- c = 0; ++ c = '\0'; + case CTLBACKQ|CTLQUOTE: + expbackq(argbackq->n, c, quotes); + argbackq = argbackq->next; +@@ -6119,15 +6176,15 @@ subevalvar(char *p, char *str, int strlo + #if ENABLE_ASH_BASH_COMPAT + case VSSUBSTR: + loc = str = stackblock() + strloc; +-// TODO: number() instead? It does error checking... +- pos = atoi(loc); ++ /* Read POS in ${var:POS:LEN} */ ++ pos = atoi(loc); /* number(loc) errors out on "1:4" */ + len = str - startp - 1; + + /* *loc != '\0', guaranteed by parser */ + if (quotes) { + char *ptr; + +- /* We must adjust the length by the number of escapes we find. */ ++ /* Adjust the length by the number of escapes */ + for (ptr = startp; ptr < (str - 1); ptr++) { + if (*ptr == CTLESC) { + len--; +@@ -6138,15 +6195,22 @@ subevalvar(char *p, char *str, int strlo + orig_len = len; + + if (*loc++ == ':') { +-// TODO: number() instead? It does error checking... +- len = atoi(loc); ++ /* ${var::LEN} */ ++ len = number(loc); + } else { ++ /* Skip POS in ${var:POS:LEN} */ + len = orig_len; +- while (*loc && *loc != ':') ++ while (*loc && *loc != ':') { ++ /* TODO? ++ * bash complains on: var=qwe; echo ${var:1a:123} ++ if (!isdigit(*loc)) ++ ash_msg_and_raise_error(msg_illnum, str); ++ */ + loc++; +- if (*loc++ == ':') +-// TODO: number() instead? It does error checking... +- len = atoi(loc); ++ } ++ if (*loc++ == ':') { ++ len = number(loc); ++ } + } + if (pos >= orig_len) { + pos = 0; +@@ -6190,7 +6254,7 @@ subevalvar(char *p, char *str, int strlo + rmesc = startp; + rmescend = (char *)stackblock() + strloc; + if (quotes) { +- rmesc = _rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW); ++ rmesc = rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW); + if (rmesc != startp) { + rmescend = expdest; + startp = (char *)stackblock() + startloc; +@@ -6321,7 +6385,7 @@ varvalue(char *name, int varflags, int f int syntax; int quoted = varflags & VSQUOTE; int subtype = varflags & VSTYPE; @@ -89,49 +823,321 @@ if (quoted && (flags & EXP_FULL)) sep = 1 << CHAR_BIT; -@@ -6558,6 +6609,7 @@ evalvar(char *p, int flag, struct strlis +@@ -6365,7 +6429,7 @@ varvalue(char *name, int varflags, int f + ap = shellparam.p; + if (!ap) + return -1; +- while ((p = *ap++)) { ++ while ((p = *ap++) != NULL) { + size_t partlen; + + partlen = strlen(p); +@@ -6399,8 +6463,7 @@ varvalue(char *name, int varflags, int f + case '7': + case '8': + case '9': +-// TODO: number() instead? It does error checking... +- num = atoi(name); ++ num = atoi(name); /* number(name) fails on ${N#str} etc */ + if (num < 0 || num > shellparam.nparam) + return -1; + p = num ? shellparam.p[num - 1] : arg0; +@@ -6452,7 +6515,7 @@ varvalue(char *name, int varflags, int f + * input string. + */ + static char * +-evalvar(char *p, int flag, struct strlist *var_str_list) ++evalvar(char *p, int flags, struct strlist *var_str_list) + { + char varflags; + char subtype; +@@ -6463,7 +6526,7 @@ evalvar(char *p, int flag, struct strlis + int startloc; + ssize_t varlen; + +- varflags = *p++; ++ varflags = (unsigned char) *p++; + subtype = varflags & VSTYPE; + quoted = varflags & VSQUOTE; + var = p; +@@ -6472,7 +6535,7 @@ evalvar(char *p, int flag, struct strlis + p = strchr(p, '=') + 1; + + again: +- varlen = varvalue(var, varflags, flag, var_str_list); ++ varlen = varvalue(var, varflags, flags, var_str_list); + if (varflags & VSNUL) + varlen--; + +@@ -6485,8 +6548,8 @@ evalvar(char *p, int flag, struct strlis + vsplus: + if (varlen < 0) { + argstr( +- p, flag | EXP_TILDE | +- (quoted ? EXP_QWORD : EXP_WORD), ++ p, flags | EXP_TILDE | ++ (quoted ? EXP_QWORD : EXP_WORD), + var_str_list + ); + goto end; +@@ -6558,7 +6621,8 @@ evalvar(char *p, int flag, struct strlis patloc = expdest - (char *)stackblock(); if (0 == subevalvar(p, /* str: */ NULL, patloc, subtype, startloc, varflags, +- /* quotes: */ flag & (EXP_FULL | EXP_CASE), +//TODO: | EXP_REDIR too? All other such places do it too - /* quotes: */ flag & (EXP_FULL | EXP_CASE), ++ /* quotes: */ flags & (EXP_FULL | EXP_CASE), var_str_list) ) { -@@ -12203,7 +12255,7 @@ trapcmd(int argc UNUSED_PARAM, char **ar + int amount = expdest - ( +@@ -6812,7 +6876,7 @@ expmeta(char *enddir, char *name) + p++; + if (*p == '.') + matchdot++; +- while (!intpending && (dp = readdir(dirp)) != NULL) { ++ while (!pending_int && (dp = readdir(dirp)) != NULL) { + if (dp->d_name[0] == '.' && !matchdot) + continue; + if (pmatch(start, dp->d_name)) { +@@ -6933,7 +6997,7 @@ expandmeta(struct strlist *str /*, int f + */ + nometa: + *exparg.lastp = str; +- rmescapes(str->text); ++ rmescapes(str->text, 0); + exparg.lastp = &str->next; + } else { + *exparg.lastp = NULL; +@@ -6981,7 +7045,7 @@ expandarg(union node *arg, struct arglis + expandmeta(exparg.list /*, flag*/); + } else { + if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */ +- rmescapes(p); ++ rmescapes(p, 0); + sp = stzalloc(sizeof(*sp)); + sp->text = p; + *exparg.lastp = sp; +@@ -7206,8 +7270,8 @@ shellexec(char **argv, const char *path, + break; + } + exitstatus = exerrno; +- TRACE(("shellexec failed for %s, errno %d, suppressint %d\n", +- argv[0], e, suppressint)); ++ TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n", ++ argv[0], e, suppress_int)); + ash_msg_and_raise(EXEXEC, "%s: %s", argv[0], errmsg(e, "not found")); + /* NOTREACHED */ + } +@@ -8009,7 +8073,7 @@ dotrap(void) + uint8_t savestatus; + + savestatus = exitstatus; +- pendingsig = 0; ++ pending_sig = 0; + xbarrier(); + + TRACE(("dotrap entered\n")); +@@ -8189,7 +8253,7 @@ evaltree(union node *n, int flags) + out1: + if (checkexit & exitstatus) + evalskip |= SKIPEVAL; +- else if (pendingsig && dotrap()) ++ else if (pending_sig && dotrap()) + goto exexit; + + if (flags & EV_EXIT) { +@@ -9109,7 +9173,7 @@ evalcommand(union node *cmd, int flags) + if (i == EXINT) + exit_status = 128 + SIGINT; + if (i == EXSIG) +- exit_status = 128 + pendingsig; ++ exit_status = 128 + pending_sig; + exitstatus = exit_status; + if (i == EXINT || spclbltin > 0) { + raise: +@@ -9163,7 +9227,6 @@ evalbltin(const struct builtincmd *cmd, + exitstatus |= ferror(stdout); + clearerr(stdout); + commandname = savecmdname; +-// exsig = 0; + exception_handler = savehandler; + + return i; +@@ -9214,7 +9277,7 @@ breakcmd(int argc UNUSED_PARAM, char **a + int n = argv[1] ? number(argv[1]) : 1; + + if (n <= 0) +- ash_msg_and_raise_error(illnum, argv[1]); ++ ash_msg_and_raise_error(msg_illnum, argv[1]); + if (n > loopnest) + n = loopnest; + if (n > 0) { +@@ -10022,7 +10085,7 @@ change_random(const char *value) + vrandom.flags &= ~VNOFUNC; + } else { + /* set/reset */ +- random_galois_LFSR = random_LCG = strtoul(value, (char **)NULL, 10); ++ random_galois_LFSR = random_LCG = strtoul(value, NULL, 10); + } + } + #endif +@@ -10406,7 +10469,7 @@ parsefname(void) + TRACE(("Here document %d\n", n->type)); + if (!noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN) + raise_error_syntax("illegal eof marker for << redirection"); +- rmescapes(wordtext); ++ rmescapes(wordtext, 0); + here->eofmark = wordtext; + here->next = NULL; + if (heredoclist == NULL) +@@ -12202,14 +12265,30 @@ trapcmd(int argc UNUSED_PARAM, char **ar + ap = argptr; if (!*ap) { for (signo = 0; signo < NSIG; signo++) { - if (trap[signo] != NULL) { -- out1fmt("trap -- %s %s\n", -+ out1fmt("trap -- %s SIG%s\n", - single_quote(trap[signo]), +- if (trap[signo] != NULL) { ++ char *tr = trap_ptr[signo]; ++ if (tr) { ++ /* note: bash adds "SIG", but only if invoked ++ * as "bash". If called as "sh", or if set -o posix, ++ * then it prints short signal names. ++ * We are printing short names: */ + out1fmt("trap -- %s %s\n", +- single_quote(trap[signo]), ++ single_quote(tr), get_signame(signo)); - } -diff -urpN busybox-1.15.1/shell/ash_test/ash-signals/signal1.right busybox-1.15.1-ash/shell/ash_test/ash-signals/signal1.right ---- busybox-1.15.1/shell/ash_test/ash-signals/signal1.right 2009-09-12 17:55:36.000000000 +0200 -+++ busybox-1.15.1-ash/shell/ash_test/ash-signals/signal1.right 2009-09-23 03:24:05.000000000 +0200 -@@ -1,20 +1,20 @@ - got signal --trap -- 'echo got signal' USR1 -+trap -- 'echo got signal' SIGUSR1 - sent 1 signal - got signal - wait interrupted --trap -- 'echo got signal' USR1 -+trap -- 'echo got signal' SIGUSR1 - sent 2 signal - got signal - wait interrupted --trap -- 'echo got signal' USR1 -+trap -- 'echo got signal' SIGUSR1 - sent 3 signal - got signal - wait interrupted ***The diff for this file has been truncated for email.*** ======================================= --- /trunk/gar-minimyth/script/utils/busybox/files/busybox-1.15.1-hush.patch Wed Sep 23 17:40:21 2009 +++ /trunk/gar-minimyth/script/utils/busybox/files/busybox-1.15.1-hush.patch Mon Sep 28 16:52:59 2009 @@ -1,7 +1,256 @@ diff -urpN busybox-1.15.1/shell/hush.c busybox-1.15.1-hush/shell/hush.c --- busybox-1.15.1/shell/hush.c 2009-09-12 17:56:20.000000000 +0200 -+++ busybox-1.15.1-hush/shell/hush.c 2009-09-23 03:27:27.000000000 +0200 -@@ -5183,6 +5183,47 @@ static FILE *generate_stream_from_string ++++ busybox-1.15.1-hush/shell/hush.c 2009-09-27 02:46:54.000000000 +0200 +@@ -78,6 +78,7 @@ + * Licensed under the GPL v2 or later, see the file LICENSE in this tarball. + */ + #include "busybox.h" /* for APPLET_IS_NOFORK/NOEXEC */ ++#include <malloc.h> /* for malloc_trim */ + #include <glob.h> + /* #include <dmalloc.h> */ + #if ENABLE_HUSH_CASE +@@ -786,7 +787,7 @@ static void xxfree(void *ptr) + * HUSH_DEBUG >= 2 prints line number in this file where it was detected. + */ + #if HUSH_DEBUG < 2 +-# define die_if_script(lineno, fmt...) die_if_script(fmt) ++# define die_if_script(lineno, ...) die_if_script(__VA_ARGS__) + # define syntax_error(lineno, msg) syntax_error(msg) + # define syntax_error_at(lineno, msg) syntax_error_at(msg) + # define syntax_error_unterm_ch(lineno, ch) syntax_error_unterm_ch(ch) +@@ -855,7 +856,7 @@ static void syntax_error_unexpected_ch(u + # undef syntax_error_unterm_str + # undef syntax_error_unexpected_ch + #else +-# define die_if_script(fmt...) die_if_script(__LINE__, fmt) ++# define die_if_script(...) die_if_script(__LINE__, __VA_ARGS__) + # define syntax_error(msg) syntax_error(__LINE__, msg) + # define syntax_error_at(msg) syntax_error_at(__LINE__, msg) + # define syntax_error_unterm_ch(ch) syntax_error_unterm_ch(__LINE__, ch) +@@ -898,7 +899,7 @@ static int is_well_formed_var_name(const + /* Replace each \x with x in place, return ptr past NUL. */ + static char *unbackslash(char *src) + { +- char *dst = src; ++ char *dst = src = strchrnul(src, '\\'); + while (1) { + if (*src == '\\') + src++; +@@ -1037,7 +1038,7 @@ static void restore_G_args(save_arg_t *s + * is finished or backgrounded. It is the same in interactive and + * non-interactive shells, and is the same regardless of whether + * a user trap handler is installed or a shell special one is in effect. +- * ^C or ^Z from keyboard seem to execute "at once" because it usually ++ * ^C or ^Z from keyboard seems to execute "at once" because it usually + * backgrounds (i.e. stops) or kills all members of currently running + * pipe. + * +@@ -1104,12 +1105,17 @@ static void restore_G_args(save_arg_t *s + * (child shell is not interactive), + * unset all traps (note: regardless of child shell's type - {}, (), etc) + * after [v]fork, if we plan to exec: +- * POSIX says pending signal mask is cleared in child - no need to clear it. ++ * POSIX says fork clears pending signal mask in child - no need to clear it. + * Restore blocked signal set to one inherited by shell just prior to exec. + * + * Note: as a result, we do not use signal handlers much. The only uses + * are to count SIGCHLDs + * and to restore tty pgrp on signal-induced exit. ++ * ++ * Note 2 (compat): ++ * Standard says "When a subshell is entered, traps that are not being ignored ++ * are set to the default actions". bash interprets it so that traps which ++ * are set to "" (ignore) are NOT reset to defaults. We do the same. + */ + enum { + SPECIAL_INTERACTIVE_SIGS = 0 +@@ -2596,43 +2602,51 @@ static void reset_traps_to_defaults(void + { + /* This function is always called in a child shell + * after fork (not vfork, NOMMU doesn't use this function). +- * Child shells are not interactive. +- * SIGTTIN/SIGTTOU/SIGTSTP should not have special handling. +- * Testcase: (while :; do :; done) + ^Z should background. +- * Same goes for SIGTERM, SIGHUP, SIGINT. + */ + unsigned sig; + unsigned mask; + ++ /* Child shells are not interactive. ++ * SIGTTIN/SIGTTOU/SIGTSTP should not have special handling. ++ * Testcase: (while :; do :; done) + ^Z should background. ++ * Same goes for SIGTERM, SIGHUP, SIGINT. ++ */ + if (!G.traps && !(G.non_DFL_mask & SPECIAL_INTERACTIVE_SIGS)) +- return; ++ return; /* already no traps and no SPECIAL_INTERACTIVE_SIGS */ + +- /* Stupid. It can be done with *single* &= op, but we can't use +- * the fact that G.blocked_set is implemented as a bitmask... */ ++ /* Switching off SPECIAL_INTERACTIVE_SIGS. ++ * Stupid. It can be done with *single* &= op, but we can't use ++ * the fact that G.blocked_set is implemented as a bitmask ++ * in libc... */ + mask = (SPECIAL_INTERACTIVE_SIGS >> 1); + sig = 1; + while (1) { +- if (mask & 1) +- sigdelset(&G.blocked_set, sig); ++ if (mask & 1) { ++ /* Careful. Only if no trap or trap is not "" */ ++ if (!G.traps || !G.traps[sig] || G.traps[sig][0]) ++ sigdelset(&G.blocked_set, sig); ++ } + mask >>= 1; + if (!mask) + break; + sig++; + } +- ++ /* Our homegrown sig mask is saner to work with :) */ + G.non_DFL_mask &= ~SPECIAL_INTERACTIVE_SIGS; ++ ++ /* Resetting all traps to default except empty ones */ + mask = G.non_DFL_mask; + if (G.traps) for (sig = 0; sig < NSIG; sig++, mask >>= 1) { +- if (!G.traps[sig]) ++ if (!G.traps[sig] || !G.traps[sig][0]) + continue; + free(G.traps[sig]); + G.traps[sig] = NULL; + /* There is no signal for 0 (EXIT) */ + if (sig == 0) + continue; +- /* There was a trap handler, we are removing it. ++ /* There was a trap handler, we just removed it. + * But if sig still has non-DFL handling, +- * we should not unblock it. */ ++ * we should not unblock the sig. */ + if (mask & 1) + continue; + sigdelset(&G.blocked_set, sig); +@@ -3079,15 +3093,21 @@ static const struct built_in_command* fi + } + + #if ENABLE_HUSH_FUNCTIONS +-static const struct function *find_function(const char *name) ++static struct function **find_function_slot(const char *name) + { +- const struct function *funcp = G.top_func; +- while (funcp) { +- if (strcmp(name, funcp->name) == 0) { ++ struct function **funcpp = &G.top_func; ++ while (*funcpp) { ++ if (strcmp(name, (*funcpp)->name) == 0) { + break; + } +- funcp = funcp->next; ++ funcpp = &(*funcpp)->next; + } ++ return funcpp; ++} ++ ++static const struct function *find_function(const char *name) ++{ ++ const struct function *funcp = *find_function_slot(name); + if (funcp) + debug_printf_exec("found function '%s'\n", name); + return funcp; +@@ -3096,18 +3116,11 @@ static const struct function *find_funct + /* Note: takes ownership on name ptr */ + static struct function *new_function(char *name) + { +- struct function *funcp; +- struct function **funcpp = &G.top_func; +- +- while ((funcp = *funcpp) != NULL) { +- struct command *cmd; +- +- if (strcmp(funcp->name, name) != 0) { +- funcpp = &funcp->next; +- continue; +- } ++ struct function **funcpp = find_function_slot(name); ++ struct function *funcp = *funcpp; + +- cmd = funcp->parent_cmd; ++ if (funcp != NULL) { ++ struct command *cmd = funcp->parent_cmd; + debug_printf_exec("func %p parent_cmd %p\n", funcp, cmd); + if (!cmd) { + debug_printf_exec("freeing & replacing function '%s'\n", funcp->name); +@@ -3129,39 +3142,36 @@ static struct function *new_function(cha + cmd->group_as_string = funcp->body_as_string; + # endif + } +- goto skip; ++ } else { ++ debug_printf_exec("remembering new function '%s'\n", name); ++ funcp = *funcpp = xzalloc(sizeof(*funcp)); ++ /*funcp->next = NULL;*/ + } +- debug_printf_exec("remembering new function '%s'\n", name); +- funcp = *funcpp = xzalloc(sizeof(*funcp)); +- /*funcp->next = NULL;*/ +- skip: ++ + funcp->name = name; + return funcp; + } + + static void unset_func(const char *name) + { +- struct function *funcp; +- struct function **funcpp = &G.top_func; ++ struct function **funcpp = find_function_slot(name); ++ struct function *funcp = *funcpp; + +- while ((funcp = *funcpp) != NULL) { +- if (strcmp(funcp->name, name) == 0) { +- *funcpp = funcp->next; +- /* funcp is unlinked now, deleting it. +- * Note: if !funcp->body, the function was created by +- * "-F name body", do not free ->body_as_string +- * and ->name as they were not malloced. */ +- if (funcp->body) { +- free_pipe_list(funcp->body); +- free(funcp->name); ++ if (funcp != NULL) { ++ debug_printf_exec("freeing function '%s'\n", funcp->name); ++ *funcpp = funcp->next; ++ /* funcp is unlinked now, deleting it. ++ * Note: if !funcp->body, the function was created by ++ * "-F name body", do not free ->body_as_string ++ * and ->name as they were not malloced. */ ++ if (funcp->body) { ++ free_pipe_list(funcp->body); ++ free(funcp->name); + # if !BB_MMU +- free(funcp->body_as_string); ++ free(funcp->body_as_string); + # endif +- } +- free(funcp); +- break; + } +- funcpp = &funcp->next; ++ free(funcp); + } + } + +@@ -3628,9 +3638,9 @@ static int checkjobs(struct pipe* fg_pip + /* 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* ++ /* bash prints killer signal's name for *last* + * process in pipe (prints just newline for SIGINT). +- * Mimic this. Example: "sleep 5" + ^\ ++ * Mimic this. Example: "sleep 5" + (^\ or kill -QUIT) + */ + if (WIFSIGNALED(status)) { + int sig = WTERMSIG(status); +@@ -5183,6 +5193,47 @@ static FILE *generate_stream_from_string xmove_fd(channel[1], 1); /* Prevent it from trying to handle ctrl-z etc */ IF_HUSH_JOB(G.run_list_level = 1;) @@ -49,13 +298,116 @@ #if BB_MMU reset_traps_to_defaults(); parse_and_run_string(s); -@@ -7057,7 +7098,8 @@ static int FAST_FUNC builtin_trap(char * +@@ -5676,8 +5727,10 @@ static int handle_dollar(o_string *as_st + goto make_var; + } + /* else: it's $_ */ +- /* TODO: */ +- /* $_ Shell or shell script name; or last cmd name */ ++ /* TODO: $_ and $-: */ ++ /* $_ Shell or shell script name; or last argument of last command ++ * (if last command wasn't a pipe; if it was, bash sets $_ to ""); ++ * but in command's env, set to full pathname used to invoke it */ + /* $- Option flags set by set builtin or shell options (-i etc) */ + default: + o_addQchr(dest, '$'); +@@ -5794,7 +5847,7 @@ static struct pipe *parse_stream(char ** + * found. When recursing, quote state is passed in via dest->o_escape. + */ + debug_printf_parse("parse_stream entered, end_trigger='%c'\n", +- end_trigger ? : 'X'); ++ end_trigger ? end_trigger : 'X'); + debug_enter(); + + G.ifs = get_local_var_value("IFS"); +@@ -6860,7 +6913,8 @@ static int FAST_FUNC builtin_cd(char **a + * bash says "bash: cd: HOME not set" and does nothing + * (exitcode 1) + */ +- newdir = get_local_var_value("HOME") ? : "/"; ++ const char *home = get_local_var_value("HOME"); ++ newdir = home ? home : "/"; + } + if (chdir(newdir)) { + /* Mimic bash message exactly */ +@@ -7057,6 +7111,10 @@ static int FAST_FUNC builtin_trap(char * if (G.traps[i]) { printf("trap -- "); print_escaped(G.traps[i]); -- printf(" %s\n", get_signame(i)); -+ /* bash compat: it says SIGxxx, not just xxx */ -+ printf(" SIG%s\n", get_signame(i)); ++ /* note: bash adds "SIG", but only if invoked ++ * as "bash". If called as "sh", or if set -o posix, ++ * then it prints short signal names. ++ * We are printing short names: */ + printf(" %s\n", get_signame(i)); } } - /*fflush(stdout); - done after each builtin anyway */ +@@ -7268,6 +7326,10 @@ static int FAST_FUNC builtin_memleak(cha + void *p; + unsigned long l; + ++#ifdef M_TRIM_THRESHOLD ++ /* Optional. Reduces probability of false positives */ ++ malloc_trim(0); ++#endif + /* Crude attempt to find where "free memory" starts, + * sans fragmentation. */ + p = malloc(240); +diff -urpN busybox-1.15.1/shell/hush_test/hush-trap/savetrap.right busybox-1.15.1-hush/shell/hush_test/hush-trap/savetrap.right +--- busybox-1.15.1/shell/hush_test/hush-trap/savetrap.right 1970-01-01 01:00:00.000000000 +0100 ++++ busybox-1.15.1-hush/shell/hush_test/hush-trap/savetrap.right 2009-09-27 02:03:53.000000000 +0200 +@@ -0,0 +1,8 @@ ++trap -- 'echo Exiting' EXIT ++trap -- 'echo WINCH!' WINCH ++trap -- 'echo Exiting' EXIT ++trap -- 'echo WINCH!' WINCH ++trap -- 'echo Exiting' EXIT ++trap -- 'echo WINCH!' WINCH ++Done ++Exiting +diff -urpN busybox-1.15.1/shell/hush_test/hush-trap/savetrap.tests busybox-1.15.1-hush/shell/hush_test/hush-trap/savetrap.tests +--- busybox-1.15.1/shell/hush_test/hush-trap/savetrap.tests 1970-01-01 01:00:00.000000000 +0100 ++++ busybox-1.15.1-hush/shell/hush_test/hush-trap/savetrap.tests 2009-09-27 02:04:02.000000000 +0200 +@@ -0,0 +1,9 @@ ++trap 'echo Exiting' EXIT ++trap 'echo WINCH!' SIGWINCH ++v=` trap ` ++echo "$v" ++v=$( trap ) ++echo "$v" ++v=`trap` ++echo "$v" ++echo Done +diff -urpN busybox-1.15.1/shell/hush_test/hush-trap/subshell.right busybox-1.15.1-hush/shell/hush_test/hush-trap/subshell.right +--- busybox-1.15.1/shell/hush_test/hush-trap/subshell.right 1970-01-01 01:00:00.000000000 +0100 ++++ busybox-1.15.1-hush/shell/hush_test/hush-trap/subshell.right 2009-09-26 15:14:57.000000000 +0200 +@@ -0,0 +1,6 @@ ++Ok ++Ok ++Ok ++Ok ++TERM ++Done +diff -urpN busybox-1.15.1/shell/hush_test/hush-trap/subshell.tests busybox-1.15.1-hush/shell/hush_test/hush-trap/subshell.tests +--- busybox-1.15.1/shell/hush_test/hush-trap/subshell.tests 1970-01-01 01:00:00.000000000 +0100 ++++ busybox-1.15.1-hush/shell/hush_test/hush-trap/subshell.tests 2009-09-26 15:14:57.000000000 +0200 +@@ -0,0 +1,20 @@ ++# Non-empty traps should be reset in subshell ++ ++# HUP is special in interactive shells ++trap '' HUP ++# QUIT is always special ++trap '' QUIT ++# SYS is not special ++trap '' SYS ++# WINCH is harmless ++trap 'bad: caught WINCH' WINCH ++# With TERM we'll check whether it is reset ++trap 'bad: caught TERM' TERM ++ ++# using bash, becuase we don't have $PPID (yet) ++(bash -c 'kill -HUP $PPID'; echo Ok) ++(bash -c 'kill -QUIT $PPID'; echo Ok) ++(bash -c 'kill -SYS $PPID'; echo Ok) ++(bash -c 'kill -WINCH $PPID'; echo Ok) ++(bash -c 'kill -TERM $PPID'; echo Bad: TERM is not reset) ++echo Done --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "minimyth-commits" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/minimyth-commits?hl=en -~----------~----~----~----~------~----~------~--~---
