xref: /plan9/sys/src/ape/cmd/make/dosys.c (revision 027288c8a8763d34db13dc89d8bcd6514dbc2163)
1219b2ee8SDavid du Colombier #include "defs.h"
2219b2ee8SDavid du Colombier #include <sys/wait.h>
3219b2ee8SDavid du Colombier #include <sys/stat.h>
4219b2ee8SDavid du Colombier #include <fcntl.h>
5219b2ee8SDavid du Colombier #include <errno.h>
6219b2ee8SDavid du Colombier 
7219b2ee8SDavid du Colombier static int	metas(char *);
8219b2ee8SDavid du Colombier static int	waitproc(int *);
9219b2ee8SDavid du Colombier static int	doshell(char *, int);
10219b2ee8SDavid du Colombier static int	doexec(char *);
11219b2ee8SDavid du Colombier 
12219b2ee8SDavid du Colombier int
dosys(char * comstring,int nohalt,int nowait,char * prefix)13219b2ee8SDavid du Colombier dosys(char *comstring, int nohalt, int nowait, char *prefix)
14219b2ee8SDavid du Colombier {
15219b2ee8SDavid du Colombier int status;
16219b2ee8SDavid du Colombier struct process *procp;
17219b2ee8SDavid du Colombier 
18219b2ee8SDavid du Colombier /* make sure there is room in the process stack */
19219b2ee8SDavid du Colombier if(nproc >= MAXPROC)
20219b2ee8SDavid du Colombier 	waitstack(MAXPROC-1);
21219b2ee8SDavid du Colombier 
22219b2ee8SDavid du Colombier /* make sure fewer than proclimit processes are running */
23219b2ee8SDavid du Colombier while(proclive >= proclimit)
24219b2ee8SDavid du Colombier 	{
25219b2ee8SDavid du Colombier 	enbint(SIG_IGN);
26219b2ee8SDavid du Colombier 	waitproc(&status);
27219b2ee8SDavid du Colombier 	enbint(intrupt);
28219b2ee8SDavid du Colombier 	}
29219b2ee8SDavid du Colombier 
30219b2ee8SDavid du Colombier if(prefix)
31219b2ee8SDavid du Colombier 	{
32219b2ee8SDavid du Colombier 	fputs(prefix, stdout);
33219b2ee8SDavid du Colombier 	fputs(comstring, stdout);
34219b2ee8SDavid du Colombier 	}
35219b2ee8SDavid du Colombier 
36219b2ee8SDavid du Colombier procp = procstack + nproc;
37219b2ee8SDavid du Colombier procp->pid = (forceshell || metas(comstring) ) ?
38219b2ee8SDavid du Colombier 	doshell(comstring,nohalt) : doexec(comstring);
39219b2ee8SDavid du Colombier if(procp->pid == -1)
40219b2ee8SDavid du Colombier 	fatal("fork failed");
41219b2ee8SDavid du Colombier procstack[nproc].nohalt = nohalt;
42219b2ee8SDavid du Colombier procstack[nproc].nowait = nowait;
43219b2ee8SDavid du Colombier procstack[nproc].done = NO;
44219b2ee8SDavid du Colombier ++proclive;
45219b2ee8SDavid du Colombier ++nproc;
46219b2ee8SDavid du Colombier 
47219b2ee8SDavid du Colombier if(nowait)
48219b2ee8SDavid du Colombier 	{
49219b2ee8SDavid du Colombier 	printf(" &%d\n", procp->pid);
50219b2ee8SDavid du Colombier 	fflush(stdout);
51219b2ee8SDavid du Colombier 	return 0;
52219b2ee8SDavid du Colombier 	}
53219b2ee8SDavid du Colombier if(prefix)
54219b2ee8SDavid du Colombier 	{
55219b2ee8SDavid du Colombier 	putchar('\n');
56219b2ee8SDavid du Colombier 	fflush(stdout);
57219b2ee8SDavid du Colombier 	}
58219b2ee8SDavid du Colombier return waitstack(nproc-1);
59219b2ee8SDavid du Colombier }
60219b2ee8SDavid du Colombier 
61219b2ee8SDavid du Colombier static int
metas(char * s)62219b2ee8SDavid du Colombier metas(char *s)   /* Are there are any  Shell meta-characters? */
63219b2ee8SDavid du Colombier {
64219b2ee8SDavid du Colombier char c;
65219b2ee8SDavid du Colombier 
66219b2ee8SDavid du Colombier while( (funny[c = *s++] & META) == 0 )
67219b2ee8SDavid du Colombier 	;
68219b2ee8SDavid du Colombier return( c );
69219b2ee8SDavid du Colombier }
70219b2ee8SDavid du Colombier 
71219b2ee8SDavid du Colombier static void
doclose(void)72219b2ee8SDavid du Colombier doclose(void)	/* Close open directory files before exec'ing */
73219b2ee8SDavid du Colombier {
74219b2ee8SDavid du Colombier struct dirhd *od;
75219b2ee8SDavid du Colombier 
76219b2ee8SDavid du Colombier for (od = firstod; od; od = od->nxtdirhd)
77219b2ee8SDavid du Colombier 	if(od->dirfc)
78219b2ee8SDavid du Colombier 		closedir(od->dirfc);
79219b2ee8SDavid du Colombier }
80219b2ee8SDavid du Colombier 
81219b2ee8SDavid du Colombier /*  wait till none of the processes in the stack starting at k is live */
82219b2ee8SDavid du Colombier int
waitstack(int k)83219b2ee8SDavid du Colombier waitstack(int k)
84219b2ee8SDavid du Colombier {
85219b2ee8SDavid du Colombier int npending, status, totstatus;
86219b2ee8SDavid du Colombier int i;
87219b2ee8SDavid du Colombier 
88219b2ee8SDavid du Colombier totstatus = 0;
89219b2ee8SDavid du Colombier npending = 0;
90219b2ee8SDavid du Colombier for(i=k ; i<nproc; ++i)
91219b2ee8SDavid du Colombier 	if(! procstack[i].done)
92219b2ee8SDavid du Colombier 		++npending;
93219b2ee8SDavid du Colombier enbint(SIG_IGN);
94219b2ee8SDavid du Colombier if(dbgflag > 1)
95219b2ee8SDavid du Colombier 	printf("waitstack(%d)\n", k);
96219b2ee8SDavid du Colombier 
97219b2ee8SDavid du Colombier while(npending>0 && proclive>0)
98219b2ee8SDavid du Colombier 	{
99219b2ee8SDavid du Colombier 	if(waitproc(&status) >= k)
100219b2ee8SDavid du Colombier 		--npending;
101219b2ee8SDavid du Colombier 	totstatus |= status;
102219b2ee8SDavid du Colombier 	}
103219b2ee8SDavid du Colombier 
104219b2ee8SDavid du Colombier if(nproc > k)
105219b2ee8SDavid du Colombier 	nproc = k;
106219b2ee8SDavid du Colombier enbint(intrupt);
107219b2ee8SDavid du Colombier return totstatus;
108219b2ee8SDavid du Colombier }
109219b2ee8SDavid du Colombier 
110219b2ee8SDavid du Colombier static int
waitproc(int * statp)111219b2ee8SDavid du Colombier waitproc(int *statp)
112219b2ee8SDavid du Colombier {
113219b2ee8SDavid du Colombier pid_t pid;
114219b2ee8SDavid du Colombier int status;
115219b2ee8SDavid du Colombier int i;
116219b2ee8SDavid du Colombier struct process *procp;
117219b2ee8SDavid du Colombier char junk[50];
118219b2ee8SDavid du Colombier static int inwait = NO;
119219b2ee8SDavid du Colombier 
120219b2ee8SDavid du Colombier if(inwait)	/* avoid infinite recursions on errors */
121219b2ee8SDavid du Colombier 	return MAXPROC;
122219b2ee8SDavid du Colombier inwait = YES;
123219b2ee8SDavid du Colombier 
124219b2ee8SDavid du Colombier pid = wait(&status);
125219b2ee8SDavid du Colombier if(dbgflag > 1)
126219b2ee8SDavid du Colombier 	fprintf(stderr, "process %d done, status = %d\n", pid, status);
127219b2ee8SDavid du Colombier if(pid == -1)
128219b2ee8SDavid du Colombier 	{
129219b2ee8SDavid du Colombier 	if(errno == ECHILD)	/* multiple deaths, no problem */
130219b2ee8SDavid du Colombier 		{
131219b2ee8SDavid du Colombier 		if(proclive)
132219b2ee8SDavid du Colombier 			{
133219b2ee8SDavid du Colombier 			for(i=0, procp=procstack; i<nproc; ++i, ++procp)
134219b2ee8SDavid du Colombier 				procp->done = YES;
135219b2ee8SDavid du Colombier 			proclive = nproc = 0;
136219b2ee8SDavid du Colombier 			}
137219b2ee8SDavid du Colombier 		return MAXPROC;
138219b2ee8SDavid du Colombier 		}
139219b2ee8SDavid du Colombier 	fatal("bad wait code");
140219b2ee8SDavid du Colombier 	}
141219b2ee8SDavid du Colombier for(i=0, procp=procstack; i<nproc; ++i, ++procp)
142219b2ee8SDavid du Colombier 	if(procp->pid == pid)
143219b2ee8SDavid du Colombier 		{
144219b2ee8SDavid du Colombier 		--proclive;
145219b2ee8SDavid du Colombier 		procp->done = YES;
146219b2ee8SDavid du Colombier 
147219b2ee8SDavid du Colombier 		if(status)
148219b2ee8SDavid du Colombier 			{
149219b2ee8SDavid du Colombier 			if(procp->nowait)
150219b2ee8SDavid du Colombier 				printf("%d: ", pid);
151219b2ee8SDavid du Colombier 			if( WEXITSTATUS(status) )
152219b2ee8SDavid du Colombier 				printf("*** Error code %d", WEXITSTATUS(status) );
153219b2ee8SDavid du Colombier 			else	printf("*** Termination code %d", WTERMSIG(status));
154219b2ee8SDavid du Colombier 
155219b2ee8SDavid du Colombier 			printf(procp->nohalt ? "(ignored)\n" : "\n");
156219b2ee8SDavid du Colombier 			fflush(stdout);
157219b2ee8SDavid du Colombier 			if(!keepgoing && !procp->nohalt)
158219b2ee8SDavid du Colombier 				fatal(CHNULL);
159219b2ee8SDavid du Colombier 			}
160219b2ee8SDavid du Colombier 		*statp = status;
161219b2ee8SDavid du Colombier 		inwait = NO;
162219b2ee8SDavid du Colombier 		return i;
163219b2ee8SDavid du Colombier 		}
164219b2ee8SDavid du Colombier 
165219b2ee8SDavid du Colombier sprintf(junk, "spurious return from process %d", pid);
166219b2ee8SDavid du Colombier fatal(junk);
167219b2ee8SDavid du Colombier /*NOTREACHED*/
168*027288c8SDavid du Colombier return -1;
169219b2ee8SDavid du Colombier }
170219b2ee8SDavid du Colombier 
171219b2ee8SDavid du Colombier static int
doshell(char * comstring,int nohalt)172219b2ee8SDavid du Colombier doshell(char *comstring, int nohalt)
173219b2ee8SDavid du Colombier {
174219b2ee8SDavid du Colombier pid_t pid;
175219b2ee8SDavid du Colombier 
176219b2ee8SDavid du Colombier if((pid = fork()) == 0)
177219b2ee8SDavid du Colombier 	{
178219b2ee8SDavid du Colombier 	enbint(SIG_DFL);
179219b2ee8SDavid du Colombier 	doclose();
180219b2ee8SDavid du Colombier 
181f19e7b74SDavid du Colombier 	execl(SHELLCOM, "sh", (nohalt ? "-c" : "-ce"), comstring, NULL);
182219b2ee8SDavid du Colombier 	fatal("Couldn't load Shell");
183219b2ee8SDavid du Colombier 	}
184219b2ee8SDavid du Colombier 
185219b2ee8SDavid du Colombier return pid;
186219b2ee8SDavid du Colombier }
187219b2ee8SDavid du Colombier 
188219b2ee8SDavid du Colombier static int
doexec(char * str)189219b2ee8SDavid du Colombier doexec(char *str)
190219b2ee8SDavid du Colombier {
191219b2ee8SDavid du Colombier char *t, *tend;
192219b2ee8SDavid du Colombier char **argv;
193219b2ee8SDavid du Colombier char **p;
194219b2ee8SDavid du Colombier int nargs;
195219b2ee8SDavid du Colombier pid_t pid;
196219b2ee8SDavid du Colombier 
197219b2ee8SDavid du Colombier while( *str==' ' || *str=='\t' )
198219b2ee8SDavid du Colombier 	++str;
199219b2ee8SDavid du Colombier if( *str == '\0' )
200219b2ee8SDavid du Colombier 	return(-1);	/* no command */
201219b2ee8SDavid du Colombier 
202219b2ee8SDavid du Colombier nargs = 1;
203219b2ee8SDavid du Colombier for(t = str ; *t ; )
204219b2ee8SDavid du Colombier 	{
205219b2ee8SDavid du Colombier 	++nargs;
206219b2ee8SDavid du Colombier 	while(*t!=' ' && *t!='\t' && *t!='\0')
207219b2ee8SDavid du Colombier 		++t;
208219b2ee8SDavid du Colombier 	if(*t)	/* replace first white space with \0, skip rest */
209219b2ee8SDavid du Colombier 		for( *t++ = '\0' ; *t==' ' || *t=='\t'  ; ++t)
210219b2ee8SDavid du Colombier 			;
211219b2ee8SDavid du Colombier 	}
212219b2ee8SDavid du Colombier 
213219b2ee8SDavid du Colombier /* now allocate args array, copy pointer to start of each string,
214219b2ee8SDavid du Colombier    then terminate array with a null
215219b2ee8SDavid du Colombier */
216219b2ee8SDavid du Colombier p = argv = (char **) ckalloc(nargs*sizeof(char *));
217219b2ee8SDavid du Colombier tend = t;
218219b2ee8SDavid du Colombier for(t = str ; t<tend ; )
219219b2ee8SDavid du Colombier 	{
220219b2ee8SDavid du Colombier 	*p++ = t;
221219b2ee8SDavid du Colombier 	while( *t )
222219b2ee8SDavid du Colombier 		++t;
223219b2ee8SDavid du Colombier 	do	{
224219b2ee8SDavid du Colombier 		++t;
225219b2ee8SDavid du Colombier 		} while(t<tend && (*t==' ' || *t=='\t') );
226219b2ee8SDavid du Colombier 	}
227219b2ee8SDavid du Colombier *p = NULL;
228219b2ee8SDavid du Colombier /*TEMP  for(p=argv; *p; ++p)printf("arg=%s\n", *p);*/
229219b2ee8SDavid du Colombier 
230219b2ee8SDavid du Colombier if((pid = fork()) == 0)
231219b2ee8SDavid du Colombier 	{
232219b2ee8SDavid du Colombier 	enbint(SIG_DFL);
233219b2ee8SDavid du Colombier 	doclose();
234219b2ee8SDavid du Colombier 	enbint(intrupt);
235219b2ee8SDavid du Colombier 	execvp(str, argv);
236219b2ee8SDavid du Colombier 	printf("\n");
237219b2ee8SDavid du Colombier 	fatal1("Cannot load %s",str);
238219b2ee8SDavid du Colombier 	}
239219b2ee8SDavid du Colombier 
240219b2ee8SDavid du Colombier free( (char *) argv);
241219b2ee8SDavid du Colombier return pid;
242219b2ee8SDavid du Colombier }
243219b2ee8SDavid du Colombier 
244219b2ee8SDavid du Colombier void
touch(int force,char * name)245219b2ee8SDavid du Colombier touch(int force, char *name)
246219b2ee8SDavid du Colombier {
247219b2ee8SDavid du Colombier struct stat stbuff;
248219b2ee8SDavid du Colombier char junk[1];
249219b2ee8SDavid du Colombier int fd;
250219b2ee8SDavid du Colombier 
251219b2ee8SDavid du Colombier if( stat(name,&stbuff) < 0)
252219b2ee8SDavid du Colombier 	if(force)
253219b2ee8SDavid du Colombier 		goto create;
254219b2ee8SDavid du Colombier 	else
255219b2ee8SDavid du Colombier 		{
256219b2ee8SDavid du Colombier 		fprintf(stderr, "touch: file %s does not exist.\n", name);
257219b2ee8SDavid du Colombier 		return;
258219b2ee8SDavid du Colombier 		}
259219b2ee8SDavid du Colombier 
260219b2ee8SDavid du Colombier if(stbuff.st_size == 0)
261219b2ee8SDavid du Colombier 	goto create;
262219b2ee8SDavid du Colombier 
263219b2ee8SDavid du Colombier if( (fd = open(name, O_RDWR)) < 0)
264219b2ee8SDavid du Colombier 	goto bad;
265219b2ee8SDavid du Colombier 
266219b2ee8SDavid du Colombier if( read(fd, junk, 1) < 1)
267219b2ee8SDavid du Colombier 	{
268219b2ee8SDavid du Colombier 	close(fd);
269219b2ee8SDavid du Colombier 	goto bad;
270219b2ee8SDavid du Colombier 	}
271219b2ee8SDavid du Colombier lseek(fd, 0L, SEEK_SET);
272219b2ee8SDavid du Colombier if( write(fd, junk, 1) < 1 )
273219b2ee8SDavid du Colombier 	{
274219b2ee8SDavid du Colombier 	close(fd);
275219b2ee8SDavid du Colombier 	goto bad;
276219b2ee8SDavid du Colombier 	}
277219b2ee8SDavid du Colombier close(fd);
278219b2ee8SDavid du Colombier return;
279219b2ee8SDavid du Colombier 
280219b2ee8SDavid du Colombier bad:
281219b2ee8SDavid du Colombier 	fprintf(stderr, "Cannot touch %s\n", name);
282219b2ee8SDavid du Colombier 	return;
283219b2ee8SDavid du Colombier 
284219b2ee8SDavid du Colombier create:
285219b2ee8SDavid du Colombier 	if( (fd = creat(name, 0666)) < 0)
286219b2ee8SDavid du Colombier 		goto bad;
287219b2ee8SDavid du Colombier 	close(fd);
288219b2ee8SDavid du Colombier }
289