1 /* $NetBSD: jobs.c,v 1.71 2012/12/31 14:10:15 dsl Exp $ */ 2 3 /*- 4 * Copyright (c) 1991, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Kenneth Almquist. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35 #include <sys/cdefs.h> 36 #ifndef lint 37 #if 0 38 static char sccsid[] = "@(#)jobs.c 8.5 (Berkeley) 5/4/95"; 39 #else 40 __RCSID("$NetBSD: jobs.c,v 1.71 2012/12/31 14:10:15 dsl Exp $"); 41 #endif 42 #endif /* not lint */ 43 44 #include <fcntl.h> 45 #include <signal.h> 46 #include <errno.h> 47 #include <unistd.h> 48 #include <stdlib.h> 49 #include <paths.h> 50 #include <sys/types.h> 51 #include <sys/param.h> 52 #ifdef BSD 53 #include <sys/wait.h> 54 #include <sys/time.h> 55 #include <sys/resource.h> 56 #endif 57 #include <sys/ioctl.h> 58 59 #include "shell.h" 60 #if JOBS 61 #if OLD_TTY_DRIVER 62 #include "sgtty.h" 63 #else 64 #include <termios.h> 65 #endif 66 #undef CEOF /* syntax.h redefines this */ 67 #endif 68 #include "redir.h" 69 #include "show.h" 70 #include "main.h" 71 #include "parser.h" 72 #include "nodes.h" 73 #include "jobs.h" 74 #include "options.h" 75 #include "builtins.h" 76 #include "trap.h" 77 #include "syntax.h" 78 #include "input.h" 79 #include "output.h" 80 #include "memalloc.h" 81 #include "error.h" 82 #include "mystring.h" 83 84 85 static struct job *jobtab; /* array of jobs */ 86 static int njobs; /* size of array */ 87 static int jobs_invalid; /* set in child */ 88 MKINIT pid_t backgndpid = -1; /* pid of last background process */ 89 #if JOBS 90 int initialpgrp; /* pgrp of shell on invocation */ 91 static int curjob = -1; /* current job */ 92 #endif 93 #if JOBS && defined(__minix) 94 static int ttyfd = -1; 95 #endif /* JOBS && defined(__minix) */ 96 97 STATIC void restartjob(struct job *); 98 STATIC void freejob(struct job *); 99 STATIC struct job *getjob(const char *, int); 100 STATIC int dowait(int, struct job *); 101 #define WBLOCK 1 102 #define WNOFREE 2 103 STATIC int waitproc(int, struct job *, int *); 104 STATIC void cmdtxt(union node *); 105 STATIC void cmdlist(union node *, int); 106 STATIC void cmdputs(const char *); 107 108 #ifdef SYSV 109 STATIC int onsigchild(void); 110 #endif 111 112 #ifdef OLD_TTY_DRIVER 113 static pid_t tcgetpgrp(int fd); 114 static int tcsetpgrp(int fd, pid_t pgrp); 115 116 static pid_t 117 tcgetpgrp(int fd) 118 { 119 pid_t pgrp; 120 if (ioctl(fd, TIOCGPGRP, (char *)&pgrp) == -1) 121 return -1; 122 else 123 return pgrp; 124 } 125 126 static int 127 tcsetpgrp(int fd, pid_tpgrp) 128 { 129 return ioctl(fd, TIOCSPGRP, (char *)&pgrp); 130 } 131 #endif 132 133 /* 134 * Turn job control on and off. 135 * 136 * Note: This code assumes that the third arg to ioctl is a character 137 * pointer, which is true on Berkeley systems but not System V. Since 138 * System V doesn't have job control yet, this isn't a problem now. 139 */ 140 141 MKINIT int jobctl; 142 143 #if JOBS /* Minix setjobctl is defined to empty, compilation error */ 144 void 145 setjobctl(int on) 146 { 147 #ifdef OLD_TTY_DRIVER 148 int ldisc; 149 #endif 150 151 if (on == jobctl || rootshell == 0) 152 return; 153 if (on) { 154 #if defined(FIOCLEX) || defined(FD_CLOEXEC) 155 int err; 156 int i; 157 if (ttyfd != -1) 158 close(ttyfd); 159 if ((ttyfd = open("/dev/tty", O_RDWR)) == -1) { 160 for (i = 0; i < 3; i++) { 161 if (isatty(i) && (ttyfd = dup(i)) != -1) 162 break; 163 } 164 if (i == 3) 165 goto out; 166 } 167 /* Move to a high fd */ 168 for (i = 10; i > 2; i--) { 169 if ((err = fcntl(ttyfd, F_DUPFD, (1 << i) - 1)) != -1) 170 break; 171 } 172 if (err != -1) { 173 close(ttyfd); 174 ttyfd = err; 175 } 176 #ifdef FIOCLEX 177 err = ioctl(ttyfd, FIOCLEX, 0); 178 #elif FD_CLOEXEC 179 err = fcntl(ttyfd, F_SETFD, 180 fcntl(ttyfd, F_GETFD, 0) | FD_CLOEXEC); 181 #endif 182 if (err == -1) { 183 close(ttyfd); 184 ttyfd = -1; 185 goto out; 186 } 187 #else 188 out2str("sh: Need FIOCLEX or FD_CLOEXEC to support job control"); 189 goto out; 190 #endif 191 do { /* while we are in the background */ 192 if ((initialpgrp = tcgetpgrp(ttyfd)) < 0) { 193 out: 194 out2str("sh: can't access tty; job control turned off\n"); 195 mflag = 0; 196 return; 197 } 198 if (initialpgrp == -1) 199 initialpgrp = getpgrp(); 200 else if (initialpgrp != getpgrp()) { 201 killpg(0, SIGTTIN); 202 continue; 203 } 204 } while (0); 205 206 #ifdef OLD_TTY_DRIVER 207 if (ioctl(ttyfd, TIOCGETD, (char *)&ldisc) < 0 208 || ldisc != NTTYDISC) { 209 out2str("sh: need new tty driver to run job control; job control turned off\n"); 210 mflag = 0; 211 return; 212 } 213 #endif 214 setsignal(SIGTSTP, 0); 215 setsignal(SIGTTOU, 0); 216 setsignal(SIGTTIN, 0); 217 if (getpgrp() != rootpid && setpgid(0, rootpid) == -1) 218 error("Cannot set process group (%s) at %d", 219 strerror(errno), __LINE__); 220 if (tcsetpgrp(ttyfd, rootpid) == -1) 221 error("Cannot set tty process group (%s) at %d", 222 strerror(errno), __LINE__); 223 } else { /* turning job control off */ 224 if (getpgrp() != initialpgrp && setpgid(0, initialpgrp) == -1) 225 error("Cannot set process group (%s) at %d", 226 strerror(errno), __LINE__); 227 if (tcsetpgrp(ttyfd, initialpgrp) == -1) 228 error("Cannot set tty process group (%s) at %d", 229 strerror(errno), __LINE__); 230 close(ttyfd); 231 ttyfd = -1; 232 setsignal(SIGTSTP, 0); 233 setsignal(SIGTTOU, 0); 234 setsignal(SIGTTIN, 0); 235 } 236 jobctl = on; 237 } 238 #endif /* JOBS */ 239 240 241 #ifdef mkinit 242 INCLUDE <stdlib.h> 243 244 SHELLPROC { 245 backgndpid = -1; 246 #if JOBS 247 jobctl = 0; 248 #endif 249 } 250 251 #endif 252 253 254 255 #if JOBS 256 static int 257 do_fgcmd(const char *arg_ptr) 258 { 259 struct job *jp; 260 int i; 261 int status; 262 263 jp = getjob(arg_ptr, 0); 264 if (jp->jobctl == 0) 265 error("job not created under job control"); 266 out1fmt("%s", jp->ps[0].cmd); 267 for (i = 1; i < jp->nprocs; i++) 268 out1fmt(" | %s", jp->ps[i].cmd ); 269 out1c('\n'); 270 flushall(); 271 272 for (i = 0; i < jp->nprocs; i++) 273 if (tcsetpgrp(ttyfd, jp->ps[i].pid) != -1) 274 break; 275 276 if (i >= jp->nprocs) { 277 error("Cannot set tty process group (%s) at %d", 278 strerror(errno), __LINE__); 279 } 280 restartjob(jp); 281 INTOFF; 282 status = waitforjob(jp); 283 INTON; 284 return status; 285 } 286 287 int 288 fgcmd(int argc, char **argv) 289 { 290 nextopt(""); 291 return do_fgcmd(*argptr); 292 } 293 294 int 295 fgcmd_percent(int argc, char **argv) 296 { 297 nextopt(""); 298 return do_fgcmd(*argv); 299 } 300 301 static void 302 set_curjob(struct job *jp, int mode) 303 { 304 struct job *jp1, *jp2; 305 int i, ji; 306 307 ji = jp - jobtab; 308 309 /* first remove from list */ 310 if (ji == curjob) 311 curjob = jp->prev_job; 312 else { 313 for (i = 0; i < njobs; i++) { 314 if (jobtab[i].prev_job != ji) 315 continue; 316 jobtab[i].prev_job = jp->prev_job; 317 break; 318 } 319 } 320 321 /* Then re-insert in correct position */ 322 switch (mode) { 323 case 0: /* job being deleted */ 324 jp->prev_job = -1; 325 break; 326 case 1: /* newly created job or backgrounded job, 327 put after all stopped jobs. */ 328 if (curjob != -1 && jobtab[curjob].state == JOBSTOPPED) { 329 for (jp1 = jobtab + curjob; ; jp1 = jp2) { 330 if (jp1->prev_job == -1) 331 break; 332 jp2 = jobtab + jp1->prev_job; 333 if (jp2->state != JOBSTOPPED) 334 break; 335 } 336 jp->prev_job = jp1->prev_job; 337 jp1->prev_job = ji; 338 break; 339 } 340 /* FALLTHROUGH */ 341 case 2: /* newly stopped job - becomes curjob */ 342 jp->prev_job = curjob; 343 curjob = ji; 344 break; 345 } 346 } 347 348 int 349 bgcmd(int argc, char **argv) 350 { 351 struct job *jp; 352 int i; 353 354 nextopt(""); 355 do { 356 jp = getjob(*argptr, 0); 357 if (jp->jobctl == 0) 358 error("job not created under job control"); 359 set_curjob(jp, 1); 360 out1fmt("[%ld] %s", (long)(jp - jobtab + 1), jp->ps[0].cmd); 361 for (i = 1; i < jp->nprocs; i++) 362 out1fmt(" | %s", jp->ps[i].cmd ); 363 out1c('\n'); 364 flushall(); 365 restartjob(jp); 366 } while (*argptr && *++argptr); 367 return 0; 368 } 369 370 371 STATIC void 372 restartjob(struct job *jp) 373 { 374 struct procstat *ps; 375 int i; 376 377 if (jp->state == JOBDONE) 378 return; 379 INTOFF; 380 for (i = 0; i < jp->nprocs; i++) 381 if (killpg(jp->ps[i].pid, SIGCONT) != -1) 382 break; 383 if (i >= jp->nprocs) 384 error("Cannot continue job (%s)", strerror(errno)); 385 for (ps = jp->ps, i = jp->nprocs ; --i >= 0 ; ps++) { 386 if (WIFSTOPPED(ps->status)) { 387 ps->status = -1; 388 jp->state = JOBRUNNING; 389 } 390 } 391 INTON; 392 } 393 #else 394 /* LSC: For Minix add dummy functions. */ 395 int 396 fgcmd(int argc, char **argv) 397 { 398 error("no job control in this shell."); 399 return 1; 400 } 401 402 int 403 fgcmd_percent(int argc, char **argv) 404 { 405 error("no job control in this shell."); 406 return 1; 407 } 408 409 410 int 411 bgcmd(int argc, char **argv) 412 { 413 error("no job control in this shell."); 414 return 1; 415 } 416 #endif 417 418 static void 419 showjob(struct output *out, struct job *jp, int mode) 420 { 421 int procno; 422 int st; 423 struct procstat *ps; 424 int col; 425 char s[64]; 426 427 #if JOBS 428 if (mode & SHOW_PGID) { 429 /* just output process (group) id of pipeline */ 430 outfmt(out, "%ld\n", (long)jp->ps->pid); 431 return; 432 } 433 #endif 434 435 procno = jp->nprocs; 436 if (!procno) 437 return; 438 439 if (mode & SHOW_PID) 440 mode |= SHOW_MULTILINE; 441 442 if ((procno > 1 && !(mode & SHOW_MULTILINE)) 443 || (mode & SHOW_SIGNALLED)) { 444 /* See if we have more than one status to report */ 445 ps = jp->ps; 446 st = ps->status; 447 do { 448 int st1 = ps->status; 449 if (st1 != st) 450 /* yes - need multi-line output */ 451 mode |= SHOW_MULTILINE; 452 if (st1 == -1 || !(mode & SHOW_SIGNALLED) || WIFEXITED(st1)) 453 continue; 454 if (WIFSTOPPED(st1) || ((st1 = WTERMSIG(st1) & 0x7f) 455 && st1 != SIGINT && st1 != SIGPIPE)) 456 mode |= SHOW_ISSIG; 457 458 } while (ps++, --procno); 459 procno = jp->nprocs; 460 } 461 462 if (mode & SHOW_SIGNALLED && !(mode & SHOW_ISSIG)) { 463 if (jp->state == JOBDONE && !(mode & SHOW_NO_FREE)) { 464 TRACE(("showjob: freeing job %d\n", jp - jobtab + 1)); 465 freejob(jp); 466 } 467 return; 468 } 469 470 for (ps = jp->ps; --procno >= 0; ps++) { /* for each process */ 471 if (ps == jp->ps) 472 fmtstr(s, 16, "[%ld] %c ", 473 (long)(jp - jobtab + 1), 474 #if JOBS 475 jp == jobtab + curjob ? '+' : 476 curjob != -1 && jp == jobtab + 477 jobtab[curjob].prev_job ? '-' : 478 #endif 479 ' '); 480 else 481 fmtstr(s, 16, " " ); 482 col = strlen(s); 483 if (mode & SHOW_PID) { 484 fmtstr(s + col, 16, "%ld ", (long)ps->pid); 485 col += strlen(s + col); 486 } 487 if (ps->status == -1) { 488 scopy("Running", s + col); 489 } else if (WIFEXITED(ps->status)) { 490 st = WEXITSTATUS(ps->status); 491 if (st) 492 fmtstr(s + col, 16, "Done(%d)", st); 493 else 494 fmtstr(s + col, 16, "Done"); 495 } else { 496 #if JOBS 497 if (WIFSTOPPED(ps->status)) 498 st = WSTOPSIG(ps->status); 499 else /* WIFSIGNALED(ps->status) */ 500 #endif 501 st = WTERMSIG(ps->status); 502 st &= 0x7f; 503 if (st < NSIG && sys_siglist[st]) 504 scopyn(sys_siglist[st], s + col, 32); 505 else 506 fmtstr(s + col, 16, "Signal %d", st); 507 if (WCOREDUMP(ps->status)) { 508 col += strlen(s + col); 509 scopyn(" (core dumped)", s + col, 64 - col); 510 } 511 } 512 col += strlen(s + col); 513 outstr(s, out); 514 do { 515 outc(' ', out); 516 col++; 517 } while (col < 30); 518 outstr(ps->cmd, out); 519 if (mode & SHOW_MULTILINE) { 520 if (procno > 0) { 521 outc(' ', out); 522 outc('|', out); 523 } 524 } else { 525 while (--procno >= 0) 526 outfmt(out, " | %s", (++ps)->cmd ); 527 } 528 outc('\n', out); 529 } 530 flushout(out); 531 jp->changed = 0; 532 if (jp->state == JOBDONE && !(mode & SHOW_NO_FREE)) 533 freejob(jp); 534 } 535 536 537 int 538 jobscmd(int argc, char **argv) 539 { 540 int mode, m; 541 int sv = jobs_invalid; 542 543 jobs_invalid = 0; 544 mode = 0; 545 while ((m = nextopt("lp"))) 546 if (m == 'l') 547 mode = SHOW_PID; 548 else 549 mode = SHOW_PGID; 550 if (*argptr) 551 do 552 showjob(out1, getjob(*argptr,0), mode); 553 while (*++argptr); 554 else 555 showjobs(out1, mode); 556 jobs_invalid = sv; 557 return 0; 558 } 559 560 561 /* 562 * Print a list of jobs. If "change" is nonzero, only print jobs whose 563 * statuses have changed since the last call to showjobs. 564 * 565 * If the shell is interrupted in the process of creating a job, the 566 * result may be a job structure containing zero processes. Such structures 567 * will be freed here. 568 */ 569 570 void 571 showjobs(struct output *out, int mode) 572 { 573 int jobno; 574 struct job *jp; 575 int silent = 0, gotpid; 576 577 TRACE(("showjobs(%x) called\n", mode)); 578 579 /* If not even one one job changed, there is nothing to do */ 580 gotpid = dowait(0, NULL); 581 while (dowait(0, NULL) > 0) 582 continue; 583 #if JOBS /* MINIX: #ifdef fails when JOBS = 0 */ 584 /* 585 * Check if we are not in our foreground group, and if not 586 * put us in it. 587 */ 588 if (mflag && gotpid != -1 && tcgetpgrp(ttyfd) != getpid()) { 589 if (tcsetpgrp(ttyfd, getpid()) == -1) 590 error("Cannot set tty process group (%s) at %d", 591 strerror(errno), __LINE__); 592 TRACE(("repaired tty process group\n")); 593 silent = 1; 594 } 595 #endif 596 if (jobs_invalid) 597 return; 598 599 for (jobno = 1, jp = jobtab ; jobno <= njobs ; jobno++, jp++) { 600 if (!jp->used) 601 continue; 602 if (jp->nprocs == 0) { 603 freejob(jp); 604 continue; 605 } 606 if ((mode & SHOW_CHANGED) && !jp->changed) 607 continue; 608 if (silent && jp->changed) { 609 jp->changed = 0; 610 continue; 611 } 612 showjob(out, jp, mode); 613 } 614 } 615 616 /* 617 * Mark a job structure as unused. 618 */ 619 620 STATIC void 621 freejob(struct job *jp) 622 { 623 INTOFF; 624 if (jp->ps != &jp->ps0) { 625 ckfree(jp->ps); 626 jp->ps = &jp->ps0; 627 } 628 jp->nprocs = 0; 629 jp->used = 0; 630 #if JOBS 631 set_curjob(jp, 0); 632 #endif 633 INTON; 634 } 635 636 637 638 int 639 waitcmd(int argc, char **argv) 640 { 641 struct job *job; 642 int status, retval; 643 struct job *jp; 644 645 nextopt(""); 646 647 if (!*argptr) { 648 /* wait for all jobs */ 649 jp = jobtab; 650 if (jobs_invalid) 651 return 0; 652 for (;;) { 653 if (jp >= jobtab + njobs) { 654 /* no running procs */ 655 return 0; 656 } 657 if (!jp->used || jp->state != JOBRUNNING) { 658 jp++; 659 continue; 660 } 661 if (dowait(WBLOCK, NULL) == -1) 662 return 128 + SIGINT; 663 jp = jobtab; 664 } 665 } 666 667 retval = 127; /* XXXGCC: -Wuninitialized */ 668 for (; *argptr; argptr++) { 669 job = getjob(*argptr, 1); 670 if (!job) { 671 retval = 127; 672 continue; 673 } 674 /* loop until process terminated or stopped */ 675 while (job->state == JOBRUNNING) { 676 if (dowait(WBLOCK|WNOFREE, job) == -1) 677 return 128 + SIGINT; 678 } 679 status = job->ps[job->nprocs - 1].status; 680 if (WIFEXITED(status)) 681 retval = WEXITSTATUS(status); 682 #if JOBS 683 else if (WIFSTOPPED(status)) 684 retval = WSTOPSIG(status) + 128; 685 #endif 686 else { 687 /* XXX: limits number of signals */ 688 retval = WTERMSIG(status) + 128; 689 } 690 if (!iflag) 691 freejob(job); 692 } 693 return retval; 694 } 695 696 697 698 int 699 jobidcmd(int argc, char **argv) 700 { 701 struct job *jp; 702 int i; 703 704 nextopt(""); 705 jp = getjob(*argptr, 0); 706 for (i = 0 ; i < jp->nprocs ; ) { 707 out1fmt("%ld", (long)jp->ps[i].pid); 708 out1c(++i < jp->nprocs ? ' ' : '\n'); 709 } 710 return 0; 711 } 712 713 int 714 getjobpgrp(const char *name) 715 { 716 struct job *jp; 717 718 jp = getjob(name, 1); 719 if (jp == 0) 720 return 0; 721 return -jp->ps[0].pid; 722 } 723 724 /* 725 * Convert a job name to a job structure. 726 */ 727 728 STATIC struct job * 729 getjob(const char *name, int noerror) 730 { 731 int jobno = -1; 732 struct job *jp; 733 int pid; 734 int i; 735 const char *err_msg = "No such job: %s"; 736 737 if (name == NULL) { 738 #if JOBS 739 jobno = curjob; 740 #endif 741 err_msg = "No current job"; 742 } else if (name[0] == '%') { 743 if (is_number(name + 1)) { 744 jobno = number(name + 1) - 1; 745 } else if (!name[2]) { 746 switch (name[1]) { 747 #if JOBS 748 case 0: 749 case '+': 750 case '%': 751 jobno = curjob; 752 err_msg = "No current job"; 753 break; 754 case '-': 755 jobno = curjob; 756 if (jobno != -1) 757 jobno = jobtab[jobno].prev_job; 758 err_msg = "No previous job"; 759 break; 760 #endif 761 default: 762 goto check_pattern; 763 } 764 } else { 765 struct job *found; 766 check_pattern: 767 found = NULL; 768 for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) { 769 if (!jp->used || jp->nprocs <= 0) 770 continue; 771 if ((name[1] == '?' 772 && strstr(jp->ps[0].cmd, name + 2)) 773 || prefix(name + 1, jp->ps[0].cmd)) { 774 if (found) { 775 err_msg = "%s: ambiguous"; 776 found = 0; 777 break; 778 } 779 found = jp; 780 } 781 } 782 if (found) 783 return found; 784 } 785 786 } else if (is_number(name)) { 787 pid = number(name); 788 for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) { 789 if (jp->used && jp->nprocs > 0 790 && jp->ps[jp->nprocs - 1].pid == pid) 791 return jp; 792 } 793 } 794 795 if (!jobs_invalid && jobno >= 0 && jobno < njobs) { 796 jp = jobtab + jobno; 797 if (jp->used) 798 return jp; 799 } 800 if (!noerror) 801 error(err_msg, name); 802 return 0; 803 } 804 805 806 807 /* 808 * Return a new job structure, 809 */ 810 811 struct job * 812 makejob(union node *node, int nprocs) 813 { 814 int i; 815 struct job *jp; 816 817 if (jobs_invalid) { 818 for (i = njobs, jp = jobtab ; --i >= 0 ; jp++) { 819 if (jp->used) 820 freejob(jp); 821 } 822 jobs_invalid = 0; 823 } 824 825 for (i = njobs, jp = jobtab ; ; jp++) { 826 if (--i < 0) { 827 INTOFF; 828 if (njobs == 0) { 829 jobtab = ckmalloc(4 * sizeof jobtab[0]); 830 } else { 831 jp = ckmalloc((njobs + 4) * sizeof jobtab[0]); 832 memcpy(jp, jobtab, njobs * sizeof jp[0]); 833 /* Relocate `ps' pointers */ 834 for (i = 0; i < njobs; i++) 835 if (jp[i].ps == &jobtab[i].ps0) 836 jp[i].ps = &jp[i].ps0; 837 ckfree(jobtab); 838 jobtab = jp; 839 } 840 jp = jobtab + njobs; 841 for (i = 4 ; --i >= 0 ; ) 842 jobtab[njobs++].used = 0; 843 INTON; 844 break; 845 } 846 if (jp->used == 0) 847 break; 848 } 849 INTOFF; 850 jp->state = JOBRUNNING; 851 jp->used = 1; 852 jp->changed = 0; 853 jp->nprocs = 0; 854 #if JOBS 855 jp->jobctl = jobctl; 856 set_curjob(jp, 1); 857 #endif 858 if (nprocs > 1) { 859 jp->ps = ckmalloc(nprocs * sizeof (struct procstat)); 860 } else { 861 jp->ps = &jp->ps0; 862 } 863 INTON; 864 TRACE(("makejob(0x%lx, %d) returns %%%d\n", (long)node, nprocs, 865 jp - jobtab + 1)); 866 return jp; 867 } 868 869 870 /* 871 * Fork off a subshell. If we are doing job control, give the subshell its 872 * own process group. Jp is a job structure that the job is to be added to. 873 * N is the command that will be evaluated by the child. Both jp and n may 874 * be NULL. The mode parameter can be one of the following: 875 * FORK_FG - Fork off a foreground process. 876 * FORK_BG - Fork off a background process. 877 * FORK_NOJOB - Like FORK_FG, but don't give the process its own 878 * process group even if job control is on. 879 * 880 * When job control is turned off, background processes have their standard 881 * input redirected to /dev/null (except for the second and later processes 882 * in a pipeline). 883 */ 884 885 int 886 forkshell(struct job *jp, union node *n, int mode) 887 { 888 int pid; 889 890 TRACE(("forkshell(%%%d, %p, %d) called\n", jp - jobtab, n, mode)); 891 switch ((pid = fork())) { 892 case -1: 893 TRACE(("Fork failed, errno=%d\n", errno)); 894 INTON; 895 error("Cannot fork"); 896 break; 897 case 0: 898 forkchild(jp, n, mode, 0); 899 return 0; 900 default: 901 return forkparent(jp, n, mode, pid); 902 } 903 } 904 905 int 906 forkparent(struct job *jp, union node *n, int mode, pid_t pid) 907 { 908 int pgrp; 909 910 if (rootshell && mode != FORK_NOJOB && mflag) { 911 if (jp == NULL || jp->nprocs == 0) 912 pgrp = pid; 913 else 914 pgrp = jp->ps[0].pid; 915 #if JOBS /* LSC: not available under MINIX. */ 916 /* This can fail because we are doing it in the child also */ 917 (void)setpgid(pid, pgrp); 918 #endif 919 } 920 if (mode == FORK_BG) 921 backgndpid = pid; /* set $! */ 922 if (jp) { 923 struct procstat *ps = &jp->ps[jp->nprocs++]; 924 ps->pid = pid; 925 ps->status = -1; 926 ps->cmd[0] = 0; 927 if (/* iflag && rootshell && */ n) 928 commandtext(ps, n); 929 } 930 TRACE(("In parent shell: child = %d\n", pid)); 931 return pid; 932 } 933 934 void 935 forkchild(struct job *jp, union node *n, int mode, int vforked) 936 { 937 int wasroot; 938 #if JOBS /* LSC: for proper compilation with JOBS == 0 */ 939 int pgrp; 940 #endif 941 const char *devnull = _PATH_DEVNULL; 942 const char *nullerr = "Can't open %s"; 943 944 wasroot = rootshell; 945 TRACE(("Child shell %d\n", getpid())); 946 if (!vforked) 947 rootshell = 0; 948 949 closescript(vforked); 950 clear_traps(vforked); 951 #if JOBS 952 if (!vforked) 953 jobctl = 0; /* do job control only in root shell */ 954 if (wasroot && mode != FORK_NOJOB && mflag) { 955 if (jp == NULL || jp->nprocs == 0) 956 pgrp = getpid(); 957 else 958 pgrp = jp->ps[0].pid; 959 /* This can fail because we are doing it in the parent also */ 960 (void)setpgid(0, pgrp); 961 if (mode == FORK_FG) { 962 if (tcsetpgrp(ttyfd, pgrp) == -1) 963 error("Cannot set tty process group (%s) at %d", 964 strerror(errno), __LINE__); 965 } 966 setsignal(SIGTSTP, vforked); 967 setsignal(SIGTTOU, vforked); 968 } else if (mode == FORK_BG) { 969 ignoresig(SIGINT, vforked); 970 ignoresig(SIGQUIT, vforked); 971 if ((jp == NULL || jp->nprocs == 0) && 972 ! fd0_redirected_p ()) { 973 close(0); 974 if (open(devnull, O_RDONLY) != 0) 975 error(nullerr, devnull); 976 } 977 } 978 #else 979 if (mode == FORK_BG) { 980 ignoresig(SIGINT, vforked); 981 ignoresig(SIGQUIT, vforked); 982 if ((jp == NULL || jp->nprocs == 0) && 983 ! fd0_redirected_p ()) { 984 close(0); 985 if (open(devnull, O_RDONLY) != 0) 986 error(nullerr, devnull); 987 } 988 } 989 #endif 990 if (wasroot && iflag) { 991 setsignal(SIGINT, vforked); 992 setsignal(SIGQUIT, vforked); 993 setsignal(SIGTERM, vforked); 994 } 995 996 if (!vforked) 997 jobs_invalid = 1; 998 } 999 1000 /* 1001 * Wait for job to finish. 1002 * 1003 * Under job control we have the problem that while a child process is 1004 * running interrupts generated by the user are sent to the child but not 1005 * to the shell. This means that an infinite loop started by an inter- 1006 * active user may be hard to kill. With job control turned off, an 1007 * interactive user may place an interactive program inside a loop. If 1008 * the interactive program catches interrupts, the user doesn't want 1009 * these interrupts to also abort the loop. The approach we take here 1010 * is to have the shell ignore interrupt signals while waiting for a 1011 * forground process to terminate, and then send itself an interrupt 1012 * signal if the child process was terminated by an interrupt signal. 1013 * Unfortunately, some programs want to do a bit of cleanup and then 1014 * exit on interrupt; unless these processes terminate themselves by 1015 * sending a signal to themselves (instead of calling exit) they will 1016 * confuse this approach. 1017 */ 1018 1019 int 1020 waitforjob(struct job *jp) 1021 { 1022 #if JOBS 1023 int mypgrp = getpgrp(); 1024 #endif 1025 int status; 1026 int st; 1027 1028 INTOFF; 1029 TRACE(("waitforjob(%%%d) called\n", jp - jobtab + 1)); 1030 while (jp->state == JOBRUNNING) { 1031 dowait(WBLOCK, jp); 1032 } 1033 #if JOBS 1034 if (jp->jobctl) { 1035 if (tcsetpgrp(ttyfd, mypgrp) == -1) 1036 error("Cannot set tty process group (%s) at %d", 1037 strerror(errno), __LINE__); 1038 } 1039 if (jp->state == JOBSTOPPED && curjob != jp - jobtab) 1040 set_curjob(jp, 2); 1041 #endif 1042 status = jp->ps[jp->nprocs - 1].status; 1043 /* convert to 8 bits */ 1044 if (WIFEXITED(status)) 1045 st = WEXITSTATUS(status); 1046 #if JOBS 1047 else if (WIFSTOPPED(status)) 1048 st = WSTOPSIG(status) + 128; 1049 #endif 1050 else 1051 st = WTERMSIG(status) + 128; 1052 TRACE(("waitforjob: job %d, nproc %d, status %x, st %x\n", 1053 jp - jobtab + 1, jp->nprocs, status, st )); 1054 #if JOBS 1055 if (jp->jobctl) { 1056 /* 1057 * This is truly gross. 1058 * If we're doing job control, then we did a TIOCSPGRP which 1059 * caused us (the shell) to no longer be in the controlling 1060 * session -- so we wouldn't have seen any ^C/SIGINT. So, we 1061 * intuit from the subprocess exit status whether a SIGINT 1062 * occurred, and if so interrupt ourselves. Yuck. - mycroft 1063 */ 1064 if (WIFSIGNALED(status) && WTERMSIG(status) == SIGINT) 1065 raise(SIGINT); 1066 } 1067 #endif 1068 if (! JOBS || jp->state == JOBDONE) 1069 freejob(jp); 1070 INTON; 1071 return st; 1072 } 1073 1074 1075 1076 /* 1077 * Wait for a process to terminate. 1078 */ 1079 1080 STATIC int 1081 dowait(int flags, struct job *job) 1082 { 1083 int pid; 1084 int status; 1085 struct procstat *sp; 1086 struct job *jp; 1087 struct job *thisjob; 1088 int done; 1089 int stopped; 1090 extern volatile char gotsig[]; 1091 1092 TRACE(("dowait(%x) called\n", flags)); 1093 do { 1094 pid = waitproc(flags & WBLOCK, job, &status); 1095 TRACE(("wait returns pid %d, status %d\n", pid, status)); 1096 } while (pid == -1 && errno == EINTR && gotsig[SIGINT - 1] == 0); 1097 if (pid <= 0) 1098 return pid; 1099 INTOFF; 1100 thisjob = NULL; 1101 for (jp = jobtab ; jp < jobtab + njobs ; jp++) { 1102 if (jp->used) { 1103 done = 1; 1104 stopped = 1; 1105 for (sp = jp->ps ; sp < jp->ps + jp->nprocs ; sp++) { 1106 if (sp->pid == -1) 1107 continue; 1108 if (sp->pid == pid) { 1109 TRACE(("Job %d: changing status of proc %d from 0x%x to 0x%x\n", jp - jobtab + 1, pid, sp->status, status)); 1110 sp->status = status; 1111 thisjob = jp; 1112 } 1113 if (sp->status == -1) 1114 stopped = 0; 1115 else if (WIFSTOPPED(sp->status)) 1116 done = 0; 1117 } 1118 if (stopped) { /* stopped or done */ 1119 int state = done ? JOBDONE : JOBSTOPPED; 1120 if (jp->state != state) { 1121 TRACE(("Job %d: changing state from %d to %d\n", jp - jobtab + 1, jp->state, state)); 1122 jp->state = state; 1123 #if JOBS 1124 if (done) 1125 set_curjob(jp, 0); 1126 #endif 1127 } 1128 } 1129 } 1130 } 1131 1132 if (thisjob && thisjob->state != JOBRUNNING) { 1133 int mode = 0; 1134 if (!rootshell || !iflag) 1135 mode = SHOW_SIGNALLED; 1136 if ((job == thisjob && (flags & WNOFREE) == 0) || 1137 (job != thisjob && (flags & WNOFREE) != 0)) 1138 mode = SHOW_SIGNALLED | SHOW_NO_FREE; 1139 if (mode) 1140 showjob(out2, thisjob, mode); 1141 else { 1142 TRACE(("Not printing status, rootshell=%d, job=%p\n", 1143 rootshell, job)); 1144 thisjob->changed = 1; 1145 } 1146 } 1147 1148 INTON; 1149 return pid; 1150 } 1151 1152 1153 1154 /* 1155 * Do a wait system call. If job control is compiled in, we accept 1156 * stopped processes. If block is zero, we return a value of zero 1157 * rather than blocking. 1158 * 1159 * System V doesn't have a non-blocking wait system call. It does 1160 * have a SIGCLD signal that is sent to a process when one of its 1161 * children dies. The obvious way to use SIGCLD would be to install 1162 * a handler for SIGCLD which simply bumped a counter when a SIGCLD 1163 * was received, and have waitproc bump another counter when it got 1164 * the status of a process. Waitproc would then know that a wait 1165 * system call would not block if the two counters were different. 1166 * This approach doesn't work because if a process has children that 1167 * have not been waited for, System V will send it a SIGCLD when it 1168 * installs a signal handler for SIGCLD. What this means is that when 1169 * a child exits, the shell will be sent SIGCLD signals continuously 1170 * until is runs out of stack space, unless it does a wait call before 1171 * restoring the signal handler. The code below takes advantage of 1172 * this (mis)feature by installing a signal handler for SIGCLD and 1173 * then checking to see whether it was called. If there are any 1174 * children to be waited for, it will be. 1175 * 1176 * If neither SYSV nor BSD is defined, we don't implement nonblocking 1177 * waits at all. In this case, the user will not be informed when 1178 * a background process until the next time she runs a real program 1179 * (as opposed to running a builtin command or just typing return), 1180 * and the jobs command may give out of date information. 1181 */ 1182 1183 #ifdef SYSV 1184 STATIC int gotsigchild; 1185 1186 STATIC int onsigchild() { 1187 gotsigchild = 1; 1188 } 1189 #endif 1190 1191 1192 STATIC int 1193 waitproc(int block, struct job *jp, int *status) 1194 { 1195 #ifdef BSD 1196 int flags = 0; 1197 1198 #if JOBS 1199 if (jp != NULL && jp->jobctl) 1200 flags |= WUNTRACED; 1201 #endif 1202 if (block == 0) 1203 flags |= WNOHANG; 1204 return waitpid(-1, status, flags); 1205 #else 1206 #ifdef SYSV 1207 int (*save)(); 1208 1209 if (block == 0) { 1210 gotsigchild = 0; 1211 save = signal(SIGCLD, onsigchild); 1212 signal(SIGCLD, save); 1213 if (gotsigchild == 0) 1214 return 0; 1215 } 1216 return wait(status); 1217 #else 1218 if (block == 0) 1219 return 0; 1220 return wait(status); 1221 #endif 1222 #endif 1223 } 1224 1225 /* 1226 * return 1 if there are stopped jobs, otherwise 0 1227 */ 1228 int job_warning = 0; 1229 int 1230 stoppedjobs(void) 1231 { 1232 int jobno; 1233 struct job *jp; 1234 1235 if (job_warning || jobs_invalid) 1236 return (0); 1237 for (jobno = 1, jp = jobtab; jobno <= njobs; jobno++, jp++) { 1238 if (jp->used == 0) 1239 continue; 1240 if (jp->state == JOBSTOPPED) { 1241 out2str("You have stopped jobs.\n"); 1242 job_warning = 2; 1243 return (1); 1244 } 1245 } 1246 1247 return (0); 1248 } 1249 1250 /* 1251 * Return a string identifying a command (to be printed by the 1252 * jobs command). 1253 */ 1254 1255 STATIC char *cmdnextc; 1256 STATIC int cmdnleft; 1257 1258 void 1259 commandtext(struct procstat *ps, union node *n) 1260 { 1261 int len; 1262 1263 cmdnextc = ps->cmd; 1264 if (iflag || mflag || sizeof ps->cmd < 100) 1265 len = sizeof(ps->cmd); 1266 else 1267 len = sizeof(ps->cmd) / 10; 1268 cmdnleft = len; 1269 cmdtxt(n); 1270 if (cmdnleft <= 0) { 1271 char *p = ps->cmd + len - 4; 1272 p[0] = '.'; 1273 p[1] = '.'; 1274 p[2] = '.'; 1275 p[3] = 0; 1276 } else 1277 *cmdnextc = '\0'; 1278 TRACE(("commandtext: ps->cmd %x, end %x, left %d\n\t\"%s\"\n", 1279 ps->cmd, cmdnextc, cmdnleft, ps->cmd)); 1280 } 1281 1282 1283 STATIC void 1284 cmdtxt(union node *n) 1285 { 1286 union node *np; 1287 struct nodelist *lp; 1288 const char *p; 1289 int i; 1290 char s[2]; 1291 1292 if (n == NULL || cmdnleft <= 0) 1293 return; 1294 switch (n->type) { 1295 case NSEMI: 1296 cmdtxt(n->nbinary.ch1); 1297 cmdputs("; "); 1298 cmdtxt(n->nbinary.ch2); 1299 break; 1300 case NAND: 1301 cmdtxt(n->nbinary.ch1); 1302 cmdputs(" && "); 1303 cmdtxt(n->nbinary.ch2); 1304 break; 1305 case NOR: 1306 cmdtxt(n->nbinary.ch1); 1307 cmdputs(" || "); 1308 cmdtxt(n->nbinary.ch2); 1309 break; 1310 case NPIPE: 1311 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) { 1312 cmdtxt(lp->n); 1313 if (lp->next) 1314 cmdputs(" | "); 1315 } 1316 break; 1317 case NSUBSHELL: 1318 cmdputs("("); 1319 cmdtxt(n->nredir.n); 1320 cmdputs(")"); 1321 break; 1322 case NREDIR: 1323 case NBACKGND: 1324 cmdtxt(n->nredir.n); 1325 break; 1326 case NIF: 1327 cmdputs("if "); 1328 cmdtxt(n->nif.test); 1329 cmdputs("; then "); 1330 cmdtxt(n->nif.ifpart); 1331 if (n->nif.elsepart) { 1332 cmdputs("; else "); 1333 cmdtxt(n->nif.elsepart); 1334 } 1335 cmdputs("; fi"); 1336 break; 1337 case NWHILE: 1338 cmdputs("while "); 1339 goto until; 1340 case NUNTIL: 1341 cmdputs("until "); 1342 until: 1343 cmdtxt(n->nbinary.ch1); 1344 cmdputs("; do "); 1345 cmdtxt(n->nbinary.ch2); 1346 cmdputs("; done"); 1347 break; 1348 case NFOR: 1349 cmdputs("for "); 1350 cmdputs(n->nfor.var); 1351 cmdputs(" in "); 1352 cmdlist(n->nfor.args, 1); 1353 cmdputs("; do "); 1354 cmdtxt(n->nfor.body); 1355 cmdputs("; done"); 1356 break; 1357 case NCASE: 1358 cmdputs("case "); 1359 cmdputs(n->ncase.expr->narg.text); 1360 cmdputs(" in "); 1361 for (np = n->ncase.cases; np; np = np->nclist.next) { 1362 cmdtxt(np->nclist.pattern); 1363 cmdputs(") "); 1364 cmdtxt(np->nclist.body); 1365 cmdputs(";; "); 1366 } 1367 cmdputs("esac"); 1368 break; 1369 case NDEFUN: 1370 cmdputs(n->narg.text); 1371 cmdputs("() { ... }"); 1372 break; 1373 case NCMD: 1374 cmdlist(n->ncmd.args, 1); 1375 cmdlist(n->ncmd.redirect, 0); 1376 break; 1377 case NARG: 1378 cmdputs(n->narg.text); 1379 break; 1380 case NTO: 1381 p = ">"; i = 1; goto redir; 1382 case NCLOBBER: 1383 p = ">|"; i = 1; goto redir; 1384 case NAPPEND: 1385 p = ">>"; i = 1; goto redir; 1386 case NTOFD: 1387 p = ">&"; i = 1; goto redir; 1388 case NFROM: 1389 p = "<"; i = 0; goto redir; 1390 case NFROMFD: 1391 p = "<&"; i = 0; goto redir; 1392 case NFROMTO: 1393 p = "<>"; i = 0; goto redir; 1394 redir: 1395 if (n->nfile.fd != i) { 1396 s[0] = n->nfile.fd + '0'; 1397 s[1] = '\0'; 1398 cmdputs(s); 1399 } 1400 cmdputs(p); 1401 if (n->type == NTOFD || n->type == NFROMFD) { 1402 s[0] = n->ndup.dupfd + '0'; 1403 s[1] = '\0'; 1404 cmdputs(s); 1405 } else { 1406 cmdtxt(n->nfile.fname); 1407 } 1408 break; 1409 case NHERE: 1410 case NXHERE: 1411 cmdputs("<<..."); 1412 break; 1413 default: 1414 cmdputs("???"); 1415 break; 1416 } 1417 } 1418 1419 STATIC void 1420 cmdlist(union node *np, int sep) 1421 { 1422 for (; np; np = np->narg.next) { 1423 if (!sep) 1424 cmdputs(" "); 1425 cmdtxt(np); 1426 if (sep && np->narg.next) 1427 cmdputs(" "); 1428 } 1429 } 1430 1431 1432 STATIC void 1433 cmdputs(const char *s) 1434 { 1435 const char *p, *str = 0; 1436 char c, cc[2] = " "; 1437 char *nextc; 1438 int nleft; 1439 int subtype = 0; 1440 int quoted = 0; 1441 static char vstype[16][4] = { "", "}", "-", "+", "?", "=", 1442 "#", "##", "%", "%%" }; 1443 1444 p = s; 1445 nextc = cmdnextc; 1446 nleft = cmdnleft; 1447 while (nleft > 0 && (c = *p++) != 0) { 1448 switch (c) { 1449 case CTLESC: 1450 c = *p++; 1451 break; 1452 case CTLVAR: 1453 subtype = *p++; 1454 if ((subtype & VSTYPE) == VSLENGTH) 1455 str = "${#"; 1456 else 1457 str = "${"; 1458 if (!(subtype & VSQUOTE) != !(quoted & 1)) { 1459 quoted ^= 1; 1460 c = '"'; 1461 } else 1462 c = *str++; 1463 break; 1464 case CTLENDVAR: 1465 if (quoted & 1) { 1466 c = '"'; 1467 str = "}"; 1468 } else 1469 c = '}'; 1470 quoted >>= 1; 1471 subtype = 0; 1472 break; 1473 case CTLBACKQ: 1474 c = '$'; 1475 str = "(...)"; 1476 break; 1477 case CTLBACKQ+CTLQUOTE: 1478 c = '"'; 1479 str = "$(...)\""; 1480 break; 1481 case CTLARI: 1482 c = '$'; 1483 str = "(("; 1484 break; 1485 case CTLENDARI: 1486 c = ')'; 1487 str = ")"; 1488 break; 1489 case CTLQUOTEMARK: 1490 quoted ^= 1; 1491 c = '"'; 1492 break; 1493 case '=': 1494 if (subtype == 0) 1495 break; 1496 str = vstype[subtype & VSTYPE]; 1497 if (subtype & VSNUL) 1498 c = ':'; 1499 else 1500 c = *str++; 1501 if (c != '}') 1502 quoted <<= 1; 1503 break; 1504 case '\'': 1505 case '\\': 1506 case '"': 1507 case '$': 1508 /* These can only happen inside quotes */ 1509 cc[0] = c; 1510 str = cc; 1511 c = '\\'; 1512 break; 1513 default: 1514 break; 1515 } 1516 do { 1517 *nextc++ = c; 1518 } while (--nleft > 0 && str && (c = *str++)); 1519 str = 0; 1520 } 1521 if ((quoted & 1) && nleft) { 1522 *nextc++ = '"'; 1523 nleft--; 1524 } 1525 cmdnleft = nleft; 1526 cmdnextc = nextc; 1527 } 1528