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