ash: cleanup part 5
authorDenis Vlasenko <vda.linux@googlemail.com>
Fri, 23 Feb 2007 01:05:03 +0000 (01:05 -0000)
committerDenis Vlasenko <vda.linux@googlemail.com>
Fri, 23 Feb 2007 01:05:03 +0000 (01:05 -0000)
shell/ash.c

index 7ffecf4..54fc8ea 100644 (file)
@@ -175,6 +175,18 @@ static int exsig;
 static volatile sig_atomic_t pendingsigs;
 
 /*
+ * Sigmode records the current value of the signal handlers for the various
+ * modes.  A value of zero means that the current handler is not known.
+ * S_HARD_IGN indicates that the signal was ignored on entry to the shell,
+ */
+
+#define S_DFL 1                 /* default signal handling (SIG_DFL) */
+#define S_CATCH 2               /* signal is caught */
+#define S_IGN 3                 /* signal is ignored (SIG_IGN) */
+#define S_HARD_IGN 4            /* signal is ignored permenantly */
+#define S_RESET 5               /* temporary - to reset a hard ignored sig */
+
+/*
  * These macros allow the user to suspend the handling of interrupt signals
  * over a period of time.  This is similar to SIGHOLD to or sigblock, but
  * much more efficient and portable.  (But hacking the kernel is so much
@@ -285,6 +297,34 @@ force_int_on(void)
        })
 /* EXSIG is turned off by evalbltin(). */
 
+/*
+ * Ignore a signal. Only one usage site - in forkchild()
+ */
+static void
+ignoresig(int signo)
+{
+       if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
+               signal(signo, SIG_IGN);
+       }
+       sigmode[signo - 1] = S_HARD_IGN;
+}
+
+/*
+ * Signal handler. Only one usage site - in setsignal()
+ */
+static void
+onsig(int signo)
+{
+       gotsig[signo - 1] = 1;
+       pendingsigs = signo;
+
+       if (exsig || (signo == SIGINT && !trap[SIGINT])) {
+               if (!suppressint)
+                       raise_interrupt();
+               intpending = 1;
+       }
+}
+
 
 /* ============ stdout/stderr output */
 
@@ -3244,10 +3284,10 @@ static void unsetfunc(const char *);
 
 #if ENABLE_ASH_MATH_SUPPORT_64
 typedef int64_t arith_t;
-#define arith_t_type (long long)
+#define arith_t_type long long
 #else
 typedef long arith_t;
-#define arith_t_type (long)
+#define arith_t_type long
 #endif
 
 #if ENABLE_ASH_MATH_SUPPORT
@@ -3341,7 +3381,6 @@ static int jobctl;              /* true if doing job control */
 static struct job *makejob(union node *, int);
 static int forkshell(struct job *, union node *, int);
 static int waitforjob(struct job *);
-static int stoppedjobs(void);
 
 #if ! JOBS
 #define setjobctl(on)   /* do nothing */
@@ -3384,8 +3423,6 @@ static int redirectsafe(union node *, int);
 
 static void clear_traps(void);
 static void setsignal(int);
-static void ignoresig(int);
-static void onsig(int);
 static int dotrap(void);
 static void setinteractive(int);
 static void exitshell(void) ATTRIBUTE_NORETURN;
@@ -7226,38 +7263,26 @@ closescript(void)
 #define DOWAIT_NORMAL 0
 #define DOWAIT_BLOCK 1
 
-/* array of jobs */
-static struct job *jobtab;
-/* size of array */
-static unsigned njobs;
 #if JOBS
 /* pgrp of shell on invocation */
 static int initialpgrp;
 static int ttyfd = -1;
 #endif
+/* array of jobs */
+static struct job *jobtab;
+/* size of array */
+static unsigned njobs;
 /* current job */
 static struct job *curjob;
 /* number of presumed living untracked jobs */
 static int jobless;
 
-static void set_curjob(struct job *, unsigned);
 #if JOBS
-static int restartjob(struct job *, int);
-static void xtcsetpgrp(int, pid_t);
 static char *commandtext(union node *);
 static void cmdlist(union node *, int);
 static void cmdtxt(union node *);
 static void cmdputs(const char *);
-static void showpipe(struct job *, FILE *);
 #endif
-static int sprint_status(char *, int, int);
-static void freejob(struct job *);
-static struct job *getjob(const char *, int);
-static struct job *growjobtab(void);
-static void forkchild(struct job *, union node *, int);
-static void forkparent(struct job *, union node *, int, pid_t);
-static int dowait(int, struct job *);
-static int getstatus(struct job *);
 
 static void
 set_curjob(struct job *jp, unsigned mode)
@@ -7307,7 +7332,126 @@ set_curjob(struct job *jp, unsigned mode)
        }
 }
 
