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