1 /* $NetBSD: proc.c,v 1.20 1999/05/19 14:37:05 kleink 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.20 1999/05/19 14:37:05 kleink 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 /* ARGSUSED */ 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 int w; 95 int jobflags; 96 struct rusage ru; 97 98 loop: 99 errno = 0; /* reset, just in case */ 100 pid = wait3(&w, 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 = WSTOPSIG(w); 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 (WTERMSIG(w) == SIGINT) 130 pp->p_flags |= PINTERRUPTED; 131 else 132 pp->p_flags |= PSIGNALED; 133 if (WCOREDUMP(w)) 134 pp->p_flags |= PDUMPED; 135 pp->p_reason = WTERMSIG(w); 136 } 137 else { 138 pp->p_reason = WEXITSTATUS(w); 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 (void) sigaddset(&sigset, SIGCHLD); 216 for (pp = proclist.p_next; pp != NULL; pp = pp->p_next) { 217 if (pp->p_flags & PNEEDNOTE) { 218 (void) 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 (void) 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 (void) sigaddset(&sigset, SIGCHLD); 243 (void) 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 (void) 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 (void) sigaddset(&sigset, SIGCHLD); 286 (void) sigprocmask(SIG_BLOCK, &sigset, &osigset); 287 for (;;) { 288 sigemptyset(&sigset); 289 (void) sigaddset(&sigset, SIGCHLD); 290 (void) 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 (void) sigdelset(&sigset, SIGCHLD); 303 (void) sigsuspend(&sigset); 304 } 305 (void) 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 } 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 struct process *pp; 363 sigset_t sigset, osigset; 364 365 pjobs++; 366 sigemptyset(&sigset); 367 (void) sigaddset(&sigset, SIGCHLD); 368 (void) 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 (void) sigsuspend(&sigset); 375 goto loop; 376 } 377 (void) 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 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 struct process *pp; 402 { 403 struct process *np; 404 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 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 struct command *t; 464 { 465 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 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 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 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, " %ld", (long)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 struct process *pp; 669 bool flag; 670 { 671 int 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, "%5ld ", (long)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 struct process *tp; 835 { 836 struct timeval tetime, diff; 837 static struct timeval ztime; 838 struct rusage ru; 839 static struct rusage zru; 840 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 struct process *pp; 863 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 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 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 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 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 int signum = SIGTERM; 976 Char *signame; 977 char *name; 978 979 v++; 980 if (v[0] && v[0][0] == '-') { 981 if (v[0][1] == 'l') { 982 if (v[1]) { 983 if (!Isdigit(v[1][0])) 984 stderror(ERR_NAME | ERR_BADSIG); 985 986 signum = atoi(short2str(v[1])); 987 if (signum < 0 || signum >= NSIG) 988 stderror(ERR_NAME | ERR_BADSIG); 989 else if (signum == 0) 990 (void) fputc('0', cshout); /* 0's symbolic name is '0' */ 991 else 992 (void) fprintf(cshout, "%s ", sys_signame[signum]); 993 } else { 994 for (signum = 1; signum < NSIG; signum++) { 995 (void) fprintf(cshout, "%s ", sys_signame[signum]); 996 if (signum == NSIG / 2) 997 (void) fputc('\n', cshout); 998 } 999 } 1000 (void) fputc('\n', cshout); 1001 return; 1002 } 1003 if (Isdigit(v[0][1])) { 1004 signum = atoi(short2str(v[0] + 1)); 1005 if (signum < 0 || signum > NSIG) 1006 stderror(ERR_NAME | ERR_BADSIG); 1007 } 1008 else { 1009 if (v[0][1] == 's' && v[0][2] == '\0') 1010 signame = *(++v); 1011 else 1012 signame = &v[0][1]; 1013 1014 if (signame == NULL || v[1] == NULL) 1015 stderror(ERR_NAME | ERR_TOOFEW); 1016 1017 name = short2str(signame); 1018 for (signum = 1; signum < NSIG; signum++) 1019 if (!strcasecmp(sys_signame[signum], name) || 1020 (!strncasecmp("SIG", name, 3) && /* skip "SIG" prefix */ 1021 !strcasecmp(sys_signame[signum], name + 3))) 1022 break; 1023 1024 if (signum == NSIG) { 1025 if (signame[0] == '0') 1026 signum = 0; 1027 else { 1028 setname(vis_str(signame)); 1029 stderror(ERR_NAME | ERR_UNKSIG); 1030 } 1031 } 1032 } 1033 v++; 1034 } 1035 pkill(v, signum); 1036 } 1037 1038 static void 1039 pkill(v, signum) 1040 Char **v; 1041 int signum; 1042 { 1043 struct process *pp, *np; 1044 int jobflags = 0; 1045 int pid, err1 = 0; 1046 sigset_t sigset; 1047 Char *cp; 1048 1049 sigemptyset(&sigset); 1050 (void) sigaddset(&sigset, SIGCHLD); 1051 if (setintr) 1052 (void) sigaddset(&sigset, SIGINT); 1053 (void) sigprocmask(SIG_BLOCK, &sigset, NULL); 1054 gflag = 0, tglob(v); 1055 if (gflag) { 1056 v = globall(v); 1057 if (v == 0) 1058 stderror(ERR_NAME | ERR_NOMATCH); 1059 } 1060 else { 1061 v = gargv = saveblk(v); 1062 trim(v); 1063 } 1064 1065 while (v && (cp = *v)) { 1066 if (*cp == '%') { 1067 np = pp = pfind(cp); 1068 do 1069 jobflags |= np->p_flags; 1070 while ((np = np->p_friends) != pp); 1071 switch (signum) { 1072 1073 case SIGSTOP: 1074 case SIGTSTP: 1075 case SIGTTIN: 1076 case SIGTTOU: 1077 if ((jobflags & PRUNNING) == 0) { 1078 (void) fprintf(csherr, "%s: Already suspended\n", 1079 vis_str(cp)); 1080 err1++; 1081 goto cont; 1082 } 1083 break; 1084 /* 1085 * suspend a process, kill -CONT %, then type jobs; the shell 1086 * says it is suspended, but it is running; thanks jaap.. 1087 */ 1088 case SIGCONT: 1089 pstart(pp, 0); 1090 goto cont; 1091 } 1092 if (kill(-pp->p_jobid, signum) < 0) { 1093 (void) fprintf(csherr, "%s: %s\n", vis_str(cp), 1094 strerror(errno)); 1095 err1++; 1096 } 1097 if (signum == SIGTERM || signum == SIGHUP) 1098 (void) kill(-pp->p_jobid, SIGCONT); 1099 } 1100 else if (!(Isdigit(*cp) || *cp == '-')) 1101 stderror(ERR_NAME | ERR_JOBARGS); 1102 else { 1103 pid = atoi(short2str(cp)); 1104 if (kill((pid_t) pid, signum) < 0) { 1105 (void) fprintf(csherr, "%d: %s\n", pid, strerror(errno)); 1106 err1++; 1107 goto cont; 1108 } 1109 if (signum == SIGTERM || signum == SIGHUP) 1110 (void) kill((pid_t) pid, SIGCONT); 1111 } 1112 cont: 1113 v++; 1114 } 1115 if (gargv) 1116 blkfree(gargv), gargv = 0; 1117 (void) sigprocmask(SIG_UNBLOCK, &sigset, NULL); 1118 if (err1) 1119 stderror(ERR_SILENT); 1120 } 1121 1122 /* 1123 * pstart - start the job in foreground/background 1124 */ 1125 void 1126 pstart(pp, foregnd) 1127 struct process *pp; 1128 int foregnd; 1129 { 1130 struct process *np; 1131 sigset_t sigset, osigset; 1132 long jobflags = 0; 1133 1134 sigemptyset(&sigset); 1135 (void) sigaddset(&sigset, SIGCHLD); 1136 (void) sigprocmask(SIG_BLOCK, &sigset, &osigset); 1137 np = pp; 1138 do { 1139 jobflags |= np->p_flags; 1140 if (np->p_flags & (PRUNNING | PSTOPPED)) { 1141 np->p_flags |= PRUNNING; 1142 np->p_flags &= ~PSTOPPED; 1143 if (foregnd) 1144 np->p_flags |= PFOREGND; 1145 else 1146 np->p_flags &= ~PFOREGND; 1147 } 1148 } while ((np = np->p_friends) != pp); 1149 if (!foregnd) 1150 pclrcurr(pp); 1151 (void) pprint(pp, foregnd ? NAME | JOBDIR : NUMBER | NAME | AMPERSAND); 1152 if (foregnd) 1153 (void) tcsetpgrp(FSHTTY, pp->p_jobid); 1154 if (jobflags & PSTOPPED) 1155 (void) kill(-pp->p_jobid, SIGCONT); 1156 (void) sigprocmask(SIG_SETMASK, &osigset, NULL); 1157 } 1158 1159 void 1160 panystop(neednl) 1161 bool neednl; 1162 { 1163 struct process *pp; 1164 1165 chkstop = 2; 1166 for (pp = proclist.p_next; pp; pp = pp->p_next) 1167 if (pp->p_flags & PSTOPPED) 1168 stderror(ERR_STOPPED, neednl ? "\n" : ""); 1169 } 1170 1171 struct process * 1172 pfind(cp) 1173 Char *cp; 1174 { 1175 struct process *pp, *np; 1176 1177 if (cp == 0 || cp[1] == 0 || eq(cp, STRcent2) || eq(cp, STRcentplus)) { 1178 if (pcurrent == NULL) 1179 stderror(ERR_NAME | ERR_JOBCUR); 1180 return (pcurrent); 1181 } 1182 if (eq(cp, STRcentminus) || eq(cp, STRcenthash)) { 1183 if (pprevious == NULL) 1184 stderror(ERR_NAME | ERR_JOBPREV); 1185 return (pprevious); 1186 } 1187 if (Isdigit(cp[1])) { 1188 int idx = atoi(short2str(cp + 1)); 1189 1190 for (pp = proclist.p_next; pp; pp = pp->p_next) 1191 if (pp->p_index == idx && pp->p_pid == pp->p_jobid) 1192 return (pp); 1193 stderror(ERR_NAME | ERR_NOSUCHJOB); 1194 } 1195 np = NULL; 1196 for (pp = proclist.p_next; pp; pp = pp->p_next) 1197 if (pp->p_pid == pp->p_jobid) { 1198 if (cp[1] == '?') { 1199 Char *dp; 1200 1201 for (dp = pp->p_command; *dp; dp++) { 1202 if (*dp != cp[2]) 1203 continue; 1204 if (prefix(cp + 2, dp)) 1205 goto match; 1206 } 1207 } 1208 else if (prefix(cp + 1, pp->p_command)) { 1209 match: 1210 if (np) 1211 stderror(ERR_NAME | ERR_AMBIG); 1212 np = pp; 1213 } 1214 } 1215 if (np) 1216 return (np); 1217 stderror(ERR_NAME | (cp[1] == '?' ? ERR_JOBPAT : ERR_NOSUCHJOB)); 1218 /* NOTREACHED */ 1219 } 1220 1221 1222 /* 1223 * pgetcurr - find most recent job that is not pp, preferably stopped 1224 */ 1225 static struct process * 1226 pgetcurr(pp) 1227 struct process *pp; 1228 { 1229 struct process *np; 1230 struct process *xp = NULL; 1231 1232 for (np = proclist.p_next; np; np = np->p_next) 1233 if (np != pcurrent && np != pp && np->p_pid && 1234 np->p_pid == np->p_jobid) { 1235 if (np->p_flags & PSTOPPED) 1236 return (np); 1237 if (xp == NULL) 1238 xp = np; 1239 } 1240 return (xp); 1241 } 1242 1243 /* 1244 * donotify - flag the job so as to report termination asynchronously 1245 */ 1246 void 1247 /*ARGSUSED*/ 1248 donotify(v, t) 1249 Char **v; 1250 struct command *t; 1251 { 1252 struct process *pp; 1253 1254 pp = pfind(*++v); 1255 pp->p_flags |= PNOTIFY; 1256 } 1257 1258 /* 1259 * Do the fork and whatever should be done in the child side that 1260 * should not be done if we are not forking at all (like for simple builtin's) 1261 * Also do everything that needs any signals fiddled with in the parent side 1262 * 1263 * Wanttty tells whether process and/or tty pgrps are to be manipulated: 1264 * -1: leave tty alone; inherit pgrp from parent 1265 * 0: already have tty; manipulate process pgrps only 1266 * 1: want to claim tty; manipulate process and tty pgrps 1267 * It is usually just the value of tpgrp. 1268 */ 1269 1270 int 1271 pfork(t, wanttty) 1272 struct command *t; /* command we are forking for */ 1273 int wanttty; 1274 { 1275 int pid; 1276 bool ignint = 0; 1277 int pgrp; 1278 sigset_t sigset, osigset; 1279 1280 /* 1281 * A child will be uninterruptible only under very special conditions. 1282 * Remember that the semantics of '&' is implemented by disconnecting the 1283 * process from the tty so signals do not need to ignored just for '&'. 1284 * Thus signals are set to default action for children unless: we have had 1285 * an "onintr -" (then specifically ignored) we are not playing with 1286 * signals (inherit action) 1287 */ 1288 if (setintr) 1289 ignint = (tpgrp == -1 && (t->t_dflg & F_NOINTERRUPT)) 1290 || (gointr && eq(gointr, STRminus)); 1291 /* 1292 * Check for maximum nesting of 16 processes to avoid Forking loops 1293 */ 1294 if (child == 16) 1295 stderror(ERR_NESTING, 16); 1296 /* 1297 * Hold SIGCHLD until we have the process installed in our table. 1298 */ 1299 sigemptyset(&sigset); 1300 (void) sigaddset(&sigset, SIGCHLD); 1301 (void) sigprocmask(SIG_BLOCK, &sigset, &osigset); 1302 while ((pid = fork()) < 0) 1303 if (setintr == 0) 1304 (void) sleep(FORKSLEEP); 1305 else { 1306 (void) sigprocmask(SIG_SETMASK, &osigset, NULL); 1307 stderror(ERR_NOPROC); 1308 } 1309 if (pid == 0) { 1310 settimes(); 1311 pgrp = pcurrjob ? pcurrjob->p_jobid : getpid(); 1312 pflushall(); 1313 pcurrjob = NULL; 1314 child++; 1315 if (setintr) { 1316 setintr = 0; /* until I think otherwise */ 1317 /* 1318 * Children just get blown away on SIGINT, SIGQUIT unless "onintr 1319 * -" seen. 1320 */ 1321 (void) signal(SIGINT, ignint ? SIG_IGN : SIG_DFL); 1322 (void) signal(SIGQUIT, ignint ? SIG_IGN : SIG_DFL); 1323 if (wanttty >= 0) { 1324 /* make stoppable */ 1325 (void) signal(SIGTSTP, SIG_DFL); 1326 (void) signal(SIGTTIN, SIG_DFL); 1327 (void) signal(SIGTTOU, SIG_DFL); 1328 } 1329 (void) signal(SIGTERM, parterm); 1330 } 1331 else if (tpgrp == -1 && (t->t_dflg & F_NOINTERRUPT)) { 1332 (void) signal(SIGINT, SIG_IGN); 1333 (void) signal(SIGQUIT, SIG_IGN); 1334 } 1335 pgetty(wanttty, pgrp); 1336 /* 1337 * Nohup and nice apply only to NODE_COMMAND's but it would be nice 1338 * (?!?) if you could say "nohup (foo;bar)" Then the parser would have 1339 * to know about nice/nohup/time 1340 */ 1341 if (t->t_dflg & F_NOHUP) 1342 (void) signal(SIGHUP, SIG_IGN); 1343 if (t->t_dflg & F_NICE) 1344 (void) setpriority(PRIO_PROCESS, 0, t->t_nice); 1345 } 1346 else { 1347 if (wanttty >= 0) 1348 (void) setpgid(pid, pcurrjob ? pcurrjob->p_jobid : pid); 1349 palloc(pid, t); 1350 (void) sigprocmask(SIG_SETMASK, &osigset, NULL); 1351 } 1352 1353 return (pid); 1354 } 1355 1356 static void 1357 okpcntl() 1358 { 1359 if (tpgrp == -1) 1360 stderror(ERR_JOBCONTROL); 1361 if (tpgrp == 0) 1362 stderror(ERR_JOBCTRLSUB); 1363 /* NOTREACHED */ 1364 } 1365 1366 /* 1367 * if we don't have vfork(), things can still go in the wrong order 1368 * resulting in the famous 'Stopped (tty output)'. But some systems 1369 * don't permit the setpgid() call, (these are more recent secure 1370 * systems such as ibm's aix). Then we'd rather print an error message 1371 * than hang the shell! 1372 * I am open to suggestions how to fix that. 1373 */ 1374 void 1375 pgetty(wanttty, pgrp) 1376 int wanttty, pgrp; 1377 { 1378 sigset_t sigset, osigset; 1379 1380 /* 1381 * christos: I am blocking the tty signals till I've set things 1382 * correctly.... 1383 */ 1384 if (wanttty > 0) { 1385 sigemptyset(&sigset); 1386 (void) sigaddset(&sigset, SIGTSTP); 1387 (void) sigaddset(&sigset, SIGTTIN); 1388 (void) sigaddset(&sigset, SIGTTOU); 1389 (void) sigprocmask(SIG_BLOCK, &sigset, &osigset); 1390 } 1391 /* 1392 * From: Michael Schroeder <mlschroe@immd4.informatik.uni-erlangen.de> 1393 * Don't check for tpgrp >= 0 so even non-interactive shells give 1394 * background jobs process groups Same for the comparison in the other part 1395 * of the #ifdef 1396 */ 1397 if (wanttty >= 0) 1398 if (setpgid(0, pgrp) == -1) { 1399 (void) fprintf(csherr, "csh: setpgid error.\n"); 1400 xexit(0); 1401 } 1402 1403 if (wanttty > 0) { 1404 (void) tcsetpgrp(FSHTTY, pgrp); 1405 (void) sigprocmask(SIG_SETMASK, &osigset, NULL); 1406 } 1407 1408 if (tpgrp > 0) 1409 tpgrp = 0; /* gave tty away */ 1410 } 1411