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