do not lock vnode while doing VFS_STATFS
[unix-history] / usr / src / bin / csh / sem.c
CommitLineData
b79f4fa9
DF
1/*
2 * Copyright (c) 1980 Regents of the University of California.
094e80ed 3 * All rights reserved. The Berkeley Software License Agreement
b79f4fa9
DF
4 * specifies the terms and conditions for redistribution.
5 */
6
35371dec 7#ifndef lint
1f7b623f 8static char *sccsid = "@(#)sem.c 5.5 (Berkeley) %G%";
094e80ed 9#endif
e0cb907a
BJ
10
11#include "sh.h"
12#include "sh.proc.h"
13#include <sys/ioctl.h>
14
15/*
16 * C shell
17 */
18
19/*VARARGS 1*/
20execute(t, wanttty, pipein, pipeout)
21 register struct command *t;
22 int wanttty, *pipein, *pipeout;
23{
24 bool forked = 0;
25 struct biltins *bifunc;
26 int pid = 0;
27 int pv[2];
28
29 if (t == 0)
30 return;
31 if ((t->t_dflg & FAND) && wanttty > 0)
32 wanttty = 0;
33 switch (t->t_dtyp) {
34
35 case TCOM:
36 if ((t->t_dcom[0][0] & (QUOTE|TRIM)) == QUOTE)
35371dec 37 (void) strcpy(t->t_dcom[0], t->t_dcom[0] + 1);
e0cb907a
BJ
38 if ((t->t_dflg & FREDO) == 0)
39 Dfix(t); /* $ " ' \ */
40 if (t->t_dcom[0] == 0)
41 return;
42 /* fall into... */
43
44 case TPAR:
45 if (t->t_dflg & FPOU)
46 mypipe(pipeout);
47 /*
48 * Must do << early so parent will know
49 * where input pointer should be.
50 * If noexec then this is all we do.
51 */
52 if (t->t_dflg & FHERE) {
35371dec 53 (void) close(0);
e0cb907a
BJ
54 heredoc(t->t_dlef);
55 if (noexec)
35371dec 56 (void) close(0);
e0cb907a
BJ
57 }
58 if (noexec)
59 break;
60
61 set("status", "0");
62
63 /*
64 * This mess is the necessary kludge to handle the prefix
65 * builtins: nice, nohup, time. These commands can also
66 * be used by themselves, and this is not handled here.
67 * This will also work when loops are parsed.
68 */
69 while (t->t_dtyp == TCOM)
70 if (eq(t->t_dcom[0], "nice"))
71 if (t->t_dcom[1])
72 if (any(t->t_dcom[1][0], "+-"))
73 if (t->t_dcom[2]) {
74 setname("nice");
75 t->t_nice = getn(t->t_dcom[1]);
76 lshift(t->t_dcom, 2);
77 t->t_dflg |= FNICE;
78 } else
79 break;
80 else {
81 t->t_nice = 4;
82 lshift(t->t_dcom, 1);
83 t->t_dflg |= FNICE;
84 }
85 else
86 break;
87 else if (eq(t->t_dcom[0], "nohup"))
88 if (t->t_dcom[1]) {
89 t->t_dflg |= FNOHUP;
90 lshift(t->t_dcom, 1);
91 } else
92 break;
93 else if (eq(t->t_dcom[0], "time"))
94 if (t->t_dcom[1]) {
95 t->t_dflg |= FTIME;
96 lshift(t->t_dcom, 1);
97 } else
98 break;
99 else
100 break;
101 /*
102 * Check if we have a builtin function and remember which one.
103 */
104 bifunc = t->t_dtyp == TCOM ? isbfunc(t) : (struct biltins *) 0;
105
106 /*
107 * We fork only if we are timed, or are not the end of
108 * a parenthesized list and not a simple builtin function.
109 * Simple meaning one that is not pipedout, niced, nohupped,
110 * or &'d.
111 * It would be nice(?) to not fork in some of these cases.
112 */
113 if (((t->t_dflg & FTIME) || (t->t_dflg & FPAR) == 0 &&
114 (!bifunc || t->t_dflg & (FPOU|FAND|FNICE|FNOHUP))))
115#ifdef VFORK
116 if (t->t_dtyp == TPAR || t->t_dflg&(FREDO|FAND) || bifunc)
117#endif
118 { forked++; pid = pfork(t, wanttty); }
119#ifdef VFORK
120 else {
121 int vffree();
35371dec 122 int ochild, osetintr, ohaderr, odidfds;
e0cb907a 123 int oSHIN, oSHOUT, oSHDIAG, oOLDSTD, otpgrp;
1f7b623f 124 long omask;
e0cb907a 125
e9c261bb
JL
126 /*
127 * Prepare for the vfork by saving everything
128 * that the child corrupts before it exec's.
129 * Note that in some signal implementations
130 * which keep the signal info in user space
131 * (e.g. Sun's) it will also be necessary to
132 * save and restore the current sigvec's for
133 * the signals the child touches before it
134 * exec's.
135 */
d33af40e 136 omask = sigblock(sigmask(SIGCHLD));
e0cb907a 137 ochild = child; osetintr = setintr;
35371dec 138 ohaderr = haderr; odidfds = didfds;
e0cb907a
BJ
139 oSHIN = SHIN; oSHOUT = SHOUT;
140 oSHDIAG = SHDIAG; oOLDSTD = OLDSTD; otpgrp = tpgrp;
141 Vsav = Vdp = 0; Vav = 0;
142 pid = vfork();
143 if (pid < 0) {
35371dec 144 (void) sigsetmask(omask);
e0cb907a
BJ
145 error("No more processes");
146 }
147 forked++;
e9c261bb 148 if (pid) { /* parent */
e0cb907a
BJ
149 child = ochild; setintr = osetintr;
150 haderr = ohaderr; didfds = odidfds;
35371dec 151 SHIN = oSHIN;
e0cb907a
BJ
152 SHOUT = oSHOUT; SHDIAG = oSHDIAG;
153 OLDSTD = oOLDSTD; tpgrp = otpgrp;
154 xfree(Vsav); Vsav = 0;
155 xfree(Vdp); Vdp = 0;
35371dec 156 xfree((char *)Vav); Vav = 0;
e0cb907a
BJ
157 /* this is from pfork() */
158 palloc(pid, t);
35371dec 159 (void) sigsetmask(omask);
e9c261bb 160 } else { /* child */
e0cb907a
BJ
161 /* this is from pfork() */
162 int pgrp;
163 bool ignint = 0;
164
165 if (setintr)
166 ignint =
167 (tpgrp == -1 && (t->t_dflg&FINT))
168 || gointr && eq(gointr, "-");
169 pgrp = pcurrjob ? pcurrjob->p_jobid : getpid();
170 child++;
171 if (setintr) {
172 setintr = 0;
ec1a81af 173#ifdef notdef
35371dec 174 (void) signal(SIGCHLD, SIG_DFL);
ec1a81af 175#endif
35371dec 176 (void) signal(SIGINT, ignint ?
d33af40e 177 SIG_IGN : vffree);
35371dec 178 (void) signal(SIGQUIT, ignint ?
d33af40e 179 SIG_IGN : SIG_DFL);
e0cb907a 180 if (wanttty >= 0) {
35371dec
EW
181 (void) signal(SIGTSTP, SIG_DFL);
182 (void) signal(SIGTTIN, SIG_DFL);
183 (void) signal(SIGTTOU, SIG_DFL);
e0cb907a 184 }
35371dec 185 (void) signal(SIGTERM, parterm);
e0cb907a 186 } else if (tpgrp == -1 && (t->t_dflg&FINT)) {
35371dec
EW
187 (void) signal(SIGINT, SIG_IGN);
188 (void) signal(SIGQUIT, SIG_IGN);
e0cb907a
BJ
189 }
190 if (wanttty > 0)
35371dec
EW
191 (void) ioctl(FSHTTY, TIOCSPGRP,
192 (char *)&pgrp);
e0cb907a 193 if (wanttty >= 0 && tpgrp >= 0)
35371dec 194 (void) setpgrp(0, pgrp);
e0cb907a
BJ
195 if (tpgrp > 0)
196 tpgrp = 0;
197 if (t->t_dflg & FNOHUP)
35371dec 198 (void) signal(SIGHUP, SIG_IGN);
e0cb907a 199 if (t->t_dflg & FNICE)
e9c261bb
JL
200 (void) setpriority(PRIO_PROCESS,
201 0, t->t_nice);
e0cb907a
BJ
202 }
203
d33af40e 204 }
e0cb907a
BJ
205#endif
206 if (pid != 0) {
207 /*
208 * It would be better if we could wait for the
209 * whole job when we knew the last process
210 * had been started. Pwait, in fact, does
211 * wait for the whole job anyway, but this test
212 * doesn't really express our intentions.
213 */
35371dec
EW
214 if (didfds==0 && t->t_dflg&FPIN) {
215 (void) close(pipein[0]);
216 (void) close(pipein[1]);
217 }
e0cb907a
BJ
218 if ((t->t_dflg & (FPOU|FAND)) == 0)
219 pwait();
220 break;
221 }
222 doio(t, pipein, pipeout);
35371dec
EW
223 if (t->t_dflg & FPOU) {
224 (void) close(pipeout[0]);
225 (void) close(pipeout[1]);
226 }
e0cb907a
BJ
227
228 /*
229 * Perform a builtin function.
230 * If we are not forked, arrange for possible stopping
231 */
232 if (bifunc) {
233 func(t, bifunc);
234 if (forked)
235 exitstat();
236 break;
237 }
238 if (t->t_dtyp != TPAR) {
239 doexec(t);
240 /*NOTREACHED*/
241 }
242 /*
243 * For () commands must put new 0,1,2 in FSH* and recurse
244 */
245 OLDSTD = dcopy(0, FOLDSTD);
246 SHOUT = dcopy(1, FSHOUT);
247 SHDIAG = dcopy(2, FSHDIAG);
35371dec
EW
248 (void) close(SHIN);
249 SHIN = -1;
250 didfds = 0;
e0cb907a
BJ
251 wanttty = -1;
252 t->t_dspr->t_dflg |= t->t_dflg & FINT;
253 execute(t->t_dspr, wanttty);
254 exitstat();
255
256 case TFIL:
257 t->t_dcar->t_dflg |= FPOU |
258 (t->t_dflg & (FPIN|FAND|FDIAG|FINT));
259 execute(t->t_dcar, wanttty, pipein, pv);
260 t->t_dcdr->t_dflg |= FPIN |
261 (t->t_dflg & (FPOU|FAND|FPAR|FINT));
262 if (wanttty > 0)
263 wanttty = 0; /* got tty already */
264 execute(t->t_dcdr, wanttty, pv, pipeout);
265 break;
266
267 case TLST:
268 if (t->t_dcar) {
269 t->t_dcar->t_dflg |= t->t_dflg & FINT;
270 execute(t->t_dcar, wanttty);
271 /*
272 * In strange case of A&B make a new job after A
273 */
274 if (t->t_dcar->t_dflg&FAND && t->t_dcdr &&
275 (t->t_dcdr->t_dflg&FAND) == 0)
276 pendjob();
277 }
278 if (t->t_dcdr) {
279 t->t_dcdr->t_dflg |= t->t_dflg & (FPAR|FINT);
280 execute(t->t_dcdr, wanttty);
281 }
282 break;
283
284 case TOR:
285 case TAND:
286 if (t->t_dcar) {
287 t->t_dcar->t_dflg |= t->t_dflg & FINT;
288 execute(t->t_dcar, wanttty);
289 if ((getn(value("status")) == 0) != (t->t_dtyp == TAND))
290 return;
291 }
292 if (t->t_dcdr) {
293 t->t_dcdr->t_dflg |= t->t_dflg & (FPAR|FINT);
294 execute(t->t_dcdr, wanttty);
295 }
296 break;
297 }
298 /*
299 * Fall through for all breaks from switch
300 *
301 * If there will be no more executions of this
302 * command, flush all file descriptors.
303 * Places that turn on the FREDO bit are responsible
304 * for doing donefds after the last re-execution
305 */
306 if (didfds && !(t->t_dflg & FREDO))
307 donefds();
308}
309
310#ifdef VFORK
311vffree()
312{
313 register char **v;
314
315 if (v = gargv)
35371dec 316 gargv = 0, xfree((char *)v);
e0cb907a 317 if (v = pargv)
35371dec 318 pargv = 0, xfree((char *)v);
e0cb907a
BJ
319 _exit(1);
320}
321#endif
322
323/*
324 * Perform io redirection.
325 * We may or maynot be forked here.
326 */
327doio(t, pipein, pipeout)
328 register struct command *t;
329 int *pipein, *pipeout;
330{
331 register char *cp;
332 register int flags = t->t_dflg;
333
334 if (didfds || (flags & FREDO))
335 return;
336 if ((flags & FHERE) == 0) { /* FHERE already done */
35371dec 337 (void) close(0);
e0cb907a
BJ
338 if (cp = t->t_dlef) {
339 cp = globone(Dfix1(cp));
340 xfree(cp);
341 if (open(cp, 0) < 0)
342 Perror(cp);
35371dec
EW
343 } else if (flags & FPIN) {
344 (void) dup(pipein[0]);
345 (void) close(pipein[0]);
346 (void) close(pipein[1]);
347 } else if ((flags & FINT) && tpgrp == -1) {
348 (void) close(0);
349 (void) open("/dev/null", 0);
350 } else
d671c35e 351 (void) dup(OLDSTD);
e0cb907a 352 }
35371dec 353 (void) close(1);
e0cb907a
BJ
354 if (cp = t->t_drit) {
355 cp = globone(Dfix1(cp));
356 xfree(cp);
357 if ((flags & FCAT) && open(cp, 1) >= 0)
35371dec 358 (void) lseek(1, (off_t)0, 2);
e0cb907a
BJ
359 else {
360 if (!(flags & FANY) && adrof("noclobber")) {
361 if (flags & FCAT)
362 Perror(cp);
363 chkclob(cp);
364 }
365 if (creat(cp, 0666) < 0)
366 Perror(cp);
367 }
368 } else if (flags & FPOU)
35371dec 369 (void) dup(pipeout[1]);
e0cb907a 370 else
d671c35e 371 (void) dup(SHOUT);
e0cb907a 372
35371dec
EW
373 (void) close(2);
374 if (flags & FDIAG)
375 (void) dup(1);
376 else
d671c35e 377 (void) dup(SHDIAG);
e0cb907a
BJ
378 didfds = 1;
379}
380
381mypipe(pv)
382 register int *pv;
383{
384
385 if (pipe(pv) < 0)
386 goto oops;
387 pv[0] = dmove(pv[0], -1);
388 pv[1] = dmove(pv[1], -1);
389 if (pv[0] >= 0 && pv[1] >= 0)
390 return;
391oops:
392 error("Can't make pipe");
393}
394
395chkclob(cp)
396 register char *cp;
397{
398 struct stat stb;
399
400 if (stat(cp, &stb) < 0)
401 return;
402 if ((stb.st_mode & S_IFMT) == S_IFCHR)
403 return;
404 error("%s: File exists", cp);
405}