+#if JOBS || DEBUG
+static int
+jobno(const struct job *jp)
+{
+       return jp - jobtab + 1;
+}
+#endif
+
+/*
+ * Convert a job name to a job structure.
+ */
+static struct job *
+getjob(const char *name, int getctl)
+{
+       struct job *jp;
+       struct job *found;
+       const char *err_msg = "No such job: %s";
+       unsigned num;
+       int c;
+       const char *p;
+       char *(*match)(const char *, const char *);
+
+       jp = curjob;
+       p = name;
+       if (!p)
+               goto currentjob;
+
+       if (*p != '%')
+               goto err;
+
+       c = *++p;
+       if (!c)
+               goto currentjob;
+
+       if (!p[1]) {
+               if (c == '+' || c == '%') {
+ currentjob:
+                       err_msg = "No current job";
+                       goto check;
+               }
+               if (c == '-') {
+                       if (jp)
+                               jp = jp->prev_job;
+                       err_msg = "No previous job";
+ check:
+                       if (!jp)
+                               goto err;
+                       goto gotit;
+               }
+       }
+
+       if (is_number(p)) {
+               num = atoi(p);
+               if (num < njobs) {
+                       jp = jobtab + num - 1;
+                       if (jp->used)
+                               goto gotit;
+                       goto err;
+               }
+       }
+
+       match = prefix;
+       if (*p == '?') {
+               match = strstr;
+               p++;
+       }
+
+       found = 0;
+       while (1) {
+               if (!jp)
+                       goto err;
+               if (match(jp->ps[0].cmd, p)) {
+                       if (found)
+                               goto err;
+                       found = jp;
+                       err_msg = "%s: ambiguous";
+               }
+               jp = jp->prev_job;
+       }
+
+ gotit:
+#if JOBS
+       err_msg = "job %s not created under job control";
+       if (getctl && jp->jobctl == 0)
+               goto err;
+#endif
+       return jp;
+ err:
+       ash_msg_and_raise_error(err_msg, name);
+}
+
+/*
+ * Mark a job structure as unused.
+ */
+static void
+freejob(struct job *jp)
+{
+       struct procstat *ps;
+       int i;
+
+       INT_OFF;
+       for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
+               if (ps->cmd != nullstr)
+                       free(ps->cmd);
+       }
+       if (jp->ps != &jp->ps0)
+               free(jp->ps);
+       jp->used = 0;
+       set_curjob(jp, CUR_DELETE);
+       INT_ON;
+}
+
 #if JOBS
+static void
+xtcsetpgrp(int fd, pid_t pgrp)
+{
+       if (tcsetpgrp(fd, pgrp))
+               ash_msg_and_raise_error("Cannot set tty process group (%m)");
+}
+
 /*
  * Turn job control on and off.
  *
@@ -7401,7 +7545,7 @@ killcmd(int argc, char **argv)
                if (signo < 0) {
                        int c;
 
-                       while ((c = nextopt("ls:")) != '\0')
+                       while ((c = nextopt("ls:")) != '\0') {
                                switch (c) {
                                default:
 #if DEBUG
@@ -7420,6 +7564,7 @@ killcmd(int argc, char **argv)
                                        }
                                        break;
                                }
+                       }
                        argv = argptr;
                } else
                        argv++;
@@ -7467,42 +7612,21 @@ killcmd(int argc, char **argv)
 
        return i;
 }
-#endif /* JOBS */
-
-#if JOBS || DEBUG
-static int
-jobno(const struct job *jp)
-{
-       return jp - jobtab + 1;
-}
-#endif
 
-#if JOBS
-static int
-fg_bgcmd(int argc, char **argv)
+static void
+showpipe(struct job *jp, FILE *out)
 {
-       struct job *jp;
-       FILE *out;
-       int mode;
-       int retval;
+       struct procstat *sp;
+       struct procstat *spend;
 
-       mode = (**argv == 'f') ? FORK_FG : FORK_BG;
-       nextopt(nullstr);
-       argv = argptr;
-       out = stdout;
-       do {
-               jp = getjob(*argv, 1);
-               if (mode == FORK_BG) {
-                       set_curjob(jp, CUR_RUNNING);
-                       fprintf(out, "[%d] ", jobno(jp));
-               }
-               outstr(jp->ps->cmd, out);
-               showpipe(jp, out);
-               retval = restartjob(jp, mode);
-       } while (*argv && *++argv);
-       return retval;
+       spend = jp->ps + jp->nprocs;
+       for (sp = jp->ps + 1; sp < spend; sp++)
+               fprintf(out, " | %s", sp->cmd);
+       outcslow('\n', out);
+       flush_stdout_stderr();
 }
 
+
 static int
 restartjob(struct job *jp, int mode)
 {
@@ -7531,6 +7655,31 @@ restartjob(struct job *jp, int mode)
        INT_ON;
        return status;
 }
+
+static int
+fg_bgcmd(int argc, char **argv)
+{
+       struct job *jp;
+       FILE *out;
+       int mode;
+       int retval;
+
+       mode = (**argv == 'f') ? FORK_FG : FORK_BG;
+       nextopt(nullstr);
+       argv = argptr;
+       out = stdout;
+       do {
+               jp = getjob(*argv, 1);
+               if (mode == FORK_BG) {
+                       set_curjob(jp, CUR_RUNNING);
+                       fprintf(out, "[%d] ", jobno(jp));
+               }
+               outstr(jp->ps->cmd, out);
+               showpipe(jp, out);
+               retval = restartjob(jp, mode);
+       } while (*argv && *++argv);
+       return retval;
+}
 #endif
 
 static int
