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