jobs.c revision 1.90 1 /* $NetBSD: jobs.c,v 1.90 2017/10/19 01:57:18 kre Exp $ */
2
3 /*-
4 * Copyright (c) 1991, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Kenneth Almquist.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35 #include <sys/cdefs.h>
36 #ifndef lint
37 #if 0
38 static char sccsid[] = "@(#)jobs.c 8.5 (Berkeley) 5/4/95";
39 #else
40 __RCSID("$NetBSD: jobs.c,v 1.90 2017/10/19 01:57:18 kre Exp $");
41 #endif
42 #endif /* not lint */
43
44 #include <fcntl.h>
45 #include <signal.h>
46 #include <errno.h>
47 #include <unistd.h>
48 #include <stdlib.h>
49 #include <paths.h>
50 #include <sys/types.h>
51 #include <sys/param.h>
52 #ifdef BSD
53 #include <sys/wait.h>
54 #include <sys/time.h>
55 #include <sys/resource.h>
56 #endif
57 #include <sys/ioctl.h>
58
59 #include "shell.h"
60 #if JOBS
61 #if OLD_TTY_DRIVER
62 #include "sgtty.h"
63 #else
64 #include <termios.h>
65 #endif
66 #undef CEOF /* syntax.h redefines this */
67 #endif
68 #include "redir.h"
69 #include "show.h"
70 #include "main.h"
71 #include "parser.h"
72 #include "nodes.h"
73 #include "jobs.h"
74 #include "options.h"
75 #include "builtins.h"
76 #include "trap.h"
77 #include "syntax.h"
78 #include "input.h"
79 #include "output.h"
80 #include "memalloc.h"
81 #include "error.h"
82 #include "mystring.h"
83
84
85 static struct job *jobtab; /* array of jobs */
86 static int njobs; /* size of array */
87 static int jobs_invalid; /* set in child */
88 MKINIT pid_t backgndpid = -1; /* pid of last background process */
89 #if JOBS
90 int initialpgrp; /* pgrp of shell on invocation */
91 static int curjob = -1; /* current job */
92 #endif
93 static int ttyfd = -1;
94
95 STATIC void restartjob(struct job *);
96 STATIC void freejob(struct job *);
97 STATIC struct job *getjob(const char *, int);
98 STATIC int dowait(int, struct job *);
99 #define WBLOCK 1
100 #define WNOFREE 2
101 STATIC int jobstatus(const struct job *, int);
102 STATIC int waitproc(int, struct job *, int *);
103 STATIC void cmdtxt(union node *);
104 STATIC void cmdlist(union node *, int);
105 STATIC void cmdputs(const char *);
106 inline static void cmdputi(int);
107
108 #ifdef SYSV
109 STATIC int onsigchild(void);
110 #endif
111
112 #ifdef OLD_TTY_DRIVER
113 static pid_t tcgetpgrp(int fd);
114 static int tcsetpgrp(int fd, pid_t pgrp);
115
116 static pid_t
117 tcgetpgrp(int fd)
118 {
119 pid_t pgrp;
120 if (ioctl(fd, TIOCGPGRP, (char *)&pgrp) == -1)
121 return -1;
122 else
123 return pgrp;
124 }
125
126 static int
127 tcsetpgrp(int fd, pid_tpgrp)
128 {
129 return ioctl(fd, TIOCSPGRP, (char *)&pgrp);
130 }
131 #endif
132
133 static void
134 ttyfd_change(int from, int to)
135 {
136 if (ttyfd == from)
137 ttyfd = to;
138 }
139
140 /*
141 * Turn job control on and off.
142 *
143 * Note: This code assumes that the third arg to ioctl is a character
144 * pointer, which is true on Berkeley systems but not System V. Since
145 * System V doesn't have job control yet, this isn't a problem now.
146 */
147
148 MKINIT int jobctl;
149
150 void
151 setjobctl(int on)
152 {
153 #ifdef OLD_TTY_DRIVER
154 int ldisc;
155 #endif
156
157 if (on == jobctl || rootshell == 0)
158 return;
159 if (on) {
160 #if defined(FIOCLEX) || defined(FD_CLOEXEC)
161 int i;
162
163 if (ttyfd != -1)
164 sh_close(ttyfd);
165 if ((ttyfd = open("/dev/tty", O_RDWR)) == -1) {
166 for (i = 0; i < 3; i++) {
167 if (isatty(i) && (ttyfd = dup(i)) != -1)
168 break;
169 }
170 if (i == 3)
171 goto out;
172 }
173 ttyfd = to_upper_fd(ttyfd); /* Move to a high fd */
174 register_sh_fd(ttyfd, ttyfd_change);
175 #else
176 out2str("sh: Need FIOCLEX or FD_CLOEXEC to support job control");
177 goto out;
178 #endif
179 do { /* while we are in the background */
180 if ((initialpgrp = tcgetpgrp(ttyfd)) < 0) {
181 out:
182 out2str("sh: can't access tty; job control turned off\n");
183 mflag = 0;
184 return;
185 }
186 if (initialpgrp == -1)
187 initialpgrp = getpgrp();
188 else if (initialpgrp != getpgrp()) {
189 killpg(0, SIGTTIN);
190 continue;
191 }
192 } while (0);
193
194 #ifdef OLD_TTY_DRIVER
195 if (ioctl(ttyfd, TIOCGETD, (char *)&ldisc) < 0
196 || ldisc != NTTYDISC) {
197 out2str("sh: need new tty driver to run job control; job control turned off\n");
198 mflag = 0;
199 return;
200 }
201 #endif
202 setsignal(SIGTSTP, 0);
203 setsignal(SIGTTOU, 0);
204 setsignal(SIGTTIN, 0);
205 if (getpgrp() != rootpid && setpgid(0, rootpid) == -1)
206 error("Cannot set process group (%s) at %d",
207 strerror(errno), __LINE__);
208 if (tcsetpgrp(ttyfd, rootpid) == -1)
209 error("Cannot set tty process group (%s) at %d",
210 strerror(errno), __LINE__);
211 } else { /* turning job control off */
212 if (getpgrp() != initialpgrp && setpgid(0, initialpgrp) == -1)
213 error("Cannot set process group (%s) at %d",
214 strerror(errno), __LINE__);
215 if (tcsetpgrp(ttyfd, initialpgrp) == -1)
216 error("Cannot set tty process group (%s) at %d",
217 strerror(errno), __LINE__);
218 sh_close(ttyfd);
219 ttyfd = -1;
220 setsignal(SIGTSTP, 0);
221 setsignal(SIGTTOU, 0);
222 setsignal(SIGTTIN, 0);
223 }
224 jobctl = on;
225 }
226
227
228 #ifdef mkinit
229 INCLUDE <stdlib.h>
230
231 SHELLPROC {
232 backgndpid = -1;
233 #if JOBS
234 jobctl = 0;
235 #endif
236 }
237
238 #endif
239
240
241
242 #if JOBS
243 static int
244 do_fgcmd(const char *arg_ptr)
245 {
246 struct job *jp;
247 int i;
248 int status;
249
250 jp = getjob(arg_ptr, 0);
251 if (jp->jobctl == 0)
252 error("job not created under job control");
253 out1fmt("%s", jp->ps[0].cmd);
254 for (i = 1; i < jp->nprocs; i++)
255 out1fmt(" | %s", jp->ps[i].cmd );
256 out1c('\n');
257 flushall();
258
259 for (i = 0; i < jp->nprocs; i++)
260 if (tcsetpgrp(ttyfd, jp->ps[i].pid) != -1)
261 break;
262
263 if (i >= jp->nprocs) {
264 error("Cannot set tty process group (%s) at %d",
265 strerror(errno), __LINE__);
266 }
267 restartjob(jp);
268 INTOFF;
269 status = waitforjob(jp);
270 INTON;
271 return status;
272 }
273
274 int
275 fgcmd(int argc, char **argv)
276 {
277 nextopt("");
278 return do_fgcmd(*argptr);
279 }
280
281 int
282 fgcmd_percent(int argc, char **argv)
283 {
284 nextopt("");
285 return do_fgcmd(*argv);
286 }
287
288 static void
289 set_curjob(struct job *jp, int mode)
290 {
291 struct job *jp1, *jp2;
292 int i, ji;
293
294 ji = jp - jobtab;
295
296 /* first remove from list */
297 if (ji == curjob)
298 curjob = jp->prev_job;
299 else {
300 for (i = 0; i < njobs; i++) {
301 if (jobtab[i].prev_job != ji)
302 continue;
303 jobtab[i].prev_job = jp->prev_job;
304 break;
305 }
306 }
307
308 /* Then re-insert in correct position */
309 switch (mode) {
310 case 0: /* job being deleted */
311 jp->prev_job = -1;
312 break;
313 case 1: /* newly created job or backgrounded job,
314 put after all stopped jobs. */
315 if (curjob != -1 && jobtab[curjob].state == JOBSTOPPED) {
316 for (jp1 = jobtab + curjob; ; jp1 = jp2) {
317 if (jp1->prev_job == -1)
318 break;
319 jp2 = jobtab + jp1->prev_job;
320 if (jp2->state != JOBSTOPPED)
321 break;
322 }
323 jp->prev_job = jp1->prev_job;
324 jp1->prev_job = ji;
325 break;
326 }
327 /* FALLTHROUGH */
328 case 2: /* newly stopped job - becomes curjob */
329 jp->prev_job = curjob;
330 curjob = ji;
331 break;
332 }
333 }
334
335 int
336 bgcmd(int argc, char **argv)
337 {
338 struct job *jp;
339 int i;
340
341 nextopt("");
342 do {
343 jp = getjob(*argptr, 0);
344 if (jp->jobctl == 0)
345 error("job not created under job control");
346 set_curjob(jp, 1);
347 out1fmt("[%ld] %s", (long)(jp - jobtab + 1), jp->ps[0].cmd);
348 for (i = 1; i < jp->nprocs; i++)
349 out1fmt(" | %s", jp->ps[i].cmd );
350 out1c('\n');
351 flushall();
352 restartjob(jp);
353 } while (*argptr && *++argptr);
354 return 0;
355 }
356
357
358 STATIC void
359 restartjob(struct job *jp)
360 {
361 struct procstat *ps;
362 int i;
363
364 if (jp->state == JOBDONE)
365 return;
366 INTOFF;
367 for (i = 0; i < jp->nprocs; i++)
368 if (killpg(jp->ps[i].pid, SIGCONT) != -1)
369 break;
370 if (i >= jp->nprocs)
371 error("Cannot continue job (%s)", strerror(errno));
372 for (ps = jp->ps, i = jp->nprocs ; --i >= 0 ; ps++) {
373 if (WIFSTOPPED(ps->status)) {
374 ps->status = -1;
375 jp->state = JOBRUNNING;
376 }
377 }
378 INTON;
379 }
380 #endif
381
382 inline static void
383 cmdputi(int n)
384 {
385 char str[20];
386
387 fmtstr(str, sizeof str, "%d", n);
388 cmdputs(str);
389 }
390
391 static void
392 showjob(struct output *out, struct job *jp, int mode)
393 {
394 int procno;
395 int st;
396 struct procstat *ps;
397 int col;
398 char s[64];
399
400 #if JOBS
401 if (mode & SHOW_PGID) {
402 /* just output process (group) id of pipeline */
403 outfmt(out, "%ld\n", (long)jp->ps->pid);
404 return;
405 }
406 #endif
407
408 procno = jp->nprocs;
409 if (!procno)
410 return;
411
412 if (mode & SHOW_PID)
413 mode |= SHOW_MULTILINE;
414
415 if ((procno > 1 && !(mode & SHOW_MULTILINE))
416 || (mode & SHOW_SIGNALLED)) {
417 /* See if we have more than one status to report */
418 ps = jp->ps;
419 st = ps->status;
420 do {
421 int st1 = ps->status;
422 if (st1 != st)
423 /* yes - need multi-line output */
424 mode |= SHOW_MULTILINE;
425 if (st1 == -1 || !(mode & SHOW_SIGNALLED) || WIFEXITED(st1))
426 continue;
427 if (WIFSTOPPED(st1) || ((st1 = WTERMSIG(st1) & 0x7f)
428 && st1 != SIGINT && st1 != SIGPIPE))
429 mode |= SHOW_ISSIG;
430
431 } while (ps++, --procno);
432 procno = jp->nprocs;
433 }
434
435 if (mode & SHOW_SIGNALLED && !(mode & SHOW_ISSIG)) {
436 if (jp->state == JOBDONE && !(mode & SHOW_NO_FREE)) {
437 VTRACE(DBG_JOBS, ("showjob: freeing job %d\n",
438 jp - jobtab + 1));
439 freejob(jp);
440 }
441 return;
442 }
443
444 for (ps = jp->ps; --procno >= 0; ps++) { /* for each process */
445 if (ps == jp->ps)
446 fmtstr(s, 16, "[%ld] %c ",
447 (long)(jp - jobtab + 1),
448 #if JOBS
449 jp == jobtab + curjob ? '+' :
450 curjob != -1 && jp == jobtab +
451 jobtab[curjob].prev_job ? '-' :
452 #endif
453 ' ');
454 else
455 fmtstr(s, 16, " " );
456 col = strlen(s);
457 if (mode & SHOW_PID) {
458 fmtstr(s + col, 16, "%ld ", (long)ps->pid);
459 col += strlen(s + col);
460 }
461 if (ps->status == -1) {
462 scopy("Running", s + col);
463 } else if (WIFEXITED(ps->status)) {
464 st = WEXITSTATUS(ps->status);
465 if (st)
466 fmtstr(s + col, 16, "Done(%d)", st);
467 else
468 fmtstr(s + col, 16, "Done");
469 } else {
470 #if JOBS
471 if (WIFSTOPPED(ps->status))
472 st = WSTOPSIG(ps->status);
473 else /* WIFSIGNALED(ps->status) */
474 #endif
475 st = WTERMSIG(ps->status);
476 st &= 0x7f;
477 if (st < NSIG && sys_siglist[st])
478 scopyn(sys_siglist[st], s + col, 32);
479 else
480 fmtstr(s + col, 16, "Signal %d", st);
481 if (WCOREDUMP(ps->status)) {
482 col += strlen(s + col);
483 scopyn(" (core dumped)", s + col, 64 - col);
484 }
485 }
486 col += strlen(s + col);
487 outstr(s, out);
488 do {
489 outc(' ', out);
490 col++;
491 } while (col < 30);
492 outstr(ps->cmd, out);
493 if (mode & SHOW_MULTILINE) {
494 if (procno > 0) {
495 outc(' ', out);
496 outc('|', out);
497 }
498 } else {
499 while (--procno >= 0)
500 outfmt(out, " | %s", (++ps)->cmd );
501 }
502 outc('\n', out);
503 }
504 flushout(out);
505 jp->changed = 0;
506 if (jp->state == JOBDONE && !(mode & SHOW_NO_FREE))
507 freejob(jp);
508 }
509
510
511 int
512 jobscmd(int argc, char **argv)
513 {
514 int mode, m;
515 int sv = jobs_invalid;
516
517 jobs_invalid = 0;
518 mode = 0;
519 while ((m = nextopt("lp")))
520 if (m == 'l')
521 mode = SHOW_PID;
522 else
523 mode = SHOW_PGID;
524 if (*argptr)
525 do
526 showjob(out1, getjob(*argptr,0), mode);
527 while (*++argptr);
528 else
529 showjobs(out1, mode);
530 jobs_invalid = sv;
531 return 0;
532 }
533
534
535 /*
536 * Print a list of jobs. If "change" is nonzero, only print jobs whose
537 * statuses have changed since the last call to showjobs.
538 *
539 * If the shell is interrupted in the process of creating a job, the
540 * result may be a job structure containing zero processes. Such structures
541 * will be freed here.
542 */
543
544 void
545 showjobs(struct output *out, int mode)
546 {
547 int jobno;
548 struct job *jp;
549 int silent = 0, gotpid;
550
551 CTRACE(DBG_JOBS, ("showjobs(%x) called\n", mode));
552
553 /* If not even one one job changed, there is nothing to do */
554 gotpid = dowait(0, NULL);
555 while (dowait(0, NULL) > 0)
556 continue;
557 #ifdef JOBS
558 /*
559 * Check if we are not in our foreground group, and if not
560 * put us in it.
561 */
562 if (mflag && gotpid != -1 && tcgetpgrp(ttyfd) != getpid()) {
563 if (tcsetpgrp(ttyfd, getpid()) == -1)
564 error("Cannot set tty process group (%s) at %d",
565 strerror(errno), __LINE__);
566 VTRACE(DBG_JOBS|DBG_INPUT, ("repaired tty process group\n"));
567 silent = 1;
568 }
569 #endif
570 if (jobs_invalid)
571 return;
572
573 for (jobno = 1, jp = jobtab ; jobno <= njobs ; jobno++, jp++) {
574 if (!jp->used)
575 continue;
576 if (jp->nprocs == 0) {
577 freejob(jp);
578 continue;
579 }
580 if ((mode & SHOW_CHANGED) && !jp->changed)
581 continue;
582 if (silent && jp->changed) {
583 jp->changed = 0;
584 continue;
585 }
586 showjob(out, jp, mode);
587 }
588 }
589
590 /*
591 * Mark a job structure as unused.
592 */
593
594 STATIC void
595 freejob(struct job *jp)
596 {
597 INTOFF;
598 if (jp->ps != &jp->ps0) {
599 ckfree(jp->ps);
600 jp->ps = &jp->ps0;
601 }
602 jp->nprocs = 0;
603 jp->used = 0;
604 #if JOBS
605 set_curjob(jp, 0);
606 #endif
607 INTON;
608 }
609
610 /*
611 * Extract the status of a completed job (for $?)
612 */
613 STATIC int
614 jobstatus(const struct job *jp, int raw)
615 {
616 int status = 0;
617 int retval;
618
619 if (pipefail && jp->nprocs) {
620 int i;
621
622 for (i = 0; i < jp->nprocs; i++)
623 if (jp->ps[i].status != 0)
624 status = jp->ps[i].status;
625 } else
626 status = jp->ps[jp->nprocs ? jp->nprocs - 1 : 0].status;
627
628 if (raw)
629 return status;
630
631 if (WIFEXITED(status))
632 retval = WEXITSTATUS(status);
633 #if JOBS
634 else if (WIFSTOPPED(status))
635 retval = WSTOPSIG(status) + 128;
636 #endif
637 else {
638 /* XXX: limits number of signals */
639 retval = WTERMSIG(status) + 128;
640 }
641
642 return retval;
643 }
644
645
646
647 int
648 waitcmd(int argc, char **argv)
649 {
650 struct job *job;
651 int retval;
652 struct job *jp;
653
654 nextopt("");
655
656 if (!*argptr) {
657 /* wait for all jobs */
658 jp = jobtab;
659 if (jobs_invalid)
660 return 0;
661 for (;;) {
662 if (jp >= jobtab + njobs) {
663 /* no running procs */
664 return 0;
665 }
666 if (!jp->used || jp->state != JOBRUNNING) {
667 jp++;
668 continue;
669 }
670 if (dowait(WBLOCK, NULL) == -1)
671 return 128 + lastsig();
672 jp = jobtab;
673 }
674 }
675
676 retval = 127; /* XXXGCC: -Wuninitialized */
677 for (; *argptr; argptr++) {
678 job = getjob(*argptr, 1);
679 if (!job) {
680 retval = 127;
681 continue;
682 }
683 /* loop until process terminated or stopped */
684 while (job->state == JOBRUNNING) {
685 if (dowait(WBLOCK|WNOFREE, job) == -1)
686 return 128 + lastsig();
687 }
688 retval = jobstatus(job, 0);
689 if (!iflag)
690 freejob(job);
691 }
692 return retval;
693 }
694
695
696
697 int
698 jobidcmd(int argc, char **argv)
699 {
700 struct job *jp;
701 int i;
702
703 nextopt("");
704 jp = getjob(*argptr, 0);
705 for (i = 0 ; i < jp->nprocs ; ) {
706 out1fmt("%ld", (long)jp->ps[i].pid);
707 out1c(++i < jp->nprocs ? ' ' : '\n');
708 }
709 return 0;
710 }
711
712 int
713 getjobpgrp(const char *name)
714 {
715 struct job *jp;
716
717 jp = getjob(name, 1);
718 if (jp == 0)
719 return 0;
720 return -jp->ps[0].pid;
721 }
722
723 /*
724 * Convert a job name to a job structure.
725 */
726
727 STATIC struct job *
728 getjob(const char *name, int noerror)
729 {
730 int jobno = -1;
731 struct job *jp;
732 int pid;
733 int i;
734 const char *err_msg = "No such job: %s";
735
736 if (name == NULL) {
737 #if JOBS
738 jobno = curjob;
739 #endif
740 err_msg = "No current job";
741 } else if (name[0] == '%') {
742 if (is_number(name + 1)) {
743 jobno = number(name + 1) - 1;
744 } else if (!name[2]) {
745 switch (name[1]) {
746 #if JOBS
747 case 0:
748 case '+':
749 case '%':
750 jobno = curjob;
751 err_msg = "No current job";
752 break;
753 case '-':
754 jobno = curjob;
755 if (jobno != -1)
756 jobno = jobtab[jobno].prev_job;
757 err_msg = "No previous job";
758 break;
759 #endif
760 default:
761 goto check_pattern;
762 }
763 } else {
764 struct job *found;
765 check_pattern:
766 found = NULL;
767 for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) {
768 if (!jp->used || jp->nprocs <= 0)
769 continue;
770 if ((name[1] == '?'
771 && strstr(jp->ps[0].cmd, name + 2))
772 || prefix(name + 1, jp->ps[0].cmd)) {
773 if (found) {
774 err_msg = "%s: ambiguous";
775 found = 0;
776 break;
777 }
778 found = jp;
779 }
780 }
781 if (found)
782 return found;
783 }
784
785 } else if (is_number(name)) {
786 pid = number(name);
787 for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) {
788 if (jp->used && jp->nprocs > 0
789 && jp->ps[jp->nprocs - 1].pid == pid)
790 return jp;
791 }
792 }
793
794 if (!jobs_invalid && jobno >= 0 && jobno < njobs) {
795 jp = jobtab + jobno;
796 if (jp->used)
797 return jp;
798 }
799 if (!noerror)
800 error(err_msg, name);
801 return 0;
802 }
803
804
805
806 /*
807 * Return a new job structure,
808 */
809
810 struct job *
811 makejob(union node *node, int nprocs)
812 {
813 int i;
814 struct job *jp;
815
816 if (jobs_invalid) {
817 for (i = njobs, jp = jobtab ; --i >= 0 ; jp++) {
818 if (jp->used)
819 freejob(jp);
820 }
821 jobs_invalid = 0;
822 }
823
824 for (i = njobs, jp = jobtab ; ; jp++) {
825 if (--i < 0) {
826 INTOFF;
827 if (njobs == 0) {
828 jobtab = ckmalloc(4 * sizeof jobtab[0]);
829 } else {
830 jp = ckmalloc((njobs + 4) * sizeof jobtab[0]);
831 memcpy(jp, jobtab, njobs * sizeof jp[0]);
832 /* Relocate `ps' pointers */
833 for (i = 0; i < njobs; i++)
834 if (jp[i].ps == &jobtab[i].ps0)
835 jp[i].ps = &jp[i].ps0;
836 ckfree(jobtab);
837 jobtab = jp;
838 }
839 jp = jobtab + njobs;
840 for (i = 4 ; --i >= 0 ; )
841 jobtab[njobs++].used = 0;
842 INTON;
843 break;
844 }
845 if (jp->used == 0)
846 break;
847 }
848 INTOFF;
849 jp->state = JOBRUNNING;
850 jp->used = 1;
851 jp->changed = 0;
852 jp->nprocs = 0;
853 #if JOBS
854 jp->jobctl = jobctl;
855 set_curjob(jp, 1);
856 #endif
857 if (nprocs > 1) {
858 jp->ps = ckmalloc(nprocs * sizeof (struct procstat));
859 } else {
860 jp->ps = &jp->ps0;
861 }
862 INTON;
863 VTRACE(DBG_JOBS, ("makejob(0x%lx, %d) returns %%%d\n",
864 (long)node, nprocs, jp - jobtab + 1));
865 return jp;
866 }
867
868
869 /*
870 * Fork off a subshell. If we are doing job control, give the subshell its
871 * own process group. Jp is a job structure that the job is to be added to.
872 * N is the command that will be evaluated by the child. Both jp and n may
873 * be NULL. The mode parameter can be one of the following:
874 * FORK_FG - Fork off a foreground process.
875 * FORK_BG - Fork off a background process.
876 * FORK_NOJOB - Like FORK_FG, but don't give the process its own
877 * process group even if job control is on.
878 *
879 * When job control is turned off, background processes have their standard
880 * input redirected to /dev/null (except for the second and later processes
881 * in a pipeline).
882 */
883
884 int
885 forkshell(struct job *jp, union node *n, int mode)
886 {
887 pid_t pid;
888 int serrno;
889
890 CTRACE(DBG_JOBS, ("forkshell(%%%d, %p, %d) called\n",
891 jp - jobtab, n, mode));
892
893 switch ((pid = fork())) {
894 case -1:
895 serrno = errno;
896 VTRACE(DBG_JOBS, ("Fork failed, errno=%d\n", serrno));
897 INTON;
898 error("Cannot fork (%s)", strerror(serrno));
899 break;
900 case 0:
901 SHELL_FORKED();
902 forkchild(jp, n, mode, 0);
903 return 0;
904 default:
905 return forkparent(jp, n, mode, pid);
906 }
907 }
908
909 int
910 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
911 {
912 int pgrp;
913
914 if (rootshell && mode != FORK_NOJOB && mflag) {
915 if (jp == NULL || jp->nprocs == 0)
916 pgrp = pid;
917 else
918 pgrp = jp->ps[0].pid;
919 /* This can fail because we are doing it in the child also */
920 (void)setpgid(pid, pgrp);
921 }
922 if (mode == FORK_BG)
923 backgndpid = pid; /* set $! */
924 if (jp) {
925 struct procstat *ps = &jp->ps[jp->nprocs++];
926 ps->pid = pid;
927 ps->status = -1;
928 ps->cmd[0] = 0;
929 if (/* iflag && rootshell && */ n)
930 commandtext(ps, n);
931 }
932 CTRACE(DBG_JOBS, ("In parent shell: child = %d (mode %d)\n",pid,mode));
933 return pid;
934 }
935
936 void
937 forkchild(struct job *jp, union node *n, int mode, int vforked)
938 {
939 int wasroot;
940 int pgrp;
941 const char *devnull = _PATH_DEVNULL;
942 const char *nullerr = "Can't open %s";
943
944 wasroot = rootshell;
945 CTRACE(DBG_JOBS, ("Child shell %d%s\n",getpid(),vforked?" vforked":""));
946 if (!vforked)
947 rootshell = 0;
948
949 closescript(vforked);
950 clear_traps(vforked);
951 #if JOBS
952 if (!vforked)
953 jobctl = 0; /* do job control only in root shell */
954 if (wasroot && mode != FORK_NOJOB && mflag) {
955 if (jp == NULL || jp->nprocs == 0)
956 pgrp = getpid();
957 else
958 pgrp = jp->ps[0].pid;
959 /* This can fail because we are doing it in the parent also */
960 (void)setpgid(0, pgrp);
961 if (mode == FORK_FG) {
962 if (tcsetpgrp(ttyfd, pgrp) == -1)
963 error("Cannot set tty process group (%s) at %d",
964 strerror(errno), __LINE__);
965 }
966 setsignal(SIGTSTP, vforked);
967 setsignal(SIGTTOU, vforked);
968 } else if (mode == FORK_BG) {
969 ignoresig(SIGINT, vforked);
970 ignoresig(SIGQUIT, vforked);
971 if ((jp == NULL || jp->nprocs == 0) &&
972 ! fd0_redirected_p ()) {
973 close(0);
974 if (open(devnull, O_RDONLY) != 0)
975 error(nullerr, devnull);
976 }
977 }
978 #else
979 if (mode == FORK_BG) {
980 ignoresig(SIGINT, vforked);
981 ignoresig(SIGQUIT, vforked);
982 if ((jp == NULL || jp->nprocs == 0) &&
983 ! fd0_redirected_p ()) {
984 close(0);
985 if (open(devnull, O_RDONLY) != 0)
986 error(nullerr, devnull);
987 }
988 }
989 #endif
990 if (wasroot && iflag) {
991 setsignal(SIGINT, vforked);
992 setsignal(SIGQUIT, vforked);
993 setsignal(SIGTERM, vforked);
994 }
995
996 if (!vforked)
997 jobs_invalid = 1;
998 }
999
1000 /*
1001 * Wait for job to finish.
1002 *
1003 * Under job control we have the problem that while a child process is
1004 * running interrupts generated by the user are sent to the child but not
1005 * to the shell. This means that an infinite loop started by an inter-
1006 * active user may be hard to kill. With job control turned off, an
1007 * interactive user may place an interactive program inside a loop. If
1008 * the interactive program catches interrupts, the user doesn't want
1009 * these interrupts to also abort the loop. The approach we take here
1010 * is to have the shell ignore interrupt signals while waiting for a
1011 * forground process to terminate, and then send itself an interrupt
1012 * signal if the child process was terminated by an interrupt signal.
1013 * Unfortunately, some programs want to do a bit of cleanup and then
1014 * exit on interrupt; unless these processes terminate themselves by
1015 * sending a signal to themselves (instead of calling exit) they will
1016 * confuse this approach.
1017 */
1018
1019 int
1020 waitforjob(struct job *jp)
1021 {
1022 #if JOBS
1023 int mypgrp = getpgrp();
1024 #endif
1025 int status;
1026 int st;
1027
1028 INTOFF;
1029 VTRACE(DBG_JOBS, ("waitforjob(%%%d) called\n", jp - jobtab + 1));
1030 while (jp->state == JOBRUNNING) {
1031 dowait(WBLOCK, jp);
1032 }
1033 #if JOBS
1034 if (jp->jobctl) {
1035 if (tcsetpgrp(ttyfd, mypgrp) == -1)
1036 error("Cannot set tty process group (%s) at %d",
1037 strerror(errno), __LINE__);
1038 }
1039 if (jp->state == JOBSTOPPED && curjob != jp - jobtab)
1040 set_curjob(jp, 2);
1041 #endif
1042 status = jobstatus(jp, 1);
1043
1044 /* convert to 8 bits */
1045 if (WIFEXITED(status))
1046 st = WEXITSTATUS(status);
1047 #if JOBS
1048 else if (WIFSTOPPED(status))
1049 st = WSTOPSIG(status) + 128;
1050 #endif
1051 else
1052 st = WTERMSIG(status) + 128;
1053
1054 VTRACE(DBG_JOBS, ("waitforjob: job %d, nproc %d, status %d, st %x\n",
1055 jp - jobtab + 1, jp->nprocs, status, st));
1056 #if JOBS
1057 if (jp->jobctl) {
1058 /*
1059 * This is truly gross.
1060 * If we're doing job control, then we did a TIOCSPGRP which
1061 * caused us (the shell) to no longer be in the controlling
1062 * session -- so we wouldn't have seen any ^C/SIGINT. So, we
1063 * intuit from the subprocess exit status whether a SIGINT
1064 * occurred, and if so interrupt ourselves. Yuck. - mycroft
1065 */
1066 if (WIFSIGNALED(status) && WTERMSIG(status) == SIGINT)
1067 raise(SIGINT);
1068 }
1069 #endif
1070 if (! JOBS || jp->state == JOBDONE)
1071 freejob(jp);
1072 INTON;
1073 return st;
1074 }
1075
1076
1077
1078 /*
1079 * Wait for a process to terminate.
1080 */
1081
1082 STATIC int
1083 dowait(int flags, struct job *job)
1084 {
1085 int pid;
1086 int status;
1087 struct procstat *sp;
1088 struct job *jp;
1089 struct job *thisjob;
1090 int done;
1091 int stopped;
1092
1093 VTRACE(DBG_JOBS|DBG_PROCS, ("dowait(%x) called\n", flags));
1094 do {
1095 pid = waitproc(flags & WBLOCK, job, &status);
1096 VTRACE(DBG_JOBS|DBG_PROCS, ("wait returns pid %d, status %#x\n",
1097 pid, status));
1098 } while (pid == -1 && errno == EINTR && pendingsigs == 0);
1099 if (pid <= 0)
1100 return pid;
1101 INTOFF;
1102 thisjob = NULL;
1103 for (jp = jobtab ; jp < jobtab + njobs ; jp++) {
1104 if (jp->used) {
1105 done = 1;
1106 stopped = 1;
1107 for (sp = jp->ps ; sp < jp->ps + jp->nprocs ; sp++) {
1108 if (sp->pid == -1)
1109 continue;
1110 if (sp->pid == pid) {
1111 VTRACE(DBG_JOBS | DBG_PROCS,
1112 ("Job %d: changing status of proc %d from %#x to %#x\n",
1113 jp - jobtab + 1, pid,
1114 sp->status, status));
1115 sp->status = status;
1116 thisjob = jp;
1117 }
1118 if (sp->status == -1)
1119 stopped = 0;
1120 else if (WIFSTOPPED(sp->status))
1121 done = 0;
1122 }
1123 if (stopped) { /* stopped or done */
1124 int state = done ? JOBDONE : JOBSTOPPED;
1125 if (jp->state != state) {
1126 VTRACE(DBG_JOBS,
1127 ("Job %d: changing state from %d to %d\n",
1128 jp - jobtab + 1, jp->state, state));
1129 jp->state = state;
1130 #if JOBS
1131 if (done)
1132 set_curjob(jp, 0);
1133 #endif
1134 }
1135 }
1136 }
1137 }
1138
1139 if (thisjob && thisjob->state != JOBRUNNING) {
1140 int mode = 0;
1141 if (!rootshell || !iflag)
1142 mode = SHOW_SIGNALLED;
1143 if ((job == thisjob && (flags & WNOFREE) == 0) ||
1144 (job != thisjob && (flags & WNOFREE) != 0))
1145 mode = SHOW_SIGNALLED | SHOW_NO_FREE;
1146 if (mode)
1147 showjob(out2, thisjob, mode);
1148 else {
1149 VTRACE(DBG_JOBS,
1150 ("Not printing status, rootshell=%d, job=%p\n",
1151 rootshell, job));
1152 thisjob->changed = 1;
1153 }
1154 }
1155
1156 INTON;
1157 return pid;
1158 }
1159
1160
1161
1162 /*
1163 * Do a wait system call. If job control is compiled in, we accept
1164 * stopped processes. If block is zero, we return a value of zero
1165 * rather than blocking.
1166 *
1167 * System V doesn't have a non-blocking wait system call. It does
1168 * have a SIGCLD signal that is sent to a process when one of its
1169 * children dies. The obvious way to use SIGCLD would be to install
1170 * a handler for SIGCLD which simply bumped a counter when a SIGCLD
1171 * was received, and have waitproc bump another counter when it got
1172 * the status of a process. Waitproc would then know that a wait
1173 * system call would not block if the two counters were different.
1174 * This approach doesn't work because if a process has children that
1175 * have not been waited for, System V will send it a SIGCLD when it
1176 * installs a signal handler for SIGCLD. What this means is that when
1177 * a child exits, the shell will be sent SIGCLD signals continuously
1178 * until is runs out of stack space, unless it does a wait call before
1179 * restoring the signal handler. The code below takes advantage of
1180 * this (mis)feature by installing a signal handler for SIGCLD and
1181 * then checking to see whether it was called. If there are any
1182 * children to be waited for, it will be.
1183 *
1184 * If neither SYSV nor BSD is defined, we don't implement nonblocking
1185 * waits at all. In this case, the user will not be informed when
1186 * a background process until the next time she runs a real program
1187 * (as opposed to running a builtin command or just typing return),
1188 * and the jobs command may give out of date information.
1189 */
1190
1191 #ifdef SYSV
1192 STATIC int gotsigchild;
1193
1194 STATIC int onsigchild() {
1195 gotsigchild = 1;
1196 }
1197 #endif
1198
1199
1200 STATIC int
1201 waitproc(int block, struct job *jp, int *status)
1202 {
1203 #ifdef BSD
1204 int flags = 0;
1205
1206 #if JOBS
1207 if (jp != NULL && jp->jobctl)
1208 flags |= WUNTRACED;
1209 #endif
1210 if (block == 0)
1211 flags |= WNOHANG;
1212 return waitpid(-1, status, flags);
1213 #else
1214 #ifdef SYSV
1215 int (*save)();
1216
1217 if (block == 0) {
1218 gotsigchild = 0;
1219 save = signal(SIGCLD, onsigchild);
1220 signal(SIGCLD, save);
1221 if (gotsigchild == 0)
1222 return 0;
1223 }
1224 return wait(status);
1225 #else
1226 if (block == 0)
1227 return 0;
1228 return wait(status);
1229 #endif
1230 #endif
1231 }
1232
1233 /*
1234 * return 1 if there are stopped jobs, otherwise 0
1235 */
1236 int job_warning = 0;
1237 int
1238 stoppedjobs(void)
1239 {
1240 int jobno;
1241 struct job *jp;
1242
1243 if (job_warning || jobs_invalid)
1244 return (0);
1245 for (jobno = 1, jp = jobtab; jobno <= njobs; jobno++, jp++) {
1246 if (jp->used == 0)
1247 continue;
1248 if (jp->state == JOBSTOPPED) {
1249 out2str("You have stopped jobs.\n");
1250 job_warning = 2;
1251 return (1);
1252 }
1253 }
1254
1255 return (0);
1256 }
1257
1258 /*
1259 * Return a string identifying a command (to be printed by the
1260 * jobs command).
1261 */
1262
1263 STATIC char *cmdnextc;
1264 STATIC int cmdnleft;
1265
1266 void
1267 commandtext(struct procstat *ps, union node *n)
1268 {
1269 int len;
1270
1271 cmdnextc = ps->cmd;
1272 if (iflag || mflag || sizeof ps->cmd < 100)
1273 len = sizeof(ps->cmd);
1274 else
1275 len = sizeof(ps->cmd) / 10;
1276 cmdnleft = len;
1277 cmdtxt(n);
1278 if (cmdnleft <= 0) {
1279 char *p = ps->cmd + len - 4;
1280 p[0] = '.';
1281 p[1] = '.';
1282 p[2] = '.';
1283 p[3] = 0;
1284 } else
1285 *cmdnextc = '\0';
1286
1287 VTRACE(DBG_JOBS,
1288 ("commandtext: ps->cmd %x, end %x, left %d\n\t\"%s\"\n",
1289 ps->cmd, cmdnextc, cmdnleft, ps->cmd));
1290 }
1291
1292
1293 STATIC void
1294 cmdtxt(union node *n)
1295 {
1296 union node *np;
1297 struct nodelist *lp;
1298 const char *p;
1299 int i;
1300
1301 if (n == NULL || cmdnleft <= 0)
1302 return;
1303 switch (n->type) {
1304 case NSEMI:
1305 cmdtxt(n->nbinary.ch1);
1306 cmdputs("; ");
1307 cmdtxt(n->nbinary.ch2);
1308 break;
1309 case NAND:
1310 cmdtxt(n->nbinary.ch1);
1311 cmdputs(" && ");
1312 cmdtxt(n->nbinary.ch2);
1313 break;
1314 case NOR:
1315 cmdtxt(n->nbinary.ch1);
1316 cmdputs(" || ");
1317 cmdtxt(n->nbinary.ch2);
1318 break;
1319 case NDNOT:
1320 cmdputs("! ");
1321 /* FALLTHROUGH */
1322 case NNOT:
1323 cmdputs("! ");
1324 cmdtxt(n->nnot.com);
1325 break;
1326 case NPIPE:
1327 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
1328 cmdtxt(lp->n);
1329 if (lp->next)
1330 cmdputs(" | ");
1331 }
1332 if (n->npipe.backgnd)
1333 cmdputs(" &");
1334 break;
1335 case NSUBSHELL:
1336 cmdputs("(");
1337 cmdtxt(n->nredir.n);
1338 cmdputs(")");
1339 break;
1340 case NREDIR:
1341 case NBACKGND:
1342 cmdtxt(n->nredir.n);
1343 break;
1344 case NIF:
1345 cmdputs("if ");
1346 cmdtxt(n->nif.test);
1347 cmdputs("; then ");
1348 cmdtxt(n->nif.ifpart);
1349 if (n->nif.elsepart) {
1350 cmdputs("; else ");
1351 cmdtxt(n->nif.elsepart);
1352 }
1353 cmdputs("; fi");
1354 break;
1355 case NWHILE:
1356 cmdputs("while ");
1357 goto until;
1358 case NUNTIL:
1359 cmdputs("until ");
1360 until:
1361 cmdtxt(n->nbinary.ch1);
1362 cmdputs("; do ");
1363 cmdtxt(n->nbinary.ch2);
1364 cmdputs("; done");
1365 break;
1366 case NFOR:
1367 cmdputs("for ");
1368 cmdputs(n->nfor.var);
1369 cmdputs(" in ");
1370 cmdlist(n->nfor.args, 1);
1371 cmdputs("; do ");
1372 cmdtxt(n->nfor.body);
1373 cmdputs("; done");
1374 break;
1375 case NCASE:
1376 cmdputs("case ");
1377 cmdputs(n->ncase.expr->narg.text);
1378 cmdputs(" in ");
1379 for (np = n->ncase.cases; np; np = np->nclist.next) {
1380 cmdtxt(np->nclist.pattern);
1381 cmdputs(") ");
1382 cmdtxt(np->nclist.body);
1383 switch (n->type) { /* switch (not if) for later */
1384 case NCLISTCONT:
1385 cmdputs(";& ");
1386 break;
1387 default:
1388 cmdputs(";; ");
1389 break;
1390 }
1391 }
1392 cmdputs("esac");
1393 break;
1394 case NDEFUN:
1395 cmdputs(n->narg.text);
1396 cmdputs("() { ... }");
1397 break;
1398 case NCMD:
1399 cmdlist(n->ncmd.args, 1);
1400 cmdlist(n->ncmd.redirect, 0);
1401 if (n->ncmd.backgnd)
1402 cmdputs(" &");
1403 break;
1404 case NARG:
1405 cmdputs(n->narg.text);
1406 break;
1407 case NTO:
1408 p = ">"; i = 1; goto redir;
1409 case NCLOBBER:
1410 p = ">|"; i = 1; goto redir;
1411 case NAPPEND:
1412 p = ">>"; i = 1; goto redir;
1413 case NTOFD:
1414 p = ">&"; i = 1; goto redir;
1415 case NFROM:
1416 p = "<"; i = 0; goto redir;
1417 case NFROMFD:
1418 p = "<&"; i = 0; goto redir;
1419 case NFROMTO:
1420 p = "<>"; i = 0; goto redir;
1421 redir:
1422 if (n->nfile.fd != i)
1423 cmdputi(n->nfile.fd);
1424 cmdputs(p);
1425 if (n->type == NTOFD || n->type == NFROMFD) {
1426 if (n->ndup.dupfd < 0)
1427 cmdputs("-");
1428 else
1429 cmdputi(n->ndup.dupfd);
1430 } else {
1431 cmdtxt(n->nfile.fname);
1432 }
1433 break;
1434 case NHERE:
1435 case NXHERE:
1436 cmdputs("<<...");
1437 break;
1438 default:
1439 cmdputs("???");
1440 break;
1441 }
1442 }
1443
1444 STATIC void
1445 cmdlist(union node *np, int sep)
1446 {
1447 for (; np; np = np->narg.next) {
1448 if (!sep)
1449 cmdputs(" ");
1450 cmdtxt(np);
1451 if (sep && np->narg.next)
1452 cmdputs(" ");
1453 }
1454 }
1455
1456
1457 STATIC void
1458 cmdputs(const char *s)
1459 {
1460 const char *p, *str = 0;
1461 char c, cc[2] = " ";
1462 char *nextc;
1463 int nleft;
1464 int subtype = 0;
1465 int quoted = 0;
1466 static char vstype[16][4] = { "", "}", "-", "+", "?", "=",
1467 "#", "##", "%", "%%", "}" };
1468
1469 p = s;
1470 nextc = cmdnextc;
1471 nleft = cmdnleft;
1472 while (nleft > 0 && (c = *p++) != 0) {
1473 switch (c) {
1474 case CTLNONL:
1475 c = '\0';
1476 break;
1477 case CTLESC:
1478 c = *p++;
1479 break;
1480 case CTLVAR:
1481 subtype = *p++;
1482 if (subtype & VSLINENO) { /* undo LINENO hack */
1483 if ((subtype & VSTYPE) == VSLENGTH)
1484 str = "${#LINENO"; /*}*/
1485 else
1486 str = "${LINENO"; /*}*/
1487 while (is_digit(*p))
1488 p++;
1489 } else if ((subtype & VSTYPE) == VSLENGTH)
1490 str = "${#"; /*}*/
1491 else
1492 str = "${"; /*}*/
1493 if (!(subtype & VSQUOTE) != !(quoted & 1)) {
1494 quoted ^= 1;
1495 c = '"';
1496 } else {
1497 c = *str++;
1498 }
1499 break;
1500 case CTLENDVAR: /*{*/
1501 c = '}';
1502 if (quoted & 1)
1503 str = "\"";
1504 quoted >>= 1;
1505 subtype = 0;
1506 break;
1507 case CTLBACKQ:
1508 c = '$';
1509 str = "(...)";
1510 break;
1511 case CTLBACKQ+CTLQUOTE:
1512 c = '"';
1513 str = "$(...)\"";
1514 break;
1515 case CTLARI:
1516 c = '$';
1517 if (*p == ' ')
1518 p++;
1519 str = "(("; /*))*/
1520 break;
1521 case CTLENDARI: /*((*/
1522 c = ')';
1523 str = ")";
1524 break;
1525 case CTLQUOTEMARK:
1526 quoted ^= 1;
1527 c = '"';
1528 break;
1529 case CTLQUOTEEND:
1530 quoted >>= 1;
1531 c = '"';
1532 break;
1533 case '=':
1534 if (subtype == 0)
1535 break;
1536 str = vstype[subtype & VSTYPE];
1537 if (subtype & VSNUL)
1538 c = ':';
1539 else
1540 c = *str++; /*{*/
1541 if (c != '}')
1542 quoted <<= 1;
1543 else if (*p == CTLENDVAR)
1544 c = *str++;
1545 subtype = 0;
1546 break;
1547 case '\'':
1548 case '\\':
1549 case '"':
1550 case '$':
1551 /* These can only happen inside quotes */
1552 cc[0] = c;
1553 str = cc;
1554 c = '\\';
1555 break;
1556 default:
1557 break;
1558 }
1559 if (c != '\0') do { /* c == 0 implies nothing in str */
1560 *nextc++ = c;
1561 } while (--nleft > 0 && str && (c = *str++));
1562 str = 0;
1563 }
1564 if ((quoted & 1) && nleft) {
1565 *nextc++ = '"';
1566 nleft--;
1567 }
1568 cmdnleft = nleft;
1569 cmdnextc = nextc;
1570 }
1571