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: #if !defined(lint) && defined(DOSCCS) 8: static char *sccsid = "@(#)sh.proc.c 5.5.1 (2.11BSD) 1996/3/20"; 9: #endif 10: 11: #include "sh.h" 12: #include "sh.dir.h" 13: #include "sh.proc.h" 14: #include <string.h> 15: #include <sys/wait.h> 16: #include <sys/ioctl.h> 17: 18: /* 19: * C Shell - functions that manage processes, handling hanging, termination 20: */ 21: 22: #define BIGINDEX 9 /* largest desirable job index */ 23: 24: /* 25: * pchild - called at interrupt level by the SIGCHLD signal 26: * indicating that at least one child has terminated or stopped 27: * thus at least one wait system call will definitely return a 28: * childs status. Top level routines (like pwait) must be sure 29: * to mask interrupts when playing with the proclist data structures! 30: */ 31: pchild() 32: { 33: register struct process *pp; 34: register struct process *fp; 35: register int pid; 36: union wait w; 37: int jobflags; 38: struct rusage ru; 39: 40: loop: 41: pid = wait3(&w, (setintr ? 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 = "%-21s"; 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: putchar('\n'); 790: } 791: putchar('\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: 824: omask = sigmask(SIGCHLD); 825: if (setintr) 826: omask |= sigmask(SIGINT); 827: omask = sigblock(omask) & ~omask; 828: while (*v) { 829: cp = globone(*v); 830: if (*cp == '%') { 831: np = pp = pfind(cp); 832: do 833: jobflags |= np->p_flags; 834: while ((np = np->p_friends) != pp); 835: switch (signum) { 836: 837: case SIGSTOP: 838: case SIGTSTP: 839: case SIGTTIN: 840: case SIGTTOU: 841: if ((jobflags & PRUNNING) == 0) { 842: printf("%s: Already stopped\n", cp); 843: err++; 844: goto cont; 845: } 846: } 847: if (killpg(pp->p_jobid, signum) < 0) { 848: printf("%s: ", cp); 849: printf("%s\n", syserrlst(errno)); 850: err++; 851: } 852: if (signum == SIGTERM || signum == SIGHUP) 853: (void) killpg(pp->p_jobid, SIGCONT); 854: } else if (!(digit(*cp) || *cp == '-')) 855: bferr("Arguments should be jobs or process id's"); 856: else { 857: pid = atoi(cp); 858: if (kill(pid, signum) < 0) { 859: printf("%d: ", pid); 860: printf("%s\n", syserrlst(errno)); 861: err++; 862: goto cont; 863: } 864: if (signum == SIGTERM || signum == SIGHUP) 865: (void) kill(pid, SIGCONT); 866: } 867: cont: 868: xfree(cp); 869: v++; 870: } 871: (void) sigsetmask(omask); 872: if (err) 873: error(NOSTR); 874: } 875: 876: /* 877: * pstart - start the job in foreground/background 878: */ 879: pstart(pp, foregnd) 880: register struct process *pp; 881: int foregnd; 882: { 883: register struct process *np; 884: int jobflags = 0; 885: long omask; 886: 887: omask = sigblock(sigmask(SIGCHLD)); 888: np = pp; 889: do { 890: jobflags |= np->p_flags; 891: if (np->p_flags&(PRUNNING|PSTOPPED)) { 892: np->p_flags |= PRUNNING; 893: np->p_flags &= ~PSTOPPED; 894: if (foregnd) 895: np->p_flags |= PFOREGND; 896: else 897: np->p_flags &= ~PFOREGND; 898: } 899: } while((np = np->p_friends) != pp); 900: if (!foregnd) 901: pclrcurr(pp); 902: (void) pprint(pp, foregnd ? NAME|JOBDIR : NUMBER|NAME|AMPERSAND); 903: if (foregnd) 904: (void) ioctl(FSHTTY, TIOCSPGRP, (char *)&pp->p_jobid); 905: if (jobflags&PSTOPPED) 906: (void) killpg(pp->p_jobid, SIGCONT); 907: (void) sigsetmask(omask); 908: } 909: 910: panystop(neednl) 911: { 912: register struct process *pp; 913: 914: chkstop = 2; 915: for (pp = proclist.p_next; pp; pp = pp->p_next) 916: if (pp->p_flags & PSTOPPED) 917: error("\nThere are stopped jobs" + 1 - neednl); 918: } 919: 920: struct process * 921: pfind(cp) 922: char *cp; 923: { 924: register struct process *pp, *np; 925: 926: if (cp == 0 || cp[1] == 0 || eq(cp, "%%") || eq(cp, "%+")) { 927: if (pcurrent == PNULL) 928: bferr("No current job"); 929: return (pcurrent); 930: } 931: if (eq(cp, "%-") || eq(cp, "%#")) { 932: if (pprevious == PNULL) 933: bferr("No previous job"); 934: return (pprevious); 935: } 936: if (digit(cp[1])) { 937: int index = atoi(cp+1); 938: for (pp = proclist.p_next; pp; pp = pp->p_next) 939: if (pp->p_index == index && pp->p_pid == pp->p_jobid) 940: return (pp); 941: bferr("No such job"); 942: } 943: np = PNULL; 944: for (pp = proclist.p_next; pp; pp = pp->p_next) 945: if (pp->p_pid == pp->p_jobid) { 946: if (cp[1] == '?') { 947: register char *dp; 948: for (dp = pp->p_command; *dp; dp++) { 949: if (*dp != cp[2]) 950: continue; 951: if (prefix(cp+2, dp)) 952: goto match; 953: } 954: } else if (prefix(cp+1, pp->p_command)) { 955: match: 956: if (np) 957: bferr("Ambiguous"); 958: np = pp; 959: } 960: } 961: if (np) 962: return (np); 963: if (cp[1] == '?') 964: bferr("No job matches pattern"); 965: else 966: bferr("No such job"); 967: /*NOTREACHED*/ 968: } 969: 970: /* 971: * pgetcurr - find most recent job that is not pp, preferably stopped 972: */ 973: struct process * 974: pgetcurr(pp) 975: register struct process *pp; 976: { 977: register struct process *np; 978: register struct process *xp = PNULL; 979: 980: for (np = proclist.p_next; np; np = np->p_next) 981: if (np != pcurrent && np != pp && np->p_pid && 982: np->p_pid == np->p_jobid) { 983: if (np->p_flags & PSTOPPED) 984: return (np); 985: if (xp == PNULL) 986: xp = np; 987: } 988: return (xp); 989: } 990: 991: /* 992: * donotify - flag the job so as to report termination asynchronously 993: */ 994: donotify(v) 995: char **v; 996: { 997: register struct process *pp; 998: 999: pp = pfind(*++v); 1000: pp->p_flags |= PNOTIFY; 1001: } 1002: 1003: /* 1004: * Do the fork and whatever should be done in the child side that 1005: * should not be done if we are not forking at all (like for simple builtin's) 1006: * Also do everything that needs any signals fiddled with in the parent side 1007: * 1008: * Wanttty tells whether process and/or tty pgrps are to be manipulated: 1009: * -1: leave tty alone; inherit pgrp from parent 1010: * 0: already have tty; manipulate process pgrps only 1011: * 1: want to claim tty; manipulate process and tty pgrps 1012: * It is usually just the value of tpgrp. 1013: */ 1014: pfork(t, wanttty) 1015: struct command *t; /* command we are forking for */ 1016: int wanttty; 1017: { 1018: register int pid; 1019: bool ignint = 0; 1020: int pgrp; 1021: long omask; 1022: 1023: /* 1024: * A child will be uninterruptible only under very special 1025: * conditions. Remember that the semantics of '&' is 1026: * implemented by disconnecting the process from the tty so 1027: * signals do not need to ignored just for '&'. 1028: * Thus signals are set to default action for children unless: 1029: * we have had an "onintr -" (then specifically ignored) 1030: * we are not playing with signals (inherit action) 1031: */ 1032: if (setintr) 1033: ignint = (tpgrp == -1 && (t->t_dflg&FINT)) 1034: || (gointr && eq(gointr, "-")); 1035: /* 1036: * Hold SIGCHLD until we have the process installed in our table. 1037: */ 1038: omask = sigblock(sigmask(SIGCHLD)); 1039: while ((pid = fork()) < 0) 1040: if (setintr == 0) 1041: sleep(FORKSLEEP); 1042: else { 1043: (void) sigsetmask(omask); 1044: error("No more processes"); 1045: } 1046: if (pid == 0) { 1047: settimes(); 1048: pgrp = pcurrjob ? pcurrjob->p_jobid : getpid(); 1049: pflushall(); 1050: pcurrjob = PNULL; 1051: child++; 1052: if (setintr) { 1053: setintr = 0; /* until I think otherwise */ 1054: /* 1055: * Children just get blown away on SIGINT, SIGQUIT 1056: * unless "onintr -" seen. 1057: */ 1058: (void) signal(SIGINT, ignint ? SIG_IGN : SIG_DFL); 1059: (void) signal(SIGQUIT, ignint ? SIG_IGN : SIG_DFL); 1060: if (wanttty >= 0) { 1061: /* make stoppable */ 1062: (void) signal(SIGTSTP, SIG_DFL); 1063: (void) signal(SIGTTIN, SIG_DFL); 1064: (void) signal(SIGTTOU, SIG_DFL); 1065: } 1066: (void) signal(SIGTERM, parterm); 1067: } else if (tpgrp == -1 && (t->t_dflg&FINT)) { 1068: (void) signal(SIGINT, SIG_IGN); 1069: (void) signal(SIGQUIT, SIG_IGN); 1070: } 1071: if (wanttty > 0) 1072: (void) ioctl(FSHTTY, TIOCSPGRP, (char *)&pgrp); 1073: if (wanttty >= 0 && tpgrp >= 0) 1074: (void) setpgrp(0, pgrp); 1075: if (tpgrp > 0) 1076: tpgrp = 0; /* gave tty away */ 1077: /* 1078: * Nohup and nice apply only to TCOM's but it would be 1079: * nice (?!?) if you could say "nohup (foo;bar)" 1080: * Then the parser would have to know about nice/nohup/time 1081: */ 1082: if (t->t_dflg & FNOHUP) 1083: (void) signal(SIGHUP, SIG_IGN); 1084: if (t->t_dflg & FNICE) 1085: (void) setpriority(PRIO_PROCESS, 0, t->t_nice); 1086: } else { 1087: palloc(pid, t); 1088: (void) sigsetmask(omask); 1089: } 1090: 1091: return (pid); 1092: } 1093: 1094: okpcntl() 1095: { 1096: 1097: if (tpgrp == -1) 1098: error("No job control in this shell"); 1099: if (tpgrp == 0) 1100: error("No job control in subshells"); 1101: }