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