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 "defs.h"
2
#include <sys/wait.h>
3
#include <sys/stat.h>
4
#include <fcntl.h>
5
#include <errno.h>
6
 
7
static int	metas(char *);
8
static int	waitproc(int *);
9
static int	doshell(char *, int);
10
static int	doexec(char *);
11
 
12
int
13
dosys(char *comstring, int nohalt, int nowait, char *prefix)
14
{
15
int status;
16
struct process *procp;
17
 
18
/* make sure there is room in the process stack */
19
if(nproc >= MAXPROC)
20
	waitstack(MAXPROC-1);
21
 
22
/* make sure fewer than proclimit processes are running */
23
while(proclive >= proclimit)
24
	{
25
	enbint(SIG_IGN);
26
	waitproc(&status);
27
	enbint(intrupt);
28
	}
29
 
30
if(prefix)
31
	{
32
	fputs(prefix, stdout);
33
	fputs(comstring, stdout);
34
	}
35
 
36
procp = procstack + nproc;
37
procp->pid = (forceshell || metas(comstring) ) ?
38
	doshell(comstring,nohalt) : doexec(comstring);
39
if(procp->pid == -1)
40
	fatal("fork failed");
41
procstack[nproc].nohalt = nohalt;
42
procstack[nproc].nowait = nowait;
43
procstack[nproc].done = NO;
44
++proclive;
45
++nproc;
46
 
47
if(nowait)
48
	{
49
	printf(" &%d\n", procp->pid);
50
	fflush(stdout);
51
	return 0;
52
	}
53
if(prefix)
54
	{
55
	putchar('\n');
56
	fflush(stdout);
57
	}
58
return waitstack(nproc-1);
59
}
60
 
61
static int
62
metas(char *s)   /* Are there are any  Shell meta-characters? */
63
{
64
char c;
65
 
66
while( (funny[c = *s++] & META) == 0 )
67
	;
68
return( c );
69
}
70
 
71
static void
72
doclose(void)	/* Close open directory files before exec'ing */
73
{
74
struct dirhd *od;
75
 
76
for (od = firstod; od; od = od->nxtdirhd)
77
	if(od->dirfc)
78
		closedir(od->dirfc);
79
}
80
 
81
/*  wait till none of the processes in the stack starting at k is live */
82
int
83
waitstack(int k)
84
{
85
int npending, status, totstatus;
86
int i;
87
 
88
totstatus = 0;
89
npending = 0;
90
for(i=k ; i<nproc; ++i)
91
	if(! procstack[i].done)
92
		++npending;
93
enbint(SIG_IGN);
94
if(dbgflag > 1)
95
	printf("waitstack(%d)\n", k);
96
 
97
while(npending>0 && proclive>0)
98
	{
99
	if(waitproc(&status) >= k)
100
		--npending;
101
	totstatus |= status;
102
	}
103
 
104
if(nproc > k)
105
	nproc = k;
106
enbint(intrupt);
107
return totstatus;
108
}
109
 
110
static int
111
waitproc(int *statp)
112
{
113
pid_t pid;
114
int status;
115
int i;
116
struct process *procp;
117
char junk[50];
118
static int inwait = NO;
119
 
120
if(inwait)	/* avoid infinite recursions on errors */
121
	return MAXPROC;
122
inwait = YES;
123
 
124
pid = wait(&status);
125
if(dbgflag > 1)
126
	fprintf(stderr, "process %d done, status = %d\n", pid, status);
127
if(pid == -1)
128
	{
129
	if(errno == ECHILD)	/* multiple deaths, no problem */
130
		{
131
		if(proclive)
132
			{
133
			for(i=0, procp=procstack; i<nproc; ++i, ++procp)
134
				procp->done = YES;
135
			proclive = nproc = 0;
136
			}
137
		return MAXPROC;
138
		}
139
	fatal("bad wait code");
140
	}
141
for(i=0, procp=procstack; i<nproc; ++i, ++procp)
142
	if(procp->pid == pid)
143
		{
144
		--proclive;
145
		procp->done = YES;
146
 
147
		if(status)
148
			{
149
			if(procp->nowait)
150
				printf("%d: ", pid);
151
			if( WEXITSTATUS(status) )
152
				printf("*** Error code %d", WEXITSTATUS(status) );
153
			else	printf("*** Termination code %d", WTERMSIG(status));
154
 
155
			printf(procp->nohalt ? "(ignored)\n" : "\n");
156
			fflush(stdout);
157
			if(!keepgoing && !procp->nohalt)
158
				fatal(CHNULL);
159
			}
160
		*statp = status;
161
		inwait = NO;
162
		return i;
163
		}
164
 
165
sprintf(junk, "spurious return from process %d", pid);
166
fatal(junk);
167
/*NOTREACHED*/
168
return -1;
169
}
170
 
