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