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
-~----------~----~----~----~------~----~------~--~---

Reply via email to