1 /*
2 Plan 9 from User Space src/lib9/await.c
3 http://code.swtch.com/plan9port/src/tip/src/lib9/await.c
4
5 Copyright 2001-2007 Russ Cox. All Rights Reserved.
6 Portions Copyright 2009 The Go Authors. All Rights Reserved.
7
8 Permission is hereby granted, free of charge, to any person obtaining a copy
9 of this software and associated documentation files (the "Software"), to deal
10 in the Software without restriction, including without limitation the rights
11 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 copies of the Software, and to permit persons to whom the Software is
13 furnished to do so, subject to the following conditions:
14
15 The above copyright notice and this permission notice shall be included in
16 all copies or substantial portions of the Software.
17
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 THE SOFTWARE.
25 */
26
27 #define NOPLAN9DEFINES
28 #include <u.h>
29 #include <libc.h>
30
31 #include <signal.h>
32 #include <sys/types.h>
33 #include <sys/wait.h>
34 #include <sys/time.h>
35 #include <sys/resource.h>
36
37 #ifndef WCOREDUMP /* not on Mac OS X Tiger */
38 #define WCOREDUMP(status) 0
39 #endif
40
41 static struct {
42 int sig;
43 char *str;
44 } tab[] = {
45 SIGHUP, "hangup",
46 SIGINT, "interrupt",
47 SIGQUIT, "quit",
48 SIGILL, "sys: illegal instruction",
49 SIGTRAP, "sys: breakpoint",
50 SIGABRT, "sys: abort",
51 #ifdef SIGEMT
52 SIGEMT, "sys: emulate instruction executed",
53 #endif
54 SIGFPE, "sys: fp: trap",
55 SIGKILL, "sys: kill",
56 SIGBUS, "sys: bus error",
57 SIGSEGV, "sys: segmentation violation",
58 SIGALRM, "alarm",
59 SIGTERM, "kill",
60 SIGURG, "sys: urgent condition on socket",
61 SIGSTOP, "sys: stop",
62 SIGTSTP, "sys: tstp",
63 SIGCONT, "sys: cont",
64 SIGCHLD, "sys: child",
65 SIGTTIN, "sys: ttin",
66 SIGTTOU, "sys: ttou",
67 #ifdef SIGIO /* not on Mac OS X Tiger */
68 SIGIO, "sys: i/o possible on fd",
69 #endif
70 SIGXCPU, "sys: cpu time limit exceeded",
71 SIGXFSZ, "sys: file size limit exceeded",
72 SIGVTALRM, "sys: virtual time alarm",
73 SIGPROF, "sys: profiling timer alarm",
74 #ifdef SIGWINCH /* not on Mac OS X Tiger */
75 SIGWINCH, "sys: window size change",
76 #endif
77 #ifdef SIGINFO
78 SIGINFO, "sys: status request",
79 #endif
80 SIGUSR1, "sys: usr1",
81 SIGUSR2, "sys: usr2",
82 SIGPIPE, "sys: write on closed pipe",
83 };
84
85 char*
86 _p9sigstr(int sig, char *tmp)
87 {
88 int i;
89
90 for(i=0; i<nelem(tab); i++)
91 if(tab[i].sig == sig)
92 return tab[i].str;
93 if(tmp == nil)
94 return nil;
95 sprint(tmp, "sys: signal %d", sig);
96 return tmp;
97 }
98
99 int
100 _p9strsig(char *s)
101 {
102 int i;
103
104 for(i=0; i<nelem(tab); i++)
105 if(strcmp(s, tab[i].str) == 0)
106 return tab[i].sig;
107 return 0;
108 }
109
110 static Waitmsg*
111 _wait(int pid4, int opt)
112 {
113 int pid, status, cd;
114 struct rusage ru;
115 char tmp[64];
116 ulong u, s;
117 Waitmsg *w;
118
119 w = malloc(sizeof *w + 200);
120 if(w == nil)
121 return nil;
122 memset(w, 0, sizeof *w);
123 w->msg = (char*)&w[1];
124
125 for(;;){
126 /* On Linux, pid==-1 means anyone; on SunOS, it's pid==0. */
127 if(pid4 == -1)
128 pid = wait3(&status, opt, &ru);
129 else
130 pid = wait4(pid4, &status, opt, &ru);
131 if(pid <= 0) {
132 free(w);
133 return nil;
134 }
135 u = ru.ru_utime.tv_sec*1000+((ru.ru_utime.tv_usec+500)/1000);
136 s = ru.ru_stime.tv_sec*1000+((ru.ru_stime.tv_usec+500)/1000);
137 w->pid = pid;
138 w->time[0] = u;
139 w->time[1] = s;
140 w->time[2] = u+s;
141 if(WIFEXITED(status)){
142 if(status)
143 sprint(w->msg, "%d", status);
144 return w;
145 }
146 if(WIFSIGNALED(status)){
147 cd = WCOREDUMP(status);
148 sprint(w->msg, "signal: %s", _p9sigstr(WTERMSIG(status), tmp));
149 if(cd)
150 strcat(w->msg, " (core dumped)");
151 return w;
152 }
153 }
154 }
155
156 Waitmsg*
157 p9wait(void)
158 {
159 return _wait(-1, 0);
160 }
161
162 Waitmsg*
163 p9waitfor(int pid)
164 {
165 return _wait(pid, 0);
166 }
167
168 Waitmsg*
169 p9waitnohang(void)
170 {
171 return _wait(-1, WNOHANG);
172 }
173
174 int
175 p9waitpid(void)
176 {
177 int status;
178 return wait(&status);
179 }