Magellan Linux

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 815 - (hide 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 niro 532 /*-
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 niro 815 fd = open(_PATH_TTY, O_RDWR);
192 niro 532 if (fd < 0) {
193     fd += 3;
194 niro 815 while (!isatty(fd))
195     if (--fd < 0)
196     goto out;
197 niro 532 }
198 niro 815 fd = savefd(fd);
199 niro 532 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     }