1 /* 2 3 * Copyright (c) 1984, 1985, 1986 AT&T 4 * All Rights Reserved 5 6 * THIS IS UNPUBLISHED PROPRIETARY SOURCE 7 * CODE OF AT&T. 8 * The copyright notice above does not 9 * evidence any actual or intended 10 * publication of such source code. 11 12 */ 13 /* @(#)jobs.c 1.1 */ 14 15 /* 16 * Job control for UNIX Shell 17 * 18 * David Korn 19 * AT&T Bell Laboratories 20 * Room 5D-112 21 * Murray Hill, N. J. 07974 22 * Tel. x7975 23 * 24 * Written October, 1982 25 */ 26 27 28 #include <errno.h> 29 30 #ifdef BSD 31 # ifdef BSD_4_2 32 #include <sys/wait.h> 33 # else 34 #include <wait.h> 35 # endif /* BSD_4_2 */ 36 #endif /* BSD */ 37 38 #ifdef SXT 39 #define SIGSTOP 20 40 #define SIGSTIN 21 41 #include <sys/types.h> 42 #include <sys/tty.h> 43 #include <sys/sxt.h> 44 #include <sys/stat.h> 45 #endif /* SXT */ 46 47 #include "defs.h" 48 #include "flags.h" 49 #include "shtype.h" 50 #include "jobs.h" 51 #include "brkincr.h" 52 #include "io.h" 53 #include "history.h" 54 55 #ifdef SXT 56 #undef input 57 static status_update(); 58 static int open_chan(); 59 static int fd_chan = -1; 60 static char tinybuf; 61 #endif /* SXT */ 62 63 #define LOBYTE 0377 64 #define MAXMSG 25 65 66 void await(); 67 void postclr(); 68 69 extern void fault(); 70 extern long hist_list(); 71 extern long hist_position(); 72 extern char *itos(); 73 extern char *malloc(); 74 extern void failed(); 75 extern void free(); 76 extern void p_str(); 77 extern void p_prp(); 78 extern void p_num(); 79 extern void p_sub(); 80 extern void p_nchr(); 81 extern void p_flush(); 82 extern void p_setout(); 83 84 static int set_ttygrp(); 85 static int set_job(); 86 static int reset_ttygrp(); 87 static struct process *next_proc(); 88 static struct process *jobbyname(); 89 static struct process *job_bynum(); 90 static struct process *job_bypid(); 91 static struct process *job_post(); 92 static struct process *unpost(); 93 static struct process *pgrp_jobs(); 94 static int get_job(); 95 static int match_jobname(); 96 static int unstop(); 97 static void free_job(); 98 static void pw_unlink(); 99 static struct process *freelist; 100 #define numrun jobstat.p_numrun /* number of running jobs */ 101 #define numpost jobstat.p_numpost /* number of posted jobs */ 102 #define pwlist jobstat.p_pwlist 103 #define freejobs jobstat.p_freejobs /* free job numbers */ 104 static long pr_jobname(); 105 106 #ifdef FIOLOOKLD 107 #define version8 1 108 extern int tty_ld, ntty_ld; 109 #define OTTYDISC tty_ld 110 #define NTTYDISC ntty_ld 111 #endif /* FIOLOOKLD */ 112 113 114 static int savepgrp; 115 static int savetgrp; 116 static BOOL old_driver; 117 static BOOL beenhere; 118 119 #ifdef BSD 120 static struct sgttyb my_stty; /* terminal state for shell */ 121 #else 122 static struct termio my_stty; /* terminal state for shell */ 123 #endif /* BSD */ 124 125 #ifdef BSD 126 /* 127 * initialize job control 128 * if lflag is set the switching driver message will not print 129 */ 130 131 int init_jobs(lflag) 132 { 133 int ldisc; 134 register int ntry = 0; 135 register int pid; 136 jobstat.mypid = pid = getpid(); 137 savepgrp = getpgrp(pid); 138 # ifdef version8 139 if((ldisc = ioctl (2, FIOLOOKLD, 0)) <0) 140 # else 141 if(ioctl(2,TIOCGETD,&ldisc) !=0) 142 # endif /* version8 */ 143 return(-1); 144 if(ldisc!=NTTYDISC && ldisc!=OTTYDISC) 145 { 146 /* no job control when running with MPX */ 147 # ifdef VSH 148 on_option(VIRAW); 149 # endif /* VSH */ 150 return(-1); 151 } 152 retry: 153 signal(SIGTTOU,SIG_IGN); 154 if(ioctl(2,TIOCGPGRP,&savetgrp) !=0) 155 { 156 fputs(j_not_tty,output); 157 return(-1); 158 } 159 /* This shell must be in foreground to change state */ 160 if(savetgrp != savepgrp) 161 { 162 signal(SIGTTOU,SIG_DFL); 163 kill(pid,SIGTTOU); 164 /* wait for continue and try again */ 165 if(ntry++ > 100) 166 { 167 fputs(j_no_start,output); 168 return(-1); 169 } 170 goto retry; 171 } 172 if(ldisc == OTTYDISC) 173 { 174 ldisc = NTTYDISC; 175 # ifdef version8 176 ioctl(2,TIOCGETP,&my_stty); 177 if (ioctl(2, FIOPOPLD, 0) < 0) 178 return(-1); 179 if (ioctl(2, FIOPUSHLD, &ldisc, 0) < 0) 180 { 181 ldisc = OTTYDISC; 182 ioctl(2, FIOPUSHLD, &ldisc, 0); 183 return(-1); 184 } 185 ioctl(2,TIOCSETN,&my_stty); 186 # else 187 if(ioctl(2,TIOCSETD,&ldisc) !=0) 188 return(-1); 189 # endif /* version8 */ 190 if(lflag==0) 191 { 192 fputs(j_newtty,output); 193 old_driver++; 194 } 195 } 196 on_option(MONITOR); 197 signal(SIGCHLD,fault); 198 signal(SIGTSTP,SIG_IGN); 199 signal(SIGTTIN,SIG_IGN); 200 setpgrp(pid,pid); 201 set_ttygrp(pid); 202 return(0); 203 } 204 205 206 /* 207 * see if there are any stopped jobs 208 * restore tty driver and pgrp 209 */ 210 211 int close_jobs() 212 { 213 register struct process *pw = pwlist; 214 register int count = 0; 215 int ldisc; 216 if((states&MONITOR)==0) 217 return(0); 218 for(;pw;pw=pw->p_next) 219 { 220 if((pw->p_flag&P_STOPPED)==0) 221 continue; 222 if(beenhere) 223 killpg(pw->p_pgrp,SIGTERM); 224 count++; 225 } 226 if(beenhere++ == 0 && pwlist) 227 { 228 if(count) 229 { 230 fputs(j_terminate,output); 231 return(-1); 232 } 233 else if(login_sh) 234 { 235 fputs(j_running,output); 236 return(-1); 237 } 238 } 239 set_ttygrp(savepgrp); 240 if(old_driver) 241 { 242 /* restore old line discipline */ 243 ldisc = OTTYDISC; 244 # ifdef version8 245 ioctl(2,TIOCGETP,&my_stty); 246 if (ioctl(2, FIOPOPLD, 0) < 0) 247 return(0); 248 if (ioctl(2, FIOPUSHLD, &ldisc, 0) < 0) 249 { 250 ldisc = NTTYDISC; 251 ioctl(2, FIOPUSHLD, &ldisc, 0); 252 return(0); 253 } 254 ioctl(2,TIOCSETN,&my_stty); 255 # else 256 if(ioctl(2,TIOCSETD,&ldisc) !=0) 257 return(0); 258 # endif /* version8 */ 259 fputs(j_oldtty,output); 260 } 261 return(0); 262 } 263 264 /* 265 * Set the ttygroup id to pid 266 */ 267 268 static int set_ttygrp(pid) 269 { 270 if(ioctl(2,TIOCSPGRP,&pid) !=0) 271 return(-1); 272 return(0); 273 } 274 275 /* 276 * Set the ttygroup id to a previously running job 277 */ 278 #else 279 # ifdef SXT 280 static char sxt[] = "/dev/sxt/000"; 281 static struct sxtblock status1,status2; 282 283 int init_jobs(lflag) 284 { 285 register int pid; 286 register int dev; 287 struct stat statbuf; 288 jobstat.mypid = pid = getpid(); 289 savepgrp = getpgrp(pid); 290 if(ioctl(2,SXTIOCSTAT,&status2) < 0) 291 return(-1); 292 if(ioctl(2,TCGETA,&my_stty) < 0) 293 return(-1); 294 if(fstat(2,&statbuf) < 0) 295 return(-1); 296 dev = statbuf.st_rdev&0xff; 297 /* must be channel 0 */ 298 if(dev&07) 299 return(-1); 300 dev >>= 3; 301 sxt[10] = '0' + (dev%10); 302 sxt[9] = '0' + dev/10; 303 my_stty.c_cc[VSWTCH] = CSWTCH; 304 if(ioctl(2,TCSETAF,&my_stty) < 0) 305 return(-1); 306 setpgrp(pid,pid); 307 jobstat.maxjob = MAXPCHAN; 308 on_option(MONITOR); 309 return(0); 310 } 311 #endif /* SXT */ 312 313 int close_jobs() 314 { 315 register struct process *pw = pwlist; 316 register int count = 0; 317 if((states&MONITOR)==0) 318 return(0); 319 # ifdef SXT 320 for(;pw;pw=pw->p_next) 321 { 322 if((pw->p_flag&P_STOPPED)==0) 323 continue; 324 if(beenhere) 325 kill(-pw->p_pgrp,SIGTERM); 326 count++; 327 } 328 # endif /* SXT */ 329 if(beenhere++ == 0 && pwlist && login_sh) 330 # ifdef SXT 331 { 332 if(count) 333 { 334 fputs(j_terminate,output); 335 return(-1); 336 } 337 if(login_sh || jobstat.maxjob) 338 # endif /* SXT */ 339 { 340 fputs(j_running,output); 341 return(-1); 342 } 343 # ifdef SXT 344 } 345 if(jobstat.maxjob) 346 kill_all(); 347 # endif /* SXT */ 348 return(0); 349 } 350 351 #endif /* BSD */ 352 353 static int set_job(pw) 354 register struct process *pw; 355 { 356 /* save current terminal state */ 357 #ifdef BSD 358 ioctl(2,TIOCGETP,&my_stty); 359 #else 360 ioctl(2,TCGETA,&my_stty); 361 #endif /* BSD */ 362 #ifdef SXT 363 /* make sure child has opened channel */ 364 if(jobstat.pipe[0] > 0) 365 { 366 read(jobstat.pipe[0],&tinybuf,1); 367 close(jobstat.pipe[0]); 368 jobstat.pipe[0] = 0; 369 } 370 if(pw->p_job < jobstat.maxjob) 371 if(ioctl(2,SXTIOCSWTCH,pw->p_job)!=0) 372 { 373 return(-1); 374 } 375 #endif /* SXT */ 376 if(pw->p_flag&P_STTY) 377 { 378 /* restore terminal state for job */ 379 #ifdef BSD 380 ioctl(2,TIOCSETN,&pw->p_stty); 381 #else 382 ioctl(2,TCSETAF,&pw->p_stty); 383 #endif /* BSD */ 384 } 385 #ifdef BSD 386 if(ioctl(2,TIOCSPGRP,&pw->p_pgrp) !=0) 387 return(-1); 388 #endif /* BSD */ 389 return(0); 390 } 391 392 static int reset_ttygrp(pw,flag) 393 register struct process *pw; 394 { 395 /* save the terminal state for current job */ 396 #ifdef BSD 397 if(ioctl(2,TIOCSPGRP,&jobstat.mypid) !=0) 398 { 399 return(-1); 400 } 401 #endif /* BSD */ 402 #ifdef SXT 403 if(pw && pw->p_job < jobstat.maxjob) 404 { 405 /* save the state of terminated process */ 406 if(flag==0 && fd_chan>=0) 407 { 408 if(ioctl(fd_chan,TCGETA,&pw->p_stty)==0) 409 { 410 my_stty = pw->p_stty; 411 /* for timing problem */ 412 ioctl(fd_chan,TCSETAW,&my_stty); 413 } 414 } 415 close(fd_chan); 416 fd_chan = -1; 417 /* grab control in channel 0 */ 418 ioctl(2,TCSETAW,&my_stty); 419 if(ioctl(2,SXTIOCSWTCH,0)!=0) 420 { 421 return(-1); 422 } 423 if(flag==0) 424 ioctl(2,TCSETAW,&my_stty); 425 beenhere = 0; 426 return(0); 427 } 428 #endif /* SXT */ 429 if(pw && flag) 430 { 431 #ifdef BSD 432 if(ioctl(2,TIOCGETP,&pw->p_stty) == 0) 433 #else 434 if(ioctl(2,TCGETA,&pw->p_stty) == 0) 435 #endif /* BSD */ 436 pw->p_flag |= P_STTY; 437 /* restore terminal state for job */ 438 #ifdef BSD 439 ioctl(2,TIOCSETN,&my_stty); 440 #else 441 ioctl(2,TCSETAF,&my_stty); 442 #endif /* BSD */ 443 } 444 beenhere = 0; 445 return(0); 446 } 447 448 #if BSD || SXT 449 450 /* 451 * move job to foreground if bgflag == 0 452 * move job to background if bgflag != 0 453 */ 454 455 switch_jobs(ajob,bgflag) 456 register char *ajob; 457 { 458 register struct process *pw=NULL; 459 register int pgrp; 460 # ifdef SXT 461 if(jobstat.maxjob==0) 462 return(NULL); 463 # endif /* SXT */ 464 if(*ajob) 465 pw = pgrp_jobs(ajob); 466 else if(pwlist) 467 pw = job_bynum((int)pwlist->p_job); 468 if(pw) 469 { 470 if(bgflag) 471 { 472 pgrp = pw->p_pgrp; 473 if(pw->p_flag&P_STOPPED) 474 { 475 p_sub((int)pw->p_job,'\t'); 476 pr_jobname(pw,'&',0L); 477 fputs(j_amp,output); 478 unstop(pgrp); 479 } 480 } 481 else 482 { 483 pw_unlink(pw); 484 pw->p_next = pwlist; 485 pwlist = pw; 486 pr_jobname(pw,'&',0L); 487 newline(); 488 await(pw->p_pid,3); 489 } 490 } 491 return(pw!=NULL); 492 } 493 494 /* 495 * list the current jobs 496 * flag L_FLAG for long listing 497 * flag N_FLAG for list only jobs marked for notification 498 */ 499 #endif /* BSD */ 500 501 list_jobs(flag) 502 int flag; 503 { 504 register struct process *pw; 505 register struct process *px; 506 register int m; 507 register struct process *py; 508 int n; 509 long offset; 510 int jobm = 0; 511 register char *msg; 512 int msize; 513 if(pwlist==NULL) 514 return; 515 await(0,2); 516 p_setout(standout); 517 /* get job number corresponding to '-' */ 518 if(pw=pgrp_jobs("%-")) 519 jobm = pw->p_job; 520 for(pw=pwlist;pw;pw=py) 521 { 522 py = pw->p_next; 523 if(pw->p_flag&P_PIPEJOB) 524 continue; 525 if((flag&N_FLAG) && (pw->p_flag&P_NOTIFY)==0) 526 continue; 527 n = pw->p_job; 528 p_sub(n,' '); 529 m = ' '; 530 if(pw->p_job==pwlist->p_job) 531 m = '+'; 532 else if(pw->p_job==jobm) 533 { 534 m = '-'; 535 jobm = 0; 536 } 537 putc(m,output); 538 putc(' ',output); 539 offset = 0; 540 if(flag&L_FLAG) 541 px = next_proc(pwlist,(int)pw->p_job); 542 else 543 px = pw; 544 do 545 { 546 unsigned xitval = 0; 547 if(flag&L_FLAG) 548 p_num(px->p_pid,'\t'); 549 if(px->p_sig&0177) 550 msg = sysmsg[px->p_sig&0177]; 551 else if(px->p_flag&P_NOTIFY) 552 { 553 msg = j_Done; 554 xitval = px->p_sig>>8; 555 } 556 else 557 msg = j_Running; 558 fputs(msg,output); 559 msize = strlen(msg); 560 if(xitval) 561 { 562 putc('(',output); 563 p_num((int)xitval,')'); 564 msize += (3+(xitval>10)+(xitval>100)); 565 } 566 if(px->p_flag&P_COREDUMP) 567 { 568 fputs(j_coredump,output); 569 msize += strlen(j_coredump); 570 } 571 p_nchr(SP,MAXMSG-msize); 572 if(flag&L_FLAG) 573 px = next_proc(px->p_next,(int)pw->p_job); 574 else 575 px = NULL; 576 offset = pr_jobname(pw,(px?'|':0),offset); 577 if(flag&L_FLAG) 578 { 579 if(px) 580 fputs(j_space,output); 581 else if(pw->p_pid == cpid) 582 fputs(j_cpid,output); 583 } 584 } 585 while(px); 586 if(pw->p_flag&P_STOPPED) 587 pw->p_flag &= ~P_NOTIFY; 588 else if(pw->p_flag&P_NOTIFY) 589 { 590 unpost(pw); 591 if(jobm && (px=pgrp_jobs("%-"))) 592 jobm = px->p_job; 593 } 594 } 595 } 596 597 /* 598 * return the pointer of next process with given job number after slot px 599 */ 600 601 static struct process * next_proc(pw,job) 602 register struct process *pw; 603 register int job; 604 { 605 for(;pw;pw=pw->p_next) 606 { 607 if(pw->p_job == job) 608 return(pw); 609 } 610 return(NULL); 611 } 612 613 /* 614 * print the command 615 * Stop the output if character <ch> encountered 616 */ 617 618 static long pr_jobname(pw,ch,offset) 619 register struct process *pw; 620 register long offset; 621 int ch; 622 { 623 if(fc_fix) 624 { 625 offset = hist_list(pw->p_name+offset,ch,";"); 626 offset -= pw->p_name; 627 } 628 return(++offset); 629 } 630 631 /* 632 * get the process group given the job number 633 * This routine returns the process group number or -1 634 */ 635 636 static struct process *pgrp_jobs(ajob) 637 register char *ajob; 638 { 639 register struct process *pw; 640 register int c; 641 if(*ajob++ != '%' || pwlist==NULL) 642 return(NULL); 643 c = *ajob; 644 if(isdigit(c)) 645 pw = job_bynum(atoi(ajob)); 646 else if(c=='+' || c=='%') 647 pw = job_bynum((int)pwlist->p_job); 648 else if(c=='-') 649 { 650 /* find the second jobnumber on the list */ 651 for(pw=pwlist->p_next;pw && pw->p_job==pwlist->p_job;pw=pw->p_next); 652 if(pw==NULL) 653 return(pw); 654 pw = job_bynum((int)pw->p_job); 655 } 656 else 657 pw = jobbyname(ajob); 658 if(pw && pw->p_flag) 659 return(pw); 660 return(NULL); 661 } 662 663 /* 664 * send a hang-up signal to each of the jobs 665 */ 666 int kill_all() 667 { 668 register struct process *pw = pwlist; 669 for(;pw;pw=pw->p_next) 670 { 671 if(pw->p_pgrp == pw->p_pid) 672 { 673 #ifdef BSD 674 unstop(pw->p_pgrp); 675 killpg(pw->p_pgrp,SIGHUP); 676 #else 677 kill(-pw->p_pgrp,SIGHUP); 678 #endif /* BSD */ 679 } 680 } 681 } 682 683 /* 684 * Kill a job or process 685 */ 686 687 int job_kill(job,sig) 688 register char *job; 689 int sig; 690 { 691 register char *rjob = job; 692 register struct process *pw; 693 register int pid; 694 register int r; 695 char *msg; 696 if(*rjob == '%') 697 { 698 if(pw=pgrp_jobs(rjob)) 699 { 700 #ifdef BSD 701 r = unstop(pw->p_pgrp); 702 if(sig!=SIGCONT || r < 0) 703 r = killpg(pw->p_pgrp,sig); 704 #else 705 pid = pw->p_pgrp; 706 if(states&MONITOR) 707 pid = -pid; 708 r = kill(pid,sig); 709 #endif /* BSD */ 710 } 711 else 712 { 713 r = -1; 714 errno = ESRCH; 715 } 716 } 717 else 718 { 719 pid = atoi(rjob); 720 if(pid==0 && *rjob != '0') 721 failed(bkill,kill_usage); 722 #ifdef BSD 723 if(sig==SIGSTOP && pid==jobstat.mypid && ppid==1) 724 { 725 /* can't stop login shell */ 726 errno = EPERM; 727 r = -1; 728 } 729 else 730 { 731 if((pw=job_bypid(pid)) && (pw->p_flag&P_STOPPED)) 732 { 733 pw->p_flag &= ~P_STOPPED; 734 numrun++; 735 kill(pid,SIGCONT); 736 } 737 r = kill(pid,sig); 738 } 739 #else 740 r = kill(pid,sig); 741 #endif /* BSD */ 742 } 743 if(r<0) 744 { 745 p_setout(stderr); 746 fputs(j_kill,output); 747 if(*rjob == '%') 748 msg = j_no_job; 749 else 750 msg = j_no_proc; 751 p_str(rjob,':'); 752 if(errno == EPERM) 753 msg = j_perm; 754 p_str(msg,NL); 755 r = 1; 756 } 757 return(r); 758 } 759 760 /* 761 * Get process structure from job number 762 */ 763 764 static struct process *job_bynum(num) 765 register int num; 766 { 767 register struct process *pw = pwlist; 768 for(;pw;pw=pw->p_next) 769 { 770 if((pw->p_flag&(P_PIPEJOB|P_WAITED)) == P_PIPEJOB) 771 continue; 772 if(pw->p_job == num) 773 return(pw); 774 } 775 return(NULL); 776 } 777 778 /* 779 * Get process structure from first letters of jobname 780 * 781 */ 782 783 static struct process *jobbyname(name) 784 char *name; 785 { 786 register struct process *pw = pwlist; 787 register struct fixcmd *fp = fc_fix; 788 if(fp==NULL) 789 return(NULL); 790 for(;pw;pw=pw->p_next) 791 { 792 if((pw->p_flag&(P_PIPEJOB|P_WAITED)) == P_PIPEJOB) 793 continue; 794 if(match_jobname(fp->fixfd,pw,name)) 795 goto retrn; 796 } 797 pw = NULL; 798 retrn: 799 return(pw); 800 } 801 802 803 /* 804 * match the name to the command starting with given name 805 */ 806 807 static int match_jobname(fdi,pw,name) 808 FILE *fdi; 809 register struct process *pw; 810 char *name; 811 { 812 register int c; 813 register char *sp; 814 if(fdi && pw->p_name>0) 815 { 816 fseek(fdi,pw->p_name,0); 817 for(sp=name;*sp;sp++) 818 { 819 c = getc(fdi); 820 if(c != *sp) 821 return(0); 822 } 823 return(1); 824 } 825 return(0); 826 } 827 828 829 830 /* 831 * Initialize the process posting array 832 */ 833 834 void postclr() 835 { 836 register struct process *pw = pwlist; 837 register struct process *px; 838 register int j = JBYTES; 839 for(;pw;pw=px) 840 { 841 px = pw->p_next; 842 free((char*)pw); 843 } 844 pwlist = NULL; 845 numpost=0; 846 numrun = 0; 847 while(--j >=0) 848 freejobs[j] = 0; 849 } 850 851 /* 852 * put the process <pcsid> on the process list and return the job number 853 * turn on the specified flag bits. 854 */ 855 856 int post(pid,flag) 857 int pid; 858 { 859 register struct process *pw; 860 if(pw=job_post(pid)) 861 { 862 pw->p_flag |= flag; 863 return(pw->p_job); 864 } 865 return(-1); 866 } 867 868 /* 869 * internal version of post, this routine returns a process structure 870 */ 871 872 static struct process *job_post(pcsid) 873 int pcsid; 874 { 875 register struct process *pw = pwlist; 876 register struct process *px=NULL; 877 register struct fixcmd *fp = fc_fix; 878 if(pcsid) 879 { 880 for(;pw;pw=pw->p_next) 881 { 882 if(pw->p_pid==pcsid) 883 return(pw); 884 if(pw->p_pgrp == jobstat.cur_pgrp) 885 px = pw; 886 } 887 if(pw=freelist) 888 freelist = pw->p_next; 889 else if((pw=(struct process*)malloc(sizeof(struct process)))==NULL) 890 error(nospace); 891 numrun++; 892 numpost++; 893 if(px) 894 { 895 pw->p_next = px->p_next; 896 px->p_next = pw; 897 pw->p_job = px->p_job; 898 } 899 else 900 { 901 /* put at front of list */ 902 pw->p_next = pwlist; 903 pw->p_job = get_job(); 904 pwlist = pw; 905 } 906 pw->p_pid = pcsid; 907 pw->p_flag = P_RUNNING; 908 pw->p_pgrp = jobstat.cur_pgrp; 909 if(fp!=NULL) 910 pw->p_name=hist_position(fp->fixind-1); 911 else 912 pw->p_name = -1; 913 pw->p_sig = 0; 914 if(numpost >= MAXJ-1) 915 await(0,0); 916 return(pw); 917 } 918 return(NULL); 919 } 920 921 /* 922 * get job number given the process id 923 */ 924 925 static struct process *job_bypid(pid) 926 register int pid; 927 { 928 register struct process *pw; 929 if(pid==0) 930 return(NULL); 931 for(pw=pwlist;pw;pw=pw->p_next) 932 if(pw->p_pid == pid) 933 break; 934 return(pw); 935 } 936 937 /* 938 * Wait for process i to complete 939 * flag=1 when wait builtin invoked so that it can be interrupted 940 * flag=2 to check for waiting processes and return 941 * flag=3 to resume job in foreground 942 * i=0 to wait for any process 943 * i=-1 to wait for all runing processes 944 */ 945 946 void await(i, flag) 947 register int i; 948 int flag; 949 { 950 int rc=0; 951 int w; 952 int my_job = -1; 953 #ifdef BSD 954 union wait wstat; 955 #endif /* BSD */ 956 register struct process *pw = NULL; 957 struct process *px; 958 if(i!= -1 && i) 959 { 960 if(flag) 961 { 962 pw = job_bypid(i); 963 if(flag==3 && pw) 964 flag = 0; 965 } 966 else 967 pw = job_post(i); 968 if(flag) 969 { 970 if(pw==0 || (pw->p_flag&P_STOPPED)) 971 return; 972 } 973 my_job = pw->p_job; 974 } 975 if(flag==0 && (states&MONITOR) && pw) 976 { 977 set_job(pw); 978 /* if job is stopped, resume it in the background */ 979 #if BSD || SXT 980 if(pw->p_flag&P_STOPPED) 981 unstop(pw->p_pgrp); 982 # ifdef SXT 983 if(pw->p_job < jobstat.maxjob) 984 open_chan(pw->p_job); 985 # endif /* SXT */ 986 #endif /* BSD */ 987 } 988 p_flush(); 989 while(numrun>0) 990 { 991 register int p; 992 register int sig; 993 register int w_hi; 994 #ifdef BSD 995 if(is_option(MONITOR) || flag==2) 996 { 997 retry: 998 errno = 0; 999 sig = sighold(SIGCHLD); 1000 trapnote &= ~SIGJOBS; 1001 p=wait3(&wstat,WNOHANG|WUNTRACED,0); 1002 errno = 0; 1003 if(p==0 && flag!=2) 1004 { 1005 # ifdef BSD_4_2 1006 sigpause(sig&~(1<<(SIGCHLD-1))); 1007 # else 1008 sigpause(SIGCHLD); 1009 # endif /* BSD_4_2 */ 1010 if(errno==EINTR && flag==1 && (trapnote&SIGJOBS)==0) 1011 break; 1012 goto retry; 1013 } 1014 trapnote &= ~SIGJOBS; 1015 sigrelse(SIGCHLD); 1016 if(p==0 || p== -1) 1017 return; 1018 w = wstat.w_status; 1019 pw = job_bypid(p); 1020 if(pw->p_job == my_job && (states&MONITOR)) 1021 { 1022 register int ssig = wstat.w_S.w_Stopsig; 1023 if(WIFSTOPPED(wstat) && (ssig==SIGTTIN||ssig==SIGTTOU)) 1024 { 1025 /* job stopped before it got terminal */ 1026 killpg(pw->p_pgrp,SIGCONT); 1027 continue; 1028 } 1029 if(p==i) 1030 reset_ttygrp(pw,w&LOBYTE); 1031 } 1032 } 1033 else 1034 #endif /* BSD */ 1035 { 1036 #ifndef BSD 1037 # ifdef SXT 1038 if(jobstat.maxjob >0) 1039 { 1040 /* check for job status change */ 1041 status1 = status2; 1042 status2.input = status2.output = 0; 1043 if(ioctl(2,SXTIOCSTAT,&status2)!=0) 1044 { 1045 jobstat.maxjob = 0; 1046 } 1047 else if(status1.input != status2.input) 1048 { 1049 status_update(status2.input,status1.input,SIGSTIN); 1050 } 1051 else if(status1.output != status2.output) 1052 { 1053 status_update(status2.output,status1.output,SIGSTOP); 1054 } 1055 } 1056 # endif /* SXT */ 1057 /* enable fault handler to see if there are any pending jobs */ 1058 if((trapnote&SIGJOBS)==0) 1059 signal(SIGCLD,fault); 1060 if(flag==2 && (trapnote&SIGJOBS)==0) 1061 return; 1062 # ifdef SXT 1063 if(my_job>=0 && (trapnote&SIGJOBS)==0 && jobstat.maxjob) 1064 { 1065 errno = 0; 1066 p = ioctl(2, SXTIOCWF, 0); 1067 if(p==0) 1068 /* job stopped */ 1069 { 1070 ioctl(2, SXTIOCBLK, my_job); 1071 if(fd_chan>=0) 1072 { 1073 if(ioctl(fd_chan,TCFLSH,2)!=0) 1074 { 1075 ; 1076 } 1077 } 1078 pw->p_flag |= (P_NOTIFY|P_STOPPED); 1079 pw->p_sig = SIGSTOP; 1080 reset_ttygrp(pw,1); 1081 break; 1082 } 1083 } 1084 # endif /* SXT */ 1085 #endif /* BSD */ 1086 trapnote &= ~ SIGJOBS; 1087 p=wait(&w); 1088 if(p== -1) 1089 { 1090 if(errno==ECHILD) 1091 { 1092 postclr(); 1093 return; 1094 } 1095 else if(errno==EINTR) 1096 { 1097 if(trapnote&SIGJOBS) 1098 continue; 1099 if(flag) 1100 break; 1101 } 1102 continue; 1103 } 1104 trapnote &= ~ SIGJOBS; 1105 pw = job_bypid(p); 1106 #ifdef SXT 1107 pw->p_flag &= ~P_STOPPED; 1108 #endif /* SXT */ 1109 /* restore original tty state if jobs aborted */ 1110 if(p == i && (states&MONITOR)) 1111 reset_ttygrp(pw,w&LOBYTE); 1112 } 1113 if(pw) 1114 { 1115 numrun--; 1116 pw->p_flag |= P_NOTIFY; 1117 #ifdef BSD 1118 if((states&MONITOR) && WIFSTOPPED(wstat)) 1119 pw->p_flag |= P_STOPPED; 1120 else 1121 #endif /* BSD */ 1122 { 1123 if(p==cpid) 1124 { 1125 cpid = 0; 1126 cpipe[1] = NULL; 1127 } 1128 if(p==i || (states&MONITOR)==0) 1129 { 1130 if(px=unpost(pw)) 1131 { 1132 if(i) 1133 { 1134 if(p==i && (states&MONITOR)) 1135 set_job(px); 1136 i = px->p_pid; 1137 } 1138 continue; 1139 } 1140 } 1141 } 1142 } 1143 sig = w&0177; 1144 if(states&MONITOR) 1145 { 1146 #ifdef BSD 1147 if(WIFSTOPPED(wstat)) 1148 { 1149 if(pw) 1150 pw->p_sig = wstat.w_S.w_Stopsig; 1151 if(p == i) 1152 break; 1153 continue; 1154 } 1155 else if(p!=i) 1156 #else 1157 if(p!=i) 1158 #endif /* BSD */ 1159 { 1160 if(pw) 1161 pw->p_sig = w; 1162 if(w&HIGHBIT) 1163 pw->p_flag |= P_COREDUMP; 1164 continue; 1165 } 1166 /* this is needed since child not in same process group */ 1167 else if(sig==SIGINT || sig==SIGQUIT || sig==SIGHUP) 1168 fault(sig); 1169 } 1170 w_hi = (w>>8)&LOBYTE; 1171 if(sig) 1172 { 1173 if(sig == 0177 /* ptrace! return */) 1174 { 1175 fputs(ptrace,output); 1176 sig = w_hi; 1177 } 1178 if(sig!=SIGINT && sig!=SIGPIPE) 1179 { 1180 if(i!=p || (states&PROMPT)==0) 1181 p_prp(itos(p),SP); 1182 fputs(sysmsg[sig],output); 1183 if(w&HIGHBIT) 1184 fputs(coredump,output); 1185 } 1186 newline(); 1187 } 1188 if(p == i) 1189 { 1190 rc = (sig ? sig|SIGFAIL : w_hi); 1191 break; 1192 } 1193 if(i == 0) 1194 break; 1195 } 1196 if(flag>=2) 1197 return; 1198 exitval=rc; 1199 exitset(); 1200 } 1201 1202 #if BSD || SXT 1203 /* 1204 * turn off STOP state of a process group 1205 */ 1206 1207 static int unstop(grp) 1208 register int grp; 1209 { 1210 register struct process *pw; 1211 register int num = numrun; 1212 for(pw=pwlist;pw;pw=pw->p_next) 1213 { 1214 if(pw->p_pgrp != grp) 1215 continue; 1216 if(pw->p_flag&P_STOPPED) 1217 { 1218 num++; 1219 pw->p_flag &= ~P_STOPPED; 1220 pw->p_sig = 0; 1221 # ifdef SXT 1222 break; 1223 # endif /* SXT */ 1224 } 1225 } 1226 if(num!=numrun) 1227 { 1228 p_flush(); 1229 #ifdef BSD 1230 numrun = num; 1231 return(killpg(grp,SIGCONT)); 1232 #endif 1233 } 1234 return(-1); 1235 } 1236 #endif /* BSD */ 1237 1238 /* 1239 * remove a process group from table 1240 * If all the processes have not completed then unpost returns 1241 * the structure pointer of an unfinished process. 1242 * Otherwise NULL is returned. 1243 */ 1244 1245 static struct process *unpost(pwtop) 1246 struct process *pwtop; 1247 { 1248 register struct process *pw; 1249 register struct process *px=NULL; 1250 register int job = pwtop->p_job; 1251 register struct process *py; 1252 /* look for unfinished processes */ 1253 for(pw=pwlist;pw;pw=pw->p_next) 1254 { 1255 if(pw->p_job != job) 1256 continue; 1257 if((pw->p_flag&P_NOTIFY)==0) 1258 px = pw; 1259 } 1260 if(px) 1261 { 1262 px->p_flag &= ~P_PIPEJOB; 1263 px->p_flag |= P_WAITED; 1264 return(px); 1265 } 1266 /* all processes complete, unpost job */ 1267 for(pw=pwlist;pw;pw=py) 1268 { 1269 py = pw->p_next; 1270 if(pw->p_job != job) 1271 { 1272 px = pw; 1273 continue; 1274 } 1275 numpost--; 1276 if(px==NULL) 1277 pwlist = py; 1278 else 1279 px->p_next = py; 1280 pw->p_next = freelist; 1281 freelist = pw; 1282 } 1283 free_job((int)pwtop->p_job); 1284 return(NULL); 1285 } 1286 1287 /* 1288 * unlink a process form the process list 1289 */ 1290 1291 static void pw_unlink(pw) 1292 register struct process *pw; 1293 { 1294 register struct process *px; 1295 if(pw==pwlist) 1296 { 1297 pwlist = pw->p_next; 1298 return; 1299 } 1300 for(px=pwlist;px;px=px->p_next) 1301 if(px->p_next == pw) 1302 { 1303 px->p_next = pw->p_next; 1304 return; 1305 } 1306 } 1307 1308 /* 1309 * get an unused job number 1310 * freejobs is a bit vector, 0 is unused 1311 */ 1312 1313 static int get_job() 1314 { 1315 register int j=0; 1316 register unsigned mask = 1; 1317 register unsigned char *freeword; 1318 /* skip to first word with a free slot */ 1319 while(freejobs[j] == 0xff) 1320 j++; 1321 freeword = &freejobs[j]; 1322 j *= 8; 1323 for(j++;mask&(*freeword);j++,mask <<=1); 1324 *freeword |=mask; 1325 return(j); 1326 } 1327 1328 /* 1329 * return a job number 1330 */ 1331 1332 static void free_job(n) 1333 register int n; 1334 { 1335 register int j = (--n)/8; 1336 register unsigned mask; 1337 n -= j*8; 1338 mask = 1 << n; 1339 freejobs[j] &= ~mask; 1340 } 1341 1342 #ifdef SXT 1343 /* 1344 * open up the input streams for a new channel 1345 */ 1346 1347 static char *open_mode[3] = {"r","w","w+"}; 1348 j_new_chan() 1349 { 1350 register FILE* fd; 1351 register int i; 1352 sxt[11] = '0' + jobstat.cur_job; 1353 close(jobstat.pipe[0]); 1354 fd = fopen(sxt,"r+"); 1355 if(ioctl(fileno(fd),TCSETA,&my_stty)<0 || fd==NULL) 1356 { 1357 close(jobstat.pipe[1]); 1358 return(0); 1359 } 1360 for(i=0;i<3;i++) 1361 { 1362 if(isatty(i)) 1363 { 1364 fclose(file_fd(i)); 1365 fdopen(dup(fileno(fd)),open_mode[i]); 1366 } 1367 } 1368 fclose(fd); 1369 write(jobstat.pipe[1],nullstr,1); 1370 close(jobstat.pipe[1]); 1371 return(1); 1372 } 1373 1374 int next_job() 1375 { 1376 register int i = get_job(); 1377 free_job(i); 1378 return(i); 1379 } 1380 1381 static status_update(mask2,mask1,sigval) 1382 { 1383 register int i,j; 1384 register struct process *pw; 1385 for(i = 1; i < MAXPCHAN; i++) 1386 { 1387 j = 1<<i; 1388 if((mask1&j)==0 && (mask2&j)) 1389 { 1390 if(pw = job_bynum(i)) 1391 pw->p_sig = sigval; 1392 } 1393 else if((mask2&j)==0 && (mask1&j)) 1394 { 1395 if(pw = job_bynum(i)) 1396 pw->p_sig = 0; 1397 } 1398 } 1399 } 1400 1401 static int open_chan(j) 1402 { 1403 sxt[11] = '0' + j; 1404 if(fd_chan>=0) 1405 { 1406 return; 1407 } 1408 fd_chan = open(sxt,2); 1409 } 1410 #endif /* SXT */ 1411 1412