Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include "lib.h"
2
#include <stdlib.h>
3
#include <sys/wait.h>
4
#include <sys/time.h>
5
#include <sys/resource.h>
6
#include <sys/stat.h>
7
#include <unistd.h>
8
#include <string.h>
9
#include <errno.h>
10
#include <stdio.h>
11
#include "sys9.h"
12
#include "dir.h"
13
 
14
/*
15
 * status not yet collected for processes that have exited
16
 */
17
typedef struct Waited Waited;
18
struct Waited {
19
	Waitmsg*	msg;
20
	Waited*	next;
21
};
22
static Waited *wd;
23
 
24
static Waitmsg *
25
lookpid(int pid)
26
{
27
	Waited **wl, *w;
28
	Waitmsg *msg;
29
 
30
	for(wl = &wd; (w = *wl) != nil; wl = &w->next)
31
		if(pid <= 0 || w->msg->pid == pid){
32
			msg = w->msg;
33
			*wl = w->next;
34
			free(w);
35
			return msg;
36
		}
37
	return 0;
38
}
39
 
40
static void
41
addpid(Waitmsg *msg)
42
{
43
	Waited *w;
44
 
45
	w = malloc(sizeof(*w));
46
	if(w == nil){
47
		/* lost it; what can we do? */
48
		free(msg);
49
		return;
50
	}
51
	w->msg = msg;
52
	w->next = wd;
53
	wd = w;
54
}
55
 
56
static int
57
waitstatus(Waitmsg *w)
58
{
59
	int r, t;
60
	char *bp, *ep;
61
 
62
	r = 0;
63
	t = 0;
64
	if(w->msg[0]){
65
		/* message is 'prog pid:string' */
66
		bp = w->msg;
67
		while(*bp){
68
			if(*bp++ == ':')
69
				break;
70
		}
71
		if(*bp == 0)
72
			bp = w->msg;
73
		r = strtol(bp, &ep, 10);
74
		if(*ep == 0){
75
			if(r < 0 || r >= 256)
76
				r = 1;
77
		}else{
78
			t = _stringsig(bp);
79
			if(t == 0)
80
				r = 1;
81
		}
82
	}
83
	return (r<<8) | t;
84
}
85
 
86
static void
87
waitresource(struct rusage *ru, Waitmsg *w)
88
{
89
	memset(ru, 0, sizeof(*ru));
90
	ru->ru_utime.tv_sec = w->time[0]/1000;
91
	ru->ru_utime.tv_usec = (w->time[0]%1000)*1000;
92
	ru->ru_stime.tv_sec = w->time[1]/1000;
93
	ru->ru_stime.tv_usec = (w->time[1]%1000)*1000;
94
}
95
 
96
pid_t
97
wait(int *status)
98
{
99
	return wait4(-1, status, 0, nil);
100
}
101
 
102
pid_t
103
waitpid(pid_t wpid, int *status, int options)
104
{
105
	return wait4(wpid, status, options, nil);
106
}
107
 
108
pid_t
109
wait3(int *status, int options, struct rusage *res)
110
{
111
	return wait4(-1, status, options, res);
112
}
113
 
114
pid_t
115
wait4(pid_t wpid, int *status, int options, struct rusage *res)
116
{
117
	char pname[50];
118
	Dir *d;
119
	Waitmsg *w;
120
 
121
	w = lookpid(wpid);
122
	if(w == nil){
123
		if(options & WNOHANG){
124
			snprintf(pname, sizeof(pname), "/proc/%d/wait", getpid());
125
			d = _dirstat(pname);
126
			if(d != nil && d->length == 0){
127
				free(d);
128
				return 0;
129
			}
130
			free(d);
131
		}
132
		for(;;){
133
			w = _WAIT();
134
			if(w == nil){
135
				_syserrno();
136
				return -1;
137
			}
138
			if(wpid <= 0 || w->pid == wpid)
139
				break;
140
			addpid(w);
141
		}
142
	}
143
	if(res != nil)
144
		waitresource(res, w);
145
	if(status != nil)
146
		*status = waitstatus(w);
147
	wpid = w->pid;
148
	free(w);
149
	return wpid;
150
}