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