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