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