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