@@ -7571,30 +7720,161 @@ sprint_status(char *s, int status, int sigonly)
        return col;
 }
 
-#if JOBS
-static void
-showjob(FILE *out, struct job *jp, int mode)
-{
-       struct procstat *ps;
-       struct procstat *psend;
-       int col;
-       int indent;
-       char s[80];
-
-       ps = jp->ps;
-
-       if (mode & SHOW_PGID) {
-               /* just output process (group) id of pipeline */
-               fprintf(out, "%d\n", ps->pid);
-               return;
-       }
-
-       col = fmtstr(s, 16, "[%d]   ", jobno(jp));
-       indent = col;
-
-       if (jp == curjob)
-               s[col - 2] = '+';
-       else if (curjob && jp == curjob->prev_job)
+/*
+ * Do a wait system call.  If job control is compiled in, we accept
+ * stopped processes.  If block is zero, we return a value of zero
+ * rather than blocking.
+ *
+ * System V doesn't have a non-blocking wait system call.  It does
+ * have a SIGCLD signal that is sent to a process when one of it's
+ * children dies.  The obvious way to use SIGCLD would be to install
+ * a handler for SIGCLD which simply bumped a counter when a SIGCLD
+ * was received, and have waitproc bump another counter when it got
+ * the status of a process.  Waitproc would then know that a wait
+ * system call would not block if the two counters were different.
+ * This approach doesn't work because if a process has children that
+ * have not been waited for, System V will send it a SIGCLD when it
+ * installs a signal handler for SIGCLD.  What this means is that when
+ * a child exits, the shell will be sent SIGCLD signals continuously
+ * until is runs out of stack space, unless it does a wait call before
+ * restoring the signal handler.  The code below takes advantage of
+ * this (mis)feature by installing a signal handler for SIGCLD and
+ * then checking to see whether it was called.  If there are any
+ * children to be waited for, it will be.
+ *
+ * If neither SYSV nor BSD is defined, we don't implement nonblocking
+ * waits at all.  In this case, the user will not be informed when
+ * a background process until the next time she runs a real program
+ * (as opposed to running a builtin command or just typing return),
+ * and the jobs command may give out of date information.
+ */
+static int
+waitproc(int block, int *status)
+{
+       int flags = 0;
+
+#if JOBS
+       if (jobctl)
+               flags |= WUNTRACED;
+#endif
+       if (block == 0)
+               flags |= WNOHANG;
+       return wait3(status, flags, (struct rusage *)NULL);
+}
+
+/*
+ * Wait for a process to terminate.
+ */
+static int
+dowait(int block, struct job *job)
+{
+       int pid;
+       int status;
+       struct job *jp;
+       struct job *thisjob;
+       int state;
+
+       TRACE(("dowait(%d) called\n", block));
+       pid = waitproc(block, &status);
+       TRACE(("wait returns pid %d, status=%d\n", pid, status));
+       if (pid <= 0)
+               return pid;
+       INT_OFF;
+       thisjob = NULL;
+       for (jp = curjob; jp; jp = jp->prev_job) {
+               struct procstat *sp;
+               struct procstat *spend;
+               if (jp->state == JOBDONE)
+                       continue;
+               state = JOBDONE;
+               spend = jp->ps + jp->nprocs;
+               sp = jp->ps;
+               do {
+                       if (sp->pid == pid) {
+                               TRACE(("Job %d: changing status of proc %d "
+                                       "from 0x%x to 0x%x\n",
+                                       jobno(jp), pid, sp->status, status));
+                               sp->status = status;
+                               thisjob = jp;
+                       }
+                       if (sp->status == -1)
+                               state = JOBRUNNING;
+#if JOBS
+                       if (state == JOBRUNNING)
+                               continue;
+                       if (WIFSTOPPED(sp->status)) {
+                               jp->stopstatus = sp->status;
+                               state = JOBSTOPPED;
+                       }
+#endif
+               } while (++sp < spend);
+               if (thisjob)
+                       goto gotjob;
+       }
+#if JOBS
+       if (!WIFSTOPPED(status))
+#endif
+
+               jobless--;
+       goto out;
+
+ gotjob:
+       if (state != JOBRUNNING) {
+               thisjob->changed = 1;
+
+               if (thisjob->state != state) {
+                       TRACE(("Job %d: changing state from %d to %d\n",
+                               jobno(thisjob), thisjob->state, state));
+                       thisjob->state = state;
+#if JOBS
+                       if (state == JOBSTOPPED) {
+                               set_curjob(thisjob, CUR_STOPPED);
+                       }
+#endif
+               }
+       }
+
+ out:
+       INT_ON;
+
+       if (thisjob && thisjob == job) {
+               char s[48 + 1];
+               int len;
+
+               len = sprint_status(s, status, 1);
+               if (len) {
+                       s[len] = '\n';
+                       s[len + 1] = 0;
+                       out2str(s);
+               }
+       }
+       return pid;
+}
+
+#if JOBS
+static void
+showjob(FILE *out, struct job *jp, int mode)
+{
+       struct procstat *ps;
+       struct procstat *psend;
+       int col;
+       int indent;
+       char s[80];
+
+       ps = jp->ps;
+
+       if (mode & SHOW_PGID) {
+               /* just output process (group) id of pipeline */
+               fprintf(out, "%d\n", ps->pid);
+               return;
+       }
+
+       col = fmtstr(s, 16, "[%d]   ", jobno(jp));
+       indent = col;
+
+       if (jp == curjob)
+               s[col - 2] = '+';
+       else if (curjob && jp == curjob->prev_job)
                s[col - 2] = '-';
 
        if (mode & SHOW_PID)
@@ -7641,7 +7921,6 @@ showjob(FILE *out, struct job *jp, int mode)
        }
 }
 
