1 /***********************************************************************
3 * This software is part of the ast package *
4 * Copyright (c) 1982-2010 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Common Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
13 * Information and Software Systems Research *
17 * David Korn <dgk@research.att.com> *
19 ***********************************************************************/
22 * Job control for UNIX Shell
27 * Written October, 1982
28 * Rewritten April, 1988
29 * Revised January, 1992
38 #if !defined(WCONTINUED) || !defined(WIFCONTINUED)
42 # define WIFCONTINUED(wstat) (0)
45 #define NJOB_SAVELIST 4
48 * temporary hack to get W* macros to work
51 #define wait ______wait
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
60 unsigned short exitval
;
63 static struct jobsave
*job_savelist
;
64 static int njob_savelist
;
65 static struct process
*pwfg
;
67 static void init_savelist(void)
69 register struct jobsave
*jp
;
70 while(njob_savelist
< NJOB_SAVELIST
)
72 jp
= newof(0,struct jobsave
,1,0);
73 jp
->next
= job_savelist
;
85 #define BYTE(n) (((n)+CHAR_BIT-1)/CHAR_BIT)
87 #define SH_STOPSIG (SH_EXITSIG<<1)
91 # ifdef _POSIX_VDISABLE
92 # define CNSUSP _POSIX_VDISABLE
95 # endif /* _POSIX_VDISABLE */
101 # define CSWTCH ('z'&037)
107 #define P_EXITSAVE 01
110 #define P_SIGNALLED 010
113 #define P_COREDUMP 0100
114 #define P_DISOWN 0200
118 #endif /* SHOPT_BGX */
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
;
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
;
147 extern const char e_coredump
[];
151 static void job_unstop(struct process
*);
152 static void job_fgrp(struct process
*, int);
153 # ifndef _lib_tcgetpgrp
156 # define tcgetpgrp(a) (ioctl(a, TIOCGPGRP, &_i_)>=0?_i_:-1)
157 # endif /* TIOCGPGRP */
158 int tcsetpgrp(int fd
,pid_t pgrp
)
162 return(ioctl(fd
, TIOCSPGRP
, &pgid
));
165 # endif /* TIOCGPGRP */
167 # endif /* _lib_tcgetpgrp */
169 # define job_unstop(pw)
175 #endif /* OTTYDISC */
179 typedef int (*Waitevent_f
)(int,long,int);
182 void job_chldtrap(Shell_t
*shp
, const char *trap
, int unpost
)
184 register struct process
*pw
,*pwnext
;
186 int oldexit
,trapnote
;
188 shp
->sigflag
[SIGCHLD
] &= ~SH_SIGTRAP
;
189 trapnote
= shp
->trapnote
;
191 for(pw
=job
.pwlist
;pw
;pw
=pwnext
)
193 pwnext
= pw
->p_nxtjob
;
194 if((pw
->p_flag
&(P_BG
|P_DONE
)) != (P_BG
|P_DONE
))
197 bckpid
= shp
->bckpid
;
198 oldexit
= shp
->savexit
;
199 shp
->bckpid
= pw
->p_pid
;
200 shp
->savexit
= pw
->p_exit
;
201 if(pw
->p_flag
&P_SIGNALLED
)
202 shp
->savexit
|= SH_EXITSIG
;
204 if(pw
->p_pid
==bckpid
&& unpost
)
206 shp
->savexit
= oldexit
;
207 shp
->bckpid
= bckpid
;
209 shp
->trapnote
= trapnote
;
212 #endif /* SHOPT_BGX */
215 * return next on link list of jobsave free list
217 static struct jobsave
*jobsave_create(pid_t pid
)
219 register struct jobsave
*jp
= job_savelist
;
221 if(++bck
.count
> sh
.lim
.child_max
)
226 job_savelist
= jp
->next
;
229 jp
= newof(0,struct jobsave
,1,0);
242 * When called with sig==0, it does a blocking wait
244 int job_reap(register int sig
)
247 register struct process
*pw
;
251 int nochild
=0, oerrno
, wstat
;
252 Waitevent_f waitevent
= sh
.waitevent
;
253 static int wcontinued
= WCONTINUED
;
256 errormsg(SH_DICT
,ERROR_warn(0),"vmbusy() inside job_reap() -- should not happen");
257 if (getenv("_AST_KSH_VMBUSY_ABORT"))
261 if(sfprintf(sfstderr
,"ksh: job line %4d: reap pid=%d critical=%d signal=%d\n",__LINE__
,getpid(),job
.in_critical
,sig
) <=0)
262 write(2,"waitsafe\n",9);
267 flags
= WNOHANG
|WUNTRACED
|wcontinued
;
269 flags
= WUNTRACED
|wcontinued
;
274 if(!(flags
&WNOHANG
) && !sh
.intrap
&& job
.pwlist
)
276 sh_onstate(SH_TTYWAIT
);
277 if(waitevent
&& (*waitevent
)(-1,-1L,0))
280 pid
= waitpid((pid_t
)-1,&wstat
,flags
);
281 sh_offstate(SH_TTYWAIT
);
284 * some systems (linux 2.6) may return EINVAL
285 * when there are no continued children
288 if (pid
<0 && errno
==EINVAL
&& (flags
&WCONTINUED
))
289 pid
= waitpid((pid_t
)-1,&wstat
,flags
&=~WCONTINUED
);
291 if(pid
<0 && errno
==EINTR
&& (sig
||job
.savesig
))
299 if(!(pw
=job_bypid(pid
)))
302 sfprintf(sfstderr
,"ksh: job line %4d: reap pid=%d critical=%d unknown job pid=%d pw=%x\n",__LINE__
,getpid(),job
.in_critical
,pid
,pw
);
304 if (WIFCONTINUED(wstat
) && wcontinued
)
312 jp
= jobsave_create(pid
);
314 lastpid
= pw
->p_pid
= pid
;
316 if(jp
&& WIFSTOPPED(wstat
))
318 jp
->exitval
= SH_STOPSIG
;
324 px
=job_byjid(pw
->p_job
);
325 if(WIFSTOPPED(wstat
))
329 /* move to top of job list */
331 px
->p_nxtjob
= job
.pwlist
;
334 pw
->p_flag
|= (P_NOTIFY
|P_SIGNALLED
|P_STOPPED
);
335 pw
->p_exit
= WSTOPSIG(wstat
);
336 if(pw
->p_pgrp
&& pw
->p_pgrp
==job
.curpgid
&& sh_isstate(SH_STOPOK
))
337 sh_fault(pw
->p_exit
);
340 else if (WIFCONTINUED(wstat
) && wcontinued
)
341 pw
->p_flag
&= ~(P_NOTIFY
|P_SIGNALLED
|P_STOPPED
);
345 /* check for coprocess completion */
348 sh_close(sh
.coutpipe
);
349 sh_close(sh
.cpipe
[1]);
356 pw
->p_flag
&= ~(P_STOPPED
|P_SIGNALLED
);
357 if (WIFSIGNALED(wstat
))
359 pw
->p_flag
|= (P_DONE
|P_NOTIFY
|P_SIGNALLED
);
360 if (WTERMCORE(wstat
))
361 pw
->p_flag
|= P_COREDUMP
;
362 pw
->p_exit
= WTERMSIG(wstat
);
363 /* if process in current jobs terminates from
364 * an interrupt, propogate to parent shell
366 if(pw
->p_pgrp
&& pw
->p_pgrp
==job
.curpgid
&& pw
->p_exit
==SIGINT
&& sh_isstate(SH_STOPOK
))
368 pw
->p_flag
&= ~P_NOTIFY
;
369 sh_offstate(SH_STOPOK
);
371 sh_onstate(SH_STOPOK
);
376 pw
->p_flag
|= (P_DONE
|P_NOTIFY
);
377 pw
->p_exit
= pw
->p_exitmin
;
378 if(WEXITSTATUS(wstat
) > pw
->p_exitmin
)
379 pw
->p_exit
= WEXITSTATUS(wstat
);
382 if((pw
->p_flag
&P_DONE
) && (pw
->p_flag
&P_BG
))
385 if(sh
.st
.trapcom
[SIGCHLD
])
387 sh
.sigflag
[SIGCHLD
] |= SH_SIGTRAP
;
389 job_chldtrap(&sh
,sh
.st
.trapcom
[SIGCHLD
],0);
391 sh
.trapnote
|= SH_SIGTRAP
;
396 #endif /* SHOPT_BGX */
398 pw
->p_flag
&= ~P_NOTIFY
;
400 if(jp
&& pw
== &dummy
)
402 jp
->exitval
= pw
->p_exit
;
403 if(pw
->p_flag
&P_SIGNALLED
)
404 jp
->exitval
|= SH_EXITSIG
;
407 sfprintf(sfstderr
,"ksh: job line %4d: reap pid=%d critical=%d job %d with pid %d flags=%o complete with status=%x exit=%d\n",__LINE__
,getpid(),job
.in_critical
,pw
->p_job
,pid
,pw
->p_flag
,wstat
,pw
->p_exit
);
410 /* only top-level process in job should have notify set */
412 pw
->p_flag
&= ~P_NOTIFY
;
413 if(pid
==pw
->p_fgrp
&& pid
==tcgetpgrp(JOBTTY
))
415 px
= job_byjid((int)pw
->p_job
);
416 for(; px
&& (px
->p_flag
&P_DONE
); px
=px
->p_nxtproc
);
418 tcsetpgrp(JOBTTY
,job
.mypid
);
421 if(!sh
.intrap
&& sh
.st
.trapcom
[SIGCHLD
] && pid
>0 && (pwfg
!=job_bypid(pid
)))
423 sh
.sigflag
[SIGCHLD
] |= SH_SIGTRAP
;
424 sh
.trapnote
|= SH_SIGTRAP
;
433 #endif /* SHOPT_BGX */
436 sh
.waitevent
= waitevent
;
437 if(sh_isoption(SH_NOTIFY
) && sh_isstate(SH_TTYWAIT
))
440 job_list(pw
,JOB_NFLAG
|JOB_NLFLAG
);
445 signal(sig
, job_waitsafe
);
450 * This is the SIGCLD interrupt routine
452 static void job_waitsafe(int sig
)
454 if(job
.in_critical
|| vmbusy())
464 * initialize job control if possible
465 * if lflag is set the switching driver message will not print
467 void job_init(Shell_t
*shp
, int lflag
)
471 signal(SIGCHLD
,job_waitsafe
);
472 # if defined(SIGCLD) && (SIGCLD!=SIGCHLD)
473 signal(SIGCLD
,job_waitsafe
);
475 if(njob_savelist
< NJOB_SAVELIST
)
477 if(!sh_isoption(SH_INTERACTIVE
))
479 /* use new line discipline when available */
482 if((job
.linedisc
= ioctl(JOBTTY
, FIOLOOKLD
, 0)) <0)
484 if(ioctl(JOBTTY
,TIOCGETD
,&job
.linedisc
) !=0)
485 # endif /* FIOLOOKLD */
487 if(job
.linedisc
!=NTTYDISC
&& job
.linedisc
!=OTTYDISC
)
489 /* no job control when running with MPX */
491 sh_onoption(SH_VIRAW
);
492 # endif /* SHOPT_VSH */
495 if(job
.linedisc
==NTTYDISC
)
497 #endif /* NTTYDISC */
499 job
.mypgid
= getpgrp();
500 /* some systems have job control, but not initialized */
503 /* Get a controlling terminal and set process group */
504 /* This should have already been done by rlogin */
506 register char *ttynam
;
510 if(job
.mypgid
<0 || !(ttynam
=ttyname(JOBTTY
)))
513 if((fd
= open(ttynam
,O_RDWR
)) <0)
516 sh_iorenumber(shp
,fd
,JOBTTY
);
517 job
.mypgid
= shp
->pid
;
519 tcsetpgrp(JOBTTY
,shp
->pid
);
524 if(possible
= (setpgid(0,job
.mypgid
)>=0) || errno
==EPERM
)
526 /* wait until we are in the foreground */
527 while((job
.mytgid
=tcgetpgrp(JOBTTY
)) != job
.mypgid
)
531 /* Stop this shell until continued */
532 signal(SIGTTIN
,SIG_DFL
);
533 kill(shp
->pid
,SIGTTIN
);
534 /* resumes here after continue tries again */
535 if(ntry
++ > IOMAXTRY
)
537 errormsg(SH_DICT
,0,e_no_start
);
545 /* set the line discipline */
548 int linedisc
= NTTYDISC
;
550 tty_get(JOBTTY
,&my_stty
);
551 if (ioctl(JOBTTY
, FIOPOPLD
, 0) < 0)
553 if (ioctl(JOBTTY
, FIOPUSHLD
, &linedisc
) < 0)
555 ioctl(JOBTTY
, FIOPUSHLD
, &job
.linedisc
);
558 tty_set(JOBTTY
,TCSANOW
,&my_stty
);
560 if(ioctl(JOBTTY
,TIOCSETD
,&linedisc
) !=0)
562 # endif /* FIOPUSHLD */
564 errormsg(SH_DICT
,0,e_newtty
);
568 #endif /* NTTYDISC */
573 /* make sure that we are a process group leader */
575 # if defined(SA_NOCLDSTOP) || defined(SA_NOCLDWAIT)
576 # if !defined(SA_NOCLDSTOP)
577 # define SA_NOCLDSTOP 0
579 # if !defined(SA_NOCLDWAIT)
580 # define SA_NOCLDWAIT 0
582 sigflag(SIGCHLD
, SA_NOCLDSTOP
|SA_NOCLDWAIT
, 0);
583 # endif /* SA_NOCLDSTOP || SA_NOCLDWAIT */
584 signal(SIGTTIN
,SIG_IGN
);
585 signal(SIGTTOU
,SIG_IGN
);
586 /* The shell now handles ^Z */
587 signal(SIGTSTP
,sh_fault
);
588 tcsetpgrp(JOBTTY
,shp
->pid
);
590 /* set the switch character */
591 tty_get(JOBTTY
,&my_stty
);
592 job
.suspend
= (unsigned)my_stty
.c_cc
[VSUSP
];
593 if(job
.suspend
== (unsigned char)CNSUSP
)
595 my_stty
.c_cc
[VSUSP
] = CSWTCH
;
596 tty_set(JOBTTY
,TCSAFLUSH
,&my_stty
);
599 sh_onoption(SH_MONITOR
);
601 job
.mypid
= shp
->pid
;
608 * see if there are any stopped jobs
609 * restore tty driver and pgrp
611 int job_close(Shell_t
* shp
)
613 register struct process
*pw
;
614 register int count
= 0, running
= 0;
615 if(possible
&& !job
.jobcontrol
)
617 else if(!possible
&& (!sh_isstate(SH_MONITOR
) || sh_isstate(SH_FORKED
)))
619 else if(getpid() != job
.mypid
)
624 for(pw
=job
.pwlist
;pw
;pw
=pw
->p_nxtjob
)
626 if(!(pw
->p_flag
&P_STOPPED
))
628 if(!(pw
->p_flag
&P_DONE
))
633 killpg(pw
->p_pgrp
,SIGTERM
);
636 if(beenhere
++ == 0 && job
.pwlist
)
640 errormsg(SH_DICT
,0,e_terminate
);
643 else if(running
&& shp
->login_sh
)
645 errormsg(SH_DICT
,0,e_jobsrunning
);
651 if(possible
&& setpgid(0,job
.mypgid
)>=0)
652 tcsetpgrp(job
.fd
,job
.mypgid
);
653 # endif /* SIGTSTP */
657 /* restore old line discipline */
659 tty_get(job
.fd
,&my_stty
);
660 if (ioctl(job
.fd
, FIOPOPLD
, 0) < 0)
662 if (ioctl(job
.fd
, FIOPUSHLD
, &job
.linedisc
) < 0)
664 job
.linedisc
= NTTYDISC
;
665 ioctl(job
.fd
, FIOPUSHLD
, &job
.linedisc
);
668 tty_set(job
.fd
,TCSAFLUSH
,&my_stty
);
670 if(ioctl(job
.fd
,TIOCSETD
,&job
.linedisc
) !=0)
672 # endif /* FIOPUSHLD */
673 errormsg(SH_DICT
,0,e_oldtty
);
675 # endif /* NTTYDISC */
677 if(possible
&& job
.suspend
==CNSUSP
)
679 tty_get(job
.fd
,&my_stty
);
680 my_stty
.c_cc
[VSUSP
] = CNSUSP
;
681 tty_set(job
.fd
,TCSAFLUSH
,&my_stty
);
688 static void job_set(register struct process
*pw
)
690 /* save current terminal state */
691 tty_get(job
.fd
,&my_stty
);
692 if(pw
->p_flag
&P_STTY
)
694 /* restore terminal state for job */
695 tty_set(job
.fd
,TCSAFLUSH
,&pw
->p_stty
);
698 if((pw
->p_flag
&P_STOPPED
) || tcgetpgrp(job
.fd
) == sh
.pid
)
699 tcsetpgrp(job
.fd
,pw
->p_fgrp
);
700 /* if job is stopped, resume it in the background */
705 static void job_reset(register struct process
*pw
)
707 /* save the terminal state for current job */
709 job_fgrp(pw
,tcgetpgrp(job
.fd
));
710 if(tcsetpgrp(job
.fd
,job
.mypid
) !=0)
713 /* force the following tty_get() to do a tcgetattr() unless fg */
714 if(!(pw
->p_flag
&P_FG
))
715 tty_set(-1, 0, NIL(struct termios
*));
716 if(pw
&& (pw
->p_flag
&P_SIGNALLED
) && pw
->p_exit
!=SIGHUP
)
718 if(tty_get(job
.fd
,&pw
->p_stty
) == 0)
719 pw
->p_flag
|= P_STTY
;
720 /* restore terminal state for job */
721 tty_set(job
.fd
,TCSAFLUSH
,&my_stty
);
728 * wait built-in command
731 void job_bwait(char **jobs
)
734 register struct process
*pw
;
738 else while(jp
= *jobs
++)
744 pw
= job_bystring(jp
);
753 pid
= (int)strtol(jp
, (char**)0, 10);
760 * execute function <fun> for each job
763 int job_walk(Sfio_t
*file
,int (*fun
)(struct process
*,int),int arg
,char *joblist
[])
765 register struct process
*pw
;
767 register char *jobid
, **jobs
=joblist
;
768 register struct process
*px
;
780 if(pw
->p_env
!= sh
.jobenv
)
786 else if(*jobs
==0) /* current job */
788 /* skip over non-stop jobs */
789 while(pw
&& (pw
->p_env
!=sh
.jobenv
|| pw
->p_pgrp
==0))
794 else while(jobid
= *jobs
++)
798 errormsg(SH_DICT
,ERROR_exit(1),e_jobusage
,job_string
);
800 pw
= job_bystring(jobid
);
803 int pid
= (int)strtol(jobid
, (char**)0, 10);
806 while(isdigit(*jobid
))
809 errormsg(SH_DICT
,ERROR_exit(1),e_jobusage
,job_string
);
810 if(!(pw
= job_bypid(pid
)))
827 * send signal <sig> to background process group if not disowned
829 int job_terminate(register struct process
*pw
,register int sig
)
831 if(pw
->p_pgrp
&& !(pw
->p_flag
&P_DISOWN
))
838 * flag JOB_LFLAG for long listing
839 * flag JOB_NFLAG for list only jobs marked for notification
840 * flag JOB_PFLAG for process id(s) only
843 int job_list(struct process
*pw
,register int flag
)
845 register struct process
*px
= pw
;
847 register const char *msg
;
849 if(!pw
|| pw
->p_job
<=0)
851 if(pw
->p_env
!= sh
.jobenv
)
853 if((flag
&JOB_NFLAG
) && (!(px
->p_flag
&P_NOTIFY
)||px
->p_pgrp
==0))
857 sfprintf(outfile
,"%d\n",px
->p_pgrp
?px
->p_pgrp
:px
->p_pid
);
860 if((px
->p_flag
&P_DONE
) && job
.waitall
&& !(flag
&JOB_LFLAG
))
866 else if(px
==job
.pwlist
->p_nxtjob
)
871 sfputc(outfile
,'\n');
872 sfprintf(outfile
,"[%d] %c ",n
, msize
);
877 sfprintf(outfile
,"%d\t",px
->p_pid
);
878 if(px
->p_flag
&P_SIGNALLED
)
879 msg
= job_sigmsg((int)(px
->p_exit
));
880 else if(px
->p_flag
&P_NOTIFY
)
882 msg
= sh_translate(e_done
);
886 msg
= sh_translate(e_running
);
887 px
->p_flag
&= ~P_NOTIFY
;
888 sfputr(outfile
,msg
,-1);
892 sfprintf(outfile
,"(%d)",(int)n
);
893 msize
+= (3+(n
>10)+(n
>100));
895 if(px
->p_flag
&P_COREDUMP
)
897 msg
= sh_translate(e_coredump
);
898 sfputr(outfile
, msg
, -1);
899 msize
+= strlen(msg
);
901 sfnputc(outfile
,' ',MAXMSG
>msize
?MAXMSG
-msize
:1);
906 while(px
=px
->p_nxtproc
)
907 px
->p_flag
&= ~P_NOTIFY
;
911 hist_list(sh
.hist_ptr
,outfile
,pw
->p_name
,0,";");
913 sfputr(outfile
, e_nlspace
, -1);
921 * get the process group given the job number
922 * This routine returns the process group number or -1
924 static struct process
*job_bystring(register char *ajob
)
926 register struct process
*pw
=job
.pwlist
;
928 if(*ajob
++ != '%' || !pw
)
929 return(NIL(struct process
*));
932 pw
= job_byjid((int)strtol(ajob
, (char**)0, 10));
933 else if(c
=='+' || c
=='%')
938 pw
= job
.pwlist
->p_nxtjob
;
941 pw
= job_byname(ajob
);
944 return(NIL(struct process
*));
948 * Kill a job or process
951 int job_kill(register struct process
*pw
,register int sig
)
957 int stopsig
= (sig
==SIGSTOP
||sig
==SIGTSTP
||sig
==SIGTTIN
||sig
==SIGTTOU
);
968 if(pid
==0 && job
.jobcontrol
)
969 r
= job_walk(outfile
, job_kill
,sig
, (char**)0);
971 if(sig
==SIGSTOP
&& pid
==sh
.pid
&& sh
.ppid
==1)
973 /* can't stop login shell */
981 if((r
= kill(pid
,sig
))>=0 && !stopsig
)
983 if(pw
->p_flag
&P_STOPPED
)
984 pw
->p_flag
&= ~(P_STOPPED
|P_SIGNALLED
);
991 if((r
= killpg(-pid
,sig
))>=0 && !stopsig
)
993 job_unstop(job_bypid(pw
->p_pid
));
995 killpg(-pid
,SIGCONT
);
1003 r
= killpg(-pid
,sig
);
1004 #endif /* SIGTSTP */
1008 if(pid
= pw
->p_pgrp
)
1010 r
= killpg(pid
,sig
);
1012 if(r
>=0 && (sig
==SIGHUP
||sig
==SIGTERM
|| sig
==SIGCONT
))
1014 #endif /* SIGTSTP */
1018 while(pw
&& pw
->p_pgrp
==0 && (r
=kill(pw
->p_pid
,sig
))>=0)
1021 if(sig
==SIGHUP
|| sig
==SIGTERM
)
1022 kill(pw
->p_pid
,SIGCONT
);
1023 #endif /* SIGTSTP */
1027 if(r
<0 && job_string
)
1031 msg
= sh_translate(e_no_proc
);
1033 msg
= sh_translate(e_no_job
);
1035 msg
= sh_translate(e_access
);
1036 sfprintf(sfstderr
,"kill: %s: %s\n",job_string
, msg
);
1045 * Get process structure from first letters of jobname
1049 static struct process
*job_byname(char *name
)
1051 register struct process
*pw
= job
.pwlist
;
1052 register struct process
*pz
= 0;
1053 register int *flag
= 0;
1054 register char *cp
= name
;
1057 return(NIL(struct process
*));
1060 for(;pw
;pw
=pw
->p_nxtjob
)
1062 if(hist_match(sh
.hist_ptr
,pw
->p_name
,cp
,flag
)>=0)
1065 errormsg(SH_DICT
,ERROR_exit(1),e_jobusage
,name
-1);
1074 # define job_reset(x)
1080 * Initialize the process posting array
1083 void job_clear(void)
1085 register struct process
*pw
, *px
;
1086 register struct process
*pwnext
;
1087 register int j
= BYTE(sh
.lim
.child_max
);
1088 register struct jobsave
*jp
,*jpnext
;
1090 for(pw
=job
.pwlist
; pw
; pw
=pwnext
)
1092 pwnext
= pw
->p_nxtjob
;
1099 for(jp
=bck
.list
; jp
;jp
=jpnext
)
1105 if(njob_savelist
< NJOB_SAVELIST
)
1107 job
.pwlist
= NIL(struct process
*);
1111 #endif /* SHOPT_BGX */
1116 job
.freejobs
= (unsigned char*)malloc((unsigned)(j
+1));
1118 job
.freejobs
[j
--] = 0;
1123 * put the process <pid> on the process list and return the job number
1124 * if non-zero, <join> is the process id of the job to join
1127 int job_post(pid_t pid
, pid_t join
)
1129 register struct process
*pw
;
1130 register History_t
*hp
= sh
.hist_ptr
;
1136 sh
.jobenv
= sh
.curenv
;
1150 #endif /* SHOPT_BGX */
1151 if(njob_savelist
< NJOB_SAVELIST
)
1153 if(pw
= job_bypid(pid
))
1155 if(join
&& (pw
=job_bypid(join
)))
1157 /* if job to join is not first move it to front */
1158 if((pw
=job_byjid(pw
->p_job
)) != job
.pwlist
)
1161 pw
->p_nxtjob
= job
.pwlist
;
1166 freelist
= pw
->p_nxtjob
;
1168 pw
= new_of(struct process
,0);
1171 if(join
&& job
.pwlist
)
1173 /* join existing current job */
1174 pw
->p_nxtjob
= job
.pwlist
->p_nxtjob
;
1175 pw
->p_nxtproc
= job
.pwlist
;
1176 pw
->p_job
= job
.pwlist
->p_job
;
1180 /* create a new job */
1181 while((pw
->p_job
= job_alloc()) < 0)
1183 pw
->p_nxtjob
= job
.pwlist
;
1187 pw
->p_env
= sh
.curenv
;
1189 if(!sh
.outpipe
|| (sh_isoption(SH_PIPEFAIL
) && job
.waitall
))
1190 pw
->p_flag
= P_EXITSAVE
;
1191 pw
->p_exitmin
= sh
.xargexit
;
1193 if(sh_isstate(SH_MONITOR
))
1195 if(killpg(job
.curpgid
,0)<0 && errno
==ESRCH
)
1197 pw
->p_fgrp
= job
.curpgid
;
1201 pw
->p_pgrp
= pw
->p_fgrp
;
1203 sfprintf(sfstderr
,"ksh: job line %4d: post pid=%d critical=%d job=%d pid=%d pgid=%d savesig=%d join=%d\n",__LINE__
,getpid(),job
.in_critical
,pw
->p_job
,
1204 pw
->p_pid
,pw
->p_pgrp
,job
.savesig
,join
);
1208 if(hp
&& !sh_isstate(SH_PROFILE
))
1209 pw
->p_name
=hist_tell(sh
.hist_ptr
,(int)hp
->histind
-1);
1213 if ((val
= job_chksave(pid
)) >= 0)
1216 if(pw
->p_exit
==SH_STOPSIG
)
1218 pw
->p_flag
|= (P_SIGNALLED
|P_STOPPED
);
1221 else if(pw
->p_exit
>= SH_EXITSIG
)
1223 pw
->p_flag
|= P_DONE
|P_SIGNALLED
;
1224 pw
->p_exit
&= SH_EXITMASK
;
1227 pw
->p_flag
|= (P_DONE
|P_NOTIFY
);
1230 if(bg
&& !(pw
->p_flag
&P_DONE
))
1232 #endif /* SHOPT_BGX */
1239 * Returns a process structure give a process id
1242 static struct process
*job_bypid(pid_t pid
)
1244 register struct process
*pw
, *px
;
1245 for(pw
=job
.pwlist
; pw
; pw
=pw
->p_nxtjob
)
1246 for(px
=pw
; px
; px
=px
->p_nxtproc
)
1251 return(NIL(struct process
*));
1255 * return a pointer to a job given the job id
1258 static struct process
*job_byjid(int jobid
)
1260 register struct process
*pw
;
1261 for(pw
=job
.pwlist
;pw
; pw
= pw
->p_nxtjob
)
1263 if(pw
->p_job
==jobid
)
1270 * print a signal message
1272 static void job_prmsg(register struct process
*pw
)
1274 if(pw
->p_exit
!=SIGINT
&& pw
->p_exit
!=SIGPIPE
)
1276 register const char *msg
, *dump
;
1277 msg
= job_sigmsg((int)(pw
->p_exit
));
1278 msg
= sh_translate(msg
);
1279 if(pw
->p_flag
&P_COREDUMP
)
1280 dump
= sh_translate(e_coredump
);
1283 if(sh_isstate(SH_INTERACTIVE
))
1284 sfprintf(sfstderr
,"%s%s\n",msg
,dump
);
1286 errormsg(SH_DICT
,2,"%d: %s%s",pw
->p_pid
,msg
,dump
);
1291 * Wait for process pid to complete
1292 * If pid < -1, then wait can be interrupted, -pid is waited for (wait builtin)
1293 * pid=0 to unpost all done processes
1294 * pid=1 to wait for at least one process to complete
1295 * pid=-1 to wait for all runing processes
1298 int job_wait(register pid_t pid
)
1300 register struct process
*pw
=0,*px
;
1301 register int jobid
= 0;
1316 if(!(pw
=job_bypid(pid
)))
1318 /* check to see whether job status has been saved */
1319 if((sh
.exitval
= job_chksave(pid
)) < 0)
1320 sh
.exitval
= ERROR_NOENT
;
1325 else if(intr
&& pw
->p_env
!=sh
.curenv
)
1327 sh
.exitval
= ERROR_NOENT
;
1333 pw
->p_flag
&= ~P_EXITSAVE
;
1334 if(pw
->p_pgrp
&& job
.parent
!= (pid_t
)-1)
1335 job_set(job_byjid(jobid
));
1339 sfprintf(sfstderr
,"ksh: job line %4d: wait pid=%d critical=%d job=%d pid=%d\n",__LINE__
,getpid(),job
.in_critical
,jobid
,pid
);
1341 sfprintf(sfstderr
,"ksh: job line %4d: wait pid=%d critical=%d flags=%o\n",__LINE__
,getpid(),job
.in_critical
,pw
->p_flag
);
1344 if(sh
.coutpipe
>=0 && sh
.cpid
==lastpid
)
1346 sh_close(sh
.coutpipe
);
1347 sh_close(sh
.cpipe
[1]);
1348 sh
.cpipe
[1] = sh
.coutpipe
= -1;
1354 for(px
=job
.pwlist
;px
; px
= px
->p_nxtjob
)
1356 if(px
!=pw
&& (px
->p_flag
&P_NOTIFY
))
1358 if(sh_isoption(SH_NOTIFY
))
1361 job_list(px
,JOB_NFLAG
|JOB_NLFLAG
);
1364 else if(!sh_isoption(SH_INTERACTIVE
) && (px
->p_flag
&P_SIGNALLED
))
1367 px
->p_flag
&= ~P_NOTIFY
;
1372 if(pw
&& (pw
->p_flag
&(P_DONE
|P_STOPPED
)))
1375 if(pw
->p_flag
&P_STOPPED
)
1377 pw
->p_flag
|= P_EXITSAVE
;
1378 if(sh_isoption(SH_INTERACTIVE
) && !sh_isstate(SH_FORKED
))
1380 if( pw
->p_exit
!=SIGTTIN
&& pw
->p_exit
!=SIGTTOU
)
1383 killpg(pw
->p_pgrp
,SIGCONT
);
1385 else /* ignore stop when non-interactive */
1386 pw
->p_flag
&= ~(P_NOTIFY
|P_SIGNALLED
|P_STOPPED
|P_EXITSAVE
);
1389 #endif /* SIGTSTP */
1391 if(pw
->p_flag
&P_SIGNALLED
)
1393 pw
->p_flag
&= ~P_NOTIFY
;
1396 else if(pw
->p_flag
&P_DONE
)
1397 pw
->p_flag
&= ~P_NOTIFY
;
1398 if(pw
->p_job
==jobid
)
1400 px
= job_byjid(jobid
);
1401 /* last process in job */
1402 if(sh_isoption(SH_PIPEFAIL
))
1404 /* last non-zero exit */
1405 for(;px
;px
=px
->p_nxtproc
)
1417 sh
.exitval
=px
->p_exit
;
1418 if(px
->p_flag
&P_SIGNALLED
)
1419 sh
.exitval
|= SH_EXITSIG
;
1421 px
->p_flag
&= ~P_EXITSAVE
;
1424 px
= job_unpost(pw
,1);
1425 if(!px
|| !sh_isoption(SH_PIPEFAIL
) || !job
.waitall
)
1433 nochild
= job_reap(job
.savesig
);
1438 if(sh
.sigflag
[SIGALRM
]&SH_SIGTRAP
)
1440 if((intr
&& sh
.trapnote
) || (pid
==1 && !intr
))
1451 /* propogate keyboard interrupts to parent */
1452 if((pw
->p_flag
&P_SIGNALLED
) && pw
->p_exit
==SIGINT
&& !(sh
.sigflag
[SIGINT
]&SH_SIGOFF
))
1455 else if((pw
->p_flag
&P_STOPPED
) && pw
->p_exit
==SIGTSTP
)
1460 #endif /* SIGTSTP */
1464 if(pw
->p_pid
== tcgetpgrp(JOBTTY
))
1467 pw
->p_pgrp
= pw
->p_pid
;
1470 tty_set(-1, 0, NIL(struct termios
*));
1473 if(!job
.waitall
&& sh_isoption(SH_PIPEFAIL
))
1478 for(pw
=job
.pwlist
; pw
; pw
=px
)
1489 * move job to foreground if bgflag == 'f'
1490 * move job to background if bgflag == 'b'
1491 * disown job if bgflag == 'd'
1494 int job_switch(register struct process
*pw
,int bgflag
)
1496 register const char *msg
;
1498 if(!pw
|| !(pw
=job_byjid((int)pw
->p_job
)))
1505 for(; pw
; pw
=pw
->p_nxtproc
)
1506 pw
->p_flag
|= P_DISOWN
;
1513 sfprintf(outfile
,"[%d]\t",(int)pw
->p_job
);
1514 sh
.bckpid
= pw
->p_pid
;
1523 pw
->p_nxtjob
= job
.pwlist
;
1527 hist_list(sh
.hist_ptr
,outfile
,pw
->p_name
,'&',";");
1528 sfputr(outfile
,msg
,'\n');
1532 if(!(pw
=job_unpost(pw
,1)))
1540 pw
->p_flag
&= ~P_BG
;
1542 job_wait(pw
->p_pid
);
1545 else if(pw
->p_flag
&P_STOPPED
)
1547 #endif /* SIGTSTP */
1555 * Set the foreground group associated with a job
1558 static void job_fgrp(register struct process
*pw
, int newgrp
)
1560 for(; pw
; pw
=pw
->p_nxtproc
)
1561 pw
->p_fgrp
= newgrp
;
1565 * turn off STOP state of a process group and send CONT signals
1568 static void job_unstop(register struct process
*px
)
1570 register struct process
*pw
;
1571 register int num
= 0;
1572 for(pw
=px
;pw
;pw
=pw
->p_nxtproc
)
1574 if(pw
->p_flag
&P_STOPPED
)
1577 pw
->p_flag
&= ~(P_STOPPED
|P_SIGNALLED
|P_NOTIFY
);
1582 if(px
->p_fgrp
!= px
->p_pgrp
)
1583 killpg(px
->p_fgrp
,SIGCONT
);
1584 killpg(px
->p_pgrp
,SIGCONT
);
1587 #endif /* SIGTSTP */
1590 * remove a job from table
1591 * If all the processes have not completed, unpost first non-completed process
1592 * Otherwise the job is removed and job_unpost returns NULL.
1593 * pwlist is reset if the first job is removed
1594 * if <notify> is non-zero, then jobs with pending notifications are unposted
1597 static struct process
*job_unpost(register struct process
*pwtop
,int notify
)
1599 register struct process
*pw
;
1600 /* make sure all processes are done */
1602 sfprintf(sfstderr
,"ksh: job line %4d: drop pid=%d critical=%d pid=%d env=%d\n",__LINE__
,getpid(),job
.in_critical
,pwtop
->p_pid
,pwtop
->p_env
);
1605 pwtop
= pw
= job_byjid((int)pwtop
->p_job
);
1609 #endif /* SHOPT_BGX */
1610 for(; pw
&& (pw
->p_flag
&P_DONE
)&&(notify
||!(pw
->p_flag
&P_NOTIFY
)||pw
->p_env
); pw
=pw
->p_nxtproc
);
1613 /* all processes complete, unpost job */
1615 for(pw
=pwtop
; pw
; pw
=pw
->p_nxtproc
)
1617 /* save the exit status for background jobs */
1618 if((pw
->p_flag
&P_EXITSAVE
) || pw
->p_pid
==sh
.spid
)
1621 /* save status for future wait */
1622 if(jp
= jobsave_create(pw
->p_pid
))
1624 jp
->exitval
= pw
->p_exit
;
1625 if(pw
->p_flag
&P_SIGNALLED
)
1626 jp
->exitval
|= SH_EXITSIG
;
1628 pw
->p_flag
&= ~P_EXITSAVE
;
1630 pw
->p_flag
&= ~P_DONE
;
1632 pw
->p_nxtjob
= freelist
;
1637 sfprintf(sfstderr
,"ksh: job line %4d: free pid=%d critical=%d job=%d\n",__LINE__
,getpid(),job
.in_critical
,pwtop
->p_job
);
1640 job_free((int)pwtop
->p_job
);
1641 return((struct process
*)0);
1645 * unlink a job form the job list
1647 static void job_unlink(register struct process
*pw
)
1649 register struct process
*px
;
1652 job
.pwlist
= pw
->p_nxtjob
;
1656 for(px
=job
.pwlist
;px
;px
=px
->p_nxtjob
)
1657 if(px
->p_nxtjob
== pw
)
1659 px
->p_nxtjob
= pw
->p_nxtjob
;
1665 * get an unused job number
1666 * freejobs is a bit vector, 0 is unused
1669 static int job_alloc(void)
1672 register unsigned mask
= 1;
1673 register unsigned char *freeword
;
1674 register int jmax
= BYTE(sh
.lim
.child_max
);
1675 /* skip to first word with a free slot */
1676 for(j
=0;job
.freejobs
[j
] == UCHAR_MAX
; j
++);
1679 register struct process
*pw
;
1680 for(j
=1; j
< sh
.lim
.child_max
; j
++)
1682 if((pw
=job_byjid(j
))&& !job_unpost(pw
,0))
1689 freeword
= &job
.freejobs
[j
];
1691 for(j
++;mask
&(*freeword
);j
++,mask
<<=1);
1697 * return a job number
1700 static void job_free(register int n
)
1702 register int j
= (--n
)/CHAR_BIT
;
1703 register unsigned mask
;
1706 job
.freejobs
[j
] &= ~mask
;
1709 static char *job_sigmsg(int sig
)
1711 static char signo
[40];
1714 * This code handles the formatting for the apollo specific signal
1717 extern char *apollo_error(void);
1719 if ( sig
== SIGAPOLLO
)
1720 return( apollo_error() );
1722 if(sig
<=sh
.sigmax
&& sh
.sigmsg
[sig
])
1723 return(sh
.sigmsg
[sig
]);
1724 #if defined(SIGRTMIN) && defined(SIGRTMAX)
1725 if(sig
>=sh
.sigruntime
[SH_SIGRTMIN
] && sig
<=sh
.sigruntime
[SH_SIGRTMAX
])
1727 static char sigrt
[20];
1728 if(sig
>sh
.sigruntime
[SH_SIGRTMIN
]+(sh
.sigruntime
[SH_SIGRTMAX
]-sig
<=sh
.sigruntime
[SH_SIGRTMIN
])/2)
1729 sfsprintf(sigrt
,sizeof(sigrt
),"SIGRTMAX-%d",sh
.sigruntime
[SH_SIGRTMAX
]-sig
);
1731 sfsprintf(sigrt
,sizeof(sigrt
),"SIGRTMIN+%d",sig
-sh
.sigruntime
[SH_SIGRTMIN
]);
1735 sfsprintf(signo
,sizeof(signo
),sh_translate(e_signo
),sig
);
1740 * see whether exit status has been saved and delete it
1741 * if pid==0, then oldest saved process is deleted
1742 * If pid is not found a -1 is returned.
1744 static int job_chksave(register pid_t pid
)
1746 register struct jobsave
*jp
= bck
.list
, *jpold
=0;
1748 register int count
=bck
.count
;
1749 while(jp
&& count
-->0)
1753 if(pid
==0 && !jp
->next
)
1764 jpold
->next
= jp
->next
;
1766 bck
.list
= jp
->next
;
1768 if(njob_savelist
< NJOB_SAVELIST
)
1771 jp
->next
= job_savelist
;
1780 void *job_subsave(void)
1782 struct back_save
*bp
= new_of(struct back_save
,0);
1791 void job_subrestore(void* ptr
)
1793 register struct jobsave
*jp
;
1794 register struct back_save
*bp
= (struct back_save
*)ptr
;
1795 register struct process
*pw
, *px
, *pwnext
;
1796 struct jobsave
*jpnext
;
1798 for(jp
=bck
.list
; jp
; jp
=jpnext
)
1801 if(jp
->pid
==sh
.spid
)
1803 jp
->next
= bp
->list
;
1808 job_chksave(jp
->pid
);
1810 for(pw
=job
.pwlist
; pw
; pw
=pwnext
)
1812 pwnext
= pw
->p_nxtjob
;
1813 if(pw
->p_env
!= sh
.curenv
|| pw
->p_pid
==sh
.pipepid
)
1815 for(px
=pw
; px
; px
=px
->p_nxtproc
)
1816 px
->p_flag
|= P_DONE
;
1821 * queue up old lists for disposal by job_reap()
1829 int sh_waitsafe(void)
1831 return(job
.waitsafe
);
1834 void job_fork(pid_t parent
)
1837 sfprintf(sfstderr
,"ksh: job line %4d: fork pid=%d critical=%d parent=%d\n",__LINE__
,getpid(),job
.in_critical
,parent
);
1847 job
.in_critical
= 0;
1850 job_chksave(parent
);