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