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