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