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