xref: /freebsd/contrib/tcsh/sh.proc.c (revision e4e9813eb92cd7c4d4b819a8fbed5cbd3d92f5d8)
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 }
2193