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