xref: /freebsd/bin/sh/jobs.c (revision 952d112864d8008aa87278a30a539d888a8493cd)
1 /*-
2  * Copyright (c) 1991, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Kenneth Almquist.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *	This product includes software developed by the University of
19  *	California, Berkeley and its contributors.
20  * 4. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  *
36  *	$Id$
37  */
38 
39 #ifndef lint
40 static char const sccsid[] = "@(#)jobs.c	8.5 (Berkeley) 5/4/95";
41 #endif /* not lint */
42 
43 #include <fcntl.h>
44 #include <signal.h>
45 #include <errno.h>
46 #include <unistd.h>
47 #include <stdlib.h>
48 #include <sys/types.h>
49 #include <sys/param.h>
50 #ifdef BSD
51 #include <sys/wait.h>
52 #include <sys/time.h>
53 #include <sys/resource.h>
54 #endif
55 #include <sys/ioctl.h>
56 
57 #include "shell.h"
58 #if JOBS
59 #ifdef OLD_TTY_DRIVER
60 #include "sgtty.h"
61 #else
62 #include <termios.h>
63 #endif
64 #undef CEOF			/* syntax.h redefines this */
65 #endif
66 #include "redir.h"
67 #include "show.h"
68 #include "main.h"
69 #include "parser.h"
70 #include "nodes.h"
71 #include "jobs.h"
72 #include "options.h"
73 #include "trap.h"
74 #include "syntax.h"
75 #include "input.h"
76 #include "output.h"
77 #include "memalloc.h"
78 #include "error.h"
79 #include "mystring.h"
80 
81 
82 struct job *jobtab;		/* array of jobs */
83 int njobs;			/* size of array */
84 MKINIT short backgndpid = -1;	/* pid of last background process */
85 #if JOBS
86 int initialpgrp;		/* pgrp of shell on invocation */
87 short curjob;			/* current job */
88 #endif
89 
90 #if JOBS
91 STATIC void restartjob __P((struct job *));
92 #endif
93 STATIC void freejob __P((struct job *));
94 STATIC struct job *getjob __P((char *));
95 STATIC int dowait __P((int, struct job *));
96 #if SYSV
97 STATIC int onsigchild __P((void));
98 #endif
99 STATIC int waitproc __P((int, int *));
100 STATIC void cmdtxt __P((union node *));
101 STATIC void cmdputs __P((char *));
102 
103 
104 /*
105  * Turn job control on and off.
106  *
107  * Note:  This code assumes that the third arg to ioctl is a character
108  * pointer, which is true on Berkeley systems but not System V.  Since
109  * System V doesn't have job control yet, this isn't a problem now.
110  */
111 
112 MKINIT int jobctl;
113 
114 #if JOBS
115 void
116 setjobctl(on)
117 	int on;
118 {
119 #ifdef OLD_TTY_DRIVER
120 	int ldisc;
121 #endif
122 
123 	if (on == jobctl || rootshell == 0)
124 		return;
125 	if (on) {
126 		do { /* while we are in the background */
127 #ifdef OLD_TTY_DRIVER
128 			if (ioctl(2, TIOCGPGRP, (char *)&initialpgrp) < 0) {
129 #else
130 			initialpgrp = tcgetpgrp(2);
131 			if (initialpgrp < 0) {
132 #endif
133 				out2str("sh: can't access tty; job control turned off\n");
134 				mflag = 0;
135 				return;
136 			}
137 			if (initialpgrp == -1)
138 				initialpgrp = getpgrp();
139 			else if (initialpgrp != getpgrp()) {
140 				killpg(initialpgrp, SIGTTIN);
141 				continue;
142 			}
143 		} while (0);
144 #ifdef OLD_TTY_DRIVER
145 		if (ioctl(2, TIOCGETD, (char *)&ldisc) < 0 || ldisc != NTTYDISC) {
146 			out2str("sh: need new tty driver to run job control; job control turned off\n");
147 			mflag = 0;
148 			return;
149 		}
150 #endif
151 		setsignal(SIGTSTP);
152 		setsignal(SIGTTOU);
153 		setsignal(SIGTTIN);
154 		setpgid(0, rootpid);
155 #ifdef OLD_TTY_DRIVER
156 		ioctl(2, TIOCSPGRP, (char *)&rootpid);
157 #else
158 		tcsetpgrp(2, rootpid);
159 #endif
160 	} else { /* turning job control off */
161 		setpgid(0, initialpgrp);
162 #ifdef OLD_TTY_DRIVER
163 		ioctl(2, TIOCSPGRP, (char *)&initialpgrp);
164 #else
165 		tcsetpgrp(2, initialpgrp);
166 #endif
167 		setsignal(SIGTSTP);
168 		setsignal(SIGTTOU);
169 		setsignal(SIGTTIN);
170 	}
171 	jobctl = on;
172 }
173 #endif
174 
175 
176 #ifdef mkinit
177 INCLUDE <stdlib.h>
178 
179 SHELLPROC {
180 	backgndpid = -1;
181 #if JOBS
182 	jobctl = 0;
183 #endif
184 }
185 
186 #endif
187 
188 
189 
190 #if JOBS
191 int
192 fgcmd(argc, argv)
193 	int argc;
194 	char **argv;
195 {
196 	struct job *jp;
197 	int pgrp;
198 	int status;
199 
200 	jp = getjob(argv[1]);
201 	if (jp->jobctl == 0)
202 		error("job not created under job control");
203 	pgrp = jp->ps[0].pid;
204 #ifdef OLD_TTY_DRIVER
205 	ioctl(2, TIOCSPGRP, (char *)&pgrp);
206 #else
207 	tcsetpgrp(2, pgrp);
208 #endif
209 	restartjob(jp);
210 	INTOFF;
211 	status = waitforjob(jp);
212 	INTON;
213 	return status;
214 }
215 
216 
217 int
218 bgcmd(argc, argv)
219 	int argc;
220 	char **argv;
221 {
222 	struct job *jp;
223 
224 	do {
225 		jp = getjob(*++argv);
226 		if (jp->jobctl == 0)
227 			error("job not created under job control");
228 		restartjob(jp);
229 	} while (--argc > 1);
230 	return 0;
231 }
232 
233 
234 STATIC void
235 restartjob(jp)
236 	struct job *jp;
237 {
238 	struct procstat *ps;
239 	int i;
240 
241 	if (jp->state == JOBDONE)
242 		return;
243 	INTOFF;
244 	killpg(jp->ps[0].pid, SIGCONT);
245 	for (ps = jp->ps, i = jp->nprocs ; --i >= 0 ; ps++) {
246 		if ((ps->status & 0377) == 0177) {
247 			ps->status = -1;
248 			jp->state = 0;
249 		}
250 	}
251 	INTON;
252 }
253 #endif
254 
255 
256 int
257 jobscmd(argc, argv)
258 	int argc;
259 	char **argv;
260 {
261 	showjobs(0);
262 	return 0;
263 }
264 
265 
266 /*
267  * Print a list of jobs.  If "change" is nonzero, only print jobs whose
268  * statuses have changed since the last call to showjobs.
269  *
270  * If the shell is interrupted in the process of creating a job, the
271  * result may be a job structure containing zero processes.  Such structures
272  * will be freed here.
273  */
274 
275 void
276 showjobs(change)
277 	int change;
278 {
279 	int jobno;
280 	int procno;
281 	int i;
282 	struct job *jp;
283 	struct procstat *ps;
284 	int col;
285 	char s[64];
286 
287 	TRACE(("showjobs(%d) called\n", change));
288 	while (dowait(0, (struct job *)NULL) > 0);
289 	for (jobno = 1, jp = jobtab ; jobno <= njobs ; jobno++, jp++) {
290 		if (! jp->used)
291 			continue;
292 		if (jp->nprocs == 0) {
293 			freejob(jp);
294 			continue;
295 		}
296 		if (change && ! jp->changed)
297 			continue;
298 		procno = jp->nprocs;
299 		for (ps = jp->ps ; ; ps++) {	/* for each process */
300 			if (ps == jp->ps)
301 				fmtstr(s, 64, "[%d] %d ", jobno, ps->pid);
302 			else
303 				fmtstr(s, 64, "    %d ", ps->pid);
304 			out1str(s);
305 			col = strlen(s);
306 			s[0] = '\0';
307 			if (ps->status == -1) {
308 				/* don't print anything */
309 			} else if ((ps->status & 0xFF) == 0) {
310 				fmtstr(s, 64, "Exit %d", ps->status >> 8);
311 			} else {
312 				i = ps->status;
313 #if JOBS
314 				if ((i & 0xFF) == 0177)
315 					i >>= 8;
316 #endif
317 				if ((i & 0x7F) < NSIG && sys_siglist[i & 0x7F])
318 					scopy(sys_siglist[i & 0x7F], s);
319 				else
320 					fmtstr(s, 64, "Signal %d", i & 0x7F);
321 				if (i & 0x80)
322 					strcat(s, " (core dumped)");
323 			}
324 			out1str(s);
325 			col += strlen(s);
326 			do {
327 				out1c(' ');
328 				col++;
329 			} while (col < 30);
330 			out1str(ps->cmd);
331 			out1c('\n');
332 			if (--procno <= 0)
333 				break;
334 		}
335 		jp->changed = 0;
336 		if (jp->state == JOBDONE) {
337 			freejob(jp);
338 		}
339 	}
340 }
341 
342 
343 /*
344  * Mark a job structure as unused.
345  */
346 
347 STATIC void
348 freejob(jp)
349 	struct job *jp;
350 	{
351 	struct procstat *ps;
352 	int i;
353 
354 	INTOFF;
355 	for (i = jp->nprocs, ps = jp->ps ; --i >= 0 ; ps++) {
356 		if (ps->cmd != nullstr)
357 			ckfree(ps->cmd);
358 	}
359 	if (jp->ps != &jp->ps0)
360 		ckfree(jp->ps);
361 	jp->used = 0;
362 #if JOBS
363 	if (curjob == jp - jobtab + 1)
364 		curjob = 0;
365 #endif
366 	INTON;
367 }
368 
369 
370 
371 int
372 waitcmd(argc, argv)
373 	int argc;
374 	char **argv;
375 {
376 	struct job *job;
377 	int status;
378 	struct job *jp;
379 
380 	if (argc > 1) {
381 		job = getjob(argv[1]);
382 	} else {
383 		job = NULL;
384 	}
385 	for (;;) {	/* loop until process terminated or stopped */
386 		if (job != NULL) {
387 			if (job->state) {
388 				status = job->ps[job->nprocs - 1].status;
389 				if ((status & 0xFF) == 0)
390 					status = status >> 8 & 0xFF;
391 #if JOBS
392 				else if ((status & 0xFF) == 0177)
393 					status = (status >> 8 & 0x7F) + 128;
394 #endif
395 				else
396 					status = (status & 0x7F) + 128;
397 				if (! iflag)
398 					freejob(job);
399 				return status;
400 			}
401 		} else {
402 			for (jp = jobtab ; ; jp++) {
403 				if (jp >= jobtab + njobs) {	/* no running procs */
404 					return 0;
405 				}
406 				if (jp->used && jp->state == 0)
407 					break;
408 			}
409 		}
410 		dowait(1, (struct job *)NULL);
411 	}
412 }
413 
414 
415 
416 int
417 jobidcmd(argc, argv)
418 	int argc;
419 	char **argv;
420 {
421 	struct job *jp;
422 	int i;
423 
424 	jp = getjob(argv[1]);
425 	for (i = 0 ; i < jp->nprocs ; ) {
426 		out1fmt("%d", jp->ps[i].pid);
427 		out1c(++i < jp->nprocs? ' ' : '\n');
428 	}
429 	return 0;
430 }
431 
432 
433 
434 /*
435  * Convert a job name to a job structure.
436  */
437 
438 STATIC struct job *
439 getjob(name)
440 	char *name;
441 	{
442 	int jobno;
443 	register struct job *jp;
444 	int pid;
445 	int i;
446 
447 	if (name == NULL) {
448 #if JOBS
449 currentjob:
450 		if ((jobno = curjob) == 0 || jobtab[jobno - 1].used == 0)
451 			error("No current job");
452 		return &jobtab[jobno - 1];
453 #else
454 		error("No current job");
455 #endif
456 	} else if (name[0] == '%') {
457 		if (is_digit(name[1])) {
458 			jobno = number(name + 1);
459 			if (jobno > 0 && jobno <= njobs
460 			 && jobtab[jobno - 1].used != 0)
461 				return &jobtab[jobno - 1];
462 #if JOBS
463 		} else if (name[1] == '%' && name[2] == '\0') {
464 			goto currentjob;
465 #endif
466 		} else {
467 			register struct job *found = NULL;
468 			for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) {
469 				if (jp->used && jp->nprocs > 0
470 				 && prefix(name + 1, jp->ps[0].cmd)) {
471 					if (found)
472 						error("%s: ambiguous", name);
473 					found = jp;
474 				}
475 			}
476 			if (found)
477 				return found;
478 		}
479 	} else if (is_number(name)) {
480 		pid = number(name);
481 		for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) {
482 			if (jp->used && jp->nprocs > 0
483 			 && jp->ps[jp->nprocs - 1].pid == pid)
484 				return jp;
485 		}
486 	}
487 	error("No such job: %s", name);
488 	/*NOTREACHED*/
489 	return NULL;
490 }
491 
492 
493 
494 /*
495  * Return a new job structure,
496  */
497 
498 struct job *
499 makejob(node, nprocs)
500 	union node *node;
501 	int nprocs;
502 {
503 	int i;
504 	struct job *jp;
505 
506 	for (i = njobs, jp = jobtab ; ; jp++) {
507 		if (--i < 0) {
508 			INTOFF;
509 			if (njobs == 0) {
510 				jobtab = ckmalloc(4 * sizeof jobtab[0]);
511 			} else {
512 				jp = ckmalloc((njobs + 4) * sizeof jobtab[0]);
513 				memcpy(jp, jobtab, njobs * sizeof jp[0]);
514 				/* Relocate `ps' pointers */
515 				for (i = 0; i < njobs; i++)
516 					if (jp[i].ps == &jobtab[i].ps0)
517 						jp[i].ps = &jp[i].ps0;
518 				ckfree(jobtab);
519 				jobtab = jp;
520 			}
521 			jp = jobtab + njobs;
522 			for (i = 4 ; --i >= 0 ; jobtab[njobs++].used = 0);
523 			INTON;
524 			break;
525 		}
526 		if (jp->used == 0)
527 			break;
528 	}
529 	INTOFF;
530 	jp->state = 0;
531 	jp->used = 1;
532 	jp->changed = 0;
533 	jp->nprocs = 0;
534 #if JOBS
535 	jp->jobctl = jobctl;
536 #endif
537 	if (nprocs > 1) {
538 		jp->ps = ckmalloc(nprocs * sizeof (struct procstat));
539 	} else {
540 		jp->ps = &jp->ps0;
541 	}
542 	INTON;
543 	TRACE(("makejob(0x%lx, %d) returns %%%d\n", (long)node, nprocs,
544 	    jp - jobtab + 1));
545 	return jp;
546 }
547 
548 
549 /*
550  * Fork of a subshell.  If we are doing job control, give the subshell its
551  * own process group.  Jp is a job structure that the job is to be added to.
552  * N is the command that will be evaluated by the child.  Both jp and n may
553  * be NULL.  The mode parameter can be one of the following:
554  *	FORK_FG - Fork off a foreground process.
555  *	FORK_BG - Fork off a background process.
556  *	FORK_NOJOB - Like FORK_FG, but don't give the process its own
557  *		     process group even if job control is on.
558  *
559  * When job control is turned off, background processes have their standard
560  * input redirected to /dev/null (except for the second and later processes
561  * in a pipeline).
562  */
563 
564 int
565 forkshell(jp, n, mode)
566 	union node *n;
567 	struct job *jp;
568 	int mode;
569 {
570 	int pid;
571 	int pgrp;
572 
573 	TRACE(("forkshell(%%%d, 0x%lx, %d) called\n", jp - jobtab, (long)n,
574 	    mode));
575 	INTOFF;
576 	pid = fork();
577 	if (pid == -1) {
578 		TRACE(("Fork failed, errno=%d\n", errno));
579 		INTON;
580 		error("Cannot fork");
581 	}
582 	if (pid == 0) {
583 		struct job *p;
584 		int wasroot;
585 		int i;
586 
587 		TRACE(("Child shell %d\n", getpid()));
588 		wasroot = rootshell;
589 		rootshell = 0;
590 		for (i = njobs, p = jobtab ; --i >= 0 ; p++)
591 			if (p->used)
592 				freejob(p);
593 		closescript();
594 		INTON;
595 		clear_traps();
596 #if JOBS
597 		jobctl = 0;		/* do job control only in root shell */
598 		if (wasroot && mode != FORK_NOJOB && mflag) {
599 			if (jp == NULL || jp->nprocs == 0)
600 				pgrp = getpid();
601 			else
602 				pgrp = jp->ps[0].pid;
603 			if (setpgid(0, pgrp) == 0 && mode == FORK_FG) {
604 				/*** this causes superfluous TIOCSPGRPS ***/
605 #ifdef OLD_TTY_DRIVER
606 				if (ioctl(2, TIOCSPGRP, (char *)&pgrp) < 0)
607 					error("TIOCSPGRP failed, errno=%d", errno);
608 #else
609 				if (tcsetpgrp(2, pgrp) < 0)
610 					error("tcsetpgrp failed, errno=%d", errno);
611 #endif
612 			}
613 			setsignal(SIGTSTP);
614 			setsignal(SIGTTOU);
615 		} else if (mode == FORK_BG) {
616 			ignoresig(SIGINT);
617 			ignoresig(SIGQUIT);
618 			if ((jp == NULL || jp->nprocs == 0) &&
619 			    ! fd0_redirected_p ()) {
620 				close(0);
621 				if (open("/dev/null", O_RDONLY) != 0)
622 					error("Can't open /dev/null");
623 			}
624 		}
625 #else
626 		if (mode == FORK_BG) {
627 			ignoresig(SIGINT);
628 			ignoresig(SIGQUIT);
629 			if ((jp == NULL || jp->nprocs == 0) &&
630 			    ! fd0_redirected_p ()) {
631 				close(0);
632 				if (open("/dev/null", O_RDONLY) != 0)
633 					error("Can't open /dev/null");
634 			}
635 		}
636 #endif
637 		if (wasroot && iflag) {
638 			setsignal(SIGINT);
639 			setsignal(SIGQUIT);
640 			setsignal(SIGTERM);
641 		}
642 		return pid;
643 	}
644 	if (rootshell && mode != FORK_NOJOB && mflag) {
645 		if (jp == NULL || jp->nprocs == 0)
646 			pgrp = pid;
647 		else
648 			pgrp = jp->ps[0].pid;
649 		setpgid(pid, pgrp);
650 	}
651 	if (mode == FORK_BG)
652 		backgndpid = pid;		/* set $! */
653 	if (jp) {
654 		struct procstat *ps = &jp->ps[jp->nprocs++];
655 		ps->pid = pid;
656 		ps->status = -1;
657 		ps->cmd = nullstr;
658 		if (iflag && rootshell && n)
659 			ps->cmd = commandtext(n);
660 	}
661 	INTON;
662 	TRACE(("In parent shell:  child = %d\n", pid));
663 	return pid;
664 }
665 
666 
667 
668 /*
669  * Wait for job to finish.
670  *
671  * Under job control we have the problem that while a child process is
672  * running interrupts generated by the user are sent to the child but not
673  * to the shell.  This means that an infinite loop started by an inter-
674  * active user may be hard to kill.  With job control turned off, an
675  * interactive user may place an interactive program inside a loop.  If
676  * the interactive program catches interrupts, the user doesn't want
677  * these interrupts to also abort the loop.  The approach we take here
678  * is to have the shell ignore interrupt signals while waiting for a
679  * forground process to terminate, and then send itself an interrupt
680  * signal if the child process was terminated by an interrupt signal.
681  * Unfortunately, some programs want to do a bit of cleanup and then
682  * exit on interrupt; unless these processes terminate themselves by
683  * sending a signal to themselves (instead of calling exit) they will
684  * confuse this approach.
685  */
686 
687 int
688 waitforjob(jp)
689 	register struct job *jp;
690 	{
691 #if JOBS
692 	int mypgrp = getpgrp();
693 #endif
694 	int status;
695 	int st;
696 
697 	INTOFF;
698 	TRACE(("waitforjob(%%%d) called\n", jp - jobtab + 1));
699 	while (jp->state == 0) {
700 		dowait(1, jp);
701 	}
702 #if JOBS
703 	if (jp->jobctl) {
704 #ifdef OLD_TTY_DRIVER
705 		if (ioctl(2, TIOCSPGRP, (char *)&mypgrp) < 0)
706 			error("TIOCSPGRP failed, errno=%d\n", errno);
707 #else
708 		if (tcsetpgrp(2, mypgrp) < 0)
709 			error("tcsetpgrp failed, errno=%d\n", errno);
710 #endif
711 	}
712 	if (jp->state == JOBSTOPPED)
713 		curjob = jp - jobtab + 1;
714 #endif
715 	status = jp->ps[jp->nprocs - 1].status;
716 	/* convert to 8 bits */
717 	if ((status & 0xFF) == 0)
718 		st = status >> 8 & 0xFF;
719 #if JOBS
720 	else if ((status & 0xFF) == 0177)
721 		st = (status >> 8 & 0x7F) + 128;
722 #endif
723 	else
724 		st = (status & 0x7F) + 128;
725 	if (! JOBS || jp->state == JOBDONE)
726 		freejob(jp);
727 	CLEAR_PENDING_INT;
728 	if ((status & 0x7F) == SIGINT)
729 		kill(getpid(), SIGINT);
730 	INTON;
731 	return st;
732 }
733 
734 
735 
736 /*
737  * Wait for a process to terminate.
738  */
739 
740 STATIC int
741 dowait(block, job)
742 	int block;
743 	struct job *job;
744 {
745 	int pid;
746 	int status;
747 	struct procstat *sp;
748 	struct job *jp;
749 	struct job *thisjob;
750 	int done;
751 	int stopped;
752 	int core;
753 
754 	TRACE(("dowait(%d) called\n", block));
755 	do {
756 		pid = waitproc(block, &status);
757 		TRACE(("wait returns %d, status=%d\n", pid, status));
758 	} while (pid == -1 && errno == EINTR);
759 	if (pid <= 0)
760 		return pid;
761 	INTOFF;
762 	thisjob = NULL;
763 	for (jp = jobtab ; jp < jobtab + njobs ; jp++) {
764 		if (jp->used) {
765 			done = 1;
766 			stopped = 1;
767 			for (sp = jp->ps ; sp < jp->ps + jp->nprocs ; sp++) {
768 				if (sp->pid == -1)
769 					continue;
770 				if (sp->pid == pid) {
771 					TRACE(("Changin status of proc %d from 0x%x to 0x%x\n", pid, sp->status, status));
772 					sp->status = status;
773 					thisjob = jp;
774 				}
775 				if (sp->status == -1)
776 					stopped = 0;
777 				else if ((sp->status & 0377) == 0177)
778 					done = 0;
779 			}
780 			if (stopped) {		/* stopped or done */
781 				int state = done? JOBDONE : JOBSTOPPED;
782 				if (jp->state != state) {
783 					TRACE(("Job %d: changing state from %d to %d\n", jp - jobtab + 1, jp->state, state));
784 					jp->state = state;
785 #if JOBS
786 					if (done && curjob == jp - jobtab + 1)
787 						curjob = 0;		/* no current job */
788 #endif
789 				}
790 			}
791 		}
792 	}
793 	INTON;
794 	if (! rootshell || ! iflag || (job && thisjob == job)) {
795 #if JOBS
796 		if ((status & 0xFF) == 0177)
797 			status >>= 8;
798 #endif
799 		core = status & 0x80;
800 		status &= 0x7F;
801 		if (status != 0 && status != SIGINT && status != SIGPIPE) {
802 			if (thisjob != job)
803 				outfmt(out2, "%d: ", pid);
804 #if JOBS
805 			if (status == SIGTSTP && rootshell && iflag)
806 				outfmt(out2, "%%%d ", job - jobtab + 1);
807 #endif
808 			if (status < NSIG && sys_siglist[status])
809 				out2str(sys_siglist[status]);
810 			else
811 				outfmt(out2, "Signal %d", status);
812 			if (core)
813 				out2str(" - core dumped");
814 			out2c('\n');
815 			flushout(&errout);
816 		} else {
817 			TRACE(("Not printing status: status=%d\n", status));
818 		}
819 	} else {
820 		TRACE(("Not printing status, rootshell=%d, job=0x%x\n", rootshell, job));
821 		if (thisjob)
822 			thisjob->changed = 1;
823 	}
824 	return pid;
825 }
826 
827 
828 
829 /*
830  * Do a wait system call.  If job control is compiled in, we accept
831  * stopped processes.  If block is zero, we return a value of zero
832  * rather than blocking.
833  *
834  * System V doesn't have a non-blocking wait system call.  It does
835  * have a SIGCLD signal that is sent to a process when one of it's
836  * children dies.  The obvious way to use SIGCLD would be to install
837  * a handler for SIGCLD which simply bumped a counter when a SIGCLD
838  * was received, and have waitproc bump another counter when it got
839  * the status of a process.  Waitproc would then know that a wait
840  * system call would not block if the two counters were different.
841  * This approach doesn't work because if a process has children that
842  * have not been waited for, System V will send it a SIGCLD when it
843  * installs a signal handler for SIGCLD.  What this means is that when
844  * a child exits, the shell will be sent SIGCLD signals continuously
845  * until is runs out of stack space, unless it does a wait call before
846  * restoring the signal handler.  The code below takes advantage of
847  * this (mis)feature by installing a signal handler for SIGCLD and
848  * then checking to see whether it was called.  If there are any
849  * children to be waited for, it will be.
850  *
851  * If neither SYSV nor BSD is defined, we don't implement nonblocking
852  * waits at all.  In this case, the user will not be informed when
853  * a background process until the next time she runs a real program
854  * (as opposed to running a builtin command or just typing return),
855  * and the jobs command may give out of date information.
856  */
857 
858 #ifdef SYSV
859 STATIC int gotsigchild;
860 
861 STATIC int onsigchild() {
862 	gotsigchild = 1;
863 }
864 #endif
865 
866 
867 STATIC int
868 waitproc(block, status)
869 	int block;
870 	int *status;
871 {
872 #ifdef BSD
873 	int flags;
874 
875 #if JOBS
876 	flags = WUNTRACED;
877 #else
878 	flags = 0;
879 #endif
880 	if (block == 0)
881 		flags |= WNOHANG;
882 	return wait3(status, flags, (struct rusage *)NULL);
883 #else
884 #ifdef SYSV
885 	int (*save)();
886 
887 	if (block == 0) {
888 		gotsigchild = 0;
889 		save = signal(SIGCLD, onsigchild);
890 		signal(SIGCLD, save);
891 		if (gotsigchild == 0)
892 			return 0;
893 	}
894 	return wait(status);
895 #else
896 	if (block == 0)
897 		return 0;
898 	return wait(status);
899 #endif
900 #endif
901 }
902 
903 /*
904  * return 1 if there are stopped jobs, otherwise 0
905  */
906 int job_warning = 0;
907 int
908 stoppedjobs()
909 {
910 	register int jobno;
911 	register struct job *jp;
912 
913 	if (job_warning)
914 		return (0);
915 	for (jobno = 1, jp = jobtab; jobno <= njobs; jobno++, jp++) {
916 		if (jp->used == 0)
917 			continue;
918 		if (jp->state == JOBSTOPPED) {
919 			out2str("You have stopped jobs.\n");
920 			job_warning = 2;
921 			return (1);
922 		}
923 	}
924 
925 	return (0);
926 }
927 
928 /*
929  * Return a string identifying a command (to be printed by the
930  * jobs command.
931  */
932 
933 STATIC char *cmdnextc;
934 STATIC int cmdnleft;
935 STATIC void cmdtxt(), cmdputs();
936 #define MAXCMDTEXT	200
937 
938 char *
939 commandtext(n)
940 	union node *n;
941 	{
942 	char *name;
943 
944 	cmdnextc = name = ckmalloc(MAXCMDTEXT);
945 	cmdnleft = MAXCMDTEXT - 4;
946 	cmdtxt(n);
947 	*cmdnextc = '\0';
948 	return name;
949 }
950 
951 
952 STATIC void
953 cmdtxt(n)
954 	union node *n;
955 	{
956 	union node *np;
957 	struct nodelist *lp;
958 	char *p;
959 	int i;
960 	char s[2];
961 
962 	if (n == NULL)
963 		return;
964 	switch (n->type) {
965 	case NSEMI:
966 		cmdtxt(n->nbinary.ch1);
967 		cmdputs("; ");
968 		cmdtxt(n->nbinary.ch2);
969 		break;
970 	case NAND:
971 		cmdtxt(n->nbinary.ch1);
972 		cmdputs(" && ");
973 		cmdtxt(n->nbinary.ch2);
974 		break;
975 	case NOR:
976 		cmdtxt(n->nbinary.ch1);
977 		cmdputs(" || ");
978 		cmdtxt(n->nbinary.ch2);
979 		break;
980 	case NPIPE:
981 		for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
982 			cmdtxt(lp->n);
983 			if (lp->next)
984 				cmdputs(" | ");
985 		}
986 		break;
987 	case NSUBSHELL:
988 		cmdputs("(");
989 		cmdtxt(n->nredir.n);
990 		cmdputs(")");
991 		break;
992 	case NREDIR:
993 	case NBACKGND:
994 		cmdtxt(n->nredir.n);
995 		break;
996 	case NIF:
997 		cmdputs("if ");
998 		cmdtxt(n->nif.test);
999 		cmdputs("; then ");
1000 		cmdtxt(n->nif.ifpart);
1001 		cmdputs("...");
1002 		break;
1003 	case NWHILE:
1004 		cmdputs("while ");
1005 		goto until;
1006 	case NUNTIL:
1007 		cmdputs("until ");
1008 until:
1009 		cmdtxt(n->nbinary.ch1);
1010 		cmdputs("; do ");
1011 		cmdtxt(n->nbinary.ch2);
1012 		cmdputs("; done");
1013 		break;
1014 	case NFOR:
1015 		cmdputs("for ");
1016 		cmdputs(n->nfor.var);
1017 		cmdputs(" in ...");
1018 		break;
1019 	case NCASE:
1020 		cmdputs("case ");
1021 		cmdputs(n->ncase.expr->narg.text);
1022 		cmdputs(" in ...");
1023 		break;
1024 	case NDEFUN:
1025 		cmdputs(n->narg.text);
1026 		cmdputs("() ...");
1027 		break;
1028 	case NCMD:
1029 		for (np = n->ncmd.args ; np ; np = np->narg.next) {
1030 			cmdtxt(np);
1031 			if (np->narg.next)
1032 				cmdputs(" ");
1033 		}
1034 		for (np = n->ncmd.redirect ; np ; np = np->nfile.next) {
1035 			cmdputs(" ");
1036 			cmdtxt(np);
1037 		}
1038 		break;
1039 	case NARG:
1040 		cmdputs(n->narg.text);
1041 		break;
1042 	case NTO:
1043 		p = ">";  i = 1;  goto redir;
1044 	case NAPPEND:
1045 		p = ">>";  i = 1;  goto redir;
1046 	case NTOFD:
1047 		p = ">&";  i = 1;  goto redir;
1048 	case NFROM:
1049 		p = "<";  i = 0;  goto redir;
1050 	case NFROMFD:
1051 		p = "<&";  i = 0;  goto redir;
1052 redir:
1053 		if (n->nfile.fd != i) {
1054 			s[0] = n->nfile.fd + '0';
1055 			s[1] = '\0';
1056 			cmdputs(s);
1057 		}
1058 		cmdputs(p);
1059 		if (n->type == NTOFD || n->type == NFROMFD) {
1060 			s[0] = n->ndup.dupfd + '0';
1061 			s[1] = '\0';
1062 			cmdputs(s);
1063 		} else {
1064 			cmdtxt(n->nfile.fname);
1065 		}
1066 		break;
1067 	case NHERE:
1068 	case NXHERE:
1069 		cmdputs("<<...");
1070 		break;
1071 	default:
1072 		cmdputs("???");
1073 		break;
1074 	}
1075 }
1076 
1077 
1078 
1079 STATIC void
1080 cmdputs(s)
1081 	char *s;
1082 	{
1083 	register char *p, *q;
1084 	register char c;
1085 	int subtype = 0;
1086 
1087 	if (cmdnleft <= 0)
1088 		return;
1089 	p = s;
1090 	q = cmdnextc;
1091 	while ((c = *p++) != '\0') {
1092 		if (c == CTLESC)
1093 			*q++ = *p++;
1094 		else if (c == CTLVAR) {
1095 			*q++ = '$';
1096 			if (--cmdnleft > 0)
1097 				*q++ = '{';
1098 			subtype = *p++;
1099 		} else if (c == '=' && subtype != 0) {
1100 			*q++ = "}-+?="[(subtype & VSTYPE) - VSNORMAL];
1101 			subtype = 0;
1102 		} else if (c == CTLENDVAR) {
1103 			*q++ = '}';
1104 		} else if (c == CTLBACKQ || c == CTLBACKQ+CTLQUOTE)
1105 			cmdnleft++;		/* ignore it */
1106 		else
1107 			*q++ = c;
1108 		if (--cmdnleft <= 0) {
1109 			*q++ = '.';
1110 			*q++ = '.';
1111 			*q++ = '.';
1112 			break;
1113 		}
1114 	}
1115 	cmdnextc = q;
1116 }
1117