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