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