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