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