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