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