source: trunk/third/tcsh/sh.sem.c @ 12039

Revision 12039, 24.2 KB checked in by danw, 26 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r12038, which included commits to RCS files with non-trunk default branches.
Line 
1/* $Header: /afs/dev.mit.edu/source/repository/third/tcsh/sh.sem.c,v 1.1.1.2 1998-10-03 21:10:07 danw Exp $ */
2/*
3 * sh.sem.c: I/O redirections and job forking. A touchy issue!
4 *           Most stuff with builtins is incorrect
5 */
6/*-
7 * Copyright (c) 1980, 1991 The Regents of the University of California.
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 *    must display the following acknowledgement:
20 *      This product includes software developed by the University of
21 *      California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 *    may be used to endorse or promote products derived from this software
24 *    without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 */
38#include "sh.h"
39
40RCSID("$Id: sh.sem.c,v 1.1.1.2 1998-10-03 21:10:07 danw Exp $")
41
42#include "tc.h"
43#include "tw.h"
44#ifdef WINNT
45#include "nt.const.h"
46#endif /*WINNT*/
47
48#ifdef CLOSE_ON_EXEC
49# ifndef SUNOS4
50#  ifndef CLEX_DUPS
51#   define CLEX_DUPS
52#  endif /* CLEX_DUPS */
53# endif /* !SUNOS4 */
54#endif /* CLOSE_ON_EXEC */
55
56#if defined(__sparc__) || defined(sparc)
57# if !defined(MACH) && SYSVREL == 0 && !defined(Lynx) && !defined(BSD4_4) && !defined(linux)
58#  include <vfork.h>
59# endif /* !MACH && SYSVREL == 0 && !Lynx && !BSD4_4 */
60#endif /* __sparc__ || sparc */
61
62#ifdef VFORK
63static  sigret_t        vffree  __P((int));
64#endif
65static  Char            *splicepipe     __P((struct command *, Char *));
66static  void             doio           __P((struct command *, int *, int *));
67static  void             chkclob        __P((char *));
68
69/*
70 * C shell
71 */
72
73/*
74 * For SVR4, there are problems with pipelines having the first process as
75 * the group leader.  The problem occurs when the first process exits before
76 * the others have a chance to setpgid().  This is because in SVR4 you can't
77 * have a zombie as a group leader.  The solution I have used is to reverse
78 * the order in which pipelines are started, making the last process the
79 * group leader.  (Note I am not using 'pipeline' in the generic sense -- I
80 * mean processes connected by '|'.)  I don't know yet if this causes other
81 * problems.
82 *
83 * All the changes for this are in execute(), and are enclosed in
84 * '#ifdef BACKPIPE'
85 *
86 * David Dawes (dawes@physics.su.oz.au) Oct 1991
87 */
88
89/*VARARGS 1*/
90void
91execute(t, wanttty, pipein, pipeout)
92    register struct command *t;
93    int     wanttty;
94    int *pipein, *pipeout;
95{
96#ifdef VFORK
97    extern bool use_fork;       /* use fork() instead of vfork()? */
98#endif
99
100    bool    forked = 0;
101    struct biltins *bifunc;
102    int     pid = 0;
103    int     pv[2];
104#ifdef BSDSIGS
105    static sigmask_t csigmask;
106#endif /* BSDSIGS */
107#ifdef VFORK
108    static int onosigchld = 0;
109#endif /* VFORK */
110    static int nosigchld = 0;
111
112    (void) &wanttty;
113    (void) &forked;
114    (void) &bifunc;
115
116    if (t == 0)
117        return;
118
119#ifdef WINNT
120    {
121        if ((varval(STRNTslowexec) != STRNULL) &&
122            !t->t_dcdr && !t->t_dcar && !t->t_dflg && !didfds &&
123            (intty || intact) && (t->t_dtyp == NODE_COMMAND) &&
124            !isbfunc(t)) {
125            if ((t->t_dcom[0][0] & (QUOTE | TRIM)) == QUOTE)
126                (void) Strcpy(t->t_dcom[0], t->t_dcom[0] + 1);
127            Dfix(t);
128            if (nt_try_fast_exec(t) == 0)
129                return;
130        }
131    }
132#endif /* WINNT */
133
134    /*
135     * Ed hutchins@sgi.com & Dominic dbg@sgi.com
136     * Sat Feb 25 03:13:11 PST 1995
137     * try implicit cd if we have a 1 word command
138     */
139    if (implicit_cd && (intty || intact) && t->t_dcom && t->t_dcom[0] &&
140         t->t_dcom[0][0] && (blklen(t->t_dcom) == 1) && !noexec) {
141        Char sCName[MAXPATHLEN];
142        Char *pCN;
143        struct stat stbuf;
144        char *pathname;
145
146        dollar(sCName, t->t_dcom[0]);
147        pCN = sCName;
148        if (pCN[0] == '~') {
149            Char sCPath[MAXPATHLEN];
150            Char *pCP = sCPath;
151
152            ++pCN;
153            while (*pCN && *pCN != '/')
154                *pCP++ = *pCN++;
155            *pCP = 0;
156            if (sCPath[0])
157                gethdir(sCPath);
158            else
159                (void) Strcpy(sCPath, varval(STRhome));
160            catn(sCPath, pCN, MAXPATHLEN);
161            (void) Strcpy(sCName, sCPath);
162        }
163   
164        pathname = short2str(sCName);
165        /* if this is a dir, tack a "cd" on as the first arg */
166        if ((stat(pathname, &stbuf) != -1 && S_ISDIR(stbuf.st_mode))
167#ifdef WINNT
168            || (pathname[0] && pathname[1] == ':' && pathname[2] == '\0')
169#endif /* WINNT */
170        ) {
171            Char *vCD[2];
172            Char **ot_dcom = t->t_dcom;
173       
174            vCD[0] = Strsave(STRcd);
175            vCD[1] = NULL;
176            t->t_dcom = blkspl(vCD, ot_dcom);
177            if (implicit_cd > 1) {
178                blkpr(t->t_dcom);
179                xputchar( '\n' );
180            }
181            xfree((ptr_t) ot_dcom);
182        }
183    }
184
185    /*
186     * From: Michael Schroeder <mlschroe@immd4.informatik.uni-erlangen.de>
187     * Don't check for wantty > 0...
188     */
189    if (t->t_dflg & F_AMPERSAND)
190        wanttty = 0;
191    switch (t->t_dtyp) {
192
193    case NODE_COMMAND:
194        if ((t->t_dcom[0][0] & (QUOTE | TRIM)) == QUOTE)
195            (void) Strcpy(t->t_dcom[0], t->t_dcom[0] + 1);
196        if ((t->t_dflg & F_REPEAT) == 0)
197            Dfix(t);            /* $ " ' \ */
198        if (t->t_dcom[0] == 0) {
199            return;
200        }
201        /*FALLTHROUGH*/
202
203    case NODE_PAREN:
204#ifdef BACKPIPE
205        if (t->t_dflg & F_PIPEIN)
206            mypipe(pipein);
207#else /* !BACKPIPE */
208        if (t->t_dflg & F_PIPEOUT)
209            mypipe(pipeout);
210#endif /* BACKPIPE */
211        /*
212         * Must do << early so parent will know where input pointer should be.
213         * If noexec then this is all we do.
214         */
215        if (t->t_dflg & F_READ) {
216            (void) close(0);
217            heredoc(t->t_dlef);
218            if (noexec)
219                (void) close(0);
220        }
221
222        set(STRstatus, Strsave(STR0), VAR_READWRITE);
223
224        /*
225         * This mess is the necessary kludge to handle the prefix builtins:
226         * nice, nohup, time.  These commands can also be used by themselves,
227         * and this is not handled here. This will also work when loops are
228         * parsed.
229         */
230        while (t->t_dtyp == NODE_COMMAND)
231            if (eq(t->t_dcom[0], STRnice)) {
232                if (t->t_dcom[1]) {
233                    if (strchr("+-", t->t_dcom[1][0])) {
234                        if (t->t_dcom[2]) {
235                            setname("nice");
236                            t->t_nice =
237                                getn(t->t_dcom[1]);
238                            lshift(t->t_dcom, 2);
239                            t->t_dflg |= F_NICE;
240                        }
241                        else
242                            break;
243                    }
244                    else {
245                        t->t_nice = 4;
246                        lshift(t->t_dcom, 1);
247                        t->t_dflg |= F_NICE;
248                    }
249                }
250                else
251                    break;
252            }
253            else if (eq(t->t_dcom[0], STRnohup)) {
254                if (t->t_dcom[1]) {
255                    t->t_dflg |= F_NOHUP;
256                    lshift(t->t_dcom, 1);
257                }
258                else
259                    break;
260            }
261            else if (eq(t->t_dcom[0], STRhup)) {
262                if (t->t_dcom[1]) {
263                    t->t_dflg |= F_HUP;
264                    lshift(t->t_dcom, 1);
265                }
266                else
267                    break;
268            }
269            else if (eq(t->t_dcom[0], STRtime)) {
270                if (t->t_dcom[1]) {
271                    t->t_dflg |= F_TIME;
272                    lshift(t->t_dcom, 1);
273                }
274                else
275                    break;
276            }
277#ifdef F_VER
278            else if (eq(t->t_dcom[0], STRver))
279                if (t->t_dcom[1] && t->t_dcom[2]) {
280                    setname("ver");
281                    t->t_systype = getv(t->t_dcom[1]);
282                    lshift(t->t_dcom, 2);
283                    t->t_dflg |= F_VER;
284                }
285                else
286                    break;
287#endif  /* F_VER */
288            else
289                break;
290
291        /* is it a command */
292        if (t->t_dtyp == NODE_COMMAND) {
293            /*
294             * Check if we have a builtin function and remember which one.
295             */
296            bifunc = isbfunc(t);
297            if (noexec && bifunc) {
298                /*
299                 * Continue for builtins that are part of the scripting language
300                 */
301                if (bifunc->bfunct != (bfunc_t)dobreak  &&
302                    bifunc->bfunct != (bfunc_t)docontin &&
303                    bifunc->bfunct != (bfunc_t)doelse   &&
304                    bifunc->bfunct != (bfunc_t)doend    &&
305                    bifunc->bfunct != (bfunc_t)doforeach&&
306                    bifunc->bfunct != (bfunc_t)dogoto   &&
307                    bifunc->bfunct != (bfunc_t)doif     &&
308                    bifunc->bfunct != (bfunc_t)dorepeat &&
309                    bifunc->bfunct != (bfunc_t)doswbrk  &&
310                    bifunc->bfunct != (bfunc_t)doswitch &&
311                    bifunc->bfunct != (bfunc_t)dowhile  &&
312                    bifunc->bfunct != (bfunc_t)dozip)
313                    break;
314            }
315        }
316        else {                  /* not a command */
317            bifunc = NULL;
318            if (noexec)
319                break;
320        }
321
322        /*
323         * We fork only if we are timed, or are not the end of a parenthesized
324         * list and not a simple builtin function. Simple meaning one that is
325         * not pipedout, niced, nohupped, or &'d. It would be nice(?) to not
326         * fork in some of these cases.
327         */
328        /*
329         * Prevent forking cd, pushd, popd, chdir cause this will cause the
330         * shell not to change dir!
331         */
332#ifdef BACKPIPE
333        /*
334         * Can't have NOFORK for the tail of a pipe - because it is not the
335         * last command spawned (even if it is at the end of a parenthesised
336         * list).
337         */
338        if (t->t_dflg & F_PIPEIN)
339            t->t_dflg &= ~(F_NOFORK);
340#endif /* BACKPIPE */
341        if (bifunc && (bifunc->bfunct == (bfunc_t)dochngd ||
342                       bifunc->bfunct == (bfunc_t)dopushd ||
343                       bifunc->bfunct == (bfunc_t)dopopd))
344            t->t_dflg &= ~(F_NICE);
345        if (((t->t_dflg & F_TIME) || ((t->t_dflg & F_NOFORK) == 0 &&
346             (!bifunc || t->t_dflg &
347              (F_PIPEOUT | F_AMPERSAND | F_NICE | F_NOHUP | F_HUP)))) ||
348        /*
349         * We have to fork for eval too.
350         */
351            (bifunc && (t->t_dflg & F_PIPEIN) != 0 &&
352             bifunc->bfunct == (bfunc_t)doeval))
353#ifdef VFORK
354            if (t->t_dtyp == NODE_PAREN ||
355                t->t_dflg & (F_REPEAT | F_AMPERSAND) || bifunc)
356#endif /* VFORK */
357            {
358                forked++;
359                /*
360                 * We need to block SIGCHLD here, so that if the process does
361                 * not die before we can set the process group
362                 */
363                if (wanttty >= 0 && !nosigchld) {
364#ifdef BSDSIGS
365                    csigmask = sigblock(sigmask(SIGCHLD));
366#else /* !BSDSIGS */
367                    (void) sighold(SIGCHLD);
368#endif /* BSDSIGS */
369
370                    nosigchld = 1;
371                }
372
373                pid = pfork(t, wanttty);
374                if (pid == 0 && nosigchld) {
375#ifdef BSDSIGS
376                    (void) sigsetmask(csigmask);
377#else /* !BSDSIGS */
378                    (void) sigrelse(SIGCHLD);
379#endif /* BSDSIGS */
380                    nosigchld = 0;
381                }
382                else if (pid != 0 && (t->t_dflg & F_AMPERSAND))
383                    backpid = pid;
384            }
385
386#ifdef VFORK
387            else {
388                int     ochild, osetintr, ohaderr, odidfds;
389                int     oSHIN, oSHOUT, oSHDIAG, oOLDSTD, otpgrp;
390                int     oisoutatty, oisdiagatty;
391
392# ifndef CLOSE_ON_EXEC
393                int     odidcch;
394# endif  /* !CLOSE_ON_EXEC */
395# ifdef BSDSIGS
396                sigmask_t omask, ocsigmask;
397# endif /* BSDSIGS */
398
399                /*
400                 * Prepare for the vfork by saving everything that the child
401                 * corrupts before it exec's. Note that in some signal
402                 * implementations which keep the signal info in user space
403                 * (e.g. Sun's) it will also be necessary to save and restore
404                 * the current sigvec's for the signals the child touches
405                 * before it exec's.
406                 */
407
408                /*
409                 * Sooooo true... If this is a Sun, save the sigvec's. (Skip
410                 * Gilbrech - 11/22/87)
411                 */
412# ifdef SAVESIGVEC
413                sigvec_t savesv[NSIGSAVED];
414                sigmask_t savesm;
415
416# endif /* SAVESIGVEC */
417                if (wanttty >= 0 && !nosigchld && !noexec) {
418# ifdef BSDSIGS
419                    csigmask = sigblock(sigmask(SIGCHLD));
420# else /* !BSDSIGS */
421                    (void) sighold(SIGCHLD);
422# endif  /* BSDSIGS */
423                    nosigchld = 1;
424                }
425# ifdef BSDSIGS
426                omask = sigblock(sigmask(SIGCHLD)|sigmask(SIGINT));
427# else /* !BSDSIGS */
428                (void) sighold(SIGCHLD);
429                (void) sighold(SIGINT);
430# endif  /* BSDSIGS */
431                ochild = child;
432                osetintr = setintr;
433                ohaderr = haderr;
434                odidfds = didfds;
435# ifndef CLOSE_ON_EXEC
436                odidcch = didcch;
437# endif /* !CLOSE_ON_EXEC */
438                oSHIN = SHIN;
439                oSHOUT = SHOUT;
440                oSHDIAG = SHDIAG;
441                oOLDSTD = OLDSTD;
442                otpgrp = tpgrp;
443                oisoutatty = isoutatty;
444                oisdiagatty = isdiagatty;
445# ifdef BSDSIGS
446                ocsigmask = csigmask;
447# endif /* BSDSIGS */
448                onosigchld = nosigchld;
449                Vsav = Vdp = 0;
450                Vexpath = 0;
451                Vt = 0;
452# ifdef SAVESIGVEC
453                savesm = savesigvec(savesv);
454# endif /* SAVESIGVEC */
455                if (use_fork)
456                    pid = fork();
457                else
458                    pid = vfork();
459
460                if (pid < 0) {
461# ifdef BSDSIGS
462#  ifdef SAVESIGVEC
463                    restoresigvec(savesv, savesm);
464#  endif /* SAVESIGVEC */
465                    (void) sigsetmask(omask);
466# else /* !BSDSIGS */
467                    (void) sigrelse(SIGCHLD);
468                    (void) sigrelse(SIGINT);
469# endif  /* BSDSIGS */
470                    stderror(ERR_NOPROC);
471                }
472                forked++;
473                if (pid) {      /* parent */
474# ifdef SAVESIGVEC
475                    restoresigvec(savesv, savesm);
476# endif /* SAVESIGVEC */
477                    child = ochild;
478                    setintr = osetintr;
479                    haderr = ohaderr;
480                    didfds = odidfds;
481                    SHIN = oSHIN;
482# ifndef CLOSE_ON_EXEC
483                    didcch = odidcch;
484# endif /* !CLOSE_ON_EXEC */
485                    SHOUT = oSHOUT;
486                    SHDIAG = oSHDIAG;
487                    OLDSTD = oOLDSTD;
488                    tpgrp = otpgrp;
489                    isoutatty = oisoutatty;
490                    isdiagatty = oisdiagatty;
491# ifdef BSDSIGS
492                    csigmask = ocsigmask;
493# endif /* BSDSIGS */
494                    nosigchld = onosigchld;
495
496                    xfree((ptr_t) Vsav);
497                    Vsav = 0;
498                    xfree((ptr_t) Vdp);
499                    Vdp = 0;
500                    xfree((ptr_t) Vexpath);
501                    Vexpath = 0;
502                    blkfree((Char **) Vt);
503                    Vt = 0;
504                    /* this is from pfork() */
505                    palloc(pid, t);
506# ifdef BSDSIGS
507                    (void) sigsetmask(omask);
508# else /* !BSDSIGS */
509                    (void) sigrelse(SIGCHLD);
510                    (void) sigrelse(SIGINT);
511# endif  /* BSDSIGS */
512                }
513                else {          /* child */
514                    /* this is from pfork() */
515                    int     pgrp;
516                    bool    ignint = 0;
517                    if (nosigchld) {
518# ifdef BSDSIGS
519                        (void) sigsetmask(csigmask);
520# else /* !BSDSIGS */
521                        (void) sigrelse(SIGCHLD);
522# endif /* BSDSIGS */
523                        nosigchld = 0;
524                    }
525
526                    if (setintr)
527                        ignint = (tpgrp == -1 && (t->t_dflg & F_NOINTERRUPT))
528                                || (gointr && eq(gointr, STRminus));
529                    pgrp = pcurrjob ? pcurrjob->p_jobid : getpid();
530                    child++;
531                    if (setintr) {
532                        setintr = 0;
533/*
534 * casts made right for SunOS 4.0 by Douglas C. Schmidt
535 * <schmidt%sunshine.ics.uci.edu@ROME.ICS.UCI.EDU>
536 * (thanks! -- PWP)
537 *
538 * ignint ifs cleaned by Johan Widen <mcvax!osiris.sics.se!jw@uunet.UU.NET>
539 * (thanks again)
540 */
541                        if (ignint) {
542                            (void) signal(SIGINT, SIG_IGN);
543                            (void) signal(SIGQUIT, SIG_IGN);
544                        }
545                        else {
546                            (void) signal(SIGINT,  vffree);
547                            (void) signal(SIGQUIT, SIG_DFL);
548                        }
549# ifdef BSDJOBS
550                        if (wanttty >= 0) {
551                            (void) signal(SIGTSTP, SIG_DFL);
552                            (void) signal(SIGTTIN, SIG_DFL);
553                            (void) signal(SIGTTOU, SIG_DFL);
554                        }
555# endif /* BSDJOBS */
556
557                        (void) signal(SIGTERM, parterm);
558                    }
559                    else if (tpgrp == -1 &&
560                             (t->t_dflg & F_NOINTERRUPT)) {
561                        (void) signal(SIGINT, SIG_IGN);
562                        (void) signal(SIGQUIT, SIG_IGN);
563                    }
564
565                    pgetty(wanttty, pgrp);
566
567                    if (t->t_dflg & F_NOHUP)
568                        (void) signal(SIGHUP, SIG_IGN);
569                    if (t->t_dflg & F_HUP)
570                        (void) signal(SIGHUP, SIG_DFL);
571                    if (t->t_dflg & F_NICE) {
572                        int nval = SIGN_EXTEND_CHAR(t->t_nice);
573# ifdef BSDNICE
574                        (void) setpriority(PRIO_PROCESS, 0, nval);
575# else /* !BSDNICE */
576                        (void) nice(nval);
577# endif /* BSDNICE */
578                    }
579# ifdef F_VER
580                    if (t->t_dflg & F_VER) {
581                        tsetenv(STRSYSTYPE, t->t_systype ? STRbsd43 : STRsys53);
582                        dohash(NULL, NULL);
583                    }
584# endif /* F_VER */
585                }
586
587            }
588#endif /* VFORK */
589        if (pid != 0) {
590            /*
591             * It would be better if we could wait for the whole job when we
592             * knew the last process had been started.  Pwait, in fact, does
593             * wait for the whole job anyway, but this test doesn't really
594             * express our intentions.
595             */
596#ifdef BACKPIPE
597            if (didfds == 0 && t->t_dflg & F_PIPEOUT) {
598                (void) close(pipeout[0]);
599                (void) close(pipeout[1]);
600            }
601            if ((t->t_dflg & F_PIPEIN) != 0)
602                break;
603#else /* !BACKPIPE */
604            if (didfds == 0 && t->t_dflg & F_PIPEIN) {
605                (void) close(pipein[0]);
606                (void) close(pipein[1]);
607            }
608            if ((t->t_dflg & F_PIPEOUT) != 0)
609                break;
610#endif /* BACKPIPE */
611
612            if (nosigchld) {
613#ifdef BSDSIGS
614                (void) sigsetmask(csigmask);
615#else /* !BSDSIGS */
616                (void) sigrelse(SIGCHLD);
617#endif /* BSDSIGS */
618                nosigchld = 0;
619            }
620            if ((t->t_dflg & F_AMPERSAND) == 0)
621                pwait();
622            break;
623        }
624
625        doio(t, pipein, pipeout);
626#ifdef BACKPIPE
627        if (t->t_dflg & F_PIPEIN) {
628            (void) close(pipein[0]);
629            (void) close(pipein[1]);
630        }
631#else /* !BACKPIPE */
632        if (t->t_dflg & F_PIPEOUT) {
633            (void) close(pipeout[0]);
634            (void) close(pipeout[1]);
635        }
636#endif /* BACKPIPE */
637        /*
638         * Perform a builtin function. If we are not forked, arrange for
639         * possible stopping
640         */
641        if (bifunc) {
642            func(t, bifunc);
643            if (forked)
644                exitstat();
645            break;
646        }
647        if (t->t_dtyp != NODE_PAREN) {
648            doexec(t);
649            /* NOTREACHED */
650        }
651        /*
652         * For () commands must put new 0,1,2 in FSH* and recurse
653         */
654        OLDSTD = dcopy(0, FOLDSTD);
655        SHOUT = dcopy(1, FSHOUT);
656        isoutatty = isatty(SHOUT);
657        SHDIAG = dcopy(2, FSHDIAG);
658        isdiagatty = isatty(SHDIAG);
659        (void) close(SHIN);
660        SHIN = -1;
661#ifndef CLOSE_ON_EXEC
662        didcch = 0;
663#endif /* !CLOSE_ON_EXEC */
664        didfds = 0;
665        wanttty = -1;
666        t->t_dspr->t_dflg |= t->t_dflg & F_NOINTERRUPT;
667        execute(t->t_dspr, wanttty, NULL, NULL);
668        exitstat();
669
670    case NODE_PIPE:
671#ifdef BACKPIPE
672        t->t_dcdr->t_dflg |= F_PIPEIN | (t->t_dflg &
673                        (F_PIPEOUT | F_AMPERSAND | F_NOFORK | F_NOINTERRUPT));
674        execute(t->t_dcdr, wanttty, pv, pipeout);
675        t->t_dcar->t_dflg |= F_PIPEOUT |
676            (t->t_dflg & (F_PIPEIN | F_AMPERSAND | F_STDERR | F_NOINTERRUPT));
677        execute(t->t_dcar, wanttty, pipein, pv);
678#else /* !BACKPIPE */
679        t->t_dcar->t_dflg |= F_PIPEOUT |
680            (t->t_dflg & (F_PIPEIN | F_AMPERSAND | F_STDERR | F_NOINTERRUPT));
681        execute(t->t_dcar, wanttty, pipein, pv);
682        t->t_dcdr->t_dflg |= F_PIPEIN | (t->t_dflg &
683                        (F_PIPEOUT | F_AMPERSAND | F_NOFORK | F_NOINTERRUPT));
684        execute(t->t_dcdr, wanttty, pv, pipeout);
685#endif /* BACKPIPE */
686        break;
687
688    case NODE_LIST:
689        if (t->t_dcar) {
690            t->t_dcar->t_dflg |= t->t_dflg & F_NOINTERRUPT;
691            execute(t->t_dcar, wanttty, NULL, NULL);
692            /*
693             * In strange case of A&B make a new job after A
694             */
695            if (t->t_dcar->t_dflg & F_AMPERSAND && t->t_dcdr &&
696                (t->t_dcdr->t_dflg & F_AMPERSAND) == 0)
697                pendjob();
698        }
699        if (t->t_dcdr) {
700            t->t_dcdr->t_dflg |= t->t_dflg &
701                (F_NOFORK | F_NOINTERRUPT);
702            execute(t->t_dcdr, wanttty, NULL, NULL);
703        }
704        break;
705
706    case NODE_OR:
707    case NODE_AND:
708        if (t->t_dcar) {
709            t->t_dcar->t_dflg |= t->t_dflg & F_NOINTERRUPT;
710            execute(t->t_dcar, wanttty, NULL, NULL);
711            if ((getn(varval(STRstatus)) == 0) !=
712                (t->t_dtyp == NODE_AND)) {
713                return;
714            }
715        }
716        if (t->t_dcdr) {
717            t->t_dcdr->t_dflg |= t->t_dflg &
718                (F_NOFORK | F_NOINTERRUPT);
719            execute(t->t_dcdr, wanttty, NULL, NULL);
720        }
721        break;
722
723    default:
724        break;
725    }
726    /*
727     * Fall through for all breaks from switch
728     *
729     * If there will be no more executions of this command, flush all file
730     * descriptors. Places that turn on the F_REPEAT bit are responsible for
731     * doing donefds after the last re-execution
732     */
733    if (didfds && !(t->t_dflg & F_REPEAT))
734        donefds();
735}
736
737#ifdef VFORK
738static sigret_t
739/*ARGSUSED*/
740vffree(snum)
741int snum;
742{
743    register Char **v;
744
745    USE(snum);
746    if ((v = gargv) != 0) {
747        gargv = 0;
748        xfree((ptr_t) v);
749    }
750
751    if ((v = pargv) != 0) {
752        pargv = 0;
753        xfree((ptr_t) v);
754    }
755
756    _exit(1);
757#ifndef SIGVOID
758    /*NOTREACHED*/
759    return(0);
760#endif /* SIGVOID */
761}
762#endif /* VFORK */
763
764/*
765 * Expand and glob the words after an i/o redirection.
766 * If more than one word is generated, then update the command vector.
767 *
768 * This is done differently in all the shells:
769 * 1. in the bourne shell and ksh globbing is not performed
770 * 2. Bash/csh say ambiguous
771 * 3. zsh does i/o to/from all the files
772 * 4. itcsh concatenates the words.
773 *
774 * I don't know what is best to do. I think that Ambiguous is better
775 * than restructuring the command vector, because the user can get
776 * unexpected results. In any case, the command vector restructuring
777 * code is present and the user can choose it by setting noambiguous
778 */
779static Char *
780splicepipe(t, cp)
781    register struct command *t;
782    Char *cp;   /* word after < or > */
783{
784    Char *blk[2];
785
786    if (adrof(STRnoambiguous)) {
787        Char **pv;
788
789        blk[0] = Dfix1(cp); /* expand $ */
790        blk[1] = NULL;
791
792        gflag = 0, tglob(blk);
793        if (gflag) {
794            pv = globall(blk);
795            if (pv == NULL) {
796                setname(short2str(blk[0]));
797                xfree((ptr_t) blk[0]);
798                stderror(ERR_NAME | ERR_NOMATCH);
799            }
800            gargv = NULL;
801            if (pv[1] != NULL) { /* we need to fix the command vector */
802                Char **av = blkspl(t->t_dcom, &pv[1]);
803                xfree((ptr_t) t->t_dcom);
804                t->t_dcom = av;
805            }
806            xfree((ptr_t) blk[0]);
807            blk[0] = pv[0];
808            xfree((ptr_t) pv);
809        }
810    }
811    else {
812        Char buf[BUFSIZE];
813
814        (void) Strcpy(buf, blk[1] = Dfix1(cp));
815        xfree((ptr_t) blk[1]);
816        blk[0] = globone(buf, G_ERROR);
817    }
818    return(blk[0]);
819}
820   
821/*
822 * Perform io redirection.
823 * We may or maynot be forked here.
824 */
825static void
826doio(t, pipein, pipeout)
827    register struct command *t;
828    int    *pipein, *pipeout;
829{
830    register int fd;
831    register Char *cp;
832    register unsigned long flags = t->t_dflg;
833
834    if (didfds || (flags & F_REPEAT))
835        return;
836    if ((flags & F_READ) == 0) {/* F_READ already done */
837        if (t->t_dlef) {
838            char    tmp[MAXPATHLEN+1];
839
840            /*
841             * so < /dev/std{in,out,err} work
842             */
843            (void) dcopy(SHIN, 0);
844            (void) dcopy(SHOUT, 1);
845            (void) dcopy(SHDIAG, 2);
846            cp = splicepipe(t, t->t_dlef);
847            (void) strncpy(tmp, short2str(cp), MAXPATHLEN);
848            tmp[MAXPATHLEN] = '\0';
849            xfree((ptr_t) cp);
850            if ((fd = open(tmp, O_RDONLY)) < 0)
851                stderror(ERR_SYSTEM, tmp, strerror(errno));
852#ifdef O_LARGEFILE
853            /* allow input files larger than 2Gb  */
854            (void) fcntl(fd, O_LARGEFILE, 0);
855#endif /* O_LARGEFILE */
856            (void) dmove(fd, 0);
857        }
858        else if (flags & F_PIPEIN) {
859            (void) close(0);
860            (void) dup(pipein[0]);
861            (void) close(pipein[0]);
862            (void) close(pipein[1]);
863        }
864        else if ((flags & F_NOINTERRUPT) && tpgrp == -1) {
865            (void) close(0);
866            (void) open(_PATH_DEVNULL, O_RDONLY);
867        }
868        else {
869            (void) close(0);
870            (void) dup(OLDSTD);
871#if defined(CLOSE_ON_EXEC) && defined(CLEX_DUPS)
872            /*
873             * PWP: Unlike Bezerkeley 4.3, FIONCLEX for Pyramid is preserved
874             * across dup()s, so we have to UNSET it here or else we get a
875             * command with NO stdin, stdout, or stderr at all (a bad thing
876             * indeed)
877             */
878            (void) close_on_exec(0, 0);
879#endif /* CLOSE_ON_EXEC && CLEX_DUPS */
880        }
881    }
882    if (t->t_drit) {
883        char    tmp[MAXPATHLEN+1];
884
885        cp = splicepipe(t, t->t_drit);
886        (void) strncpy(tmp, short2str(cp), MAXPATHLEN);
887        tmp[MAXPATHLEN] = '\0';
888        xfree((ptr_t) cp);
889        /*
890         * so > /dev/std{out,err} work
891         */
892        (void) dcopy(SHOUT, 1);
893        (void) dcopy(SHDIAG, 2);
894        if ((flags & F_APPEND) != 0) {
895#ifdef O_APPEND
896            fd = open(tmp, O_WRONLY | O_APPEND);
897#else /* !O_APPEND */
898            fd = open(tmp, O_WRONLY);
899            (void) lseek(fd, (off_t) 0, L_XTND);
900#endif /* O_APPEND */
901        }
902        else
903            fd = 0;
904        if ((flags & F_APPEND) == 0 || fd == -1) {
905            if (!(flags & F_OVERWRITE) && adrof(STRnoclobber)) {
906                if (flags & F_APPEND)
907                    stderror(ERR_SYSTEM, tmp, strerror(errno));
908                chkclob(tmp);
909            }
910            if ((fd = creat(tmp, 0666)) < 0)
911                stderror(ERR_SYSTEM, tmp, strerror(errno));
912#ifdef O_LARGEFILE
913            /* allow input files larger than 2Gb  */
914            (void) fcntl(fd, O_LARGEFILE, 0);
915#endif /* O_LARGEFILE */
916        }
917        (void) dmove(fd, 1);
918        is1atty = isatty(1);
919    }
920    else if (flags & F_PIPEOUT) {
921        (void) close(1);
922        (void) dup(pipeout[1]);
923        is1atty = 0;
924    }
925    else {
926        (void) close(1);
927        (void) dup(SHOUT);
928        is1atty = isoutatty;
929# if defined(CLOSE_ON_EXEC) && defined(CLEX_DUPS)
930        (void) close_on_exec(1, 0);
931# endif /* CLOSE_ON_EXEC && CLEX_DUPS */
932    }
933
934    (void) close(2);
935    if (flags & F_STDERR) {
936        (void) dup(1);
937        is2atty = is1atty;
938    }
939    else {
940        (void) dup(SHDIAG);
941        is2atty = isdiagatty;
942# if defined(CLOSE_ON_EXEC) && defined(CLEX_DUPS)
943        (void) close_on_exec(2, 0);
944# endif /* CLOSE_ON_EXEC && CLEX_DUPS */
945    }
946    didfds = 1;
947}
948
949void
950mypipe(pv)
951    register int *pv;
952{
953
954    if (pipe(pv) < 0)
955        goto oops;
956    pv[0] = dmove(pv[0], -1);
957    pv[1] = dmove(pv[1], -1);
958    if (pv[0] >= 0 && pv[1] >= 0)
959        return;
960oops:
961    stderror(ERR_PIPE);
962}
963
964static void
965chkclob(cp)
966    register char *cp;
967{
968    struct stat stb;
969
970    if (stat(cp, &stb) < 0)
971        return;
972    if (S_ISCHR(stb.st_mode))
973        return;
974    stderror(ERR_EXISTS, cp);
975}
Note: See TracBrowser for help on using the repository browser.