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