BSD 3 development
[unix-history] / usr / src / cmd / csh / sh.sem.c
CommitLineData
39af1cb3
BJ
1/* Copyright (c) 1979 Regents of the University of California */
2#include "sh.h"
3
4/*
5 * C shell
6 */
7
8execute(t, pipein, pipeout)
9 register struct command *t;
10 int *pipein, *pipeout;
11{
12 int pid, flags, pv[2];
13 register struct command *t1;
14 register char *cp;
15 bool forked = 0;
16 bool shudint, shudhup;
17#ifdef VFORK
18 int (*savint)(), vffree();
19 int ochild, osetintr, ohaderr, otimflg, odidfds, odidcch;
20 int oSHIN, oSHOUT, oSHDIAG, oOLDSTD;
21 int isvfork = 0;
22#endif
23
24 if (t == 0)
25 return;
26 switch (t->t_dtyp) {
27
28 case TCOM:
29 cp = t->t_dcom[0];
30 if ((cp[0] & (QUOTE|TRIM)) == QUOTE)
31 strcpy(cp, cp + 1);
32 if ((t->t_dflg & FREDO) == 0)
33 Dfix(t); /* $ " ' \ */
34 /* fall into... */
35
36 case TPAR:
37 flags = t->t_dflg;
38 if (flags & FPOU)
39 mypipe(pipeout);
40 /*
41 * A child will be interruptible only under very
42 * certain conditions:
43 * we must be monkeying with interrupts
44 * the child must not be &'ed
45 * we must not have had an "onintr -"
46 */
47 shudint = setintr && (flags & FINT) == 0 && (!gointr || !eq(gointr, "-"));
48 shudhup = (flags & FAND) == 0;
49
50 /*
51 * Must do << early so parent will know
52 * where input pointer should be
53 */
54 if (flags & FHERE)
55 close(0), heredoc(t->t_dlef);
56
57 /*
58 * If not executing commands then
59 * all we must do is read forward in the input to
60 * account for << redirection if present.
61 */
62 if (noexec) {
63 if (flags & FHERE)
64 close(0);
65 return;
66 }
67
68 set("status", "0");
69 pid = 0;
70
71 /*
72 * Built-in functions
73 */
74 if (t->t_dtyp == TCOM && isbfunc(t->t_dcom[0])) {
75 /*
76 * If output is piped, or running & and we would
77 * eventually fork for non-builtin commands,
78 * then do it now, so we won't block.
79 */
80 if ((flags & (FPOU|FAND)) && (flags & FPAR) == 0)
81 pid = dofork(shudint, shudhup), forked++;
82
83 /*
84 * If the builtin is actually executed (some, e.g.
85 * time and nice may refuse to execute here)
86 * then either exit (if we forked) or close i/o
87 * and continue execution (if we didn't).
88 */
89 if (pid == 0) {
90 doio(t, pipein, pipeout);
91 if (flags & FPOU) {
92 close(pipeout[0]), close(pipeout[1]);
93 pipeout[0] = pipeout[1] = -1;
94 }
95 if (setintr && forked) {
96 if (shudint)
97 signal(SIGINT, SIG_DFL), signal(SIGQUIT, SIG_DFL);
98 signal(SIGTERM, parterm);
99 if (flags & FINT)
100 setintr = 0;
101 }
102 if (func(t, pipein, pipeout)) {
103 if (forked)
104 exitstat();
105 if (didfds && !(t->t_dflg & FREDO))
106 donefds();
107 return;
108 }
109 }
110 }
111
112 /*
113 * Now, we must make a new process since either the
114 * command is non-builtin, a parenthesized list,
115 * or builtin such as time or nice which really
116 * requires a child.
117 */
118 if (!forked && (flags & FPAR) == 0)
119#ifdef VFORK
120 if (t->t_dtyp == TPAR || (flags&FREDO) ||
121 eq(t->t_dcom[0], "nice") || eq(t->t_dcom[0], "nohup"))
122#endif
123 pid = dofork(shudint, shudhup);
124#ifdef VFORK
125 else {
126 savint = signal(SIGINT, SIG_IGN);
127 ochild = child; osetintr = setintr;
128 ohaderr = haderr; otimflg = timflg;
129 odidfds = didfds; odidcch = didcch;
130 oSHIN = SHIN; oSHOUT = SHOUT;
131 oSHDIAG = SHDIAG; oOLDSTD = OLDSTD;
132 Vsav = Vdp = 0; Vav = 0;
133 isvfork++;
134 pid = vfork();
135 if (pid < 0) {
136 signal(SIGINT, savint);
137 error("No more processes");
138 }
139 if (pid == 0) {
140 child++;
141 signal(SIGINT, shudint ? SIG_DFL : savint);
142 if (!shudhup)
143 signal(SIGHUP, SIG_IGN);
144 } else {
145 child = ochild; setintr = osetintr;
146 haderr = ohaderr; timflg = otimflg;
147 didfds = odidfds; didcch = odidcch;
148 SHIN = oSHIN; SHOUT = oSHOUT;
149 SHDIAG = oSHDIAG; OLDSTD = oOLDSTD;
150 xfree(Vsav), Vsav = 0;
151 xfree(Vdp), Vdp = 0;
152 xfree(Vav), Vav = 0;
153 signal(SIGINT, savint);
154 }
155 }
156#endif
157 if (pid != 0) {
158 /*
159 * The parent path (or nobody does this if
160 * (flags & FPAR), i.e. date in (set;date))
161 */
162 if (didfds == 0 && (flags & FPIN))
163 close(pipein[0]), close(pipein[1]);
164 if (didfds && !(t->t_dflg & FREDO))
165 donefds();
166 if (flags & FPRS)
167 printf("%d\n", pid), set("child", putn(pid));
168 /*
169 * Unless output is piped or command is &
170 * wait for it.
171 */
172 if (t->t_dtyp == TCOM)
173 cadd(pid, t->t_dcom[0]);
174 else
175 cadd(pid, "()");
176 if ((flags & (FPOU|FAND)) == 0)
177 pwait(pid);
178 return;
179 }
180
181 /*
182 * Insure that this (child) shell doesn't muck on
183 */
184 child++;
185
186 /*
187 * If havent yet, finally set up the file descriptors.
188 */
189 doio(t, pipein, pipeout);
190 if (flags & FPOU)
191 close(pipeout[0]), close(pipeout[1]);
192
193 /*
194 * If mucking with interrupts fix interrupt, quit,
195 * and terminate handling ... in any case set setintr
196 * to 0 if we are not interruptible so that no further
197 * interrupt mucking occurs.
198 */
199 if (setintr) {
200 if (shudint) {
201 signal(SIGQUIT, SIG_DFL);
202#ifdef VFORK
203 if (isvfork)
204 signal(SIGINT, vffree);
205 else
206#endif
207 signal(SIGINT, SIG_DFL);
208 }
209 signal(SIGTERM, parterm);
210 if (flags & FINT)
211 setintr = 0;
212 }
213
214 /*
215 * For () commands must put new 0,1,2 in FSH* and recurse
216 */
217 if (t->t_dtyp == TPAR) {
218 t1 = t->t_dspr;
219 t1->t_dflg |= flags & FINT;
220 OLDSTD = dcopy(0, FOLDSTD);
221 SHOUT = dcopy(1, FSHOUT);
222 SHDIAG = dcopy(2, FSHDIAG);
223 close(SHIN), SHIN = -1;
224 didcch = 0, didfds = 0;
225 execute(t1);
226 exitstat();
227 }
228 if (eq(t->t_dcom[0], "nice")) {
229/* sigh...
230 nice(20);
231 nice(-10);
232*/
233 cp = t->t_dcom[1];
234 if (any(cp[0], "+-"))
235 nice(getn(cp)), lshift(t->t_dcom, 2);
236 else
237 nice(4), lshift(t->t_dcom, 1);
238 t->t_dflg = FPAR | FREDO;
239 execute(t);
240 exitstat();
241 }
242 if (eq(t->t_dcom[0], "nohup")) {
243 if (setintr == 0)
244 signal(SIGHUP, SIG_IGN);
245 signal(SIGTERM, SIG_IGN);
246 lshift(t->t_dcom, 1);
247 t->t_dflg = FPAR | FREDO;
248 execute(t);
249 exitstat();
250 }
251 doexec(t);
252 /* no return */
253
254 case TFIL:
255 flags = t->t_dflg;
256 t1 = t->t_dcar;
257 t1->t_dflg |= FPOU | (flags & (FPIN|FINT|FPRS|FDIAG));
258 execute(t1, pipein, pv);
259 t1 = t->t_dcdr;
260 t1->t_dflg |= FPIN | (flags & (FPOU|FINT|FAND|FPRS|FPAR));
261 execute(t1, pv, pipeout);
262 return;
263
264 case TLST:
265 flags = t->t_dflg & FINT;
266 if (t1 = t->t_dcar)
267 t1->t_dflg |= flags, execute(t1);
268 if (t1 = t->t_dcdr)
269 t1->t_dflg |= t->t_dflg & (FINT|FPAR), execute(t1);
270 return;
271
272 case TOR:
273 case TAND:
274 flags = t->t_dflg & FINT;
275 if (t1 = t->t_dcar) {
276 t1->t_dflg |= flags, execute(t1);
277 if ((getn(value("status")) == 0) == (t->t_dtyp == TAND))
278 return;
279 }
280 if (t1 = t->t_dcdr)
281 t1->t_dflg |= t->t_dflg & (FINT|FPAR), execute(t1);
282 return;
283 }
284}
285
286#ifdef VFORK
287vffree()
288{
289 register char **v;
290
291 if (v = gargv)
292 gargv = 0, xfree(gargv);
293 if (v = pargv)
294 pargv = 0, xfree(pargv);
295 _exit(1);
296}
297#endif
298
299doio(t, pipein, pipeout)
300 register struct command *t;
301 int *pipein, *pipeout;
302{
303 register char *cp;
304 register int flags = t->t_dflg;
305 char *dp;
306
307 if (didfds || (flags & FREDO))
308 return;
309 if (flags & FHERE)
310 goto skipin;
311 close(0);
312 if (cp = t->t_dlef) {
313 cp = globone(dp = Dfix1(cp));
314 xfree(dp);
315 xfree(cp);
316 if (open(cp, 0) < 0)
317 Perror(cp);
318 } else if (flags & FPIN)
319 dup(pipein[0]), close(pipein[0]), close(pipein[1]);
320 else if (flags & FINT)
321 close(0), open("/dev/null", 0);
322 else
323 dup(OLDSTD);
324
325skipin:
326 close(1);
327 if (cp = t->t_drit) {
328 cp = globone(dp = Dfix1(cp));
329 xfree(dp);
330 xfree(cp);
331 if ((flags & FCAT) && open(cp, 1) >= 0)
332 lseek(1, 0l, 2);
333 else {
334 if (!(flags & FANY) && adrof("noclobber")) {
335 if (flags & FCAT)
336 Perror(cp);
337 chkclob(cp);
338 }
339#ifdef V6
340 if (creat(cp, 0644) < 0)
341 Perror(cp);
342#else
343 if (creat(cp, 0666) < 0)
344 Perror(cp);
345#endif
346 }
347 } else
348 dup((flags & FPOU) ? pipeout[1] : SHOUT);
349
350 close(2);
351 dup((flags & FDIAG) ? 1 : SHDIAG);
352 didfds = 1;
353}
354
355dofork(shudint, shudhup)
356 bool shudint, shudhup;
357{
358 register int pid, (*savint)();
359
360 savint = signal(SIGINT, SIG_IGN);
361 pid = fork();
362 if (pid < 0) {
363 signal(SIGINT, savint);
364 error("No more processes");
365 }
366 if (pid == 0) {
367 child++;
368 signal(SIGINT, shudint ? SIG_DFL : savint);
369 if (!shudhup)
370 signal(SIGHUP, SIG_IGN);
371 } else
372 signal(SIGINT, savint);
373 return (pid);
374}
375
376mypipe(pv)
377 register int *pv;
378{
379
380 if (pipe(pv) < 0)
381 goto oops;
382 pv[0] = dmove(pv[0], -1);
383 pv[1] = dmove(pv[1], -1);
384 if (pv[0] >= 0 && pv[1] >= 0)
385 return;
386oops:
387 error("Can't make pipe");
388}
389
390chkclob(cp)
391 register char *cp;
392{
393 struct stat stb;
394
395 if (stat(cp, &stb) < 0)
396 return;
397 if ((stb.st_mode & S_IFMT) == S_IFCHR)
398 return;
399 error("%s: File exists", cp);
400}