13e12c5d1SDavid du Colombier #include "lib.h"
23e12c5d1SDavid du Colombier #include <stdlib.h>
33e12c5d1SDavid du Colombier #include <sys/wait.h>
4*9c742404SDavid du Colombier #include <sys/time.h>
5*9c742404SDavid du Colombier #include <sys/resource.h>
6219b2ee8SDavid du Colombier #include <sys/stat.h>
7219b2ee8SDavid du Colombier #include <unistd.h>
8*9c742404SDavid du Colombier #include <string.h>
93e12c5d1SDavid du Colombier #include <errno.h>
10219b2ee8SDavid du Colombier #include <stdio.h>
113e12c5d1SDavid du Colombier #include "sys9.h"
12*9c742404SDavid du Colombier #include "dir.h"
133e12c5d1SDavid du Colombier
147def40e1SDavid du Colombier /*
15*9c742404SDavid du Colombier * status not yet collected for processes that have exited
167def40e1SDavid du Colombier */
17*9c742404SDavid du Colombier typedef struct Waited Waited;
18*9c742404SDavid du Colombier struct Waited {
19*9c742404SDavid du Colombier Waitmsg* msg;
20*9c742404SDavid du Colombier Waited* next;
217def40e1SDavid du Colombier };
22*9c742404SDavid du Colombier static Waited *wd;
237def40e1SDavid du Colombier
247def40e1SDavid du Colombier static Waitmsg *
lookpid(int pid)25*9c742404SDavid du Colombier lookpid(int pid)
26*9c742404SDavid du Colombier {
27*9c742404SDavid du Colombier Waited **wl, *w;
287def40e1SDavid du Colombier Waitmsg *msg;
297def40e1SDavid du Colombier
30*9c742404SDavid du Colombier for(wl = &wd; (w = *wl) != nil; wl = &w->next)
31*9c742404SDavid du Colombier if(pid <= 0 || w->msg->pid == pid){
32*9c742404SDavid du Colombier msg = w->msg;
33*9c742404SDavid du Colombier *wl = w->next;
34*9c742404SDavid du Colombier free(w);
357def40e1SDavid du Colombier return msg;
367def40e1SDavid du Colombier }
377def40e1SDavid du Colombier return 0;
387def40e1SDavid du Colombier }
397def40e1SDavid du Colombier
407def40e1SDavid du Colombier static void
addpid(Waitmsg * msg)41*9c742404SDavid du Colombier addpid(Waitmsg *msg)
42*9c742404SDavid du Colombier {
43*9c742404SDavid du Colombier Waited *w;
447def40e1SDavid du Colombier
45*9c742404SDavid du Colombier w = malloc(sizeof(*w));
46*9c742404SDavid du Colombier if(w == nil){
47*9c742404SDavid du Colombier /* lost it; what can we do? */
48*9c742404SDavid du Colombier free(msg);
49*9c742404SDavid du Colombier return;
50*9c742404SDavid du Colombier }
51*9c742404SDavid du Colombier w->msg = msg;
52*9c742404SDavid du Colombier w->next = wd;
53*9c742404SDavid du Colombier wd = w;
543e12c5d1SDavid du Colombier }
553e12c5d1SDavid du Colombier
56*9c742404SDavid du Colombier static int
waitstatus(Waitmsg * w)57*9c742404SDavid du Colombier waitstatus(Waitmsg *w)
58*9c742404SDavid du Colombier {
59*9c742404SDavid du Colombier int r, t;
607def40e1SDavid du Colombier char *bp, *ep;
617def40e1SDavid du Colombier
62*9c742404SDavid du Colombier r = 0;
63*9c742404SDavid du Colombier t = 0;
649a747e4fSDavid du Colombier if(w->msg[0]){
65219b2ee8SDavid du Colombier /* message is 'prog pid:string' */
669a747e4fSDavid du Colombier bp = w->msg;
67219b2ee8SDavid du Colombier while(*bp){
68219b2ee8SDavid du Colombier if(*bp++ == ':')
69219b2ee8SDavid du Colombier break;
70219b2ee8SDavid du Colombier }
71219b2ee8SDavid du Colombier if(*bp == 0)
729a747e4fSDavid du Colombier bp = w->msg;
73219b2ee8SDavid du Colombier r = strtol(bp, &ep, 10);
743e12c5d1SDavid du Colombier if(*ep == 0){
753e12c5d1SDavid du Colombier if(r < 0 || r >= 256)
763e12c5d1SDavid du Colombier r = 1;
773e12c5d1SDavid du Colombier }else{
78219b2ee8SDavid du Colombier t = _stringsig(bp);
793e12c5d1SDavid du Colombier if(t == 0)
803e12c5d1SDavid du Colombier r = 1;
813e12c5d1SDavid du Colombier }
823e12c5d1SDavid du Colombier }
83*9c742404SDavid du Colombier return (r<<8) | t;
843e12c5d1SDavid du Colombier }
85*9c742404SDavid du Colombier
86*9c742404SDavid du Colombier static void
waitresource(struct rusage * ru,Waitmsg * w)87*9c742404SDavid du Colombier waitresource(struct rusage *ru, Waitmsg *w)
88*9c742404SDavid du Colombier {
89*9c742404SDavid du Colombier memset(ru, 0, sizeof(*ru));
90*9c742404SDavid du Colombier ru->ru_utime.tv_sec = w->time[0]/1000;
91*9c742404SDavid du Colombier ru->ru_utime.tv_usec = (w->time[0]%1000)*1000;
92*9c742404SDavid du Colombier ru->ru_stime.tv_sec = w->time[1]/1000;
93*9c742404SDavid du Colombier ru->ru_stime.tv_usec = (w->time[1]%1000)*1000;
94*9c742404SDavid du Colombier }
95*9c742404SDavid du Colombier
96*9c742404SDavid du Colombier pid_t
wait(int * status)97*9c742404SDavid du Colombier wait(int *status)
98*9c742404SDavid du Colombier {
99*9c742404SDavid du Colombier return wait4(-1, status, 0, nil);
100*9c742404SDavid du Colombier }
101*9c742404SDavid du Colombier
102*9c742404SDavid du Colombier pid_t
waitpid(pid_t wpid,int * status,int options)103*9c742404SDavid du Colombier waitpid(pid_t wpid, int *status, int options)
104*9c742404SDavid du Colombier {
105*9c742404SDavid du Colombier return wait4(wpid, status, options, nil);
106*9c742404SDavid du Colombier }
107*9c742404SDavid du Colombier
108*9c742404SDavid du Colombier pid_t
wait3(int * status,int options,struct rusage * res)109*9c742404SDavid du Colombier wait3(int *status, int options, struct rusage *res)
110*9c742404SDavid du Colombier {
111*9c742404SDavid du Colombier return wait4(-1, status, options, res);
112*9c742404SDavid du Colombier }
113*9c742404SDavid du Colombier
114*9c742404SDavid du Colombier pid_t
wait4(pid_t wpid,int * status,int options,struct rusage * res)115*9c742404SDavid du Colombier wait4(pid_t wpid, int *status, int options, struct rusage *res)
116*9c742404SDavid du Colombier {
117*9c742404SDavid du Colombier char pname[50];
118*9c742404SDavid du Colombier Dir *d;
119*9c742404SDavid du Colombier Waitmsg *w;
120*9c742404SDavid du Colombier
121*9c742404SDavid du Colombier w = lookpid(wpid);
122*9c742404SDavid du Colombier if(w == nil){
123*9c742404SDavid du Colombier if(options & WNOHANG){
124*9c742404SDavid du Colombier snprintf(pname, sizeof(pname), "/proc/%d/wait", getpid());
125*9c742404SDavid du Colombier d = _dirstat(pname);
126*9c742404SDavid du Colombier if(d != nil && d->length == 0){
127*9c742404SDavid du Colombier free(d);
128*9c742404SDavid du Colombier return 0;
129*9c742404SDavid du Colombier }
130*9c742404SDavid du Colombier free(d);
131*9c742404SDavid du Colombier }
132*9c742404SDavid du Colombier for(;;){
133*9c742404SDavid du Colombier w = _WAIT();
134*9c742404SDavid du Colombier if(w == nil){
135*9c742404SDavid du Colombier _syserrno();
136*9c742404SDavid du Colombier return -1;
137*9c742404SDavid du Colombier }
138*9c742404SDavid du Colombier if(wpid <= 0 || w->pid == wpid)
139*9c742404SDavid du Colombier break;
1407def40e1SDavid du Colombier addpid(w);
1417def40e1SDavid du Colombier }
1427def40e1SDavid du Colombier }
143*9c742404SDavid du Colombier if(res != nil)
144*9c742404SDavid du Colombier waitresource(res, w);
145*9c742404SDavid du Colombier if(status != nil)
146*9c742404SDavid du Colombier *status = waitstatus(w);
147*9c742404SDavid du Colombier wpid = w->pid;
148*9c742404SDavid du Colombier free(w);
149*9c742404SDavid du Colombier return wpid;
1503e12c5d1SDavid du Colombier }
151