jobs.c revision 1.43.2.1 1 /* $NetBSD: jobs.c,v 1.43.2.1 2002/03/27 20:37:38 elric 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.43.2.1 2002/03/27 20:37:38 elric 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 struct job *jobtab; /* array of jobs */
89 int njobs; /* size of array */
90 MKINIT short backgndpid = -1; /* pid of last background process */
91 #if JOBS
92 int initialpgrp; /* pgrp of shell on invocation */
93 short curjob; /* current job */
94 #endif
95
96 STATIC void restartjob __P((struct job *));
97 STATIC void freejob __P((struct job *));
98 STATIC struct job *getjob __P((char *));
99 STATIC int dowait __P((int, struct job *));
100 STATIC int onsigchild __P((void));
101 STATIC int waitproc __P((int, struct job *, int *));
102 STATIC void cmdtxt __P((union node *));
103 STATIC void cmdputs __P((const char *));
104
105
106 /*
107 * Turn job control on and off.
108 *
109 * Note: This code assumes that the third arg to ioctl is a character
110 * pointer, which is true on Berkeley systems but not System V. Since
111 * System V doesn't have job control yet, this isn't a problem now.
112 */
113
114 MKINIT int jobctl;
115
116 void
117 setjobctl(on)
118 int on;
119 {
120 #ifdef OLD_TTY_DRIVER
121 int ldisc;
122 #endif
123
124 if (on == jobctl || rootshell == 0)
125 return;
126 if (on) {
127 do { /* while we are in the background */
128 #ifdef OLD_TTY_DRIVER
129 if (ioctl(2, TIOCGPGRP, (char *)&initialpgrp) < 0) {
130 #else
131 initialpgrp = tcgetpgrp(2);
132 if (initialpgrp < 0) {
133 #endif
134 out2str("sh: can't access tty; job control turned off\n");
135 mflag = 0;
136 return;
137 }
138 if (initialpgrp == -1)
139 initialpgrp = getpgrp();
140 else if (initialpgrp != getpgrp()) {
141 killpg(initialpgrp, SIGTTIN);
142 continue;
143 }
144 } while (0);
145 #ifdef OLD_TTY_DRIVER
146 if (ioctl(2, TIOCGETD, (char *)&ldisc) < 0 || ldisc != NTTYDISC) {
147 out2str("sh: need new tty driver to run job control; job control turned off\n");
148 mflag = 0;
149 return;
150 }
151 #endif
152 setsignal(SIGTSTP, 0);
153 setsignal(SIGTTOU, 0);
154 setsignal(SIGTTIN, 0);
155 setpgid(0, rootpid);
156 #ifdef OLD_TTY_DRIVER
157 ioctl(2, TIOCSPGRP, (char *)&rootpid);
158 #else
159 tcsetpgrp(2, rootpid);
160 #endif
161 } else { /* turning job control off */
162 setpgid(0, initialpgrp);
163 #ifdef OLD_TTY_DRIVER
164 ioctl(2, TIOCSPGRP, (char *)&initialpgrp);
165 #else
166 tcsetpgrp(2, initialpgrp);
167 #endif
168 setsignal(SIGTSTP, 0);
169 setsignal(SIGTTOU, 0);
170 setsignal(SIGTTIN, 0);
171 }
172 jobctl = on;
173 }
174
175
176 #ifdef mkinit
177 INCLUDE <stdlib.h>
178
179 SHELLPROC {
180 backgndpid = -1;
181 #if JOBS
182 jobctl = 0;
183 #endif
184 }
185
186 #endif
187
188
189
190 #if JOBS
191 int
192 fgcmd(argc, argv)
193 int argc;
194 char **argv;
195 {
196 struct job *jp;
197 int pgrp;
198 int status;
199
200 jp = getjob(argv[1]);
201 if (jp->jobctl == 0)
202 error("job not created under job control");
203 pgrp = jp->ps[0].pid;
204 #ifdef OLD_TTY_DRIVER
205 ioctl(2, TIOCSPGRP, (char *)&pgrp);
206 #else
207 tcsetpgrp(2, pgrp);
208 #endif
209 restartjob(jp);
210 INTOFF;
211 status = waitforjob(jp);
212 INTON;
213 return status;
214 }
215
216
217 int
218 bgcmd(argc, argv)
219 int argc;
220 char **argv;
221 {
222 struct job *jp;
223
224 do {
225 jp = getjob(*++argv);
226 if (jp->jobctl == 0)
227 error("job not created under job control");
228 restartjob(jp);
229 } while (--argc > 1);
230 return 0;
231 }
232
233
234 STATIC void
235 restartjob(jp)
236 struct job *jp;
237 {
238 struct procstat *ps;
239 int i;
240
241 if (jp->state == JOBDONE)
242 return;
243 INTOFF;
244 killpg(jp->ps[0].pid, SIGCONT);
245 for (ps = jp->ps, i = jp->nprocs ; --i >= 0 ; ps++) {
246 if (WIFSTOPPED(ps->status)) {
247 ps->status = -1;
248 jp->state = 0;
249 }
250 }
251 INTON;
252 }
253 #endif
254
255
256 int
257 jobscmd(argc, argv)
258 int argc;
259 char **argv;
260 {
261 showjobs(0);
262 return 0;
263 }
264
265
266 /*
267 * Print a list of jobs. If "change" is nonzero, only print jobs whose
268 * statuses have changed since the last call to showjobs.
269 *
270 * If the shell is interrupted in the process of creating a job, the
271 * result may be a job structure containing zero processes. Such structures
272 * will be freed here.
273 */
274
275 void
276 showjobs(change)
277 int change;
278 {
279 int jobno;
280 int procno;
281 int i;
282 struct job *jp;
283 struct procstat *ps;
284 int col;
285 char s[64];
286
287 TRACE(("showjobs(%d) called\n", change));
288 while (dowait(0, (struct job *)NULL) > 0);
289 for (jobno = 1, jp = jobtab ; jobno <= njobs ; jobno++, jp++) {
290 if (! jp->used)
291 continue;
292 if (jp->nprocs == 0) {
293 freejob(jp);
294 continue;
295 }
296 if (change && ! jp->changed)
297 continue;
298 procno = jp->nprocs;
299 for (ps = jp->ps ; ; ps++) { /* for each process */
300 if (ps == jp->ps)
301 fmtstr(s, 64, "[%d] %ld ", jobno,
302 (long)ps->pid);
303 else
304 fmtstr(s, 64, " %ld ",
305 (long)ps->pid);
306 out1str(s);
307 col = strlen(s);
308 s[0] = '\0';
309 if (ps->status == -1) {
310 /* don't print anything */
311 } else if (WIFEXITED(ps->status)) {
312 fmtstr(s, 64, "Exit %d",
313 WEXITSTATUS(ps->status));
314 } else {
315 #if JOBS
316 if (WIFSTOPPED(ps->status))
317 i = WSTOPSIG(ps->status);
318 else /* WIFSIGNALED(ps->status) */
319 #endif
320 i = WTERMSIG(ps->status);
321 if ((i & 0x7F) < NSIG && sys_siglist[i & 0x7F])
322 scopy(sys_siglist[i & 0x7F], s);
323 else
324 fmtstr(s, 64, "Signal %d", i & 0x7F);
325 if (WCOREDUMP(ps->status))
326 strcat(s, " (core dumped)");
327 }
328 out1str(s);
329 col += strlen(s);
330 do {
331 out1c(' ');
332 col++;
333 } while (col < 30);
334 out1str(ps->cmd);
335 out1c('\n');
336 if (--procno <= 0)
337 break;
338 }
339 jp->changed = 0;
340 if (jp->state == JOBDONE) {
341 freejob(jp);
342 }
343 }
344 }
345
346
347 /*
348 * Mark a job structure as unused.
349 */
350
351 STATIC void
352 freejob(jp)
353 struct job *jp;
354 {
355 struct procstat *ps;
356 int i;
357
358 INTOFF;
359 for (i = jp->nprocs, ps = jp->ps ; --i >= 0 ; ps++) {
360 if (ps->cmd != nullstr)
361 ckfree(ps->cmd);
362 }
363 if (jp->ps != &jp->ps0) {
364 ckfree(jp->ps);
365 jp->ps = &jp->ps0;
366 }
367 jp->nprocs = 0;
368 jp->used = 0;
369 #if JOBS
370 if (curjob == jp - jobtab + 1)
371 curjob = 0;
372 #endif
373 INTON;
374 }
375
376
377
378 int
379 waitcmd(argc, argv)
380 int argc;
381 char **argv;
382 {
383 struct job *job;
384 int status, retval;
385 struct job *jp;
386
387 if (argc > 1) {
388 job = getjob(argv[1]);
389 } else {
390 job = NULL;
391 }
392 for (;;) { /* loop until process terminated or stopped */
393 if (job != NULL) {
394 if (job->state) {
395 status = job->ps[job->nprocs - 1].status;
396 if (WIFEXITED(status))
397 retval = WEXITSTATUS(status);
398 #if JOBS
399 else if (WIFSTOPPED(status))
400 retval = WSTOPSIG(status) + 128;
401 #endif
402 else {
403 /* XXX: limits number of signals */
404 retval = WTERMSIG(status) + 128;
405 }
406 if (! iflag)
407 freejob(job);
408 return retval;
409 }
410 } else {
411 for (jp = jobtab ; ; jp++) {
412 if (jp >= jobtab + njobs) { /* no running procs */
413 return 0;
414 }
415 if (jp->used && jp->state == 0)
416 break;
417 }
418 }
419 if (dowait(1, (struct job *)NULL) == -1)
420 return 128 + SIGINT;
421 }
422 }
423
424
425
426 int
427 jobidcmd(argc, argv)
428 int argc;
429 char **argv;
430 {
431 struct job *jp;
432 int i;
433
434 jp = getjob(argv[1]);
435 for (i = 0 ; i < jp->nprocs ; ) {
436 out1fmt("%ld", (long)jp->ps[i].pid);
437 out1c(++i < jp->nprocs? ' ' : '\n');
438 }
439 return 0;
440 }
441
442
443
444 /*
445 * Convert a job name to a job structure.
446 */
447
448 STATIC struct job *
449 getjob(name)
450 char *name;
451 {
452 int jobno;
453 struct job *jp;
454 int pid;
455 int i;
456
457 if (name == NULL) {
458 #if JOBS
459 currentjob:
460 if ((jobno = curjob) == 0 || jobtab[jobno - 1].used == 0)
461 error("No current job");
462 return &jobtab[jobno - 1];
463 #else
464 error("No current job");
465 #endif
466 } else if (name[0] == '%') {
467 if (is_digit(name[1])) {
468 jobno = number(name + 1);
469 if (jobno > 0 && jobno <= njobs
470 && jobtab[jobno - 1].used != 0)
471 return &jobtab[jobno - 1];
472 #if JOBS
473 } else if (name[1] == '%' && name[2] == '\0') {
474 goto currentjob;
475 #endif
476 } else {
477 struct job *found = NULL;
478 for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) {
479 if (jp->used && jp->nprocs > 0
480 && prefix(name + 1, jp->ps[0].cmd)) {
481 if (found)
482 error("%s: ambiguous", name);
483 found = jp;
484 }
485 }
486 if (found)
487 return found;
488 }
489 } else if (is_number(name)) {
490 pid = number(name);
491 for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) {
492 if (jp->used && jp->nprocs > 0
493 && jp->ps[jp->nprocs - 1].pid == pid)
494 return jp;
495 }
496 }
497 error("No such job: %s", name);
498 /* NOTREACHED */
499 }
500
501
502
503 /*
504 * Return a new job structure,
505 */
506
507 struct job *
508 makejob(node, nprocs)
509 union node *node;
510 int nprocs;
511 {
512 int i;
513 struct job *jp;
514
515 for (i = njobs, jp = jobtab ; ; jp++) {
516 if (--i < 0) {
517 INTOFF;
518 if (njobs == 0) {
519 jobtab = ckmalloc(4 * sizeof jobtab[0]);
520 } else {
521 jp = ckmalloc((njobs + 4) * sizeof jobtab[0]);
522 memcpy(jp, jobtab, njobs * sizeof jp[0]);
523 /* Relocate `ps' pointers */
524 for (i = 0; i < njobs; i++)
525 if (jp[i].ps == &jobtab[i].ps0)
526 jp[i].ps = &jp[i].ps0;
527 ckfree(jobtab);
528 jobtab = jp;
529 }
530 jp = jobtab + njobs;
531 for (i = 4 ; --i >= 0 ; jobtab[njobs++].used = 0);
532 INTON;
533 break;
534 }
535 if (jp->used == 0)
536 break;
537 }
538 INTOFF;
539 jp->state = 0;
540 jp->used = 1;
541 jp->changed = 0;
542 jp->nprocs = 0;
543 #if JOBS
544 jp->jobctl = jobctl;
545 #endif
546 if (nprocs > 1) {
547 jp->ps = ckmalloc(nprocs * sizeof (struct procstat));
548 } else {
549 jp->ps = &jp->ps0;
550 }
551 INTON;
552 TRACE(("makejob(0x%lx, %d) returns %%%d\n", (long)node, nprocs,
553 jp - jobtab + 1));
554 return jp;
555 }
556
557
558 /*
559 * Fork off a subshell. If we are doing job control, give the subshell its
560 * own process group. Jp is a job structure that the job is to be added to.
561 * N is the command that will be evaluated by the child. Both jp and n may
562 * be NULL. The mode parameter can be one of the following:
563 * FORK_FG - Fork off a foreground process.
564 * FORK_BG - Fork off a background process.
565 * FORK_NOJOB - Like FORK_FG, but don't give the process its own
566 * process group even if job control is on.
567 *
568 * When job control is turned off, background processes have their standard
569 * input redirected to /dev/null (except for the second and later processes
570 * in a pipeline).
571 */
572
573 int
574 forkshell(jp, n, mode)
575 union node *n;
576 struct job *jp;
577 int mode;
578 {
579 int pid;
580
581 TRACE(("forkshell(%%%d, %p, %d) called\n", jp - jobtab, n, mode));
582 INTOFF;
583 switch ((pid = fork())) {
584 case -1:
585 TRACE(("Fork failed, errno=%d\n", errno));
586 INTON;
587 error("Cannot fork");
588 break;
589 case 0:
590 forkchild(jp, n, mode, 0);
591 return 0;
592 default:
593 return forkparent(jp, n, mode, pid);
594 }
595 }
596
597 int
598 forkparent(jp, n, mode, pid)
599 union node *n;
600 struct job *jp;
601 int mode;
602 pid_t pid;
603 {
604 int pgrp;
605
606 if (rootshell && mode != FORK_NOJOB && mflag) {
607 if (jp == NULL || jp->nprocs == 0)
608 pgrp = pid;
609 else
610 pgrp = jp->ps[0].pid;
611 setpgid(pid, pgrp);
612 }
613 if (mode == FORK_BG)
614 backgndpid = pid; /* set $! */
615 if (jp) {
616 struct procstat *ps = &jp->ps[jp->nprocs++];
617 ps->pid = pid;
618 ps->status = -1;
619 ps->cmd = nullstr;
620 if (iflag && rootshell && n)
621 ps->cmd = commandtext(n);
622 }
623 INTON;
624 TRACE(("In parent shell: child = %d\n", pid));
625 return pid;
626 }
627
628 void
629 forkchild(jp, n, mode, vforked)
630 union node *n;
631 struct job *jp;
632 int mode;
633 int vforked;
634 {
635 struct job *p;
636 int wasroot;
637 int i;
638 int pgrp;
639 const char *devnull = _PATH_DEVNULL;
640 const char *nullerr = "Can't open %s";
641
642 TRACE(("Child shell %d\n", getpid()));
643 wasroot = rootshell;
644 if (!vforked) {
645 rootshell = 0;
646 for (i = njobs, p = jobtab ; --i >= 0 ; p++)
647 if (p->used)
648 freejob(p);
649 }
650 closescript(vforked);
651 if (!vforked) {
652 INTON;
653 }
654 clear_traps(vforked);
655 #if JOBS
656 if (!vforked)
657 jobctl = 0; /* do job control only in root shell */
658 if (wasroot && mode != FORK_NOJOB && mflag) {
659 if (jp == NULL || jp->nprocs == 0)
660 pgrp = getpid();
661 else
662 pgrp = jp->ps[0].pid;
663 setpgid(0, pgrp);
664 if (mode == FORK_FG) {
665 /*** this causes superfluous TIOCSPGRPS ***/
666 #ifdef OLD_TTY_DRIVER
667 if (ioctl(2, TIOCSPGRP, (char *)&pgrp) < 0)
668 error("TIOCSPGRP failed, errno=%d", errno);
669 #else
670 if (tcsetpgrp(2, pgrp) < 0)
671 error("tcsetpgrp failed, errno=%d", errno);
672 #endif
673 }
674 setsignal(SIGTSTP, vforked);
675 setsignal(SIGTTOU, vforked);
676 } else if (mode == FORK_BG) {
677 ignoresig(SIGINT, vforked);
678 ignoresig(SIGQUIT, vforked);
679 if ((jp == NULL || jp->nprocs == 0) &&
680 ! fd0_redirected_p ()) {
681 close(0);
682 if (open(devnull, O_RDONLY) != 0)
683 error(nullerr, devnull);
684 }
685 }
686 #else
687 if (mode == FORK_BG) {
688 ignoresig(SIGINT, vforked);
689 ignoresig(SIGQUIT, vforked);
690 if ((jp == NULL || jp->nprocs == 0) &&
691 ! fd0_redirected_p ()) {
692 close(0);
693 if (open(devnull, O_RDONLY) != 0)
694 error(nullerr, devnull);
695 }
696 }
697 #endif
698 if (wasroot && iflag) {
699 setsignal(SIGINT, vforked);
700 setsignal(SIGQUIT, vforked);
701 setsignal(SIGTERM, vforked);
702 }
703 }
704
705
706
707 /*
708 * Wait for job to finish.
709 *
710 * Under job control we have the problem that while a child process is
711 * running interrupts generated by the user are sent to the child but not
712 * to the shell. This means that an infinite loop started by an inter-
713 * active user may be hard to kill. With job control turned off, an
714 * interactive user may place an interactive program inside a loop. If
715 * the interactive program catches interrupts, the user doesn't want
716 * these interrupts to also abort the loop. The approach we take here
717 * is to have the shell ignore interrupt signals while waiting for a
718 * forground process to terminate, and then send itself an interrupt
719 * signal if the child process was terminated by an interrupt signal.
720 * Unfortunately, some programs want to do a bit of cleanup and then
721 * exit on interrupt; unless these processes terminate themselves by
722 * sending a signal to themselves (instead of calling exit) they will
723 * confuse this approach.
724 */
725
726 int
727 waitforjob(jp)
728 struct job *jp;
729 {
730 #if JOBS
731 int mypgrp = getpgrp();
732 #endif
733 int status;
734 int st;
735
736 INTOFF;
737 TRACE(("waitforjob(%%%d) called\n", jp - jobtab + 1));
738 while (jp->state == 0) {
739 dowait(1, jp);
740 }
741 #if JOBS
742 if (jp->jobctl) {
743 #ifdef OLD_TTY_DRIVER
744 if (ioctl(2, TIOCSPGRP, (char *)&mypgrp) < 0)
745 error("TIOCSPGRP failed, errno=%d\n", errno);
746 #else
747 if (tcsetpgrp(2, mypgrp) < 0)
748 error("tcsetpgrp failed, errno=%d\n", errno);
749 #endif
750 }
751 if (jp->state == JOBSTOPPED)
752 curjob = jp - jobtab + 1;
753 #endif
754 status = jp->ps[jp->nprocs - 1].status;
755 /* convert to 8 bits */
756 if (WIFEXITED(status))
757 st = WEXITSTATUS(status);
758 #if JOBS
759 else if (WIFSTOPPED(status))
760 st = WSTOPSIG(status) + 128;
761 #endif
762 else
763 st = WTERMSIG(status) + 128;
764 #if JOBS
765 if (jp->jobctl) {
766 /*
767 * This is truly gross.
768 * If we're doing job control, then we did a TIOCSPGRP which
769 * caused us (the shell) to no longer be in the controlling
770 * session -- so we wouldn't have seen any ^C/SIGINT. So, we
771 * intuit from the subprocess exit status whether a SIGINT
772 * occurred, and if so interrupt ourselves. Yuck. - mycroft
773 */
774 if (WIFSIGNALED(status) && WTERMSIG(status) == SIGINT)
775 raise(SIGINT);
776 }
777 #endif
778 if (! JOBS || jp->state == JOBDONE)
779 freejob(jp);
780 INTON;
781 return st;
782 }
783
784
785
786 /*
787 * Wait for a process to terminate.
788 */
789
790 STATIC int
791 dowait(block, job)
792 int block;
793 struct job *job;
794 {
795 int pid;
796 int status;
797 struct procstat *sp;
798 struct job *jp;
799 struct job *thisjob;
800 int done;
801 int stopped;
802 int core;
803 int sig;
804 extern volatile char gotsig[];
805
806 TRACE(("dowait(%d) called\n", block));
807 do {
808 pid = waitproc(block, job, &status);
809 TRACE(("wait returns %d, status=%d\n", pid, status));
810 } while (pid == -1 && errno == EINTR && gotsig[SIGINT - 1] == 0);
811 if (pid <= 0)
812 return pid;
813 INTOFF;
814 thisjob = NULL;
815 for (jp = jobtab ; jp < jobtab + njobs ; jp++) {
816 if (jp->used) {
817 done = 1;
818 stopped = 1;
819 for (sp = jp->ps ; sp < jp->ps + jp->nprocs ; sp++) {
820 if (sp->pid == -1)
821 continue;
822 if (sp->pid == pid) {
823 TRACE(("Changing status of proc %d from 0x%x to 0x%x\n", pid, sp->status, status));
824 sp->status = status;
825 thisjob = jp;
826 }
827 if (sp->status == -1)
828 stopped = 0;
829 else if (WIFSTOPPED(sp->status))
830 done = 0;
831 }
832 if (stopped) { /* stopped or done */
833 int state = done? JOBDONE : JOBSTOPPED;
834 if (jp->state != state) {
835 TRACE(("Job %d: changing state from %d to %d\n", jp - jobtab + 1, jp->state, state));
836 jp->state = state;
837 #if JOBS
838 if (done && curjob == jp - jobtab + 1)
839 curjob = 0; /* no current job */
840 #endif
841 }
842 }
843 }
844 }
845 INTON;
846 if (! rootshell || ! iflag || (job && thisjob == job)) {
847 core = WCOREDUMP(status);
848 #if JOBS
849 if (WIFSTOPPED(status)) sig = WSTOPSIG(status);
850 else
851 #endif
852 if (WIFEXITED(status)) sig = 0;
853 else sig = WTERMSIG(status);
854
855 if (sig != 0 && sig != SIGINT && sig != SIGPIPE) {
856 if (thisjob != job)
857 outfmt(out2, "%d: ", pid);
858 #if JOBS
859 if (sig == SIGTSTP && rootshell && iflag)
860 outfmt(out2, "%%%ld ",
861 (long)(job - jobtab + 1));
862 #endif
863 if (sig < NSIG && sys_siglist[sig])
864 out2str(sys_siglist[sig]);
865 else
866 outfmt(out2, "Signal %d", sig);
867 if (core)
868 out2str(" - core dumped");
869 out2c('\n');
870 flushout(&errout);
871 } else {
872 TRACE(("Not printing status: status=%d, sig=%d\n",
873 status, sig));
874 }
875 } else {
876 TRACE(("Not printing status, rootshell=%d, job=0x%x\n", rootshell, job));
877 if (thisjob)
878 thisjob->changed = 1;
879 }
880 return pid;
881 }
882
883
884
885 /*
886 * Do a wait system call. If job control is compiled in, we accept
887 * stopped processes. If block is zero, we return a value of zero
888 * rather than blocking.
889 *
890 * System V doesn't have a non-blocking wait system call. It does
891 * have a SIGCLD signal that is sent to a process when one of it's
892 * children dies. The obvious way to use SIGCLD would be to install
893 * a handler for SIGCLD which simply bumped a counter when a SIGCLD
894 * was received, and have waitproc bump another counter when it got
895 * the status of a process. Waitproc would then know that a wait
896 * system call would not block if the two counters were different.
897 * This approach doesn't work because if a process has children that
898 * have not been waited for, System V will send it a SIGCLD when it
899 * installs a signal handler for SIGCLD. What this means is that when
900 * a child exits, the shell will be sent SIGCLD signals continuously
901 * until is runs out of stack space, unless it does a wait call before
902 * restoring the signal handler. The code below takes advantage of
903 * this (mis)feature by installing a signal handler for SIGCLD and
904 * then checking to see whether it was called. If there are any
905 * children to be waited for, it will be.
906 *
907 * If neither SYSV nor BSD is defined, we don't implement nonblocking
908 * waits at all. In this case, the user will not be informed when
909 * a background process until the next time she runs a real program
910 * (as opposed to running a builtin command or just typing return),
911 * and the jobs command may give out of date information.
912 */
913
914 #ifdef SYSV
915 STATIC int gotsigchild;
916
917 STATIC int onsigchild() {
918 gotsigchild = 1;
919 }
920 #endif
921
922
923 STATIC int
924 waitproc(block, jp, status)
925 int block;
926 struct job *jp;
927 int *status;
928 {
929 #ifdef BSD
930 int flags = 0;
931
932 #if JOBS
933 if (jp != NULL && jp->jobctl)
934 flags |= WUNTRACED;
935 #endif
936 if (block == 0)
937 flags |= WNOHANG;
938 return wait3(status, flags, (struct rusage *)NULL);
939 #else
940 #ifdef SYSV
941 int (*save)();
942
943 if (block == 0) {
944 gotsigchild = 0;
945 save = signal(SIGCLD, onsigchild);
946 signal(SIGCLD, save);
947 if (gotsigchild == 0)
948 return 0;
949 }
950 return wait(status);
951 #else
952 if (block == 0)
953 return 0;
954 return wait(status);
955 #endif
956 #endif
957 }
958
959 /*
960 * return 1 if there are stopped jobs, otherwise 0
961 */
962 int job_warning = 0;
963 int
964 stoppedjobs()
965 {
966 int jobno;
967 struct job *jp;
968
969 if (job_warning)
970 return (0);
971 for (jobno = 1, jp = jobtab; jobno <= njobs; jobno++, jp++) {
972 if (jp->used == 0)
973 continue;
974 if (jp->state == JOBSTOPPED) {
975 out2str("You have stopped jobs.\n");
976 job_warning = 2;
977 return (1);
978 }
979 }
980
981 return (0);
982 }
983
984 /*
985 * Return a string identifying a command (to be printed by the
986 * jobs command.
987 */
988
989 STATIC char *cmdnextc;
990 STATIC int cmdnleft;
991 #define MAXCMDTEXT 200
992
993 char *
994 commandtext(n)
995 union node *n;
996 {
997 char *name;
998
999 cmdnextc = name = ckmalloc(MAXCMDTEXT);
1000 cmdnleft = MAXCMDTEXT - 4;
1001 cmdtxt(n);
1002 *cmdnextc = '\0';
1003 return name;
1004 }
1005
1006
1007 STATIC void
1008 cmdtxt(n)
1009 union node *n;
1010 {
1011 union node *np;
1012 struct nodelist *lp;
1013 const char *p;
1014 int i;
1015 char s[2];
1016
1017 if (n == NULL)
1018 return;
1019 switch (n->type) {
1020 case NSEMI:
1021 cmdtxt(n->nbinary.ch1);
1022 cmdputs("; ");
1023 cmdtxt(n->nbinary.ch2);
1024 break;
1025 case NAND:
1026 cmdtxt(n->nbinary.ch1);
1027 cmdputs(" && ");
1028 cmdtxt(n->nbinary.ch2);
1029 break;
1030 case NOR:
1031 cmdtxt(n->nbinary.ch1);
1032 cmdputs(" || ");
1033 cmdtxt(n->nbinary.ch2);
1034 break;
1035 case NPIPE:
1036 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
1037 cmdtxt(lp->n);
1038 if (lp->next)
1039 cmdputs(" | ");
1040 }
1041 break;
1042 case NSUBSHELL:
1043 cmdputs("(");
1044 cmdtxt(n->nredir.n);
1045 cmdputs(")");
1046 break;
1047 case NREDIR:
1048 case NBACKGND:
1049 cmdtxt(n->nredir.n);
1050 break;
1051 case NIF:
1052 cmdputs("if ");
1053 cmdtxt(n->nif.test);
1054 cmdputs("; then ");
1055 cmdtxt(n->nif.ifpart);
1056 cmdputs("...");
1057 break;
1058 case NWHILE:
1059 cmdputs("while ");
1060 goto until;
1061 case NUNTIL:
1062 cmdputs("until ");
1063 until:
1064 cmdtxt(n->nbinary.ch1);
1065 cmdputs("; do ");
1066 cmdtxt(n->nbinary.ch2);
1067 cmdputs("; done");
1068 break;
1069 case NFOR:
1070 cmdputs("for ");
1071 cmdputs(n->nfor.var);
1072 cmdputs(" in ...");
1073 break;
1074 case NCASE:
1075 cmdputs("case ");
1076 cmdputs(n->ncase.expr->narg.text);
1077 cmdputs(" in ...");
1078 break;
1079 case NDEFUN:
1080 cmdputs(n->narg.text);
1081 cmdputs("() ...");
1082 break;
1083 case NCMD:
1084 for (np = n->ncmd.args ; np ; np = np->narg.next) {
1085 cmdtxt(np);
1086 if (np->narg.next)
1087 cmdputs(" ");
1088 }
1089 for (np = n->ncmd.redirect ; np ; np = np->nfile.next) {
1090 cmdputs(" ");
1091 cmdtxt(np);
1092 }
1093 break;
1094 case NARG:
1095 cmdputs(n->narg.text);
1096 break;
1097 case NTO:
1098 p = ">"; i = 1; goto redir;
1099 case NAPPEND:
1100 p = ">>"; i = 1; goto redir;
1101 case NTOFD:
1102 p = ">&"; i = 1; goto redir;
1103 case NFROM:
1104 p = "<"; i = 0; goto redir;
1105 case NFROMFD:
1106 p = "<&"; i = 0; goto redir;
1107 case NFROMTO:
1108 p = "<>"; i = 0; goto redir;
1109 redir:
1110 if (n->nfile.fd != i) {
1111 s[0] = n->nfile.fd + '0';
1112 s[1] = '\0';
1113 cmdputs(s);
1114 }
1115 cmdputs(p);
1116 if (n->type == NTOFD || n->type == NFROMFD) {
1117 s[0] = n->ndup.dupfd + '0';
1118 s[1] = '\0';
1119 cmdputs(s);
1120 } else {
1121 cmdtxt(n->nfile.fname);
1122 }
1123 break;
1124 case NHERE:
1125 case NXHERE:
1126 cmdputs("<<...");
1127 break;
1128 default:
1129 cmdputs("???");
1130 break;
1131 }
1132 }
1133
1134
1135
1136 STATIC void
1137 cmdputs(s)
1138 const char *s;
1139 {
1140 const char *p;
1141 char *q;
1142 char c;
1143 int subtype = 0;
1144
1145 if (cmdnleft <= 0)
1146 return;
1147 p = s;
1148 q = cmdnextc;
1149 while ((c = *p++) != '\0') {
1150 if (c == CTLESC)
1151 *q++ = *p++;
1152 else if (c == CTLVAR) {
1153 *q++ = '$';
1154 if (--cmdnleft > 0)
1155 *q++ = '{';
1156 subtype = *p++;
1157 } else if (c == '=' && subtype != 0) {
1158 *q++ = "}-+?="[(subtype & VSTYPE) - VSNORMAL];
1159 subtype = 0;
1160 } else if (c == CTLENDVAR) {
1161 *q++ = '}';
1162 } else if (c == CTLBACKQ || c == CTLBACKQ+CTLQUOTE)
1163 cmdnleft++; /* ignore it */
1164 else
1165 *q++ = c;
1166 if (--cmdnleft <= 0) {
1167 *q++ = '.';
1168 *q++ = '.';
1169 *q++ = '.';
1170 break;
1171 }
1172 }
1173 cmdnextc = q;
1174 }
1175