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