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