1 /* $NetBSD: proc.c,v 1.16 1998/12/11 14:28:58 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.16 1998/12/11 14:28:58 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 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 (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, " %d", pp->p_pid); 656 pp = pp->p_friends; 657 } while (pp != tp); 658 (void) fputc('\n', cshout); 659 } 660 pholdjob = pcurrjob = 0; 661 } 662 663 /* 664 * pprint - print a job 665 */ 666 static int 667 pprint(pp, flag) 668 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, "%5d ", pp->p_pid); 714 hadnl = 0; 715 } 716 if (flag & (REASON | AREASON)) { 717 if (flag & NAME) 718 format = "%-23s"; 719 else 720 format = "%s"; 721 if (pstatus == status) 722 if (pp->p_reason == reason) { 723 (void) fprintf(cshout, format, ""); 724 hadnl = 0; 725 goto prcomd; 726 } 727 else 728 reason = pp->p_reason; 729 else { 730 status = pstatus; 731 reason = pp->p_reason; 732 } 733 switch (status) { 734 735 case PRUNNING: 736 (void) fprintf(cshout, format, "Running "); 737 hadnl = 0; 738 break; 739 740 case PINTERRUPTED: 741 case PSTOPPED: 742 case PSIGNALED: 743 /* 744 * tell what happened to the background job 745 * From: Michael Schroeder 746 * <mlschroe@immd4.informatik.uni-erlangen.de> 747 */ 748 if ((flag & REASON) 749 || ((flag & AREASON) 750 && reason != SIGINT 751 && (reason != SIGPIPE 752 || (pp->p_flags & PPOU) == 0))) { 753 (void) fprintf(cshout, format, 754 sys_siglist[(unsigned char) 755 pp->p_reason]); 756 hadnl = 0; 757 } 758 break; 759 760 case PNEXITED: 761 case PAEXITED: 762 if (flag & REASON) { 763 if (pp->p_reason) 764 (void) fprintf(cshout, "Exit %-18d", pp->p_reason); 765 else 766 (void) fprintf(cshout, format, "Done"); 767 hadnl = 0; 768 } 769 break; 770 771 default: 772 (void) fprintf(csherr, "BUG: status=%-9o", status); 773 } 774 } 775 } 776 prcomd: 777 if (flag & NAME) { 778 (void) fprintf(cshout, "%s", vis_str(pp->p_command)); 779 if (pp->p_flags & PPOU) 780 (void) fprintf(cshout, " |"); 781 if (pp->p_flags & PERR) 782 (void) fputc('&', cshout); 783 hadnl = 0; 784 } 785 if (flag & (REASON | AREASON) && pp->p_flags & PDUMPED) { 786 (void) fprintf(cshout, " (core dumped)"); 787 hadnl = 0; 788 } 789 if (tp == pp->p_friends) { 790 if (flag & AMPERSAND) { 791 (void) fprintf(cshout, " &"); 792 hadnl = 0; 793 } 794 if (flag & JOBDIR && 795 !eq(tp->p_cwd->di_name, dcwd->di_name)) { 796 (void) fprintf(cshout, " (wd: "); 797 dtildepr(value(STRhome), tp->p_cwd->di_name); 798 (void) fputc(')', cshout); 799 hadnl = 0; 800 } 801 } 802 if (pp->p_flags & PPTIME && !(status & (PSTOPPED | PRUNNING))) { 803 if (!hadnl) 804 (void) fprintf(cshout, "\n\t"); 805 prusage(&zru, &pp->p_rusage, &pp->p_etime, 806 &pp->p_btime); 807 hadnl = 1; 808 } 809 if (tp == pp->p_friends) { 810 if (!hadnl) { 811 (void) fputc('\n', cshout); 812 hadnl = 1; 813 } 814 if (flag & SHELLDIR && !eq(tp->p_cwd->di_name, dcwd->di_name)) { 815 (void) fprintf(cshout, "(wd now: "); 816 dtildepr(value(STRhome), dcwd->di_name); 817 (void) fprintf(cshout, ")\n"); 818 hadnl = 1; 819 } 820 } 821 } while ((pp = pp->p_friends) != tp); 822 if (jobflags & PTIME && (jobflags & (PSTOPPED | PRUNNING)) == 0) { 823 if (jobflags & NUMBER) 824 (void) fprintf(cshout, " "); 825 ptprint(tp); 826 hadnl = 1; 827 } 828 (void) fflush(cshout); 829 return (jobflags); 830 } 831 832 static void 833 ptprint(tp) 834 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 *name; 977 978 v++; 979 if (v[0] && v[0][0] == '-') { 980 if (v[0][1] == 'l') { 981 if (v[1]) { 982 if (!Isdigit(v[1][0])) 983 stderror(ERR_NAME | ERR_BADSIG); 984 985 signum = atoi(short2str(v[1])); 986 if (signum < 0 || signum >= NSIG) 987 stderror(ERR_NAME | ERR_BADSIG); 988 else if (signum == 0) 989 (void) fputc('0', cshout); /* 0's symbolic name is '0' */ 990 else 991 (void) fprintf(cshout, "%s ", sys_signame[signum]); 992 } else { 993 for (signum = 1; signum < NSIG; signum++) { 994 (void) fprintf(cshout, "%s ", sys_signame[signum]); 995 if (signum == NSIG / 2) 996 (void) fputc('\n', cshout); 997 } 998 } 999 (void) fputc('\n', cshout); 1000 return; 1001 } 1002 if (Isdigit(v[0][1])) { 1003 signum = atoi(short2str(v[0] + 1)); 1004 if (signum < 0 || signum > NSIG) 1005 stderror(ERR_NAME | ERR_BADSIG); 1006 } 1007 else { 1008 if (v[0][1] == 's' && (Isspace(v[0][2]) || v[0][2] == '\0')) 1009 v++; 1010 else 1011 (*v)++; 1012 1013 if (v[0] == NULL || v[1] == NULL) 1014 stderror(ERR_NAME | ERR_TOOFEW); 1015 1016 name = short2str(&v[0][0]); 1017 for (signum = 1; signum < NSIG; signum++) 1018 if (!strcasecmp(sys_signame[signum], name) || 1019 (!strncasecmp("SIG", name, 3) && /* skip "SIG" prefix */ 1020 !strcasecmp(sys_signame[signum], name + 3))) 1021 break; 1022 1023 if (signum == NSIG) { 1024 if (v[0][0] == '0') 1025 signum = 0; 1026 else { 1027 setname(vis_str(&v[0][0])); 1028 stderror(ERR_NAME | ERR_UNKSIG); 1029 } 1030 } 1031 } 1032 v++; 1033 } 1034 pkill(v, signum); 1035 } 1036 1037 static void 1038 pkill(v, signum) 1039 Char **v; 1040 int signum; 1041 { 1042 struct process *pp, *np; 1043 int jobflags = 0; 1044 int pid, err1 = 0; 1045 sigset_t sigset; 1046 Char *cp; 1047 1048 sigemptyset(&sigset); 1049 (void) sigaddset(&sigset, SIGCHLD); 1050 if (setintr) 1051 (void) sigaddset(&sigset, SIGINT); 1052 (void) sigprocmask(SIG_BLOCK, &sigset, NULL); 1053 gflag = 0, tglob(v); 1054 if (gflag) { 1055 v = globall(v); 1056 if (v == 0) 1057 stderror(ERR_NAME | ERR_NOMATCH); 1058 } 1059 else { 1060 v = gargv = saveblk(v); 1061 trim(v); 1062 } 1063 1064 while (v && (cp = *v)) { 1065 if (*cp == '%') { 1066 np = pp = pfind(cp); 1067 do 1068 jobflags |= np->p_flags; 1069 while ((np = np->p_friends) != pp); 1070 switch (signum) { 1071 1072 case SIGSTOP: 1073 case SIGTSTP: 1074 case SIGTTIN: 1075 case SIGTTOU: 1076 if ((jobflags & PRUNNING) == 0) { 1077 (void) fprintf(csherr, "%s: Already suspended\n", 1078 vis_str(cp)); 1079 err1++; 1080 goto cont; 1081 } 1082 break; 1083 /* 1084 * suspend a process, kill -CONT %, then type jobs; the shell 1085 * says it is suspended, but it is running; thanks jaap.. 1086 */ 1087 case SIGCONT: 1088 pstart(pp, 0); 1089 goto cont; 1090 } 1091 if (kill(-pp->p_jobid, signum) < 0) { 1092 (void) fprintf(csherr, "%s: %s\n", vis_str(cp), 1093 strerror(errno)); 1094 err1++; 1095 } 1096 if (signum == SIGTERM || signum == SIGHUP) 1097 (void) kill(-pp->p_jobid, SIGCONT); 1098 } 1099 else if (!(Isdigit(*cp) || *cp == '-')) 1100 stderror(ERR_NAME | ERR_JOBARGS); 1101 else { 1102 pid = atoi(short2str(cp)); 1103 if (kill((pid_t) pid, signum) < 0) { 1104 (void) fprintf(csherr, "%d: %s\n", pid, strerror(errno)); 1105 err1++; 1106 goto cont; 1107 } 1108 if (signum == SIGTERM || signum == SIGHUP) 1109 (void) kill((pid_t) pid, SIGCONT); 1110 } 1111 cont: 1112 v++; 1113 } 1114 if (gargv) 1115 blkfree(gargv), gargv = 0; 1116 (void) sigprocmask(SIG_UNBLOCK, &sigset, NULL); 1117 if (err1) 1118 stderror(ERR_SILENT); 1119 } 1120 1121 /* 1122 * pstart - start the job in foreground/background 1123 */ 1124 void 1125 pstart(pp, foregnd) 1126 struct process *pp; 1127 int foregnd; 1128 { 1129 struct process *np; 1130 sigset_t sigset, osigset; 1131 long jobflags = 0; 1132 1133 sigemptyset(&sigset); 1134 (void) sigaddset(&sigset, SIGCHLD); 1135 (void) sigprocmask(SIG_BLOCK, &sigset, &osigset); 1136 np = pp; 1137 do { 1138 jobflags |= np->p_flags; 1139 if (np->p_flags & (PRUNNING | PSTOPPED)) { 1140 np->p_flags |= PRUNNING; 1141 np->p_flags &= ~PSTOPPED; 1142 if (foregnd) 1143 np->p_flags |= PFOREGND; 1144 else 1145 np->p_flags &= ~PFOREGND; 1146 } 1147 } while ((np = np->p_friends) != pp); 1148 if (!foregnd) 1149 pclrcurr(pp); 1150 (void) pprint(pp, foregnd ? NAME | JOBDIR : NUMBER | NAME | AMPERSAND); 1151 if (foregnd) 1152 (void) tcsetpgrp(FSHTTY, pp->p_jobid); 1153 if (jobflags & PSTOPPED) 1154 (void) kill(-pp->p_jobid, SIGCONT); 1155 (void) sigprocmask(SIG_SETMASK, &osigset, NULL); 1156 } 1157 1158 void 1159 panystop(neednl) 1160 bool neednl; 1161 { 1162 struct process *pp; 1163 1164 chkstop = 2; 1165 for (pp = proclist.p_next; pp; pp = pp->p_next) 1166 if (pp->p_flags & PSTOPPED) 1167 stderror(ERR_STOPPED, neednl ? "\n" : ""); 1168 } 1169 1170 struct process * 1171 pfind(cp) 1172 Char *cp; 1173 { 1174 struct process *pp, *np; 1175 1176 if (cp == 0 || cp[1] == 0 || eq(cp, STRcent2) || eq(cp, STRcentplus)) { 1177 if (pcurrent == NULL) 1178 stderror(ERR_NAME | ERR_JOBCUR); 1179 return (pcurrent); 1180 } 1181 if (eq(cp, STRcentminus) || eq(cp, STRcenthash)) { 1182 if (pprevious == NULL) 1183 stderror(ERR_NAME | ERR_JOBPREV); 1184 return (pprevious); 1185 } 1186 if (Isdigit(cp[1])) { 1187 int idx = atoi(short2str(cp + 1)); 1188 1189 for (pp = proclist.p_next; pp; pp = pp->p_next) 1190 if (pp->p_index == idx && pp->p_pid == pp->p_jobid) 1191 return (pp); 1192 stderror(ERR_NAME | ERR_NOSUCHJOB); 1193 } 1194 np = NULL; 1195 for (pp = proclist.p_next; pp; pp = pp->p_next) 1196 if (pp->p_pid == pp->p_jobid) { 1197 if (cp[1] == '?') { 1198 Char *dp; 1199 1200 for (dp = pp->p_command; *dp; dp++) { 1201 if (*dp != cp[2]) 1202 continue; 1203 if (prefix(cp + 2, dp)) 1204 goto match; 1205 } 1206 } 1207 else if (prefix(cp + 1, pp->p_command)) { 1208 match: 1209 if (np) 1210 stderror(ERR_NAME | ERR_AMBIG); 1211 np = pp; 1212 } 1213 } 1214 if (np) 1215 return (np); 1216 stderror(ERR_NAME | (cp[1] == '?' ? ERR_JOBPAT : ERR_NOSUCHJOB)); 1217 /* NOTREACHED */ 1218 } 1219 1220 1221 /* 1222 * pgetcurr - find most recent job that is not pp, preferably stopped 1223 */ 1224 static struct process * 1225 pgetcurr(pp) 1226 struct process *pp; 1227 { 1228 struct process *np; 1229 struct process *xp = NULL; 1230 1231 for (np = proclist.p_next; np; np = np->p_next) 1232 if (np != pcurrent && np != pp && np->p_pid && 1233 np->p_pid == np->p_jobid) { 1234 if (np->p_flags & PSTOPPED) 1235 return (np); 1236 if (xp == NULL) 1237 xp = np; 1238 } 1239 return (xp); 1240 } 1241 1242 /* 1243 * donotify - flag the job so as to report termination asynchronously 1244 */ 1245 void 1246 /*ARGSUSED*/ 1247 donotify(v, t) 1248 Char **v; 1249 struct command *t; 1250 { 1251 struct process *pp; 1252 1253 pp = pfind(*++v); 1254 pp->p_flags |= PNOTIFY; 1255 } 1256 1257 /* 1258 * Do the fork and whatever should be done in the child side that 1259 * should not be done if we are not forking at all (like for simple builtin's) 1260 * Also do everything that needs any signals fiddled with in the parent side 1261 * 1262 * Wanttty tells whether process and/or tty pgrps are to be manipulated: 1263 * -1: leave tty alone; inherit pgrp from parent 1264 * 0: already have tty; manipulate process pgrps only 1265 * 1: want to claim tty; manipulate process and tty pgrps 1266 * It is usually just the value of tpgrp. 1267 */ 1268 1269 int 1270 pfork(t, wanttty) 1271 struct command *t; /* command we are forking for */ 1272 int wanttty; 1273 { 1274 int pid; 1275 bool ignint = 0; 1276 int pgrp; 1277 sigset_t sigset, osigset; 1278 1279 /* 1280 * A child will be uninterruptible only under very special conditions. 1281 * Remember that the semantics of '&' is implemented by disconnecting the 1282 * process from the tty so signals do not need to ignored just for '&'. 1283 * Thus signals are set to default action for children unless: we have had 1284 * an "onintr -" (then specifically ignored) we are not playing with 1285 * signals (inherit action) 1286 */ 1287 if (setintr) 1288 ignint = (tpgrp == -1 && (t->t_dflg & F_NOINTERRUPT)) 1289 || (gointr && eq(gointr, STRminus)); 1290 /* 1291 * Check for maximum nesting of 16 processes to avoid Forking loops 1292 */ 1293 if (child == 16) 1294 stderror(ERR_NESTING, 16); 1295 /* 1296 * Hold SIGCHLD until we have the process installed in our table. 1297 */ 1298 sigemptyset(&sigset); 1299 (void) sigaddset(&sigset, SIGCHLD); 1300 (void) sigprocmask(SIG_BLOCK, &sigset, &osigset); 1301 while ((pid = fork()) < 0) 1302 if (setintr == 0) 1303 (void) sleep(FORKSLEEP); 1304 else { 1305 (void) sigprocmask(SIG_SETMASK, &osigset, NULL); 1306 stderror(ERR_NOPROC); 1307 } 1308 if (pid == 0) { 1309 settimes(); 1310 pgrp = pcurrjob ? pcurrjob->p_jobid : getpid(); 1311 pflushall(); 1312 pcurrjob = NULL; 1313 child++; 1314 if (setintr) { 1315 setintr = 0; /* until I think otherwise */ 1316 /* 1317 * Children just get blown away on SIGINT, SIGQUIT unless "onintr 1318 * -" seen. 1319 */ 1320 (void) signal(SIGINT, ignint ? SIG_IGN : SIG_DFL); 1321 (void) signal(SIGQUIT, ignint ? SIG_IGN : SIG_DFL); 1322 if (wanttty >= 0) { 1323 /* make stoppable */ 1324 (void) signal(SIGTSTP, SIG_DFL); 1325 (void) signal(SIGTTIN, SIG_DFL); 1326 (void) signal(SIGTTOU, SIG_DFL); 1327 } 1328 (void) signal(SIGTERM, parterm); 1329 } 1330 else if (tpgrp == -1 && (t->t_dflg & F_NOINTERRUPT)) { 1331 (void) signal(SIGINT, SIG_IGN); 1332 (void) signal(SIGQUIT, SIG_IGN); 1333 } 1334 pgetty(wanttty, pgrp); 1335 /* 1336 * Nohup and nice apply only to NODE_COMMAND's but it would be nice 1337 * (?!?) if you could say "nohup (foo;bar)" Then the parser would have 1338 * to know about nice/nohup/time 1339 */ 1340 if (t->t_dflg & F_NOHUP) 1341 (void) signal(SIGHUP, SIG_IGN); 1342 if (t->t_dflg & F_NICE) 1343 (void) setpriority(PRIO_PROCESS, 0, t->t_nice); 1344 } 1345 else { 1346 if (wanttty >= 0) 1347 (void) setpgid(pid, pcurrjob ? pcurrjob->p_jobid : pid); 1348 palloc(pid, t); 1349 (void) sigprocmask(SIG_SETMASK, &osigset, NULL); 1350 } 1351 1352 return (pid); 1353 } 1354 1355 static void 1356 okpcntl() 1357 { 1358 if (tpgrp == -1) 1359 stderror(ERR_JOBCONTROL); 1360 if (tpgrp == 0) 1361 stderror(ERR_JOBCTRLSUB); 1362 /* NOTREACHED */ 1363 } 1364 1365 /* 1366 * if we don't have vfork(), things can still go in the wrong order 1367 * resulting in the famous 'Stopped (tty output)'. But some systems 1368 * don't permit the setpgid() call, (these are more recent secure 1369 * systems such as ibm's aix). Then we'd rather print an error message 1370 * than hang the shell! 1371 * I am open to suggestions how to fix that. 1372 */ 1373 void 1374 pgetty(wanttty, pgrp) 1375 int wanttty, pgrp; 1376 { 1377 sigset_t sigset, osigset; 1378 1379 /* 1380 * christos: I am blocking the tty signals till I've set things 1381 * correctly.... 1382 */ 1383 if (wanttty > 0) { 1384 sigemptyset(&sigset); 1385 (void) sigaddset(&sigset, SIGTSTP); 1386 (void) sigaddset(&sigset, SIGTTIN); 1387 (void) sigaddset(&sigset, SIGTTOU); 1388 (void) sigprocmask(SIG_BLOCK, &sigset, &osigset); 1389 } 1390 /* 1391 * From: Michael Schroeder <mlschroe@immd4.informatik.uni-erlangen.de> 1392 * Don't check for tpgrp >= 0 so even non-interactive shells give 1393 * background jobs process groups Same for the comparison in the other part 1394 * of the #ifdef 1395 */ 1396 if (wanttty >= 0) 1397 if (setpgid(0, pgrp) == -1) { 1398 (void) fprintf(csherr, "csh: setpgid error.\n"); 1399 xexit(0); 1400 } 1401 1402 if (wanttty > 0) { 1403 (void) tcsetpgrp(FSHTTY, pgrp); 1404 (void) sigprocmask(SIG_SETMASK, &osigset, NULL); 1405 } 1406 1407 if (tpgrp > 0) 1408 tpgrp = 0; /* gave tty away */ 1409 } 1410