1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1982-2010 AT&T Intellectual Property * 5 * and is licensed under the * 6 * Common Public License, Version 1.0 * 7 * by AT&T Intellectual Property * 8 * * 9 * A copy of the License is available at * 10 * http://www.opensource.org/licenses/cpl1.0.txt * 11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 12 * * 13 * Information and Software Systems Research * 14 * AT&T Research * 15 * Florham Park NJ * 16 * * 17 * David Korn <dgk@research.att.com> * 18 * * 19 ***********************************************************************/ 20 #pragma prototyped 21 /* 22 * Job control for UNIX Shell 23 * 24 * David Korn 25 * AT&T Labs 26 * 27 * Written October, 1982 28 * Rewritten April, 1988 29 * Revised January, 1992 30 */ 31 32 #include "defs.h" 33 #include <wait.h> 34 #include "io.h" 35 #include "jobs.h" 36 #include "history.h" 37 38 #if !defined(WCONTINUED) || !defined(WIFCONTINUED) 39 # undef WCONTINUED 40 # define WCONTINUED 0 41 # undef WIFCONTINUED 42 # define WIFCONTINUED(wstat) (0) 43 #endif 44 45 #define NJOB_SAVELIST 4 46 47 /* 48 * temporary hack to get W* macros to work 49 */ 50 #undef wait 51 #define wait ______wait 52 /* 53 * This struct saves a link list of processes that have non-zero exit 54 * status, have had $! saved, but haven't been waited for 55 */ 56 struct jobsave 57 { 58 struct jobsave *next; 59 pid_t pid; 60 unsigned short exitval; 61 }; 62 63 static struct jobsave *job_savelist; 64 static int njob_savelist; 65 static struct process *pwfg; 66 67 static void init_savelist(void) 68 { 69 register struct jobsave *jp; 70 while(njob_savelist < NJOB_SAVELIST) 71 { 72 jp = newof(0,struct jobsave,1,0); 73 jp->next = job_savelist; 74 job_savelist = jp; 75 njob_savelist++; 76 } 77 } 78 79 struct back_save 80 { 81 int count; 82 struct jobsave *list; 83 }; 84 85 #define BYTE(n) (((n)+CHAR_BIT-1)/CHAR_BIT) 86 #define MAXMSG 25 87 #define SH_STOPSIG (SH_EXITSIG<<1) 88 89 #ifdef VSUSP 90 # ifndef CNSUSP 91 # ifdef _POSIX_VDISABLE 92 # define CNSUSP _POSIX_VDISABLE 93 # else 94 # define CNSUSP 0 95 # endif /* _POSIX_VDISABLE */ 96 # endif /* CNSUSP */ 97 # ifndef CSWTCH 98 # ifdef CSUSP 99 # define CSWTCH CSUSP 100 # else 101 # define CSWTCH ('z'&037) 102 # endif /* CSUSP */ 103 # endif /* CSWTCH */ 104 #endif /* VSUSP */ 105 106 /* Process states */ 107 #define P_EXITSAVE 01 108 #define P_STOPPED 02 109 #define P_NOTIFY 04 110 #define P_SIGNALLED 010 111 #define P_STTY 020 112 #define P_DONE 040 113 #define P_COREDUMP 0100 114 #define P_DISOWN 0200 115 #define P_FG 0400 116 #ifdef SHOPT_BGX 117 #define P_BG 01000 118 #endif /* SHOPT_BGX */ 119 120 static int job_chksave(pid_t); 121 static struct process *job_bypid(pid_t); 122 static struct process *job_byjid(int); 123 static char *job_sigmsg(int); 124 static int job_alloc(void); 125 static void job_free(int); 126 static struct process *job_unpost(struct process*,int); 127 static void job_unlink(struct process*); 128 static void job_prmsg(struct process*); 129 static struct process *freelist; 130 static char beenhere; 131 static char possible; 132 static struct process dummy; 133 static char by_number; 134 static Sfio_t *outfile; 135 static pid_t lastpid; 136 static struct back_save bck; 137 138 #ifdef JOBS 139 static void job_set(struct process*); 140 static void job_reset(struct process*); 141 static void job_waitsafe(int); 142 static struct process *job_byname(char*); 143 static struct process *job_bystring(char*); 144 static struct termios my_stty; /* terminal state for shell */ 145 static char *job_string; 146 #else 147 extern const char e_coredump[]; 148 #endif /* JOBS */ 149 150 #ifdef SIGTSTP 151 static void job_unstop(struct process*); 152 static void job_fgrp(struct process*, int); 153 # ifndef _lib_tcgetpgrp 154 # ifdef TIOCGPGRP 155 static int _i_; 156 # define tcgetpgrp(a) (ioctl(a, TIOCGPGRP, &_i_)>=0?_i_:-1) 157 # endif /* TIOCGPGRP */ 158 int tcsetpgrp(int fd,pid_t pgrp) 159 { 160 int pgid = pgrp; 161 # ifdef TIOCGPGRP 162 return(ioctl(fd, TIOCSPGRP, &pgid)); 163 # else 164 return(-1); 165 # endif /* TIOCGPGRP */ 166 } 167 # endif /* _lib_tcgetpgrp */ 168 #else 169 # define job_unstop(pw) 170 # undef CNSUSP 171 #endif /* SIGTSTP */ 172 173 #ifndef OTTYDISC 174 # undef NTTYDISC 175 #endif /* OTTYDISC */ 176 177 #ifdef JOBS 178 179 typedef int (*Waitevent_f)(int,long,int); 180 181 #ifdef SHOPT_BGX 182 void job_chldtrap(Shell_t *shp, const char *trap, int unpost) 183 { 184 register struct process *pw,*pwnext; 185 pid_t bckpid; 186 int oldexit,trapnote; 187 job_lock(); 188 shp->sigflag[SIGCHLD] &= ~SH_SIGTRAP; 189 trapnote = shp->trapnote; 190 shp->trapnote = 0; 191 for(pw=job.pwlist;pw;pw=pwnext) 192 { 193 pwnext = pw->p_nxtjob; 194 if((pw->p_flag&(P_BG|P_DONE)) != (P_BG|P_DONE)) 195 continue; 196 pw->p_flag &= ~P_BG; 197 bckpid = shp->bckpid; 198 oldexit = shp->savexit; 199 shp->bckpid = pw->p_pid; 200 shp->savexit = pw->p_exit; 201 if(pw->p_flag&P_SIGNALLED) 202 shp->savexit |= SH_EXITSIG; 203 sh_trap(trap,0); 204 if(pw->p_pid==bckpid && unpost) 205 job_unpost(pw,0); 206 shp->savexit = oldexit; 207 shp->bckpid = bckpid; 208 } 209 shp->trapnote = trapnote; 210 job_unlock(); 211 } 212 #endif /* SHOPT_BGX */ 213 214 /* 215 * return next on link list of jobsave free list 216 */ 217 static struct jobsave *jobsave_create(pid_t pid) 218 { 219 register struct jobsave *jp = job_savelist; 220 job_chksave(pid); 221 if(++bck.count > sh.lim.child_max) 222 job_chksave(0); 223 if(jp) 224 { 225 njob_savelist--; 226 job_savelist = jp->next; 227 } 228 else 229 jp = newof(0,struct jobsave,1,0); 230 if(jp) 231 { 232 jp->pid = pid; 233 jp->next = bck.list; 234 bck.list = jp; 235 jp->exitval = 0; 236 } 237 return(jp); 238 } 239 240 /* 241 * Reap one job 242 * When called with sig==0, it does a blocking wait 243 */ 244 int job_reap(register int sig) 245 { 246 register pid_t pid; 247 register struct process *pw; 248 struct process *px; 249 register int flags; 250 struct jobsave *jp; 251 int nochild=0, oerrno, wstat; 252 Waitevent_f waitevent = sh.waitevent; 253 static int wcontinued = WCONTINUED; 254 if (vmbusy()) 255 { 256 errormsg(SH_DICT,ERROR_warn(0),"vmbusy() inside job_reap() -- should not happen"); 257 if (getenv("_AST_KSH_VMBUSY_ABORT")) 258 abort(); 259 } 260 #ifdef DEBUG 261 if(sfprintf(sfstderr,"ksh: job line %4d: reap pid=%d critical=%d signal=%d\n",__LINE__,getpid(),job.in_critical,sig) <=0) 262 write(2,"waitsafe\n",9); 263 sfsync(sfstderr); 264 #endif /* DEBUG */ 265 job.savesig = 0; 266 if(sig) 267 flags = WNOHANG|WUNTRACED|wcontinued; 268 else 269 flags = WUNTRACED|wcontinued; 270 sh.waitevent = 0; 271 oerrno = errno; 272 while(1) 273 { 274 if(!(flags&WNOHANG) && !sh.intrap && job.pwlist) 275 { 276 sh_onstate(SH_TTYWAIT); 277 if(waitevent && (*waitevent)(-1,-1L,0)) 278 flags |= WNOHANG; 279 } 280 pid = waitpid((pid_t)-1,&wstat,flags); 281 sh_offstate(SH_TTYWAIT); 282 283 /* 284 * some systems (linux 2.6) may return EINVAL 285 * when there are no continued children 286 */ 287 288 if (pid<0 && errno==EINVAL && (flags&WCONTINUED)) 289 pid = waitpid((pid_t)-1,&wstat,flags&=~WCONTINUED); 290 sh_sigcheck(); 291 if(pid<0 && errno==EINTR && (sig||job.savesig)) 292 continue; 293 if(pid<=0) 294 break; 295 flags |= WNOHANG; 296 job.waitsafe++; 297 jp = 0; 298 lastpid = pid; 299 if(!(pw=job_bypid(pid))) 300 { 301 #ifdef DEBUG 302 sfprintf(sfstderr,"ksh: job line %4d: reap pid=%d critical=%d unknown job pid=%d pw=%x\n",__LINE__,getpid(),job.in_critical,pid,pw); 303 #endif /* DEBUG */ 304 if (WIFCONTINUED(wstat) && wcontinued) 305 continue; 306 pw = &dummy; 307 pw->p_exit = 0; 308 pw->p_pgrp = 0; 309 pw->p_exitmin = 0; 310 if(job.toclear) 311 job_clear(); 312 jp = jobsave_create(pid); 313 pw->p_flag = 0; 314 lastpid = pw->p_pid = pid; 315 px = 0; 316 if(jp && WIFSTOPPED(wstat)) 317 { 318 jp->exitval = SH_STOPSIG; 319 continue; 320 } 321 } 322 #ifdef SIGTSTP 323 else 324 px=job_byjid(pw->p_job); 325 if(WIFSTOPPED(wstat)) 326 { 327 if(px) 328 { 329 /* move to top of job list */ 330 job_unlink(px); 331 px->p_nxtjob = job.pwlist; 332 job.pwlist = px; 333 } 334 pw->p_flag |= (P_NOTIFY|P_SIGNALLED|P_STOPPED); 335 pw->p_exit = WSTOPSIG(wstat); 336 if(pw->p_pgrp && pw->p_pgrp==job.curpgid && sh_isstate(SH_STOPOK)) 337 sh_fault(pw->p_exit); 338 continue; 339 } 340 else if (WIFCONTINUED(wstat) && wcontinued) 341 pw->p_flag &= ~(P_NOTIFY|P_SIGNALLED|P_STOPPED); 342 else 343 #endif /* SIGTSTP */ 344 { 345 /* check for coprocess completion */ 346 if(pid==sh.cpid) 347 { 348 sh_close(sh.coutpipe); 349 sh_close(sh.cpipe[1]); 350 sh.cpipe[1] = -1; 351 sh.coutpipe = -1; 352 } 353 else if(sh.subshell) 354 sh_subjobcheck(pid); 355 356 pw->p_flag &= ~(P_STOPPED|P_SIGNALLED); 357 if (WIFSIGNALED(wstat)) 358 { 359 pw->p_flag |= (P_DONE|P_NOTIFY|P_SIGNALLED); 360 if (WTERMCORE(wstat)) 361 pw->p_flag |= P_COREDUMP; 362 pw->p_exit = WTERMSIG(wstat); 363 /* if process in current jobs terminates from 364 * an interrupt, propogate to parent shell 365 */ 366 if(pw->p_pgrp && pw->p_pgrp==job.curpgid && pw->p_exit==SIGINT && sh_isstate(SH_STOPOK)) 367 { 368 pw->p_flag &= ~P_NOTIFY; 369 sh_offstate(SH_STOPOK); 370 sh_fault(SIGINT); 371 sh_onstate(SH_STOPOK); 372 } 373 } 374 else 375 { 376 pw->p_flag |= (P_DONE|P_NOTIFY); 377 pw->p_exit = pw->p_exitmin; 378 if(WEXITSTATUS(wstat) > pw->p_exitmin) 379 pw->p_exit = WEXITSTATUS(wstat); 380 } 381 #ifdef SHOPT_BGX 382 if((pw->p_flag&P_DONE) && (pw->p_flag&P_BG)) 383 { 384 job.numbjob--; 385 if(sh.st.trapcom[SIGCHLD]) 386 { 387 sh.sigflag[SIGCHLD] |= SH_SIGTRAP; 388 if(sig==0) 389 job_chldtrap(&sh,sh.st.trapcom[SIGCHLD],0); 390 else 391 sh.trapnote |= SH_SIGTRAP; 392 } 393 else 394 pw->p_flag &= ~P_BG; 395 } 396 #endif /* SHOPT_BGX */ 397 if(pw->p_pgrp==0) 398 pw->p_flag &= ~P_NOTIFY; 399 } 400 if(jp && pw== &dummy) 401 { 402 jp->exitval = pw->p_exit; 403 if(pw->p_flag&P_SIGNALLED) 404 jp->exitval |= SH_EXITSIG; 405 } 406 #ifdef DEBUG 407 sfprintf(sfstderr,"ksh: job line %4d: reap pid=%d critical=%d job %d with pid %d flags=%o complete with status=%x exit=%d\n",__LINE__,getpid(),job.in_critical,pw->p_job,pid,pw->p_flag,wstat,pw->p_exit); 408 sfsync(sfstderr); 409 #endif /* DEBUG*/ 410 /* only top-level process in job should have notify set */ 411 if(px && pw != px) 412 pw->p_flag &= ~P_NOTIFY; 413 if(pid==pw->p_fgrp && pid==tcgetpgrp(JOBTTY)) 414 { 415 px = job_byjid((int)pw->p_job); 416 for(; px && (px->p_flag&P_DONE); px=px->p_nxtproc); 417 if(!px) 418 tcsetpgrp(JOBTTY,job.mypid); 419 } 420 #ifndef SHOPT_BGX 421 if(!sh.intrap && sh.st.trapcom[SIGCHLD] && pid>0 && (pwfg!=job_bypid(pid))) 422 { 423 sh.sigflag[SIGCHLD] |= SH_SIGTRAP; 424 sh.trapnote |= SH_SIGTRAP; 425 } 426 #endif 427 } 428 if(errno==ECHILD) 429 { 430 errno = oerrno; 431 #ifdef SHOPT_BGX 432 job.numbjob = 0; 433 #endif /* SHOPT_BGX */ 434 nochild = 1; 435 } 436 sh.waitevent = waitevent; 437 if(sh_isoption(SH_NOTIFY) && sh_isstate(SH_TTYWAIT)) 438 { 439 outfile = sfstderr; 440 job_list(pw,JOB_NFLAG|JOB_NLFLAG); 441 job_unpost(pw,1); 442 sfsync(sfstderr); 443 } 444 if(sig) 445 signal(sig, job_waitsafe); 446 return(nochild); 447 } 448 449 /* 450 * This is the SIGCLD interrupt routine 451 */ 452 static void job_waitsafe(int sig) 453 { 454 if(job.in_critical || vmbusy()) 455 { 456 job.savesig = sig; 457 job.waitsafe++; 458 } 459 else 460 job_reap(sig); 461 } 462 463 /* 464 * initialize job control if possible 465 * if lflag is set the switching driver message will not print 466 */ 467 void job_init(Shell_t *shp, int lflag) 468 { 469 register int ntry=0; 470 job.fd = JOBTTY; 471 signal(SIGCHLD,job_waitsafe); 472 # if defined(SIGCLD) && (SIGCLD!=SIGCHLD) 473 signal(SIGCLD,job_waitsafe); 474 # endif 475 if(njob_savelist < NJOB_SAVELIST) 476 init_savelist(); 477 if(!sh_isoption(SH_INTERACTIVE)) 478 return; 479 /* use new line discipline when available */ 480 #ifdef NTTYDISC 481 # ifdef FIOLOOKLD 482 if((job.linedisc = ioctl(JOBTTY, FIOLOOKLD, 0)) <0) 483 # else 484 if(ioctl(JOBTTY,TIOCGETD,&job.linedisc) !=0) 485 # endif /* FIOLOOKLD */ 486 return; 487 if(job.linedisc!=NTTYDISC && job.linedisc!=OTTYDISC) 488 { 489 /* no job control when running with MPX */ 490 # if SHOPT_VSH 491 sh_onoption(SH_VIRAW); 492 # endif /* SHOPT_VSH */ 493 return; 494 } 495 if(job.linedisc==NTTYDISC) 496 job.linedisc = -1; 497 #endif /* NTTYDISC */ 498 499 job.mypgid = getpgrp(); 500 /* some systems have job control, but not initialized */ 501 if(job.mypgid<=0) 502 { 503 /* Get a controlling terminal and set process group */ 504 /* This should have already been done by rlogin */ 505 register int fd; 506 register char *ttynam; 507 #ifndef SIGTSTP 508 setpgid(0,shp->pid); 509 #endif /*SIGTSTP */ 510 if(job.mypgid<0 || !(ttynam=ttyname(JOBTTY))) 511 return; 512 close(JOBTTY); 513 if((fd = open(ttynam,O_RDWR)) <0) 514 return; 515 if(fd!=JOBTTY) 516 sh_iorenumber(shp,fd,JOBTTY); 517 job.mypgid = shp->pid; 518 #ifdef SIGTSTP 519 tcsetpgrp(JOBTTY,shp->pid); 520 setpgid(0,shp->pid); 521 #endif /* SIGTSTP */ 522 } 523 #ifdef SIGTSTP 524 if(possible = (setpgid(0,job.mypgid)>=0) || errno==EPERM) 525 { 526 /* wait until we are in the foreground */ 527 while((job.mytgid=tcgetpgrp(JOBTTY)) != job.mypgid) 528 { 529 if(job.mytgid == -1) 530 return; 531 /* Stop this shell until continued */ 532 signal(SIGTTIN,SIG_DFL); 533 kill(shp->pid,SIGTTIN); 534 /* resumes here after continue tries again */ 535 if(ntry++ > IOMAXTRY) 536 { 537 errormsg(SH_DICT,0,e_no_start); 538 return; 539 } 540 } 541 } 542 #endif /* SIGTTIN */ 543 544 #ifdef NTTYDISC 545 /* set the line discipline */ 546 if(job.linedisc>=0) 547 { 548 int linedisc = NTTYDISC; 549 # ifdef FIOPUSHLD 550 tty_get(JOBTTY,&my_stty); 551 if (ioctl(JOBTTY, FIOPOPLD, 0) < 0) 552 return; 553 if (ioctl(JOBTTY, FIOPUSHLD, &linedisc) < 0) 554 { 555 ioctl(JOBTTY, FIOPUSHLD, &job.linedisc); 556 return; 557 } 558 tty_set(JOBTTY,TCSANOW,&my_stty); 559 # else 560 if(ioctl(JOBTTY,TIOCSETD,&linedisc) !=0) 561 return; 562 # endif /* FIOPUSHLD */ 563 if(lflag==0) 564 errormsg(SH_DICT,0,e_newtty); 565 else 566 job.linedisc = -1; 567 } 568 #endif /* NTTYDISC */ 569 if(!possible) 570 return; 571 572 #ifdef SIGTSTP 573 /* make sure that we are a process group leader */ 574 setpgid(0,shp->pid); 575 # if defined(SA_NOCLDSTOP) || defined(SA_NOCLDWAIT) 576 # if !defined(SA_NOCLDSTOP) 577 # define SA_NOCLDSTOP 0 578 # endif 579 # if !defined(SA_NOCLDWAIT) 580 # define SA_NOCLDWAIT 0 581 # endif 582 sigflag(SIGCHLD, SA_NOCLDSTOP|SA_NOCLDWAIT, 0); 583 # endif /* SA_NOCLDSTOP || SA_NOCLDWAIT */ 584 signal(SIGTTIN,SIG_IGN); 585 signal(SIGTTOU,SIG_IGN); 586 /* The shell now handles ^Z */ 587 signal(SIGTSTP,sh_fault); 588 tcsetpgrp(JOBTTY,shp->pid); 589 # ifdef CNSUSP 590 /* set the switch character */ 591 tty_get(JOBTTY,&my_stty); 592 job.suspend = (unsigned)my_stty.c_cc[VSUSP]; 593 if(job.suspend == (unsigned char)CNSUSP) 594 { 595 my_stty.c_cc[VSUSP] = CSWTCH; 596 tty_set(JOBTTY,TCSAFLUSH,&my_stty); 597 } 598 # endif /* CNSUSP */ 599 sh_onoption(SH_MONITOR); 600 job.jobcontrol++; 601 job.mypid = shp->pid; 602 #endif /* SIGTSTP */ 603 return; 604 } 605 606 607 /* 608 * see if there are any stopped jobs 609 * restore tty driver and pgrp 610 */ 611 int job_close(Shell_t* shp) 612 { 613 register struct process *pw; 614 register int count = 0, running = 0; 615 if(possible && !job.jobcontrol) 616 return(0); 617 else if(!possible && (!sh_isstate(SH_MONITOR) || sh_isstate(SH_FORKED))) 618 return(0); 619 else if(getpid() != job.mypid) 620 return(0); 621 job_lock(); 622 if(!tty_check(0)) 623 beenhere++; 624 for(pw=job.pwlist;pw;pw=pw->p_nxtjob) 625 { 626 if(!(pw->p_flag&P_STOPPED)) 627 { 628 if(!(pw->p_flag&P_DONE)) 629 running++; 630 continue; 631 } 632 if(beenhere) 633 killpg(pw->p_pgrp,SIGTERM); 634 count++; 635 } 636 if(beenhere++ == 0 && job.pwlist) 637 { 638 if(count) 639 { 640 errormsg(SH_DICT,0,e_terminate); 641 return(-1); 642 } 643 else if(running && shp->login_sh) 644 { 645 errormsg(SH_DICT,0,e_jobsrunning); 646 return(-1); 647 } 648 } 649 job_unlock(); 650 # ifdef SIGTSTP 651 if(possible && setpgid(0,job.mypgid)>=0) 652 tcsetpgrp(job.fd,job.mypgid); 653 # endif /* SIGTSTP */ 654 # ifdef NTTYDISC 655 if(job.linedisc>=0) 656 { 657 /* restore old line discipline */ 658 # ifdef FIOPUSHLD 659 tty_get(job.fd,&my_stty); 660 if (ioctl(job.fd, FIOPOPLD, 0) < 0) 661 return(0); 662 if (ioctl(job.fd, FIOPUSHLD, &job.linedisc) < 0) 663 { 664 job.linedisc = NTTYDISC; 665 ioctl(job.fd, FIOPUSHLD, &job.linedisc); 666 return(0); 667 } 668 tty_set(job.fd,TCSAFLUSH,&my_stty); 669 # else 670 if(ioctl(job.fd,TIOCSETD,&job.linedisc) !=0) 671 return(0); 672 # endif /* FIOPUSHLD */ 673 errormsg(SH_DICT,0,e_oldtty); 674 } 675 # endif /* NTTYDISC */ 676 # ifdef CNSUSP 677 if(possible && job.suspend==CNSUSP) 678 { 679 tty_get(job.fd,&my_stty); 680 my_stty.c_cc[VSUSP] = CNSUSP; 681 tty_set(job.fd,TCSAFLUSH,&my_stty); 682 } 683 # endif /* CNSUSP */ 684 job.jobcontrol = 0; 685 return(0); 686 } 687 688 static void job_set(register struct process *pw) 689 { 690 /* save current terminal state */ 691 tty_get(job.fd,&my_stty); 692 if(pw->p_flag&P_STTY) 693 { 694 /* restore terminal state for job */ 695 tty_set(job.fd,TCSAFLUSH,&pw->p_stty); 696 } 697 #ifdef SIGTSTP 698 if((pw->p_flag&P_STOPPED) || tcgetpgrp(job.fd) == sh.pid) 699 tcsetpgrp(job.fd,pw->p_fgrp); 700 /* if job is stopped, resume it in the background */ 701 job_unstop(pw); 702 #endif /* SIGTSTP */ 703 } 704 705 static void job_reset(register struct process *pw) 706 { 707 /* save the terminal state for current job */ 708 #ifdef SIGTSTP 709 job_fgrp(pw,tcgetpgrp(job.fd)); 710 if(tcsetpgrp(job.fd,job.mypid) !=0) 711 return; 712 #endif /* SIGTSTP */ 713 /* force the following tty_get() to do a tcgetattr() unless fg */ 714 if(!(pw->p_flag&P_FG)) 715 tty_set(-1, 0, NIL(struct termios*)); 716 if(pw && (pw->p_flag&P_SIGNALLED) && pw->p_exit!=SIGHUP) 717 { 718 if(tty_get(job.fd,&pw->p_stty) == 0) 719 pw->p_flag |= P_STTY; 720 /* restore terminal state for job */ 721 tty_set(job.fd,TCSAFLUSH,&my_stty); 722 } 723 beenhere = 0; 724 } 725 #endif /* JOBS */ 726 727 /* 728 * wait built-in command 729 */ 730 731 void job_bwait(char **jobs) 732 { 733 register char *jp; 734 register struct process *pw; 735 register pid_t pid; 736 if(*jobs==0) 737 job_wait((pid_t)-1); 738 else while(jp = *jobs++) 739 { 740 #ifdef JOBS 741 if(*jp == '%') 742 { 743 job_lock(); 744 pw = job_bystring(jp); 745 job_unlock(); 746 if(pw) 747 pid = pw->p_pid; 748 else 749 return; 750 } 751 else 752 #endif /* JOBS */ 753 pid = (int)strtol(jp, (char**)0, 10); 754 job_wait(-pid); 755 } 756 } 757 758 #ifdef JOBS 759 /* 760 * execute function <fun> for each job 761 */ 762 763 int job_walk(Sfio_t *file,int (*fun)(struct process*,int),int arg,char *joblist[]) 764 { 765 register struct process *pw; 766 register int r = 0; 767 register char *jobid, **jobs=joblist; 768 register struct process *px; 769 job_string = 0; 770 outfile = file; 771 by_number = 0; 772 job_lock(); 773 pw = job.pwlist; 774 if(jobs==0) 775 { 776 /* do all jobs */ 777 for(;pw;pw=px) 778 { 779 px = pw->p_nxtjob; 780 if(pw->p_env != sh.jobenv) 781 continue; 782 if((*fun)(pw,arg)) 783 r = 2; 784 } 785 } 786 else if(*jobs==0) /* current job */ 787 { 788 /* skip over non-stop jobs */ 789 while(pw && (pw->p_env!=sh.jobenv || pw->p_pgrp==0)) 790 pw = pw->p_nxtjob; 791 if((*fun)(pw,arg)) 792 r = 2; 793 } 794 else while(jobid = *jobs++) 795 { 796 job_string = jobid; 797 if(*jobid==0) 798 errormsg(SH_DICT,ERROR_exit(1),e_jobusage,job_string); 799 if(*jobid == '%') 800 pw = job_bystring(jobid); 801 else 802 { 803 int pid = (int)strtol(jobid, (char**)0, 10); 804 if(pid<0) 805 jobid++; 806 while(isdigit(*jobid)) 807 jobid++; 808 if(*jobid) 809 errormsg(SH_DICT,ERROR_exit(1),e_jobusage,job_string); 810 if(!(pw = job_bypid(pid))) 811 { 812 pw = &dummy; 813 pw->p_pid = pid; 814 pw->p_pgrp = pid; 815 } 816 by_number = 1; 817 } 818 if((*fun)(pw,arg)) 819 r = 2; 820 by_number = 0; 821 } 822 job_unlock(); 823 return(r); 824 } 825 826 /* 827 * send signal <sig> to background process group if not disowned 828 */ 829 int job_terminate(register struct process *pw,register int sig) 830 { 831 if(pw->p_pgrp && !(pw->p_flag&P_DISOWN)) 832 job_kill(pw,sig); 833 return(0); 834 } 835 836 /* 837 * list the given job 838 * flag JOB_LFLAG for long listing 839 * flag JOB_NFLAG for list only jobs marked for notification 840 * flag JOB_PFLAG for process id(s) only 841 */ 842 843 int job_list(struct process *pw,register int flag) 844 { 845 register struct process *px = pw; 846 register int n; 847 register const char *msg; 848 register int msize; 849 if(!pw || pw->p_job<=0) 850 return(1); 851 if(pw->p_env != sh.jobenv) 852 return(0); 853 if((flag&JOB_NFLAG) && (!(px->p_flag&P_NOTIFY)||px->p_pgrp==0)) 854 return(0); 855 if((flag&JOB_PFLAG)) 856 { 857 sfprintf(outfile,"%d\n",px->p_pgrp?px->p_pgrp:px->p_pid); 858 return(0); 859 } 860 if((px->p_flag&P_DONE) && job.waitall && !(flag&JOB_LFLAG)) 861 return(0); 862 job_lock(); 863 n = px->p_job; 864 if(px==job.pwlist) 865 msize = '+'; 866 else if(px==job.pwlist->p_nxtjob) 867 msize = '-'; 868 else 869 msize = ' '; 870 if(flag&JOB_NLFLAG) 871 sfputc(outfile,'\n'); 872 sfprintf(outfile,"[%d] %c ",n, msize); 873 do 874 { 875 n = 0; 876 if(flag&JOB_LFLAG) 877 sfprintf(outfile,"%d\t",px->p_pid); 878 if(px->p_flag&P_SIGNALLED) 879 msg = job_sigmsg((int)(px->p_exit)); 880 else if(px->p_flag&P_NOTIFY) 881 { 882 msg = sh_translate(e_done); 883 n = px->p_exit; 884 } 885 else 886 msg = sh_translate(e_running); 887 px->p_flag &= ~P_NOTIFY; 888 sfputr(outfile,msg,-1); 889 msize = strlen(msg); 890 if(n) 891 { 892 sfprintf(outfile,"(%d)",(int)n); 893 msize += (3+(n>10)+(n>100)); 894 } 895 if(px->p_flag&P_COREDUMP) 896 { 897 msg = sh_translate(e_coredump); 898 sfputr(outfile, msg, -1); 899 msize += strlen(msg); 900 } 901 sfnputc(outfile,' ',MAXMSG>msize?MAXMSG-msize:1); 902 if(flag&JOB_LFLAG) 903 px = px->p_nxtproc; 904 else 905 { 906 while(px=px->p_nxtproc) 907 px->p_flag &= ~P_NOTIFY; 908 px = 0; 909 } 910 if(!px) 911 hist_list(sh.hist_ptr,outfile,pw->p_name,0,";"); 912 else 913 sfputr(outfile, e_nlspace, -1); 914 } 915 while(px); 916 job_unlock(); 917 return(0); 918 } 919 920 /* 921 * get the process group given the job number 922 * This routine returns the process group number or -1 923 */ 924 static struct process *job_bystring(register char *ajob) 925 { 926 register struct process *pw=job.pwlist; 927 register int c; 928 if(*ajob++ != '%' || !pw) 929 return(NIL(struct process*)); 930 c = *ajob; 931 if(isdigit(c)) 932 pw = job_byjid((int)strtol(ajob, (char**)0, 10)); 933 else if(c=='+' || c=='%') 934 ; 935 else if(c=='-') 936 { 937 if(pw) 938 pw = job.pwlist->p_nxtjob; 939 } 940 else 941 pw = job_byname(ajob); 942 if(pw && pw->p_flag) 943 return(pw); 944 return(NIL(struct process*)); 945 } 946 947 /* 948 * Kill a job or process 949 */ 950 951 int job_kill(register struct process *pw,register int sig) 952 { 953 register pid_t pid; 954 register int r; 955 const char *msg; 956 #ifdef SIGTSTP 957 int stopsig = (sig==SIGSTOP||sig==SIGTSTP||sig==SIGTTIN||sig==SIGTTOU); 958 #else 959 # define stopsig 1 960 #endif /* SIGTSTP */ 961 job_lock(); 962 errno = ECHILD; 963 if(pw==0) 964 goto error; 965 pid = pw->p_pid; 966 if(by_number) 967 { 968 if(pid==0 && job.jobcontrol) 969 r = job_walk(outfile, job_kill,sig, (char**)0); 970 #ifdef SIGTSTP 971 if(sig==SIGSTOP && pid==sh.pid && sh.ppid==1) 972 { 973 /* can't stop login shell */ 974 errno = EPERM; 975 r = -1; 976 } 977 else 978 { 979 if(pid>=0) 980 { 981 if((r = kill(pid,sig))>=0 && !stopsig) 982 { 983 if(pw->p_flag&P_STOPPED) 984 pw->p_flag &= ~(P_STOPPED|P_SIGNALLED); 985 if(sig) 986 kill(pid,SIGCONT); 987 } 988 } 989 else 990 { 991 if((r = killpg(-pid,sig))>=0 && !stopsig) 992 { 993 job_unstop(job_bypid(pw->p_pid)); 994 if(sig) 995 killpg(-pid,SIGCONT); 996 } 997 } 998 } 999 #else 1000 if(pid>=0) 1001 r = kill(pid,sig); 1002 else 1003 r = killpg(-pid,sig); 1004 #endif /* SIGTSTP */ 1005 } 1006 else 1007 { 1008 if(pid = pw->p_pgrp) 1009 { 1010 r = killpg(pid,sig); 1011 #ifdef SIGTSTP 1012 if(r>=0 && (sig==SIGHUP||sig==SIGTERM || sig==SIGCONT)) 1013 job_unstop(pw); 1014 #endif /* SIGTSTP */ 1015 if(r>=0) 1016 sh_delay(.05); 1017 } 1018 while(pw && pw->p_pgrp==0 && (r=kill(pw->p_pid,sig))>=0) 1019 { 1020 #ifdef SIGTSTP 1021 if(sig==SIGHUP || sig==SIGTERM) 1022 kill(pw->p_pid,SIGCONT); 1023 #endif /* SIGTSTP */ 1024 pw = pw->p_nxtproc; 1025 } 1026 } 1027 if(r<0 && job_string) 1028 { 1029 error: 1030 if(pw && by_number) 1031 msg = sh_translate(e_no_proc); 1032 else 1033 msg = sh_translate(e_no_job); 1034 if(errno == EPERM) 1035 msg = sh_translate(e_access); 1036 sfprintf(sfstderr,"kill: %s: %s\n",job_string, msg); 1037 r = 2; 1038 } 1039 sh_delay(.001); 1040 job_unlock(); 1041 return(r); 1042 } 1043 1044 /* 1045 * Get process structure from first letters of jobname 1046 * 1047 */ 1048 1049 static struct process *job_byname(char *name) 1050 { 1051 register struct process *pw = job.pwlist; 1052 register struct process *pz = 0; 1053 register int *flag = 0; 1054 register char *cp = name; 1055 int offset; 1056 if(!sh.hist_ptr) 1057 return(NIL(struct process*)); 1058 if(*cp=='?') 1059 cp++,flag= &offset; 1060 for(;pw;pw=pw->p_nxtjob) 1061 { 1062 if(hist_match(sh.hist_ptr,pw->p_name,cp,flag)>=0) 1063 { 1064 if(pz) 1065 errormsg(SH_DICT,ERROR_exit(1),e_jobusage,name-1); 1066 pz = pw; 1067 } 1068 } 1069 return(pz); 1070 } 1071 1072 #else 1073 # define job_set(x) 1074 # define job_reset(x) 1075 #endif /* JOBS */ 1076 1077 1078 1079 /* 1080 * Initialize the process posting array 1081 */ 1082 1083 void job_clear(void) 1084 { 1085 register struct process *pw, *px; 1086 register struct process *pwnext; 1087 register int j = BYTE(sh.lim.child_max); 1088 register struct jobsave *jp,*jpnext; 1089 job_lock(); 1090 for(pw=job.pwlist; pw; pw=pwnext) 1091 { 1092 pwnext = pw->p_nxtjob; 1093 while(px=pw) 1094 { 1095 pw = pw->p_nxtproc; 1096 free((void*)px); 1097 } 1098 } 1099 for(jp=bck.list; jp;jp=jpnext) 1100 { 1101 jpnext = jp->next; 1102 free((void*)jp); 1103 } 1104 bck.list = 0; 1105 if(njob_savelist < NJOB_SAVELIST) 1106 init_savelist(); 1107 job.pwlist = NIL(struct process*); 1108 job.numpost=0; 1109 #ifdef SHOPT_BGX 1110 job.numbjob = 0; 1111 #endif /* SHOPT_BGX */ 1112 job.waitall = 0; 1113 job.curpgid = 0; 1114 job.toclear = 0; 1115 if(!job.freejobs) 1116 job.freejobs = (unsigned char*)malloc((unsigned)(j+1)); 1117 while(j >=0) 1118 job.freejobs[j--] = 0; 1119 job_unlock(); 1120 } 1121 1122 /* 1123 * put the process <pid> on the process list and return the job number 1124 * if non-zero, <join> is the process id of the job to join 1125 */ 1126 1127 int job_post(pid_t pid, pid_t join) 1128 { 1129 register struct process *pw; 1130 register History_t *hp = sh.hist_ptr; 1131 #ifdef SHOPT_BGX 1132 int val,bg=0; 1133 #else 1134 int val; 1135 #endif 1136 sh.jobenv = sh.curenv; 1137 if(job.toclear) 1138 { 1139 job_clear(); 1140 return(0); 1141 } 1142 job_lock(); 1143 #ifdef SHOPT_BGX 1144 if(join==1) 1145 { 1146 join = 0; 1147 bg = P_BG; 1148 job.numbjob++; 1149 } 1150 #endif /* SHOPT_BGX */ 1151 if(njob_savelist < NJOB_SAVELIST) 1152 init_savelist(); 1153 if(pw = job_bypid(pid)) 1154 job_unpost(pw,0); 1155 if(join && (pw=job_bypid(join))) 1156 { 1157 /* if job to join is not first move it to front */ 1158 if((pw=job_byjid(pw->p_job)) != job.pwlist) 1159 { 1160 job_unlink(pw); 1161 pw->p_nxtjob = job.pwlist; 1162 job.pwlist = pw; 1163 } 1164 } 1165 if(pw=freelist) 1166 freelist = pw->p_nxtjob; 1167 else 1168 pw = new_of(struct process,0); 1169 pw->p_flag = 0; 1170 job.numpost++; 1171 if(join && job.pwlist) 1172 { 1173 /* join existing current job */ 1174 pw->p_nxtjob = job.pwlist->p_nxtjob; 1175 pw->p_nxtproc = job.pwlist; 1176 pw->p_job = job.pwlist->p_job; 1177 } 1178 else 1179 { 1180 /* create a new job */ 1181 while((pw->p_job = job_alloc()) < 0) 1182 job_wait((pid_t)1); 1183 pw->p_nxtjob = job.pwlist; 1184 pw->p_nxtproc = 0; 1185 } 1186 job.pwlist = pw; 1187 pw->p_env = sh.curenv; 1188 pw->p_pid = pid; 1189 if(!sh.outpipe || (sh_isoption(SH_PIPEFAIL) && job.waitall)) 1190 pw->p_flag = P_EXITSAVE; 1191 pw->p_exitmin = sh.xargexit; 1192 pw->p_exit = 0; 1193 if(sh_isstate(SH_MONITOR)) 1194 { 1195 if(killpg(job.curpgid,0)<0 && errno==ESRCH) 1196 job.curpgid = pid; 1197 pw->p_fgrp = job.curpgid; 1198 } 1199 else 1200 pw->p_fgrp = 0; 1201 pw->p_pgrp = pw->p_fgrp; 1202 #ifdef DEBUG 1203 sfprintf(sfstderr,"ksh: job line %4d: post pid=%d critical=%d job=%d pid=%d pgid=%d savesig=%d join=%d\n",__LINE__,getpid(),job.in_critical,pw->p_job, 1204 pw->p_pid,pw->p_pgrp,job.savesig,join); 1205 sfsync(sfstderr); 1206 #endif /* DEBUG */ 1207 #ifdef JOBS 1208 if(hp && !sh_isstate(SH_PROFILE)) 1209 pw->p_name=hist_tell(sh.hist_ptr,(int)hp->histind-1); 1210 else 1211 pw->p_name = -1; 1212 #endif /* JOBS */ 1213 if ((val = job_chksave(pid)) >= 0) 1214 { 1215 pw->p_exit = val; 1216 if(pw->p_exit==SH_STOPSIG) 1217 { 1218 pw->p_flag |= (P_SIGNALLED|P_STOPPED); 1219 pw->p_exit = 0; 1220 } 1221 else if(pw->p_exit >= SH_EXITSIG) 1222 { 1223 pw->p_flag |= P_DONE|P_SIGNALLED; 1224 pw->p_exit &= SH_EXITMASK; 1225 } 1226 else 1227 pw->p_flag |= (P_DONE|P_NOTIFY); 1228 } 1229 #ifdef SHOPT_BGX 1230 if(bg && !(pw->p_flag&P_DONE)) 1231 pw->p_flag |= P_BG; 1232 #endif /* SHOPT_BGX */ 1233 lastpid = 0; 1234 job_unlock(); 1235 return(pw->p_job); 1236 } 1237 1238 /* 1239 * Returns a process structure give a process id 1240 */ 1241 1242 static struct process *job_bypid(pid_t pid) 1243 { 1244 register struct process *pw, *px; 1245 for(pw=job.pwlist; pw; pw=pw->p_nxtjob) 1246 for(px=pw; px; px=px->p_nxtproc) 1247 { 1248 if(px->p_pid==pid) 1249 return(px); 1250 } 1251 return(NIL(struct process*)); 1252 } 1253 1254 /* 1255 * return a pointer to a job given the job id 1256 */ 1257 1258 static struct process *job_byjid(int jobid) 1259 { 1260 register struct process *pw; 1261 for(pw=job.pwlist;pw; pw = pw->p_nxtjob) 1262 { 1263 if(pw->p_job==jobid) 1264 break; 1265 } 1266 return(pw); 1267 } 1268 1269 /* 1270 * print a signal message 1271 */ 1272 static void job_prmsg(register struct process *pw) 1273 { 1274 if(pw->p_exit!=SIGINT && pw->p_exit!=SIGPIPE) 1275 { 1276 register const char *msg, *dump; 1277 msg = job_sigmsg((int)(pw->p_exit)); 1278 msg = sh_translate(msg); 1279 if(pw->p_flag&P_COREDUMP) 1280 dump = sh_translate(e_coredump); 1281 else 1282 dump = ""; 1283 if(sh_isstate(SH_INTERACTIVE)) 1284 sfprintf(sfstderr,"%s%s\n",msg,dump); 1285 else 1286 errormsg(SH_DICT,2,"%d: %s%s",pw->p_pid,msg,dump); 1287 } 1288 } 1289 1290 /* 1291 * Wait for process pid to complete 1292 * If pid < -1, then wait can be interrupted, -pid is waited for (wait builtin) 1293 * pid=0 to unpost all done processes 1294 * pid=1 to wait for at least one process to complete 1295 * pid=-1 to wait for all runing processes 1296 */ 1297 1298 int job_wait(register pid_t pid) 1299 { 1300 register struct process *pw=0,*px; 1301 register int jobid = 0; 1302 int nochild = 1; 1303 char intr = 0; 1304 if(pid <= 0) 1305 { 1306 if(pid==0) 1307 goto done; 1308 pid = -pid; 1309 intr = 1; 1310 } 1311 job_lock(); 1312 if(pid > 1) 1313 { 1314 if(pid==sh.spid) 1315 sh.spid = 0; 1316 if(!(pw=job_bypid(pid))) 1317 { 1318 /* check to see whether job status has been saved */ 1319 if((sh.exitval = job_chksave(pid)) < 0) 1320 sh.exitval = ERROR_NOENT; 1321 exitset(); 1322 job_unlock(); 1323 return(nochild); 1324 } 1325 else if(intr && pw->p_env!=sh.curenv) 1326 { 1327 sh.exitval = ERROR_NOENT; 1328 job_unlock(); 1329 return(nochild); 1330 } 1331 jobid = pw->p_job; 1332 if(!intr) 1333 pw->p_flag &= ~P_EXITSAVE; 1334 if(pw->p_pgrp && job.parent!= (pid_t)-1) 1335 job_set(job_byjid(jobid)); 1336 } 1337 pwfg = pw; 1338 #ifdef DEBUG 1339 sfprintf(sfstderr,"ksh: job line %4d: wait pid=%d critical=%d job=%d pid=%d\n",__LINE__,getpid(),job.in_critical,jobid,pid); 1340 if(pw) 1341 sfprintf(sfstderr,"ksh: job line %4d: wait pid=%d critical=%d flags=%o\n",__LINE__,getpid(),job.in_critical,pw->p_flag); 1342 #endif /* DEBUG*/ 1343 errno = 0; 1344 if(sh.coutpipe>=0 && sh.cpid==lastpid) 1345 { 1346 sh_close(sh.coutpipe); 1347 sh_close(sh.cpipe[1]); 1348 sh.cpipe[1] = sh.coutpipe = -1; 1349 } 1350 while(1) 1351 { 1352 if(job.waitsafe) 1353 { 1354 for(px=job.pwlist;px; px = px->p_nxtjob) 1355 { 1356 if(px!=pw && (px->p_flag&P_NOTIFY)) 1357 { 1358 if(sh_isoption(SH_NOTIFY)) 1359 { 1360 outfile = sfstderr; 1361 job_list(px,JOB_NFLAG|JOB_NLFLAG); 1362 sfsync(sfstderr); 1363 } 1364 else if(!sh_isoption(SH_INTERACTIVE) && (px->p_flag&P_SIGNALLED)) 1365 { 1366 job_prmsg(px); 1367 px->p_flag &= ~P_NOTIFY; 1368 } 1369 } 1370 } 1371 } 1372 if(pw && (pw->p_flag&(P_DONE|P_STOPPED))) 1373 { 1374 #ifdef SIGTSTP 1375 if(pw->p_flag&P_STOPPED) 1376 { 1377 pw->p_flag |= P_EXITSAVE; 1378 if(sh_isoption(SH_INTERACTIVE) && !sh_isstate(SH_FORKED)) 1379 { 1380 if( pw->p_exit!=SIGTTIN && pw->p_exit!=SIGTTOU) 1381 break; 1382 1383 killpg(pw->p_pgrp,SIGCONT); 1384 } 1385 else /* ignore stop when non-interactive */ 1386 pw->p_flag &= ~(P_NOTIFY|P_SIGNALLED|P_STOPPED|P_EXITSAVE); 1387 } 1388 else 1389 #endif /* SIGTSTP */ 1390 { 1391 if(pw->p_flag&P_SIGNALLED) 1392 { 1393 pw->p_flag &= ~P_NOTIFY; 1394 job_prmsg(pw); 1395 } 1396 else if(pw->p_flag&P_DONE) 1397 pw->p_flag &= ~P_NOTIFY; 1398 if(pw->p_job==jobid) 1399 { 1400 px = job_byjid(jobid); 1401 /* last process in job */ 1402 if(sh_isoption(SH_PIPEFAIL)) 1403 { 1404 /* last non-zero exit */ 1405 for(;px;px=px->p_nxtproc) 1406 { 1407 if(px->p_exit) 1408 break; 1409 } 1410 if(!px) 1411 px = pw; 1412 } 1413 else if(px!=pw) 1414 px = 0; 1415 if(px) 1416 { 1417 sh.exitval=px->p_exit; 1418 if(px->p_flag&P_SIGNALLED) 1419 sh.exitval |= SH_EXITSIG; 1420 if(intr) 1421 px->p_flag &= ~P_EXITSAVE; 1422 } 1423 } 1424 px = job_unpost(pw,1); 1425 if(!px || !sh_isoption(SH_PIPEFAIL) || !job.waitall) 1426 break; 1427 pw = px; 1428 continue; 1429 } 1430 } 1431 sfsync(sfstderr); 1432 job.waitsafe = 0; 1433 nochild = job_reap(job.savesig); 1434 if(job.waitsafe) 1435 continue; 1436 if(nochild) 1437 break; 1438 if(sh.sigflag[SIGALRM]&SH_SIGTRAP) 1439 sh_timetraps(); 1440 if((intr && sh.trapnote) || (pid==1 && !intr)) 1441 break; 1442 } 1443 pwfg = 0; 1444 job_unlock(); 1445 if(pid==1) 1446 return(nochild); 1447 exitset(); 1448 if(pw->p_pgrp) 1449 { 1450 job_reset(pw); 1451 /* propogate keyboard interrupts to parent */ 1452 if((pw->p_flag&P_SIGNALLED) && pw->p_exit==SIGINT && !(sh.sigflag[SIGINT]&SH_SIGOFF)) 1453 sh_fault(SIGINT); 1454 #ifdef SIGTSTP 1455 else if((pw->p_flag&P_STOPPED) && pw->p_exit==SIGTSTP) 1456 { 1457 job.parent = 0; 1458 sh_fault(SIGTSTP); 1459 } 1460 #endif /* SIGTSTP */ 1461 } 1462 else 1463 { 1464 if(pw->p_pid == tcgetpgrp(JOBTTY)) 1465 { 1466 if(pw->p_pgrp==0) 1467 pw->p_pgrp = pw->p_pid; 1468 job_reset(pw); 1469 } 1470 tty_set(-1, 0, NIL(struct termios*)); 1471 } 1472 done: 1473 if(!job.waitall && sh_isoption(SH_PIPEFAIL)) 1474 return(nochild); 1475 if(!sh.intrap) 1476 { 1477 job_lock(); 1478 for(pw=job.pwlist; pw; pw=px) 1479 { 1480 px = pw->p_nxtjob; 1481 job_unpost(pw,0); 1482 } 1483 job_unlock(); 1484 } 1485 return(nochild); 1486 } 1487 1488 /* 1489 * move job to foreground if bgflag == 'f' 1490 * move job to background if bgflag == 'b' 1491 * disown job if bgflag == 'd' 1492 */ 1493 1494 int job_switch(register struct process *pw,int bgflag) 1495 { 1496 register const char *msg; 1497 job_lock(); 1498 if(!pw || !(pw=job_byjid((int)pw->p_job))) 1499 { 1500 job_unlock(); 1501 return(1); 1502 } 1503 if(bgflag=='d') 1504 { 1505 for(; pw; pw=pw->p_nxtproc) 1506 pw->p_flag |= P_DISOWN; 1507 job_unlock(); 1508 return(0); 1509 } 1510 #ifdef SIGTSTP 1511 if(bgflag=='b') 1512 { 1513 sfprintf(outfile,"[%d]\t",(int)pw->p_job); 1514 sh.bckpid = pw->p_pid; 1515 #ifdef SHOPT_BGX 1516 pw->p_flag |= P_BG; 1517 #endif 1518 msg = "&"; 1519 } 1520 else 1521 { 1522 job_unlink(pw); 1523 pw->p_nxtjob = job.pwlist; 1524 job.pwlist = pw; 1525 msg = ""; 1526 } 1527 hist_list(sh.hist_ptr,outfile,pw->p_name,'&',";"); 1528 sfputr(outfile,msg,'\n'); 1529 sfsync(outfile); 1530 if(bgflag=='f') 1531 { 1532 if(!(pw=job_unpost(pw,1))) 1533 { 1534 job_unlock(); 1535 return(1); 1536 } 1537 job.waitall = 1; 1538 pw->p_flag |= P_FG; 1539 #ifdef SHOPT_BGX 1540 pw->p_flag &= ~P_BG; 1541 #endif 1542 job_wait(pw->p_pid); 1543 job.waitall = 0; 1544 } 1545 else if(pw->p_flag&P_STOPPED) 1546 job_unstop(pw); 1547 #endif /* SIGTSTP */ 1548 job_unlock(); 1549 return(0); 1550 } 1551 1552 1553 #ifdef SIGTSTP 1554 /* 1555 * Set the foreground group associated with a job 1556 */ 1557 1558 static void job_fgrp(register struct process *pw, int newgrp) 1559 { 1560 for(; pw; pw=pw->p_nxtproc) 1561 pw->p_fgrp = newgrp; 1562 } 1563 1564 /* 1565 * turn off STOP state of a process group and send CONT signals 1566 */ 1567 1568 static void job_unstop(register struct process *px) 1569 { 1570 register struct process *pw; 1571 register int num = 0; 1572 for(pw=px ;pw ;pw=pw->p_nxtproc) 1573 { 1574 if(pw->p_flag&P_STOPPED) 1575 { 1576 num++; 1577 pw->p_flag &= ~(P_STOPPED|P_SIGNALLED|P_NOTIFY); 1578 } 1579 } 1580 if(num!=0) 1581 { 1582 if(px->p_fgrp != px->p_pgrp) 1583 killpg(px->p_fgrp,SIGCONT); 1584 killpg(px->p_pgrp,SIGCONT); 1585 } 1586 } 1587 #endif /* SIGTSTP */ 1588 1589 /* 1590 * remove a job from table 1591 * If all the processes have not completed, unpost first non-completed process 1592 * Otherwise the job is removed and job_unpost returns NULL. 1593 * pwlist is reset if the first job is removed 1594 * if <notify> is non-zero, then jobs with pending notifications are unposted 1595 */ 1596 1597 static struct process *job_unpost(register struct process *pwtop,int notify) 1598 { 1599 register struct process *pw; 1600 /* make sure all processes are done */ 1601 #ifdef DEBUG 1602 sfprintf(sfstderr,"ksh: job line %4d: drop pid=%d critical=%d pid=%d env=%d\n",__LINE__,getpid(),job.in_critical,pwtop->p_pid,pwtop->p_env); 1603 sfsync(sfstderr); 1604 #endif /* DEBUG */ 1605 pwtop = pw = job_byjid((int)pwtop->p_job); 1606 #ifdef SHOPT_BGX 1607 if(pw->p_flag&P_BG) 1608 return(pw); 1609 #endif /* SHOPT_BGX */ 1610 for(; pw && (pw->p_flag&P_DONE)&&(notify||!(pw->p_flag&P_NOTIFY)||pw->p_env); pw=pw->p_nxtproc); 1611 if(pw) 1612 return(pw); 1613 /* all processes complete, unpost job */ 1614 job_unlink(pwtop); 1615 for(pw=pwtop; pw; pw=pw->p_nxtproc) 1616 { 1617 /* save the exit status for background jobs */ 1618 if((pw->p_flag&P_EXITSAVE) || pw->p_pid==sh.spid) 1619 { 1620 struct jobsave *jp; 1621 /* save status for future wait */ 1622 if(jp = jobsave_create(pw->p_pid)) 1623 { 1624 jp->exitval = pw->p_exit; 1625 if(pw->p_flag&P_SIGNALLED) 1626 jp->exitval |= SH_EXITSIG; 1627 } 1628 pw->p_flag &= ~P_EXITSAVE; 1629 } 1630 pw->p_flag &= ~P_DONE; 1631 job.numpost--; 1632 pw->p_nxtjob = freelist; 1633 freelist = pw; 1634 } 1635 pwtop->p_pid = 0; 1636 #ifdef DEBUG 1637 sfprintf(sfstderr,"ksh: job line %4d: free pid=%d critical=%d job=%d\n",__LINE__,getpid(),job.in_critical,pwtop->p_job); 1638 sfsync(sfstderr); 1639 #endif /* DEBUG */ 1640 job_free((int)pwtop->p_job); 1641 return((struct process*)0); 1642 } 1643 1644 /* 1645 * unlink a job form the job list 1646 */ 1647 static void job_unlink(register struct process *pw) 1648 { 1649 register struct process *px; 1650 if(pw==job.pwlist) 1651 { 1652 job.pwlist = pw->p_nxtjob; 1653 job.curpgid = 0; 1654 return; 1655 } 1656 for(px=job.pwlist;px;px=px->p_nxtjob) 1657 if(px->p_nxtjob == pw) 1658 { 1659 px->p_nxtjob = pw->p_nxtjob; 1660 return; 1661 } 1662 } 1663 1664 /* 1665 * get an unused job number 1666 * freejobs is a bit vector, 0 is unused 1667 */ 1668 1669 static int job_alloc(void) 1670 { 1671 register int j=0; 1672 register unsigned mask = 1; 1673 register unsigned char *freeword; 1674 register int jmax = BYTE(sh.lim.child_max); 1675 /* skip to first word with a free slot */ 1676 for(j=0;job.freejobs[j] == UCHAR_MAX; j++); 1677 if(j >= jmax) 1678 { 1679 register struct process *pw; 1680 for(j=1; j < sh.lim.child_max; j++) 1681 { 1682 if((pw=job_byjid(j))&& !job_unpost(pw,0)) 1683 break; 1684 } 1685 j /= CHAR_BIT; 1686 if(j >= jmax) 1687 return(-1); 1688 } 1689 freeword = &job.freejobs[j]; 1690 j *= CHAR_BIT; 1691 for(j++;mask&(*freeword);j++,mask <<=1); 1692 *freeword |= mask; 1693 return(j); 1694 } 1695 1696 /* 1697 * return a job number 1698 */ 1699 1700 static void job_free(register int n) 1701 { 1702 register int j = (--n)/CHAR_BIT; 1703 register unsigned mask; 1704 n -= j*CHAR_BIT; 1705 mask = 1 << n; 1706 job.freejobs[j] &= ~mask; 1707 } 1708 1709 static char *job_sigmsg(int sig) 1710 { 1711 static char signo[40]; 1712 #ifdef apollo 1713 /* 1714 * This code handles the formatting for the apollo specific signal 1715 * SIGAPOLLO. 1716 */ 1717 extern char *apollo_error(void); 1718 1719 if ( sig == SIGAPOLLO ) 1720 return( apollo_error() ); 1721 #endif /* apollo */ 1722 if(sig<=sh.sigmax && sh.sigmsg[sig]) 1723 return(sh.sigmsg[sig]); 1724 #if defined(SIGRTMIN) && defined(SIGRTMAX) 1725 if(sig>=sh.sigruntime[SH_SIGRTMIN] && sig<=sh.sigruntime[SH_SIGRTMAX]) 1726 { 1727 static char sigrt[20]; 1728 if(sig>sh.sigruntime[SH_SIGRTMIN]+(sh.sigruntime[SH_SIGRTMAX]-sig<=sh.sigruntime[SH_SIGRTMIN])/2) 1729 sfsprintf(sigrt,sizeof(sigrt),"SIGRTMAX-%d",sh.sigruntime[SH_SIGRTMAX]-sig); 1730 else 1731 sfsprintf(sigrt,sizeof(sigrt),"SIGRTMIN+%d",sig-sh.sigruntime[SH_SIGRTMIN]); 1732 return(sigrt); 1733 } 1734 #endif 1735 sfsprintf(signo,sizeof(signo),sh_translate(e_signo),sig); 1736 return(signo); 1737 } 1738 1739 /* 1740 * see whether exit status has been saved and delete it 1741 * if pid==0, then oldest saved process is deleted 1742 * If pid is not found a -1 is returned. 1743 */ 1744 static int job_chksave(register pid_t pid) 1745 { 1746 register struct jobsave *jp = bck.list, *jpold=0; 1747 register int r= -1; 1748 register int count=bck.count; 1749 while(jp && count-->0) 1750 { 1751 if(jp->pid==pid) 1752 break; 1753 if(pid==0 && !jp->next) 1754 break; 1755 jpold = jp; 1756 jp = jp->next; 1757 } 1758 if(jp) 1759 { 1760 r = 0; 1761 if(pid) 1762 r = jp->exitval; 1763 if(jpold) 1764 jpold->next = jp->next; 1765 else 1766 bck.list = jp->next; 1767 bck.count--; 1768 if(njob_savelist < NJOB_SAVELIST) 1769 { 1770 njob_savelist++; 1771 jp->next = job_savelist; 1772 job_savelist = jp; 1773 } 1774 else 1775 free((void*)jp); 1776 } 1777 return(r); 1778 } 1779 1780 void *job_subsave(void) 1781 { 1782 struct back_save *bp = new_of(struct back_save,0); 1783 job_lock(); 1784 *bp = bck; 1785 bck.count = 0; 1786 bck.list = 0; 1787 job_unlock(); 1788 return((void*)bp); 1789 } 1790 1791 void job_subrestore(void* ptr) 1792 { 1793 register struct jobsave *jp; 1794 register struct back_save *bp = (struct back_save*)ptr; 1795 register struct process *pw, *px, *pwnext; 1796 struct jobsave *jpnext; 1797 job_lock(); 1798 for(jp=bck.list; jp; jp=jpnext) 1799 { 1800 jpnext = jp->next; 1801 if(jp->pid==sh.spid) 1802 { 1803 jp->next = bp->list; 1804 bp->list = jp; 1805 bp->count++; 1806 } 1807 else 1808 job_chksave(jp->pid); 1809 } 1810 for(pw=job.pwlist; pw; pw=pwnext) 1811 { 1812 pwnext = pw->p_nxtjob; 1813 if(pw->p_env != sh.curenv || pw->p_pid==sh.pipepid) 1814 continue; 1815 for(px=pw; px; px=px->p_nxtproc) 1816 px->p_flag |= P_DONE; 1817 job_unpost(pw,0); 1818 } 1819 1820 /* 1821 * queue up old lists for disposal by job_reap() 1822 */ 1823 1824 bck = *bp; 1825 free((void*)bp); 1826 job_unlock(); 1827 } 1828 1829 int sh_waitsafe(void) 1830 { 1831 return(job.waitsafe); 1832 } 1833 1834 void job_fork(pid_t parent) 1835 { 1836 #ifdef DEBUG 1837 sfprintf(sfstderr,"ksh: job line %4d: fork pid=%d critical=%d parent=%d\n",__LINE__,getpid(),job.in_critical,parent); 1838 #endif /* DEBUG */ 1839 switch (parent) 1840 { 1841 case -1: 1842 job_lock(); 1843 break; 1844 case 0: 1845 job_unlock(); 1846 job.waitsafe = 0; 1847 job.in_critical = 0; 1848 break; 1849 default: 1850 job_chksave(parent); 1851 job_unlock(); 1852 break; 1853 } 1854 } 1855