summaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
Diffstat (limited to 'shell')
-rw-r--r--shell/ash.c903
1 files changed, 439 insertions, 464 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,6 +7720,137 @@ sprint_status(char *s, int status, int sigonly)
return col;
}
+/*
+ * 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)
@@ -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.
@@ -7902,50 +8143,6 @@ makejob(union node *node, int nprocs)
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);
- 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");