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