From 5c67e3ed90f559b61b02aa013ad4dd7d57fce772 Mon Sep 17 00:00:00 2001
From: Denis Vlasenko <vda.linux@googlemail.com>
Date: Fri, 23 Feb 2007 01:05:03 +0000
Subject: ash: cleanup part 5

---
 shell/ash.c | 959 +++++++++++++++++++++++++++++-------------------------------
 1 file changed, 467 insertions(+), 492 deletions(-)

(limited to 'shell')

diff --git a/shell/ash.c b/shell/ash.c
index 7ffecf43d..54fc8ea48 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -174,6 +174,18 @@ static int exsig;
 /* last pending signal */
 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
@@ -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 */
 
 
 /*
@@ -11506,36 +11510,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");
-- 
cgit v1.2.3