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