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