aboutsummaryrefslogtreecommitdiff
path: root/shell/ash.c
diff options
context:
space:
mode:
authorvda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277>2007-02-23 01:05:03 +0000
committervda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277>2007-02-23 01:05:03 +0000
commit5b7579bbbaf369e6de72e5f063560f54b2637b08 (patch)
tree65c9d248b9b3c05a11a4c88dec739e5c1c26c140 /shell/ash.c
parent487a5f166d47cbc76877bb58240c1609bfcd8319 (diff)
downloadbusybox-w32-5b7579bbbaf369e6de72e5f063560f54b2637b08.tar.gz
busybox-w32-5b7579bbbaf369e6de72e5f063560f54b2637b08.tar.bz2
busybox-w32-5b7579bbbaf369e6de72e5f063560f54b2637b08.zip
ash: cleanup part 5
git-svn-id: svn://busybox.net/trunk/busybox@17957 69ca8d6d-28ef-0310-b511-8ec308f3f277
Diffstat (limited to 'shell/ash.c')
-rw-r--r--shell/ash.c903
1 files changed, 439 insertions, 464 deletions
diff --git a/shell/ash.c b/shell/ash.c
index 7ffecf43d..54fc8ea48 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -175,6 +175,18 @@ static int exsig;
175static volatile sig_atomic_t pendingsigs; 175static volatile sig_atomic_t pendingsigs;
176 176
177/* 177/*
178 * Sigmode records the current value of the signal handlers for the various
179 * modes. A value of zero means that the current handler is not known.
180 * S_HARD_IGN indicates that the signal was ignored on entry to the shell,
181 */
182
183#define S_DFL 1 /* default signal handling (SIG_DFL) */
184#define S_CATCH 2 /* signal is caught */
185#define S_IGN 3 /* signal is ignored (SIG_IGN) */
186#define S_HARD_IGN 4 /* signal is ignored permenantly */
187#define S_RESET 5 /* temporary - to reset a hard ignored sig */
188
189/*
178 * These macros allow the user to suspend the handling of interrupt signals 190 * These macros allow the user to suspend the handling of interrupt signals
179 * over a period of time. This is similar to SIGHOLD to or sigblock, but 191 * over a period of time. This is similar to SIGHOLD to or sigblock, but
180 * much more efficient and portable. (But hacking the kernel is so much 192 * much more efficient and portable. (But hacking the kernel is so much
@@ -285,6 +297,34 @@ force_int_on(void)
285 }) 297 })
286/* EXSIG is turned off by evalbltin(). */ 298/* EXSIG is turned off by evalbltin(). */
287 299
300/*
301 * Ignore a signal. Only one usage site - in forkchild()
302 */
303static void
304ignoresig(int signo)
305{
306 if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
307 signal(signo, SIG_IGN);
308 }
309 sigmode[signo - 1] = S_HARD_IGN;
310}
311
312/*
313 * Signal handler. Only one usage site - in setsignal()
314 */
315static void
316onsig(int signo)
317{
318 gotsig[signo - 1] = 1;
319 pendingsigs = signo;
320
321 if (exsig || (signo == SIGINT && !trap[SIGINT])) {
322 if (!suppressint)
323 raise_interrupt();
324 intpending = 1;
325 }
326}
327
288 328
289/* ============ stdout/stderr output */ 329/* ============ stdout/stderr output */
290 330
@@ -3244,10 +3284,10 @@ static void unsetfunc(const char *);
3244 3284
3245#if ENABLE_ASH_MATH_SUPPORT_64 3285#if ENABLE_ASH_MATH_SUPPORT_64
3246typedef int64_t arith_t; 3286typedef int64_t arith_t;
3247#define arith_t_type (long long) 3287#define arith_t_type long long
3248#else 3288#else
3249typedef long arith_t; 3289typedef long arith_t;
3250#define arith_t_type (long) 3290#define arith_t_type long
3251#endif 3291#endif
3252 3292
3253#if ENABLE_ASH_MATH_SUPPORT 3293#if ENABLE_ASH_MATH_SUPPORT
@@ -3341,7 +3381,6 @@ static int jobctl; /* true if doing job control */
3341static struct job *makejob(union node *, int); 3381static struct job *makejob(union node *, int);
3342static int forkshell(struct job *, union node *, int); 3382static int forkshell(struct job *, union node *, int);
3343static int waitforjob(struct job *); 3383static int waitforjob(struct job *);
3344static int stoppedjobs(void);
3345 3384
3346#if ! JOBS 3385#if ! JOBS
3347#define setjobctl(on) /* do nothing */ 3386#define setjobctl(on) /* do nothing */
@@ -3384,8 +3423,6 @@ static int redirectsafe(union node *, int);
3384 3423
3385static void clear_traps(void); 3424static void clear_traps(void);
3386static void setsignal(int); 3425static void setsignal(int);
3387static void ignoresig(int);
3388static void onsig(int);
3389static int dotrap(void); 3426static int dotrap(void);
3390static void setinteractive(int); 3427static void setinteractive(int);
3391static void exitshell(void) ATTRIBUTE_NORETURN; 3428static void exitshell(void) ATTRIBUTE_NORETURN;
@@ -7226,38 +7263,26 @@ closescript(void)
7226#define DOWAIT_NORMAL 0 7263#define DOWAIT_NORMAL 0
7227#define DOWAIT_BLOCK 1 7264#define DOWAIT_BLOCK 1
7228 7265
7229/* array of jobs */
7230static struct job *jobtab;
7231/* size of array */
7232static unsigned njobs;
7233#if JOBS 7266#if JOBS
7234/* pgrp of shell on invocation */ 7267/* pgrp of shell on invocation */
7235static int initialpgrp; 7268static int initialpgrp;
7236static int ttyfd = -1; 7269static int ttyfd = -1;
7237#endif 7270#endif
7271/* array of jobs */
7272static struct job *jobtab;
7273/* size of array */
7274static unsigned njobs;
7238/* current job */ 7275/* current job */
7239static struct job *curjob; 7276static struct job *curjob;
7240/* number of presumed living untracked jobs */ 7277/* number of presumed living untracked jobs */
7241static int jobless; 7278static int jobless;
7242 7279
7243static void set_curjob(struct job *, unsigned);
7244#if JOBS 7280#if JOBS
7245static int restartjob(struct job *, int);
7246static void xtcsetpgrp(int, pid_t);
7247static char *commandtext(union node *); 7281static char *commandtext(union node *);
7248static void cmdlist(union node *, int); 7282static void cmdlist(union node *, int);
7249static void cmdtxt(union node *); 7283static void cmdtxt(union node *);
7250static void cmdputs(const char *); 7284static void cmdputs(const char *);
7251static void showpipe(struct job *, FILE *);
7252#endif 7285#endif
7253static int sprint_status(char *, int, int);
7254static void freejob(struct job *);
7255static struct job *getjob(const char *, int);
7256static struct job *growjobtab(void);
7257static void forkchild(struct job *, union node *, int);
7258static void forkparent(struct job *, union node *, int, pid_t);
7259static int dowait(int, struct job *);
7260static int getstatus(struct job *);
7261 7286
7262static void 7287static void
7263set_curjob(struct job *jp, unsigned mode) 7288set_curjob(struct job *jp, unsigned mode)
@@ -7307,7 +7332,126 @@ set_curjob(struct job *jp, unsigned mode)
7307 } 7332 }
7308} 7333}
7309 7334
7335#if JOBS || DEBUG
7336static int
7337jobno(const struct job *jp)
7338{
7339 return jp - jobtab + 1;
7340}
7341#endif
7342
7343/*
7344 * Convert a job name to a job structure.
7345 */
7346static struct job *
7347getjob(const char *name, int getctl)
7348{
7349 struct job *jp;
7350 struct job *found;
7351 const char *err_msg = "No such job: %s";
7352 unsigned num;
7353 int c;
7354 const char *p;
7355 char *(*match)(const char *, const char *);
7356
7357 jp = curjob;
7358 p = name;
7359 if (!p)
7360 goto currentjob;
7361
7362 if (*p != '%')
7363 goto err;
7364
7365 c = *++p;
7366 if (!c)
7367 goto currentjob;
7368
7369 if (!p[1]) {
7370 if (c == '+' || c == '%') {
7371 currentjob:
7372 err_msg = "No current job";
7373 goto check;
7374 }
7375 if (c == '-') {
7376 if (jp)
7377 jp = jp->prev_job;
7378 err_msg = "No previous job";
7379 check:
7380 if (!jp)
7381 goto err;
7382 goto gotit;
7383 }
7384 }
7385
7386 if (is_number(p)) {
7387 num = atoi(p);
7388 if (num < njobs) {
7389 jp = jobtab + num - 1;
7390 if (jp->used)
7391 goto gotit;
7392 goto err;
7393 }
7394 }
7395
7396 match = prefix;
7397 if (*p == '?') {
7398 match = strstr;
7399 p++;
7400 }
7401
7402 found = 0;
7403 while (1) {
7404 if (!jp)
7405 goto err;
7406 if (match(jp->ps[0].cmd, p)) {
7407 if (found)
7408 goto err;
7409 found = jp;
7410 err_msg = "%s: ambiguous";
7411 }
7412 jp = jp->prev_job;
7413 }
7414
7415 gotit:
7416#if JOBS
7417 err_msg = "job %s not created under job control";
7418 if (getctl && jp->jobctl == 0)
7419 goto err;
7420#endif
7421 return jp;
7422 err:
7423 ash_msg_and_raise_error(err_msg, name);
7424}
7425
7426/*
7427 * Mark a job structure as unused.
7428 */
7429static void
7430freejob(struct job *jp)
7431{
7432 struct procstat *ps;
7433 int i;
7434
7435 INT_OFF;
7436 for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
7437 if (ps->cmd != nullstr)
7438 free(ps->cmd);
7439 }
7440 if (jp->ps != &jp->ps0)
7441 free(jp->ps);
7442 jp->used = 0;
7443 set_curjob(jp, CUR_DELETE);
7444 INT_ON;
7445}
7446
7310#if JOBS 7447#if JOBS
7448static void
7449xtcsetpgrp(int fd, pid_t pgrp)
7450{
7451 if (tcsetpgrp(fd, pgrp))
7452 ash_msg_and_raise_error("Cannot set tty process group (%m)");
7453}
7454
7311/* 7455/*
7312 * Turn job control on and off. 7456 * Turn job control on and off.
7313 * 7457 *
@@ -7401,7 +7545,7 @@ killcmd(int argc, char **argv)
7401 if (signo < 0) { 7545 if (signo < 0) {
7402 int c; 7546 int c;
7403 7547
7404 while ((c = nextopt("ls:")) != '\0') 7548 while ((c = nextopt("ls:")) != '\0') {
7405 switch (c) { 7549 switch (c) {
7406 default: 7550 default:
7407#if DEBUG 7551#if DEBUG
@@ -7420,6 +7564,7 @@ killcmd(int argc, char **argv)
7420 } 7564 }
7421 break; 7565 break;
7422 } 7566 }
7567 }
7423 argv = argptr; 7568 argv = argptr;
7424 } else 7569 } else
7425 argv++; 7570 argv++;
@@ -7467,42 +7612,21 @@ killcmd(int argc, char **argv)
7467 7612
7468 return i; 7613 return i;
7469} 7614}
7470#endif /* JOBS */
7471
7472#if JOBS || DEBUG
7473static int
7474jobno(const struct job *jp)
7475{
7476 return jp - jobtab + 1;
7477}
7478#endif
7479 7615
7480#if JOBS 7616static void
7481static int 7617showpipe(struct job *jp, FILE *out)
7482fg_bgcmd(int argc, char **argv)
7483{ 7618{
7484 struct job *jp; 7619 struct procstat *sp;
7485 FILE *out; 7620 struct procstat *spend;
7486 int mode;
7487 int retval;
7488 7621
7489 mode = (**argv == 'f') ? FORK_FG : FORK_BG; 7622 spend = jp->ps + jp->nprocs;
7490 nextopt(nullstr); 7623 for (sp = jp->ps + 1; sp < spend; sp++)
7491 argv = argptr; 7624 fprintf(out, " | %s", sp->cmd);
7492 out = stdout; 7625 outcslow('\n', out);
7493 do { 7626 flush_stdout_stderr();
7494 jp = getjob(*argv, 1);
7495 if (mode == FORK_BG) {
7496 set_curjob(jp, CUR_RUNNING);
7497 fprintf(out, "[%d] ", jobno(jp));
7498 }
7499 outstr(jp->ps->cmd, out);
7500 showpipe(jp, out);
7501 retval = restartjob(jp, mode);
7502 } while (*argv && *++argv);
7503 return retval;
7504} 7627}
7505 7628
7629
7506static int 7630static int
7507restartjob(struct job *jp, int mode) 7631restartjob(struct job *jp, int mode)
7508{ 7632{
@@ -7531,6 +7655,31 @@ restartjob(struct job *jp, int mode)
7531 INT_ON; 7655 INT_ON;
7532 return status; 7656 return status;
7533} 7657}
7658
7659static int
7660fg_bgcmd(int argc, char **argv)
7661{
7662 struct job *jp;
7663 FILE *out;
7664 int mode;
7665 int retval;
7666
7667 mode = (**argv == 'f') ? FORK_FG : FORK_BG;
7668 nextopt(nullstr);
7669 argv = argptr;
7670 out = stdout;
7671 do {
7672 jp = getjob(*argv, 1);
7673 if (mode == FORK_BG) {
7674 set_curjob(jp, CUR_RUNNING);
7675 fprintf(out, "[%d] ", jobno(jp));
7676 }
7677 outstr(jp->ps->cmd, out);
7678 showpipe(jp, out);
7679 retval = restartjob(jp, mode);
7680 } while (*argv && *++argv);
7681 return retval;
7682}
7534#endif 7683#endif
7535 7684
7536static int 7685static int
@@ -7571,6 +7720,137 @@ sprint_status(char *s, int status, int sigonly)
7571 return col; 7720 return col;
7572} 7721}
7573 7722
7723/*
7724 * Do a wait system call. If job control is compiled in, we accept
7725 * stopped processes. If block is zero, we return a value of zero
7726 * rather than blocking.
7727 *
7728 * System V doesn't have a non-blocking wait system call. It does
7729 * have a SIGCLD signal that is sent to a process when one of it's
7730 * children dies. The obvious way to use SIGCLD would be to install
7731 * a handler for SIGCLD which simply bumped a counter when a SIGCLD
7732 * was received, and have waitproc bump another counter when it got
7733 * the status of a process. Waitproc would then know that a wait
7734 * system call would not block if the two counters were different.
7735 * This approach doesn't work because if a process has children that
7736 * have not been waited for, System V will send it a SIGCLD when it
7737 * installs a signal handler for SIGCLD. What this means is that when
7738 * a child exits, the shell will be sent SIGCLD signals continuously
7739 * until is runs out of stack space, unless it does a wait call before
7740 * restoring the signal handler. The code below takes advantage of
7741 * this (mis)feature by installing a signal handler for SIGCLD and
7742 * then checking to see whether it was called. If there are any
7743 * children to be waited for, it will be.
7744 *
7745 * If neither SYSV nor BSD is defined, we don't implement nonblocking
7746 * waits at all. In this case, the user will not be informed when
7747 * a background process until the next time she runs a real program
7748 * (as opposed to running a builtin command or just typing return),
7749 * and the jobs command may give out of date information.
7750 */
7751static int
7752waitproc(int block, int *status)
7753{
7754 int flags = 0;
7755
7756#if JOBS
7757 if (jobctl)
7758 flags |= WUNTRACED;
7759#endif
7760 if (block == 0)
7761 flags |= WNOHANG;
7762 return wait3(status, flags, (struct rusage *)NULL);
7763}
7764
7765/*
7766 * Wait for a process to terminate.
7767 */
7768static int
7769dowait(int block, struct job *job)
7770{
7771 int pid;
7772 int status;
7773 struct job *jp;
7774 struct job *thisjob;
7775 int state;
7776
7777 TRACE(("dowait(%d) called\n", block));
7778 pid = waitproc(block, &status);
7779 TRACE(("wait returns pid %d, status=%d\n", pid, status));
7780 if (pid <= 0)
7781 return pid;
7782 INT_OFF;
7783 thisjob = NULL;
7784 for (jp = curjob; jp; jp = jp->prev_job) {
7785 struct procstat *sp;
7786 struct procstat *spend;
7787 if (jp->state == JOBDONE)
7788 continue;
7789 state = JOBDONE;
7790 spend = jp->ps + jp->nprocs;
7791 sp = jp->ps;
7792 do {
7793 if (sp->pid == pid) {
7794 TRACE(("Job %d: changing status of proc %d "
7795 "from 0x%x to 0x%x\n",
7796 jobno(jp), pid, sp->status, status));
7797 sp->status = status;
7798 thisjob = jp;
7799 }
7800 if (sp->status == -1)
7801 state = JOBRUNNING;
7802#if JOBS
7803 if (state == JOBRUNNING)
7804 continue;
7805 if (WIFSTOPPED(sp->status)) {
7806 jp->stopstatus = sp->status;
7807 state = JOBSTOPPED;
7808 }
7809#endif
7810 } while (++sp < spend);
7811 if (thisjob)
7812 goto gotjob;
7813 }
7814#if JOBS
7815 if (!WIFSTOPPED(status))
7816#endif
7817
7818 jobless--;
7819 goto out;
7820
7821 gotjob:
7822 if (state != JOBRUNNING) {
7823 thisjob->changed = 1;
7824
7825 if (thisjob->state != state) {
7826 TRACE(("Job %d: changing state from %d to %d\n",
7827 jobno(thisjob), thisjob->state, state));
7828 thisjob->state = state;
7829#if JOBS
7830 if (state == JOBSTOPPED) {
7831 set_curjob(thisjob, CUR_STOPPED);
7832 }
7833#endif
7834 }
7835 }
7836
7837 out:
7838 INT_ON;
7839
7840 if (thisjob && thisjob == job) {
7841 char s[48 + 1];
7842 int len;
7843
7844 len = sprint_status(s, status, 1);
7845 if (len) {
7846 s[len] = '\n';
7847 s[len + 1] = 0;
7848 out2str(s);
7849 }
7850 }
7851 return pid;
7852}
7853
7574#if JOBS 7854#if JOBS
7575static void 7855static void
7576showjob(FILE *out, struct job *jp, int mode) 7856showjob(FILE *out, struct job *jp, int mode)
@@ -7641,7 +7921,6 @@ showjob(FILE *out, struct job *jp, int mode)
7641 } 7921 }
7642} 7922}
7643 7923
7644
7645static int 7924static int
7646jobscmd(int argc, char **argv) 7925jobscmd(int argc, char **argv)
7647{ 7926{
@@ -7668,7 +7947,6 @@ jobscmd(int argc, char **argv)
7668 return 0; 7947 return 0;
7669} 7948}
7670 7949
7671
7672/* 7950/*
7673 * Print a list of jobs. If "change" is nonzero, only print jobs whose 7951 * Print a list of jobs. If "change" is nonzero, only print jobs whose
7674 * statuses have changed since the last call to showjobs. 7952 * statuses have changed since the last call to showjobs.
@@ -7691,29 +7969,34 @@ showjobs(FILE *out, int mode)
7691} 7969}
7692#endif /* JOBS */ 7970#endif /* JOBS */
7693 7971
7694 7972static int
7695/* 7973getstatus(struct job *job)
7696 * Mark a job structure as unused.
7697 */
7698static void
7699freejob(struct job *jp)
7700{ 7974{
7701 struct procstat *ps; 7975 int status;
7702 int i; 7976 int retval;
7703 7977
7704 INT_OFF; 7978 status = job->ps[job->nprocs - 1].status;
7705 for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) { 7979 retval = WEXITSTATUS(status);
7706 if (ps->cmd != nullstr) 7980 if (!WIFEXITED(status)) {
7707 free(ps->cmd); 7981#if JOBS
7982 retval = WSTOPSIG(status);
7983 if (!WIFSTOPPED(status))
7984#endif
7985 {
7986 /* XXX: limits number of signals */
7987 retval = WTERMSIG(status);
7988#if JOBS
7989 if (retval == SIGINT)
7990 job->sigint = 1;
7991#endif
7992 }
7993 retval += 128;
7708 } 7994 }
7709 if (jp->ps != &jp->ps0) 7995 TRACE(("getstatus: job %d, nproc %d, status %x, retval %x\n",
7710 free(jp->ps); 7996 jobno(job), job->nprocs, status, retval));
7711 jp->used = 0; 7997 return retval;
7712 set_curjob(jp, CUR_DELETE);
7713 INT_ON;
7714} 7998}
7715 7999
7716
7717static int 8000static int
7718waitcmd(int argc, char **argv) 8001waitcmd(int argc, char **argv)
7719{ 8002{
@@ -7774,91 +8057,49 @@ waitcmd(int argc, char **argv)
7774 return retval; 8057 return retval;
7775} 8058}
7776 8059
7777
7778/*
7779 * Convert a job name to a job structure.
7780 */
7781static struct job * 8060static struct job *
7782getjob(const char *name, int getctl) 8061growjobtab(void)
7783{ 8062{
7784 struct job *jp; 8063 size_t len;
7785 struct job *found; 8064 ptrdiff_t offset;
7786 const char *err_msg = "No such job: %s"; 8065 struct job *jp, *jq;
7787 unsigned num;
7788 int c;
7789 const char *p;
7790 char *(*match)(const char *, const char *);
7791
7792 jp = curjob;
7793 p = name;
7794 if (!p)
7795 goto currentjob;
7796
7797 if (*p != '%')
7798 goto err;
7799
7800 c = *++p;
7801 if (!c)
7802 goto currentjob;
7803
7804 if (!p[1]) {
7805 if (c == '+' || c == '%') {
7806 currentjob:
7807 err_msg = "No current job";
7808 goto check;
7809 }
7810 if (c == '-') {
7811 if (jp)
7812 jp = jp->prev_job;
7813 err_msg = "No previous job";
7814 check:
7815 if (!jp)
7816 goto err;
7817 goto gotit;
7818 }
7819 }
7820 8066
7821 if (is_number(p)) { 8067 len = njobs * sizeof(*jp);
7822 num = atoi(p); 8068 jq = jobtab;
7823 if (num < njobs) { 8069 jp = ckrealloc(jq, len + 4 * sizeof(*jp));
7824 jp = jobtab + num - 1;
7825 if (jp->used)
7826 goto gotit;
7827 goto err;
7828 }
7829 }
7830 8070
7831 match = prefix; 8071 offset = (char *)jp - (char *)jq;
7832 if (*p == '?') { 8072 if (offset) {
7833 match = strstr; 8073 /* Relocate pointers */
7834 p++; 8074 size_t l = len;
7835 }
7836 8075
7837 found = 0; 8076 jq = (struct job *)((char *)jq + l);
7838 while (1) { 8077 while (l) {
7839 if (!jp) 8078 l -= sizeof(*jp);
7840 goto err; 8079 jq--;
7841 if (match(jp->ps[0].cmd, p)) { 8080#define joff(p) ((struct job *)((char *)(p) + l))
7842 if (found) 8081#define jmove(p) (p) = (void *)((char *)(p) + offset)
7843 goto err; 8082 if (xlikely(joff(jp)->ps == &jq->ps0))
7844 found = jp; 8083 jmove(joff(jp)->ps);
7845 err_msg = "%s: ambiguous"; 8084 if (joff(jp)->prev_job)
8085 jmove(joff(jp)->prev_job);
7846 } 8086 }
7847 jp = jp->prev_job; 8087 if (curjob)
8088 jmove(curjob);
8089#undef joff
8090#undef jmove
7848 } 8091 }
7849 8092
7850 gotit: 8093 njobs += 4;
7851#if JOBS 8094 jobtab = jp;
7852 err_msg = "job %s not created under job control"; 8095 jp = (struct job *)((char *)jp + len);
7853 if (getctl && jp->jobctl == 0) 8096 jq = jp + 3;
7854 goto err; 8097 do {
7855#endif 8098 jq->used = 0;
8099 } while (--jq >= jp);
7856 return jp; 8100 return jp;
7857 err:
7858 ash_msg_and_raise_error(err_msg, name);
7859} 8101}
7860 8102
7861
7862/* 8103/*
7863 * Return a new job structure. 8104 * Return a new job structure.
7864 * Called with interrupts off. 8105 * Called with interrupts off.
@@ -7902,50 +8143,6 @@ makejob(union node *node, int nprocs)
7902 return jp; 8143 return jp;
7903} 8144}
7904 8145
7905static struct job *
7906growjobtab(void)
7907{
7908 size_t len;
7909 ptrdiff_t offset;
7910 struct job *jp, *jq;
7911
7912 len = njobs * sizeof(*jp);
7913 jq = jobtab;
7914 jp = ckrealloc(jq, len + 4 * sizeof(*jp));
7915
7916 offset = (char *)jp - (char *)jq;
7917 if (offset) {
7918 /* Relocate pointers */
7919 size_t l = len;
7920
7921 jq = (struct job *)((char *)jq + l);
7922 while (l) {
7923 l -= sizeof(*jp);
7924 jq--;
7925#define joff(p) ((struct job *)((char *)(p) + l))
7926#define jmove(p) (p) = (void *)((char *)(p) + offset)
7927 if (xlikely(joff(jp)->ps == &jq->ps0))
7928 jmove(joff(jp)->ps);
7929 if (joff(jp)->prev_job)
7930 jmove(joff(jp)->prev_job);
7931 }
7932 if (curjob)
7933 jmove(curjob);
7934#undef joff
7935#undef jmove
7936 }
7937
7938 njobs += 4;
7939 jobtab = jp;
7940 jp = (struct job *)((char *)jp + len);
7941 jq = jp + 3;
7942 do {
7943 jq->used = 0;
7944 } while (--jq >= jp);
7945 return jp;
7946}
7947
7948
7949/* 8146/*
7950 * Fork off a subshell. If we are doing job control, give the subshell its 8147 * Fork off a subshell. If we are doing job control, give the subshell its
7951 * own process group. Jp is a job structure that the job is to be added to. 8148 * own process group. Jp is a job structure that the job is to be added to.
@@ -7962,7 +8159,8 @@ growjobtab(void)
7962 * 8159 *
7963 * Called with interrupts off. 8160 * Called with interrupts off.
7964 */ 8161 */
7965static void forkchild(struct job *jp, union node *n, int mode) 8162static void
8163forkchild(struct job *jp, union node *n, int mode)
7966{ 8164{
7967 int oldlvl; 8165 int oldlvl;
7968 8166
@@ -8009,7 +8207,8 @@ static void forkchild(struct job *jp, union node *n, int mode)
8009 jobless = 0; 8207 jobless = 0;
8010} 8208}
8011 8209
8012static void forkparent(struct job *jp, union node *n, int mode, pid_t pid) 8210static void
8211forkparent(struct job *jp, union node *n, int mode, pid_t pid)
8013{ 8212{
8014 TRACE(("In parent shell: child = %d\n", pid)); 8213 TRACE(("In parent shell: child = %d\n", pid));
8015 if (!jp) { 8214 if (!jp) {
@@ -8065,7 +8264,6 @@ forkshell(struct job *jp, union node *n, int mode)
8065 return pid; 8264 return pid;
8066} 8265}
8067 8266
8068
8069/* 8267/*
8070 * Wait for job to finish. 8268 * Wait for job to finish.
8071 * 8269 *
@@ -8116,144 +8314,10 @@ waitforjob(struct job *jp)
8116 return st; 8314 return st;
8117} 8315}
8118 8316
8119
8120/*
8121 * Do a wait system call. If job control is compiled in, we accept
8122 * stopped processes. If block is zero, we return a value of zero
8123 * rather than blocking.
8124 *
8125 * System V doesn't have a non-blocking wait system call. It does
8126 * have a SIGCLD signal that is sent to a process when one of it's
8127 * children dies. The obvious way to use SIGCLD would be to install
8128 * a handler for SIGCLD which simply bumped a counter when a SIGCLD
8129 * was received, and have waitproc bump another counter when it got
8130 * the status of a process. Waitproc would then know that a wait
8131 * system call would not block if the two counters were different.
8132 * This approach doesn't work because if a process has children that
8133 * have not been waited for, System V will send it a SIGCLD when it
8134 * installs a signal handler for SIGCLD. What this means is that when
8135 * a child exits, the shell will be sent SIGCLD signals continuously
8136 * until is runs out of stack space, unless it does a wait call before
8137 * restoring the signal handler. The code below takes advantage of
8138 * this (mis)feature by installing a signal handler for SIGCLD and
8139 * then checking to see whether it was called. If there are any
8140 * children to be waited for, it will be.
8141 *
8142 * If neither SYSV nor BSD is defined, we don't implement nonblocking
8143 * waits at all. In this case, the user will not be informed when
8144 * a background process until the next time she runs a real program
8145 * (as opposed to running a builtin command or just typing return),
8146 * and the jobs command may give out of date information.
8147 */
8148static int
8149waitproc(int block, int *status)
8150{
8151 int flags = 0;
8152
8153#if JOBS
8154 if (jobctl)
8155 flags |= WUNTRACED;
8156#endif
8157 if (block == 0)
8158 flags |= WNOHANG;
8159 return wait3(status, flags, (struct rusage *)NULL);
8160}
8161
8162
8163/*
8164 * Wait for a process to terminate.
8165 */
8166static int
8167dowait(int block, struct job *job)
8168{
8169 int pid;
8170 int status;
8171 struct job *jp;
8172 struct job *thisjob;
8173 int state;
8174
8175 TRACE(("dowait(%d) called\n", block));
8176 pid = waitproc(block, &status);
8177 TRACE(("wait returns pid %d, status=%d\n", pid, status));
8178 if (pid <= 0)
8179 return pid;
8180 INT_OFF;
8181 thisjob = NULL;
8182 for (jp = curjob; jp; jp = jp->prev_job) {
8183 struct procstat *sp;
8184 struct procstat *spend;
8185 if (jp->state == JOBDONE)
8186 continue;
8187 state = JOBDONE;
8188 spend = jp->ps + jp->nprocs;
8189 sp = jp->ps;
8190 do {
8191 if (sp->pid == pid) {
8192 TRACE(("Job %d: changing status of proc %d "
8193 "from 0x%x to 0x%x\n",
8194 jobno(jp), pid, sp->status, status));
8195 sp->status = status;
8196 thisjob = jp;
8197 }
8198 if (sp->status == -1)
8199 state = JOBRUNNING;
8200#if JOBS
8201 if (state == JOBRUNNING)
8202 continue;
8203 if (WIFSTOPPED(sp->status)) {
8204 jp->stopstatus = sp->status;
8205 state = JOBSTOPPED;
8206 }
8207#endif
8208 } while (++sp < spend);
8209 if (thisjob)
8210 goto gotjob;
8211 }
8212#if JOBS
8213 if (!WIFSTOPPED(status))
8214#endif
8215
8216 jobless--;
8217 goto out;
8218
8219 gotjob:
8220 if (state != JOBRUNNING) {
8221 thisjob->changed = 1;
8222
8223 if (thisjob->state != state) {
8224 TRACE(("Job %d: changing state from %d to %d\n",
8225 jobno(thisjob), thisjob->state, state));
8226 thisjob->state = state;
8227#if JOBS
8228 if (state == JOBSTOPPED) {
8229 set_curjob(thisjob, CUR_STOPPED);
8230 }
8231#endif
8232 }
8233 }
8234
8235 out:
8236 INT_ON;
8237
8238 if (thisjob && thisjob == job) {
8239 char s[48 + 1];
8240 int len;
8241
8242 len = sprint_status(s, status, 1);
8243 if (len) {
8244 s[len] = '\n';
8245 s[len + 1] = 0;
8246 out2str(s);
8247 }
8248 }
8249 return pid;
8250}
8251
8252
8253/* 8317/*
8254 * return 1 if there are stopped jobs, otherwise 0 8318 * return 1 if there are stopped jobs, otherwise 0
8255 */ 8319 */
8256int 8320static int
8257stoppedjobs(void) 8321stoppedjobs(void)
8258{ 8322{
8259 struct job *jp; 8323 struct job *jp;
@@ -8289,7 +8353,7 @@ commandtext(union node *n)
8289 cmdtxt(n); 8353 cmdtxt(n);
8290 name = stackblock(); 8354 name = stackblock();
8291 TRACE(("commandtext: name %p, end %p\n\t\"%s\"\n", 8355 TRACE(("commandtext: name %p, end %p\n\t\"%s\"\n",
8292 name, cmdnextc, cmdnextc)); 8356 name, cmdnextc, cmdnextc));
8293 return ckstrdup(name); 8357 return ckstrdup(name);
8294} 8358}
8295 8359
@@ -8550,57 +8614,8 @@ cmdputs(const char *s)
8550 *nextc = 0; 8614 *nextc = 0;
8551 cmdnextc = nextc; 8615 cmdnextc = nextc;
8552} 8616}
8553
8554
8555static void
8556showpipe(struct job *jp, FILE *out)
8557{
8558 struct procstat *sp;
8559 struct procstat *spend;
8560
8561 spend = jp->ps + jp->nprocs;
8562 for (sp = jp->ps + 1; sp < spend; sp++)
8563 fprintf(out, " | %s", sp->cmd);
8564 outcslow('\n', out);
8565 flush_stdout_stderr();
8566}
8567
8568static void
8569xtcsetpgrp(int fd, pid_t pgrp)
8570{
8571 if (tcsetpgrp(fd, pgrp))
8572 ash_msg_and_raise_error("Cannot set tty process group (%m)");
8573}
8574#endif /* JOBS */ 8617#endif /* JOBS */
8575 8618
8576static int
8577getstatus(struct job *job)
8578{
8579 int status;
8580 int retval;
8581
8582 status = job->ps[job->nprocs - 1].status;
8583 retval = WEXITSTATUS(status);
8584 if (!WIFEXITED(status)) {
8585#if JOBS
8586 retval = WSTOPSIG(status);
8587 if (!WIFSTOPPED(status))
8588#endif
8589 {
8590 /* XXX: limits number of signals */
8591 retval = WTERMSIG(status);
8592#if JOBS
8593 if (retval == SIGINT)
8594 job->sigint = 1;
8595#endif
8596 }
8597 retval += 128;
8598 }
8599 TRACE(("getstatus: job %d, nproc %d, status %x, retval %x\n",
8600 jobno(job), job->nprocs, status, retval));
8601 return retval;
8602}
8603
8604#if ENABLE_ASH_MAIL 8619#if ENABLE_ASH_MAIL
8605/* mail.c */ 8620/* mail.c */
8606 8621
@@ -11333,17 +11348,6 @@ redirectsafe(union node *redir, int flags)
11333 11348
11334/* trap.c */ 11349/* trap.c */
11335 11350
11336/*
11337 * Sigmode records the current value of the signal handlers for the various
11338 * modes. A value of zero means that the current handler is not known.
11339 * S_HARD_IGN indicates that the signal was ignored on entry to the shell,
11340 */
11341
11342#define S_DFL 1 /* default signal handling (SIG_DFL) */
11343#define S_CATCH 2 /* signal is caught */
11344#define S_IGN 3 /* signal is ignored (SIG_IGN) */
11345#define S_HARD_IGN 4 /* signal is ignored permenantly */
11346#define S_RESET 5 /* temporary - to reset a hard ignored sig */
11347 11351
11348 11352
11349/* 11353/*
@@ -11507,36 +11511,6 @@ setsignal(int signo)
11507 11511
11508 11512
11509/* 11513/*
11510 * Ignore a signal.
11511 */
11512static void
11513ignoresig(int signo)
11514{
11515 if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
11516 signal(signo, SIG_IGN);
11517 }
11518 sigmode[signo - 1] = S_HARD_IGN;
11519}
11520
11521
11522/*
11523 * Signal handler.
11524 */
11525static void
11526onsig(int signo)
11527{
11528 gotsig[signo - 1] = 1;
11529 pendingsigs = signo;
11530
11531 if (exsig || (signo == SIGINT && !trap[SIGINT])) {
11532 if (!suppressint)
11533 raise_interrupt();
11534 intpending = 1;
11535 }
11536}
11537
11538
11539/*
11540 * Called to execute a trap. Perhaps we should avoid entering new trap 11514 * Called to execute a trap. Perhaps we should avoid entering new trap
11541 * handlers while we are executing a trap handler. 11515 * handlers while we are executing a trap handler.
11542 */ 11516 */
@@ -11587,7 +11561,7 @@ setinteractive(int on)
11587#if !ENABLE_FEATURE_SH_EXTRA_QUIET 11561#if !ENABLE_FEATURE_SH_EXTRA_QUIET
11588 if (is_interactive > 1) { 11562 if (is_interactive > 1) {
11589 /* Looks like they want an interactive shell */ 11563 /* Looks like they want an interactive shell */
11590 static int do_banner; 11564 static smallint do_banner;
11591 11565
11592 if (!do_banner) { 11566 if (!do_banner) {
11593 out1fmt( 11567 out1fmt(
@@ -11596,15 +11570,16 @@ setinteractive(int on)
11596 "Enter 'help' for a list of built-in commands." 11570 "Enter 'help' for a list of built-in commands."
11597 "\n\n", 11571 "\n\n",
11598 BB_BANNER); 11572 BB_BANNER);
11599 do_banner++; 11573 do_banner = 1;
11600 } 11574 }
11601 } 11575 }
11602#endif 11576#endif
11603} 11577}
11604 11578
11605#if !ENABLE_FEATURE_SH_EXTRA_QUIET 11579#if !ENABLE_FEATURE_SH_EXTRA_QUIET
11606/*** List the available builtins ***/ 11580/*
11607 11581 * Lists available builtins
11582 */
11608static int 11583static int
11609helpcmd(int argc, char **argv) 11584helpcmd(int argc, char **argv)
11610{ 11585{
@@ -11711,7 +11686,8 @@ exportcmd(int argc, char **argv)
11711 * will be restored when the shell function returns. We handle the name 11686 * will be restored when the shell function returns. We handle the name
11712 * "-" as a special case. 11687 * "-" as a special case.
11713 */ 11688 */
11714static void mklocal(char *name) 11689static void
11690mklocal(char *name)
11715{ 11691{
11716 struct localvar *lvp; 11692 struct localvar *lvp;
11717 struct var **vpp; 11693 struct var **vpp;
@@ -11811,9 +11787,10 @@ static const unsigned char timescmd_str[] = {
11811 0 11787 0
11812}; 11788};
11813 11789
11814static int timescmd(int ac, char **av) 11790static int
11791timescmd(int ac, char **av)
11815{ 11792{
11816 long int clk_tck, s, t; 11793 long clk_tck, s, t;
11817 const unsigned char *p; 11794 const unsigned char *p;
11818 struct tms buf; 11795 struct tms buf;
11819 11796
@@ -11845,12 +11822,11 @@ dash_arith(const char *s)
11845 if (errcode < 0) { 11822 if (errcode < 0) {
11846 if (errcode == -3) 11823 if (errcode == -3)
11847 ash_msg_and_raise_error("exponent less than 0"); 11824 ash_msg_and_raise_error("exponent less than 0");
11848 else if (errcode == -2) 11825 if (errcode == -2)
11849 ash_msg_and_raise_error("divide by zero"); 11826 ash_msg_and_raise_error("divide by zero");
11850 else if (errcode == -5) 11827 if (errcode == -5)
11851 ash_msg_and_raise_error("expression recursion loop detected"); 11828 ash_msg_and_raise_error("expression recursion loop detected");
11852 else 11829 raise_error_syntax(s);
11853 raise_error_syntax(s);
11854 } 11830 }
11855 INT_ON; 11831 INT_ON;
11856 11832
@@ -12083,7 +12059,8 @@ readcmd(int argc, char **argv)
12083} 12059}
12084 12060
12085 12061
12086static int umaskcmd(int argc, char **argv) 12062static int
12063umaskcmd(int argc, char **argv)
12087{ 12064{
12088 static const char permuser[3] = "ugo"; 12065 static const char permuser[3] = "ugo";
12089 static const char permmode[3] = "rwx"; 12066 static const char permmode[3] = "rwx";
@@ -12201,12 +12178,13 @@ static const struct limits limits[] = {
12201#ifdef RLIMIT_LOCKS 12178#ifdef RLIMIT_LOCKS
12202 { "locks", RLIMIT_LOCKS, 1, 'w' }, 12179 { "locks", RLIMIT_LOCKS, 1, 'w' },
12203#endif 12180#endif
12204 { (char *) 0, 0, 0, '\0' } 12181 { NULL, 0, 0, '\0' }
12205}; 12182};
12206 12183
12207enum limtype { SOFT = 0x1, HARD = 0x2 }; 12184enum limtype { SOFT = 0x1, HARD = 0x2 };
12208 12185
12209static void printlim(enum limtype how, const struct rlimit *limit, 12186static void
12187printlim(enum limtype how, const struct rlimit *limit,
12210 const struct limits *l) 12188 const struct limits *l)
12211{ 12189{
12212 rlim_t val; 12190 rlim_t val;
@@ -12223,16 +12201,16 @@ static void printlim(enum limtype how, const struct rlimit *limit,
12223 } 12201 }
12224} 12202}
12225 12203
12226int 12204static int
12227ulimitcmd(int argc, char **argv) 12205ulimitcmd(int argc, char **argv)
12228{ 12206{
12229 int c; 12207 int c;
12230 rlim_t val = 0; 12208 rlim_t val = 0;
12231 enum limtype how = SOFT | HARD; 12209 enum limtype how = SOFT | HARD;
12232 const struct limits *l; 12210 const struct limits *l;
12233 int set, all = 0; 12211 int set, all = 0;
12234 int optc, what; 12212 int optc, what;
12235 struct rlimit limit; 12213 struct rlimit limit;
12236 12214
12237 what = 'f'; 12215 what = 'f';
12238 while ((optc = nextopt("HSa" 12216 while ((optc = nextopt("HSa"
@@ -12428,11 +12406,9 @@ ulimitcmd(int argc, char **argv)
12428 * - always use special isspace(), see comment from bash ;-) 12406 * - always use special isspace(), see comment from bash ;-)
12429 */ 12407 */
12430 12408
12431
12432#define arith_isspace(arithval) \ 12409#define arith_isspace(arithval) \
12433 (arithval == ' ' || arithval == '\n' || arithval == '\t') 12410 (arithval == ' ' || arithval == '\n' || arithval == '\t')
12434 12411
12435
12436typedef unsigned char operator; 12412typedef unsigned char operator;
12437 12413
12438/* An operator's token id is a bit of a bitfield. The lower 5 bits are the 12414/* 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;
12524 12500
12525#define NUMPTR (*numstackptr) 12501#define NUMPTR (*numstackptr)
12526 12502
12527static int tok_have_assign(operator op) 12503static int
12504tok_have_assign(operator op)
12528{ 12505{
12529 operator prec = PREC(op); 12506 operator prec = PREC(op);
12530 12507
@@ -12533,13 +12510,13 @@ static int tok_have_assign(operator op)
12533 prec == PREC_PRE || prec == PREC_POST); 12510 prec == PREC_PRE || prec == PREC_POST);
12534} 12511}
12535 12512
12536static int is_right_associativity(operator prec) 12513static int
12514is_right_associativity(operator prec)
12537{ 12515{
12538 return (prec == PREC(TOK_ASSIGN) || prec == PREC(TOK_EXPONENT) 12516 return (prec == PREC(TOK_ASSIGN) || prec == PREC(TOK_EXPONENT)
12539 || prec == PREC(TOK_CONDITIONAL)); 12517 || prec == PREC(TOK_CONDITIONAL));
12540} 12518}
12541 12519
12542
12543typedef struct ARITCH_VAR_NUM { 12520typedef struct ARITCH_VAR_NUM {
12544 arith_t val; 12521 arith_t val;
12545 arith_t contidional_second_val; 12522 arith_t contidional_second_val;
@@ -12548,7 +12525,6 @@ typedef struct ARITCH_VAR_NUM {
12548 else is variable name */ 12525 else is variable name */
12549} v_n_t; 12526} v_n_t;
12550 12527
12551
12552typedef struct CHK_VAR_RECURSIVE_LOOPED { 12528typedef struct CHK_VAR_RECURSIVE_LOOPED {
12553 const char *var; 12529 const char *var;
12554 struct CHK_VAR_RECURSIVE_LOOPED *next; 12530 struct CHK_VAR_RECURSIVE_LOOPED *next;
@@ -12556,8 +12532,8 @@ typedef struct CHK_VAR_RECURSIVE_LOOPED {
12556 12532
12557static chk_var_recursive_looped_t *prev_chk_var_recursive; 12533static chk_var_recursive_looped_t *prev_chk_var_recursive;
12558 12534
12559 12535static int
12560static int arith_lookup_val(v_n_t *t) 12536arith_lookup_val(v_n_t *t)
12561{ 12537{
12562 if (t->var) { 12538 if (t->var) {
12563 const char * p = lookupvar(t->var); 12539 const char * p = lookupvar(t->var);
@@ -12595,7 +12571,8 @@ static int arith_lookup_val(v_n_t *t)
12595/* "applying" a token means performing it on the top elements on the integer 12571/* "applying" a token means performing it on the top elements on the integer
12596 * stack. For a unary operator it will only change the top element, but a 12572 * stack. For a unary operator it will only change the top element, but a
12597 * binary operator will pop two arguments and push a result */ 12573 * binary operator will pop two arguments and push a result */
12598static int arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr) 12574static int
12575arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
12599{ 12576{
12600 v_n_t *numptr_m1; 12577 v_n_t *numptr_m1;
12601 arith_t numptr_val, rez; 12578 arith_t numptr_val, rez;
@@ -12692,12 +12669,10 @@ static int arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
12692 } 12669 }
12693 numptr_m1->contidional_second_val_initialized = op; 12670 numptr_m1->contidional_second_val_initialized = op;
12694 numptr_m1->contidional_second_val = numptr_val; 12671 numptr_m1->contidional_second_val = numptr_val;
12695 } 12672 } else if (op == TOK_CONDITIONAL) {
12696 else if (op == TOK_CONDITIONAL) {
12697 rez = rez ? 12673 rez = rez ?
12698 numptr_val : numptr_m1->contidional_second_val; 12674 numptr_val : numptr_m1->contidional_second_val;
12699 } 12675 } else if (op == TOK_EXPONENT) {
12700 else if (op == TOK_EXPONENT) {
12701 if (numptr_val < 0) 12676 if (numptr_val < 0)
12702 return -3; /* exponent less than 0 */ 12677 return -3; /* exponent less than 0 */
12703 else { 12678 else {
@@ -12708,8 +12683,7 @@ static int arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
12708 c *= rez; 12683 c *= rez;
12709 rez = c; 12684 rez = c;
12710 } 12685 }
12711 } 12686 } else if (numptr_val==0) /* zero divisor check */
12712 else if (numptr_val==0) /* zero divisor check */
12713 return -2; 12687 return -2;
12714 else if (op == TOK_DIV || op == TOK_DIV_ASSIGN) 12688 else if (op == TOK_DIV || op == TOK_DIV_ASSIGN)
12715 rez /= numptr_val; 12689 rez /= numptr_val;
@@ -12717,7 +12691,7 @@ static int arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
12717 rez %= numptr_val; 12691 rez %= numptr_val;
12718 } 12692 }
12719 if (tok_have_assign(op)) { 12693 if (tok_have_assign(op)) {
12720 char buf[32]; 12694 char buf[sizeof(arith_t_type)*3 + 2];
12721 12695
12722 if (numptr_m1->var == NULL) { 12696 if (numptr_m1->var == NULL) {
12723 /* Hmm, 1=2 ? */ 12697 /* Hmm, 1=2 ? */
@@ -12725,9 +12699,9 @@ static int arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
12725 } 12699 }
12726 /* save to shell variable */ 12700 /* save to shell variable */
12727#if ENABLE_ASH_MATH_SUPPORT_64 12701#if ENABLE_ASH_MATH_SUPPORT_64
12728 snprintf(buf, sizeof(buf), "%lld", arith_t_type rez); 12702 snprintf(buf, sizeof(buf), "%lld", (arith_t_type) rez);
12729#else 12703#else
12730 snprintf(buf, sizeof(buf), "%ld", arith_t_type rez); 12704 snprintf(buf, sizeof(buf), "%ld", (arith_t_type) rez);
12731#endif 12705#endif
12732 setvar(numptr_m1->var, buf, 0); 12706 setvar(numptr_m1->var, buf, 0);
12733 /* after saving, make previous value for v++ or v-- */ 12707 /* 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)
12744 return -1; 12718 return -1;
12745} 12719}
12746 12720
12747/* longest must first */ 12721/* longest must be first */
12748static const char op_tokens[] = { 12722static const char op_tokens[] = {
12749 '<','<','=',0, TOK_LSHIFT_ASSIGN, 12723 '<','<','=',0, TOK_LSHIFT_ASSIGN,
12750 '>','>','=',0, TOK_RSHIFT_ASSIGN, 12724 '>','>','=',0, TOK_RSHIFT_ASSIGN,
@@ -12792,7 +12766,8 @@ static const char op_tokens[] = {
12792#define endexpression &op_tokens[sizeof(op_tokens)-7] 12766#define endexpression &op_tokens[sizeof(op_tokens)-7]
12793 12767
12794 12768
12795static arith_t arith(const char *expr, int *perrcode) 12769static arith_t
12770arith(const char *expr, int *perrcode)
12796{ 12771{
12797 char arithval; /* Current character under analysis */ 12772 char arithval; /* Current character under analysis */
12798 operator lasttok, op; 12773 operator lasttok, op;
@@ -12990,8 +12965,8 @@ static arith_t arith(const char *expr, int *perrcode)
12990 * exception occurs. When an exception occurs the variable "state" 12965 * exception occurs. When an exception occurs the variable "state"
12991 * is used to figure out how far we had gotten. 12966 * is used to figure out how far we had gotten.
12992 */ 12967 */
12993 12968static void
12994static void init(void) 12969init(void)
12995{ 12970{
12996 /* from input.c: */ 12971 /* from input.c: */
12997 basepf.nextc = basepf.buf = basebuf; 12972 basepf.nextc = basepf.buf = basebuf;
@@ -13002,7 +12977,7 @@ static void init(void)
13002 /* from var.c: */ 12977 /* from var.c: */
13003 { 12978 {
13004 char **envp; 12979 char **envp;
13005 char ppid[32]; 12980 char ppid[sizeof(int)*3 + 1];
13006 const char *p; 12981 const char *p;
13007 struct stat st1, st2; 12982 struct stat st1, st2;
13008 12983
@@ -13013,7 +12988,7 @@ static void init(void)
13013 } 12988 }
13014 } 12989 }
13015 12990
13016 snprintf(ppid, sizeof(ppid), "%d", (int) getppid()); 12991 snprintf(ppid, sizeof(ppid), "%u", (unsigned) getppid());
13017 setvar("PPID", ppid, 0); 12992 setvar("PPID", ppid, 0);
13018 12993
13019 p = lookupvar("PWD"); 12994 p = lookupvar("PWD");