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