|
|
1.1 root 1: /*
2: * Copyright (c) 1980 Regents of the University of California.
3: * All rights reserved. The Berkeley Software License Agreement
4: * specifies the terms and conditions for redistribution.
5: */
6:
7: #ifndef lint
8: static char *sccsid = "@(#)sh.proc.c 5.10 (Berkeley) 5/19/88";
9: #endif
10:
11: #include "sh.h"
12: #include "sh.dir.h"
13: #include "sh.proc.h"
14: #include <sys/wait.h>
15: #include <sys/ioctl.h>
16:
17: /*
18: * C Shell - functions that manage processes, handling hanging, termination
19: */
20:
21: #define BIGINDEX 9 /* largest desirable job index */
22:
23: /*
24: * pchild - called at interrupt level by the SIGCHLD signal
25: * indicating that at least one child has terminated or stopped
26: * thus at least one wait system call will definitely return a
27: * childs status. Top level routines (like pwait) must be sure
28: * to mask interrupts when playing with the proclist data structures!
29: */
30: pchild()
31: {
32: register struct process *pp;
33: register struct process *fp;
34: register int pid;
35: union wait w;
36: int jobflags;
37: struct rusage ru;
38: extern int insource;
39:
40: loop:
41: pid = wait3(&w, (setintr && (intty || insource) ? WNOHANG|WUNTRACED:WNOHANG), &ru);
42: if (pid <= 0) {
43: if (errno == EINTR) {
44: errno = 0;
45: goto loop;
46: }
47: pnoprocesses = pid == -1;
48: return;
49: }
50: for (pp = proclist.p_next; pp != PNULL; pp = pp->p_next)
51: if (pid == pp->p_pid)
52: goto found;
53: goto loop;
54: found:
55: if (pid == atoi(value("child")))
56: unsetv("child");
57: pp->p_flags &= ~(PRUNNING|PSTOPPED|PREPORTED);
58: if (WIFSTOPPED(w)) {
59: pp->p_flags |= PSTOPPED;
60: pp->p_reason = w.w_stopsig;
61: } else {
62: if (pp->p_flags & (PTIME|PPTIME) || adrof("time"))
63: (void) gettimeofday(&pp->p_etime, (struct timezone *)0);
64: pp->p_rusage = ru;
65: if (WIFSIGNALED(w)) {
66: if (w.w_termsig == SIGINT)
67: pp->p_flags |= PINTERRUPTED;
68: else
69: pp->p_flags |= PSIGNALED;
70: if (w.w_coredump)
71: pp->p_flags |= PDUMPED;
72: pp->p_reason = w.w_termsig;
73: } else {
74: pp->p_reason = w.w_retcode;
75: if (pp->p_reason != 0)
76: pp->p_flags |= PAEXITED;
77: else
78: pp->p_flags |= PNEXITED;
79: }
80: }
81: jobflags = 0;
82: fp = pp;
83: do {
84: if ((fp->p_flags & (PPTIME|PRUNNING|PSTOPPED)) == 0 &&
85: !child && adrof("time") &&
86: fp->p_rusage.ru_utime.tv_sec+fp->p_rusage.ru_stime.tv_sec >=
87: atoi(value("time")))
88: fp->p_flags |= PTIME;
89: jobflags |= fp->p_flags;
90: } while ((fp = fp->p_friends) != pp);
91: pp->p_flags &= ~PFOREGND;
92: if (pp == pp->p_friends && (pp->p_flags & PPTIME)) {
93: pp->p_flags &= ~PPTIME;
94: pp->p_flags |= PTIME;
95: }
96: if ((jobflags & (PRUNNING|PREPORTED)) == 0) {
97: fp = pp;
98: do {
99: if (fp->p_flags&PSTOPPED)
100: fp->p_flags |= PREPORTED;
101: } while((fp = fp->p_friends) != pp);
102: while(fp->p_pid != fp->p_jobid)
103: fp = fp->p_friends;
104: if (jobflags&PSTOPPED) {
105: if (pcurrent && pcurrent != fp)
106: pprevious = pcurrent;
107: pcurrent = fp;
108: } else
109: pclrcurr(fp);
110: if (jobflags&PFOREGND) {
111: if (jobflags & (PSIGNALED|PSTOPPED|PPTIME) ||
112: #ifdef IIASA
113: jobflags & PAEXITED ||
114: #endif
115: !eq(dcwd->di_name, fp->p_cwd->di_name)) {
116: ; /* print in pjwait */
117: }
118: /*
119: else if ((jobflags & (PTIME|PSTOPPED)) == PTIME)
120: ptprint(fp);
121: */
122: } else {
123: if (jobflags&PNOTIFY || adrof("notify")) {
124: printf("\215\n");
125: (void) pprint(pp, NUMBER|NAME|REASON);
126: if ((jobflags&PSTOPPED) == 0)
127: pflush(pp);
128: } else {
129: fp->p_flags |= PNEEDNOTE;
130: neednote++;
131: }
132: }
133: }
134: goto loop;
135: }
136:
137: pnote()
138: {
139: register struct process *pp;
140: int flags;
141: long omask;
142:
143: neednote = 0;
144: for (pp = proclist.p_next; pp != PNULL; pp = pp->p_next) {
145: if (pp->p_flags & PNEEDNOTE) {
146: omask = sigblock(sigmask(SIGCHLD));
147: pp->p_flags &= ~PNEEDNOTE;
148: flags = pprint(pp, NUMBER|NAME|REASON);
149: if ((flags&(PRUNNING|PSTOPPED)) == 0)
150: pflush(pp);
151: (void) sigsetmask(omask);
152: }
153: }
154: }
155:
156: /*
157: * pwait - wait for current job to terminate, maintaining integrity
158: * of current and previous job indicators.
159: */
160: pwait()
161: {
162: register struct process *fp, *pp;
163: long omask;
164:
165: /*
166: * Here's where dead procs get flushed.
167: */
168: omask = sigblock(sigmask(SIGCHLD));
169: for (pp = (fp = &proclist)->p_next; pp != PNULL; pp = (fp = pp)->p_next)
170: if (pp->p_pid == 0) {
171: fp->p_next = pp->p_next;
172: xfree(pp->p_command);
173: if (pp->p_cwd && --pp->p_cwd->di_count == 0)
174: if (pp->p_cwd->di_next == 0)
175: dfree(pp->p_cwd);
176: xfree((char *)pp);
177: pp = fp;
178: }
179: (void) sigsetmask(omask);
180: pjwait(pcurrjob);
181: }
182:
183: /*
184: * pjwait - wait for a job to finish or become stopped
185: * It is assumed to be in the foreground state (PFOREGND)
186: */
187: pjwait(pp)
188: register struct process *pp;
189: {
190: register struct process *fp;
191: int jobflags, reason;
192: long omask;
193:
194: while (pp->p_pid != pp->p_jobid)
195: pp = pp->p_friends;
196: fp = pp;
197: do {
198: if ((fp->p_flags&(PFOREGND|PRUNNING)) == PRUNNING)
199: printf("BUG: waiting for background job!\n");
200: } while ((fp = fp->p_friends) != pp);
201: /*
202: * Now keep pausing as long as we are not interrupted (SIGINT),
203: * and the target process, or any of its friends, are running
204: */
205: fp = pp;
206: omask = sigblock(sigmask(SIGCHLD));
207: for (;;) {
208: jobflags = 0;
209: do
210: jobflags |= fp->p_flags;
211: while ((fp = (fp->p_friends)) != pp);
212: if ((jobflags & PRUNNING) == 0)
213: break;
214: sigpause(sigblock(0L) &~ sigmask(SIGCHLD));
215: }
216: (void) sigsetmask(omask);
217: if (tpgrp > 0) /* get tty back */
218: (void) ioctl(FSHTTY, TIOCSPGRP, (char *)&tpgrp);
219: if ((jobflags&(PSIGNALED|PSTOPPED|PTIME)) ||
220: !eq(dcwd->di_name, fp->p_cwd->di_name)) {
221: if (jobflags&PSTOPPED)
222: printf("\n");
223: (void) pprint(pp, AREASON|SHELLDIR);
224: }
225: if ((jobflags&(PINTERRUPTED|PSTOPPED)) && setintr &&
226: (!gointr || !eq(gointr, "-"))) {
227: if ((jobflags & PSTOPPED) == 0)
228: pflush(pp);
229: pintr1(0);
230: /*NOTREACHED*/
231: }
232: reason = 0;
233: fp = pp;
234: do {
235: if (fp->p_reason)
236: reason = fp->p_flags & (PSIGNALED|PINTERRUPTED) ?
237: fp->p_reason | QUOTE : fp->p_reason;
238: } while ((fp = fp->p_friends) != pp);
239: set("status", putn(reason));
240: if (reason && exiterr)
241: exitstat();
242: pflush(pp);
243: }
244:
245: /*
246: * dowait - wait for all processes to finish
247: */
248: dowait()
249: {
250: register struct process *pp;
251: long omask;
252:
253: pjobs++;
254: omask = sigblock(sigmask(SIGCHLD));
255: loop:
256: for (pp = proclist.p_next; pp; pp = pp->p_next)
257: if (pp->p_pid && /* pp->p_pid == pp->p_jobid && */
258: pp->p_flags&PRUNNING) {
259: sigpause(0L);
260: goto loop;
261: }
262: (void) sigsetmask(omask);
263: pjobs = 0;
264: }
265:
266: /*
267: * pflushall - flush all jobs from list (e.g. at fork())
268: */
269: pflushall()
270: {
271: register struct process *pp;
272:
273: for (pp = proclist.p_next; pp != PNULL; pp = pp->p_next)
274: if (pp->p_pid)
275: pflush(pp);
276: }
277:
278: /*
279: * pflush - flag all process structures in the same job as the
280: * the argument process for deletion. The actual free of the
281: * space is not done here since pflush is called at interrupt level.
282: */
283: pflush(pp)
284: register struct process *pp;
285: {
286: register struct process *np;
287: register int index;
288:
289: if (pp->p_pid == 0) {
290: printf("BUG: process flushed twice");
291: return;
292: }
293: while (pp->p_pid != pp->p_jobid)
294: pp = pp->p_friends;
295: pclrcurr(pp);
296: if (pp == pcurrjob)
297: pcurrjob = 0;
298: index = pp->p_index;
299: np = pp;
300: do {
301: np->p_index = np->p_pid = 0;
302: np->p_flags &= ~PNEEDNOTE;
303: } while ((np = np->p_friends) != pp);
304: if (index == pmaxindex) {
305: for (np = proclist.p_next, index = 0; np; np = np->p_next)
306: if (np->p_index > index)
307: index = np->p_index;
308: pmaxindex = index;
309: }
310: }
311:
312: /*
313: * pclrcurr - make sure the given job is not the current or previous job;
314: * pp MUST be the job leader
315: */
316: pclrcurr(pp)
317: register struct process *pp;
318: {
319:
320: if (pp == pcurrent)
321: if (pprevious != PNULL) {
322: pcurrent = pprevious;
323: pprevious = pgetcurr(pp);
324: } else {
325: pcurrent = pgetcurr(pp);
326: pprevious = pgetcurr(pp);
327: }
328: else if (pp == pprevious)
329: pprevious = pgetcurr(pp);
330: }
331:
332: /* +4 here is 1 for '\0', 1 ea for << >& >> */
333: char command[PMAXLEN+4];
334: int cmdlen;
335: char *cmdp;
336: /*
337: * palloc - allocate a process structure and fill it up.
338: * an important assumption is made that the process is running.
339: */
340: palloc(pid, t)
341: int pid;
342: register struct command *t;
343: {
344: register struct process *pp;
345: int i;
346:
347: pp = (struct process *)calloc(1, sizeof(struct process));
348: pp->p_pid = pid;
349: pp->p_flags = t->t_dflg & FAND ? PRUNNING : PRUNNING|PFOREGND;
350: if (t->t_dflg & FTIME)
351: pp->p_flags |= PPTIME;
352: cmdp = command;
353: cmdlen = 0;
354: padd(t);
355: *cmdp++ = 0;
356: if (t->t_dflg & FPOU) {
357: pp->p_flags |= PPOU;
358: if (t->t_dflg & FDIAG)
359: pp->p_flags |= PDIAG;
360: }
361: pp->p_command = savestr(command);
362: if (pcurrjob) {
363: struct process *fp;
364: /* careful here with interrupt level */
365: pp->p_cwd = 0;
366: pp->p_index = pcurrjob->p_index;
367: pp->p_friends = pcurrjob;
368: pp->p_jobid = pcurrjob->p_pid;
369: for (fp = pcurrjob; fp->p_friends != pcurrjob; fp = fp->p_friends)
370: ;
371: fp->p_friends = pp;
372: } else {
373: pcurrjob = pp;
374: pp->p_jobid = pid;
375: pp->p_friends = pp;
376: pp->p_cwd = dcwd;
377: dcwd->di_count++;
378: if (pmaxindex < BIGINDEX)
379: pp->p_index = ++pmaxindex;
380: else {
381: struct process *np;
382:
383: for (i = 1; ; i++) {
384: for (np = proclist.p_next; np; np = np->p_next)
385: if (np->p_index == i)
386: goto tryagain;
387: pp->p_index = i;
388: if (i > pmaxindex)
389: pmaxindex = i;
390: break;
391: tryagain:;
392: }
393: }
394: if (pcurrent == PNULL)
395: pcurrent = pp;
396: else if (pprevious == PNULL)
397: pprevious = pp;
398: }
399: pp->p_next = proclist.p_next;
400: proclist.p_next = pp;
401: (void) gettimeofday(&pp->p_btime, (struct timezone *)0);
402: }
403:
404: padd(t)
405: register struct command *t;
406: {
407: char **argp;
408:
409: if (t == 0)
410: return;
411: switch (t->t_dtyp) {
412:
413: case TPAR:
414: pads("( ");
415: padd(t->t_dspr);
416: pads(" )");
417: break;
418:
419: case TCOM:
420: for (argp = t->t_dcom; *argp; argp++) {
421: pads(*argp);
422: if (argp[1])
423: pads(" ");
424: }
425: break;
426:
427: case TOR:
428: case TAND:
429: case TFIL:
430: case TLST:
431: padd(t->t_dcar);
432: switch (t->t_dtyp) {
433: case TOR:
434: pads(" || ");
435: break;
436: case TAND:
437: pads(" && ");
438: break;
439: case TFIL:
440: pads(" | ");
441: break;
442: case TLST:
443: pads("; ");
444: break;
445: }
446: padd(t->t_dcdr);
447: return;
448: }
449: if ((t->t_dflg & FPIN) == 0 && t->t_dlef) {
450: pads((t->t_dflg & FHERE) ? " << " : " < ");
451: pads(t->t_dlef);
452: }
453: if ((t->t_dflg & FPOU) == 0 && t->t_drit) {
454: pads((t->t_dflg & FCAT) ? " >>" : " >");
455: if (t->t_dflg & FDIAG)
456: pads("&");
457: pads(" ");
458: pads(t->t_drit);
459: }
460: }
461:
462: pads(cp)
463: char *cp;
464: {
465: register int i = strlen(cp);
466:
467: if (cmdlen >= PMAXLEN)
468: return;
469: if (cmdlen + i >= PMAXLEN) {
470: (void) strcpy(cmdp, " ...");
471: cmdlen = PMAXLEN;
472: cmdp += 4;
473: return;
474: }
475: (void) strcpy(cmdp, cp);
476: cmdp += i;
477: cmdlen += i;
478: }
479:
480: /*
481: * psavejob - temporarily save the current job on a one level stack
482: * so another job can be created. Used for { } in exp6
483: * and `` in globbing.
484: */
485: psavejob()
486: {
487:
488: pholdjob = pcurrjob;
489: pcurrjob = PNULL;
490: }
491:
492: /*
493: * prestjob - opposite of psavejob. This may be missed if we are interrupted
494: * somewhere, but pendjob cleans up anyway.
495: */
496: prestjob()
497: {
498:
499: pcurrjob = pholdjob;
500: pholdjob = PNULL;
501: }
502:
503: /*
504: * pendjob - indicate that a job (set of commands) has been completed
505: * or is about to begin.
506: */
507: pendjob()
508: {
509: register struct process *pp, *tp;
510:
511: if (pcurrjob && (pcurrjob->p_flags&(PFOREGND|PSTOPPED)) == 0) {
512: pp = pcurrjob;
513: while (pp->p_pid != pp->p_jobid)
514: pp = pp->p_friends;
515: printf("[%d]", pp->p_index);
516: tp = pp;
517: do {
518: printf(" %d", pp->p_pid);
519: pp = pp->p_friends;
520: } while (pp != tp);
521: printf("\n");
522: }
523: pholdjob = pcurrjob = 0;
524: }
525:
526: /*
527: * pprint - print a job
528: */
529: pprint(pp, flag)
530: register struct process *pp;
531: {
532: register status, reason;
533: struct process *tp;
534: extern char *linp, linbuf[];
535: int jobflags, pstatus;
536: char *format;
537:
538: while (pp->p_pid != pp->p_jobid)
539: pp = pp->p_friends;
540: if (pp == pp->p_friends && (pp->p_flags & PPTIME)) {
541: pp->p_flags &= ~PPTIME;
542: pp->p_flags |= PTIME;
543: }
544: tp = pp;
545: status = reason = -1;
546: jobflags = 0;
547: do {
548: jobflags |= pp->p_flags;
549: pstatus = pp->p_flags & PALLSTATES;
550: if (tp != pp && linp != linbuf && !(flag&FANCY) &&
551: (pstatus == status && pp->p_reason == reason ||
552: !(flag&REASON)))
553: printf(" ");
554: else {
555: if (tp != pp && linp != linbuf)
556: printf("\n");
557: if(flag&NUMBER)
558: if (pp == tp)
559: printf("[%d]%s %c ", pp->p_index,
560: pp->p_index < 10 ? " " : "",
561: pp==pcurrent ? '+' :
562: (pp == pprevious ? '-' : ' '));
563: else
564: printf(" ");
565: if (flag&FANCY)
566: printf("%5d ", pp->p_pid);
567: if (flag&(REASON|AREASON)) {
568: if (flag&NAME)
569: format = "%-23s";
570: else
571: format = "%s";
572: if (pstatus == status)
573: if (pp->p_reason == reason) {
574: printf(format, "");
575: goto prcomd;
576: } else
577: reason = pp->p_reason;
578: else {
579: status = pstatus;
580: reason = pp->p_reason;
581: }
582: switch (status) {
583:
584: case PRUNNING:
585: printf(format, "Running ");
586: break;
587:
588: case PINTERRUPTED:
589: case PSTOPPED:
590: case PSIGNALED:
591: if ((flag&(REASON|AREASON))
592: && reason != SIGINT
593: && reason != SIGPIPE)
594: printf(format, mesg[pp->p_reason].pname);
595: break;
596:
597: case PNEXITED:
598: case PAEXITED:
599: if (flag & REASON)
600: if (pp->p_reason)
601: printf("Exit %-16d", pp->p_reason);
602: else
603: printf(format, "Done");
604: break;
605:
606: default:
607: printf("BUG: status=%-9o", status);
608: }
609: }
610: }
611: prcomd:
612: if (flag&NAME) {
613: printf("%s", pp->p_command);
614: if (pp->p_flags & PPOU)
615: printf(" |");
616: if (pp->p_flags & PDIAG)
617: printf("&");
618: }
619: if (flag&(REASON|AREASON) && pp->p_flags&PDUMPED)
620: printf(" (core dumped)");
621: if (tp == pp->p_friends) {
622: if (flag&ERSAND)
623: printf(" &");
624: if (flag&JOBDIR &&
625: !eq(tp->p_cwd->di_name, dcwd->di_name)) {
626: printf(" (wd: ");
627: dtildepr(value("home"), tp->p_cwd->di_name);
628: printf(")");
629: }
630: }
631: if (pp->p_flags&PPTIME && !(status&(PSTOPPED|PRUNNING))) {
632: if (linp != linbuf)
633: printf("\n\t");
634: { static struct rusage zru;
635: prusage(&zru, &pp->p_rusage, &pp->p_etime,
636: &pp->p_btime);
637: }
638: }
639: if (tp == pp->p_friends) {
640: if (linp != linbuf)
641: printf("\n");
642: if (flag&SHELLDIR && !eq(tp->p_cwd->di_name, dcwd->di_name)) {
643: printf("(wd now: ");
644: dtildepr(value("home"), dcwd->di_name);
645: printf(")\n");
646: }
647: }
648: } while ((pp = pp->p_friends) != tp);
649: if (jobflags&PTIME && (jobflags&(PSTOPPED|PRUNNING)) == 0) {
650: if (jobflags & NUMBER)
651: printf(" ");
652: ptprint(tp);
653: }
654: return (jobflags);
655: }
656:
657: ptprint(tp)
658: register struct process *tp;
659: {
660: struct timeval tetime, diff;
661: static struct timeval ztime;
662: struct rusage ru;
663: static struct rusage zru;
664: register struct process *pp = tp;
665:
666: ru = zru;
667: tetime = ztime;
668: do {
669: ruadd(&ru, &pp->p_rusage);
670: tvsub(&diff, &pp->p_etime, &pp->p_btime);
671: if (timercmp(&diff, &tetime, >))
672: tetime = diff;
673: } while ((pp = pp->p_friends) != tp);
674: prusage(&zru, &ru, &tetime, &ztime);
675: }
676:
677: /*
678: * dojobs - print all jobs
679: */
680: dojobs(v)
681: char **v;
682: {
683: register struct process *pp;
684: register int flag = NUMBER|NAME|REASON;
685: int i;
686:
687: if (chkstop)
688: chkstop = 2;
689: if (*++v) {
690: if (v[1] || !eq(*v, "-l"))
691: error("Usage: jobs [ -l ]");
692: flag |= FANCY|JOBDIR;
693: }
694: for (i = 1; i <= pmaxindex; i++)
695: for (pp = proclist.p_next; pp; pp = pp->p_next)
696: if (pp->p_index == i && pp->p_pid == pp->p_jobid) {
697: pp->p_flags &= ~PNEEDNOTE;
698: if (!(pprint(pp, flag) & (PRUNNING|PSTOPPED)))
699: pflush(pp);
700: break;
701: }
702: }
703:
704: /*
705: * dofg - builtin - put the job into the foreground
706: */
707: dofg(v)
708: char **v;
709: {
710: register struct process *pp;
711:
712: okpcntl();
713: ++v;
714: do {
715: pp = pfind(*v);
716: pstart(pp, 1);
717: pjwait(pp);
718: } while (*v && *++v);
719: }
720:
721: /*
722: * %... - builtin - put the job into the foreground
723: */
724: dofg1(v)
725: char **v;
726: {
727: register struct process *pp;
728:
729: okpcntl();
730: pp = pfind(v[0]);
731: pstart(pp, 1);
732: pjwait(pp);
733: }
734:
735: /*
736: * dobg - builtin - put the job into the background
737: */
738: dobg(v)
739: char **v;
740: {
741: register struct process *pp;
742:
743: okpcntl();
744: ++v;
745: do {
746: pp = pfind(*v);
747: pstart(pp, 0);
748: } while (*v && *++v);
749: }
750:
751: /*
752: * %... & - builtin - put the job into the background
753: */
754: dobg1(v)
755: char **v;
756: {
757: register struct process *pp;
758:
759: pp = pfind(v[0]);
760: pstart(pp, 0);
761: }
762:
763: /*
764: * dostop - builtin - stop the job
765: */
766: dostop(v)
767: char **v;
768: {
769:
770: pkill(++v, SIGSTOP);
771: }
772:
773: /*
774: * dokill - builtin - superset of kill (1)
775: */
776: dokill(v)
777: char **v;
778: {
779: register int signum;
780: register char *name;
781:
782: v++;
783: if (v[0] && v[0][0] == '-') {
784: if (v[0][1] == 'l') {
785: for (signum = 1; signum <= NSIG; signum++) {
786: if (name = mesg[signum].iname)
787: printf("%s ", name);
788: if (signum == 16)
789: cshputchar('\n');
790: }
791: cshputchar('\n');
792: return;
793: }
794: if (digit(v[0][1])) {
795: signum = atoi(v[0]+1);
796: if (signum < 0 || signum > NSIG)
797: bferr("Bad signal number");
798: } else {
799: name = &v[0][1];
800: for (signum = 1; signum <= NSIG; signum++)
801: if (mesg[signum].iname &&
802: eq(name, mesg[signum].iname))
803: goto gotsig;
804: setname(name);
805: bferr("Unknown signal; kill -l lists signals");
806: }
807: gotsig:
808: v++;
809: } else
810: signum = SIGTERM;
811: pkill(v, signum);
812: }
813:
814: pkill(v, signum)
815: char **v;
816: int signum;
817: {
818: register struct process *pp, *np;
819: register int jobflags = 0;
820: int pid, err = 0;
821: long omask;
822: char *cp;
823: extern char *sys_errlist[];
824:
825: omask = sigmask(SIGCHLD);
826: if (setintr)
827: omask |= sigmask(SIGINT);
828: omask = sigblock(omask) & ~omask;
829: while (*v) {
830: cp = globone(*v);
831: if (*cp == '%') {
832: np = pp = pfind(cp);
833: do
834: jobflags |= np->p_flags;
835: while ((np = np->p_friends) != pp);
836: switch (signum) {
837:
838: case SIGSTOP:
839: case SIGTSTP:
840: case SIGTTIN:
841: case SIGTTOU:
842: if ((jobflags & PRUNNING) == 0) {
843: printf("%s: Already suspended\n", cp);
844: err++;
845: goto cont;
846: }
847: }
848: if (killpg(pp->p_jobid, signum) < 0) {
849: printf("%s: ", cp);
850: printf("%s\n", sys_errlist[errno]);
851: err++;
852: }
853: if (signum == SIGTERM || signum == SIGHUP)
854: (void) killpg(pp->p_jobid, SIGCONT);
855: } else if (!(digit(*cp) || *cp == '-'))
856: bferr("Arguments should be jobs or process id's");
857: else {
858: pid = atoi(cp);
859: if (kill(pid, signum) < 0) {
860: printf("%d: ", pid);
861: printf("%s\n", sys_errlist[errno]);
862: err++;
863: goto cont;
864: }
865: if (signum == SIGTERM || signum == SIGHUP)
866: (void) kill(pid, SIGCONT);
867: }
868: cont:
869: xfree(cp);
870: v++;
871: }
872: (void) sigsetmask(omask);
873: if (err)
874: error(NOSTR);
875: }
876:
877: /*
878: * pstart - start the job in foreground/background
879: */
880: pstart(pp, foregnd)
881: register struct process *pp;
882: int foregnd;
883: {
884: register struct process *np;
885: int jobflags = 0;
886: long omask;
887:
888: omask = sigblock(sigmask(SIGCHLD));
889: np = pp;
890: do {
891: jobflags |= np->p_flags;
892: if (np->p_flags&(PRUNNING|PSTOPPED)) {
893: np->p_flags |= PRUNNING;
894: np->p_flags &= ~PSTOPPED;
895: if (foregnd)
896: np->p_flags |= PFOREGND;
897: else
898: np->p_flags &= ~PFOREGND;
899: }
900: } while((np = np->p_friends) != pp);
901: if (!foregnd)
902: pclrcurr(pp);
903: (void) pprint(pp, foregnd ? NAME|JOBDIR : NUMBER|NAME|AMPERSAND);
904: if (foregnd)
905: (void) ioctl(FSHTTY, TIOCSPGRP, (char *)&pp->p_jobid);
906: if (jobflags&PSTOPPED)
907: (void) killpg(pp->p_jobid, SIGCONT);
908: (void) sigsetmask(omask);
909: }
910:
911: panystop(neednl)
912: {
913: register struct process *pp;
914:
915: chkstop = 2;
916: for (pp = proclist.p_next; pp; pp = pp->p_next)
917: if (pp->p_flags & PSTOPPED)
918: error("\nThere are suspended jobs" + 1 - neednl);
919: }
920:
921: struct process *
922: pfind(cp)
923: char *cp;
924: {
925: register struct process *pp, *np;
926:
927: if (cp == 0 || cp[1] == 0 || eq(cp, "%%") || eq(cp, "%+")) {
928: if (pcurrent == PNULL)
929: bferr("No current job");
930: return (pcurrent);
931: }
932: if (eq(cp, "%-") || eq(cp, "%#")) {
933: if (pprevious == PNULL)
934: bferr("No previous job");
935: return (pprevious);
936: }
937: if (digit(cp[1])) {
938: int index = atoi(cp+1);
939: for (pp = proclist.p_next; pp; pp = pp->p_next)
940: if (pp->p_index == index && pp->p_pid == pp->p_jobid)
941: return (pp);
942: bferr("No such job");
943: }
944: np = PNULL;
945: for (pp = proclist.p_next; pp; pp = pp->p_next)
946: if (pp->p_pid == pp->p_jobid) {
947: if (cp[1] == '?') {
948: register char *dp;
949: for (dp = pp->p_command; *dp; dp++) {
950: if (*dp != cp[2])
951: continue;
952: if (prefix(cp+2, dp))
953: goto match;
954: }
955: } else if (prefix(cp+1, pp->p_command)) {
956: match:
957: if (np)
958: bferr("Ambiguous");
959: np = pp;
960: }
961: }
962: if (np)
963: return (np);
964: if (cp[1] == '?')
965: bferr("No job matches pattern");
966: else
967: bferr("No such job");
968: /*NOTREACHED*/
969: }
970:
971: /*
972: * pgetcurr - find most recent job that is not pp, preferably stopped
973: */
974: struct process *
975: pgetcurr(pp)
976: register struct process *pp;
977: {
978: register struct process *np;
979: register struct process *xp = PNULL;
980:
981: for (np = proclist.p_next; np; np = np->p_next)
982: if (np != pcurrent && np != pp && np->p_pid &&
983: np->p_pid == np->p_jobid) {
984: if (np->p_flags & PSTOPPED)
985: return (np);
986: if (xp == PNULL)
987: xp = np;
988: }
989: return (xp);
990: }
991:
992: /*
993: * donotify - flag the job so as to report termination asynchronously
994: */
995: donotify(v)
996: char **v;
997: {
998: register struct process *pp;
999:
1000: pp = pfind(*++v);
1001: pp->p_flags |= PNOTIFY;
1002: }
1003:
1004: /*
1005: * Do the fork and whatever should be done in the child side that
1006: * should not be done if we are not forking at all (like for simple builtin's)
1007: * Also do everything that needs any signals fiddled with in the parent side
1008: *
1009: * Wanttty tells whether process and/or tty pgrps are to be manipulated:
1010: * -1: leave tty alone; inherit pgrp from parent
1011: * 0: already have tty; manipulate process pgrps only
1012: * 1: want to claim tty; manipulate process and tty pgrps
1013: * It is usually just the value of tpgrp.
1014: */
1015: pfork(t, wanttty)
1016: struct command *t; /* command we are forking for */
1017: int wanttty;
1018: {
1019: register int pid;
1020: bool ignint = 0;
1021: int pgrp;
1022: long omask;
1023:
1024: /*
1025: * A child will be uninterruptible only under very special
1026: * conditions. Remember that the semantics of '&' is
1027: * implemented by disconnecting the process from the tty so
1028: * signals do not need to ignored just for '&'.
1029: * Thus signals are set to default action for children unless:
1030: * we have had an "onintr -" (then specifically ignored)
1031: * we are not playing with signals (inherit action)
1032: */
1033: if (setintr)
1034: ignint = (tpgrp == -1 && (t->t_dflg&FINT))
1035: || (gointr && eq(gointr, "-"));
1036: /*
1037: * Hold SIGCHLD until we have the process installed in our table.
1038: */
1039: omask = sigblock(sigmask(SIGCHLD));
1040: while ((pid = fork()) < 0)
1041: if (setintr == 0)
1042: sleep(FORKSLEEP);
1043: else {
1044: (void) sigsetmask(omask);
1045: error("No more processes");
1046: }
1047: if (pid == 0) {
1048: settimes();
1049: pgrp = pcurrjob ? pcurrjob->p_jobid : getpid();
1050: pflushall();
1051: pcurrjob = PNULL;
1052: child++;
1053: if (setintr) {
1054: setintr = 0; /* until I think otherwise */
1055: /*
1056: * Children just get blown away on SIGINT, SIGQUIT
1057: * unless "onintr -" seen.
1058: */
1059: (void) signal(SIGINT, ignint ? SIG_IGN : SIG_DFL);
1060: (void) signal(SIGQUIT, ignint ? SIG_IGN : SIG_DFL);
1061: if (wanttty >= 0) {
1062: /* make stoppable */
1063: (void) signal(SIGTSTP, SIG_DFL);
1064: (void) signal(SIGTTIN, SIG_DFL);
1065: (void) signal(SIGTTOU, SIG_DFL);
1066: }
1067: (void) signal(SIGTERM, parterm);
1068: } else if (tpgrp == -1 && (t->t_dflg&FINT)) {
1069: (void) signal(SIGINT, SIG_IGN);
1070: (void) signal(SIGQUIT, SIG_IGN);
1071: }
1072: if (wanttty > 0)
1073: (void) ioctl(FSHTTY, TIOCSPGRP, (char *)&pgrp);
1074: if (wanttty >= 0 && tpgrp >= 0)
1075: (void) setpgrp(0, pgrp);
1076: if (tpgrp > 0)
1077: tpgrp = 0; /* gave tty away */
1078: /*
1079: * Nohup and nice apply only to TCOM's but it would be
1080: * nice (?!?) if you could say "nohup (foo;bar)"
1081: * Then the parser would have to know about nice/nohup/time
1082: */
1083: if (t->t_dflg & FNOHUP)
1084: (void) signal(SIGHUP, SIG_IGN);
1085: if (t->t_dflg & FNICE)
1086: (void) setpriority(PRIO_PROCESS, 0, t->t_nice);
1087: } else {
1088: palloc(pid, t);
1089: (void) sigsetmask(omask);
1090: }
1091:
1092: return (pid);
1093: }
1094:
1095: okpcntl()
1096: {
1097:
1098: if (tpgrp == -1)
1099: error("No job control in this shell");
1100: if (tpgrp == 0)
1101: error("No job control in subshells");
1102: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.