]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/tcsh/sh.proc.c
This commit was generated by cvs2svn to compensate for changes in r152058,
[FreeBSD/FreeBSD.git] / contrib / tcsh / sh.proc.c
1 /* $Header: /src/pub/tcsh/sh.proc.c,v 3.90 2005/03/03 19:57:07 kim Exp $ */
2 /*
3  * sh.proc.c: Job manipulations
4  */
5 /*-
6  * Copyright (c) 1980, 1991 The Regents of the University of California.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33 #include "sh.h"
34
35 RCSID("$Id: sh.proc.c,v 3.90 2005/03/03 19:57:07 kim Exp $")
36
37 #include "ed.h"
38 #include "tc.h"
39 #include "tc.wait.h"
40
41 #ifdef WINNT_NATIVE
42 #undef POSIX
43 #define POSIX
44 #endif /* WINNT_NATIVE */
45 #ifdef aiws
46 # undef HZ
47 # define HZ 16
48 #endif /* aiws */
49
50 #if defined(_BSD) || (defined(IRIS4D) && __STDC__) || defined(__lucid) || defined(linux) || defined(__GNU__) || defined(__GLIBC__)
51 # define BSDWAIT
52 #endif /* _BSD || (IRIS4D && __STDC__) || __lucid || glibc */
53 #ifndef WTERMSIG
54 # define WTERMSIG(w)    (((union wait *) &(w))->w_termsig)
55 # ifndef BSDWAIT
56 #  define BSDWAIT
57 # endif /* !BSDWAIT */
58 #endif /* !WTERMSIG */
59 #ifndef WEXITSTATUS
60 # define WEXITSTATUS(w) (((union wait *) &(w))->w_retcode)
61 #endif /* !WEXITSTATUS */
62 #ifndef WSTOPSIG
63 # define WSTOPSIG(w)    (((union wait *) &(w))->w_stopsig)
64 #endif /* !WSTOPSIG */
65
66 #ifdef __osf__
67 # ifndef WCOREDUMP
68 #  define WCOREDUMP(x) (_W_INT(x) & WCOREFLAG)
69 # endif
70 #endif
71
72 #ifndef WCOREDUMP
73 # ifdef BSDWAIT
74 #  define WCOREDUMP(w)  (((union wait *) &(w))->w_coredump)
75 # else /* !BSDWAIT */
76 #  define WCOREDUMP(w)  ((w) & 0200)
77 # endif /* !BSDWAIT */
78 #endif /* !WCOREDUMP */
79
80 /*
81  * C Shell - functions that manage processes, handling hanging, termination
82  */
83
84 #define BIGINDEX        9       /* largest desirable job index */
85
86 #ifdef BSDTIMES
87 # ifdef convex
88 /* use 'cvxrusage' to get parallel statistics */
89 static struct cvxrusage zru = {{0L, 0L}, {0L, 0L}, 0L, 0L, 0L, 0L,
90                                 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L,
91                                 {0L, 0L}, 0LL, 0LL, 0LL, 0LL, 0L, 0L, 0L,
92                                 0LL, 0LL, {0L, 0L, 0L, 0L, 0L}};
93 # else
94 static struct rusage zru;
95 # endif /* convex */
96 #else /* !BSDTIMES */
97 # ifdef _SEQUENT_
98 static struct process_stats zru = {{0L, 0L}, {0L, 0L}, 0, 0, 0, 0, 0, 0, 0,
99                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
100 # else /* !_SEQUENT_ */
101 #  ifdef _SX
102 static struct tms zru = {0, 0, 0, 0}, lru = {0, 0, 0, 0};
103 #  else /* !_SX */
104 static struct tms zru = {0L, 0L, 0L, 0L}, lru = {0L, 0L, 0L, 0L};
105 #  endif        /* !_SX */
106 # endif /* !_SEQUENT_ */
107 #endif /* !BSDTIMES */
108
109 #ifndef RUSAGE_CHILDREN
110 # define        RUSAGE_CHILDREN -1
111 #endif /* RUSAGE_CHILDREN */
112
113 static  void             pflushall      __P((void));
114 static  void             pflush         __P((struct process *));
115 static  void             pfree          __P((struct process *));
116 static  void             pclrcurr       __P((struct process *));
117 static  void             padd           __P((struct command *));
118 static  int              pprint         __P((struct process *, int));
119 static  void             ptprint        __P((struct process *));
120 static  void             pads           __P((Char *));
121 static  void             pkill          __P((Char **, int));
122 static  struct process  *pgetcurr       __P((struct process *));
123 static  void             okpcntl        __P((void));
124 static  void             setttypgrp     __P((int));
125
126 /*
127  * pchild - called at interrupt level by the SIGCHLD signal
128  *      indicating that at least one child has terminated or stopped
129  *      thus at least one wait system call will definitely return a
130  *      childs status.  Top level routines (like pwait) must be sure
131  *      to mask interrupts when playing with the proclist data structures!
132  */
133 RETSIGTYPE
134 /*ARGSUSED*/
135 pchild(snum)
136 int snum;
137 {
138     struct process *pp;
139     struct process *fp;
140     int pid;
141 #ifdef BSDWAIT
142     union wait w;
143 #else /* !BSDWAIT */
144     int     w;
145 #endif /* !BSDWAIT */
146     int     jobflags;
147 #ifdef BSDTIMES
148     struct sysrusage ru;
149 #else /* !BSDTIMES */
150 # ifdef _SEQUENT_
151     struct process_stats ru;
152     struct process_stats cpst1, cpst2;
153     timeval_t tv;
154 # else /* !_SEQUENT_ */
155     struct tms proctimes;
156
157     if (!timesdone) {
158         timesdone++;
159         (void) times(&shtimes);
160     }
161 # endif /* !_SEQUENT_ */
162 #endif /* !BSDTIMES */
163
164     USE(snum);
165 #ifdef JOBDEBUG
166     xprintf("pchild()\n");
167 #endif  /* JOBDEBUG */
168
169 /* Christos on where the signal(SIGCHLD, pchild) shoud be:
170  *
171  * I think that it should go *after* the wait, unlike most signal handlers.
172  *
173  * In release two (for which I have manuals), it says that wait will remove
174  * the first child from the queue of dead children.
175  * All the rest of the children that die while in the signal handler of the
176  * SIGC(H)LD, will be placed in the queue. If signal is called to re-establish
177  * the signal handler, and there are items in the queue, the process will
178  * receive another SIGC(H)LD before signal returns. BTW this is from the
179  * manual page on comp-sim... Maybe it is not applicable to the hp's, but
180  * I read on the news in comp.unix.wizards or comp.unix.questions yesterday
181  * that another person was claiming the the signal() call should be after
182  * the wait().
183  */
184
185 loop:
186     errno = 0;                  /* reset, just in case */
187 #ifdef JOBDEBUG
188     xprintf("Waiting...\n");
189     flush();
190 #endif /* JOBDEBUG */
191 #ifndef WINNT_NATIVE
192 # ifdef BSDJOBS
193 #  ifdef BSDTIMES
194 #   ifdef convex
195     /* use 'cvxwait' to get parallel statistics */
196     pid = cvxwait(&w,
197         (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG), &ru);
198 #   else
199     /* both a wait3 and rusage */
200 #    if !defined(BSDWAIT) || defined(NeXT) || defined(MACH) || defined(linux) || defined(__GNU__) || defined(__GLIBC__) || (defined(IRIS4D) && (__STDC__ || defined(PROTOTYPES)) && SYSVREL <= 3) || defined(__lucid) || defined(__osf__)
201     pid = wait3(&w,
202        (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG), &ru);
203 #    else /* BSDWAIT */
204     pid = wait3(&w.w_status,
205        (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG), &ru);
206 #    endif /* BSDWAIT */
207 #   endif /* convex */
208 #  else /* !BSDTIMES */
209 #   ifdef _SEQUENT_
210     (void) get_process_stats(&tv, PS_SELF, 0, &cpst1);
211     pid = waitpid(-1, &w,
212             (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG));
213     (void) get_process_stats(&tv, PS_SELF, 0, &cpst2);
214     pr_stat_sub(&cpst2, &cpst1, &ru);
215 #   else        /* !_SEQUENT_ */
216 #    ifndef POSIX
217     /* we have a wait3, but no rusage stuff */
218     pid = wait3(&w.w_status,
219          (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG), 0);
220 #    else /* POSIX */
221     pid = waitpid(-1, &w,
222             (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG));
223 #    endif /* POSIX */
224 #   endif /* !_SEQUENT_ */
225 #  endif        /* !BSDTIMES */
226 # else /* !BSDJOBS */
227 #  ifdef BSDTIMES
228 #   define HAVEwait3
229     /* both a wait3 and rusage */
230 #   ifdef hpux
231     pid = wait3(&w.w_status, WNOHANG, 0);
232 #   else        /* !hpux */
233     pid = wait3(&w.w_status, WNOHANG, &ru);
234 #   endif /* !hpux */
235 #  else /* !BSDTIMES */
236 #   ifdef ODT  /* For Sco Unix 3.2.0 or ODT 1.0 */
237 #    define HAVEwait3
238      pid = waitpid(-1, &w,
239             (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG));
240 #   endif /* ODT */         
241 #   if defined(aiws) || defined(uts)
242 #    define HAVEwait3
243     pid = wait3(&w.w_status, 
244         (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG), 0);
245 #   endif /* aiws || uts */
246 #   ifndef HAVEwait3
247 #    ifdef UNRELSIGS
248      /* no wait3, therefore no rusage */
249      /* on Sys V, this may hang.  I hope it's not going to be a problem */
250 #     ifdef _MINIX
251       pid = wait(&w);
252 #     else /* !_MINIX */
253       pid = ourwait(&w.w_status);
254 #     endif /* _MINIX */
255 #    else /* !UNRELSIGS */
256      /* 
257       * XXX: for greater than 3 we should use waitpid(). 
258       * but then again, SVR4 falls into the POSIX/BSDJOBS category.
259       */
260      pid = wait(&w.w_status);
261 #    endif /* !UNRELSIGS */
262 #   endif /* !HAVEwait3 */
263 #  endif        /* !BSDTIMES */
264 #  ifndef BSDSIGS
265     (void) sigset(SIGCHLD, pchild);
266 #  endif /* !BSDSIGS */
267 # endif /* !BSDJOBS */
268 #else /* WINNT_NATIVE */
269     {
270         extern int insource;
271         pid = waitpid(-1, &w,
272             (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG));
273     }
274 #endif /* WINNT_NATIVE */
275
276 #ifdef JOBDEBUG
277     xprintf("parent %d pid %d, retval %x termsig %x retcode %x\n",
278             getpid(), pid, w, WTERMSIG(w), WEXITSTATUS(w));
279     flush();
280 #endif /* JOBDEBUG */
281
282     if ((pid == 0) || (pid == -1)) {
283 #ifdef JOBDEBUG
284         xprintf("errno == %d\n", errno);
285 #endif /* JOBDEBUG */
286         if (errno == EINTR) {
287             errno = 0;
288             goto loop;
289         }
290         pnoprocesses = pid == -1;
291         goto end;
292     }
293     for (pp = proclist.p_next; pp != NULL; pp = pp->p_next)
294         if (pid == pp->p_procid)
295             goto found;
296 #if !defined(BSDJOBS) && !defined(WINNT_NATIVE)
297     /* this should never have happened */
298     stderror(ERR_SYNC, pid);
299     xexit(0);
300 #else /* BSDJOBS || WINNT_NATIVE */
301     goto loop;
302 #endif /* !BSDJOBS && !WINNT_NATIVE */
303 found:
304     pp->p_flags &= ~(PRUNNING | PSTOPPED | PREPORTED);
305     if (WIFSTOPPED(w)) {
306         pp->p_flags |= PSTOPPED;
307         pp->p_reason = WSTOPSIG(w);
308     }
309     else {
310         if (pp->p_flags & (PTIME | PPTIME) || adrof(STRtime))
311 #ifndef BSDTIMES
312 # ifdef _SEQUENT_
313             (void) get_process_stats(&pp->p_etime, PS_SELF, NULL, NULL);
314 # else  /* !_SEQUENT_ */
315 #  ifndef COHERENT
316             pp->p_etime = times(&proctimes);
317 #  else /* COHERENT */
318             pp->p_etime = HZ * time(NULL);
319             times(&proctimes);
320 #  endif /* COHERENT */
321 # endif /* !_SEQUENT_ */
322 #else /* BSDTIMES */
323             (void) gettimeofday(&pp->p_etime, NULL);
324 #endif /* BSDTIMES */
325
326
327 #if defined(BSDTIMES) || defined(_SEQUENT_)
328         pp->p_rusage = ru;
329 #else /* !BSDTIMES && !_SEQUENT_ */
330         (void) times(&proctimes);
331         pp->p_utime = proctimes.tms_cutime - shtimes.tms_cutime;
332         pp->p_stime = proctimes.tms_cstime - shtimes.tms_cstime;
333         shtimes = proctimes;
334 #endif /* !BSDTIMES && !_SEQUENT_ */
335         if (WIFSIGNALED(w)) {
336             if (WTERMSIG(w) == SIGINT)
337                 pp->p_flags |= PINTERRUPTED;
338             else
339                 pp->p_flags |= PSIGNALED;
340             if (WCOREDUMP(w))
341                 pp->p_flags |= PDUMPED;
342             pp->p_reason = WTERMSIG(w);
343         }
344         else {
345             pp->p_reason = WEXITSTATUS(w);
346             if (pp->p_reason != 0)
347                 pp->p_flags |= PAEXITED;
348             else
349                 pp->p_flags |= PNEXITED;
350         }
351     }
352     jobflags = 0;
353     fp = pp;
354     do {
355         if ((fp->p_flags & (PPTIME | PRUNNING | PSTOPPED)) == 0 &&
356             !child && adrof(STRtime) &&
357 #ifdef BSDTIMES
358             fp->p_rusage.ru_utime.tv_sec + fp->p_rusage.ru_stime.tv_sec
359 #else /* !BSDTIMES */
360 # ifdef _SEQUENT_
361             fp->p_rusage.ps_utime.tv_sec + fp->p_rusage.ps_stime.tv_sec
362 # else /* !_SEQUENT_ */
363 #  ifndef POSIX
364             (fp->p_utime + fp->p_stime) / HZ
365 #  else /* POSIX */
366             (fp->p_utime + fp->p_stime) / clk_tck
367 #  endif /* POSIX */
368 # endif /* !_SEQUENT_ */
369 #endif /* !BSDTIMES */
370             >= atoi(short2str(varval(STRtime))))
371             fp->p_flags |= PTIME;
372         jobflags |= fp->p_flags;
373     } while ((fp = fp->p_friends) != pp);
374     pp->p_flags &= ~PFOREGND;
375     if (pp == pp->p_friends && (pp->p_flags & PPTIME)) {
376         pp->p_flags &= ~PPTIME;
377         pp->p_flags |= PTIME;
378     }
379     if ((jobflags & (PRUNNING | PREPORTED)) == 0) {
380         fp = pp;
381         do {
382             if (fp->p_flags & PSTOPPED)
383                 fp->p_flags |= PREPORTED;
384         } while ((fp = fp->p_friends) != pp);
385         while (fp->p_procid != fp->p_jobid)
386             fp = fp->p_friends;
387         if (jobflags & PSTOPPED) {
388             if (pcurrent && pcurrent != fp)
389                 pprevious = pcurrent;
390             pcurrent = fp;
391         }
392         else
393             pclrcurr(fp);
394         if (jobflags & PFOREGND) {
395             if (!(jobflags & (PSIGNALED | PSTOPPED | PPTIME) ||
396 #ifdef notdef
397                 jobflags & PAEXITED ||
398 #endif /* notdef */
399                 !eq(dcwd->di_name, fp->p_cwd->di_name))) {
400             /* PWP: print a newline after ^C */
401                 if (jobflags & PINTERRUPTED) {
402 #ifdef SHORT_STRINGS
403                     xputchar('\r' | QUOTE), xputchar('\n');
404 #else /* !SHORT_STRINGS */
405                     xprintf("\215\n");  /* \215 is a quoted ^M */
406 #endif /* !SHORT_STRINGS */
407                 }
408 #ifdef notdef
409                 else if ((jobflags & (PTIME|PSTOPPED)) == PTIME)
410                     ptprint(fp);
411 #endif /* notdef */
412             }
413         }
414         else {
415             if (jobflags & PNOTIFY || adrof(STRnotify)) {
416 #ifdef SHORT_STRINGS
417                 xputchar('\r' | QUOTE), xputchar('\n');
418 #else /* !SHORT_STRINGS */
419                 xprintf("\215\n");      /* \215 is a quoted ^M */
420 #endif /* !SHORT_STRINGS */
421                 (void) pprint(pp, NUMBER | NAME | REASON);
422                 if ((jobflags & PSTOPPED) == 0)
423                     pflush(pp);
424                 {
425                     if (GettingInput) {
426                         errno = 0;
427                         (void) Rawmode();
428 #ifdef notdef
429                         /*
430                          * don't really want to do that, because it
431                          * will erase our message in case of multi-line
432                          * input
433                          */
434                         ClearLines();
435 #endif /* notdef */
436                         ClearDisp();
437                         Refresh();
438                     }
439                 }
440             }
441             else {
442                 fp->p_flags |= PNEEDNOTE;
443                 neednote++;
444             }
445         }
446     }
447 #if defined(BSDJOBS) || defined(HAVEwait3)
448     goto loop;
449 #endif /* BSDJOBS || HAVEwait3 */
450  end:
451     ;
452 }
453
454 void
455 pnote()
456 {
457     struct process *pp;
458     int     flags;
459 #ifdef BSDSIGS
460     sigmask_t omask;
461 #endif /* BSDSIGS */
462
463     neednote = 0;
464     for (pp = proclist.p_next; pp != NULL; pp = pp->p_next) {
465         if (pp->p_flags & PNEEDNOTE) {
466 #ifdef BSDSIGS
467             omask = sigblock(sigmask(SIGCHLD));
468 #else /* !BSDSIGS */
469             (void) sighold(SIGCHLD);
470 #endif /* !BSDSIGS */
471             pp->p_flags &= ~PNEEDNOTE;
472             flags = pprint(pp, NUMBER | NAME | REASON);
473             if ((flags & (PRUNNING | PSTOPPED)) == 0)
474                 pflush(pp);
475 #ifdef BSDSIGS
476             (void) sigsetmask(omask);
477 #else /* !BSDSIGS */
478             (void) sigrelse(SIGCHLD);
479 #endif /* !BSDSIGS */
480         }
481     }
482 }
483
484
485 static void
486 pfree(pp)
487     struct process *pp;
488 {       
489     xfree((ptr_t) pp->p_command);
490     if (pp->p_cwd && --pp->p_cwd->di_count == 0)
491         if (pp->p_cwd->di_next == 0)
492             dfree(pp->p_cwd);
493     xfree((ptr_t) pp);
494 }
495
496
497 /*
498  * pwait - wait for current job to terminate, maintaining integrity
499  *      of current and previous job indicators.
500  */
501 void
502 pwait()
503 {
504     struct process *fp, *pp;
505 #ifdef BSDSIGS
506     sigmask_t omask;
507 #endif /* BSDSIGS */
508
509     /*
510      * Here's where dead procs get flushed.
511      */
512 #ifdef BSDSIGS
513     omask = sigblock(sigmask(SIGCHLD));
514 #else /* !BSDSIGS */
515     (void) sighold(SIGCHLD);
516 #endif /* !BSDSIGS */
517     for (pp = (fp = &proclist)->p_next; pp != NULL; pp = (fp = pp)->p_next)
518         if (pp->p_procid == 0) {
519             fp->p_next = pp->p_next;
520             pfree(pp);
521             pp = fp;
522         }
523 #ifdef BSDSIGS
524     (void) sigsetmask(omask);
525 #else /* !BSDSIGS */
526     (void) sigrelse(SIGCHLD);
527 # ifdef notdef
528     if (setintr)
529         sigignore(SIGINT);
530 # endif /* notdef */
531 #endif /* !BSDSIGS */
532     pjwait(pcurrjob);
533 }
534
535
536 /*
537  * pjwait - wait for a job to finish or become stopped
538  *      It is assumed to be in the foreground state (PFOREGND)
539  */
540 void
541 pjwait(pp)
542     struct process *pp;
543 {
544     struct process *fp;
545     int     jobflags, reason;
546 #ifdef BSDSIGS
547     sigmask_t omask;
548 #endif /* BSDSIGS */
549 #ifdef UNRELSIGS
550     signalfun_t inthandler;
551 #endif /* UNRELSIGS */
552     while (pp->p_procid != pp->p_jobid)
553         pp = pp->p_friends;
554     fp = pp;
555
556     do {
557         if ((fp->p_flags & (PFOREGND | PRUNNING)) == PRUNNING)
558             xprintf(CGETS(17, 1, "BUG: waiting for background job!\n"));
559     } while ((fp = fp->p_friends) != pp);
560     /*
561      * Now keep pausing as long as we are not interrupted (SIGINT), and the
562      * target process, or any of its friends, are running
563      */
564     fp = pp;
565 #ifdef BSDSIGS
566     omask = sigblock(sigmask(SIGCHLD));
567 #endif /* BSDSIGS */
568 #ifdef UNRELSIGS
569     if (setintr)
570         inthandler = signal(SIGINT, SIG_IGN);
571 #endif /* UNRELSIGS */
572     for (;;) {
573 #ifndef BSDSIGS
574         (void) sighold(SIGCHLD);
575 #endif /* !BSDSIGS */
576         jobflags = 0;
577         do
578             jobflags |= fp->p_flags;
579         while ((fp = (fp->p_friends)) != pp);
580         if ((jobflags & PRUNNING) == 0)
581             break;
582 #ifdef JOBDEBUG
583         xprintf("%d starting to sigpause for SIGCHLD on %d\n",
584                 getpid(), fp->p_procid);
585 #endif /* JOBDEBUG */
586 #ifdef BSDSIGS
587         /* (void) sigpause(sigblock((sigmask_t) 0) &~ sigmask(SIGCHLD)); */
588         (void) sigpause(omask & ~sigmask(SIGCHLD));
589 #else /* !BSDSIGS */
590         (void) sigpause(SIGCHLD);
591 #endif /* !BSDSIGS */
592     }
593 #ifdef JOBDEBUG
594         xprintf("%d returned from sigpause loop\n", getpid());
595 #endif /* JOBDEBUG */
596 #ifdef BSDSIGS
597     (void) sigsetmask(omask);
598 #else /* !BSDSIGS */
599     (void) sigrelse(SIGCHLD);
600 #endif /* !BSDSIGS */
601 #ifdef UNRELSIGS
602     if (setintr)
603         (void) signal(SIGINT, inthandler);
604 #endif /* UNRELSIGS */
605 #ifdef BSDJOBS
606     if (tpgrp > 0)              /* get tty back */
607         (void) tcsetpgrp(FSHTTY, tpgrp);
608 #endif /* BSDJOBS */
609     if ((jobflags & (PSIGNALED | PSTOPPED | PTIME)) ||
610         !eq(dcwd->di_name, fp->p_cwd->di_name)) {
611         if (jobflags & PSTOPPED) {
612             xputchar('\n');
613             if (adrof(STRlistjobs)) {
614                 Char   *jobcommand[3];
615
616                 jobcommand[0] = STRjobs;
617                 if (eq(varval(STRlistjobs), STRlong))
618                     jobcommand[1] = STRml;
619                 else
620                     jobcommand[1] = NULL;
621                 jobcommand[2] = NULL;
622
623                 dojobs(jobcommand, NULL);
624                 (void) pprint(pp, SHELLDIR);
625             }
626             else
627                 (void) pprint(pp, AREASON | SHELLDIR);
628         }
629         else
630             (void) pprint(pp, AREASON | SHELLDIR);
631     }
632     if ((jobflags & (PINTERRUPTED | PSTOPPED)) && setintr &&
633         (!gointr || !eq(gointr, STRminus))) {
634         if ((jobflags & PSTOPPED) == 0)
635             pflush(pp);
636         pintr1(0);
637         /* NOTREACHED */
638     }
639     reason = 0;
640     fp = pp;
641     do {
642         if (fp->p_reason)
643             reason = fp->p_flags & (PSIGNALED | PINTERRUPTED) ?
644                 fp->p_reason | META : fp->p_reason;
645     } while ((fp = fp->p_friends) != pp);
646     /*
647      * Don't report on backquoted jobs, cause it will mess up 
648      * their output.
649      */
650     if ((reason != 0) && (adrof(STRprintexitvalue)) && 
651         (pp->p_flags & PBACKQ) == 0)
652         xprintf(CGETS(17, 2, "Exit %d\n"), reason);
653     set(STRstatus, putn(reason), VAR_READWRITE);
654     if (reason && exiterr)
655         exitstat();
656     pflush(pp);
657 }
658
659 /*
660  * dowait - wait for all processes to finish
661  */
662
663 /*ARGSUSED*/
664 void
665 dowait(v, c)
666     Char **v;
667     struct command *c;
668 {
669     struct process *pp;
670 #ifdef BSDSIGS
671     sigmask_t omask;
672 #endif /* BSDSIGS */
673
674     USE(c);
675     USE(v);
676     pjobs++;
677 #ifdef BSDSIGS
678     omask = sigblock(sigmask(SIGCHLD));
679 loop:
680 #else /* !BSDSIGS */
681     if (setintr)
682         (void) sigrelse(SIGINT);
683 loop:
684     (void) sighold(SIGCHLD);
685 #endif /* !BSDSIGS */
686     for (pp = proclist.p_next; pp; pp = pp->p_next)
687         if (pp->p_procid &&     /* pp->p_procid == pp->p_jobid && */
688             pp->p_flags & PRUNNING) {
689 #ifdef BSDSIGS
690             (void) sigpause((sigmask_t) 0);
691 #else /* !BSDSIGS */
692             (void) sigpause(SIGCHLD);
693 #endif /* !BSDSIGS */
694             goto loop;
695         }
696 #ifdef BSDSIGS
697     (void) sigsetmask(omask);
698 #else /* !BSDSIGS */
699     (void) sigrelse(SIGCHLD);
700 #endif /* !BSDSIGS */
701     pjobs = 0;
702 }
703
704 /*
705  * pflushall - flush all jobs from list (e.g. at fork())
706  */
707 static void
708 pflushall()
709 {
710     struct process *pp;
711
712     for (pp = proclist.p_next; pp != NULL; pp = pp->p_next)
713         if (pp->p_procid)
714             pflush(pp);
715 }
716
717 /*
718  * pflush - flag all process structures in the same job as the
719  *      the argument process for deletion.  The actual free of the
720  *      space is not done here since pflush is called at interrupt level.
721  */
722 static void
723 pflush(pp)
724     struct process *pp;
725 {
726     struct process *np;
727     int idx;
728
729     if (pp->p_procid == 0) {
730         xprintf(CGETS(17, 3, "BUG: process flushed twice"));
731         return;
732     }
733     while (pp->p_procid != pp->p_jobid)
734         pp = pp->p_friends;
735     pclrcurr(pp);
736     if (pp == pcurrjob)
737         pcurrjob = 0;
738     idx = pp->p_index;
739     np = pp;
740     do {
741         np->p_index = np->p_procid = 0;
742         np->p_flags &= ~PNEEDNOTE;
743     } while ((np = np->p_friends) != pp);
744     if (idx == pmaxindex) {
745         for (np = proclist.p_next, idx = 0; np; np = np->p_next)
746             if (np->p_index > idx)
747                 idx = np->p_index;
748         pmaxindex = idx;
749     }
750 }
751
752 /*
753  * pclrcurr - make sure the given job is not the current or previous job;
754  *      pp MUST be the job leader
755  */
756 static void
757 pclrcurr(pp)
758     struct process *pp;
759 {
760     if (pp == pcurrent) {
761         if (pprevious != NULL) {
762             pcurrent = pprevious;
763             pprevious = pgetcurr(pp);
764         }
765         else {
766             pcurrent = pgetcurr(pp);
767             pprevious = pgetcurr(pp);
768         }
769     }
770     else if (pp == pprevious)
771         pprevious = pgetcurr(pp);
772 }
773
774 /* +4 here is 1 for '\0', 1 ea for << >& >> */
775 static Char command[PMAXLEN + 4];
776 static int cmdlen;
777 static Char *cmdp;
778
779 /* GrP
780  * unparse - Export padd() functionality 
781  */
782 Char *
783 unparse(t)
784     struct command *t;
785 {
786     cmdp = command;
787     cmdlen = 0;
788     padd(t);
789     *cmdp++ = '\0';
790     return Strsave(command);
791 }
792
793
794 /*
795  * palloc - allocate a process structure and fill it up.
796  *      an important assumption is made that the process is running.
797  */
798 void
799 palloc(pid, t)
800     int     pid;
801     struct command *t;
802 {
803     struct process *pp;
804     int     i;
805
806     pp = (struct process *) xcalloc(1, (size_t) sizeof(struct process));
807     pp->p_procid = pid;
808     pp->p_flags = ((t->t_dflg & F_AMPERSAND) ? 0 : PFOREGND) | PRUNNING;
809     if (t->t_dflg & F_TIME)
810         pp->p_flags |= PPTIME;
811     if (t->t_dflg & F_BACKQ)
812         pp->p_flags |= PBACKQ;
813     if (t->t_dflg & F_HUP)
814         pp->p_flags |= PHUP;
815     cmdp = command;
816     cmdlen = 0;
817     padd(t);
818     *cmdp++ = 0;
819     if (t->t_dflg & F_PIPEOUT) {
820         pp->p_flags |= PPOU;
821         if (t->t_dflg & F_STDERR)
822             pp->p_flags |= PDIAG;
823     }
824     pp->p_command = Strsave(command);
825     if (pcurrjob) {
826         struct process *fp;
827
828         /* careful here with interrupt level */
829         pp->p_cwd = 0;
830         pp->p_index = pcurrjob->p_index;
831         pp->p_friends = pcurrjob;
832         pp->p_jobid = pcurrjob->p_procid;
833         for (fp = pcurrjob; fp->p_friends != pcurrjob; fp = fp->p_friends)
834             continue;
835         fp->p_friends = pp;
836     }
837     else {
838         pcurrjob = pp;
839         pp->p_jobid = pid;
840         pp->p_friends = pp;
841         pp->p_cwd = dcwd;
842         dcwd->di_count++;
843         if (pmaxindex < BIGINDEX)
844             pp->p_index = ++pmaxindex;
845         else {
846             struct process *np;
847
848             for (i = 1;; i++) {
849                 for (np = proclist.p_next; np; np = np->p_next)
850                     if (np->p_index == i)
851                         goto tryagain;
852                 pp->p_index = i;
853                 if (i > pmaxindex)
854                     pmaxindex = i;
855                 break;
856         tryagain:;
857             }
858         }
859         if (pcurrent == NULL)
860             pcurrent = pp;
861         else if (pprevious == NULL)
862             pprevious = pp;
863     }
864     pp->p_next = proclist.p_next;
865     proclist.p_next = pp;
866 #ifdef BSDTIMES
867     (void) gettimeofday(&pp->p_btime, NULL);
868 #else /* !BSDTIMES */
869 # ifdef _SEQUENT_
870     (void) get_process_stats(&pp->p_btime, PS_SELF, NULL, NULL);
871 # else /* !_SEQUENT_ */
872     {
873         struct tms tmptimes;
874
875 #  ifndef COHERENT
876         pp->p_btime = times(&tmptimes);
877 #  else /* !COHERENT */
878         pp->p_btime = HZ * time(NULL);
879         times(&tmptimes);
880 #  endif /* !COHERENT */
881     }
882 # endif /* !_SEQUENT_ */
883 #endif /* !BSDTIMES */
884 }
885
886 static void
887 padd(t)
888     struct command *t;
889 {
890     Char  **argp;
891
892     if (t == 0)
893         return;
894     switch (t->t_dtyp) {
895
896     case NODE_PAREN:
897         pads(STRLparensp);
898         padd(t->t_dspr);
899         pads(STRspRparen);
900         break;
901
902     case NODE_COMMAND:
903         for (argp = t->t_dcom; *argp; argp++) {
904             pads(*argp);
905             if (argp[1])
906                 pads(STRspace);
907         }
908         break;
909
910     case NODE_OR:
911     case NODE_AND:
912     case NODE_PIPE:
913     case NODE_LIST:
914         padd(t->t_dcar);
915         switch (t->t_dtyp) {
916         case NODE_OR:
917             pads(STRspor2sp);
918             break;
919         case NODE_AND:
920             pads(STRspand2sp);
921             break;
922         case NODE_PIPE:
923             pads(STRsporsp);
924             break;
925         case NODE_LIST:
926             pads(STRsemisp);
927             break;
928         default:
929             break;
930         }
931         padd(t->t_dcdr);
932         return;
933
934     default:
935         break;
936     }
937     if ((t->t_dflg & F_PIPEIN) == 0 && t->t_dlef) {
938         pads((t->t_dflg & F_READ) ? STRspLarrow2sp : STRspLarrowsp);
939         pads(t->t_dlef);
940     }
941     if ((t->t_dflg & F_PIPEOUT) == 0 && t->t_drit) {
942         pads((t->t_dflg & F_APPEND) ? STRspRarrow2 : STRspRarrow);
943         if (t->t_dflg & F_STDERR)
944             pads(STRand);
945         pads(STRspace);
946         pads(t->t_drit);
947     }
948 }
949
950 static void
951 pads(cp)
952     Char   *cp;
953 {
954     int i;
955
956     /*
957      * Avoid the Quoted Space alias hack! Reported by:
958      * sam@john-bigboote.ICS.UCI.EDU (Sam Horrocks)
959      */
960     if (cp[0] == STRQNULL[0])
961         cp++;
962
963     i = (int) Strlen(cp);
964
965     if (cmdlen >= PMAXLEN)
966         return;
967     if (cmdlen + i >= PMAXLEN) {
968         (void) Strcpy(cmdp, STRsp3dots);
969         cmdlen = PMAXLEN;
970         cmdp += 4;
971         return;
972     }
973     (void) Strcpy(cmdp, cp);
974     cmdp += i;
975     cmdlen += i;
976 }
977
978 /*
979  * psavejob - temporarily save the current job on a one level stack
980  *      so another job can be created.  Used for { } in exp6
981  *      and `` in globbing.
982  */
983 void
984 psavejob()
985 {
986     pholdjob = pcurrjob;
987     pcurrjob = NULL;
988 }
989
990 /*
991  * prestjob - opposite of psavejob.  This may be missed if we are interrupted
992  *      somewhere, but pendjob cleans up anyway.
993  */
994 void
995 prestjob()
996 {
997     pcurrjob = pholdjob;
998     pholdjob = NULL;
999 }
1000
1001 /*
1002  * pendjob - indicate that a job (set of commands) has been completed
1003  *      or is about to begin.
1004  */
1005 void
1006 pendjob()
1007 {
1008     struct process *pp, *tp;
1009
1010     if (pcurrjob && (pcurrjob->p_flags & (PFOREGND | PSTOPPED)) == 0) {
1011         pp = pcurrjob;
1012         while (pp->p_procid != pp->p_jobid)
1013             pp = pp->p_friends;
1014         xprintf("[%d]", pp->p_index);
1015         tp = pp;
1016         do {
1017             xprintf(" %d", pp->p_procid);
1018             pp = pp->p_friends;
1019         } while (pp != tp);
1020         xputchar('\n');
1021     }
1022     pholdjob = pcurrjob = 0;
1023 }
1024
1025 /*
1026  * pprint - print a job
1027  */
1028
1029 /*
1030  * Hacks have been added for SVR4 to deal with pipe's being spawned in
1031  * reverse order
1032  *
1033  * David Dawes (dawes@physics.su.oz.au) Oct 1991
1034  */
1035
1036 static int
1037 pprint(pp, flag)
1038     struct process *pp;
1039     int    flag;
1040 {
1041     int status, reason;
1042     struct process *tp;
1043     int     jobflags, pstatus, pcond;
1044     const char *format;
1045
1046 #ifdef BACKPIPE
1047     struct process *pipehead = NULL, *pipetail = NULL, *pmarker = NULL;
1048     int inpipe = 0;
1049 #endif /* BACKPIPE */
1050
1051     while (pp->p_procid != pp->p_jobid)
1052         pp = pp->p_friends;
1053     if (pp == pp->p_friends && (pp->p_flags & PPTIME)) {
1054         pp->p_flags &= ~PPTIME;
1055         pp->p_flags |= PTIME;
1056     }
1057     tp = pp;
1058     status = reason = -1;
1059     jobflags = 0;
1060     do {
1061 #ifdef BACKPIPE
1062         /*
1063          * The pipeline is reversed, so locate the real head of the pipeline
1064          * if pp is at the tail of a pipe (and not already in a pipeline)
1065          */
1066         if ((pp->p_friends->p_flags & PPOU) && !inpipe && (flag & NAME)) {
1067             inpipe = 1;
1068             pipetail = pp;
1069             do 
1070                 pp = pp->p_friends;
1071             while (pp->p_friends->p_flags & PPOU);
1072             pipehead = pp;
1073             pmarker = pp;
1074         /*
1075          * pmarker is used to hold the place of the proc being processed, so
1076          * we can search for the next one downstream later.
1077          */
1078         }
1079         pcond = (int) (tp != pp || (inpipe && tp == pp));
1080 #else /* !BACKPIPE */
1081         pcond = (int) (tp != pp);
1082 #endif /* BACKPIPE */       
1083
1084         jobflags |= pp->p_flags;
1085         pstatus = (int) (pp->p_flags & PALLSTATES);
1086         if (pcond && linp != linbuf && !(flag & FANCY) &&
1087             ((pstatus == status && pp->p_reason == reason) ||
1088              !(flag & REASON)))
1089             xputchar(' ');
1090         else {
1091             if (pcond && linp != linbuf)
1092                 xputchar('\n');
1093             if (flag & NUMBER) {
1094 #ifdef BACKPIPE
1095                 pcond = ((pp == tp && !inpipe) ||
1096                          (inpipe && pipetail == tp && pp == pipehead));
1097 #else /* BACKPIPE */
1098                 pcond = (pp == tp);
1099 #endif /* BACKPIPE */
1100                 if (pcond)
1101                     xprintf("[%d]%s %c ", pp->p_index,
1102                             pp->p_index < 10 ? " " : "",
1103                             pp == pcurrent ? '+' :
1104                             (pp == pprevious ? '-' : ' '));
1105                 else
1106                     xprintf("       ");
1107             }
1108             if (flag & FANCY) {
1109 #ifdef TCF
1110                 extern char *sitename();
1111
1112 #endif /* TCF */
1113                 xprintf("%5d ", pp->p_procid);
1114 #ifdef TCF
1115                 xprintf("%11s ", sitename(pp->p_procid));
1116 #endif /* TCF */
1117             }
1118             if (flag & (REASON | AREASON)) {
1119                 if (flag & NAME)
1120                     format = "%-30s";
1121                 else
1122                     format = "%s";
1123                 if (pstatus == status) {
1124                     if (pp->p_reason == reason) {
1125                         xprintf(format, "");
1126                         goto prcomd;
1127                     }
1128                     else
1129                         reason = (int) pp->p_reason;
1130                 }
1131                 else {
1132                     status = pstatus;
1133                     reason = (int) pp->p_reason;
1134                 }
1135                 switch (status) {
1136
1137                 case PRUNNING:
1138                     xprintf(format, CGETS(17, 4, "Running "));
1139                     break;
1140
1141                 case PINTERRUPTED:
1142                 case PSTOPPED:
1143                 case PSIGNALED:
1144                     /*
1145                      * tell what happened to the background job
1146                      * From: Michael Schroeder 
1147                      * <mlschroe@immd4.informatik.uni-erlangen.de>
1148                      */
1149                     if ((flag & REASON)
1150                         || ((flag & AREASON)
1151                             && reason != SIGINT
1152                             && (reason != SIGPIPE
1153                                 || (pp->p_flags & PPOU) == 0))) {
1154                         const char *ptr;
1155                         char buf[1024];
1156
1157                         if ((ptr = mesg[pp->p_reason & ASCII].pname) == NULL) {
1158                             xsnprintf(buf, sizeof(buf), "%s %d",
1159                                 CGETS(17, 5, "Signal"), pp->p_reason & ASCII);
1160                             ptr = buf;
1161                         }
1162                         xprintf(format, ptr);
1163                     }
1164                     else
1165                         reason = -1;
1166                     break;
1167
1168                 case PNEXITED:
1169                 case PAEXITED:
1170                     if (flag & REASON) {
1171                         if (pp->p_reason)
1172                             xprintf(CGETS(17, 6, "Exit %-25d"), pp->p_reason);
1173                         else
1174                             xprintf(format, CGETS(17, 7, "Done"));
1175                     }
1176                     break;
1177
1178                 default:
1179                     xprintf(CGETS(17, 8, "BUG: status=%-9o"),
1180                             status);
1181                 }
1182             }
1183         }
1184 prcomd:
1185         if (flag & NAME) {
1186             xprintf("%S", pp->p_command);
1187             if (pp->p_flags & PPOU)
1188                 xprintf(" |");
1189             if (pp->p_flags & PDIAG)
1190                 xprintf("&");
1191         }
1192         if (flag & (REASON | AREASON) && pp->p_flags & PDUMPED)
1193             xprintf(CGETS(17, 9, " (core dumped)"));
1194         if (tp == pp->p_friends) {
1195             if (flag & AMPERSAND)
1196                 xprintf(" &");
1197             if (flag & JOBDIR &&
1198                 !eq(tp->p_cwd->di_name, dcwd->di_name)) {
1199                 xprintf(CGETS(17, 10, " (wd: "));
1200                 dtildepr(tp->p_cwd->di_name);
1201                 xprintf(")");
1202             }
1203         }
1204         if (pp->p_flags & PPTIME && !(status & (PSTOPPED | PRUNNING))) {
1205             if (linp != linbuf)
1206                 xprintf("\n\t");
1207 #if defined(BSDTIMES) || defined(_SEQUENT_)
1208             prusage(&zru, &pp->p_rusage, &pp->p_etime,
1209                     &pp->p_btime);
1210 #else /* !BSDTIMES && !SEQUENT */
1211             lru.tms_utime = pp->p_utime;
1212             lru.tms_stime = pp->p_stime;
1213             lru.tms_cutime = 0;
1214             lru.tms_cstime = 0;
1215             prusage(&zru, &lru, pp->p_etime,
1216                     pp->p_btime);
1217 #endif /* !BSDTIMES && !SEQUENT */
1218
1219         }
1220 #ifdef BACKPIPE
1221         pcond = ((tp == pp->p_friends && !inpipe) ||
1222                  (inpipe && pipehead->p_friends == tp && pp == pipetail));
1223 #else  /* !BACKPIPE */
1224         pcond = (tp == pp->p_friends);
1225 #endif /* BACKPIPE */
1226         if (pcond) {
1227             if (linp != linbuf)
1228                 xputchar('\n');
1229             if (flag & SHELLDIR && !eq(tp->p_cwd->di_name, dcwd->di_name)) {
1230                 xprintf(CGETS(17, 11, "(wd now: "));
1231                 dtildepr(dcwd->di_name);
1232                 xprintf(")\n");
1233             }
1234         }
1235 #ifdef BACKPIPE
1236         if (inpipe) {
1237             /*
1238              * if pmaker == pipetail, we are finished that pipeline, and
1239              * can now skip to past the head
1240              */
1241             if (pmarker == pipetail) {
1242                 inpipe = 0;
1243                 pp = pipehead;
1244             }
1245             else {
1246             /*
1247              * set pp to one before the one we want next, so the while below
1248              * increments to the correct spot.
1249              */
1250                 do
1251                     pp = pp->p_friends;
1252                 while (pp->p_friends->p_friends != pmarker);
1253                 pmarker = pp->p_friends;
1254             }
1255         }
1256         pcond = ((pp = pp->p_friends) != tp || inpipe);
1257 #else /* !BACKPIPE */
1258         pcond = ((pp = pp->p_friends) != tp);
1259 #endif /* BACKPIPE */
1260     } while (pcond);
1261
1262     if (jobflags & PTIME && (jobflags & (PSTOPPED | PRUNNING)) == 0) {
1263         if (jobflags & NUMBER)
1264             xprintf("       ");
1265         ptprint(tp);
1266     }
1267     return (jobflags);
1268 }
1269
1270 /*
1271  * All 4.3 BSD derived implementations are buggy and I've had enough.
1272  * The following implementation produces similar code and works in all
1273  * cases. The 4.3BSD one works only for <, >, !=
1274  */
1275 # undef timercmp
1276 #  define timercmp(tvp, uvp, cmp) \
1277       (((tvp)->tv_sec == (uvp)->tv_sec) ? \
1278            ((tvp)->tv_usec cmp (uvp)->tv_usec) : \
1279            ((tvp)->tv_sec  cmp (uvp)->tv_sec))
1280
1281 static void
1282 ptprint(tp)
1283     struct process *tp;
1284 {
1285 #ifdef BSDTIMES
1286     struct timeval tetime, diff;
1287     static struct timeval ztime;
1288     struct sysrusage ru;
1289     struct process *pp = tp;
1290
1291     ru = zru;
1292     tetime = ztime;
1293     do {
1294         ruadd(&ru, &pp->p_rusage);
1295         tvsub(&diff, &pp->p_etime, &pp->p_btime);
1296         if (timercmp(&diff, &tetime, >))
1297             tetime = diff;
1298     } while ((pp = pp->p_friends) != tp);
1299     prusage(&zru, &ru, &tetime, &ztime);
1300 #else /* !BSDTIMES */
1301 # ifdef _SEQUENT_
1302     timeval_t tetime, diff;
1303     static timeval_t ztime;
1304     struct process_stats ru;
1305     struct process *pp = tp;
1306
1307     ru = zru;
1308     tetime = ztime;
1309     do {
1310         ruadd(&ru, &pp->p_rusage);
1311         tvsub(&diff, &pp->p_etime, &pp->p_btime);
1312         if (timercmp(&diff, &tetime, >))
1313             tetime = diff;
1314     } while ((pp = pp->p_friends) != tp);
1315     prusage(&zru, &ru, &tetime, &ztime);
1316 # else /* !_SEQUENT_ */
1317 #  ifndef POSIX
1318     static time_t ztime = 0;
1319     static time_t zu_time = 0;
1320     static time_t zs_time = 0;
1321     time_t  tetime, diff;
1322     time_t  u_time, s_time;
1323
1324 #  else /* POSIX */
1325     static clock_t ztime = 0;
1326     static clock_t zu_time = 0;
1327     static clock_t zs_time = 0;
1328     clock_t tetime, diff;
1329     clock_t u_time, s_time;
1330
1331 #  endif /* POSIX */
1332     struct tms zts, rts;
1333     struct process *pp = tp;
1334
1335     u_time = zu_time;
1336     s_time = zs_time;
1337     tetime = ztime;
1338     do {
1339         u_time += pp->p_utime;
1340         s_time += pp->p_stime;
1341         diff = pp->p_etime - pp->p_btime;
1342         if (diff > tetime)
1343             tetime = diff;
1344     } while ((pp = pp->p_friends) != tp);
1345     zts.tms_utime = zu_time;
1346     zts.tms_stime = zs_time;
1347     zts.tms_cutime = 0;
1348     zts.tms_cstime = 0;
1349     rts.tms_utime = u_time;
1350     rts.tms_stime = s_time;
1351     rts.tms_cutime = 0;
1352     rts.tms_cstime = 0;
1353     prusage(&zts, &rts, tetime, ztime);
1354 # endif /* !_SEQUENT_ */
1355 #endif  /* !BSDTIMES */
1356 }
1357
1358 /*
1359  * dojobs - print all jobs
1360  */
1361 /*ARGSUSED*/
1362 void
1363 dojobs(v, c)
1364     Char  **v;
1365     struct command *c;
1366 {
1367     struct process *pp;
1368     int flag = NUMBER | NAME | REASON;
1369     int     i;
1370
1371     USE(c);
1372     if (chkstop)
1373         chkstop = 2;
1374     if (*++v) {
1375         if (v[1] || !eq(*v, STRml))
1376             stderror(ERR_JOBS);
1377         flag |= FANCY | JOBDIR;
1378     }
1379     for (i = 1; i <= pmaxindex; i++)
1380         for (pp = proclist.p_next; pp; pp = pp->p_next)
1381             if (pp->p_index == i && pp->p_procid == pp->p_jobid) {
1382                 pp->p_flags &= ~PNEEDNOTE;
1383                 if (!(pprint(pp, flag) & (PRUNNING | PSTOPPED)))
1384                     pflush(pp);
1385                 break;
1386             }
1387 }
1388
1389 /*
1390  * dofg - builtin - put the job into the foreground
1391  */
1392 /*ARGSUSED*/
1393 void
1394 dofg(v, c)
1395     Char  **v;
1396     struct command *c;
1397 {
1398     struct process *pp;
1399
1400     USE(c);
1401     okpcntl();
1402     ++v;
1403     do {
1404         pp = pfind(*v);
1405         if (!pstart(pp, 1)) {
1406             pp->p_procid = 0;
1407             stderror(ERR_NAME|ERR_BADJOB, pp->p_command, strerror(errno));
1408             continue;
1409         }
1410 #ifndef BSDSIGS
1411 # ifdef notdef
1412         if (setintr)
1413             sigignore(SIGINT);
1414 # endif
1415 #endif /* !BSDSIGS */
1416         pjwait(pp);
1417     } while (*v && *++v);
1418 }
1419
1420 /*
1421  * %... - builtin - put the job into the foreground
1422  */
1423 /*ARGSUSED*/
1424 void
1425 dofg1(v, c)
1426     Char  **v;
1427     struct command *c;
1428 {
1429     struct process *pp;
1430
1431     USE(c);
1432     okpcntl();
1433     pp = pfind(v[0]);
1434     if (!pstart(pp, 1)) {
1435         pp->p_procid = 0;
1436         stderror(ERR_NAME|ERR_BADJOB, pp->p_command, strerror(errno));
1437         return;
1438     }
1439 #ifndef BSDSIGS
1440 # ifdef notdef
1441     if (setintr)
1442         sigignore(SIGINT);
1443 # endif
1444 #endif /* !BSDSIGS */
1445     pjwait(pp);
1446 }
1447
1448 /*
1449  * dobg - builtin - put the job into the background
1450  */
1451 /*ARGSUSED*/
1452 void
1453 dobg(v, c)
1454     Char  **v;
1455     struct command *c;
1456 {
1457     struct process *pp;
1458
1459     USE(c);
1460     okpcntl();
1461     ++v;
1462     do {
1463         pp = pfind(*v);
1464         if (!pstart(pp, 0)) {
1465             pp->p_procid = 0;
1466             stderror(ERR_NAME|ERR_BADJOB, pp->p_command, strerror(errno));
1467         }
1468     } while (*v && *++v);
1469 }
1470
1471 /*
1472  * %... & - builtin - put the job into the background
1473  */
1474 /*ARGSUSED*/
1475 void
1476 dobg1(v, c)
1477     Char  **v;
1478     struct command *c;
1479 {
1480     struct process *pp;
1481
1482     USE(c);
1483     pp = pfind(v[0]);
1484     if (!pstart(pp, 0)) {
1485         pp->p_procid = 0;
1486         stderror(ERR_NAME|ERR_BADJOB, pp->p_command, strerror(errno));
1487     }
1488 }
1489
1490 /*
1491  * dostop - builtin - stop the job
1492  */
1493 /*ARGSUSED*/
1494 void
1495 dostop(v, c)
1496     Char  **v;
1497     struct command *c;
1498 {
1499     USE(c);
1500 #ifdef BSDJOBS
1501     pkill(++v, SIGSTOP);
1502 #endif /* BSDJOBS */
1503 }
1504
1505 /*
1506  * dokill - builtin - superset of kill (1)
1507  */
1508 /*ARGSUSED*/
1509 void
1510 dokill(v, c)
1511     Char  **v;
1512     struct command *c;
1513 {
1514     int signum, len = 0;
1515     const char *name;
1516     Char *sigptr;
1517
1518     USE(c);
1519     v++;
1520     if (v[0] && v[0][0] == '-') {
1521         if (v[0][1] == 'l') {
1522             for (signum = 0; signum <= nsig; signum++) {
1523                 if ((name = mesg[signum].iname) != NULL) {
1524                     len += strlen(name) + 1;
1525                     if (len >= T_Cols - 1) {
1526                         xputchar('\n');
1527                         len = strlen(name) + 1;
1528                     }
1529                     xprintf("%s ", name);
1530                 }
1531             }
1532             xputchar('\n');
1533             return;
1534         }
1535         sigptr = &v[0][1];
1536         if (v[0][1] == 's') {
1537             if (v[1]) {
1538                 v++;
1539                 sigptr = &v[0][0];
1540             } else {
1541                 stderror(ERR_NAME | ERR_TOOFEW);
1542             }
1543         }
1544         if (Isdigit(*sigptr)) {
1545             char *ep;
1546             signum = strtoul(short2str(sigptr), &ep, 0);
1547             if (*ep || signum < 0 || signum > (MAXSIG-1))
1548                 stderror(ERR_NAME | ERR_BADSIG);
1549         }
1550         else {
1551             for (signum = 0; signum <= nsig; signum++)
1552                 if (mesg[signum].iname &&
1553                     eq(sigptr, str2short(mesg[signum].iname)))
1554                     goto gotsig;
1555             setname(short2str(sigptr));
1556             stderror(ERR_NAME | ERR_UNKSIG);
1557         }
1558 gotsig:
1559         v++;
1560     }
1561     else
1562         signum = SIGTERM;
1563     pkill(v, signum);
1564 }
1565
1566 static void
1567 pkill(v, signum)
1568     Char  **v;
1569     int     signum;
1570 {
1571     struct process *pp, *np;
1572     int jobflags = 0, err1 = 0;
1573     pid_t     pid;
1574 #ifdef BSDSIGS
1575     sigmask_t omask;
1576 #endif /* BSDSIGS */
1577     Char   *cp, **vp;
1578
1579 #ifdef BSDSIGS
1580     omask = sigmask(SIGCHLD);
1581     if (setintr)
1582         omask |= sigmask(SIGINT);
1583     omask = sigblock(omask) & ~omask;
1584 #else /* !BSDSIGS */
1585     if (setintr)
1586         (void) sighold(SIGINT);
1587     (void) sighold(SIGCHLD);
1588 #endif /* !BSDSIGS */
1589
1590     /* Avoid globbing %?x patterns */
1591     for (vp = v; vp && *vp; vp++)
1592         if (**vp == '%')
1593             (void) quote(*vp);
1594
1595     gflag = 0, tglob(v);
1596     if (gflag) {
1597         v = globall(v);
1598         if (v == 0)
1599             stderror(ERR_NAME | ERR_NOMATCH);
1600     }
1601     else {
1602         v = gargv = saveblk(v);
1603         trim(v);
1604     }
1605
1606
1607     while (v && (cp = *v)) {
1608         if (*cp == '%') {
1609             np = pp = pfind(cp);
1610             do
1611                 jobflags |= np->p_flags;
1612             while ((np = np->p_friends) != pp);
1613 #ifdef BSDJOBS
1614             switch (signum) {
1615
1616             case SIGSTOP:
1617             case SIGTSTP:
1618             case SIGTTIN:
1619             case SIGTTOU:
1620                 if ((jobflags & PRUNNING) == 0) {
1621 # ifdef SUSPENDED
1622                     xprintf(CGETS(17, 12, "%S: Already suspended\n"), cp);
1623 # else /* !SUSPENDED */
1624                     xprintf(CGETS(17, 13, "%S: Already stopped\n"), cp);
1625 # endif /* !SUSPENDED */
1626                     err1++;
1627                     goto cont;
1628                 }
1629                 break;
1630                 /*
1631                  * suspend a process, kill -CONT %, then type jobs; the shell
1632                  * says it is suspended, but it is running; thanks jaap..
1633                  */
1634             case SIGCONT:
1635                 if (!pstart(pp, 0)) {
1636                     pp->p_procid = 0;
1637                     stderror(ERR_NAME|ERR_BADJOB, pp->p_command,
1638                              strerror(errno));
1639                 }
1640                 goto cont;
1641             default:
1642                 break;
1643             }
1644 #endif /* BSDJOBS */
1645             if (killpg(pp->p_jobid, signum) < 0) {
1646                 xprintf("%S: %s\n", cp, strerror(errno));
1647                 err1++;
1648             }
1649 #ifdef BSDJOBS
1650             if (signum == SIGTERM || signum == SIGHUP)
1651                 (void) killpg(pp->p_jobid, SIGCONT);
1652 #endif /* BSDJOBS */
1653         }
1654         else if (!(Isdigit(*cp) || *cp == '-'))
1655             stderror(ERR_NAME | ERR_JOBARGS);
1656         else {
1657             char *ep;
1658 #ifndef WINNT_NATIVE
1659             pid = strtol(short2str(cp), &ep, 10);
1660 #else
1661             pid = strtoul(short2str(cp), &ep, 0);
1662 #endif /* WINNT_NATIVE */
1663             if (*ep)
1664                 stderror(ERR_NAME | ERR_JOBARGS);
1665             else if (kill(pid, signum) < 0) {
1666                 xprintf("%d: %s\n", pid, strerror(errno));
1667                 err1++;
1668                 goto cont;
1669             }
1670 #ifdef BSDJOBS
1671             if (signum == SIGTERM || signum == SIGHUP)
1672                 (void) kill(pid, SIGCONT);
1673 #endif /* BSDJOBS */
1674         }
1675 cont:
1676         v++;
1677     }
1678     if (gargv)
1679         blkfree(gargv), gargv = 0;
1680 #ifdef BSDSIGS
1681     (void) sigsetmask(omask);
1682 #else /* !BSDSIGS */
1683     (void) sigrelse(SIGCHLD);
1684     if (setintr)
1685         (void) sigrelse(SIGINT);
1686 #endif /* !BSDSIGS */
1687     if (err1)
1688         stderror(ERR_SILENT);
1689 }
1690
1691 /*
1692  * pstart - start the job in foreground/background
1693  */
1694 int
1695 pstart(pp, foregnd)
1696     struct process *pp;
1697     int     foregnd;
1698 {
1699     int rv = 0;
1700     struct process *np;
1701 #ifdef BSDSIGS
1702     sigmask_t omask;
1703 #endif /* BSDSIGS */
1704     /* We don't use jobflags in this function right now (see below) */
1705     /* long    jobflags = 0; */
1706
1707 #ifdef BSDSIGS
1708     omask = sigblock(sigmask(SIGCHLD));
1709 #else /* !BSDSIGS */
1710     (void) sighold(SIGCHLD);
1711 #endif
1712     np = pp;
1713     do {
1714         /* We don't use jobflags in this function right now (see below) */
1715         /* jobflags |= np->p_flags; */
1716         if (np->p_flags & (PRUNNING | PSTOPPED)) {
1717             np->p_flags |= PRUNNING;
1718             np->p_flags &= ~PSTOPPED;
1719             if (foregnd)
1720                 np->p_flags |= PFOREGND;
1721             else
1722                 np->p_flags &= ~PFOREGND;
1723         }
1724     } while ((np = np->p_friends) != pp);
1725     if (!foregnd)
1726         pclrcurr(pp);
1727     (void) pprint(pp, foregnd ? NAME | JOBDIR : NUMBER | NAME | AMPERSAND);
1728
1729     /* GrP run jobcmd hook if foregrounding */
1730     if (foregnd) {
1731         job_cmd(pp->p_command);
1732     }
1733
1734 #ifdef BSDJOBS
1735     if (foregnd) {
1736         rv = tcsetpgrp(FSHTTY, pp->p_jobid);
1737     }
1738     /*
1739      * 1. child process of csh (shell script) receives SIGTTIN/SIGTTOU
1740      * 2. parent process (csh) receives SIGCHLD
1741      * 3. The "csh" signal handling function pchild() is invoked
1742      *    with a SIGCHLD signal.
1743      * 4. pchild() calls wait3(WNOHANG) which returns 0.
1744      *    The child process is NOT ready to be waited for at this time.
1745      *    pchild() returns without picking-up the correct status
1746      *    for the child process which generated the SIGCHILD.
1747      * 5. CONSEQUENCE : csh is UNaware that the process is stopped
1748      * 6. THIS LINE HAS BEEN COMMENTED OUT : if (jobflags&PSTOPPED)
1749      *    (beto@aixwiz.austin.ibm.com - aug/03/91)
1750      * 7. I removed the line completely and added extra checks for
1751      *    pstart, so that if a job gets attached to and dies inside
1752      *    a debugger it does not confuse the shell. [christos]
1753      * 8. on the nec sx-4 there seems to be a problem, which requires
1754      *    a syscall(151, getpid(), getpid()) in osinit. Don't ask me
1755      *    what this is doing. [schott@rzg.mpg.de]
1756      */
1757
1758     if (rv != -1)
1759         rv = killpg(pp->p_jobid, SIGCONT);
1760 #endif /* BSDJOBS */
1761 #ifdef BSDSIGS
1762     (void) sigsetmask(omask);
1763 #else /* !BSDSIGS */
1764     (void) sigrelse(SIGCHLD);
1765 #endif /* !BSDSIGS */
1766     return rv != -1;
1767 }
1768
1769 void
1770 panystop(neednl)
1771     int    neednl;
1772 {
1773     struct process *pp;
1774
1775     chkstop = 2;
1776     for (pp = proclist.p_next; pp; pp = pp->p_next)
1777         if (pp->p_flags & PSTOPPED)
1778             stderror(ERR_STOPPED, neednl ? "\n" : "");
1779 }
1780
1781 struct process *
1782 pfind(cp)
1783     Char   *cp;
1784 {
1785     struct process *pp, *np;
1786
1787     if (cp == 0 || cp[1] == 0 || eq(cp, STRcent2) || eq(cp, STRcentplus)) {
1788         if (pcurrent == NULL)
1789             stderror(ERR_NAME | ERR_JOBCUR);
1790         return (pcurrent);
1791     }
1792     if (eq(cp, STRcentminus) || eq(cp, STRcenthash)) {
1793         if (pprevious == NULL)
1794             stderror(ERR_NAME | ERR_JOBPREV);
1795         return (pprevious);
1796     }
1797     if (Isdigit(cp[1])) {
1798         int     idx = atoi(short2str(cp + 1));
1799
1800         for (pp = proclist.p_next; pp; pp = pp->p_next)
1801             if (pp->p_index == idx && pp->p_procid == pp->p_jobid)
1802                 return (pp);
1803         stderror(ERR_NAME | ERR_NOSUCHJOB);
1804     }
1805     np = NULL;
1806     for (pp = proclist.p_next; pp; pp = pp->p_next)
1807         if (pp->p_procid == pp->p_jobid) {
1808             if (cp[1] == '?') {
1809                 Char *dp;
1810
1811                 for (dp = pp->p_command; *dp; dp++) {
1812                     if (*dp != cp[2])
1813                         continue;
1814                     if (prefix(cp + 2, dp))
1815                         goto match;
1816                 }
1817             }
1818             else if (prefix(cp + 1, pp->p_command)) {
1819         match:
1820                 if (np)
1821                     stderror(ERR_NAME | ERR_AMBIG);
1822                 np = pp;
1823             }
1824         }
1825     if (np)
1826         return (np);
1827     stderror(ERR_NAME | (cp[1] == '?' ? ERR_JOBPAT : ERR_NOSUCHJOB));
1828     /* NOTREACHED */
1829     return (0);
1830 }
1831
1832
1833 /*
1834  * pgetcurr - find most recent job that is not pp, preferably stopped
1835  */
1836 static struct process *
1837 pgetcurr(pp)
1838     struct process *pp;
1839 {
1840     struct process *np;
1841     struct process *xp = NULL;
1842
1843     for (np = proclist.p_next; np; np = np->p_next)
1844         if (np != pcurrent && np != pp && np->p_procid &&
1845             np->p_procid == np->p_jobid) {
1846             if (np->p_flags & PSTOPPED)
1847                 return (np);
1848             if (xp == NULL)
1849                 xp = np;
1850         }
1851     return (xp);
1852 }
1853
1854 /*
1855  * donotify - flag the job so as to report termination asynchronously
1856  */
1857 /*ARGSUSED*/
1858 void
1859 donotify(v, c)
1860     Char  **v;
1861     struct command *c;
1862 {
1863     struct process *pp;
1864
1865     USE(c);
1866     pp = pfind(*++v);
1867     pp->p_flags |= PNOTIFY;
1868 }
1869
1870 /*
1871  * Do the fork and whatever should be done in the child side that
1872  * should not be done if we are not forking at all (like for simple builtin's)
1873  * Also do everything that needs any signals fiddled with in the parent side
1874  *
1875  * Wanttty tells whether process and/or tty pgrps are to be manipulated:
1876  *      -1:     leave tty alone; inherit pgrp from parent
1877  *       0:     already have tty; manipulate process pgrps only
1878  *       1:     want to claim tty; manipulate process and tty pgrps
1879  * It is usually just the value of tpgrp.
1880  */
1881
1882 int
1883 pfork(t, wanttty)
1884     struct command *t;          /* command we are forking for */
1885     int     wanttty;
1886 {
1887     int pid;
1888     int    ignint = 0;
1889     int     pgrp;
1890 #ifdef BSDSIGS
1891     sigmask_t omask = 0;
1892 #endif /* BSDSIGS */
1893 #ifdef SIGSYNCH
1894     sigvec_t osv;
1895     static sigvec_t nsv = {synch_handler, (sigset_t) ~0, 0};
1896 #endif /* SIGSYNCH */
1897
1898     /*
1899      * A child will be uninterruptible only under very special conditions.
1900      * Remember that the semantics of '&' is implemented by disconnecting the
1901      * process from the tty so signals do not need to ignored just for '&'.
1902      * Thus signals are set to default action for children unless: we have had
1903      * an "onintr -" (then specifically ignored) we are not playing with
1904      * signals (inherit action)
1905      */
1906     if (setintr)
1907         ignint = (tpgrp == -1 && (t->t_dflg & F_NOINTERRUPT))
1908             || (gointr && eq(gointr, STRminus));
1909
1910 #ifdef COHERENT
1911     ignint |= gointr && eq(gointr, STRminus);
1912 #endif /* COHERENT */
1913
1914     /*
1915      * Check for maximum nesting of 16 processes to avoid Forking loops
1916      */
1917     if (child == 16)
1918         stderror(ERR_NESTING, 16);
1919 #ifdef SIGSYNCH
1920     if (mysigvec(SIGSYNCH, &nsv, &osv))
1921         stderror(ERR_SYSTEM, "pfork: sigvec set", strerror(errno));
1922 #endif /* SIGSYNCH */
1923     /*
1924      * Hold SIGCHLD until we have the process installed in our table.
1925      */
1926     if (wanttty < 0) {
1927 #ifdef BSDSIGS
1928         omask = sigblock(sigmask(SIGCHLD));
1929 #else /* !BSDSIGS */
1930         (void) sighold(SIGCHLD);
1931 #endif /* !BSDSIGS */
1932     }
1933     while ((pid = fork()) == -1)
1934         if (setintr == 0)
1935             (void) sleep(FORKSLEEP);
1936         else {
1937             if (wanttty < 0)
1938 #ifdef BSDSIGS
1939                 (void) sigsetmask(omask);
1940 #else /* !BSDSIGS */
1941                 (void) sigrelse(SIGCHLD);
1942             (void) sigrelse(SIGINT);
1943 #endif /* !BSDSIGS */
1944             stderror(ERR_NOPROC);
1945         }
1946     if (pid == 0) {
1947         settimes();
1948         pgrp = pcurrjob ? pcurrjob->p_jobid : getpid();
1949         pflushall();
1950         pcurrjob = NULL;
1951 #if !defined(BSDTIMES) && !defined(_SEQUENT_) 
1952         timesdone = 0;
1953 #endif /* !defined(BSDTIMES) && !defined(_SEQUENT_) */
1954         child++;
1955         if (setintr) {
1956             setintr = 0;        /* until I think otherwise */
1957 #ifndef BSDSIGS
1958             if (wanttty < 0)
1959                 (void) sigrelse(SIGCHLD);
1960 #endif /* !BSDSIGS */
1961             /*
1962              * Children just get blown away on SIGINT, SIGQUIT unless "onintr
1963              * -" seen.
1964              */
1965             (void) signal(SIGINT, ignint ? SIG_IGN : SIG_DFL);
1966             (void) signal(SIGQUIT, ignint ? SIG_IGN : SIG_DFL);
1967 #ifdef BSDJOBS
1968             if (wanttty >= 0) {
1969                 /* make stoppable */
1970                 (void) signal(SIGTSTP, SIG_DFL);
1971                 (void) signal(SIGTTIN, SIG_DFL);
1972                 (void) signal(SIGTTOU, SIG_DFL);
1973             }
1974 #endif /* BSDJOBS */
1975             (void) signal(SIGTERM, parterm);
1976         }
1977         else if (tpgrp == -1 && (t->t_dflg & F_NOINTERRUPT)) {
1978             (void) signal(SIGINT, SIG_IGN);
1979             (void) signal(SIGQUIT, SIG_IGN);
1980         }
1981 #ifdef OREO
1982         sigignore(SIGIO);       /* ignore SIGIO in child too */
1983 #endif /* OREO */
1984
1985         pgetty(wanttty, pgrp);
1986         /*
1987          * Nohup and nice apply only to NODE_COMMAND's but it would be nice
1988          * (?!?) if you could say "nohup (foo;bar)" Then the parser would have
1989          * to know about nice/nohup/time
1990          */
1991         if (t->t_dflg & F_NOHUP)
1992             (void) signal(SIGHUP, SIG_IGN);
1993         if (t->t_dflg & F_NICE) {
1994             int nval = SIGN_EXTEND_CHAR(t->t_nice);
1995 #ifdef HAVE_SETPRIORITY
1996             if (setpriority(PRIO_PROCESS, 0, nval) == -1 && errno)
1997                     stderror(ERR_SYSTEM, "setpriority", strerror(errno));
1998 #else /* !HAVE_SETPRIORITY */
1999             (void) nice(nval);
2000 #endif /* !HAVE_SETPRIORITY */
2001         }
2002 #ifdef F_VER
2003         if (t->t_dflg & F_VER) {
2004             tsetenv(STRSYSTYPE, t->t_systype ? STRbsd43 : STRsys53);
2005             dohash(NULL, NULL);
2006         }
2007 #endif /* F_VER */
2008 #ifdef SIGSYNCH
2009         /* rfw 8/89 now parent can continue */
2010         if (kill(getppid(), SIGSYNCH))
2011             stderror(ERR_SYSTEM, "pfork child: kill", strerror(errno));
2012 #endif /* SIGSYNCH */
2013
2014     }
2015     else {
2016 #ifdef POSIXJOBS
2017         if (wanttty >= 0) {
2018             /*
2019              * `Walking' process group fix from Beto Appleton.
2020              * (beto@aixwiz.austin.ibm.com)
2021              * If setpgid fails at this point that means that
2022              * our process leader has died. We flush the current
2023              * job and become the process leader ourselves.
2024              * The parent will figure that out later.
2025              */
2026             pgrp = pcurrjob ? pcurrjob->p_jobid : pid;
2027             if (setpgid(pid, pgrp) == -1 && errno == EPERM) {
2028                 pcurrjob = NULL;
2029                 /* 
2030                  * We don't care if this causes an error here;
2031                  * then we are already in the right process group
2032                  */
2033                 (void) setpgid(pid, pgrp = pid);
2034             }
2035         }
2036 #endif /* POSIXJOBS */
2037         palloc(pid, t);
2038 #ifdef SIGSYNCH
2039         /*
2040          * rfw 8/89 Wait for child to own terminal.  Solves half of ugly
2041          * synchronization problem.  With this change, we know that the only
2042          * reason setpgrp to a previous process in a pipeline can fail is that
2043          * the previous process has already exited. Without this hack, he may
2044          * either have exited or not yet started to run.  Two uglies become
2045          * one.
2046          */
2047         (void) sigpause(omask & ~SYNCHMASK);
2048         if (mysigvec(SIGSYNCH, &osv, NULL))
2049             stderror(ERR_SYSTEM, "pfork parent: sigvec restore",
2050                      strerror(errno));
2051 #endif /* SIGSYNCH */
2052
2053         if (wanttty < 0) {
2054 #ifdef BSDSIGS
2055             (void) sigsetmask(omask);
2056 #else /* !BSDSIGS */
2057             (void) sigrelse(SIGCHLD);
2058 #endif /* !BSDSIGS */
2059         }
2060     }
2061     return (pid);
2062 }
2063
2064 static void
2065 okpcntl()
2066 {
2067     if (tpgrp == -1)
2068         stderror(ERR_JOBCONTROL);
2069     if (tpgrp == 0)
2070         stderror(ERR_JOBCTRLSUB);
2071 }
2072
2073
2074 static void
2075 setttypgrp(pgrp)
2076     int pgrp;
2077 {
2078     /*
2079      * If we are piping out a builtin, eg. 'echo | more' things can go
2080      * out of sequence, i.e. the more can run before the echo. This
2081      * can happen even if we have vfork, since the echo will be forked
2082      * with the regular fork. In this case, we need to set the tty
2083      * pgrp ourselves. If that happens, then the process will be still
2084      * alive. And the tty process group will already be set.
2085      * This should fix the famous sequent problem as a side effect:
2086      *    The controlling terminal is lost if all processes in the
2087      *    terminal process group are zombies. In this case tcgetpgrp()
2088      *    returns 0. If this happens we must set the terminal process
2089      *    group again.
2090      */
2091     if (tcgetpgrp(FSHTTY) != pgrp) {
2092 #ifdef POSIXJOBS
2093         /*
2094          * tcsetpgrp will set SIGTTOU to all the the processes in 
2095          * the background according to POSIX... We ignore this here.
2096          */
2097         signalfun_t old = sigset(SIGTTOU, SIG_IGN);
2098 #endif
2099         (void) tcsetpgrp(FSHTTY, pgrp);
2100 # ifdef POSIXJOBS
2101         (void) sigset(SIGTTOU, old);
2102 # endif
2103
2104     }
2105 }
2106
2107
2108 /*
2109  * if we don't have vfork(), things can still go in the wrong order
2110  * resulting in the famous 'Stopped (tty output)'. But some systems
2111  * don't permit the setpgid() call, (these are more recent secure
2112  * systems such as ibm's aix), when they do. Then we'd rather print 
2113  * an error message than hang the shell!
2114  * I am open to suggestions how to fix that.
2115  */
2116 void
2117 pgetty(wanttty, pgrp)
2118     int     wanttty, pgrp;
2119 {
2120 #ifdef BSDJOBS
2121 # if defined(BSDSIGS) && defined(POSIXJOBS)
2122     sigmask_t omask = 0;
2123 # endif /* BSDSIGS && POSIXJOBS */
2124
2125 # ifdef JOBDEBUG
2126     xprintf("wanttty %d pid %d opgrp%d pgrp %d tpgrp %d\n", 
2127             wanttty, getpid(), pgrp, mygetpgrp(), tcgetpgrp(FSHTTY));
2128 # endif /* JOBDEBUG */
2129 # ifdef POSIXJOBS
2130     /*
2131      * christos: I am blocking the tty signals till I've set things
2132      * correctly....
2133      */
2134     if (wanttty > 0)
2135 #  ifdef BSDSIGS
2136         omask = sigblock(sigmask(SIGTSTP)|sigmask(SIGTTIN));
2137 #  else /* !BSDSIGS */
2138     {
2139         (void) sighold(SIGTSTP);
2140         (void) sighold(SIGTTIN);
2141     }
2142 #  endif /* !BSDSIGS */
2143 # endif /* POSIXJOBS */
2144
2145 # ifndef POSIXJOBS
2146     if (wanttty > 0)
2147         setttypgrp(pgrp);
2148 # endif /* !POSIXJOBS */
2149
2150     /*
2151      * From: Michael Schroeder <mlschroe@immd4.informatik.uni-erlangen.de>
2152      * Don't check for tpgrp >= 0 so even non-interactive shells give
2153      * background jobs process groups Same for the comparison in the other part
2154      * of the #ifdef
2155      */
2156     if (wanttty >= 0) {
2157         if (setpgid(0, pgrp) == -1) {
2158 # ifdef POSIXJOBS
2159             /* Walking process group fix; see above */
2160             if (setpgid(0, pgrp = getpid()) == -1) {
2161 # endif /* POSIXJOBS */
2162                 stderror(ERR_SYSTEM, "setpgid child:\n", strerror(errno));
2163                 xexit(0);
2164 # ifdef POSIXJOBS
2165             }
2166             wanttty = pgrp;  /* Now we really want the tty, since we became the
2167                               * the process group leader
2168                               */
2169 # endif /* POSIXJOBS */
2170         }
2171     }
2172
2173 # ifdef POSIXJOBS
2174     if (wanttty > 0)
2175         setttypgrp(pgrp);
2176 #  ifdef BSDSIGS
2177     (void) sigsetmask(omask);
2178 #  else /* BSDSIGS */
2179     (void) sigrelse(SIGTSTP);
2180     (void) sigrelse(SIGTTIN);
2181 #  endif /* !BSDSIGS */
2182 # endif /* POSIXJOBS */
2183
2184 # ifdef JOBDEBUG
2185     xprintf("wanttty %d pid %d pgrp %d tpgrp %d\n", 
2186             wanttty, getpid(), mygetpgrp(), tcgetpgrp(FSHTTY));
2187 # endif /* JOBDEBUG */
2188
2189     if (tpgrp > 0)
2190         tpgrp = 0;              /* gave tty away */
2191 #endif /* BSDJOBS */
2192 }