BSD 4_4_Lite1 development
[unix-history] / usr / src / contrib / rc-1.4 / status.c
CommitLineData
9d25673b
C
1/* status.c: functions for printing fancy status messages in rc */
2
3#include "rc.h"
4#include "sigmsgs.h"
5
6/* status == the wait() value of the last command in the pipeline, or the last command */
7
8static int statuses[512];
9static int pipelength = 1;
10
11/*
12 Test to see if rc's status is true. According to td, status is true
13 if and only if every pipe-member has an exit status of zero.
14*/
15
16extern int istrue() {
17 int i;
18 for (i = 0; i < pipelength; i++)
19 if (statuses[i] != 0)
20 return FALSE;
21 return TRUE;
22}
23
24/*
25 Return the status as an integer. A status which has low-bits set is
26 a signal number, whereas a status with high bits set is a value set
27 from exit(). The presence of a signal just sets status to 1. Also,
28 a pipeline with nonzero exit statuses in it just sets status to 1.
29*/
30
31extern int getstatus() {
32 int s;
33 if (pipelength > 1)
34 return !istrue();
35 s = statuses[0];
36 return (s&0xff) ? 1 : (s >> 8) & 0xff;
37}
38
39extern void set(bool code) {
40 setstatus(-1, (!code) << 8); /* exit status 1 == 0x100 */
41}
42
43/* take a pipeline and store the exit statuses. Check to see whether any of the children dumped core */
44
45extern void setpipestatus(int stats[], int num) {
46 int i;
47 for (i = 0; i < (pipelength = num); i++) {
48 statprint(-1, stats[i]);
49 statuses[i] = stats[i];
50 }
51}
52
53/* set a simple status, as opposed to a pipeline */
54
55extern void setstatus(int pid, int i) {
56 pipelength = 1;
57 statuses[0] = i;
58 statprint(pid, i);
59}
60
61/* print a message if termination was with a signal, and if the child dumped core. exit on error if -e is set */
62
63extern void statprint(int pid, int i) {
64 if (i & 0xff) {
65 char *msg = ((i & 0x7f) < NUMOFSIGNALS ? signals[i & 0x7f].msg : "");
66 if (pid != -1)
67 fprint(2, "%d: ", pid);
68 if (i & 0x80) {
69 if (*msg == '\0')
70 fprint(2, "core dumped\n");
71 else
72 fprint(2, "%s--core dumped\n", msg);
73 } else if (*msg != '\0')
74 fprint(2, "%s\n", msg);
75 }
76 if (i != 0 && dashee && !cond)
77 rc_exit(getstatus());
78}
79
80/* prepare a list to be passed back. Used whenever $status is dereferenced */
81
82extern List *sgetstatus() {
83 List *r;
84 int i;
85 for (r = NULL, i = 0; i < pipelength; i++) {
86 List *q = nnew(List);
87 int s = statuses[i];
88 int t;
89 q->n = r;
90 r = q;
91 if ((t = s & 0x7f) != 0) {
92 const char *core = (s & 0x80) ? "+core" : "";
93 if (t < NUMOFSIGNALS && *signals[t].name != '\0')
94 r->w = nprint("%s%s", signals[t].name, core);
95 else
96 r->w = nprint("-%d%s", t, core); /* unknown signals are negated */
97 } else
98 r->w = nprint("%d", (s >> 8) & 0xff);
99 r->m = NULL;
100 }
101 return r;
102}
103
104extern void ssetstatus(char **av) {
105 int i, j, k, l;
106 bool found;
107 for (l = 0; av[l] != NULL; l++)
108 ; /* count up array length */
109 --l;
110 for (i = 0; av[i] != NULL; i++) {
111 j = a2u(av[i]);
112 if (j >= 0) {
113 statuses[l - i] = j << 8;
114 continue;
115 }
116 found = FALSE;
117 for (k = 0; k < NUMOFSIGNALS; k++) {
118 if (streq(signals[k].name, av[i])) {
119 statuses[l - i] = k;
120 found = TRUE;
121 break;
122 }
123 else {
124 size_t len = strlen(signals[k].name);
125 if (strncmp(signals[k].name, av[i], len) == 0 && streq(av[i] + len, "+core")) {
126 statuses[l - i] = k + 0x80;
127 found = TRUE;
128 break;
129 }
130 }
131 }
132 if (!found) {
133 fprint(2, "bad status\n");
134 set(FALSE);
135 return;
136 }
137 }
138 pipelength = i;
139}