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