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