1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 23 /* All Rights Reserved */ 24 25 26 /* 27 * Copyright (c) 1996, by Sun Microsystems, Inc. 28 * All rights reserved. 29 */ 30 31 #pragma ident "%Z%%M% %I% %E% SMI" 32 /* 33 * Job control for UNIX Shell 34 */ 35 36 #include <sys/termio.h> 37 #include <sys/types.h> 38 #include <sys/wait.h> 39 #include <sys/param.h> 40 #include <fcntl.h> 41 #include <errno.h> 42 #include "defs.h" 43 44 /* 45 * one of these for each active job 46 */ 47 48 struct job 49 { 50 struct job *j_nxtp; /* next job in job ID order */ 51 struct job *j_curp; /* next job in job currency order */ 52 struct termios j_stty; /* termio save area when job stops */ 53 pid_t j_pid; /* job leader's process ID */ 54 pid_t j_pgid; /* job's process group ID */ 55 pid_t j_tgid; /* job's foreground process group ID */ 56 uint j_jid; /* job ID */ 57 ushort j_xval; /* exit code, or exit or stop signal */ 58 ushort j_flag; /* various status flags defined below */ 59 char *j_pwd; /* job's working directory */ 60 char *j_cmd; /* cmd used to invoke this job */ 61 }; 62 63 /* defines for j_flag */ 64 65 #define J_DUMPED 0001 /* job has core dumped */ 66 #define J_NOTIFY 0002 /* job has changed status */ 67 #define J_SAVETTY 0004 /* job was stopped in foreground, and its */ 68 /* termio settings were saved */ 69 #define J_STOPPED 0010 /* job has been stopped */ 70 #define J_SIGNALED 0020 /* job has received signal; j_xval has it */ 71 #define J_DONE 0040 /* job has finished */ 72 #define J_RUNNING 0100 /* job is currently running */ 73 #define J_FOREGND 0200 /* job was put in foreground by shell */ 74 75 /* options to the printjob() function defined below */ 76 77 #define PR_CUR 00001 /* print job currency ('+', '-', or ' ') */ 78 #define PR_JID 00002 /* print job ID */ 79 #define PR_PGID 00004 /* print job's process group ID */ 80 #define PR_STAT 00010 /* print status obtained from wait */ 81 #define PR_CMD 00020 /* print cmd that invoked job */ 82 #define PR_AMP 00040 /* print a '&' if in the background */ 83 #define PR_PWD 00100 /* print jobs present working directory */ 84 85 #define PR_DFL (PR_CUR|PR_JID|PR_STAT|PR_CMD) /* default options */ 86 #define PR_LONG (PR_DFL|PR_PGID|PR_PWD) /* long options */ 87 88 static struct termios mystty; /* default termio settings */ 89 static int eofflg, 90 jobcnt, /* number of active jobs */ 91 jobdone, /* number of active but finished jobs */ 92 jobnote; /* jobs requiring notification */ 93 static pid_t svpgid, /* saved process group ID */ 94 svtgid; /* saved foreground process group ID */ 95 static struct job *jobcur, /* active jobs listed in currency order */ 96 **nextjob, 97 *thisjob, 98 *joblst; /* active jobs listed in job ID order */ 99 100 pid_t 101 tcgetpgrp(fd) 102 { 103 pid_t pgid; 104 if (ioctl(fd, TIOCGPGRP, &pgid) == 0) 105 return (pgid); 106 return ((pid_t)-1); 107 } 108 109 int 110 tcsetpgrp(fd, pgid) 111 int fd; 112 pid_t pgid; 113 { 114 return (ioctl(fd, TIOCSPGRP, &pgid)); 115 } 116 117 static struct job * 118 pgid2job(pgid) 119 register pid_t pgid; 120 { 121 register struct job *jp; 122 123 for (jp = joblst; jp != 0 && jp->j_pid != pgid; jp = jp->j_nxtp) 124 continue; 125 126 return (jp); 127 } 128 129 static struct job * 130 str2job(cmd, job, mustbejob) 131 register char *cmd; 132 register char *job; 133 int mustbejob; 134 { 135 register struct job *jp, *njp; 136 register i; 137 138 if (*job != '%') 139 jp = pgid2job(stoi(job)); 140 else if (*++job == 0 || *job == '+' || *job == '%' || *job == '-') { 141 jp = jobcur; 142 if (*job == '-' && jp) 143 jp = jp->j_curp; 144 } else if (*job >= '0' && *job <= '9') { 145 i = stoi(job); 146 for (jp = joblst; jp && jp->j_jid != i; jp = jp->j_nxtp) 147 continue; 148 } else if (*job == '?') { 149 register j; 150 register char *p; 151 i = strlen(++job); 152 jp = 0; 153 for (njp = jobcur; njp; njp = njp->j_curp) { 154 if (njp->j_jid == 0) 155 continue; 156 for (p = njp->j_cmd, j = strlen(p); j >= i; p++, j--) { 157 if (strncmp(job, p, i) == 0) { 158 if (jp != 0) 159 failed(cmd, ambiguous); 160 jp = njp; 161 break; 162 } 163 } 164 } 165 } else { 166 i = strlen(job); 167 jp = 0; 168 for (njp = jobcur; njp; njp = njp->j_curp) { 169 if (njp->j_jid == 0) 170 continue; 171 if (strncmp(job, njp->j_cmd, i) == 0) { 172 if (jp != 0) 173 failed(cmd, ambiguous); 174 jp = njp; 175 } 176 } 177 } 178 179 if (mustbejob && (jp == 0 || jp->j_jid == 0)) 180 failed(cmd, nosuchjob); 181 182 return (jp); 183 } 184 185 static void 186 freejob(jp) 187 register struct job *jp; 188 { 189 register struct job **njp; 190 register struct job **cjp; 191 192 for (njp = &joblst; *njp != jp; njp = &(*njp)->j_nxtp) 193 continue; 194 195 for (cjp = &jobcur; *cjp != jp; cjp = &(*cjp)->j_curp) 196 continue; 197 198 *njp = jp->j_nxtp; 199 *cjp = jp->j_curp; 200 free(jp); 201 jobcnt--; 202 jobdone--; 203 } 204 205 /* 206 * Collect the foreground job. 207 * Used in the case where the subshell wants 208 * to exit, but needs to wait until the fg job 209 * is done. 210 */ 211 collect_fg_job() 212 { 213 register struct job *jp; 214 register pid_t pid; 215 int stat; 216 217 for (jp = joblst; jp; jp = jp->j_nxtp) 218 if (jp->j_flag & J_FOREGND) 219 break; 220 221 if (!jp) 222 /* no foreground job */ 223 return; 224 225 /* 226 * Wait on fg job until wait succeeds 227 * or it fails due to no waitable children. 228 */ 229 230 while (1) { 231 errno = 0; 232 pid = waitpid(jp->j_pid, &stat, 0); 233 if (pid == jp->j_pid || (pid == -1 && errno == ECHILD)) 234 break; 235 } 236 } 237 238 /* 239 * analyze the status of a job 240 */ 241 242 static int 243 statjob(jp, stat, fg, rc) 244 register struct job *jp; 245 register stat; 246 int fg; 247 int rc; 248 { 249 pid_t tgid; 250 int done = 0; 251 252 if (WIFCONTINUED(stat)) { 253 if (jp->j_flag & J_STOPPED) { 254 jp->j_flag &= ~(J_STOPPED|J_SIGNALED|J_SAVETTY); 255 jp->j_flag |= J_RUNNING; 256 if (!fg && jp->j_jid) { 257 jp->j_flag |= J_NOTIFY; 258 jobnote++; 259 } 260 } 261 } else if (WIFSTOPPED(stat)) { 262 jp->j_xval = WSTOPSIG(stat); 263 jp->j_flag &= ~J_RUNNING; 264 jp->j_flag |= (J_SIGNALED|J_STOPPED); 265 jp->j_pgid = getpgid(jp->j_pid); 266 jp->j_tgid = jp->j_pgid; 267 if (fg) { 268 if (tgid = settgid(mypgid, jp->j_pgid)) 269 jp->j_tgid = tgid; 270 else { 271 jp->j_flag |= J_SAVETTY; 272 tcgetattr(0, &jp->j_stty); 273 (void) tcsetattr(0, TCSANOW, &mystty); 274 } 275 } 276 if (jp->j_jid) { 277 jp->j_flag |= J_NOTIFY; 278 jobnote++; 279 } 280 } else { 281 jp->j_flag &= ~J_RUNNING; 282 jp->j_flag |= J_DONE; 283 done++; 284 jobdone++; 285 if (WIFSIGNALED(stat)) { 286 jp->j_xval = WTERMSIG(stat); 287 jp->j_flag |= J_SIGNALED; 288 if (WCOREDUMP(stat)) 289 jp->j_flag |= J_DUMPED; 290 if (!fg || jp->j_xval != SIGINT) { 291 jp->j_flag |= J_NOTIFY; 292 jobnote++; 293 } 294 } else { /* WIFEXITED */ 295 jp->j_xval = WEXITSTATUS(stat); 296 jp->j_flag &= ~J_SIGNALED; 297 if (!fg && jp->j_jid) { 298 jp->j_flag |= J_NOTIFY; 299 jobnote++; 300 } 301 } 302 if (fg) { 303 if (!settgid(mypgid, jp->j_pgid) || 304 !settgid(mypgid, getpgid(jp->j_pid))) 305 tcgetattr(0, &mystty); 306 } 307 } 308 if (rc) { 309 exitval = jp->j_xval; 310 if (jp->j_flag & J_SIGNALED) 311 exitval |= SIGFLG; 312 exitset(); 313 } 314 if (done && !(jp->j_flag & J_NOTIFY)) 315 freejob(jp); 316 return (done); 317 } 318 319 /* 320 * collect the status of jobs that have recently exited or stopped - 321 * if wnohang == WNOHANG, wait until error, or all jobs are accounted for; 322 * 323 * called after each command is executed, with wnohang == 0, and as part 324 * of "wait" builtin with wnohang == WNOHANG 325 * 326 * We do not need to call chktrap here if waitpid(2) is called with 327 * wnohang == 0, because that only happens from syswait() which is called 328 * from builtin() where chktrap() is already called. 329 */ 330 331 static void 332 collectjobs(wnohang) 333 { 334 pid_t pid; 335 register struct job *jp; 336 int stat, n; 337 int wflags; 338 339 if ((flags & (monitorflg|jcflg|jcoff)) == (monitorflg|jcflg)) 340 wflags = WUNTRACED|WCONTINUED; 341 else 342 wflags = 0; 343 344 for (n = jobcnt - jobdone; n > 0; n--) { 345 if ((pid = waitpid(-1, &stat, wnohang|wflags)) <= 0) 346 break; 347 if (jp = pgid2job(pid)) 348 (void) statjob(jp, stat, 0, 0); 349 } 350 351 } 352 353 void 354 freejobs() 355 { 356 register struct job *jp; 357 358 collectjobs(WNOHANG); 359 360 if (jobnote) { 361 register int savefd = setb(2); 362 for (jp = joblst; jp; jp = jp->j_nxtp) { 363 if (jp->j_flag & J_NOTIFY) { 364 if (jp->j_jid) 365 printjob(jp, PR_DFL); 366 else if (jp->j_flag & J_FOREGND) 367 printjob(jp, PR_STAT); 368 else 369 printjob(jp, PR_STAT|PR_PGID); 370 } 371 } 372 (void) setb(savefd); 373 } 374 375 if (jobdone) { 376 for (jp = joblst; jp; jp = jp->j_nxtp) { 377 if (jp->j_flag & J_DONE) 378 freejob(jp); 379 } 380 } 381 } 382 383 static void 384 waitjob(jp) 385 register struct job *jp; 386 { 387 int stat; 388 int done; 389 pid_t pid = jp->j_pid; 390 int wflags; 391 int ret = 0; 392 int err = 0; 393 394 if ((flags & (monitorflg|jcflg|jcoff)) == (monitorflg|jcflg)) 395 wflags = WUNTRACED; 396 else 397 wflags = 0; 398 do { 399 errno = 0; 400 ret = waitpid(pid, &stat, wflags|WNOWAIT); 401 err = errno; 402 if (ret == -1 && err == ECHILD) { 403 stat = 0; 404 break; 405 } 406 } while (ret != pid); 407 408 done = statjob(jp, stat, 1, 1); 409 waitpid(pid, 0, wflags); 410 if (done && exitval && (flags & errflg)) 411 exitsh(exitval); 412 flags |= eflag; 413 } 414 415 /* 416 * modify the foreground process group to *new* only if the 417 * current foreground process group is equal to *expected* 418 */ 419 420 int 421 settgid(new, expected) 422 pid_t new, expected; 423 { 424 register pid_t current = tcgetpgrp(0); 425 426 if (current != expected) 427 return (current); 428 429 if (new != current) 430 tcsetpgrp(0, new); 431 432 return (0); 433 } 434 435 static void 436 restartjob(jp, fg) 437 register struct job *jp; 438 { 439 if (jp != jobcur) { 440 register struct job *t; 441 for (t = jobcur; t->j_curp != jp; t = t->j_curp); 442 t->j_curp = jp->j_curp; 443 jp->j_curp = jobcur; 444 jobcur = jp; 445 } 446 if (fg) { 447 if (jp->j_flag & J_SAVETTY) { 448 jp->j_stty.c_lflag &= ~TOSTOP; 449 jp->j_stty.c_lflag |= (mystty.c_lflag&TOSTOP); 450 jp->j_stty.c_cc[VSUSP] = mystty.c_cc[VSUSP]; 451 jp->j_stty.c_cc[VDSUSP] = mystty.c_cc[VDSUSP]; 452 (void) tcsetattr(0, TCSADRAIN, &jp->j_stty); 453 } 454 (void) settgid(jp->j_tgid, mypgid); 455 } 456 (void) kill(-(jp->j_pgid), SIGCONT); 457 if (jp->j_tgid != jp->j_pgid) 458 (void) kill(-(jp->j_tgid), SIGCONT); 459 jp->j_flag &= ~(J_STOPPED|J_SIGNALED|J_SAVETTY); 460 jp->j_flag |= J_RUNNING; 461 if (fg) { 462 jp->j_flag |= J_FOREGND; 463 printjob(jp, PR_JID|PR_CMD); 464 waitjob(jp); 465 } else { 466 jp->j_flag &= ~J_FOREGND; 467 printjob(jp, PR_JID|PR_CMD|PR_AMP); 468 } 469 } 470 471 static 472 printjob(jp, propts) 473 register struct job *jp; 474 { 475 int sp = 0; 476 477 if (jp->j_flag & J_NOTIFY) { 478 jobnote--; 479 jp->j_flag &= ~J_NOTIFY; 480 } 481 482 if (propts & PR_JID) { 483 prc_buff('['); 484 prn_buff(jp->j_jid); 485 prc_buff(']'); 486 sp = 1; 487 } 488 489 if (propts & PR_CUR) { 490 while (sp-- > 0) 491 prc_buff(SPACE); 492 sp = 1; 493 if (jobcur == jp) 494 prc_buff('+'); 495 else if (jobcur != 0 && jobcur->j_curp == jp) 496 prc_buff('-'); 497 else 498 sp++; 499 } 500 501 if (propts & PR_PGID) { 502 while (sp-- > 0) 503 prc_buff(SPACE); 504 prn_buff(jp->j_pid); 505 sp = 1; 506 } 507 508 if (propts & PR_STAT) { 509 while (sp-- > 0) 510 prc_buff(SPACE); 511 sp = 28; 512 if (jp->j_flag & J_SIGNALED) { 513 char *sigstr, *strsignal(); 514 if ((sigstr = strsignal(jp->j_xval)) != NULL) { 515 sp -= strlen(sigstr); 516 prs_buff(sigstr); 517 } else { 518 itos(jp->j_xval); 519 sp -= strlen(numbuf) + 7; 520 prs_buff("Signal "); 521 prs_buff(numbuf); 522 } 523 if (jp->j_flag & J_DUMPED) { 524 sp -= strlen(coredump); 525 prs_buff(coredump); 526 } 527 } else if (jp->j_flag & J_DONE) { 528 itos(jp->j_xval); 529 sp -= strlen(exited) + strlen(numbuf) + 2; 530 prs_buff(exited); 531 prc_buff('('); 532 itos(jp->j_xval); 533 prs_buff(numbuf); 534 prc_buff(')'); 535 } else { 536 sp -= strlen(running); 537 prs_buff(running); 538 } 539 if (sp < 1) 540 sp = 1; 541 } 542 543 if (propts & PR_CMD) { 544 while (sp-- > 0) 545 prc_buff(SPACE); 546 prs_buff(jp->j_cmd); 547 sp = 1; 548 } 549 550 if (propts & PR_AMP) { 551 while (sp-- > 0) 552 prc_buff(SPACE); 553 prc_buff('&'); 554 sp = 1; 555 } 556 557 if (propts & PR_PWD) { 558 while (sp-- > 0) 559 prc_buff(SPACE); 560 prs_buff("(wd: "); 561 prs_buff(jp->j_pwd); 562 prc_buff(')'); 563 } 564 565 prc_buff(NL); 566 flushb(); 567 568 } 569 570 571 /* 572 * called to initialize job control for each new input file to the shell, 573 * and after the "exec" builtin 574 */ 575 576 void 577 startjobs() 578 { 579 svpgid = mypgid; 580 581 if (tcgetattr(0, &mystty) == -1 || (svtgid = tcgetpgrp(0)) == -1) { 582 flags &= ~jcflg; 583 return; 584 } 585 586 flags |= jcflg; 587 588 handle(SIGTTOU, SIG_IGN); 589 handle(SIGTSTP, SIG_DFL); 590 591 if (mysid != mypgid) { 592 setpgid(0, 0); 593 mypgid = mypid; 594 (void) settgid(mypgid, svpgid); 595 } 596 597 } 598 599 int 600 endjobs(check_if) 601 int check_if; 602 { 603 if ((flags & (jcoff|jcflg)) != jcflg) 604 return (1); 605 606 if (check_if && jobcnt && eofflg++ == 0) { 607 register struct job *jp; 608 if (check_if & JOB_STOPPED) { 609 for (jp = joblst; jp; jp = jp->j_nxtp) { 610 if (jp->j_jid && (jp->j_flag & J_STOPPED)) { 611 prs(jobsstopped); 612 prc(NL); 613 return (0); 614 } 615 } 616 } 617 if (check_if & JOB_RUNNING) { 618 for (jp = joblst; jp; jp = jp->j_nxtp) { 619 if (jp->j_jid && (jp->j_flag & J_RUNNING)) { 620 prs(jobsrunning); 621 prc(NL); 622 return (0); 623 } 624 } 625 } 626 } 627 628 if (svpgid != mypgid) { 629 (void) settgid(svtgid, mypgid); 630 setpgid(0, svpgid); 631 } 632 633 return (1); 634 } 635 636 637 /* 638 * called by the shell to reserve a job slot for a job about to be spawned 639 */ 640 641 void 642 deallocjob() 643 { 644 free(thisjob); 645 jobcnt--; 646 } 647 648 allocjob(cmd, cwd, monitor) 649 register char *cmd; 650 register unchar *cwd; 651 int monitor; 652 { 653 register struct job *jp, **jpp; 654 register int jid, cmdlen, cwdlen; 655 656 cmdlen = strlen(cmd) + 1; 657 if (cmd[cmdlen-2] == '&') { 658 cmd[cmdlen-3] = 0; 659 cmdlen -= 2; 660 } 661 cwdlen = strlen(cwd) + 1; 662 jp = (struct job *) alloc(sizeof (struct job) + cmdlen + cwdlen); 663 if (jp == 0) 664 error(nostack); 665 jobcnt++; 666 jp->j_cmd = ((char *)jp) + sizeof (struct job); 667 strcpy(jp->j_cmd, cmd); 668 jp->j_pwd = jp->j_cmd + cmdlen; 669 strcpy(jp->j_pwd, cwd); 670 671 jpp = &joblst; 672 673 if (monitor) { 674 for (; *jpp; jpp = &(*jpp)->j_nxtp) 675 if ((*jpp)->j_jid != 0) 676 break; 677 for (jid = 1; *jpp; jpp = &(*jpp)->j_nxtp, jid++) 678 if ((*jpp)->j_jid != jid) 679 break; 680 } else 681 jid = 0; 682 683 jp->j_jid = jid; 684 nextjob = jpp; 685 thisjob = jp; 686 } 687 688 clearjobs() 689 { 690 register struct job *jp, *sjp; 691 692 for (jp = joblst; jp; jp = sjp) { 693 sjp = jp->j_nxtp; 694 free(jp); 695 } 696 joblst = NULL; 697 jobcnt = 0; 698 jobnote = 0; 699 jobdone = 0; 700 701 } 702 703 makejob(monitor, fg) 704 int monitor, fg; 705 { 706 if (monitor) { 707 mypgid = mypid; 708 setpgid(0, 0); 709 if (fg) 710 tcsetpgrp(0, mypid); 711 handle(SIGTTOU, SIG_DFL); 712 handle(SIGTSTP, SIG_DFL); 713 } else if (!fg) { 714 #ifdef NICE 715 nice(NICE); 716 #endif 717 handle(SIGTTIN, SIG_IGN); 718 handle(SIGINT, SIG_IGN); 719 handle(SIGQUIT, SIG_IGN); 720 if (!ioset) 721 renamef(chkopen(devnull, 0), 0); 722 } 723 } 724 725 /* 726 * called by the shell after job has been spawned, to fill in the 727 * job slot, and wait for the job if in the foreground 728 */ 729 730 void 731 postjob(pid, fg) 732 pid_t pid; 733 int fg; 734 { 735 736 register propts; 737 738 thisjob->j_nxtp = *nextjob; 739 *nextjob = thisjob; 740 thisjob->j_curp = jobcur; 741 jobcur = thisjob; 742 743 if (thisjob->j_jid) { 744 thisjob->j_pgid = pid; 745 propts = PR_JID|PR_PGID; 746 } else { 747 thisjob->j_pgid = mypgid; 748 propts = PR_PGID; 749 } 750 751 thisjob->j_flag = J_RUNNING; 752 thisjob->j_tgid = thisjob->j_pgid; 753 thisjob->j_pid = pid; 754 eofflg = 0; 755 756 if (fg) { 757 thisjob->j_flag |= J_FOREGND; 758 waitjob(thisjob); 759 } else { 760 if (flags & ttyflg) 761 printjob(thisjob, propts); 762 assnum(&pcsadr, (long)pid); 763 } 764 } 765 766 /* 767 * the builtin "jobs" command 768 */ 769 770 void 771 sysjobs(argc, argv) 772 int argc; 773 char *argv[]; 774 { 775 register char *cmd = *argv; 776 register struct job *jp; 777 register propts, c; 778 extern int opterr, i; 779 int savoptind = optind; 780 int loptind = -1; 781 int savopterr = opterr; 782 int savsp = _sp; 783 char *savoptarg = optarg; 784 optind = 1; 785 opterr = 0; 786 _sp = 1; 787 propts = 0; 788 789 if ((flags & jcflg) == 0) 790 failed(cmd, nojc); 791 792 while ((c = getopt(argc, argv, "lpx")) != -1) { 793 if (propts) { 794 failure(usage, jobsuse); 795 goto err; 796 } 797 switch (c) { 798 case 'x': 799 propts = -1; 800 break; 801 case 'p': 802 propts = PR_PGID; 803 break; 804 case 'l': 805 propts = PR_LONG; 806 break; 807 case '?': 808 failure(usage, jobsuse); 809 goto err; 810 } 811 } 812 813 loptind = optind; 814 err: 815 optind = savoptind; 816 optarg = savoptarg; 817 opterr = savopterr; 818 _sp = savsp; 819 if (loptind == -1) 820 return; 821 822 if (propts == -1) { 823 register unsigned char *bp; 824 register char *cp; 825 unsigned char *savebp; 826 for (savebp = bp = locstak(); loptind < argc; loptind++) { 827 cp = argv[loptind]; 828 if (*cp == '%') { 829 jp = str2job(cmd, cp, 1); 830 itos(jp->j_pid); 831 cp = (char *)numbuf; 832 } 833 while (*cp) { 834 if (bp >= brkend) 835 growstak(bp); 836 *bp++ = *cp++; 837 } 838 if (bp >= brkend) 839 growstak(bp); 840 *bp++ = SPACE; 841 } 842 endstak(bp); 843 execexp(savebp, 0); 844 return; 845 } 846 847 collectjobs(WNOHANG); 848 849 if (propts == 0) 850 propts = PR_DFL; 851 852 if (loptind == argc) { 853 for (jp = joblst; jp; jp = jp->j_nxtp) { 854 if (jp->j_jid) 855 printjob(jp, propts); 856 } 857 } else do 858 printjob(str2job(cmd, argv[loptind++], 1), propts); 859 while (loptind < argc); 860 861 } 862 863 /* 864 * the builtin "fg" and "bg" commands 865 */ 866 867 sysfgbg(argc, argv) 868 int argc; 869 char *argv[]; 870 { 871 register char *cmd = *argv; 872 register fg; 873 874 if ((flags & jcflg) == 0) 875 failed(cmd, nojc); 876 877 fg = eq("fg", cmd); 878 879 if (*++argv == 0) { 880 struct job *jp; 881 for (jp = jobcur; ; jp = jp->j_curp) { 882 if (jp == 0) 883 failed(cmd, nocurjob); 884 if (jp->j_jid) 885 break; 886 } 887 restartjob(jp, fg); 888 } 889 890 else do 891 restartjob(str2job(cmd, *argv, 1), fg); 892 while (*++argv); 893 894 } 895 896 /* 897 * the builtin "wait" commands 898 */ 899 900 void 901 syswait(argc, argv) 902 int argc; 903 char *argv[]; 904 { 905 register char *cmd = *argv; 906 register struct job *jp; 907 int stat; 908 int wflags; 909 910 if ((flags & (monitorflg|jcflg|jcoff)) == (monitorflg|jcflg)) 911 wflags = WUNTRACED; 912 else 913 wflags = 0; 914 915 if (argc == 1) 916 collectjobs(0); 917 else while (--argc) { 918 if ((jp = str2job(cmd, *++argv, 0)) == 0) 919 continue; 920 if (!(jp->j_flag & J_RUNNING)) 921 continue; 922 if (waitpid(jp->j_pid, &stat, wflags) <= 0) 923 break; 924 (void) statjob(jp, stat, 0, 1); 925 } 926 } 927 928 static 929 sigv(cmd, sig, args) 930 char *cmd; 931 int sig; 932 char *args; 933 { 934 int pgrp = 0; 935 int stopme = 0; 936 pid_t id; 937 938 if (*args == '%') { 939 register struct job *jp; 940 jp = str2job(cmd, args, 1); 941 id = jp->j_pgid; 942 pgrp++; 943 } else { 944 if (*args == '-') { 945 pgrp++; 946 args++; 947 } 948 id = 0; 949 do { 950 if (*args < '0' || *args > '9') { 951 failure(cmd, badid); 952 return; 953 } 954 id = (id * 10) + (*args - '0'); 955 } while (*++args); 956 if (id == 0) { 957 id = mypgid; 958 pgrp++; 959 } 960 } 961 962 if (sig == SIGSTOP) { 963 if (id == mysid || id == mypid && mypgid == mysid) { 964 failure(cmd, loginsh); 965 return; 966 } 967 if (id == mypgid && mypgid != svpgid) { 968 (void) settgid(svtgid, mypgid); 969 setpgid(0, svpgid); 970 stopme++; 971 } 972 } 973 974 if (pgrp) 975 id = -id; 976 977 if (kill(id, sig) < 0) { 978 979 switch (errno) { 980 case EPERM: 981 failure(cmd, eacces); 982 break; 983 984 case EINVAL: 985 failure(cmd, badsig); 986 break; 987 988 default: 989 if (pgrp) 990 failure(cmd, nosuchpgid); 991 else 992 failure(cmd, nosuchpid); 993 break; 994 } 995 996 } else if (sig == SIGTERM && pgrp) 997 (void) kill(id, SIGCONT); 998 999 if (stopme) { 1000 setpgid(0, mypgid); 1001 (void) settgid(mypgid, svpgid); 1002 } 1003 1004 } 1005 1006 sysstop(argc, argv) 1007 int argc; 1008 char *argv[]; 1009 { 1010 char *cmd = *argv; 1011 if (argc <= 1) 1012 failed(usage, stopuse); 1013 while (*++argv) 1014 sigv(cmd, SIGSTOP, *argv); 1015 } 1016 1017 syskill(argc, argv) 1018 int argc; 1019 char *argv[]; 1020 { 1021 char *cmd = *argv; 1022 int sig = SIGTERM; 1023 1024 if (argc == 1) { 1025 failure(usage, killuse); 1026 return; 1027 } 1028 1029 if (argv[1][0] == '-') { 1030 1031 if (argc == 2) { 1032 1033 register i; 1034 register cnt = 0; 1035 register char sep = 0; 1036 char buf[12]; 1037 1038 if (!eq(argv[1], "-l")) { 1039 failure(usage, killuse); 1040 return; 1041 } 1042 1043 for (i = 1; i < MAXTRAP; i++) { 1044 if (sig2str(i, buf) < 0) 1045 continue; 1046 if (sep) 1047 prc_buff(sep); 1048 prs_buff(buf); 1049 if ((flags & ttyflg) && (++cnt % 10)) 1050 sep = TAB; 1051 else 1052 sep = NL; 1053 } 1054 prc_buff(NL); 1055 return; 1056 } 1057 1058 if (str2sig(&argv[1][1], &sig)) { 1059 failure(cmd, badsig); 1060 return; 1061 } 1062 argv++; 1063 } 1064 1065 while (*++argv) 1066 sigv(cmd, sig, *argv); 1067 1068 } 1069 1070 syssusp(argc, argv) 1071 int argc; 1072 char *argv[]; 1073 { 1074 if (argc != 1) 1075 failed(argv[0], badopt); 1076 sigv(argv[0], SIGSTOP, "0"); 1077 } 1078