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