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