-
 static int
 jobscmd(int argc, char **argv)
 {
@@ -7668,7 +7947,6 @@ jobscmd(int argc, char **argv)
        return 0;
 }
 
-
 /*
  * Print a list of jobs.  If "change" is nonzero, only print jobs whose
  * statuses have changed since the last call to showjobs.
@@ -7691,29 +7969,34 @@ showjobs(FILE *out, int mode)
 }
 #endif /* JOBS */
 
-
-/*
- * Mark a job structure as unused.
- */
-static void
-freejob(struct job *jp)
+static int
+getstatus(struct job *job)
 {
-       struct procstat *ps;
-       int i;
+       int status;
+       int retval;
 
-       INT_OFF;
-       for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
-               if (ps->cmd != nullstr)
-                       free(ps->cmd);
+       status = job->ps[job->nprocs - 1].status;
+       retval = WEXITSTATUS(status);
+       if (!WIFEXITED(status)) {
+#if JOBS
+               retval = WSTOPSIG(status);
+               if (!WIFSTOPPED(status))
+#endif
+               {
+                       /* XXX: limits number of signals */
+                       retval = WTERMSIG(status);
+#if JOBS
+                       if (retval == SIGINT)
+                               job->sigint = 1;
+#endif
+               }
+               retval += 128;
        }
-       if (jp->ps != &jp->ps0)
-               free(jp->ps);
-       jp->used = 0;
-       set_curjob(jp, CUR_DELETE);
-       INT_ON;
+       TRACE(("getstatus: job %d, nproc %d, status %x, retval %x\n",
+               jobno(job), job->nprocs, status, retval));
+       return retval;
 }
 
-
 static int
 waitcmd(int argc, char **argv)
 {
@@ -7774,91 +8057,49 @@ waitcmd(int argc, char **argv)
        return retval;
 }
 
-
-/*
- * Convert a job name to a job structure.
- */
 static struct job *
-getjob(const char *name, int getctl)
+growjobtab(void)
 {
-       struct job *jp;
-       struct job *found;
-       const char *err_msg = "No such job: %s";
-       unsigned num;
-       int c;
-       const char *p;
-       char *(*match)(const char *, const char *);
-
-       jp = curjob;
-       p = name;
-       if (!p)
-               goto currentjob;
-
-       if (*p != '%')
-               goto err;
-
-       c = *++p;
-       if (!c)
-               goto currentjob;
-
-       if (!p[1]) {
-               if (c == '+' || c == '%') {
- currentjob:
-                       err_msg = "No current job";
-                       goto check;
-               }
-               if (c == '-') {
-                       if (jp)
-                               jp = jp->prev_job;
-                       err_msg = "No previous job";
- check:
-                       if (!jp)
-                               goto err;
-                       goto gotit;
-               }
-       }
+       size_t len;
+       ptrdiff_t offset;
+       struct job *jp, *jq;
 
-       if (is_number(p)) {
-               num = atoi(p);
-               if (num < njobs) {
-                       jp = jobtab + num - 1;
-                       if (jp->used)
-                               goto gotit;
-                       goto err;
-               }
-       }
+       len = njobs * sizeof(*jp);
+       jq = jobtab;
+       jp = ckrealloc(jq, len + 4 * sizeof(*jp));
 
-       match = prefix;
-       if (*p == '?') {
-               match = strstr;
-               p++;
-       }
+       offset = (char *)jp - (char *)jq;
+       if (offset) {
+               /* Relocate pointers */
+               size_t l = len;
 
-       found = 0;
-       while (1) {
-               if (!jp)
-                       goto err;
-               if (match(jp->ps[0].cmd, p)) {
-                       if (found)
-                               goto err;
-                       found = jp;
-                       err_msg = "%s: ambiguous";
+               jq = (struct job *)((char *)jq + l);
+               while (l) {
+                       l -= sizeof(*jp);
+                       jq--;
+#define joff(p) ((struct job *)((char *)(p) + l))
+#define jmove(p) (p) = (void *)((char *)(p) + offset)
+                       if (xlikely(joff(jp)->ps == &jq->ps0))
+                               jmove(joff(jp)->ps);
+                       if (joff(jp)->prev_job)
+                               jmove(joff(jp)->prev_job);
                }
-               jp = jp->prev_job;
+               if (curjob)
+                       jmove(curjob);
+#undef joff
+#undef jmove
        }
 
- gotit:
-#if JOBS
-       err_msg = "job %s not created under job control";
-       if (getctl && jp->jobctl == 0)
-               goto err;
-#endif
+       njobs += 4;
+       jobtab = jp;
+       jp = (struct job *)((char *)jp + len);
+       jq = jp + 3;
+       do {
+               jq->used = 0;
+       } while (--jq >= jp);
        return jp;
- err:
-       ash_msg_and_raise_error(err_msg, name);
 }
 
-
 /*
  * Return a new job structure.
  * Called with interrupts off.
@@ -7895,57 +8136,13 @@ makejob(union node *node, int nprocs)
        jp->used = 1;
        jp->ps = &jp->ps0;
        if (nprocs > 1) {
-               jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
-       }
-       TRACE(("makejob(0x%lx, %d) returns %%%d\n", (long)node, nprocs,
-                               jobno(jp)));
-       return jp;
-}
-
-static struct job *
-growjobtab(void)
-{
-       size_t len;
-       ptrdiff_t offset;
-       struct job *jp, *jq;
-
-       len = njobs * sizeof(*jp);
-       jq = jobtab;
-       jp = ckrealloc(jq, len + 4 * sizeof(*jp));
-
-       offset = (char *)jp - (char *)jq;
-       if (offset) {
-               /* Relocate pointers */
-               size_t l = len;
-
-               jq = (struct job *)((char *)jq + l);
-               while (l) {
-                       l -= sizeof(*jp);
-                       jq--;
-#define joff(p) ((struct job *)((char *)(p) + l))
-#define jmove(p) (p) = (void *)((char *)(p) + offset)
-                       if (xlikely(joff(jp)->ps == &jq->ps0))
-                               jmove(joff(jp)->ps);
-                       if (joff(jp)->prev_job)
-                               jmove(joff(jp)->prev_job);
-               }
-               if (curjob)
-                       jmove(curjob);
-#undef joff
-#undef jmove
-       }
-
-       njobs += 4;
-       jobtab = jp;
-       jp = (struct job *)((char *)jp + len);
-       jq = jp + 3;
-       do {
-               jq->used = 0;
-       } while (--jq >= jp);
+               jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
+       }
+       TRACE(("makejob(0x%lx, %d) returns %%%d\n", (long)node, nprocs,
+                               jobno(jp)));
        return jp;
 }
 
