jobs.c revision 199629
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 199629 2009-11-21 14:28: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 cmdtxt(union node *);
95STATIC void cmdputs(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		closescript();
761		INTON;
762		clear_traps();
763#if JOBS
764		jobctl = 0;		/* do job control only in root shell */
765		if (wasroot && mode != FORK_NOJOB && mflag) {
766			if (jp == NULL || jp->nprocs == 0)
767				pgrp = getpid();
768			else
769				pgrp = jp->ps[0].pid;
770			if (setpgid(0, pgrp) == 0 && mode == FORK_FG) {
771				/*** this causes superfluous TIOCSPGRPS ***/
772				if (tcsetpgrp(ttyfd, pgrp) < 0)
773					error("tcsetpgrp failed, errno=%d", errno);
774			}
775			setsignal(SIGTSTP);
776			setsignal(SIGTTOU);
777		} else if (mode == FORK_BG) {
778			ignoresig(SIGINT);
779			ignoresig(SIGQUIT);
780			if ((jp == NULL || jp->nprocs == 0) &&
781			    ! fd0_redirected_p ()) {
782				close(0);
783				if (open(_PATH_DEVNULL, O_RDONLY) != 0)
784					error("Can't open %s: %s",
785					    _PATH_DEVNULL, strerror(errno));
786			}
787		}
788#else
789		if (mode == FORK_BG) {
790			ignoresig(SIGINT);
791			ignoresig(SIGQUIT);
792			if ((jp == NULL || jp->nprocs == 0) &&
793			    ! fd0_redirected_p ()) {
794				close(0);
795				if (open(_PATH_DEVNULL, O_RDONLY) != 0)
796					error("Can't open %s: %s",
797					    _PATH_DEVNULL, strerror(errno));
798			}
799		}
800#endif
801		INTOFF;
802		for (i = njobs, p = jobtab ; --i >= 0 ; p++)
803			if (p->used)
804				freejob(p);
805		INTON;
806		if (wasroot && iflag) {
807			setsignal(SIGINT);
808			setsignal(SIGQUIT);
809			setsignal(SIGTERM);
810		}
811		return pid;
812	}
813	if (rootshell && mode != FORK_NOJOB && mflag) {
814		if (jp == NULL || jp->nprocs == 0)
815			pgrp = pid;
816		else
817			pgrp = jp->ps[0].pid;
818		setpgid(pid, pgrp);
819	}
820	if (mode == FORK_BG)
821		backgndpid = pid;		/* set $! */
822	if (jp) {
823		struct procstat *ps = &jp->ps[jp->nprocs++];
824		ps->pid = pid;
825		ps->status = -1;
826		ps->cmd = nullstr;
827		if (iflag && rootshell && n)
828			ps->cmd = commandtext(n);
829		jp->foreground = mode == FORK_FG;
830#if JOBS
831		setcurjob(jp);
832#endif
833	}
834	INTON;
835	TRACE(("In parent shell:  child = %d\n", (int)pid));
836	return pid;
837}
838
839
840
841/*
842 * Wait for job to finish.
843 *
844 * Under job control we have the problem that while a child process is
845 * running interrupts generated by the user are sent to the child but not
846 * to the shell.  This means that an infinite loop started by an inter-
847 * active user may be hard to kill.  With job control turned off, an
848 * interactive user may place an interactive program inside a loop.  If
849 * the interactive program catches interrupts, the user doesn't want
850 * these interrupts to also abort the loop.  The approach we take here
851 * is to have the shell ignore interrupt signals while waiting for a
852 * foreground process to terminate, and then send itself an interrupt
853 * signal if the child process was terminated by an interrupt signal.
854 * Unfortunately, some programs want to do a bit of cleanup and then
855 * exit on interrupt; unless these processes terminate themselves by
856 * sending a signal to themselves (instead of calling exit) they will
857 * confuse this approach.
858 */
859
860int
861waitforjob(struct job *jp, int *origstatus)
862{
863#if JOBS
864	pid_t mypgrp = getpgrp();
865#endif
866	int status;
867	int st;
868
869	INTOFF;
870	TRACE(("waitforjob(%%%d) called\n", jp - jobtab + 1));
871	while (jp->state == 0)
872		if (dowait(1, jp) == -1)
873			dotrap();
874#if JOBS
875	if (jp->jobctl) {
876		if (tcsetpgrp(ttyfd, mypgrp) < 0)
877			error("tcsetpgrp failed, errno=%d\n", errno);
878	}
879	if (jp->state == JOBSTOPPED)
880		setcurjob(jp);
881#endif
882	status = jp->ps[jp->nprocs - 1].status;
883	if (origstatus != NULL)
884		*origstatus = status;
885	/* convert to 8 bits */
886	if (WIFEXITED(status))
887		st = WEXITSTATUS(status);
888#if JOBS
889	else if (WIFSTOPPED(status))
890		st = WSTOPSIG(status) + 128;
891#endif
892	else
893		st = WTERMSIG(status) + 128;
894	if (! JOBS || jp->state == JOBDONE)
895		freejob(jp);
896	if (int_pending()) {
897		if (WIFSIGNALED(status) && WTERMSIG(status) == SIGINT)
898			kill(getpid(), SIGINT);
899		else
900			CLEAR_PENDING_INT;
901	}
902	INTON;
903	return st;
904}
905
906
907
908/*
909 * Wait for a process to terminate.
910 */
911
912STATIC pid_t
913dowait(int block, struct job *job)
914{
915	pid_t pid;
916	int status;
917	struct procstat *sp;
918	struct job *jp;
919	struct job *thisjob;
920	int done;
921	int stopped;
922	int sig;
923	int i;
924
925	in_dowait++;
926	TRACE(("dowait(%d) called\n", block));
927	do {
928		pid = waitproc(block, &status);
929		TRACE(("wait returns %d, status=%d\n", (int)pid, status));
930	} while ((pid == -1 && errno == EINTR && breakwaitcmd == 0) ||
931		 (pid > 0 && WIFSTOPPED(status) && !iflag));
932	in_dowait--;
933	if (pid == -1 && errno == ECHILD && job != NULL)
934		job->state = JOBDONE;
935	if (breakwaitcmd != 0) {
936		breakwaitcmd = 0;
937		if (pid <= 0)
938			return -1;
939	}
940	if (pid <= 0)
941		return pid;
942	INTOFF;
943	thisjob = NULL;
944	for (jp = jobtab ; jp < jobtab + njobs ; jp++) {
945		if (jp->used) {
946			done = 1;
947			stopped = 1;
948			for (sp = jp->ps ; sp < jp->ps + jp->nprocs ; sp++) {
949				if (sp->pid == -1)
950					continue;
951				if (sp->pid == pid) {
952					TRACE(("Changing status of proc %d from 0x%x to 0x%x\n",
953						   (int)pid, sp->status,
954						   status));
955					sp->status = status;
956					thisjob = jp;
957				}
958				if (sp->status == -1)
959					stopped = 0;
960				else if (WIFSTOPPED(sp->status))
961					done = 0;
962			}
963			if (stopped) {		/* stopped or done */
964				int state = done? JOBDONE : JOBSTOPPED;
965				if (jp->state != state) {
966					TRACE(("Job %d: changing state from %d to %d\n", jp - jobtab + 1, jp->state, state));
967					jp->state = state;
968#if JOBS
969					if (done)
970						deljob(jp);
971#endif
972				}
973			}
974		}
975	}
976	INTON;
977	if (! rootshell || ! iflag || (job && thisjob == job)) {
978#if JOBS
979		if (WIFSTOPPED(status))
980			sig = WSTOPSIG(status);
981		else
982#endif
983		{
984			if (WIFEXITED(status))
985				sig = 0;
986			else
987				sig = WTERMSIG(status);
988		}
989		if (sig != 0 && sig != SIGINT && sig != SIGPIPE) {
990			if (!mflag ||
991			    (thisjob->foreground && !WIFSTOPPED(status))) {
992				i = WTERMSIG(status);
993				if ((i & 0x7F) < sys_nsig && sys_siglist[i & 0x7F])
994					out1str(sys_siglist[i & 0x7F]);
995				else
996					out1fmt("Signal %d", i & 0x7F);
997				if (WCOREDUMP(status))
998					out1str(" (core dumped)");
999				out1c('\n');
1000			} else
1001				showjob(thisjob, pid, SHOWJOBS_DEFAULT);
1002		}
1003	} else {
1004		TRACE(("Not printing status, rootshell=%d, job=%p\n", rootshell, job));
1005		if (thisjob)
1006			thisjob->changed = 1;
1007	}
1008	return pid;
1009}
1010
1011
1012
1013/*
1014 * Do a wait system call.  If job control is compiled in, we accept
1015 * stopped processes.  If block is zero, we return a value of zero
1016 * rather than blocking.
1017 */
1018STATIC pid_t
1019waitproc(int block, int *status)
1020{
1021	int flags;
1022
1023#if JOBS
1024	flags = WUNTRACED;
1025#else
1026	flags = 0;
1027#endif
1028	if (block == 0)
1029		flags |= WNOHANG;
1030	return wait3(status, flags, (struct rusage *)NULL);
1031}
1032
1033/*
1034 * return 1 if there are stopped jobs, otherwise 0
1035 */
1036int job_warning = 0;
1037int
1038stoppedjobs(void)
1039{
1040	int jobno;
1041	struct job *jp;
1042
1043	if (job_warning)
1044		return (0);
1045	for (jobno = 1, jp = jobtab; jobno <= njobs; jobno++, jp++) {
1046		if (jp->used == 0)
1047			continue;
1048		if (jp->state == JOBSTOPPED) {
1049			out2fmt_flush("You have stopped jobs.\n");
1050			job_warning = 2;
1051			return (1);
1052		}
1053	}
1054
1055	return (0);
1056}
1057
1058/*
1059 * Return a string identifying a command (to be printed by the
1060 * jobs command.
1061 */
1062
1063STATIC char *cmdnextc;
1064STATIC int cmdnleft;
1065#define MAXCMDTEXT	200
1066
1067char *
1068commandtext(union node *n)
1069{
1070	char *name;
1071
1072	cmdnextc = name = ckmalloc(MAXCMDTEXT);
1073	cmdnleft = MAXCMDTEXT - 4;
1074	cmdtxt(n);
1075	*cmdnextc = '\0';
1076	return name;
1077}
1078
1079
1080STATIC void
1081cmdtxt(union node *n)
1082{
1083	union node *np;
1084	struct nodelist *lp;
1085	char *p;
1086	int i;
1087	char s[2];
1088
1089	if (n == NULL)
1090		return;
1091	switch (n->type) {
1092	case NSEMI:
1093		cmdtxt(n->nbinary.ch1);
1094		cmdputs("; ");
1095		cmdtxt(n->nbinary.ch2);
1096		break;
1097	case NAND:
1098		cmdtxt(n->nbinary.ch1);
1099		cmdputs(" && ");
1100		cmdtxt(n->nbinary.ch2);
1101		break;
1102	case NOR:
1103		cmdtxt(n->nbinary.ch1);
1104		cmdputs(" || ");
1105		cmdtxt(n->nbinary.ch2);
1106		break;
1107	case NPIPE:
1108		for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
1109			cmdtxt(lp->n);
1110			if (lp->next)
1111				cmdputs(" | ");
1112		}
1113		break;
1114	case NSUBSHELL:
1115		cmdputs("(");
1116		cmdtxt(n->nredir.n);
1117		cmdputs(")");
1118		break;
1119	case NREDIR:
1120	case NBACKGND:
1121		cmdtxt(n->nredir.n);
1122		break;
1123	case NIF:
1124		cmdputs("if ");
1125		cmdtxt(n->nif.test);
1126		cmdputs("; then ");
1127		cmdtxt(n->nif.ifpart);
1128		cmdputs("...");
1129		break;
1130	case NWHILE:
1131		cmdputs("while ");
1132		goto until;
1133	case NUNTIL:
1134		cmdputs("until ");
1135until:
1136		cmdtxt(n->nbinary.ch1);
1137		cmdputs("; do ");
1138		cmdtxt(n->nbinary.ch2);
1139		cmdputs("; done");
1140		break;
1141	case NFOR:
1142		cmdputs("for ");
1143		cmdputs(n->nfor.var);
1144		cmdputs(" in ...");
1145		break;
1146	case NCASE:
1147		cmdputs("case ");
1148		cmdputs(n->ncase.expr->narg.text);
1149		cmdputs(" in ...");
1150		break;
1151	case NDEFUN:
1152		cmdputs(n->narg.text);
1153		cmdputs("() ...");
1154		break;
1155	case NCMD:
1156		for (np = n->ncmd.args ; np ; np = np->narg.next) {
1157			cmdtxt(np);
1158			if (np->narg.next)
1159				cmdputs(" ");
1160		}
1161		for (np = n->ncmd.redirect ; np ; np = np->nfile.next) {
1162			cmdputs(" ");
1163			cmdtxt(np);
1164		}
1165		break;
1166	case NARG:
1167		cmdputs(n->narg.text);
1168		break;
1169	case NTO:
1170		p = ">";  i = 1;  goto redir;
1171	case NAPPEND:
1172		p = ">>";  i = 1;  goto redir;
1173	case NTOFD:
1174		p = ">&";  i = 1;  goto redir;
1175	case NCLOBBER:
1176		p = ">|"; i = 1; goto redir;
1177	case NFROM:
1178		p = "<";  i = 0;  goto redir;
1179	case NFROMTO:
1180		p = "<>";  i = 0;  goto redir;
1181	case NFROMFD:
1182		p = "<&";  i = 0;  goto redir;
1183redir:
1184		if (n->nfile.fd != i) {
1185			s[0] = n->nfile.fd + '0';
1186			s[1] = '\0';
1187			cmdputs(s);
1188		}
1189		cmdputs(p);
1190		if (n->type == NTOFD || n->type == NFROMFD) {
1191			if (n->ndup.dupfd >= 0)
1192				s[0] = n->ndup.dupfd + '0';
1193			else
1194				s[0] = '-';
1195			s[1] = '\0';
1196			cmdputs(s);
1197		} else {
1198			cmdtxt(n->nfile.fname);
1199		}
1200		break;
1201	case NHERE:
1202	case NXHERE:
1203		cmdputs("<<...");
1204		break;
1205	default:
1206		cmdputs("???");
1207		break;
1208	}
1209}
1210
1211
1212
1213STATIC void
1214cmdputs(char *s)
1215{
1216	char *p, *q;
1217	char c;
1218	int subtype = 0;
1219
1220	if (cmdnleft <= 0)
1221		return;
1222	p = s;
1223	q = cmdnextc;
1224	while ((c = *p++) != '\0') {
1225		if (c == CTLESC)
1226			*q++ = *p++;
1227		else if (c == CTLVAR) {
1228			*q++ = '$';
1229			if (--cmdnleft > 0)
1230				*q++ = '{';
1231			subtype = *p++;
1232		} else if (c == '=' && subtype != 0) {
1233			*q++ = "}-+?="[(subtype & VSTYPE) - VSNORMAL];
1234			subtype = 0;
1235		} else if (c == CTLENDVAR) {
1236			*q++ = '}';
1237		} else if (c == CTLBACKQ || c == CTLBACKQ+CTLQUOTE)
1238			cmdnleft++;		/* ignore it */
1239		else
1240			*q++ = c;
1241		if (--cmdnleft <= 0) {
1242			*q++ = '.';
1243			*q++ = '.';
1244			*q++ = '.';
1245			break;
1246		}
1247	}
1248	cmdnextc = q;
1249}
1250