jobs.c revision 223024
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 * 4. Neither the name of the University nor the names of its contributors
17 *    may be used to endorse or promote products derived from this software
18 *    without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#ifndef lint
34#if 0
35static char sccsid[] = "@(#)jobs.c	8.5 (Berkeley) 5/4/95";
36#endif
37#endif /* not lint */
38#include <sys/cdefs.h>
39__FBSDID("$FreeBSD: head/bin/sh/jobs.c 223024 2011-06-12 23:06:04Z jilles $");
40
41#include <sys/ioctl.h>
42#include <sys/param.h>
43#include <sys/resource.h>
44#include <sys/time.h>
45#include <sys/wait.h>
46#include <errno.h>
47#include <fcntl.h>
48#include <paths.h>
49#include <signal.h>
50#include <stddef.h>
51#include <stdlib.h>
52#include <unistd.h>
53
54#include "shell.h"
55#if JOBS
56#include <termios.h>
57#undef CEOF			/* syntax.h redefines this */
58#endif
59#include "redir.h"
60#include "show.h"
61#include "main.h"
62#include "parser.h"
63#include "nodes.h"
64#include "jobs.h"
65#include "options.h"
66#include "trap.h"
67#include "syntax.h"
68#include "input.h"
69#include "output.h"
70#include "memalloc.h"
71#include "error.h"
72#include "mystring.h"
73#include "var.h"
74
75
76static struct job *jobtab;	/* array of jobs */
77static int njobs;		/* size of array */
78MKINIT pid_t backgndpid = -1;	/* pid of last background process */
79MKINIT struct job *bgjob = NULL; /* last background process */
80#if JOBS
81static struct job *jobmru;	/* most recently used job list */
82static pid_t initialpgrp;	/* pgrp of shell on invocation */
83#endif
84int in_waitcmd = 0;		/* are we in waitcmd()? */
85int in_dowait = 0;		/* are we in dowait()? */
86volatile sig_atomic_t breakwaitcmd = 0;	/* should wait be terminated? */
87static int ttyfd = -1;
88
89#if JOBS
90static void restartjob(struct job *);
91#endif
92static void freejob(struct job *);
93static struct job *getjob(char *);
94static pid_t dowait(int, struct job *);
95static pid_t waitproc(int, int *);
96static void checkzombies(void);
97static void cmdtxt(union node *);
98static void cmdputs(const char *);
99#if JOBS
100static void setcurjob(struct job *);
101static void deljob(struct job *);
102static struct job *getcurjob(struct job *);
103#endif
104static void printjobcmd(struct job *);
105static void showjob(struct job *, int);
106
107
108/*
109 * Turn job control on and off.
110 */
111
112MKINIT int jobctl;
113
114#if JOBS
115void
116setjobctl(int on)
117{
118	int i;
119
120	if (on == jobctl || rootshell == 0)
121		return;
122	if (on) {
123		if (ttyfd != -1)
124			close(ttyfd);
125		if ((ttyfd = open(_PATH_TTY, O_RDWR)) < 0) {
126			i = 0;
127			while (i <= 2 && !isatty(i))
128				i++;
129			if (i > 2 || (ttyfd = fcntl(i, F_DUPFD, 10)) < 0)
130				goto out;
131		}
132		if (ttyfd < 10) {
133			/*
134			 * Keep our TTY file descriptor out of the way of
135			 * the user's redirections.
136			 */
137			if ((i = fcntl(ttyfd, F_DUPFD, 10)) < 0) {
138				close(ttyfd);
139				ttyfd = -1;
140				goto out;
141			}
142			close(ttyfd);
143			ttyfd = i;
144		}
145		if (fcntl(ttyfd, F_SETFD, FD_CLOEXEC) < 0) {
146			close(ttyfd);
147			ttyfd = -1;
148			goto out;
149		}
150		do { /* while we are in the background */
151			initialpgrp = tcgetpgrp(ttyfd);
152			if (initialpgrp < 0) {
153out:				out2fmt_flush("sh: can't access tty; job control turned off\n");
154				mflag = 0;
155				return;
156			}
157			if (initialpgrp != getpgrp()) {
158				kill(0, SIGTTIN);
159				continue;
160			}
161		} while (0);
162		setsignal(SIGTSTP);
163		setsignal(SIGTTOU);
164		setsignal(SIGTTIN);
165		setpgid(0, rootpid);
166		tcsetpgrp(ttyfd, rootpid);
167	} else { /* turning job control off */
168		setpgid(0, initialpgrp);
169		tcsetpgrp(ttyfd, initialpgrp);
170		close(ttyfd);
171		ttyfd = -1;
172		setsignal(SIGTSTP);
173		setsignal(SIGTTOU);
174		setsignal(SIGTTIN);
175	}
176	jobctl = on;
177}
178#endif
179
180
181#if JOBS
182int
183fgcmd(int argc __unused, char **argv)
184{
185	struct job *jp;
186	pid_t pgrp;
187	int status;
188
189	jp = getjob(argv[1]);
190	if (jp->jobctl == 0)
191		error("job not created under job control");
192	printjobcmd(jp);
193	flushout(&output);
194	pgrp = jp->ps[0].pid;
195	tcsetpgrp(ttyfd, pgrp);
196	restartjob(jp);
197	jp->foreground = 1;
198	INTOFF;
199	status = waitforjob(jp, (int *)NULL);
200	INTON;
201	return status;
202}
203
204
205int
206bgcmd(int argc, char **argv)
207{
208	struct job *jp;
209
210	do {
211		jp = getjob(*++argv);
212		if (jp->jobctl == 0)
213			error("job not created under job control");
214		if (jp->state == JOBDONE)
215			continue;
216		restartjob(jp);
217		jp->foreground = 0;
218		out1fmt("[%td] ", jp - jobtab + 1);
219		printjobcmd(jp);
220	} while (--argc > 1);
221	return 0;
222}
223
224
225static void
226restartjob(struct job *jp)
227{
228	struct procstat *ps;
229	int i;
230
231	if (jp->state == JOBDONE)
232		return;
233	setcurjob(jp);
234	INTOFF;
235	kill(-jp->ps[0].pid, SIGCONT);
236	for (ps = jp->ps, i = jp->nprocs ; --i >= 0 ; ps++) {
237		if (WIFSTOPPED(ps->status)) {
238			ps->status = -1;
239			jp->state = 0;
240		}
241	}
242	INTON;
243}
244#endif
245
246
247int
248jobscmd(int argc, char *argv[])
249{
250	char *id;
251	int ch, mode;
252
253	optind = optreset = 1;
254	opterr = 0;
255	mode = SHOWJOBS_DEFAULT;
256	while ((ch = getopt(argc, argv, "lps")) != -1) {
257		switch (ch) {
258		case 'l':
259			mode = SHOWJOBS_VERBOSE;
260			break;
261		case 'p':
262			mode = SHOWJOBS_PGIDS;
263			break;
264		case 's':
265			mode = SHOWJOBS_PIDS;
266			break;
267		case '?':
268		default:
269			error("unknown option: -%c", optopt);
270		}
271	}
272	argc -= optind;
273	argv += optind;
274
275	if (argc == 0)
276		showjobs(0, mode);
277	else
278		while ((id = *argv++) != NULL)
279			showjob(getjob(id), mode);
280
281	return (0);
282}
283
284static void
285printjobcmd(struct job *jp)
286{
287	struct procstat *ps;
288	int i;
289
290	for (ps = jp->ps, i = jp->nprocs ; --i >= 0 ; ps++) {
291		out1str(ps->cmd);
292		if (i > 0)
293			out1str(" | ");
294	}
295	out1c('\n');
296}
297
298static void
299showjob(struct job *jp, int mode)
300{
301	char s[64];
302	char statestr[64];
303	struct procstat *ps;
304	struct job *j;
305	int col, curr, i, jobno, prev, procno;
306	char c;
307
308	procno = (mode == SHOWJOBS_PGIDS) ? 1 : jp->nprocs;
309	jobno = jp - jobtab + 1;
310	curr = prev = 0;
311#if JOBS
312	if ((j = getcurjob(NULL)) != NULL) {
313		curr = j - jobtab + 1;
314		if ((j = getcurjob(j)) != NULL)
315			prev = j - jobtab + 1;
316	}
317#endif
318	ps = jp->ps + jp->nprocs - 1;
319	if (jp->state == 0) {
320		strcpy(statestr, "Running");
321#if JOBS
322	} else if (jp->state == JOBSTOPPED) {
323		while (!WIFSTOPPED(ps->status) && ps > jp->ps)
324			ps--;
325		if (WIFSTOPPED(ps->status))
326			i = WSTOPSIG(ps->status);
327		else
328			i = -1;
329		if (i > 0 && i < sys_nsig && sys_siglist[i])
330			strcpy(statestr, sys_siglist[i]);
331		else
332			strcpy(statestr, "Suspended");
333#endif
334	} else if (WIFEXITED(ps->status)) {
335		if (WEXITSTATUS(ps->status) == 0)
336			strcpy(statestr, "Done");
337		else
338			fmtstr(statestr, 64, "Done(%d)",
339			    WEXITSTATUS(ps->status));
340	} else {
341		i = WTERMSIG(ps->status);
342		if (i > 0 && i < sys_nsig && sys_siglist[i])
343			strcpy(statestr, sys_siglist[i]);
344		else
345			fmtstr(statestr, 64, "Signal %d", i);
346		if (WCOREDUMP(ps->status))
347			strcat(statestr, " (core dumped)");
348	}
349
350	for (ps = jp->ps ; ; ps++) {	/* for each process */
351		if (mode == SHOWJOBS_PIDS || mode == SHOWJOBS_PGIDS) {
352			out1fmt("%d\n", (int)ps->pid);
353			goto skip;
354		}
355		if (mode != SHOWJOBS_VERBOSE && ps != jp->ps)
356			goto skip;
357		if (jobno == curr && ps == jp->ps)
358			c = '+';
359		else if (jobno == prev && ps == jp->ps)
360			c = '-';
361		else
362			c = ' ';
363		if (ps == jp->ps)
364			fmtstr(s, 64, "[%d] %c ", jobno, c);
365		else
366			fmtstr(s, 64, "    %c ", c);
367		out1str(s);
368		col = strlen(s);
369		if (mode == SHOWJOBS_VERBOSE) {
370			fmtstr(s, 64, "%d ", (int)ps->pid);
371			out1str(s);
372			col += strlen(s);
373		}
374		if (ps == jp->ps) {
375			out1str(statestr);
376			col += strlen(statestr);
377		}
378		do {
379			out1c(' ');
380			col++;
381		} while (col < 30);
382		if (mode == SHOWJOBS_VERBOSE) {
383			out1str(ps->cmd);
384			out1c('\n');
385		} else
386			printjobcmd(jp);
387skip:		if (--procno <= 0)
388			break;
389	}
390}
391
392/*
393 * Print a list of jobs.  If "change" is nonzero, only print jobs whose
394 * statuses have changed since the last call to showjobs.
395 *
396 * If the shell is interrupted in the process of creating a job, the
397 * result may be a job structure containing zero processes.  Such structures
398 * will be freed here.
399 */
400
401void
402showjobs(int change, int mode)
403{
404	int jobno;
405	struct job *jp;
406
407	TRACE(("showjobs(%d) called\n", change));
408	checkzombies();
409	for (jobno = 1, jp = jobtab ; jobno <= njobs ; jobno++, jp++) {
410		if (! jp->used)
411			continue;
412		if (jp->nprocs == 0) {
413			freejob(jp);
414			continue;
415		}
416		if (change && ! jp->changed)
417			continue;
418		showjob(jp, mode);
419		jp->changed = 0;
420		/* Hack: discard jobs for which $! has not been referenced
421		 * in interactive mode when they terminate.
422		 */
423		if (jp->state == JOBDONE && !jp->remembered &&
424				(iflag || jp != bgjob)) {
425			freejob(jp);
426		}
427	}
428}
429
430
431/*
432 * Mark a job structure as unused.
433 */
434
435static void
436freejob(struct job *jp)
437{
438	struct procstat *ps;
439	int i;
440
441	INTOFF;
442	if (bgjob == jp)
443		bgjob = NULL;
444	for (i = jp->nprocs, ps = jp->ps ; --i >= 0 ; ps++) {
445		if (ps->cmd != nullstr)
446			ckfree(ps->cmd);
447	}
448	if (jp->ps != &jp->ps0)
449		ckfree(jp->ps);
450	jp->used = 0;
451#if JOBS
452	deljob(jp);
453#endif
454	INTON;
455}
456
457
458
459int
460waitcmd(int argc, char **argv)
461{
462	struct job *job;
463	int status, retval;
464	struct job *jp;
465
466	if (argc > 1) {
467		job = getjob(argv[1]);
468	} else {
469		job = NULL;
470	}
471
472	/*
473	 * Loop until a process is terminated or stopped, or a SIGINT is
474	 * received.
475	 */
476
477	in_waitcmd++;
478	do {
479		if (job != NULL) {
480			if (job->state) {
481				status = job->ps[job->nprocs - 1].status;
482				if (WIFEXITED(status))
483					retval = WEXITSTATUS(status);
484#if JOBS
485				else if (WIFSTOPPED(status))
486					retval = WSTOPSIG(status) + 128;
487#endif
488				else
489					retval = WTERMSIG(status) + 128;
490				if (! iflag || ! job->changed)
491					freejob(job);
492				else {
493					job->remembered = 0;
494					if (job == bgjob)
495						bgjob = NULL;
496				}
497				in_waitcmd--;
498				return retval;
499			}
500		} else {
501			for (jp = jobtab ; jp < jobtab + njobs; jp++)
502				if (jp->used && jp->state == JOBDONE) {
503					if (! iflag || ! jp->changed)
504						freejob(jp);
505					else {
506						jp->remembered = 0;
507						if (jp == bgjob)
508							bgjob = NULL;
509					}
510				}
511			for (jp = jobtab ; ; jp++) {
512				if (jp >= jobtab + njobs) {	/* no running procs */
513					in_waitcmd--;
514					return 0;
515				}
516				if (jp->used && jp->state == 0)
517					break;
518			}
519		}
520	} while (dowait(1, (struct job *)NULL) != -1);
521	in_waitcmd--;
522
523	return 0;
524}
525
526
527
528int
529jobidcmd(int argc __unused, char **argv)
530{
531	struct job *jp;
532	int i;
533
534	jp = getjob(argv[1]);
535	for (i = 0 ; i < jp->nprocs ; ) {
536		out1fmt("%d", (int)jp->ps[i].pid);
537		out1c(++i < jp->nprocs? ' ' : '\n');
538	}
539	return 0;
540}
541
542
543
544/*
545 * Convert a job name to a job structure.
546 */
547
548static struct job *
549getjob(char *name)
550{
551	int jobno;
552	struct job *found, *jp;
553	pid_t pid;
554	int i;
555
556	if (name == NULL) {
557#if JOBS
558currentjob:	if ((jp = getcurjob(NULL)) == NULL)
559			error("No current job");
560		return (jp);
561#else
562		error("No current job");
563#endif
564	} else if (name[0] == '%') {
565		if (is_digit(name[1])) {
566			jobno = number(name + 1);
567			if (jobno > 0 && jobno <= njobs
568			 && jobtab[jobno - 1].used != 0)
569				return &jobtab[jobno - 1];
570#if JOBS
571		} else if (name[1] == '%' && name[2] == '\0') {
572			goto currentjob;
573		} else if (name[1] == '+' && name[2] == '\0') {
574			goto currentjob;
575		} else if (name[1] == '-' && name[2] == '\0') {
576			if ((jp = getcurjob(NULL)) == NULL ||
577			    (jp = getcurjob(jp)) == NULL)
578				error("No previous job");
579			return (jp);
580#endif
581		} else if (name[1] == '?') {
582			found = NULL;
583			for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) {
584				if (jp->used && jp->nprocs > 0
585				 && strstr(jp->ps[0].cmd, name + 2) != NULL) {
586					if (found)
587						error("%s: ambiguous", name);
588					found = jp;
589				}
590			}
591			if (found != NULL)
592				return (found);
593		} else {
594			found = NULL;
595			for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) {
596				if (jp->used && jp->nprocs > 0
597				 && prefix(name + 1, jp->ps[0].cmd)) {
598					if (found)
599						error("%s: ambiguous", name);
600					found = jp;
601				}
602			}
603			if (found)
604				return found;
605		}
606	} else if (is_number(name)) {
607		pid = (pid_t)number(name);
608		for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) {
609			if (jp->used && jp->nprocs > 0
610			 && jp->ps[jp->nprocs - 1].pid == pid)
611				return jp;
612		}
613	}
614	error("No such job: %s", name);
615	/*NOTREACHED*/
616	return NULL;
617}
618
619
620pid_t
621getjobpgrp(char *name)
622{
623	struct job *jp;
624
625	jp = getjob(name);
626	return -jp->ps[0].pid;
627}
628
629/*
630 * Return a new job structure,
631 */
632
633struct job *
634makejob(union node *node __unused, int nprocs)
635{
636	int i;
637	struct job *jp;
638
639	for (i = njobs, jp = jobtab ; ; jp++) {
640		if (--i < 0) {
641			INTOFF;
642			if (njobs == 0) {
643				jobtab = ckmalloc(4 * sizeof jobtab[0]);
644#if JOBS
645				jobmru = NULL;
646#endif
647			} else {
648				jp = ckmalloc((njobs + 4) * sizeof jobtab[0]);
649				memcpy(jp, jobtab, njobs * sizeof jp[0]);
650#if JOBS
651				/* Relocate `next' pointers and list head */
652				if (jobmru != NULL)
653					jobmru = &jp[jobmru - jobtab];
654				for (i = 0; i < njobs; i++)
655					if (jp[i].next != NULL)
656						jp[i].next = &jp[jp[i].next -
657						    jobtab];
658#endif
659				if (bgjob != NULL)
660					bgjob = &jp[bgjob - jobtab];
661				/* Relocate `ps' pointers */
662				for (i = 0; i < njobs; i++)
663					if (jp[i].ps == &jobtab[i].ps0)
664						jp[i].ps = &jp[i].ps0;
665				ckfree(jobtab);
666				jobtab = jp;
667			}
668			jp = jobtab + njobs;
669			for (i = 4 ; --i >= 0 ; jobtab[njobs++].used = 0);
670			INTON;
671			break;
672		}
673		if (jp->used == 0)
674			break;
675	}
676	INTOFF;
677	jp->state = 0;
678	jp->used = 1;
679	jp->changed = 0;
680	jp->nprocs = 0;
681	jp->foreground = 0;
682	jp->remembered = 0;
683#if JOBS
684	jp->jobctl = jobctl;
685	jp->next = NULL;
686#endif
687	if (nprocs > 1) {
688		jp->ps = ckmalloc(nprocs * sizeof (struct procstat));
689	} else {
690		jp->ps = &jp->ps0;
691	}
692	INTON;
693	TRACE(("makejob(%p, %d) returns %%%td\n", (void *)node, nprocs,
694	    jp - jobtab + 1));
695	return jp;
696}
697
698#if JOBS
699static void
700setcurjob(struct job *cj)
701{
702	struct job *jp, *prev;
703
704	for (prev = NULL, jp = jobmru; jp != NULL; prev = jp, jp = jp->next) {
705		if (jp == cj) {
706			if (prev != NULL)
707				prev->next = jp->next;
708			else
709				jobmru = jp->next;
710			jp->next = jobmru;
711			jobmru = cj;
712			return;
713		}
714	}
715	cj->next = jobmru;
716	jobmru = cj;
717}
718
719static void
720deljob(struct job *j)
721{
722	struct job *jp, *prev;
723
724	for (prev = NULL, jp = jobmru; jp != NULL; prev = jp, jp = jp->next) {
725		if (jp == j) {
726			if (prev != NULL)
727				prev->next = jp->next;
728			else
729				jobmru = jp->next;
730			return;
731		}
732	}
733}
734
735/*
736 * Return the most recently used job that isn't `nj', and preferably one
737 * that is stopped.
738 */
739static struct job *
740getcurjob(struct job *nj)
741{
742	struct job *jp;
743
744	/* Try to find a stopped one.. */
745	for (jp = jobmru; jp != NULL; jp = jp->next)
746		if (jp->used && jp != nj && jp->state == JOBSTOPPED)
747			return (jp);
748	/* Otherwise the most recently used job that isn't `nj' */
749	for (jp = jobmru; jp != NULL; jp = jp->next)
750		if (jp->used && jp != nj)
751			return (jp);
752
753	return (NULL);
754}
755
756#endif
757
758/*
759 * Fork of a subshell.  If we are doing job control, give the subshell its
760 * own process group.  Jp is a job structure that the job is to be added to.
761 * N is the command that will be evaluated by the child.  Both jp and n may
762 * be NULL.  The mode parameter can be one of the following:
763 *	FORK_FG - Fork off a foreground process.
764 *	FORK_BG - Fork off a background process.
765 *	FORK_NOJOB - Like FORK_FG, but don't give the process its own
766 *		     process group even if job control is on.
767 *
768 * When job control is turned off, background processes have their standard
769 * input redirected to /dev/null (except for the second and later processes
770 * in a pipeline).
771 */
772
773pid_t
774forkshell(struct job *jp, union node *n, int mode)
775{
776	pid_t pid;
777	pid_t pgrp;
778
779	TRACE(("forkshell(%%%td, %p, %d) called\n", jp - jobtab, (void *)n,
780	    mode));
781	INTOFF;
782	if (mode == FORK_BG && (jp == NULL || jp->nprocs == 0))
783		checkzombies();
784	flushall();
785	pid = fork();
786	if (pid == -1) {
787		TRACE(("Fork failed, errno=%d\n", errno));
788		INTON;
789		error("Cannot fork: %s", strerror(errno));
790	}
791	if (pid == 0) {
792		struct job *p;
793		int wasroot;
794		int i;
795
796		TRACE(("Child shell %d\n", (int)getpid()));
797		wasroot = rootshell;
798		rootshell = 0;
799		handler = &main_handler;
800		closescript();
801		INTON;
802		forcelocal = 0;
803		clear_traps();
804#if JOBS
805		jobctl = 0;		/* do job control only in root shell */
806		if (wasroot && mode != FORK_NOJOB && mflag) {
807			if (jp == NULL || jp->nprocs == 0)
808				pgrp = getpid();
809			else
810				pgrp = jp->ps[0].pid;
811			if (setpgid(0, pgrp) == 0 && mode == FORK_FG) {
812				/*** this causes superfluous TIOCSPGRPS ***/
813				if (tcsetpgrp(ttyfd, pgrp) < 0)
814					error("tcsetpgrp failed, errno=%d", errno);
815			}
816			setsignal(SIGTSTP);
817			setsignal(SIGTTOU);
818		} else if (mode == FORK_BG) {
819			ignoresig(SIGINT);
820			ignoresig(SIGQUIT);
821			if ((jp == NULL || jp->nprocs == 0) &&
822			    ! fd0_redirected_p ()) {
823				close(0);
824				if (open(_PATH_DEVNULL, O_RDONLY) != 0)
825					error("cannot open %s: %s",
826					    _PATH_DEVNULL, strerror(errno));
827			}
828		}
829#else
830		if (mode == FORK_BG) {
831			ignoresig(SIGINT);
832			ignoresig(SIGQUIT);
833			if ((jp == NULL || jp->nprocs == 0) &&
834			    ! fd0_redirected_p ()) {
835				close(0);
836				if (open(_PATH_DEVNULL, O_RDONLY) != 0)
837					error("cannot open %s: %s",
838					    _PATH_DEVNULL, strerror(errno));
839			}
840		}
841#endif
842		INTOFF;
843		for (i = njobs, p = jobtab ; --i >= 0 ; p++)
844			if (p->used)
845				freejob(p);
846		INTON;
847		if (wasroot && iflag) {
848			setsignal(SIGINT);
849			setsignal(SIGQUIT);
850			setsignal(SIGTERM);
851		}
852		return pid;
853	}
854	if (rootshell && mode != FORK_NOJOB && mflag) {
855		if (jp == NULL || jp->nprocs == 0)
856			pgrp = pid;
857		else
858			pgrp = jp->ps[0].pid;
859		setpgid(pid, pgrp);
860	}
861	if (mode == FORK_BG) {
862		if (bgjob != NULL && bgjob->state == JOBDONE &&
863		    !bgjob->remembered && !iflag)
864			freejob(bgjob);
865		backgndpid = pid;		/* set $! */
866		bgjob = jp;
867	}
868	if (jp) {
869		struct procstat *ps = &jp->ps[jp->nprocs++];
870		ps->pid = pid;
871		ps->status = -1;
872		ps->cmd = nullstr;
873		if (iflag && rootshell && n)
874			ps->cmd = commandtext(n);
875		jp->foreground = mode == FORK_FG;
876#if JOBS
877		setcurjob(jp);
878#endif
879	}
880	INTON;
881	TRACE(("In parent shell:  child = %d\n", (int)pid));
882	return pid;
883}
884
885
886
887/*
888 * Wait for job to finish.
889 *
890 * Under job control we have the problem that while a child process is
891 * running interrupts generated by the user are sent to the child but not
892 * to the shell.  This means that an infinite loop started by an inter-
893 * active user may be hard to kill.  With job control turned off, an
894 * interactive user may place an interactive program inside a loop.  If
895 * the interactive program catches interrupts, the user doesn't want
896 * these interrupts to also abort the loop.  The approach we take here
897 * is to have the shell ignore interrupt signals while waiting for a
898 * foreground process to terminate, and then send itself an interrupt
899 * signal if the child process was terminated by an interrupt signal.
900 * Unfortunately, some programs want to do a bit of cleanup and then
901 * exit on interrupt; unless these processes terminate themselves by
902 * sending a signal to themselves (instead of calling exit) they will
903 * confuse this approach.
904 */
905
906int
907waitforjob(struct job *jp, int *origstatus)
908{
909#if JOBS
910	pid_t mypgrp = getpgrp();
911	int propagate_int = jp->jobctl && jp->foreground;
912#endif
913	int status;
914	int st;
915
916	INTOFF;
917	TRACE(("waitforjob(%%%td) called\n", jp - jobtab + 1));
918	while (jp->state == 0)
919		if (dowait(1, jp) == -1)
920			dotrap();
921#if JOBS
922	if (jp->jobctl) {
923		if (tcsetpgrp(ttyfd, mypgrp) < 0)
924			error("tcsetpgrp failed, errno=%d\n", errno);
925	}
926	if (jp->state == JOBSTOPPED)
927		setcurjob(jp);
928#endif
929	status = jp->ps[jp->nprocs - 1].status;
930	if (origstatus != NULL)
931		*origstatus = status;
932	/* convert to 8 bits */
933	if (WIFEXITED(status))
934		st = WEXITSTATUS(status);
935#if JOBS
936	else if (WIFSTOPPED(status))
937		st = WSTOPSIG(status) + 128;
938#endif
939	else
940		st = WTERMSIG(status) + 128;
941	if (! JOBS || jp->state == JOBDONE)
942		freejob(jp);
943	if (int_pending()) {
944		if (!WIFSIGNALED(status) || WTERMSIG(status) != SIGINT)
945			CLEAR_PENDING_INT;
946	}
947#if JOBS
948	else if (rootshell && iflag && propagate_int &&
949			WIFSIGNALED(status) && WTERMSIG(status) == SIGINT)
950		kill(getpid(), SIGINT);
951#endif
952	INTON;
953	return st;
954}
955
956
957
958/*
959 * Wait for a process to terminate.
960 */
961
962static pid_t
963dowait(int block, struct job *job)
964{
965	pid_t pid;
966	int status;
967	struct procstat *sp;
968	struct job *jp;
969	struct job *thisjob;
970	int done;
971	int stopped;
972	int sig;
973	int coredump;
974
975	in_dowait++;
976	TRACE(("dowait(%d) called\n", block));
977	do {
978		pid = waitproc(block, &status);
979		TRACE(("wait returns %d, status=%d\n", (int)pid, status));
980	} while ((pid == -1 && errno == EINTR && breakwaitcmd == 0) ||
981		 (pid > 0 && WIFSTOPPED(status) && !iflag));
982	in_dowait--;
983	if (pid == -1 && errno == ECHILD && job != NULL)
984		job->state = JOBDONE;
985	if (breakwaitcmd != 0) {
986		breakwaitcmd = 0;
987		if (pid <= 0)
988			return -1;
989	}
990	if (pid <= 0)
991		return pid;
992	INTOFF;
993	thisjob = NULL;
994	for (jp = jobtab ; jp < jobtab + njobs ; jp++) {
995		if (jp->used && jp->nprocs > 0) {
996			done = 1;
997			stopped = 1;
998			for (sp = jp->ps ; sp < jp->ps + jp->nprocs ; sp++) {
999				if (sp->pid == -1)
1000					continue;
1001				if (sp->pid == pid) {
1002					TRACE(("Changing status of proc %d from 0x%x to 0x%x\n",
1003						   (int)pid, sp->status,
1004						   status));
1005					sp->status = status;
1006					thisjob = jp;
1007				}
1008				if (sp->status == -1)
1009					stopped = 0;
1010				else if (WIFSTOPPED(sp->status))
1011					done = 0;
1012			}
1013			if (stopped) {		/* stopped or done */
1014				int state = done? JOBDONE : JOBSTOPPED;
1015				if (jp->state != state) {
1016					TRACE(("Job %td: changing state from %d to %d\n", jp - jobtab + 1, jp->state, state));
1017					jp->state = state;
1018					if (jp != job) {
1019						if (done && !jp->remembered &&
1020						    !iflag && jp != bgjob)
1021							freejob(jp);
1022#if JOBS
1023						else if (done)
1024							deljob(jp);
1025#endif
1026					}
1027				}
1028			}
1029		}
1030	}
1031	INTON;
1032	if (!thisjob || thisjob->state == 0)
1033		;
1034	else if ((!rootshell || !iflag || thisjob == job) &&
1035	    thisjob->foreground && thisjob->state != JOBSTOPPED) {
1036		sig = 0;
1037		coredump = 0;
1038		for (sp = thisjob->ps; sp < thisjob->ps + thisjob->nprocs; sp++)
1039			if (WIFSIGNALED(sp->status)) {
1040				sig = WTERMSIG(sp->status);
1041				coredump = WCOREDUMP(sp->status);
1042			}
1043		if (sig > 0 && sig != SIGINT && sig != SIGPIPE) {
1044			if (sig < sys_nsig && sys_siglist[sig])
1045				out2str(sys_siglist[sig]);
1046			else
1047				outfmt(out2, "Signal %d", sig);
1048			if (coredump)
1049				out2str(" (core dumped)");
1050			out2c('\n');
1051			flushout(out2);
1052		}
1053	} else {
1054		TRACE(("Not printing status, rootshell=%d, job=%p\n", rootshell, job));
1055		thisjob->changed = 1;
1056	}
1057	return pid;
1058}
1059
1060
1061
1062/*
1063 * Do a wait system call.  If job control is compiled in, we accept
1064 * stopped processes.  If block is zero, we return a value of zero
1065 * rather than blocking.
1066 */
1067static pid_t
1068waitproc(int block, int *status)
1069{
1070	int flags;
1071
1072#if JOBS
1073	flags = WUNTRACED;
1074#else
1075	flags = 0;
1076#endif
1077	if (block == 0)
1078		flags |= WNOHANG;
1079	return wait3(status, flags, (struct rusage *)NULL);
1080}
1081
1082/*
1083 * return 1 if there are stopped jobs, otherwise 0
1084 */
1085int job_warning = 0;
1086int
1087stoppedjobs(void)
1088{
1089	int jobno;
1090	struct job *jp;
1091
1092	if (job_warning)
1093		return (0);
1094	for (jobno = 1, jp = jobtab; jobno <= njobs; jobno++, jp++) {
1095		if (jp->used == 0)
1096			continue;
1097		if (jp->state == JOBSTOPPED) {
1098			out2fmt_flush("You have stopped jobs.\n");
1099			job_warning = 2;
1100			return (1);
1101		}
1102	}
1103
1104	return (0);
1105}
1106
1107
1108static void
1109checkzombies(void)
1110{
1111	while (njobs > 0 && dowait(0, NULL) > 0)
1112		;
1113}
1114
1115
1116int
1117backgndpidset(void)
1118{
1119	return backgndpid != -1;
1120}
1121
1122
1123pid_t
1124backgndpidval(void)
1125{
1126	if (bgjob != NULL && !forcelocal)
1127		bgjob->remembered = 1;
1128	return backgndpid;
1129}
1130
1131/*
1132 * Return a string identifying a command (to be printed by the
1133 * jobs command.
1134 */
1135
1136static char *cmdnextc;
1137static int cmdnleft;
1138#define MAXCMDTEXT	200
1139
1140char *
1141commandtext(union node *n)
1142{
1143	char *name;
1144
1145	cmdnextc = name = ckmalloc(MAXCMDTEXT);
1146	cmdnleft = MAXCMDTEXT - 4;
1147	cmdtxt(n);
1148	*cmdnextc = '\0';
1149	return name;
1150}
1151
1152
1153static void
1154cmdtxt(union node *n)
1155{
1156	union node *np;
1157	struct nodelist *lp;
1158	const char *p;
1159	int i;
1160	char s[2];
1161
1162	if (n == NULL)
1163		return;
1164	switch (n->type) {
1165	case NSEMI:
1166		cmdtxt(n->nbinary.ch1);
1167		cmdputs("; ");
1168		cmdtxt(n->nbinary.ch2);
1169		break;
1170	case NAND:
1171		cmdtxt(n->nbinary.ch1);
1172		cmdputs(" && ");
1173		cmdtxt(n->nbinary.ch2);
1174		break;
1175	case NOR:
1176		cmdtxt(n->nbinary.ch1);
1177		cmdputs(" || ");
1178		cmdtxt(n->nbinary.ch2);
1179		break;
1180	case NPIPE:
1181		for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
1182			cmdtxt(lp->n);
1183			if (lp->next)
1184				cmdputs(" | ");
1185		}
1186		break;
1187	case NSUBSHELL:
1188		cmdputs("(");
1189		cmdtxt(n->nredir.n);
1190		cmdputs(")");
1191		break;
1192	case NREDIR:
1193	case NBACKGND:
1194		cmdtxt(n->nredir.n);
1195		break;
1196	case NIF:
1197		cmdputs("if ");
1198		cmdtxt(n->nif.test);
1199		cmdputs("; then ");
1200		cmdtxt(n->nif.ifpart);
1201		cmdputs("...");
1202		break;
1203	case NWHILE:
1204		cmdputs("while ");
1205		goto until;
1206	case NUNTIL:
1207		cmdputs("until ");
1208until:
1209		cmdtxt(n->nbinary.ch1);
1210		cmdputs("; do ");
1211		cmdtxt(n->nbinary.ch2);
1212		cmdputs("; done");
1213		break;
1214	case NFOR:
1215		cmdputs("for ");
1216		cmdputs(n->nfor.var);
1217		cmdputs(" in ...");
1218		break;
1219	case NCASE:
1220		cmdputs("case ");
1221		cmdputs(n->ncase.expr->narg.text);
1222		cmdputs(" in ...");
1223		break;
1224	case NDEFUN:
1225		cmdputs(n->narg.text);
1226		cmdputs("() ...");
1227		break;
1228	case NCMD:
1229		for (np = n->ncmd.args ; np ; np = np->narg.next) {
1230			cmdtxt(np);
1231			if (np->narg.next)
1232				cmdputs(" ");
1233		}
1234		for (np = n->ncmd.redirect ; np ; np = np->nfile.next) {
1235			cmdputs(" ");
1236			cmdtxt(np);
1237		}
1238		break;
1239	case NARG:
1240		cmdputs(n->narg.text);
1241		break;
1242	case NTO:
1243		p = ">";  i = 1;  goto redir;
1244	case NAPPEND:
1245		p = ">>";  i = 1;  goto redir;
1246	case NTOFD:
1247		p = ">&";  i = 1;  goto redir;
1248	case NCLOBBER:
1249		p = ">|"; i = 1; goto redir;
1250	case NFROM:
1251		p = "<";  i = 0;  goto redir;
1252	case NFROMTO:
1253		p = "<>";  i = 0;  goto redir;
1254	case NFROMFD:
1255		p = "<&";  i = 0;  goto redir;
1256redir:
1257		if (n->nfile.fd != i) {
1258			s[0] = n->nfile.fd + '0';
1259			s[1] = '\0';
1260			cmdputs(s);
1261		}
1262		cmdputs(p);
1263		if (n->type == NTOFD || n->type == NFROMFD) {
1264			if (n->ndup.dupfd >= 0)
1265				s[0] = n->ndup.dupfd + '0';
1266			else
1267				s[0] = '-';
1268			s[1] = '\0';
1269			cmdputs(s);
1270		} else {
1271			cmdtxt(n->nfile.fname);
1272		}
1273		break;
1274	case NHERE:
1275	case NXHERE:
1276		cmdputs("<<...");
1277		break;
1278	default:
1279		cmdputs("???");
1280		break;
1281	}
1282}
1283
1284
1285
1286static void
1287cmdputs(const char *s)
1288{
1289	const char *p;
1290	char *q;
1291	char c;
1292	int subtype = 0;
1293
1294	if (cmdnleft <= 0)
1295		return;
1296	p = s;
1297	q = cmdnextc;
1298	while ((c = *p++) != '\0') {
1299		if (c == CTLESC)
1300			*q++ = *p++;
1301		else if (c == CTLVAR) {
1302			*q++ = '$';
1303			if (--cmdnleft > 0)
1304				*q++ = '{';
1305			subtype = *p++;
1306			if ((subtype & VSTYPE) == VSLENGTH && --cmdnleft > 0)
1307				*q++ = '#';
1308		} else if (c == '=' && subtype != 0) {
1309			*q = "}-+?=##%%\0X"[(subtype & VSTYPE) - VSNORMAL];
1310			if (*q)
1311				q++;
1312			else
1313				cmdnleft++;
1314			if (((subtype & VSTYPE) == VSTRIMLEFTMAX ||
1315			    (subtype & VSTYPE) == VSTRIMRIGHTMAX) &&
1316			    --cmdnleft > 0)
1317				*q = q[-1], q++;
1318			subtype = 0;
1319		} else if (c == CTLENDVAR) {
1320			*q++ = '}';
1321		} else if (c == CTLBACKQ || c == CTLBACKQ+CTLQUOTE) {
1322			cmdnleft -= 5;
1323			if (cmdnleft > 0) {
1324				*q++ = '$';
1325				*q++ = '(';
1326				*q++ = '.';
1327				*q++ = '.';
1328				*q++ = '.';
1329				*q++ = ')';
1330			}
1331		} else if (c == CTLARI) {
1332			cmdnleft -= 2;
1333			if (cmdnleft > 0) {
1334				*q++ = '$';
1335				*q++ = '(';
1336				*q++ = '(';
1337			}
1338			p++;
1339		} else if (c == CTLENDARI) {
1340			if (--cmdnleft > 0) {
1341				*q++ = ')';
1342				*q++ = ')';
1343			}
1344		} else if (c == CTLQUOTEMARK || c == CTLQUOTEEND)
1345			cmdnleft++; /* ignore */
1346		else
1347			*q++ = c;
1348		if (--cmdnleft <= 0) {
1349			*q++ = '.';
1350			*q++ = '.';
1351			*q++ = '.';
1352			break;
1353		}
1354	}
1355	cmdnextc = q;
1356}
1357