From 5c67e3ed90f559b61b02aa013ad4dd7d57fce772 Mon Sep 17 00:00:00 2001 From: Denis Vlasenko Date: Fri, 23 Feb 2007 01:05:03 +0000 Subject: [PATCH] ash: cleanup part 5 --- shell/ash.c | 959 +++++++++++++++++++++++++++++------------------------------- 1 file changed, 467 insertions(+), 492 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index 7ffecf4..54fc8ea 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -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"); -- 2.7.4