Magellan Linux

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 532 - (show annotations) (download)
Sat Sep 1 22:45:15 2007 UTC (16 years, 8 months ago) by niro
File MIME type: text/plain
File size: 29099 byte(s)
-import if magellan mkinitrd; it is a fork of redhats mkinitrd-5.0.8 with all magellan patches and features; deprecates magellan-src/mkinitrd

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