-
 /*
  * Fork off a subshell.  If we are doing job control, give the subshell its
  * own process group.  Jp is a job structure that the job is to be added to.
@@ -7962,7 +8159,8 @@ growjobtab(void)
  *
  * Called with interrupts off.
  */
-static void forkchild(struct job *jp, union node *n, int mode)
+static void
+forkchild(struct job *jp, union node *n, int mode)
 {
        int oldlvl;
 
@@ -8009,7 +8207,8 @@ static void forkchild(struct job *jp, union node *n, int mode)
        jobless = 0;
 }
 
-static void forkparent(struct job *jp, union node *n, int mode, pid_t pid)
+static void
+forkparent(struct job *jp, union node *n, int mode, pid_t pid)
 {
        TRACE(("In parent shell: child = %d\n", pid));
        if (!jp) {
@@ -8065,7 +8264,6 @@ forkshell(struct job *jp, union node *n, int mode)
        return pid;
 }
 
-
 /*
  * Wait for job to finish.
  *
@@ -8116,144 +8314,10 @@ waitforjob(struct job *jp)
        return st;
 }
 
-
-/*
- * Do a wait system call.  If job control is compiled in, we accept
- * stopped processes.  If block is zero, we return a value of zero
- * rather than blocking.
- *
- * System V doesn't have a non-blocking wait system call.  It does
- * have a SIGCLD signal that is sent to a process when one of it's
- * children dies.  The obvious way to use SIGCLD would be to install
- * a handler for SIGCLD which simply bumped a counter when a SIGCLD
- * was received, and have waitproc bump another counter when it got
- * the status of a process.  Waitproc would then know that a wait
- * system call would not block if the two counters were different.
- * This approach doesn't work because if a process has children that
- * have not been waited for, System V will send it a SIGCLD when it
- * installs a signal handler for SIGCLD.  What this means is that when
- * a child exits, the shell will be sent SIGCLD signals continuously
- * until is runs out of stack space, unless it does a wait call before
- * restoring the signal handler.  The code below takes advantage of
- * this (mis)feature by installing a signal handler for SIGCLD and
- * then checking to see whether it was called.  If there are any
- * children to be waited for, it will be.
- *
- * If neither SYSV nor BSD is defined, we don't implement nonblocking
- * waits at all.  In this case, the user will not be informed when
- * a background process until the next time she runs a real program
- * (as opposed to running a builtin command or just typing return),
- * and the jobs command may give out of date information.
- */
-static int
-waitproc(int block, int *status)
-{
-       int flags = 0;
-
-#if JOBS
-       if (jobctl)
-               flags |= WUNTRACED;
-#endif
-       if (block == 0)
-               flags |= WNOHANG;
-       return wait3(status, flags, (struct rusage *)NULL);
-}
-
-
-/*
- * Wait for a process to terminate.
- */
-static int
-dowait(int block, struct job *job)
-{
-       int pid;
-       int status;
-       struct job *jp;
-       struct job *thisjob;
-       int state;
-
-       TRACE(("dowait(%d) called\n", block));
-       pid = waitproc(block, &status);
-       TRACE(("wait returns pid %d, status=%d\n", pid, status));
-       if (pid <= 0)
-               return pid;
-       INT_OFF;
-       thisjob = NULL;
-       for (jp = curjob; jp; jp = jp->prev_job) {
-               struct procstat *sp;
-               struct procstat *spend;
-               if (jp->state == JOBDONE)
-                       continue;
-               state = JOBDONE;
-               spend = jp->ps + jp->nprocs;
-               sp = jp->ps;
-               do {
-                       if (sp->pid == pid) {
-                               TRACE(("Job %d: changing status of proc %d "
-                                       "from 0x%x to 0x%x\n",
-                                       jobno(jp), pid, sp->status, status));
-                               sp->status = status;
-                               thisjob = jp;
-                       }
-                       if (sp->status == -1)
-                               state = JOBRUNNING;
-#if JOBS
-                       if (state == JOBRUNNING)
-                               continue;
-                       if (WIFSTOPPED(sp->status)) {
-                               jp->stopstatus = sp->status;
-                               state = JOBSTOPPED;
-                       }
-#endif
-               } while (++sp < spend);
-               if (thisjob)
-                       goto gotjob;
-       }
-#if JOBS
-       if (!WIFSTOPPED(status))
-#endif
-
-               jobless--;
-       goto out;
-
- gotjob:
-       if (state != JOBRUNNING) {
-               thisjob->changed = 1;
-
-               if (thisjob->state != state) {
-                       TRACE(("Job %d: changing state from %d to %d\n",
-                               jobno(thisjob), thisjob->state, state));
-                       thisjob->state = state;
-#if JOBS
-                       if (state == JOBSTOPPED) {
-                               set_curjob(thisjob, CUR_STOPPED);
-                       }
-#endif
-               }
-       }
-
- out:
-       INT_ON;
-
-       if (thisjob && thisjob == job) {
-               char s[48 + 1];
-               int len;
-
-               len = sprint_status(s, status, 1);
-               if (len) {
-                       s[len] = '\n';
-                       s[len + 1] = 0;
-                       out2str(s);
-               }
-       }
-       return pid;
-}
-
-
 /*
  * return 1 if there are stopped jobs, otherwise 0
  */
-int
+static int
 stoppedjobs(void)
 {
        struct job *jp;
@@ -8289,7 +8353,7 @@ commandtext(union node *n)
        cmdtxt(n);
        name = stackblock();
        TRACE(("commandtext: name %p, end %p\n\t\"%s\"\n",
-               name, cmdnextc, cmdnextc));
+                       name, cmdnextc, cmdnextc));
        return ckstrdup(name);
 }
 
