xref: /386bsd/usr/src/bin/csh/proc.c (revision a2142627)
1 /*-
2  * Copyright (c) 1980, 1991 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *	This product includes software developed by the University of
16  *	California, Berkeley and its contributors.
17  * 4. 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 
34 #ifndef lint
35 static char sccsid[] = "@(#)proc.c	5.22 (Berkeley) 6/14/91";
36 #endif /* not lint */
37 
38 #include <sys/types.h>
39 #include <sys/wait.h>
40 #include <errno.h>
41 #include <unistd.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #if __STDC__
45 # include <stdarg.h>
46 #else
47 # include <varargs.h>
48 #endif
49 
50 #include "csh.h"
51 #include "dir.h"
52 #include "proc.h"
53 #include "extern.h"
54 
55 #define BIGINDEX	9	/* largest desirable job index */
56 
57 static struct rusage zru;
58 
59 static void	 pflushall __P((void));
60 static void	 pflush __P((struct process *));
61 static void	 pclrcurr __P((struct process *));
62 static void	 padd __P((struct command *));
63 static int	 pprint __P((struct process *, int));
64 static void	 ptprint __P((struct process *));
65 static void	 pads __P((Char *));
66 static void	 pkill __P((Char **v, int));
67 static struct	process
68 		*pgetcurr __P((struct process *));
69 static void	 okpcntl __P((void));
70 
71 /*
72  * pchild - called at interrupt level by the SIGCHLD signal
73  *	indicating that at least one child has terminated or stopped
74  *	thus at least one wait system call will definitely return a
75  *	childs status.  Top level routines (like pwait) must be sure
76  *	to mask interrupts when playing with the proclist data structures!
77  */
78 /* ARGUSED */
79 void
pchild(notused)80 pchild(notused)
81 	int notused;
82 {
83     register struct process *pp;
84     register struct process *fp;
85     register int pid;
86     extern int insource;
87     union wait w;
88     int     jobflags;
89     struct rusage ru;
90 
91 loop:
92     errno = 0;			/* reset, just in case */
93     pid = wait3(&w.w_status,
94        (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG), &ru);
95 
96     if (pid <= 0) {
97 	if (errno == EINTR) {
98 	    errno = 0;
99 	    goto loop;
100 	}
101 	pnoprocesses = pid == -1;
102 	return;
103     }
104     for (pp = proclist.p_next; pp != NULL; pp = pp->p_next)
105 	if (pid == pp->p_pid)
106 	    goto found;
107     goto loop;
108 found:
109     if (pid == atoi(short2str(value(STRchild))))
110 	unsetv(STRchild);
111     pp->p_flags &= ~(PRUNNING | PSTOPPED | PREPORTED);
112     if (WIFSTOPPED(w)) {
113 	pp->p_flags |= PSTOPPED;
114 	pp->p_reason = w.w_stopsig;
115     }
116     else {
117 	if (pp->p_flags & (PTIME | PPTIME) || adrof(STRtime))
118 	    (void) gettimeofday(&pp->p_etime, NULL);
119 
120 	pp->p_rusage = ru;
121 	if (WIFSIGNALED(w)) {
122 	    if (w.w_termsig == SIGINT)
123 		pp->p_flags |= PINTERRUPTED;
124 	    else
125 		pp->p_flags |= PSIGNALED;
126 	    if (w.w_coredump)
127 		pp->p_flags |= PDUMPED;
128 	    pp->p_reason = w.w_termsig;
129 	}
130 	else {
131 	    pp->p_reason = w.w_retcode;
132 	    if (pp->p_reason != 0)
133 		pp->p_flags |= PAEXITED;
134 	    else
135 		pp->p_flags |= PNEXITED;
136 	}
137     }
138     jobflags = 0;
139     fp = pp;
140     do {
141 	if ((fp->p_flags & (PPTIME | PRUNNING | PSTOPPED)) == 0 &&
142 	    !child && adrof(STRtime) &&
143 	    fp->p_rusage.ru_utime.tv_sec + fp->p_rusage.ru_stime.tv_sec
144 	    >= atoi(short2str(value(STRtime))))
145 	    fp->p_flags |= PTIME;
146 	jobflags |= fp->p_flags;
147     } while ((fp = fp->p_friends) != pp);
148     pp->p_flags &= ~PFOREGND;
149     if (pp == pp->p_friends && (pp->p_flags & PPTIME)) {
150 	pp->p_flags &= ~PPTIME;
151 	pp->p_flags |= PTIME;
152     }
153     if ((jobflags & (PRUNNING | PREPORTED)) == 0) {
154 	fp = pp;
155 	do {
156 	    if (fp->p_flags & PSTOPPED)
157 		fp->p_flags |= PREPORTED;
158 	} while ((fp = fp->p_friends) != pp);
159 	while (fp->p_pid != fp->p_jobid)
160 	    fp = fp->p_friends;
161 	if (jobflags & PSTOPPED) {
162 	    if (pcurrent && pcurrent != fp)
163 		pprevious = pcurrent;
164 	    pcurrent = fp;
165 	}
166 	else
167 	    pclrcurr(fp);
168 	if (jobflags & PFOREGND) {
169 	    if (jobflags & (PSIGNALED | PSTOPPED | PPTIME) ||
170 #ifdef IIASA
171 		jobflags & PAEXITED ||
172 #endif
173 		!eq(dcwd->di_name, fp->p_cwd->di_name)) {
174 		;		/* print in pjwait */
175 	    }
176 	    /* PWP: print a newline after ^C */
177 	    else if (jobflags & PINTERRUPTED)
178 		xputchar('\r' | QUOTE), xputchar('\n');
179 	}
180 	else {
181 	    if (jobflags & PNOTIFY || adrof(STRnotify)) {
182 		xputchar('\r' | QUOTE), xputchar('\n');
183 		(void) pprint(pp, NUMBER | NAME | REASON);
184 		if ((jobflags & PSTOPPED) == 0)
185 		    pflush(pp);
186 	    }
187 	    else {
188 		fp->p_flags |= PNEEDNOTE;
189 		neednote++;
190 	    }
191 	}
192     }
193     goto loop;
194 }
195 
196 void
pnote()197 pnote()
198 {
199     register struct process *pp;
200     int     flags;
201     sigset_t omask;
202 
203     neednote = 0;
204     for (pp = proclist.p_next; pp != NULL; pp = pp->p_next) {
205 	if (pp->p_flags & PNEEDNOTE) {
206 	    omask = sigblock(sigmask(SIGCHLD));
207 	    pp->p_flags &= ~PNEEDNOTE;
208 	    flags = pprint(pp, NUMBER | NAME | REASON);
209 	    if ((flags & (PRUNNING | PSTOPPED)) == 0)
210 		pflush(pp);
211 	    (void) sigsetmask(omask);
212 	}
213     }
214 }
215 
216 /*
217  * pwait - wait for current job to terminate, maintaining integrity
218  *	of current and previous job indicators.
219  */
220 void
pwait()221 pwait()
222 {
223     register struct process *fp, *pp;
224     sigset_t omask;
225 
226     /*
227      * Here's where dead procs get flushed.
228      */
229     omask = sigblock(sigmask(SIGCHLD));
230     for (pp = (fp = &proclist)->p_next; pp != NULL; pp = (fp = pp)->p_next)
231 	if (pp->p_pid == 0) {
232 	    fp->p_next = pp->p_next;
233 	    xfree((ptr_t) pp->p_command);
234 	    if (pp->p_cwd && --pp->p_cwd->di_count == 0)
235 		if (pp->p_cwd->di_next == 0)
236 		    dfree(pp->p_cwd);
237 	    xfree((ptr_t) pp);
238 	    pp = fp;
239 	}
240     (void) sigsetmask(omask);
241     pjwait(pcurrjob);
242 }
243 
244 
245 /*
246  * pjwait - wait for a job to finish or become stopped
247  *	It is assumed to be in the foreground state (PFOREGND)
248  */
249 void
pjwait(pp)250 pjwait(pp)
251     register struct process *pp;
252 {
253     register struct process *fp;
254     int     jobflags, reason;
255     sigset_t omask;
256 
257     while (pp->p_pid != pp->p_jobid)
258 	pp = pp->p_friends;
259     fp = pp;
260 
261     do {
262 	if ((fp->p_flags & (PFOREGND | PRUNNING)) == PRUNNING)
263 	    xprintf("BUG: waiting for background job!\n");
264     } while ((fp = fp->p_friends) != pp);
265     /*
266      * Now keep pausing as long as we are not interrupted (SIGINT), and the
267      * target process, or any of its friends, are running
268      */
269     fp = pp;
270     omask = sigblock(sigmask(SIGCHLD));
271     for (;;) {
272 	(void) sigblock(sigmask(SIGCHLD));
273 	jobflags = 0;
274 	do
275 	    jobflags |= fp->p_flags;
276 	while ((fp = (fp->p_friends)) != pp);
277 	if ((jobflags & PRUNNING) == 0)
278 	    break;
279 #ifdef JOBDEBUG
280 	xprintf("starting to sigpause for  SIGCHLD on %d\n", fp->p_pid);
281 #endif				/* JOBDEBUG */
282 	(void) sigpause(omask & ~sigmask(SIGCHLD));
283     }
284     (void) sigsetmask(omask);
285     if (tpgrp > 0)		/* get tty back */
286 	(void) tcsetpgrp(FSHTTY, tpgrp);
287     if ((jobflags & (PSIGNALED | PSTOPPED | PTIME)) ||
288 	!eq(dcwd->di_name, fp->p_cwd->di_name)) {
289 	if (jobflags & PSTOPPED) {
290 	    xprintf("\n");
291 	    if (adrof(STRlistjobs)) {
292 		Char   *jobcommand[3];
293 
294 		jobcommand[0] = STRjobs;
295 		if (eq(value(STRlistjobs), STRlong))
296 		    jobcommand[1] = STRml;
297 		else
298 		    jobcommand[1] = NULL;
299 		jobcommand[2] = NULL;
300 
301 		dojobs(jobcommand);
302 		(void) pprint(pp, SHELLDIR);
303 	    }
304 	    else
305 		(void) pprint(pp, AREASON | SHELLDIR);
306 	}
307 	else
308 	    (void) pprint(pp, AREASON | SHELLDIR);
309     }
310     if ((jobflags & (PINTERRUPTED | PSTOPPED)) && setintr &&
311 	(!gointr || !eq(gointr, STRminus))) {
312 	if ((jobflags & PSTOPPED) == 0)
313 	    pflush(pp);
314 	pintr1(0);
315 	/* NOTREACHED */
316     }
317     reason = 0;
318     fp = pp;
319     do {
320 	if (fp->p_reason)
321 	    reason = fp->p_flags & (PSIGNALED | PINTERRUPTED) ?
322 		fp->p_reason | META : fp->p_reason;
323     } while ((fp = fp->p_friends) != pp);
324     if ((reason != 0) && (adrof(STRprintexitvalue)))
325 	xprintf("Exit %d\n", reason);
326     set(STRstatus, putn(reason));
327     if (reason && exiterr)
328 	exitstat();
329     pflush(pp);
330 }
331 
332 /*
333  * dowait - wait for all processes to finish
334  */
335 void
dowait()336 dowait()
337 {
338     register struct process *pp;
339     sigset_t omask;
340 
341     pjobs++;
342     omask = sigblock(sigmask(SIGCHLD));
343 loop:
344     for (pp = proclist.p_next; pp; pp = pp->p_next)
345 	if (pp->p_pid &&	/* pp->p_pid == pp->p_jobid && */
346 	    pp->p_flags & PRUNNING) {
347 	    (void) sigpause((sigset_t) 0);
348 	    goto loop;
349 	}
350     (void) sigsetmask(omask);
351     pjobs = 0;
352 }
353 
354 /*
355  * pflushall - flush all jobs from list (e.g. at fork())
356  */
357 static void
pflushall()358 pflushall()
359 {
360     register struct process *pp;
361 
362     for (pp = proclist.p_next; pp != NULL; pp = pp->p_next)
363 	if (pp->p_pid)
364 	    pflush(pp);
365 }
366 
367 /*
368  * pflush - flag all process structures in the same job as the
369  *	the argument process for deletion.  The actual free of the
370  *	space is not done here since pflush is called at interrupt level.
371  */
372 static void
pflush(pp)373 pflush(pp)
374     register struct process *pp;
375 {
376     register struct process *np;
377     register int idx;
378 
379     if (pp->p_pid == 0) {
380 	xprintf("BUG: process flushed twice");
381 	return;
382     }
383     while (pp->p_pid != pp->p_jobid)
384 	pp = pp->p_friends;
385     pclrcurr(pp);
386     if (pp == pcurrjob)
387 	pcurrjob = 0;
388     idx = pp->p_index;
389     np = pp;
390     do {
391 	np->p_index = np->p_pid = 0;
392 	np->p_flags &= ~PNEEDNOTE;
393     } while ((np = np->p_friends) != pp);
394     if (idx == pmaxindex) {
395 	for (np = proclist.p_next, idx = 0; np; np = np->p_next)
396 	    if (np->p_index > idx)
397 		idx = np->p_index;
398 	pmaxindex = idx;
399     }
400 }
401 
402 /*
403  * pclrcurr - make sure the given job is not the current or previous job;
404  *	pp MUST be the job leader
405  */
406 static void
pclrcurr(pp)407 pclrcurr(pp)
408     register struct process *pp;
409 {
410 
411     if (pp == pcurrent)
412 	if (pprevious != NULL) {
413 	    pcurrent = pprevious;
414 	    pprevious = pgetcurr(pp);
415 	}
416 	else {
417 	    pcurrent = pgetcurr(pp);
418 	    pprevious = pgetcurr(pp);
419 	}
420     else if (pp == pprevious)
421 	pprevious = pgetcurr(pp);
422 }
423 
424 /* +4 here is 1 for '\0', 1 ea for << >& >> */
425 static Char command[PMAXLEN + 4];
426 static int cmdlen;
427 static Char *cmdp;
428 
429 /*
430  * palloc - allocate a process structure and fill it up.
431  *	an important assumption is made that the process is running.
432  */
433 void
palloc(pid,t)434 palloc(pid, t)
435     int     pid;
436     register struct command *t;
437 {
438     register struct process *pp;
439     int     i;
440 
441     pp = (struct process *) xcalloc(1, (size_t) sizeof(struct process));
442     pp->p_pid = pid;
443     pp->p_flags = t->t_dflg & F_AMPERSAND ? PRUNNING : PRUNNING | PFOREGND;
444     if (t->t_dflg & F_TIME)
445 	pp->p_flags |= PPTIME;
446     cmdp = command;
447     cmdlen = 0;
448     padd(t);
449     *cmdp++ = 0;
450     if (t->t_dflg & F_PIPEOUT) {
451 	pp->p_flags |= PPOU;
452 	if (t->t_dflg & F_STDERR)
453 	    pp->p_flags |= PDIAG;
454     }
455     pp->p_command = Strsave(command);
456     if (pcurrjob) {
457 	struct process *fp;
458 
459 	/* careful here with interrupt level */
460 	pp->p_cwd = 0;
461 	pp->p_index = pcurrjob->p_index;
462 	pp->p_friends = pcurrjob;
463 	pp->p_jobid = pcurrjob->p_pid;
464 	for (fp = pcurrjob; fp->p_friends != pcurrjob; fp = fp->p_friends);
465 	fp->p_friends = pp;
466     }
467     else {
468 	pcurrjob = pp;
469 	pp->p_jobid = pid;
470 	pp->p_friends = pp;
471 	pp->p_cwd = dcwd;
472 	dcwd->di_count++;
473 	if (pmaxindex < BIGINDEX)
474 	    pp->p_index = ++pmaxindex;
475 	else {
476 	    struct process *np;
477 
478 	    for (i = 1;; i++) {
479 		for (np = proclist.p_next; np; np = np->p_next)
480 		    if (np->p_index == i)
481 			goto tryagain;
482 		pp->p_index = i;
483 		if (i > pmaxindex)
484 		    pmaxindex = i;
485 		break;
486 	tryagain:;
487 	    }
488 	}
489 	if (pcurrent == NULL)
490 	    pcurrent = pp;
491 	else if (pprevious == NULL)
492 	    pprevious = pp;
493     }
494     pp->p_next = proclist.p_next;
495     proclist.p_next = pp;
496     (void) gettimeofday(&pp->p_btime, NULL);
497 }
498 
499 static void
padd(t)500 padd(t)
501     register struct command *t;
502 {
503     Char  **argp;
504 
505     if (t == 0)
506 	return;
507     switch (t->t_dtyp) {
508 
509     case NODE_PAREN:
510 	pads(STRLparensp);
511 	padd(t->t_dspr);
512 	pads(STRspRparen);
513 	break;
514 
515     case NODE_COMMAND:
516 	for (argp = t->t_dcom; *argp; argp++) {
517 	    pads(*argp);
518 	    if (argp[1])
519 		pads(STRspace);
520 	}
521 	break;
522 
523     case NODE_OR:
524     case NODE_AND:
525     case NODE_PIPE:
526     case NODE_LIST:
527 	padd(t->t_dcar);
528 	switch (t->t_dtyp) {
529 	case NODE_OR:
530 	    pads(STRspor2sp);
531 	    break;
532 	case NODE_AND:
533 	    pads(STRspand2sp);
534 	    break;
535 	case NODE_PIPE:
536 	    pads(STRsporsp);
537 	    break;
538 	case NODE_LIST:
539 	    pads(STRsemisp);
540 	    break;
541 	}
542 	padd(t->t_dcdr);
543 	return;
544     }
545     if ((t->t_dflg & F_PIPEIN) == 0 && t->t_dlef) {
546 	pads((t->t_dflg & F_READ) ? STRspLarrow2sp : STRspLarrowsp);
547 	pads(t->t_dlef);
548     }
549     if ((t->t_dflg & F_PIPEOUT) == 0 && t->t_drit) {
550 	pads((t->t_dflg & F_APPEND) ? STRspRarrow2 : STRspRarrow);
551 	if (t->t_dflg & F_STDERR)
552 	    pads(STRand);
553 	pads(STRspace);
554 	pads(t->t_drit);
555     }
556 }
557 
558 static void
pads(cp)559 pads(cp)
560     Char   *cp;
561 {
562     register int i;
563 
564     /*
565      * Avoid the Quoted Space alias hack! Reported by:
566      * sam@john-bigboote.ICS.UCI.EDU (Sam Horrocks)
567      */
568     if (cp[0] == STRQNULL[0])
569 	cp++;
570 
571     i = Strlen(cp);
572 
573     if (cmdlen >= PMAXLEN)
574 	return;
575     if (cmdlen + i >= PMAXLEN) {
576 	(void) Strcpy(cmdp, STRsp3dots);
577 	cmdlen = PMAXLEN;
578 	cmdp += 4;
579 	return;
580     }
581     (void) Strcpy(cmdp, cp);
582     cmdp += i;
583     cmdlen += i;
584 }
585 
586 /*
587  * psavejob - temporarily save the current job on a one level stack
588  *	so another job can be created.  Used for { } in exp6
589  *	and `` in globbing.
590  */
591 void
psavejob()592 psavejob()
593 {
594 
595     pholdjob = pcurrjob;
596     pcurrjob = NULL;
597 }
598 
599 /*
600  * prestjob - opposite of psavejob.  This may be missed if we are interrupted
601  *	somewhere, but pendjob cleans up anyway.
602  */
603 void
prestjob()604 prestjob()
605 {
606 
607     pcurrjob = pholdjob;
608     pholdjob = NULL;
609 }
610 
611 /*
612  * pendjob - indicate that a job (set of commands) has been completed
613  *	or is about to begin.
614  */
615 void
pendjob()616 pendjob()
617 {
618     register struct process *pp, *tp;
619 
620     if (pcurrjob && (pcurrjob->p_flags & (PFOREGND | PSTOPPED)) == 0) {
621 	pp = pcurrjob;
622 	while (pp->p_pid != pp->p_jobid)
623 	    pp = pp->p_friends;
624 	xprintf("[%d]", pp->p_index);
625 	tp = pp;
626 	do {
627 	    xprintf(" %d", pp->p_pid);
628 	    pp = pp->p_friends;
629 	} while (pp != tp);
630 	xprintf("\n");
631     }
632     pholdjob = pcurrjob = 0;
633 }
634 
635 /*
636  * pprint - print a job
637  */
638 static int
pprint(pp,flag)639 pprint(pp, flag)
640     register struct process *pp;
641     bool    flag;
642 {
643     register status, reason;
644     struct process *tp;
645     extern char *linp, linbuf[];
646     int     jobflags, pstatus;
647     char   *format;
648 
649     while (pp->p_pid != pp->p_jobid)
650 	pp = pp->p_friends;
651     if (pp == pp->p_friends && (pp->p_flags & PPTIME)) {
652 	pp->p_flags &= ~PPTIME;
653 	pp->p_flags |= PTIME;
654     }
655     tp = pp;
656     status = reason = -1;
657     jobflags = 0;
658     do {
659 	jobflags |= pp->p_flags;
660 	pstatus = pp->p_flags & PALLSTATES;
661 	if (tp != pp && linp != linbuf && !(flag & FANCY) &&
662 	    (pstatus == status && pp->p_reason == reason ||
663 	     !(flag & REASON)))
664 	    xprintf(" ");
665 	else {
666 	    if (tp != pp && linp != linbuf)
667 		xprintf("\n");
668 	    if (flag & NUMBER)
669 		if (pp == tp)
670 		    xprintf("[%d]%s %c ", pp->p_index,
671 			    pp->p_index < 10 ? " " : "",
672 			    pp == pcurrent ? '+' :
673 			    (pp == pprevious ? '-' : ' '));
674 		else
675 		    xprintf("       ");
676 	    if (flag & FANCY) {
677 		xprintf("%5d ", pp->p_pid);
678 	    }
679 	    if (flag & (REASON | AREASON)) {
680 		if (flag & NAME)
681 		    format = "%-23s";
682 		else
683 		    format = "%s";
684 		if (pstatus == status)
685 		    if (pp->p_reason == reason) {
686 			xprintf(format, "");
687 			goto prcomd;
688 		    }
689 		    else
690 			reason = pp->p_reason;
691 		else {
692 		    status = pstatus;
693 		    reason = pp->p_reason;
694 		}
695 		switch (status) {
696 
697 		case PRUNNING:
698 		    xprintf(format, "Running ");
699 		    break;
700 
701 		case PINTERRUPTED:
702 		case PSTOPPED:
703 		case PSIGNALED:
704 		    if ((flag & REASON) ||
705 			((flag & AREASON) && reason != SIGINT
706 			 && reason != SIGPIPE))
707 			xprintf(format, mesg[pp->p_reason].pname);
708 		    break;
709 
710 		case PNEXITED:
711 		case PAEXITED:
712 		    if (flag & REASON)
713 			if (pp->p_reason)
714 			    xprintf("Exit %-18d", pp->p_reason);
715 			else
716 			    xprintf(format, "Done");
717 		    break;
718 
719 		default:
720 		    xprintf("BUG: status=%-9o", status);
721 		}
722 	    }
723 	}
724 prcomd:
725 	if (flag & NAME) {
726 	    xprintf("%s", short2str(pp->p_command));
727 	    if (pp->p_flags & PPOU)
728 		xprintf(" |");
729 	    if (pp->p_flags & PDIAG)
730 		xprintf("&");
731 	}
732 	if (flag & (REASON | AREASON) && pp->p_flags & PDUMPED)
733 	    xprintf(" (core dumped)");
734 	if (tp == pp->p_friends) {
735 	    if (flag & AMPERSAND)
736 		xprintf(" &");
737 	    if (flag & JOBDIR &&
738 		!eq(tp->p_cwd->di_name, dcwd->di_name)) {
739 		xprintf(" (wd: ");
740 		dtildepr(value(STRhome), tp->p_cwd->di_name);
741 		xprintf(")");
742 	    }
743 	}
744 	if (pp->p_flags & PPTIME && !(status & (PSTOPPED | PRUNNING))) {
745 	    if (linp != linbuf)
746 		xprintf("\n\t");
747 	    prusage(&zru, &pp->p_rusage, &pp->p_etime,
748 		    &pp->p_btime);
749 	}
750 	if (tp == pp->p_friends) {
751 	    if (linp != linbuf)
752 		xprintf("\n");
753 	    if (flag & SHELLDIR && !eq(tp->p_cwd->di_name, dcwd->di_name)) {
754 		xprintf("(wd now: ");
755 		dtildepr(value(STRhome), dcwd->di_name);
756 		xprintf(")\n");
757 	    }
758 	}
759     } while ((pp = pp->p_friends) != tp);
760     if (jobflags & PTIME && (jobflags & (PSTOPPED | PRUNNING)) == 0) {
761 	if (jobflags & NUMBER)
762 	    xprintf("       ");
763 	ptprint(tp);
764     }
765     return (jobflags);
766 }
767 
768 static void
ptprint(tp)769 ptprint(tp)
770     register struct process *tp;
771 {
772     struct timeval tetime, diff;
773     static struct timeval ztime;
774     struct rusage ru;
775     static struct rusage zru;
776     register struct process *pp = tp;
777 
778     ru = zru;
779     tetime = ztime;
780     do {
781 	ruadd(&ru, &pp->p_rusage);
782 	tvsub(&diff, &pp->p_etime, &pp->p_btime);
783 	if (timercmp(&diff, &tetime, >))
784 	    tetime = diff;
785     } while ((pp = pp->p_friends) != tp);
786     prusage(&zru, &ru, &tetime, &ztime);
787 }
788 
789 /*
790  * dojobs - print all jobs
791  */
792 void
dojobs(v)793 dojobs(v)
794     Char  **v;
795 {
796     register struct process *pp;
797     register int flag = NUMBER | NAME | REASON;
798     int     i;
799 
800     if (chkstop)
801 	chkstop = 2;
802     if (*++v) {
803 	if (v[1] || !eq(*v, STRml))
804 	    stderror(ERR_JOBS);
805 	flag |= FANCY | JOBDIR;
806     }
807     for (i = 1; i <= pmaxindex; i++)
808 	for (pp = proclist.p_next; pp; pp = pp->p_next)
809 	    if (pp->p_index == i && pp->p_pid == pp->p_jobid) {
810 		pp->p_flags &= ~PNEEDNOTE;
811 		if (!(pprint(pp, flag) & (PRUNNING | PSTOPPED)))
812 		    pflush(pp);
813 		break;
814 	    }
815 }
816 
817 /*
818  * dofg - builtin - put the job into the foreground
819  */
820 void
dofg(v)821 dofg(v)
822     Char  **v;
823 {
824     register struct process *pp;
825 
826     okpcntl();
827     ++v;
828     do {
829 	pp = pfind(*v);
830 	pstart(pp, 1);
831 	pjwait(pp);
832     } while (*v && *++v);
833 }
834 
835 /*
836  * %... - builtin - put the job into the foreground
837  */
838 void
dofg1(v)839 dofg1(v)
840     Char  **v;
841 {
842     register struct process *pp;
843 
844     okpcntl();
845     pp = pfind(v[0]);
846     pstart(pp, 1);
847     pjwait(pp);
848 }
849 
850 /*
851  * dobg - builtin - put the job into the background
852  */
853 void
dobg(v)854 dobg(v)
855     Char  **v;
856 {
857     register struct process *pp;
858 
859     okpcntl();
860     ++v;
861     do {
862 	pp = pfind(*v);
863 	pstart(pp, 0);
864     } while (*v && *++v);
865 }
866 
867 /*
868  * %... & - builtin - put the job into the background
869  */
870 void
dobg1(v)871 dobg1(v)
872     Char  **v;
873 {
874     register struct process *pp;
875 
876     pp = pfind(v[0]);
877     pstart(pp, 0);
878 }
879 
880 /*
881  * dostop - builtin - stop the job
882  */
883 void
dostop(v)884 dostop(v)
885     Char  **v;
886 {
887     pkill(++v, SIGSTOP);
888 }
889 
890 /*
891  * dokill - builtin - superset of kill (1)
892  */
893 void
dokill(v)894 dokill(v)
895     Char  **v;
896 {
897     register int signum, len = 0;
898     register char *name;
899 
900     v++;
901     if (v[0] && v[0][0] == '-') {
902 	if (v[0][1] == 'l') {
903 	    for (signum = 1; signum <= NSIG; signum++) {
904 		if ((name = mesg[signum].iname) != NULL) {
905 		    len += strlen(name) + 1;
906 		    if (len >= 80 - 1) {
907 			xprintf("\n");
908 			len = strlen(name) + 1;
909 		    }
910 		    xprintf("%s ", name);
911 		}
912 	    }
913 	    xprintf("\n");
914 	    return;
915 	}
916 	if (Isdigit(v[0][1])) {
917 	    signum = atoi(short2str(v[0] + 1));
918 	    if (signum < 0 || signum > NSIG)
919 		stderror(ERR_NAME | ERR_BADSIG);
920 	}
921 	else {
922 	    for (signum = 1; signum <= NSIG; signum++)
923 		if (mesg[signum].iname &&
924 		    eq(&v[0][1], str2short(mesg[signum].iname)))
925 		    goto gotsig;
926 	    setname(short2str(&v[0][1]));
927 	    stderror(ERR_NAME | ERR_UNKSIG);
928 	}
929 gotsig:
930 	v++;
931     }
932     else
933 	signum = SIGTERM;
934     pkill(v, signum);
935 }
936 
937 static void
pkill(v,signum)938 pkill(v, signum)
939     Char  **v;
940     int     signum;
941 {
942     register struct process *pp, *np;
943     register int jobflags = 0;
944     int     pid, err1 = 0;
945     sigset_t omask;
946     Char   *cp;
947 
948     omask = sigmask(SIGCHLD);
949     if (setintr)
950 	omask |= sigmask(SIGINT);
951     omask = sigblock(omask) & ~omask;
952     gflag = 0, tglob(v);
953     if (gflag) {
954 	v = globall(v);
955 	if (v == 0)
956 	    stderror(ERR_NAME | ERR_NOMATCH);
957     }
958     else {
959 	v = gargv = saveblk(v);
960 	trim(v);
961     }
962 
963     while (v && (cp = *v)) {
964 	if (*cp == '%') {
965 	    np = pp = pfind(cp);
966 	    do
967 		jobflags |= np->p_flags;
968 	    while ((np = np->p_friends) != pp);
969 	    switch (signum) {
970 
971 	    case SIGSTOP:
972 	    case SIGTSTP:
973 	    case SIGTTIN:
974 	    case SIGTTOU:
975 		if ((jobflags & PRUNNING) == 0) {
976 		    xprintf("%s: Already suspended\n", short2str(cp));
977 		    err1++;
978 		    goto cont;
979 		}
980 		break;
981 		/*
982 		 * suspend a process, kill -CONT %, then type jobs; the shell
983 		 * says it is suspended, but it is running; thanks jaap..
984 		 */
985 	    case SIGCONT:
986 		pstart(pp, 0);
987 		goto cont;
988 	    }
989 	    if (killpg((pid_t) pp->p_jobid, signum) < 0) {
990 		xprintf("%s: %s\n", short2str(cp), strerror(errno));
991 		err1++;
992 	    }
993 	    if (signum == SIGTERM || signum == SIGHUP)
994 		(void) killpg((pid_t) pp->p_jobid, SIGCONT);
995 	}
996 	else if (!(Isdigit(*cp) || *cp == '-'))
997 	    stderror(ERR_NAME | ERR_JOBARGS);
998 	else {
999 	    pid = atoi(short2str(cp));
1000 	    if (kill((pid_t) pid, signum) < 0) {
1001 		xprintf("%d: %s\n", pid, strerror(errno));
1002 		err1++;
1003 		goto cont;
1004 	    }
1005 	    if (signum == SIGTERM || signum == SIGHUP)
1006 		(void) kill((pid_t) pid, SIGCONT);
1007 	}
1008 cont:
1009 	v++;
1010     }
1011     if (gargv)
1012 	blkfree(gargv), gargv = 0;
1013     (void) sigsetmask(omask);
1014     if (err1)
1015 	stderror(ERR_SILENT);
1016 }
1017 
1018 /*
1019  * pstart - start the job in foreground/background
1020  */
1021 void
pstart(pp,foregnd)1022 pstart(pp, foregnd)
1023     register struct process *pp;
1024     int     foregnd;
1025 {
1026     register struct process *np;
1027     sigset_t omask;
1028     long    jobflags = 0;
1029 
1030     omask = sigblock(sigmask(SIGCHLD));
1031     np = pp;
1032     do {
1033 	jobflags |= np->p_flags;
1034 	if (np->p_flags & (PRUNNING | PSTOPPED)) {
1035 	    np->p_flags |= PRUNNING;
1036 	    np->p_flags &= ~PSTOPPED;
1037 	    if (foregnd)
1038 		np->p_flags |= PFOREGND;
1039 	    else
1040 		np->p_flags &= ~PFOREGND;
1041 	}
1042     } while ((np = np->p_friends) != pp);
1043     if (!foregnd)
1044 	pclrcurr(pp);
1045     (void) pprint(pp, foregnd ? NAME | JOBDIR : NUMBER | NAME | AMPERSAND);
1046     if (foregnd)
1047 	(void) tcsetpgrp(FSHTTY, pp->p_jobid);
1048     if (jobflags & PSTOPPED)
1049 	(void) killpg((pid_t) pp->p_jobid, SIGCONT);
1050     (void) sigsetmask(omask);
1051 }
1052 
1053 void
panystop(neednl)1054 panystop(neednl)
1055     bool    neednl;
1056 {
1057     register struct process *pp;
1058 
1059     chkstop = 2;
1060     for (pp = proclist.p_next; pp; pp = pp->p_next)
1061 	if (pp->p_flags & PSTOPPED)
1062 	    stderror(ERR_STOPPED, neednl ? "\n" : "");
1063 }
1064 
1065 struct process *
pfind(cp)1066 pfind(cp)
1067     Char   *cp;
1068 {
1069     register struct process *pp, *np;
1070 
1071     if (cp == 0 || cp[1] == 0 || eq(cp, STRcent2) || eq(cp, STRcentplus)) {
1072 	if (pcurrent == NULL)
1073 	    stderror(ERR_NAME | ERR_JOBCUR);
1074 	return (pcurrent);
1075     }
1076     if (eq(cp, STRcentminus) || eq(cp, STRcenthash)) {
1077 	if (pprevious == NULL)
1078 	    stderror(ERR_NAME | ERR_JOBPREV);
1079 	return (pprevious);
1080     }
1081     if (Isdigit(cp[1])) {
1082 	int     idx = atoi(short2str(cp + 1));
1083 
1084 	for (pp = proclist.p_next; pp; pp = pp->p_next)
1085 	    if (pp->p_index == idx && pp->p_pid == pp->p_jobid)
1086 		return (pp);
1087 	stderror(ERR_NAME | ERR_NOSUCHJOB);
1088     }
1089     np = NULL;
1090     for (pp = proclist.p_next; pp; pp = pp->p_next)
1091 	if (pp->p_pid == pp->p_jobid) {
1092 	    if (cp[1] == '?') {
1093 		register Char *dp;
1094 
1095 		for (dp = pp->p_command; *dp; dp++) {
1096 		    if (*dp != cp[2])
1097 			continue;
1098 		    if (prefix(cp + 2, dp))
1099 			goto match;
1100 		}
1101 	    }
1102 	    else if (prefix(cp + 1, pp->p_command)) {
1103 	match:
1104 		if (np)
1105 		    stderror(ERR_NAME | ERR_AMBIG);
1106 		np = pp;
1107 	    }
1108 	}
1109     if (np)
1110 	return (np);
1111     stderror(ERR_NAME | cp[1] == '?' ? ERR_JOBPAT : ERR_NOSUCHJOB);
1112     /* NOTREACHED */
1113     return (0);
1114 }
1115 
1116 
1117 /*
1118  * pgetcurr - find most recent job that is not pp, preferably stopped
1119  */
1120 static struct process *
pgetcurr(pp)1121 pgetcurr(pp)
1122     register struct process *pp;
1123 {
1124     register struct process *np;
1125     register struct process *xp = NULL;
1126 
1127     for (np = proclist.p_next; np; np = np->p_next)
1128 	if (np != pcurrent && np != pp && np->p_pid &&
1129 	    np->p_pid == np->p_jobid) {
1130 	    if (np->p_flags & PSTOPPED)
1131 		return (np);
1132 	    if (xp == NULL)
1133 		xp = np;
1134 	}
1135     return (xp);
1136 }
1137 
1138 /*
1139  * donotify - flag the job so as to report termination asynchronously
1140  */
1141 void
donotify(v)1142 donotify(v)
1143     Char  **v;
1144 {
1145     register struct process *pp;
1146 
1147     pp = pfind(*++v);
1148     pp->p_flags |= PNOTIFY;
1149 }
1150 
1151 /*
1152  * Do the fork and whatever should be done in the child side that
1153  * should not be done if we are not forking at all (like for simple builtin's)
1154  * Also do everything that needs any signals fiddled with in the parent side
1155  *
1156  * Wanttty tells whether process and/or tty pgrps are to be manipulated:
1157  *	-1:	leave tty alone; inherit pgrp from parent
1158  *	 0:	already have tty; manipulate process pgrps only
1159  *	 1:	want to claim tty; manipulate process and tty pgrps
1160  * It is usually just the value of tpgrp.
1161  */
1162 
1163 int
pfork(t,wanttty)1164 pfork(t, wanttty)
1165     struct command *t;		/* command we are forking for */
1166     int     wanttty;
1167 {
1168     register int pid;
1169     bool    ignint = 0;
1170     int     pgrp;
1171     sigset_t omask;
1172 
1173     /*
1174      * A child will be uninterruptible only under very special conditions.
1175      * Remember that the semantics of '&' is implemented by disconnecting the
1176      * process from the tty so signals do not need to ignored just for '&'.
1177      * Thus signals are set to default action for children unless: we have had
1178      * an "onintr -" (then specifically ignored) we are not playing with
1179      * signals (inherit action)
1180      */
1181     if (setintr)
1182 	ignint = (tpgrp == -1 && (t->t_dflg & F_NOINTERRUPT))
1183 	    || (gointr && eq(gointr, STRminus));
1184     /*
1185      * Check for maximum nesting of 16 processes to avoid Forking loops
1186      */
1187     if (child == 16)
1188 	stderror(ERR_NESTING, 16);
1189     /*
1190      * Hold SIGCHLD until we have the process installed in our table.
1191      */
1192     omask = sigblock(sigmask(SIGCHLD));
1193     while ((pid = fork()) < 0)
1194 	if (setintr == 0)
1195 	    (void) sleep(FORKSLEEP);
1196 	else {
1197 	    (void) sigsetmask(omask);
1198 	    stderror(ERR_NOPROC);
1199 	}
1200     if (pid == 0) {
1201 	settimes();
1202 	pgrp = pcurrjob ? pcurrjob->p_jobid : getpid();
1203 	pflushall();
1204 	pcurrjob = NULL;
1205 	child++;
1206 	if (setintr) {
1207 	    setintr = 0;	/* until I think otherwise */
1208 	    /*
1209 	     * Children just get blown away on SIGINT, SIGQUIT unless "onintr
1210 	     * -" seen.
1211 	     */
1212 	    (void) signal(SIGINT, ignint ? SIG_IGN : SIG_DFL);
1213 	    (void) signal(SIGQUIT, ignint ? SIG_IGN : SIG_DFL);
1214 	    if (wanttty >= 0) {
1215 		/* make stoppable */
1216 		(void) signal(SIGTSTP, SIG_DFL);
1217 		(void) signal(SIGTTIN, SIG_DFL);
1218 		(void) signal(SIGTTOU, SIG_DFL);
1219 	    }
1220 	    (void) signal(SIGTERM, parterm);
1221 	}
1222 	else if (tpgrp == -1 && (t->t_dflg & F_NOINTERRUPT)) {
1223 	    (void) signal(SIGINT, SIG_IGN);
1224 	    (void) signal(SIGQUIT, SIG_IGN);
1225 	}
1226 	pgetty(wanttty, pgrp);
1227 	/*
1228 	 * Nohup and nice apply only to NODE_COMMAND's but it would be nice
1229 	 * (?!?) if you could say "nohup (foo;bar)" Then the parser would have
1230 	 * to know about nice/nohup/time
1231 	 */
1232 	if (t->t_dflg & F_NOHUP)
1233 	    (void) signal(SIGHUP, SIG_IGN);
1234 	if (t->t_dflg & F_NICE)
1235 	    (void) setpriority(PRIO_PROCESS, 0, t->t_nice);
1236     }
1237     else {
1238 	if (wanttty >= 0)
1239 	    (void) setpgid(pid, pcurrjob ? pcurrjob->p_jobid : pid);
1240 	palloc(pid, t);
1241 	(void) sigsetmask(omask);
1242     }
1243 
1244     return (pid);
1245 }
1246 
1247 static void
okpcntl()1248 okpcntl()
1249 {
1250     if (tpgrp == -1)
1251 	stderror(ERR_JOBCONTROL);
1252     if (tpgrp == 0)
1253 	stderror(ERR_JOBCTRLSUB);
1254 }
1255 
1256 /*
1257  * if we don't have vfork(), things can still go in the wrong order
1258  * resulting in the famous 'Stopped (tty output)'. But some systems
1259  * don't permit the setpgid() call, (these are more recent secure
1260  * systems such as ibm's aix). Then we'd rather print an error message
1261  * than hang the shell!
1262  * I am open to suggestions how to fix that.
1263  */
1264 void
pgetty(wanttty,pgrp)1265 pgetty(wanttty, pgrp)
1266     int     wanttty, pgrp;
1267 {
1268     sigset_t omask = 0;
1269 
1270     /*
1271      * christos: I am blocking the tty signals till I've set things
1272      * correctly....
1273      */
1274     if (wanttty > 0)
1275 	omask = sigblock(sigmask(SIGTSTP)|sigmask(SIGTTIN)|sigmask(SIGTTOU));
1276     /*
1277      * From: Michael Schroeder <mlschroe@immd4.informatik.uni-erlangen.de>
1278      * Don't check for tpgrp >= 0 so even non-interactive shells give
1279      * background jobs process groups Same for the comparison in the other part
1280      * of the #ifdef
1281      */
1282     if (wanttty >= 0)
1283 	if (setpgid(0, pgrp) == -1) {
1284 	    xprintf("csh: setpgid error.\n");
1285 	    xexit(0);
1286 	}
1287 
1288     if (wanttty > 0) {
1289 	(void) tcsetpgrp(FSHTTY, pgrp);
1290 	(void) sigsetmask(omask);
1291     }
1292 
1293     if (tpgrp > 0)
1294 	tpgrp = 0;		/* gave tty away */
1295 }
1296