Magellan Linux

Contents of /trunk/mkinitrd-magellan/klibc/usr/dash/jobs.c

Parent Directory Parent Directory | Revision Log Revision Log


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