xref: /plan9/sys/src/ape/lib/ap/plan9/wait.c (revision 9c74240406852a66155a96c0daa6f8bf6e19c93e)
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