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