* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
#endif
#endif /* not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/bin/sh/jobs.c 328818 2018-02-02 22:53:58Z jilles $");
#include <sys/ioctl.h>
#include <sys/param.h>
#include "builtins.h"
+/*
+ * A job structure contains information about a job. A job is either a
+ * single process or a set of processes contained in a pipeline. In the
+ * latter case, pidlist will be non-NULL, and will point to a -1 terminated
+ * array of pids.
+ */
+
+struct procstat {
+ pid_t pid; /* process id */
+ int status; /* status flags (defined above) */
+ char *cmd; /* text of command being run */
+};
+
+
+/* states */
+#define JOBSTOPPED 1 /* all procs are stopped */
+#define JOBDONE 2 /* all procs are completed */
+
+
+struct job {
+ struct procstat ps0; /* status of process */
+ struct procstat *ps; /* status or processes when more than one */
+ short nprocs; /* number of processes */
+ pid_t pgrp; /* process group of this job */
+ char state; /* true if job is finished */
+ char used; /* true if this entry is in used */
+ char changed; /* true if status has changed */
+ char foreground; /* true if running in the foreground */
+ char remembered; /* true if $! referenced */
+#if JOBS
+ char jobctl; /* job running under job control */
+ struct job *next; /* job used after this one */
+#endif
+};
+
+
static struct job *jobtab; /* array of jobs */
static int njobs; /* size of array */
static pid_t backgndpid = -1; /* pid of last background process */
showjob(struct job *jp, int mode)
{
char s[64];
- char statestr[64];
- const char *sigstr;
+ char statebuf[16];
+ const char *statestr, *coredump;
struct procstat *ps;
struct job *j;
- int col, curr, i, jobno, prev, procno;
+ int col, curr, i, jobno, prev, procno, status;
char c;
procno = (mode == SHOWJOBS_PGIDS) ? 1 : jp->nprocs;
prev = j - jobtab + 1;
}
#endif
- ps = jp->ps + jp->nprocs - 1;
+ coredump = "";
+ status = jp->ps[jp->nprocs - 1].status;
if (jp->state == 0) {
- strcpy(statestr, "Running");
+ statestr = "Running";
#if JOBS
} else if (jp->state == JOBSTOPPED) {
+ ps = jp->ps + jp->nprocs - 1;
while (!WIFSTOPPED(ps->status) && ps > jp->ps)
ps--;
if (WIFSTOPPED(ps->status))
i = WSTOPSIG(ps->status);
else
i = -1;
- sigstr = strsignal(i);
- if (sigstr != NULL)
- strcpy(statestr, sigstr);
- else
- strcpy(statestr, "Suspended");
+ statestr = strsignal(i);
+ if (statestr == NULL)
+ statestr = "Suspended";
#endif
- } else if (WIFEXITED(ps->status)) {
- if (WEXITSTATUS(ps->status) == 0)
- strcpy(statestr, "Done");
- else
- fmtstr(statestr, 64, "Done(%d)",
- WEXITSTATUS(ps->status));
+ } else if (WIFEXITED(status)) {
+ if (WEXITSTATUS(status) == 0)
+ statestr = "Done";
+ else {
+ fmtstr(statebuf, sizeof(statebuf), "Done(%d)",
+ WEXITSTATUS(status));
+ statestr = statebuf;
+ }
} else {
- i = WTERMSIG(ps->status);
- sigstr = strsignal(i);
- if (sigstr != NULL)
- strcpy(statestr, sigstr);
- else
- strcpy(statestr, "Unknown signal");
- if (WCOREDUMP(ps->status))
- strcat(statestr, " (core dumped)");
+ i = WTERMSIG(status);
+ statestr = strsignal(i);
+ if (statestr == NULL)
+ statestr = "Unknown signal";
+ if (WCOREDUMP(status))
+ coredump = " (core dumped)";
}
for (ps = jp->ps ; procno > 0 ; ps++, procno--) { /* for each process */
}
if (ps == jp->ps) {
out1str(statestr);
- col += strlen(statestr);
+ out1str(coredump);
+ col += strlen(statestr) + strlen(coredump);
}
do {
out1c(' ');
*/
int
-waitforjob(struct job *jp, int *origstatus)
+waitforjob(struct job *jp, int *signaled)
{
#if JOBS
int propagate_int = jp->jobctl && jp->foreground;
setcurjob(jp);
#endif
status = jp->ps[jp->nprocs - 1].status;
- if (origstatus != NULL)
- *origstatus = status;
+ if (signaled != NULL)
+ *signaled = WIFSIGNALED(status);
/* convert to 8 bits */
if (WIFEXITED(status))
st = WEXITSTATUS(status);