1*35148Smarc /*
2*35148Smarc
3*35148Smarc * Copyright (c) 1984, 1985, 1986 AT&T
4*35148Smarc * All Rights Reserved
5*35148Smarc
6*35148Smarc * THIS IS UNPUBLISHED PROPRIETARY SOURCE
7*35148Smarc * CODE OF AT&T.
8*35148Smarc * The copyright notice above does not
9*35148Smarc * evidence any actual or intended
10*35148Smarc * publication of such source code.
11*35148Smarc
12*35148Smarc */
13*35148Smarc /* @(#)jobs.c 1.1 */
14*35148Smarc
15*35148Smarc /*
16*35148Smarc * Job control for UNIX Shell
17*35148Smarc *
18*35148Smarc * David Korn
19*35148Smarc * AT&T Bell Laboratories
20*35148Smarc * Room 5D-112
21*35148Smarc * Murray Hill, N. J. 07974
22*35148Smarc * Tel. x7975
23*35148Smarc *
24*35148Smarc * Written October, 1982
25*35148Smarc */
26*35148Smarc
27*35148Smarc
28*35148Smarc #include <errno.h>
29*35148Smarc
30*35148Smarc #ifdef BSD
31*35148Smarc # ifdef BSD_4_2
32*35148Smarc #include <sys/wait.h>
33*35148Smarc # else
34*35148Smarc #include <wait.h>
35*35148Smarc # endif /* BSD_4_2 */
36*35148Smarc #endif /* BSD */
37*35148Smarc
38*35148Smarc #ifdef SXT
39*35148Smarc #define SIGSTOP 20
40*35148Smarc #define SIGSTIN 21
41*35148Smarc #include <sys/types.h>
42*35148Smarc #include <sys/tty.h>
43*35148Smarc #include <sys/sxt.h>
44*35148Smarc #include <sys/stat.h>
45*35148Smarc #endif /* SXT */
46*35148Smarc
47*35148Smarc #include "defs.h"
48*35148Smarc #include "flags.h"
49*35148Smarc #include "shtype.h"
50*35148Smarc #include "jobs.h"
51*35148Smarc #include "brkincr.h"
52*35148Smarc #include "io.h"
53*35148Smarc #include "history.h"
54*35148Smarc
55*35148Smarc #ifdef SXT
56*35148Smarc #undef input
57*35148Smarc static status_update();
58*35148Smarc static int open_chan();
59*35148Smarc static int fd_chan = -1;
60*35148Smarc static char tinybuf;
61*35148Smarc #endif /* SXT */
62*35148Smarc
63*35148Smarc #define LOBYTE 0377
64*35148Smarc #define MAXMSG 25
65*35148Smarc
66*35148Smarc void await();
67*35148Smarc void postclr();
68*35148Smarc
69*35148Smarc extern void fault();
70*35148Smarc extern long hist_list();
71*35148Smarc extern long hist_position();
72*35148Smarc extern char *itos();
73*35148Smarc extern char *malloc();
74*35148Smarc extern void failed();
75*35148Smarc extern void free();
76*35148Smarc extern void p_str();
77*35148Smarc extern void p_prp();
78*35148Smarc extern void p_num();
79*35148Smarc extern void p_sub();
80*35148Smarc extern void p_nchr();
81*35148Smarc extern void p_flush();
82*35148Smarc extern void p_setout();
83*35148Smarc
84*35148Smarc static int set_ttygrp();
85*35148Smarc static int set_job();
86*35148Smarc static int reset_ttygrp();
87*35148Smarc static struct process *next_proc();
88*35148Smarc static struct process *jobbyname();
89*35148Smarc static struct process *job_bynum();
90*35148Smarc static struct process *job_bypid();
91*35148Smarc static struct process *job_post();
92*35148Smarc static struct process *unpost();
93*35148Smarc static struct process *pgrp_jobs();
94*35148Smarc static int get_job();
95*35148Smarc static int match_jobname();
96*35148Smarc static int unstop();
97*35148Smarc static void free_job();
98*35148Smarc static void pw_unlink();
99*35148Smarc static struct process *freelist;
100*35148Smarc #define numrun jobstat.p_numrun /* number of running jobs */
101*35148Smarc #define numpost jobstat.p_numpost /* number of posted jobs */
102*35148Smarc #define pwlist jobstat.p_pwlist
103*35148Smarc #define freejobs jobstat.p_freejobs /* free job numbers */
104*35148Smarc static long pr_jobname();
105*35148Smarc
106*35148Smarc #ifdef FIOLOOKLD
107*35148Smarc #define version8 1
108*35148Smarc extern int tty_ld, ntty_ld;
109*35148Smarc #define OTTYDISC tty_ld
110*35148Smarc #define NTTYDISC ntty_ld
111*35148Smarc #endif /* FIOLOOKLD */
112*35148Smarc
113*35148Smarc
114*35148Smarc static int savepgrp;
115*35148Smarc static int savetgrp;
116*35148Smarc static BOOL old_driver;
117*35148Smarc static BOOL beenhere;
118*35148Smarc
119*35148Smarc #ifdef BSD
120*35148Smarc static struct sgttyb my_stty; /* terminal state for shell */
121*35148Smarc #else
122*35148Smarc static struct termio my_stty; /* terminal state for shell */
123*35148Smarc #endif /* BSD */
124*35148Smarc
125*35148Smarc #ifdef BSD
126*35148Smarc /*
127*35148Smarc * initialize job control
128*35148Smarc * if lflag is set the switching driver message will not print
129*35148Smarc */
130*35148Smarc
init_jobs(lflag)131*35148Smarc int init_jobs(lflag)
132*35148Smarc {
133*35148Smarc int ldisc;
134*35148Smarc register int ntry = 0;
135*35148Smarc register int pid;
136*35148Smarc jobstat.mypid = pid = getpid();
137*35148Smarc savepgrp = getpgrp(pid);
138*35148Smarc # ifdef version8
139*35148Smarc if((ldisc = ioctl (2, FIOLOOKLD, 0)) <0)
140*35148Smarc # else
141*35148Smarc if(ioctl(2,TIOCGETD,&ldisc) !=0)
142*35148Smarc # endif /* version8 */
143*35148Smarc return(-1);
144*35148Smarc if(ldisc!=NTTYDISC && ldisc!=OTTYDISC)
145*35148Smarc {
146*35148Smarc /* no job control when running with MPX */
147*35148Smarc # ifdef VSH
148*35148Smarc on_option(VIRAW);
149*35148Smarc # endif /* VSH */
150*35148Smarc return(-1);
151*35148Smarc }
152*35148Smarc retry:
153*35148Smarc signal(SIGTTOU,SIG_IGN);
154*35148Smarc if(ioctl(2,TIOCGPGRP,&savetgrp) !=0)
155*35148Smarc {
156*35148Smarc fputs(j_not_tty,output);
157*35148Smarc return(-1);
158*35148Smarc }
159*35148Smarc /* This shell must be in foreground to change state */
160*35148Smarc if(savetgrp != savepgrp)
161*35148Smarc {
162*35148Smarc signal(SIGTTOU,SIG_DFL);
163*35148Smarc kill(pid,SIGTTOU);
164*35148Smarc /* wait for continue and try again */
165*35148Smarc if(ntry++ > 100)
166*35148Smarc {
167*35148Smarc fputs(j_no_start,output);
168*35148Smarc return(-1);
169*35148Smarc }
170*35148Smarc goto retry;
171*35148Smarc }
172*35148Smarc if(ldisc == OTTYDISC)
173*35148Smarc {
174*35148Smarc ldisc = NTTYDISC;
175*35148Smarc # ifdef version8
176*35148Smarc ioctl(2,TIOCGETP,&my_stty);
177*35148Smarc if (ioctl(2, FIOPOPLD, 0) < 0)
178*35148Smarc return(-1);
179*35148Smarc if (ioctl(2, FIOPUSHLD, &ldisc, 0) < 0)
180*35148Smarc {
181*35148Smarc ldisc = OTTYDISC;
182*35148Smarc ioctl(2, FIOPUSHLD, &ldisc, 0);
183*35148Smarc return(-1);
184*35148Smarc }
185*35148Smarc ioctl(2,TIOCSETN,&my_stty);
186*35148Smarc # else
187*35148Smarc if(ioctl(2,TIOCSETD,&ldisc) !=0)
188*35148Smarc return(-1);
189*35148Smarc # endif /* version8 */
190*35148Smarc if(lflag==0)
191*35148Smarc {
192*35148Smarc fputs(j_newtty,output);
193*35148Smarc old_driver++;
194*35148Smarc }
195*35148Smarc }
196*35148Smarc on_option(MONITOR);
197*35148Smarc signal(SIGCHLD,fault);
198*35148Smarc signal(SIGTSTP,SIG_IGN);
199*35148Smarc signal(SIGTTIN,SIG_IGN);
200*35148Smarc setpgrp(pid,pid);
201*35148Smarc set_ttygrp(pid);
202*35148Smarc return(0);
203*35148Smarc }
204*35148Smarc
205*35148Smarc
206*35148Smarc /*
207*35148Smarc * see if there are any stopped jobs
208*35148Smarc * restore tty driver and pgrp
209*35148Smarc */
210*35148Smarc
close_jobs()211*35148Smarc int close_jobs()
212*35148Smarc {
213*35148Smarc register struct process *pw = pwlist;
214*35148Smarc register int count = 0;
215*35148Smarc int ldisc;
216*35148Smarc if((states&MONITOR)==0)
217*35148Smarc return(0);
218*35148Smarc for(;pw;pw=pw->p_next)
219*35148Smarc {
220*35148Smarc if((pw->p_flag&P_STOPPED)==0)
221*35148Smarc continue;
222*35148Smarc if(beenhere)
223*35148Smarc killpg(pw->p_pgrp,SIGTERM);
224*35148Smarc count++;
225*35148Smarc }
226*35148Smarc if(beenhere++ == 0 && pwlist)
227*35148Smarc {
228*35148Smarc if(count)
229*35148Smarc {
230*35148Smarc fputs(j_terminate,output);
231*35148Smarc return(-1);
232*35148Smarc }
233*35148Smarc else if(login_sh)
234*35148Smarc {
235*35148Smarc fputs(j_running,output);
236*35148Smarc return(-1);
237*35148Smarc }
238*35148Smarc }
239*35148Smarc set_ttygrp(savepgrp);
240*35148Smarc if(old_driver)
241*35148Smarc {
242*35148Smarc /* restore old line discipline */
243*35148Smarc ldisc = OTTYDISC;
244*35148Smarc # ifdef version8
245*35148Smarc ioctl(2,TIOCGETP,&my_stty);
246*35148Smarc if (ioctl(2, FIOPOPLD, 0) < 0)
247*35148Smarc return(0);
248*35148Smarc if (ioctl(2, FIOPUSHLD, &ldisc, 0) < 0)
249*35148Smarc {
250*35148Smarc ldisc = NTTYDISC;
251*35148Smarc ioctl(2, FIOPUSHLD, &ldisc, 0);
252*35148Smarc return(0);
253*35148Smarc }
254*35148Smarc ioctl(2,TIOCSETN,&my_stty);
255*35148Smarc # else
256*35148Smarc if(ioctl(2,TIOCSETD,&ldisc) !=0)
257*35148Smarc return(0);
258*35148Smarc # endif /* version8 */
259*35148Smarc fputs(j_oldtty,output);
260*35148Smarc }
261*35148Smarc return(0);
262*35148Smarc }
263*35148Smarc
264*35148Smarc /*
265*35148Smarc * Set the ttygroup id to pid
266*35148Smarc */
267*35148Smarc
set_ttygrp(pid)268*35148Smarc static int set_ttygrp(pid)
269*35148Smarc {
270*35148Smarc if(ioctl(2,TIOCSPGRP,&pid) !=0)
271*35148Smarc return(-1);
272*35148Smarc return(0);
273*35148Smarc }
274*35148Smarc
275*35148Smarc /*
276*35148Smarc * Set the ttygroup id to a previously running job
277*35148Smarc */
278*35148Smarc #else
279*35148Smarc # ifdef SXT
280*35148Smarc static char sxt[] = "/dev/sxt/000";
281*35148Smarc static struct sxtblock status1,status2;
282*35148Smarc
init_jobs(lflag)283*35148Smarc int init_jobs(lflag)
284*35148Smarc {
285*35148Smarc register int pid;
286*35148Smarc register int dev;
287*35148Smarc struct stat statbuf;
288*35148Smarc jobstat.mypid = pid = getpid();
289*35148Smarc savepgrp = getpgrp(pid);
290*35148Smarc if(ioctl(2,SXTIOCSTAT,&status2) < 0)
291*35148Smarc return(-1);
292*35148Smarc if(ioctl(2,TCGETA,&my_stty) < 0)
293*35148Smarc return(-1);
294*35148Smarc if(fstat(2,&statbuf) < 0)
295*35148Smarc return(-1);
296*35148Smarc dev = statbuf.st_rdev&0xff;
297*35148Smarc /* must be channel 0 */
298*35148Smarc if(dev&07)
299*35148Smarc return(-1);
300*35148Smarc dev >>= 3;
301*35148Smarc sxt[10] = '0' + (dev%10);
302*35148Smarc sxt[9] = '0' + dev/10;
303*35148Smarc my_stty.c_cc[VSWTCH] = CSWTCH;
304*35148Smarc if(ioctl(2,TCSETAF,&my_stty) < 0)
305*35148Smarc return(-1);
306*35148Smarc setpgrp(pid,pid);
307*35148Smarc jobstat.maxjob = MAXPCHAN;
308*35148Smarc on_option(MONITOR);
309*35148Smarc return(0);
310*35148Smarc }
311*35148Smarc #endif /* SXT */
312*35148Smarc
close_jobs()313*35148Smarc int close_jobs()
314*35148Smarc {
315*35148Smarc register struct process *pw = pwlist;
316*35148Smarc register int count = 0;
317*35148Smarc if((states&MONITOR)==0)
318*35148Smarc return(0);
319*35148Smarc # ifdef SXT
320*35148Smarc for(;pw;pw=pw->p_next)
321*35148Smarc {
322*35148Smarc if((pw->p_flag&P_STOPPED)==0)
323*35148Smarc continue;
324*35148Smarc if(beenhere)
325*35148Smarc kill(-pw->p_pgrp,SIGTERM);
326*35148Smarc count++;
327*35148Smarc }
328*35148Smarc # endif /* SXT */
329*35148Smarc if(beenhere++ == 0 && pwlist && login_sh)
330*35148Smarc # ifdef SXT
331*35148Smarc {
332*35148Smarc if(count)
333*35148Smarc {
334*35148Smarc fputs(j_terminate,output);
335*35148Smarc return(-1);
336*35148Smarc }
337*35148Smarc if(login_sh || jobstat.maxjob)
338*35148Smarc # endif /* SXT */
339*35148Smarc {
340*35148Smarc fputs(j_running,output);
341*35148Smarc return(-1);
342*35148Smarc }
343*35148Smarc # ifdef SXT
344*35148Smarc }
345*35148Smarc if(jobstat.maxjob)
346*35148Smarc kill_all();
347*35148Smarc # endif /* SXT */
348*35148Smarc return(0);
349*35148Smarc }
350*35148Smarc
351*35148Smarc #endif /* BSD */
352*35148Smarc
set_job(pw)353*35148Smarc static int set_job(pw)
354*35148Smarc register struct process *pw;
355*35148Smarc {
356*35148Smarc /* save current terminal state */
357*35148Smarc #ifdef BSD
358*35148Smarc ioctl(2,TIOCGETP,&my_stty);
359*35148Smarc #else
360*35148Smarc ioctl(2,TCGETA,&my_stty);
361*35148Smarc #endif /* BSD */
362*35148Smarc #ifdef SXT
363*35148Smarc /* make sure child has opened channel */
364*35148Smarc if(jobstat.pipe[0] > 0)
365*35148Smarc {
366*35148Smarc read(jobstat.pipe[0],&tinybuf,1);
367*35148Smarc close(jobstat.pipe[0]);
368*35148Smarc jobstat.pipe[0] = 0;
369*35148Smarc }
370*35148Smarc if(pw->p_job < jobstat.maxjob)
371*35148Smarc if(ioctl(2,SXTIOCSWTCH,pw->p_job)!=0)
372*35148Smarc {
373*35148Smarc return(-1);
374*35148Smarc }
375*35148Smarc #endif /* SXT */
376*35148Smarc if(pw->p_flag&P_STTY)
377*35148Smarc {
378*35148Smarc /* restore terminal state for job */
379*35148Smarc #ifdef BSD
380*35148Smarc ioctl(2,TIOCSETN,&pw->p_stty);
381*35148Smarc #else
382*35148Smarc ioctl(2,TCSETAF,&pw->p_stty);
383*35148Smarc #endif /* BSD */
384*35148Smarc }
385*35148Smarc #ifdef BSD
386*35148Smarc if(ioctl(2,TIOCSPGRP,&pw->p_pgrp) !=0)
387*35148Smarc return(-1);
388*35148Smarc #endif /* BSD */
389*35148Smarc return(0);
390*35148Smarc }
391*35148Smarc
reset_ttygrp(pw,flag)392*35148Smarc static int reset_ttygrp(pw,flag)
393*35148Smarc register struct process *pw;
394*35148Smarc {
395*35148Smarc /* save the terminal state for current job */
396*35148Smarc #ifdef BSD
397*35148Smarc if(ioctl(2,TIOCSPGRP,&jobstat.mypid) !=0)
398*35148Smarc {
399*35148Smarc return(-1);
400*35148Smarc }
401*35148Smarc #endif /* BSD */
402*35148Smarc #ifdef SXT
403*35148Smarc if(pw && pw->p_job < jobstat.maxjob)
404*35148Smarc {
405*35148Smarc /* save the state of terminated process */
406*35148Smarc if(flag==0 && fd_chan>=0)
407*35148Smarc {
408*35148Smarc if(ioctl(fd_chan,TCGETA,&pw->p_stty)==0)
409*35148Smarc {
410*35148Smarc my_stty = pw->p_stty;
411*35148Smarc /* for timing problem */
412*35148Smarc ioctl(fd_chan,TCSETAW,&my_stty);
413*35148Smarc }
414*35148Smarc }
415*35148Smarc close(fd_chan);
416*35148Smarc fd_chan = -1;
417*35148Smarc /* grab control in channel 0 */
418*35148Smarc ioctl(2,TCSETAW,&my_stty);
419*35148Smarc if(ioctl(2,SXTIOCSWTCH,0)!=0)
420*35148Smarc {
421*35148Smarc return(-1);
422*35148Smarc }
423*35148Smarc if(flag==0)
424*35148Smarc ioctl(2,TCSETAW,&my_stty);
425*35148Smarc beenhere = 0;
426*35148Smarc return(0);
427*35148Smarc }
428*35148Smarc #endif /* SXT */
429*35148Smarc if(pw && flag)
430*35148Smarc {
431*35148Smarc #ifdef BSD
432*35148Smarc if(ioctl(2,TIOCGETP,&pw->p_stty) == 0)
433*35148Smarc #else
434*35148Smarc if(ioctl(2,TCGETA,&pw->p_stty) == 0)
435*35148Smarc #endif /* BSD */
436*35148Smarc pw->p_flag |= P_STTY;
437*35148Smarc /* restore terminal state for job */
438*35148Smarc #ifdef BSD
439*35148Smarc ioctl(2,TIOCSETN,&my_stty);
440*35148Smarc #else
441*35148Smarc ioctl(2,TCSETAF,&my_stty);
442*35148Smarc #endif /* BSD */
443*35148Smarc }
444*35148Smarc beenhere = 0;
445*35148Smarc return(0);
446*35148Smarc }
447*35148Smarc
448*35148Smarc #if BSD || SXT
449*35148Smarc
450*35148Smarc /*
451*35148Smarc * move job to foreground if bgflag == 0
452*35148Smarc * move job to background if bgflag != 0
453*35148Smarc */
454*35148Smarc
switch_jobs(ajob,bgflag)455*35148Smarc switch_jobs(ajob,bgflag)
456*35148Smarc register char *ajob;
457*35148Smarc {
458*35148Smarc register struct process *pw=NULL;
459*35148Smarc register int pgrp;
460*35148Smarc # ifdef SXT
461*35148Smarc if(jobstat.maxjob==0)
462*35148Smarc return(NULL);
463*35148Smarc # endif /* SXT */
464*35148Smarc if(*ajob)
465*35148Smarc pw = pgrp_jobs(ajob);
466*35148Smarc else if(pwlist)
467*35148Smarc pw = job_bynum((int)pwlist->p_job);
468*35148Smarc if(pw)
469*35148Smarc {
470*35148Smarc if(bgflag)
471*35148Smarc {
472*35148Smarc pgrp = pw->p_pgrp;
473*35148Smarc if(pw->p_flag&P_STOPPED)
474*35148Smarc {
475*35148Smarc p_sub((int)pw->p_job,'\t');
476*35148Smarc pr_jobname(pw,'&',0L);
477*35148Smarc fputs(j_amp,output);
478*35148Smarc unstop(pgrp);
479*35148Smarc }
480*35148Smarc }
481*35148Smarc else
482*35148Smarc {
483*35148Smarc pw_unlink(pw);
484*35148Smarc pw->p_next = pwlist;
485*35148Smarc pwlist = pw;
486*35148Smarc pr_jobname(pw,'&',0L);
487*35148Smarc newline();
488*35148Smarc await(pw->p_pid,3);
489*35148Smarc }
490*35148Smarc }
491*35148Smarc return(pw!=NULL);
492*35148Smarc }
493*35148Smarc
494*35148Smarc /*
495*35148Smarc * list the current jobs
496*35148Smarc * flag L_FLAG for long listing
497*35148Smarc * flag N_FLAG for list only jobs marked for notification
498*35148Smarc */
499*35148Smarc #endif /* BSD */
500*35148Smarc
list_jobs(flag)501*35148Smarc list_jobs(flag)
502*35148Smarc int flag;
503*35148Smarc {
504*35148Smarc register struct process *pw;
505*35148Smarc register struct process *px;
506*35148Smarc register int m;
507*35148Smarc register struct process *py;
508*35148Smarc int n;
509*35148Smarc long offset;
510*35148Smarc int jobm = 0;
511*35148Smarc register char *msg;
512*35148Smarc int msize;
513*35148Smarc if(pwlist==NULL)
514*35148Smarc return;
515*35148Smarc await(0,2);
516*35148Smarc p_setout(standout);
517*35148Smarc /* get job number corresponding to '-' */
518*35148Smarc if(pw=pgrp_jobs("%-"))
519*35148Smarc jobm = pw->p_job;
520*35148Smarc for(pw=pwlist;pw;pw=py)
521*35148Smarc {
522*35148Smarc py = pw->p_next;
523*35148Smarc if(pw->p_flag&P_PIPEJOB)
524*35148Smarc continue;
525*35148Smarc if((flag&N_FLAG) && (pw->p_flag&P_NOTIFY)==0)
526*35148Smarc continue;
527*35148Smarc n = pw->p_job;
528*35148Smarc p_sub(n,' ');
529*35148Smarc m = ' ';
530*35148Smarc if(pw->p_job==pwlist->p_job)
531*35148Smarc m = '+';
532*35148Smarc else if(pw->p_job==jobm)
533*35148Smarc {
534*35148Smarc m = '-';
535*35148Smarc jobm = 0;
536*35148Smarc }
537*35148Smarc putc(m,output);
538*35148Smarc putc(' ',output);
539*35148Smarc offset = 0;
540*35148Smarc if(flag&L_FLAG)
541*35148Smarc px = next_proc(pwlist,(int)pw->p_job);
542*35148Smarc else
543*35148Smarc px = pw;
544*35148Smarc do
545*35148Smarc {
546*35148Smarc unsigned xitval = 0;
547*35148Smarc if(flag&L_FLAG)
548*35148Smarc p_num(px->p_pid,'\t');
549*35148Smarc if(px->p_sig&0177)
550*35148Smarc msg = sysmsg[px->p_sig&0177];
551*35148Smarc else if(px->p_flag&P_NOTIFY)
552*35148Smarc {
553*35148Smarc msg = j_Done;
554*35148Smarc xitval = px->p_sig>>8;
555*35148Smarc }
556*35148Smarc else
557*35148Smarc msg = j_Running;
558*35148Smarc fputs(msg,output);
559*35148Smarc msize = strlen(msg);
560*35148Smarc if(xitval)
561*35148Smarc {
562*35148Smarc putc('(',output);
563*35148Smarc p_num((int)xitval,')');
564*35148Smarc msize += (3+(xitval>10)+(xitval>100));
565*35148Smarc }
566*35148Smarc if(px->p_flag&P_COREDUMP)
567*35148Smarc {
568*35148Smarc fputs(j_coredump,output);
569*35148Smarc msize += strlen(j_coredump);
570*35148Smarc }
571*35148Smarc p_nchr(SP,MAXMSG-msize);
572*35148Smarc if(flag&L_FLAG)
573*35148Smarc px = next_proc(px->p_next,(int)pw->p_job);
574*35148Smarc else
575*35148Smarc px = NULL;
576*35148Smarc offset = pr_jobname(pw,(px?'|':0),offset);
577*35148Smarc if(flag&L_FLAG)
578*35148Smarc {
579*35148Smarc if(px)
580*35148Smarc fputs(j_space,output);
581*35148Smarc else if(pw->p_pid == cpid)
582*35148Smarc fputs(j_cpid,output);
583*35148Smarc }
584*35148Smarc }
585*35148Smarc while(px);
586*35148Smarc if(pw->p_flag&P_STOPPED)
587*35148Smarc pw->p_flag &= ~P_NOTIFY;
588*35148Smarc else if(pw->p_flag&P_NOTIFY)
589*35148Smarc {
590*35148Smarc unpost(pw);
591*35148Smarc if(jobm && (px=pgrp_jobs("%-")))
592*35148Smarc jobm = px->p_job;
593*35148Smarc }
594*35148Smarc }
595*35148Smarc }
596*35148Smarc
597*35148Smarc /*
598*35148Smarc * return the pointer of next process with given job number after slot px
599*35148Smarc */
600*35148Smarc
next_proc(pw,job)601*35148Smarc static struct process * next_proc(pw,job)
602*35148Smarc register struct process *pw;
603*35148Smarc register int job;
604*35148Smarc {
605*35148Smarc for(;pw;pw=pw->p_next)
606*35148Smarc {
607*35148Smarc if(pw->p_job == job)
608*35148Smarc return(pw);
609*35148Smarc }
610*35148Smarc return(NULL);
611*35148Smarc }
612*35148Smarc
613*35148Smarc /*
614*35148Smarc * print the command
615*35148Smarc * Stop the output if character <ch> encountered
616*35148Smarc */
617*35148Smarc
pr_jobname(pw,ch,offset)618*35148Smarc static long pr_jobname(pw,ch,offset)
619*35148Smarc register struct process *pw;
620*35148Smarc register long offset;
621*35148Smarc int ch;
622*35148Smarc {
623*35148Smarc if(fc_fix)
624*35148Smarc {
625*35148Smarc offset = hist_list(pw->p_name+offset,ch,";");
626*35148Smarc offset -= pw->p_name;
627*35148Smarc }
628*35148Smarc return(++offset);
629*35148Smarc }
630*35148Smarc
631*35148Smarc /*
632*35148Smarc * get the process group given the job number
633*35148Smarc * This routine returns the process group number or -1
634*35148Smarc */
635*35148Smarc
pgrp_jobs(ajob)636*35148Smarc static struct process *pgrp_jobs(ajob)
637*35148Smarc register char *ajob;
638*35148Smarc {
639*35148Smarc register struct process *pw;
640*35148Smarc register int c;
641*35148Smarc if(*ajob++ != '%' || pwlist==NULL)
642*35148Smarc return(NULL);
643*35148Smarc c = *ajob;
644*35148Smarc if(isdigit(c))
645*35148Smarc pw = job_bynum(atoi(ajob));
646*35148Smarc else if(c=='+' || c=='%')
647*35148Smarc pw = job_bynum((int)pwlist->p_job);
648*35148Smarc else if(c=='-')
649*35148Smarc {
650*35148Smarc /* find the second jobnumber on the list */
651*35148Smarc for(pw=pwlist->p_next;pw && pw->p_job==pwlist->p_job;pw=pw->p_next);
652*35148Smarc if(pw==NULL)
653*35148Smarc return(pw);
654*35148Smarc pw = job_bynum((int)pw->p_job);
655*35148Smarc }
656*35148Smarc else
657*35148Smarc pw = jobbyname(ajob);
658*35148Smarc if(pw && pw->p_flag)
659*35148Smarc return(pw);
660*35148Smarc return(NULL);
661*35148Smarc }
662*35148Smarc
663*35148Smarc /*
664*35148Smarc * send a hang-up signal to each of the jobs
665*35148Smarc */
kill_all()666*35148Smarc int kill_all()
667*35148Smarc {
668*35148Smarc register struct process *pw = pwlist;
669*35148Smarc for(;pw;pw=pw->p_next)
670*35148Smarc {
671*35148Smarc if(pw->p_pgrp == pw->p_pid)
672*35148Smarc {
673*35148Smarc #ifdef BSD
674*35148Smarc unstop(pw->p_pgrp);
675*35148Smarc killpg(pw->p_pgrp,SIGHUP);
676*35148Smarc #else
677*35148Smarc kill(-pw->p_pgrp,SIGHUP);
678*35148Smarc #endif /* BSD */
679*35148Smarc }
680*35148Smarc }
681*35148Smarc }
682*35148Smarc
683*35148Smarc /*
684*35148Smarc * Kill a job or process
685*35148Smarc */
686*35148Smarc
job_kill(job,sig)687*35148Smarc int job_kill(job,sig)
688*35148Smarc register char *job;
689*35148Smarc int sig;
690*35148Smarc {
691*35148Smarc register char *rjob = job;
692*35148Smarc register struct process *pw;
693*35148Smarc register int pid;
694*35148Smarc register int r;
695*35148Smarc char *msg;
696*35148Smarc if(*rjob == '%')
697*35148Smarc {
698*35148Smarc if(pw=pgrp_jobs(rjob))
699*35148Smarc {
700*35148Smarc #ifdef BSD
701*35148Smarc r = unstop(pw->p_pgrp);
702*35148Smarc if(sig!=SIGCONT || r < 0)
703*35148Smarc r = killpg(pw->p_pgrp,sig);
704*35148Smarc #else
705*35148Smarc pid = pw->p_pgrp;
706*35148Smarc if(states&MONITOR)
707*35148Smarc pid = -pid;
708*35148Smarc r = kill(pid,sig);
709*35148Smarc #endif /* BSD */
710*35148Smarc }
711*35148Smarc else
712*35148Smarc {
713*35148Smarc r = -1;
714*35148Smarc errno = ESRCH;
715*35148Smarc }
716*35148Smarc }
717*35148Smarc else
718*35148Smarc {
719*35148Smarc pid = atoi(rjob);
720*35148Smarc if(pid==0 && *rjob != '0')
721*35148Smarc failed(bkill,kill_usage);
722*35148Smarc #ifdef BSD
723*35148Smarc if(sig==SIGSTOP && pid==jobstat.mypid && ppid==1)
724*35148Smarc {
725*35148Smarc /* can't stop login shell */
726*35148Smarc errno = EPERM;
727*35148Smarc r = -1;
728*35148Smarc }
729*35148Smarc else
730*35148Smarc {
731*35148Smarc if((pw=job_bypid(pid)) && (pw->p_flag&P_STOPPED))
732*35148Smarc {
733*35148Smarc pw->p_flag &= ~P_STOPPED;
734*35148Smarc numrun++;
735*35148Smarc kill(pid,SIGCONT);
736*35148Smarc }
737*35148Smarc r = kill(pid,sig);
738*35148Smarc }
739*35148Smarc #else
740*35148Smarc r = kill(pid,sig);
741*35148Smarc #endif /* BSD */
742*35148Smarc }
743*35148Smarc if(r<0)
744*35148Smarc {
745*35148Smarc p_setout(stderr);
746*35148Smarc fputs(j_kill,output);
747*35148Smarc if(*rjob == '%')
748*35148Smarc msg = j_no_job;
749*35148Smarc else
750*35148Smarc msg = j_no_proc;
751*35148Smarc p_str(rjob,':');
752*35148Smarc if(errno == EPERM)
753*35148Smarc msg = j_perm;
754*35148Smarc p_str(msg,NL);
755*35148Smarc r = 1;
756*35148Smarc }
757*35148Smarc return(r);
758*35148Smarc }
759*35148Smarc
760*35148Smarc /*
761*35148Smarc * Get process structure from job number
762*35148Smarc */
763*35148Smarc
job_bynum(num)764*35148Smarc static struct process *job_bynum(num)
765*35148Smarc register int num;
766*35148Smarc {
767*35148Smarc register struct process *pw = pwlist;
768*35148Smarc for(;pw;pw=pw->p_next)
769*35148Smarc {
770*35148Smarc if((pw->p_flag&(P_PIPEJOB|P_WAITED)) == P_PIPEJOB)
771*35148Smarc continue;
772*35148Smarc if(pw->p_job == num)
773*35148Smarc return(pw);
774*35148Smarc }
775*35148Smarc return(NULL);
776*35148Smarc }
777*35148Smarc
778*35148Smarc /*
779*35148Smarc * Get process structure from first letters of jobname
780*35148Smarc *
781*35148Smarc */
782*35148Smarc
jobbyname(name)783*35148Smarc static struct process *jobbyname(name)
784*35148Smarc char *name;
785*35148Smarc {
786*35148Smarc register struct process *pw = pwlist;
787*35148Smarc register struct fixcmd *fp = fc_fix;
788*35148Smarc if(fp==NULL)
789*35148Smarc return(NULL);
790*35148Smarc for(;pw;pw=pw->p_next)
791*35148Smarc {
792*35148Smarc if((pw->p_flag&(P_PIPEJOB|P_WAITED)) == P_PIPEJOB)
793*35148Smarc continue;
794*35148Smarc if(match_jobname(fp->fixfd,pw,name))
795*35148Smarc goto retrn;
796*35148Smarc }
797*35148Smarc pw = NULL;
798*35148Smarc retrn:
799*35148Smarc return(pw);
800*35148Smarc }
801*35148Smarc
802*35148Smarc
803*35148Smarc /*
804*35148Smarc * match the name to the command starting with given name
805*35148Smarc */
806*35148Smarc
match_jobname(fdi,pw,name)807*35148Smarc static int match_jobname(fdi,pw,name)
808*35148Smarc FILE *fdi;
809*35148Smarc register struct process *pw;
810*35148Smarc char *name;
811*35148Smarc {
812*35148Smarc register int c;
813*35148Smarc register char *sp;
814*35148Smarc if(fdi && pw->p_name>0)
815*35148Smarc {
816*35148Smarc fseek(fdi,pw->p_name,0);
817*35148Smarc for(sp=name;*sp;sp++)
818*35148Smarc {
819*35148Smarc c = getc(fdi);
820*35148Smarc if(c != *sp)
821*35148Smarc return(0);
822*35148Smarc }
823*35148Smarc return(1);
824*35148Smarc }
825*35148Smarc return(0);
826*35148Smarc }
827*35148Smarc
828*35148Smarc
829*35148Smarc
830*35148Smarc /*
831*35148Smarc * Initialize the process posting array
832*35148Smarc */
833*35148Smarc
postclr()834*35148Smarc void postclr()
835*35148Smarc {
836*35148Smarc register struct process *pw = pwlist;
837*35148Smarc register struct process *px;
838*35148Smarc register int j = JBYTES;
839*35148Smarc for(;pw;pw=px)
840*35148Smarc {
841*35148Smarc px = pw->p_next;
842*35148Smarc free((char*)pw);
843*35148Smarc }
844*35148Smarc pwlist = NULL;
845*35148Smarc numpost=0;
846*35148Smarc numrun = 0;
847*35148Smarc while(--j >=0)
848*35148Smarc freejobs[j] = 0;
849*35148Smarc }
850*35148Smarc
851*35148Smarc /*
852*35148Smarc * put the process <pcsid> on the process list and return the job number
853*35148Smarc * turn on the specified flag bits.
854*35148Smarc */
855*35148Smarc
post(pid,flag)856*35148Smarc int post(pid,flag)
857*35148Smarc int pid;
858*35148Smarc {
859*35148Smarc register struct process *pw;
860*35148Smarc if(pw=job_post(pid))
861*35148Smarc {
862*35148Smarc pw->p_flag |= flag;
863*35148Smarc return(pw->p_job);
864*35148Smarc }
865*35148Smarc return(-1);
866*35148Smarc }
867*35148Smarc
868*35148Smarc /*
869*35148Smarc * internal version of post, this routine returns a process structure
870*35148Smarc */
871*35148Smarc
job_post(pcsid)872*35148Smarc static struct process *job_post(pcsid)
873*35148Smarc int pcsid;
874*35148Smarc {
875*35148Smarc register struct process *pw = pwlist;
876*35148Smarc register struct process *px=NULL;
877*35148Smarc register struct fixcmd *fp = fc_fix;
878*35148Smarc if(pcsid)
879*35148Smarc {
880*35148Smarc for(;pw;pw=pw->p_next)
881*35148Smarc {
882*35148Smarc if(pw->p_pid==pcsid)
883*35148Smarc return(pw);
884*35148Smarc if(pw->p_pgrp == jobstat.cur_pgrp)
885*35148Smarc px = pw;
886*35148Smarc }
887*35148Smarc if(pw=freelist)
888*35148Smarc freelist = pw->p_next;
889*35148Smarc else if((pw=(struct process*)malloc(sizeof(struct process)))==NULL)
890*35148Smarc error(nospace);
891*35148Smarc numrun++;
892*35148Smarc numpost++;
893*35148Smarc if(px)
894*35148Smarc {
895*35148Smarc pw->p_next = px->p_next;
896*35148Smarc px->p_next = pw;
897*35148Smarc pw->p_job = px->p_job;
898*35148Smarc }
899*35148Smarc else
900*35148Smarc {
901*35148Smarc /* put at front of list */
902*35148Smarc pw->p_next = pwlist;
903*35148Smarc pw->p_job = get_job();
904*35148Smarc pwlist = pw;
905*35148Smarc }
906*35148Smarc pw->p_pid = pcsid;
907*35148Smarc pw->p_flag = P_RUNNING;
908*35148Smarc pw->p_pgrp = jobstat.cur_pgrp;
909*35148Smarc if(fp!=NULL)
910*35148Smarc pw->p_name=hist_position(fp->fixind-1);
911*35148Smarc else
912*35148Smarc pw->p_name = -1;
913*35148Smarc pw->p_sig = 0;
914*35148Smarc if(numpost >= MAXJ-1)
915*35148Smarc await(0,0);
916*35148Smarc return(pw);
917*35148Smarc }
918*35148Smarc return(NULL);
919*35148Smarc }
920*35148Smarc
921*35148Smarc /*
922*35148Smarc * get job number given the process id
923*35148Smarc */
924*35148Smarc
job_bypid(pid)925*35148Smarc static struct process *job_bypid(pid)
926*35148Smarc register int pid;
927*35148Smarc {
928*35148Smarc register struct process *pw;
929*35148Smarc if(pid==0)
930*35148Smarc return(NULL);
931*35148Smarc for(pw=pwlist;pw;pw=pw->p_next)
932*35148Smarc if(pw->p_pid == pid)
933*35148Smarc break;
934*35148Smarc return(pw);
935*35148Smarc }
936*35148Smarc
937*35148Smarc /*
938*35148Smarc * Wait for process i to complete
939*35148Smarc * flag=1 when wait builtin invoked so that it can be interrupted
940*35148Smarc * flag=2 to check for waiting processes and return
941*35148Smarc * flag=3 to resume job in foreground
942*35148Smarc * i=0 to wait for any process
943*35148Smarc * i=-1 to wait for all runing processes
944*35148Smarc */
945*35148Smarc
await(i,flag)946*35148Smarc void await(i, flag)
947*35148Smarc register int i;
948*35148Smarc int flag;
949*35148Smarc {
950*35148Smarc int rc=0;
951*35148Smarc int w;
952*35148Smarc int my_job = -1;
953*35148Smarc #ifdef BSD
954*35148Smarc union wait wstat;
955*35148Smarc #endif /* BSD */
956*35148Smarc register struct process *pw = NULL;
957*35148Smarc struct process *px;
958*35148Smarc if(i!= -1 && i)
959*35148Smarc {
960*35148Smarc if(flag)
961*35148Smarc {
962*35148Smarc pw = job_bypid(i);
963*35148Smarc if(flag==3 && pw)
964*35148Smarc flag = 0;
965*35148Smarc }
966*35148Smarc else
967*35148Smarc pw = job_post(i);
968*35148Smarc if(flag)
969*35148Smarc {
970*35148Smarc if(pw==0 || (pw->p_flag&P_STOPPED))
971*35148Smarc return;
972*35148Smarc }
973*35148Smarc my_job = pw->p_job;
974*35148Smarc }
975*35148Smarc if(flag==0 && (states&MONITOR) && pw)
976*35148Smarc {
977*35148Smarc set_job(pw);
978*35148Smarc /* if job is stopped, resume it in the background */
979*35148Smarc #if BSD || SXT
980*35148Smarc if(pw->p_flag&P_STOPPED)
981*35148Smarc unstop(pw->p_pgrp);
982*35148Smarc # ifdef SXT
983*35148Smarc if(pw->p_job < jobstat.maxjob)
984*35148Smarc open_chan(pw->p_job);
985*35148Smarc # endif /* SXT */
986*35148Smarc #endif /* BSD */
987*35148Smarc }
988*35148Smarc p_flush();
989*35148Smarc while(numrun>0)
990*35148Smarc {
991*35148Smarc register int p;
992*35148Smarc register int sig;
993*35148Smarc register int w_hi;
994*35148Smarc #ifdef BSD
995*35148Smarc if(is_option(MONITOR) || flag==2)
996*35148Smarc {
997*35148Smarc retry:
998*35148Smarc errno = 0;
999*35148Smarc sig = sighold(SIGCHLD);
1000*35148Smarc trapnote &= ~SIGJOBS;
1001*35148Smarc p=wait3(&wstat,WNOHANG|WUNTRACED,0);
1002*35148Smarc errno = 0;
1003*35148Smarc if(p==0 && flag!=2)
1004*35148Smarc {
1005*35148Smarc # ifdef BSD_4_2
1006*35148Smarc sigpause(sig&~(1<<(SIGCHLD-1)));
1007*35148Smarc # else
1008*35148Smarc sigpause(SIGCHLD);
1009*35148Smarc # endif /* BSD_4_2 */
1010*35148Smarc if(errno==EINTR && flag==1 && (trapnote&SIGJOBS)==0)
1011*35148Smarc break;
1012*35148Smarc goto retry;
1013*35148Smarc }
1014*35148Smarc trapnote &= ~SIGJOBS;
1015*35148Smarc sigrelse(SIGCHLD);
1016*35148Smarc if(p==0 || p== -1)
1017*35148Smarc return;
1018*35148Smarc w = wstat.w_status;
1019*35148Smarc pw = job_bypid(p);
1020*35148Smarc if(pw->p_job == my_job && (states&MONITOR))
1021*35148Smarc {
1022*35148Smarc register int ssig = wstat.w_S.w_Stopsig;
1023*35148Smarc if(WIFSTOPPED(wstat) && (ssig==SIGTTIN||ssig==SIGTTOU))
1024*35148Smarc {
1025*35148Smarc /* job stopped before it got terminal */
1026*35148Smarc killpg(pw->p_pgrp,SIGCONT);
1027*35148Smarc continue;
1028*35148Smarc }
1029*35148Smarc if(p==i)
1030*35148Smarc reset_ttygrp(pw,w&LOBYTE);
1031*35148Smarc }
1032*35148Smarc }
1033*35148Smarc else
1034*35148Smarc #endif /* BSD */
1035*35148Smarc {
1036*35148Smarc #ifndef BSD
1037*35148Smarc # ifdef SXT
1038*35148Smarc if(jobstat.maxjob >0)
1039*35148Smarc {
1040*35148Smarc /* check for job status change */
1041*35148Smarc status1 = status2;
1042*35148Smarc status2.input = status2.output = 0;
1043*35148Smarc if(ioctl(2,SXTIOCSTAT,&status2)!=0)
1044*35148Smarc {
1045*35148Smarc jobstat.maxjob = 0;
1046*35148Smarc }
1047*35148Smarc else if(status1.input != status2.input)
1048*35148Smarc {
1049*35148Smarc status_update(status2.input,status1.input,SIGSTIN);
1050*35148Smarc }
1051*35148Smarc else if(status1.output != status2.output)
1052*35148Smarc {
1053*35148Smarc status_update(status2.output,status1.output,SIGSTOP);
1054*35148Smarc }
1055*35148Smarc }
1056*35148Smarc # endif /* SXT */
1057*35148Smarc /* enable fault handler to see if there are any pending jobs */
1058*35148Smarc if((trapnote&SIGJOBS)==0)
1059*35148Smarc signal(SIGCLD,fault);
1060*35148Smarc if(flag==2 && (trapnote&SIGJOBS)==0)
1061*35148Smarc return;
1062*35148Smarc # ifdef SXT
1063*35148Smarc if(my_job>=0 && (trapnote&SIGJOBS)==0 && jobstat.maxjob)
1064*35148Smarc {
1065*35148Smarc errno = 0;
1066*35148Smarc p = ioctl(2, SXTIOCWF, 0);
1067*35148Smarc if(p==0)
1068*35148Smarc /* job stopped */
1069*35148Smarc {
1070*35148Smarc ioctl(2, SXTIOCBLK, my_job);
1071*35148Smarc if(fd_chan>=0)
1072*35148Smarc {
1073*35148Smarc if(ioctl(fd_chan,TCFLSH,2)!=0)
1074*35148Smarc {
1075*35148Smarc ;
1076*35148Smarc }
1077*35148Smarc }
1078*35148Smarc pw->p_flag |= (P_NOTIFY|P_STOPPED);
1079*35148Smarc pw->p_sig = SIGSTOP;
1080*35148Smarc reset_ttygrp(pw,1);
1081*35148Smarc break;
1082*35148Smarc }
1083*35148Smarc }
1084*35148Smarc # endif /* SXT */
1085*35148Smarc #endif /* BSD */
1086*35148Smarc trapnote &= ~ SIGJOBS;
1087*35148Smarc p=wait(&w);
1088*35148Smarc if(p== -1)
1089*35148Smarc {
1090*35148Smarc if(errno==ECHILD)
1091*35148Smarc {
1092*35148Smarc postclr();
1093*35148Smarc return;
1094*35148Smarc }
1095*35148Smarc else if(errno==EINTR)
1096*35148Smarc {
1097*35148Smarc if(trapnote&SIGJOBS)
1098*35148Smarc continue;
1099*35148Smarc if(flag)
1100*35148Smarc break;
1101*35148Smarc }
1102*35148Smarc continue;
1103*35148Smarc }
1104*35148Smarc trapnote &= ~ SIGJOBS;
1105*35148Smarc pw = job_bypid(p);
1106*35148Smarc #ifdef SXT
1107*35148Smarc pw->p_flag &= ~P_STOPPED;
1108*35148Smarc #endif /* SXT */
1109*35148Smarc /* restore original tty state if jobs aborted */
1110*35148Smarc if(p == i && (states&MONITOR))
1111*35148Smarc reset_ttygrp(pw,w&LOBYTE);
1112*35148Smarc }
1113*35148Smarc if(pw)
1114*35148Smarc {
1115*35148Smarc numrun--;
1116*35148Smarc pw->p_flag |= P_NOTIFY;
1117*35148Smarc #ifdef BSD
1118*35148Smarc if((states&MONITOR) && WIFSTOPPED(wstat))
1119*35148Smarc pw->p_flag |= P_STOPPED;
1120*35148Smarc else
1121*35148Smarc #endif /* BSD */
1122*35148Smarc {
1123*35148Smarc if(p==cpid)
1124*35148Smarc {
1125*35148Smarc cpid = 0;
1126*35148Smarc cpipe[1] = NULL;
1127*35148Smarc }
1128*35148Smarc if(p==i || (states&MONITOR)==0)
1129*35148Smarc {
1130*35148Smarc if(px=unpost(pw))
1131*35148Smarc {
1132*35148Smarc if(i)
1133*35148Smarc {
1134*35148Smarc if(p==i && (states&MONITOR))
1135*35148Smarc set_job(px);
1136*35148Smarc i = px->p_pid;
1137*35148Smarc }
1138*35148Smarc continue;
1139*35148Smarc }
1140*35148Smarc }
1141*35148Smarc }
1142*35148Smarc }
1143*35148Smarc sig = w&0177;
1144*35148Smarc if(states&MONITOR)
1145*35148Smarc {
1146*35148Smarc #ifdef BSD
1147*35148Smarc if(WIFSTOPPED(wstat))
1148*35148Smarc {
1149*35148Smarc if(pw)
1150*35148Smarc pw->p_sig = wstat.w_S.w_Stopsig;
1151*35148Smarc if(p == i)
1152*35148Smarc break;
1153*35148Smarc continue;
1154*35148Smarc }
1155*35148Smarc else if(p!=i)
1156*35148Smarc #else
1157*35148Smarc if(p!=i)
1158*35148Smarc #endif /* BSD */
1159*35148Smarc {
1160*35148Smarc if(pw)
1161*35148Smarc pw->p_sig = w;
1162*35148Smarc if(w&HIGHBIT)
1163*35148Smarc pw->p_flag |= P_COREDUMP;
1164*35148Smarc continue;
1165*35148Smarc }
1166*35148Smarc /* this is needed since child not in same process group */
1167*35148Smarc else if(sig==SIGINT || sig==SIGQUIT || sig==SIGHUP)
1168*35148Smarc fault(sig);
1169*35148Smarc }
1170*35148Smarc w_hi = (w>>8)&LOBYTE;
1171*35148Smarc if(sig)
1172*35148Smarc {
1173*35148Smarc if(sig == 0177 /* ptrace! return */)
1174*35148Smarc {
1175*35148Smarc fputs(ptrace,output);
1176*35148Smarc sig = w_hi;
1177*35148Smarc }
1178*35148Smarc if(sig!=SIGINT && sig!=SIGPIPE)
1179*35148Smarc {
1180*35148Smarc if(i!=p || (states&PROMPT)==0)
1181*35148Smarc p_prp(itos(p),SP);
1182*35148Smarc fputs(sysmsg[sig],output);
1183*35148Smarc if(w&HIGHBIT)
1184*35148Smarc fputs(coredump,output);
1185*35148Smarc }
1186*35148Smarc newline();
1187*35148Smarc }
1188*35148Smarc if(p == i)
1189*35148Smarc {
1190*35148Smarc rc = (sig ? sig|SIGFAIL : w_hi);
1191*35148Smarc break;
1192*35148Smarc }
1193*35148Smarc if(i == 0)
1194*35148Smarc break;
1195*35148Smarc }
1196*35148Smarc if(flag>=2)
1197*35148Smarc return;
1198*35148Smarc exitval=rc;
1199*35148Smarc exitset();
1200*35148Smarc }
1201*35148Smarc
1202*35148Smarc #if BSD || SXT
1203*35148Smarc /*
1204*35148Smarc * turn off STOP state of a process group
1205*35148Smarc */
1206*35148Smarc
unstop(grp)1207*35148Smarc static int unstop(grp)
1208*35148Smarc register int grp;
1209*35148Smarc {
1210*35148Smarc register struct process *pw;
1211*35148Smarc register int num = numrun;
1212*35148Smarc for(pw=pwlist;pw;pw=pw->p_next)
1213*35148Smarc {
1214*35148Smarc if(pw->p_pgrp != grp)
1215*35148Smarc continue;
1216*35148Smarc if(pw->p_flag&P_STOPPED)
1217*35148Smarc {
1218*35148Smarc num++;
1219*35148Smarc pw->p_flag &= ~P_STOPPED;
1220*35148Smarc pw->p_sig = 0;
1221*35148Smarc # ifdef SXT
1222*35148Smarc break;
1223*35148Smarc # endif /* SXT */
1224*35148Smarc }
1225*35148Smarc }
1226*35148Smarc if(num!=numrun)
1227*35148Smarc {
1228*35148Smarc p_flush();
1229*35148Smarc #ifdef BSD
1230*35148Smarc numrun = num;
1231*35148Smarc return(killpg(grp,SIGCONT));
1232*35148Smarc #endif
1233*35148Smarc }
1234*35148Smarc return(-1);
1235*35148Smarc }
1236*35148Smarc #endif /* BSD */
1237*35148Smarc
1238*35148Smarc /*
1239*35148Smarc * remove a process group from table
1240*35148Smarc * If all the processes have not completed then unpost returns
1241*35148Smarc * the structure pointer of an unfinished process.
1242*35148Smarc * Otherwise NULL is returned.
1243*35148Smarc */
1244*35148Smarc
unpost(pwtop)1245*35148Smarc static struct process *unpost(pwtop)
1246*35148Smarc struct process *pwtop;
1247*35148Smarc {
1248*35148Smarc register struct process *pw;
1249*35148Smarc register struct process *px=NULL;
1250*35148Smarc register int job = pwtop->p_job;
1251*35148Smarc register struct process *py;
1252*35148Smarc /* look for unfinished processes */
1253*35148Smarc for(pw=pwlist;pw;pw=pw->p_next)
1254*35148Smarc {
1255*35148Smarc if(pw->p_job != job)
1256*35148Smarc continue;
1257*35148Smarc if((pw->p_flag&P_NOTIFY)==0)
1258*35148Smarc px = pw;
1259*35148Smarc }
1260*35148Smarc if(px)
1261*35148Smarc {
1262*35148Smarc px->p_flag &= ~P_PIPEJOB;
1263*35148Smarc px->p_flag |= P_WAITED;
1264*35148Smarc return(px);
1265*35148Smarc }
1266*35148Smarc /* all processes complete, unpost job */
1267*35148Smarc for(pw=pwlist;pw;pw=py)
1268*35148Smarc {
1269*35148Smarc py = pw->p_next;
1270*35148Smarc if(pw->p_job != job)
1271*35148Smarc {
1272*35148Smarc px = pw;
1273*35148Smarc continue;
1274*35148Smarc }
1275*35148Smarc numpost--;
1276*35148Smarc if(px==NULL)
1277*35148Smarc pwlist = py;
1278*35148Smarc else
1279*35148Smarc px->p_next = py;
1280*35148Smarc pw->p_next = freelist;
1281*35148Smarc freelist = pw;
1282*35148Smarc }
1283*35148Smarc free_job((int)pwtop->p_job);
1284*35148Smarc return(NULL);
1285*35148Smarc }
1286*35148Smarc
1287*35148Smarc /*
1288*35148Smarc * unlink a process form the process list
1289*35148Smarc */
1290*35148Smarc
pw_unlink(pw)1291*35148Smarc static void pw_unlink(pw)
1292*35148Smarc register struct process *pw;
1293*35148Smarc {
1294*35148Smarc register struct process *px;
1295*35148Smarc if(pw==pwlist)
1296*35148Smarc {
1297*35148Smarc pwlist = pw->p_next;
1298*35148Smarc return;
1299*35148Smarc }
1300*35148Smarc for(px=pwlist;px;px=px->p_next)
1301*35148Smarc if(px->p_next == pw)
1302*35148Smarc {
1303*35148Smarc px->p_next = pw->p_next;
1304*35148Smarc return;
1305*35148Smarc }
1306*35148Smarc }
1307*35148Smarc
1308*35148Smarc /*
1309*35148Smarc * get an unused job number
1310*35148Smarc * freejobs is a bit vector, 0 is unused
1311*35148Smarc */
1312*35148Smarc
get_job()1313*35148Smarc static int get_job()
1314*35148Smarc {
1315*35148Smarc register int j=0;
1316*35148Smarc register unsigned mask = 1;
1317*35148Smarc register unsigned char *freeword;
1318*35148Smarc /* skip to first word with a free slot */
1319*35148Smarc while(freejobs[j] == 0xff)
1320*35148Smarc j++;
1321*35148Smarc freeword = &freejobs[j];
1322*35148Smarc j *= 8;
1323*35148Smarc for(j++;mask&(*freeword);j++,mask <<=1);
1324*35148Smarc *freeword |=mask;
1325*35148Smarc return(j);
1326*35148Smarc }
1327*35148Smarc
1328*35148Smarc /*
1329*35148Smarc * return a job number
1330*35148Smarc */
1331*35148Smarc
free_job(n)1332*35148Smarc static void free_job(n)
1333*35148Smarc register int n;
1334*35148Smarc {
1335*35148Smarc register int j = (--n)/8;
1336*35148Smarc register unsigned mask;
1337*35148Smarc n -= j*8;
1338*35148Smarc mask = 1 << n;
1339*35148Smarc freejobs[j] &= ~mask;
1340*35148Smarc }
1341*35148Smarc
1342*35148Smarc #ifdef SXT
1343*35148Smarc /*
1344*35148Smarc * open up the input streams for a new channel
1345*35148Smarc */
1346*35148Smarc
1347*35148Smarc static char *open_mode[3] = {"r","w","w+"};
j_new_chan()1348*35148Smarc j_new_chan()
1349*35148Smarc {
1350*35148Smarc register FILE* fd;
1351*35148Smarc register int i;
1352*35148Smarc sxt[11] = '0' + jobstat.cur_job;
1353*35148Smarc close(jobstat.pipe[0]);
1354*35148Smarc fd = fopen(sxt,"r+");
1355*35148Smarc if(ioctl(fileno(fd),TCSETA,&my_stty)<0 || fd==NULL)
1356*35148Smarc {
1357*35148Smarc close(jobstat.pipe[1]);
1358*35148Smarc return(0);
1359*35148Smarc }
1360*35148Smarc for(i=0;i<3;i++)
1361*35148Smarc {
1362*35148Smarc if(isatty(i))
1363*35148Smarc {
1364*35148Smarc fclose(file_fd(i));
1365*35148Smarc fdopen(dup(fileno(fd)),open_mode[i]);
1366*35148Smarc }
1367*35148Smarc }
1368*35148Smarc fclose(fd);
1369*35148Smarc write(jobstat.pipe[1],nullstr,1);
1370*35148Smarc close(jobstat.pipe[1]);
1371*35148Smarc return(1);
1372*35148Smarc }
1373*35148Smarc
next_job()1374*35148Smarc int next_job()
1375*35148Smarc {
1376*35148Smarc register int i = get_job();
1377*35148Smarc free_job(i);
1378*35148Smarc return(i);
1379*35148Smarc }
1380*35148Smarc
status_update(mask2,mask1,sigval)1381*35148Smarc static status_update(mask2,mask1,sigval)
1382*35148Smarc {
1383*35148Smarc register int i,j;
1384*35148Smarc register struct process *pw;
1385*35148Smarc for(i = 1; i < MAXPCHAN; i++)
1386*35148Smarc {
1387*35148Smarc j = 1<<i;
1388*35148Smarc if((mask1&j)==0 && (mask2&j))
1389*35148Smarc {
1390*35148Smarc if(pw = job_bynum(i))
1391*35148Smarc pw->p_sig = sigval;
1392*35148Smarc }
1393*35148Smarc else if((mask2&j)==0 && (mask1&j))
1394*35148Smarc {
1395*35148Smarc if(pw = job_bynum(i))
1396*35148Smarc pw->p_sig = 0;
1397*35148Smarc }
1398*35148Smarc }
1399*35148Smarc }
1400*35148Smarc
open_chan(j)1401*35148Smarc static int open_chan(j)
1402*35148Smarc {
1403*35148Smarc sxt[11] = '0' + j;
1404*35148Smarc if(fd_chan>=0)
1405*35148Smarc {
1406*35148Smarc return;
1407*35148Smarc }
1408*35148Smarc fd_chan = open(sxt,2);
1409*35148Smarc }
1410*35148Smarc #endif /* SXT */
1411*35148Smarc
1412