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