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