Commit | Line | Data |
---|---|---|
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 | ||
8 | static int statuses[512]; | |
9 | static 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 | ||
16 | extern 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 | ||
31 | extern 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 | ||
39 | extern 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 | ||
45 | extern 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 | ||
55 | extern 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 | ||
63 | extern 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 | ||
82 | extern 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 | ||
104 | extern 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 | } |