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 "common.h"
2
 
3
/* make a stream to a child process */
4
extern stream *
5
instream(void)
6
{
7
	stream *rv;
8
	int pfd[2];
9
 
10
	if ((rv = (stream *)malloc(sizeof(stream))) == 0)
11
		return 0;
12
	memset(rv, 0, sizeof(stream));
13
	if (pipe(pfd) < 0)
14
		return 0;
15
	if(Binit(&rv->bb, pfd[1], OWRITE) < 0){
16
		close(pfd[0]);
17
		close(pfd[1]);
18
		return 0;
19
	}
20
	rv->fp = &rv->bb;
21
	rv->fd = pfd[0];	
22
	return rv;
23
}
24
 
25
/* make a stream from a child process */
26
extern stream *
27
outstream(void)
28
{
29
	stream *rv;
30
	int pfd[2];
31
 
32
	if ((rv = (stream *)malloc(sizeof(stream))) == 0)
33
		return 0;
34
	memset(rv, 0, sizeof(stream));
35
	if (pipe(pfd) < 0)
36
		return 0;
37
	if (Binit(&rv->bb, pfd[0], OREAD) < 0){
38
		close(pfd[0]);
39
		close(pfd[1]);
40
		return 0;
41
	}
42
	rv->fp = &rv->bb;
43
	rv->fd = pfd[1];
44
	return rv;
45
}
46
 
47
extern void
48
stream_free(stream *sp)
49
{
50
	int fd;
51
 
52
	close(sp->fd);
53
	fd = Bfildes(sp->fp);
54
	Bterm(sp->fp);
55
	close(fd);
56
	free((char *)sp);
57
}
58
 
59
/* start a new process */
60
extern process *
61
noshell_proc_start(char **av, stream *inp, stream *outp, stream *errp, int newpg, char *who)
62
{
63
	process *pp;
64
	int i, n;
65
 
66
	if ((pp = (process *)malloc(sizeof(process))) == 0) {
67
		if (inp != 0)
68
			stream_free(inp);
69
		if (outp != 0)
70
			stream_free(outp);
71
		if (errp != 0)
72
			stream_free(errp);
73
		return 0;
74
	}
75
	pp->std[0] = inp;
76
	pp->std[1] = outp;
77
	pp->std[2] = errp;
78
	switch (pp->pid = fork()) {
79
	case -1:
80
		proc_free(pp);
81
		return 0;
82
	case 0:
83
		if(newpg)
84
			sysdetach();
85
		for (i=0; i<3; i++)
86
			if (pp->std[i] != 0){
87
				close(Bfildes(pp->std[i]->fp));
88
				while(pp->std[i]->fd < 3)
89
					pp->std[i]->fd = dup(pp->std[i]->fd, -1);
90
			}
91
		for (i=0; i<3; i++)
92
			if (pp->std[i] != 0)
93
				dup(pp->std[i]->fd, i);
94
		for (n = sysfiles(); i < n; i++)
95
			close(i);
96
		if(who)
97
			become(av, who);
98
		exec(av[0], av);
99
		perror("proc_start");
100
		exits("proc_start");
101
	default:
102
		for (i=0; i<3; i++)
103
			if (pp->std[i] != 0) {
104
				close(pp->std[i]->fd);
105
				pp->std[i]->fd = -1;
106
			}
107
		return pp;
108
	}
109
}
110
 
111
/* start a new process under a shell */
112
extern process *
113
proc_start(char *cmd, stream *inp, stream *outp, stream *errp, int newpg, char *who)
114
{
115
	char *av[4];
116
 
117
	av[0] = SHELL;
118
	av[1] = "-c";
119
	av[2] = cmd;
120
	av[3] = 0;
121
	return noshell_proc_start(av, inp, outp, errp, newpg, who);
122
}
123
 
124
/* wait for a process to stop */
125
extern int
126
proc_wait(process *pp)
127
{
128
	Waitmsg *status;
129
	char err[Errlen];
130
 
131
	for(;;){
132
		status = wait();
133
		if(status == nil){
134
			rerrstr(err, sizeof(err));
135
			if(strstr(err, "interrupt") == 0)
136
				break;
137
		}
138
		if (status->pid==pp->pid)
139
			break;
140
	}
141
	pp->pid = -1;
142
	if(status == nil)
143
		pp->status = -1;
144
	else
145
		pp->status = status->msg[0];
146
	pp->waitmsg = status;
147
	return pp->status;
148
}
149
 
150
/* free a process */
151
extern int
152
proc_free(process *pp)
153
{
154
	int i;
155
 
156
	if(pp->std[1] == pp->std[2])
157
		pp->std[2] = 0;		/* avoid freeing it twice */
158
	for (i = 0; i < 3; i++)
159
		if (pp->std[i])
160
			stream_free(pp->std[i]);
161
	if (pp->pid >= 0)
162
		proc_wait(pp);
163
	free(pp->waitmsg);
164
	free((char *)pp);
165
	return 0;
166
}
167
 
168
/* kill a process */
169
extern int
170
proc_kill(process *pp)
171
{
172
	return syskill(pp->pid);
173
}