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