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