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