@@ -8550,57 +8614,8 @@ cmdputs(const char *s)
        *nextc = 0;
        cmdnextc = nextc;
 }
-
-
-static void
-showpipe(struct job *jp, FILE *out)
-{
-       struct procstat *sp;
-       struct procstat *spend;
-
-       spend = jp->ps + jp->nprocs;
-       for (sp = jp->ps + 1; sp < spend; sp++)
-               fprintf(out, " | %s", sp->cmd);
-       outcslow('\n', out);
-       flush_stdout_stderr();
-}
-
-static void
-xtcsetpgrp(int fd, pid_t pgrp)
-{
-       if (tcsetpgrp(fd, pgrp))
-               ash_msg_and_raise_error("Cannot set tty process group (%m)");
-}
 #endif /* JOBS */
 
-static int
-getstatus(struct job *job)
-{
-       int status;
-       int retval;
-
-       status = job->ps[job->nprocs - 1].status;
-       retval = WEXITSTATUS(status);
-       if (!WIFEXITED(status)) {
-#if JOBS
-               retval = WSTOPSIG(status);
-               if (!WIFSTOPPED(status))
-#endif
-               {
-                       /* XXX: limits number of signals */
-                       retval = WTERMSIG(status);
-#if JOBS
-                       if (retval == SIGINT)
-                               job->sigint = 1;
-#endif
-               }
-               retval += 128;
-       }
-       TRACE(("getstatus: job %d, nproc %d, status %x, retval %x\n",
-               jobno(job), job->nprocs, status, retval));
-       return retval;
-}
-
 #if ENABLE_ASH_MAIL
 /*      mail.c       */
 
@@ -11333,17 +11348,6 @@ redirectsafe(union node *redir, int flags)
 
 /*      trap.c       */
 
