BSD 4_4_Lite2 development
[unix-history] / usr / src / contrib / rc-1.4 / status.c
/* status.c: functions for printing fancy status messages in rc */
#include "rc.h"
#include "sigmsgs.h"
/* status == the wait() value of the last command in the pipeline, or the last command */
static int statuses[512];
static int pipelength = 1;
/*
Test to see if rc's status is true. According to td, status is true
if and only if every pipe-member has an exit status of zero.
*/
extern int istrue() {
int i;
for (i = 0; i < pipelength; i++)
if (statuses[i] != 0)
return FALSE;
return TRUE;
}
/*
Return the status as an integer. A status which has low-bits set is
a signal number, whereas a status with high bits set is a value set
from exit(). The presence of a signal just sets status to 1. Also,
a pipeline with nonzero exit statuses in it just sets status to 1.
*/
extern int getstatus() {
int s;
if (pipelength > 1)
return !istrue();
s = statuses[0];
return (s&0xff) ? 1 : (s >> 8) & 0xff;
}
extern void set(bool code) {
setstatus(-1, (!code) << 8); /* exit status 1 == 0x100 */
}
/* take a pipeline and store the exit statuses. Check to see whether any of the children dumped core */
extern void setpipestatus(int stats[], int num) {
int i;
for (i = 0; i < (pipelength = num); i++) {
statprint(-1, stats[i]);
statuses[i] = stats[i];
}
}
/* set a simple status, as opposed to a pipeline */
extern void setstatus(int pid, int i) {
pipelength = 1;
statuses[0] = i;
statprint(pid, i);
}
/* print a message if termination was with a signal, and if the child dumped core. exit on error if -e is set */
extern void statprint(int pid, int i) {
if (i & 0xff) {
char *msg = ((i & 0x7f) < NUMOFSIGNALS ? signals[i & 0x7f].msg : "");
if (pid != -1)
fprint(2, "%d: ", pid);
if (i & 0x80) {
if (*msg == '\0')
fprint(2, "core dumped\n");
else
fprint(2, "%s--core dumped\n", msg);
} else if (*msg != '\0')
fprint(2, "%s\n", msg);
}
if (i != 0 && dashee && !cond)
rc_exit(getstatus());
}
/* prepare a list to be passed back. Used whenever $status is dereferenced */
extern List *sgetstatus() {
List *r;
int i;
for (r = NULL, i = 0; i < pipelength; i++) {
List *q = nnew(List);
int s = statuses[i];
int t;
q->n = r;
r = q;
if ((t = s & 0x7f) != 0) {
const char *core = (s & 0x80) ? "+core" : "";
if (t < NUMOFSIGNALS && *signals[t].name != '\0')
r->w = nprint("%s%s", signals[t].name, core);
else
r->w = nprint("-%d%s", t, core); /* unknown signals are negated */
} else
r->w = nprint("%d", (s >> 8) & 0xff);
r->m = NULL;
}
return r;
}
extern void ssetstatus(char **av) {
int i, j, k, l;
bool found;
for (l = 0; av[l] != NULL; l++)
; /* count up array length */
--l;
for (i = 0; av[i] != NULL; i++) {
j = a2u(av[i]);
if (j >= 0) {
statuses[l - i] = j << 8;
continue;
}
found = FALSE;
for (k = 0; k < NUMOFSIGNALS; k++) {
if (streq(signals[k].name, av[i])) {
statuses[l - i] = k;
found = TRUE;
break;
}
else {
size_t len = strlen(signals[k].name);
if (strncmp(signals[k].name, av[i], len) == 0 && streq(av[i] + len, "+core")) {
statuses[l - i] = k + 0x80;
found = TRUE;
break;
}
}
}
if (!found) {
fprint(2, "bad status\n");
set(FALSE);
return;
}
}
pipelength = i;
}