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