-/*
- * Sigmode records the current value of the signal handlers for the various
- * modes.  A value of zero means that the current handler is not known.
- * S_HARD_IGN indicates that the signal was ignored on entry to the shell,
- */
-
-#define S_DFL 1                 /* default signal handling (SIG_DFL) */
-#define S_CATCH 2               /* signal is caught */
-#define S_IGN 3                 /* signal is ignored (SIG_IGN) */
-#define S_HARD_IGN 4            /* signal is ignored permenantly */
-#define S_RESET 5               /* temporary - to reset a hard ignored sig */
 
 
 /*
@@ -11507,36 +11511,6 @@ setsignal(int signo)
 
 
 /*
- * Ignore a signal.
- */
-static void
-ignoresig(int signo)
-{
-       if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
-               signal(signo, SIG_IGN);
-       }
-       sigmode[signo - 1] = S_HARD_IGN;
-}
-
-
-/*
- * Signal handler.
- */
-static void
-onsig(int signo)
-{
-       gotsig[signo - 1] = 1;
-       pendingsigs = signo;
-
-       if (exsig || (signo == SIGINT && !trap[SIGINT])) {
-               if (!suppressint)
-                       raise_interrupt();
-               intpending = 1;
-       }
-}
-
-
-/*
  * Called to execute a trap.  Perhaps we should avoid entering new trap
  * handlers while we are executing a trap handler.
  */
@@ -11587,7 +11561,7 @@ setinteractive(int on)
 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
        if (is_interactive > 1) {
                /* Looks like they want an interactive shell */
-               static int do_banner;
+               static smallint do_banner;
 
                if (!do_banner) {
                        out1fmt(
@@ -11596,15 +11570,16 @@ setinteractive(int on)
                                "Enter 'help' for a list of built-in commands."
                                "\n\n",
                                BB_BANNER);
-                       do_banner++;
+                       do_banner = 1;
                }
        }
 #endif
 }
 
 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