171
static int
172
doshell(char *comstring, int nohalt)
173
{
174
pid_t pid;
175
 
176
if((pid = fork()) == 0)
177
	{
178
	enbint(SIG_DFL);
179
	doclose();
180
 
181
	execl(SHELLCOM, "sh", (nohalt ? "-c" : "-ce"), comstring, NULL);
182
	fatal("Couldn't load Shell");
183
	}
184
 
185
return pid;
186
}
187
 
188
static int
189
doexec(char *str)
190
{
191
char *t, *tend;
192
char **argv;
193
char **p;
194
int nargs;
195
pid_t pid;
196
 
197
while( *str==' ' || *str=='\t' )
198
	++str;
199
if( *str == '\0' )
200
	return(-1);	/* no command */
201
 
202
nargs = 1;
203
for(t = str ; *t ; )
204
	{
205
	++nargs;
206
	while(*t!=' ' && *t!='\t' && *t!='\0')
207
		++t;
208
	if(*t)	/* replace first white space with \0, skip rest */
209
		for( *t++ = '\0' ; *t==' ' || *t=='\t'  ; ++t)
210
			;
211
	}
212
 
213
/* now allocate args array, copy pointer to start of each string,
214
   then terminate array with a null
215
*/
216
p = argv = (char **) ckalloc(nargs*sizeof(char *));
217
tend = t;
218
for(t = str ; t<tend ; )
219
	{
220
	*p++ = t;
221
	while( *t )
222
		++t;
223
	do	{
224
		++t;
225
		} while(t<tend && (*t==' ' || *t=='\t') );
226
	}
227
*p = NULL;
228
/*TEMP  for(p=argv; *p; ++p)printf("arg=%s\n", *p);*/
229
 
230
if((pid = fork()) == 0)
231
	{
232
	enbint(SIG_DFL);
233
	doclose();
234
	enbint(intrupt);
235
	execvp(str, argv);
236
	printf("\n");
237
	fatal1("Cannot load %s",str);
238
	}
239
 
240
free( (char *) argv);
241
return pid;
242
}
243
 
244
void
245
touch(int force, char *name)
246
{
247
struct stat stbuff;
248
char junk[1];
249
int fd;
250
 
251
if( stat(name,&stbuff) < 0)
252
	if(force)
253
		goto create;
254
	else
255
		{
256
		fprintf(stderr, "touch: file %s does not exist.\n", name);
257
		return;
258
		}
259
 
260
if(stbuff.st_size == 0)
261
	goto create;
262
 
263
if( (fd = open(name, O_RDWR)) < 0)
264
	goto bad;
265
 
266
if( read(fd, junk, 1) < 1)
267
	{
268
	close(fd);
269
	goto bad;
270
	}
271
lseek(fd, 0L, SEEK_SET);
272
if( write(fd, junk, 1) < 1 )
273
	{
274
	close(fd);
275
	goto bad;
276
	}
277
close(fd);
278
return;
279
 
280
bad:
281
	fprintf(stderr, "Cannot touch %s\n", name);
282
	return;
283
 
284
create:
285
	if( (fd = creat(name, 0666)) < 0)
286
		goto bad;
287
	close(fd);
288
}