-/*** List the available builtins ***/
-
+/*
+ * Lists available builtins
+ */
 static int
 helpcmd(int argc, char **argv)
 {
@@ -11711,7 +11686,8 @@ exportcmd(int argc, char **argv)
  * will be restored when the shell function returns.  We handle the name
  * "-" as a special case.
  */
-static void mklocal(char *name)
+static void
+mklocal(char *name)
 {
        struct localvar *lvp;
        struct var **vpp;
@@ -11811,9 +11787,10 @@ static const unsigned char timescmd_str[] = {
        0
 };
 
-static int timescmd(int ac, char **av)
+static int
+timescmd(int ac, char **av)
 {
-       long int clk_tck, s, t;
+       long clk_tck, s, t;
        const unsigned char *p;
        struct tms buf;
 
@@ -11845,12 +11822,11 @@ dash_arith(const char *s)
        if (errcode < 0) {
                if (errcode == -3)
                        ash_msg_and_raise_error("exponent less than 0");
-               else if (errcode == -2)
+               if (errcode == -2)
                        ash_msg_and_raise_error("divide by zero");
-               else if (errcode == -5)
+               if (errcode == -5)
                        ash_msg_and_raise_error("expression recursion loop detected");
-               else
-                       raise_error_syntax(s);
+               raise_error_syntax(s);
        }
        INT_ON;
 
@@ -12083,7 +12059,8 @@ readcmd(int argc, char **argv)
 }
 
 
-static int umaskcmd(int argc, char **argv)
+static int
+umaskcmd(int argc, char **argv)
 {
        static const char permuser[3] = "ugo";
        static const char permmode[3] = "rwx";
@@ -12201,12 +12178,13 @@ static const struct limits limits[] = {
 #ifdef RLIMIT_LOCKS
        { "locks",                      RLIMIT_LOCKS,      1, 'w' },
 #endif
-       { (char *) 0,                   0,                 0,  '\0' }
+       { NULL,                         0,                 0,  '\0' }
 };
 
 enum limtype { SOFT = 0x1, HARD = 0x2 };
 
-static void printlim(enum limtype how, const struct rlimit *limit,
+static void
+printlim(enum limtype how, const struct rlimit *limit,
                        const struct limits *l)
 {
        rlim_t val;
@@ -12223,16 +12201,16 @@ static void printlim(enum limtype how, const struct rlimit *limit,
        }
 }
 
-int
+static int
 ulimitcmd(int argc, char **argv)
 {
-       int     c;
+       int c;
        rlim_t val = 0;
        enum limtype how = SOFT | HARD;
-       const struct limits     *l;
-       int             set, all = 0;
-       int             optc, what;
-       struct rlimit   limit;
+       const struct limits *l;
+       int set, all = 0;
+       int optc, what;
+       struct rlimit limit;
 
        what = 'f';
        while ((optc = nextopt("HSa"
@@ -12428,11 +12406,9 @@ ulimitcmd(int argc, char **argv)
  * - always use special isspace(), see comment from bash ;-)
  */
 
-
 #define arith_isspace(arithval) \
        (arithval == ' ' || arithval == '\n' || arithval == '\t')
 
-
 typedef unsigned char operator;
 
 /* An operator's token id is a bit of a bitfield. The lower 5 bits are the
@@ -12524,7 +12500,8 @@ typedef unsigned char operator;
 
 #define NUMPTR (*numstackptr)
 
-static int tok_have_assign(operator op)
+static int
+tok_have_assign(operator op)
 {
        operator prec = PREC(op);
 
@@ -12533,13 +12510,13 @@ static int tok_have_assign(operator op)
                        prec == PREC_PRE || prec == PREC_POST);
 }
 
-static int is_right_associativity(operator prec)
+static int
+is_right_associativity(operator prec)
 {
        return (prec == PREC(TOK_ASSIGN) || prec == PREC(TOK_EXPONENT)
                || prec == PREC(TOK_CONDITIONAL));
 }
 
-
 typedef struct ARITCH_VAR_NUM {
        arith_t val;
        arith_t contidional_second_val;
@@ -12548,7 +12525,6 @@ typedef struct ARITCH_VAR_NUM {
                           else is variable name */
 } v_n_t;
 
-
 typedef struct CHK_VAR_RECURSIVE_LOOPED {
        const char *var;
        struct CHK_VAR_RECURSIVE_LOOPED *next;
@@ -12556,8 +12532,8 @@ typedef struct CHK_VAR_RECURSIVE_LOOPED {
 
 static chk_var_recursive_looped_t *prev_chk_var_recursive;
 
-
-static int arith_lookup_val(v_n_t *t)
+static int
+arith_lookup_val(v_n_t *t)
 {
        if (t->var) {
                const char * p = lookupvar(t->var);
@@ -12595,7 +12571,8 @@ static int arith_lookup_val(v_n_t *t)
 /* "applying" a token means performing it on the top elements on the integer
  * stack. For a unary operator it will only change the top element, but a
  * binary operator will pop two arguments and push a result */
-static int arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
+static int
+arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
 {
        v_n_t *numptr_m1;
        arith_t numptr_val, rez;
@@ -12692,12 +12669,10 @@ static int arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
                        }
                        numptr_m1->contidional_second_val_initialized = op;
                        numptr_m1->contidional_second_val = numptr_val;
-               }
-               else if (op == TOK_CONDITIONAL) {
+               } else if (op == TOK_CONDITIONAL) {
                        rez = rez ?
                                numptr_val : numptr_m1->contidional_second_val;
-               }
-               else if (op == TOK_EXPONENT) {
+               } else if (op == TOK_EXPONENT) {
                        if (numptr_val < 0)
                                return -3;      /* exponent less than 0 */
                        else {
@@ -12708,8 +12683,7 @@ static int arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
                                                c *= rez;
                                rez = c;
                        }
-               }
-               else if (numptr_val==0)          /* zero divisor check */
+               } else if (numptr_val==0)          /* zero divisor check */
                        return -2;
                else if (op == TOK_DIV || op == TOK_DIV_ASSIGN)
                        rez /= numptr_val;
@@ -12717,7 +12691,7 @@ static int arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
                        rez %= numptr_val;
        }
        if (tok_have_assign(op)) {
-               char buf[32];
+               char buf[sizeof(arith_t_type)*3 + 2];
 
                if (numptr_m1->var == NULL) {
                        /* Hmm, 1=2 ? */
@@ -12725,9 +12699,9 @@ static int arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
                }
                /* save to shell variable */
 #if ENABLE_ASH_MATH_SUPPORT_64
-               snprintf(buf, sizeof(buf), "%lld", arith_t_type rez);
+               snprintf(buf, sizeof(buf), "%lld", (arith_t_type) rez);
 #else
-               snprintf(buf, sizeof(buf), "%ld", arith_t_type rez);
+               snprintf(buf, sizeof(buf), "%ld", (arith_t_type) rez);
 #endif
                setvar(numptr_m1->var, buf, 0);
                /* after saving, make previous value for v++ or v-- */
@@ -12744,7 +12718,7 @@ static int arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
        return -1;
 }
 
-/* longest must first */
+/* longest must be first */
 static const char op_tokens[] = {
        '<','<','=',0, TOK_LSHIFT_ASSIGN,
        '>','>','=',0, TOK_RSHIFT_ASSIGN,
@@ -12792,7 +12766,8 @@ static const char op_tokens[] = {
 #define endexpression &op_tokens[sizeof(op_tokens)-7]
 
 
-static arith_t arith(const char *expr, int *perrcode)
+static arith_t
+arith(const char *expr, int *perrcode)
 {
        char arithval; /* Current character under analysis */
        operator lasttok, op;
@@ -12990,8 +12965,8 @@ static arith_t arith(const char *expr, int *perrcode)
  * exception occurs.  When an exception occurs the variable "state"
  * is used to figure out how far we had gotten.
  */
-
-static void init(void)
+static void
+init(void)
 {
        /* from input.c: */
        basepf.nextc = basepf.buf = basebuf;
@@ -13002,7 +12977,7 @@ static void init(void)
        /* from var.c: */
        {
                char **envp;
-               char ppid[32];
+               char ppid[sizeof(int)*3 + 1];
                const char *p;
                struct stat st1, st2;
 
@@ -13013,7 +12988,7 @@ static void init(void)
                        }
                }
 
-               snprintf(ppid, sizeof(ppid), "%d", (int) getppid());
+               snprintf(ppid, sizeof(ppid), "%u", (unsigned) getppid());
                setvar("PPID", ppid, 0);
 
                p = lookupvar("PWD");