getwd moved to libc.a and error return changed
[unix-history] / usr / src / bin / csh / proc.c
CommitLineData
ea775389 1static char *sccsid = "@(#)proc.c 4.7 (Berkeley) 82/12/30";
2d4bbda8
BJ
2
3#include "sh.h"
4#include "sh.dir.h"
5#include "sh.proc.h"
6#include <wait.h>
7#include <sys/ioctl.h>
8
9/*
10 * C Shell - functions that manage processes, handling hanging, termination
11 */
12
13#define BIGINDEX 9 /* largest desirable job index */
14
15/*
16 * pchild - called at interrupt level by the SIGCHLD signal
17 * indicating that at least one child has terminated or stopped
18 * thus at least one wait system call will definitely return a
19 * childs status. Top level routines (like pwait) must be sure
20 * to mask interrupts when playing with the proclist data structures!
21 */
22pchild()
23{
24 register struct process *pp;
25 register struct process *fp;
26 register int pid;
27 union wait w;
28 int jobflags;
ea775389 29 struct rusage ru;
2d4bbda8
BJ
30
31 if (!timesdone)
32 timesdone++, times(&shtimes);
33loop:
34 pid = wait3(&w.w_status, (setintr ? WNOHANG|WUNTRACED:WNOHANG),
ea775389 35 &ru);
2d4bbda8
BJ
36 if (pid <= 0) {
37 if (errno == EINTR) {
38 errno = 0;
39 goto loop;
40 }
41 pnoprocesses = pid == -1;
42 return;
43 }
44 for (pp = proclist.p_next; pp != PNULL; pp = pp->p_next)
45 if (pid == pp->p_pid)
46 goto found;
47 goto loop;
48found:
49 if (pid == atoi(value("child")))
50 unsetv("child");
51 pp->p_flags &= ~(PRUNNING|PSTOPPED|PREPORTED);
52 if (WIFSTOPPED(w)) {
53 pp->p_flags |= PSTOPPED;
54 pp->p_reason = w.w_stopsig;
55 } else {
56 if (pp->p_flags & (PTIME|PPTIME) || adrof("time")) {
57 time_t oldcutimes, oldcstimes;
58 oldcutimes = shtimes.tms_cutime;
59 oldcstimes = shtimes.tms_cstime;
60 time(&pp->p_etime);
61 times(&shtimes);
62 pp->p_utime = shtimes.tms_cutime - oldcutimes;
63 pp->p_stime = shtimes.tms_cstime - oldcstimes;
64 } else
65 times(&shtimes);
ea775389 66 pp->p_rusage = ru;
2d4bbda8
BJ
67 if (WIFSIGNALED(w)) {
68 if (w.w_termsig == SIGINT)
69 pp->p_flags |= PINTERRUPTED;
70 else
71 pp->p_flags |= PSIGNALED;
72 if (w.w_coredump)
73 pp->p_flags |= PDUMPED;
74 pp->p_reason = w.w_termsig;
75 } else {
76 pp->p_reason = w.w_retcode;
2d4bbda8 77 if (pp->p_reason != 0)
2d4bbda8
BJ
78 pp->p_flags |= PAEXITED;
79 else
80 pp->p_flags |= PNEXITED;
81 }
82 }
83 jobflags = 0;
84 fp = pp;
85 do {
86 if ((fp->p_flags & (PPTIME|PRUNNING|PSTOPPED)) == 0 &&
87 !child && adrof("time") &&
88 (fp->p_utime + fp->p_stime) / HZ >=
89 atoi(value("time")))
90 fp->p_flags |= PTIME;
91 jobflags |= fp->p_flags;
92 } while ((fp = fp->p_friends) != pp);
93 pp->p_flags &= ~PFOREGND;
94 if (pp == pp->p_friends && (pp->p_flags & PPTIME)) {
95 pp->p_flags &= ~PPTIME;
96 pp->p_flags |= PTIME;
97 }
98 if ((jobflags & (PRUNNING|PREPORTED)) == 0) {
99 fp = pp;
100 do {
101 if (fp->p_flags&PSTOPPED)
102 fp->p_flags |= PREPORTED;
103 } while((fp = fp->p_friends) != pp);
104 while(fp->p_pid != fp->p_jobid)
105 fp = fp->p_friends;
a132d4ed
BJ
106 if (jobflags&PSTOPPED) {
107 if (pcurrent && pcurrent != fp)
108 pprevious = pcurrent;
109 pcurrent = fp;
110 } else
111 pclrcurr(fp);
2d4bbda8 112 if (jobflags&PFOREGND) {
2d4bbda8
BJ
113 if (jobflags & (PSIGNALED|PSTOPPED|PPTIME) ||
114#ifdef IIASA
115 jobflags & PAEXITED ||
116#endif
117 !eq(dcwd->di_name, fp->p_cwd->di_name)) {
401149be 118 ; /* print in pjwait */
b3409321
BJ
119 }
120/*
121 else if ((jobflags & (PTIME|PSTOPPED)) == PTIME)
2d4bbda8 122 ptprint(fp);
b3409321 123*/
2d4bbda8
BJ
124 } else {
125 if (jobflags&PNOTIFY || adrof("notify")) {
126 printf("\215\n");
127 pprint(pp, NUMBER|NAME|REASON);
128 if ((jobflags&PSTOPPED) == 0)
129 pflush(pp);
130 } else {
2d4bbda8
BJ
131 fp->p_flags |= PNEEDNOTE;
132 neednote++;
133 }
134 }
135 }
136 goto loop;
137}
138
139pnote()
140{
141 register struct process *pp;
142 int flags;
143
144 neednote = 0;
145 for (pp = proclist.p_next; pp != PNULL; pp = pp->p_next) {
146 if (pp->p_flags & PNEEDNOTE) {
147 sighold(SIGCHLD);
148 pp->p_flags &= ~PNEEDNOTE;
149 flags = pprint(pp, NUMBER|NAME|REASON);
150 if ((flags&(PRUNNING|PSTOPPED)) == 0)
151 pflush(pp);
152 sigrelse(SIGCHLD);
153 }
154 }
155}
156
157/*
158 * pwait - wait for current job to terminate, maintaining integrity
159 * of current and previous job indicators.
160 */
161pwait()
162{
163 register struct process *fp, *pp;
164
165 /*
166 * Here's where dead procs get flushed.
167 */
168 sighold(SIGCHLD);
169 for (pp = (fp = &proclist)->p_next; pp != PNULL; pp = (fp = pp)->p_next)
170 if (pp->p_pid == 0) {
171 fp->p_next = pp->p_next;
172 xfree(pp->p_command);
173 if (pp->p_cwd && --pp->p_cwd->di_count == 0)
174 if (pp->p_cwd->di_next == 0)
175 dfree(pp->p_cwd);
176 xfree((char *)pp);
177 pp = fp;
178 }
179 sigrelse(SIGCHLD);
180 if (setintr)
181 sigignore(SIGINT);
182 pjwait(pcurrjob);
183}
184
185/*
186 * pjwait - wait for a job to finish or become stopped
187 * It is assumed to be in the foreground state (PFOREGND)
188 */
189pjwait(pp)
190 register struct process *pp;
191{
192 register struct process *fp;
193 int jobflags, reason;
194
195 fp = pp;
196 do {
197 if ((fp->p_flags&(PFOREGND|PRUNNING)) == PRUNNING)
198 printf("BUG: waiting for background job!\n");
199 } while ((fp = fp->p_friends) != pp);
200 /*
201 * Now keep pausing as long as we are not interrupted (SIGINT),
202 * and the target process, or any of its friends, are running
203 */
204 fp = pp;
205 for (;;) {
206 sighold(SIGCHLD);
207 jobflags = 0;
208 do
209 jobflags |= fp->p_flags;
210 while((fp = (fp->p_friends)) != pp);
211 if ((jobflags & PRUNNING) == 0)
212 break;
213 sigpause(SIGCHLD);
214 }
215 sigrelse(SIGCHLD);
216 if (tpgrp > 0)
217 ioctl(FSHTTY, TIOCSPGRP, &tpgrp); /* get tty back */
cd4a3dcb
BJ
218 if ((jobflags&(PSIGNALED|PSTOPPED|PTIME)) ||
219 !eq(dcwd->di_name, fp->p_cwd->di_name)) {
220 if (jobflags&PSTOPPED)
221 printf("\n");
222 pprint(pp, AREASON|SHELLDIR);
223 }
401149be 224 if ((jobflags&(PINTERRUPTED|PSTOPPED)) && setintr &&
2d4bbda8 225 (!gointr || !eq(gointr, "-"))) {
401149be
BJ
226 if ((jobflags & PSTOPPED) == 0)
227 pflush(pp);
401149be 228 pintr1(0);
2d4bbda8
BJ
229 /*NOTREACHED*/
230 }
231 reason = 0;
232 fp = pp;
233 do {
234 if (fp->p_reason)
235 reason = fp->p_flags & (PSIGNALED|PINTERRUPTED) ?
236 fp->p_reason | QUOTE : fp->p_reason;
237 } while ((fp = fp->p_friends) != pp);
238 set("status", putn(reason));
239 if (reason && exiterr)
240 exitstat();
241 pflush(pp);
242}
243
244/*
245 * dowait - wait for all processes to finish
246 */
247dowait()
248{
249 register struct process *pp;
250
251 pjobs++;
252 if (setintr)
253 sigrelse(SIGINT);
254loop:
255 sighold(SIGCHLD);
256 for (pp = proclist.p_next; pp; pp = pp->p_next)
257 if (pp->p_pid && pp->p_pid == pp->p_jobid &&
258 pp->p_flags&PRUNNING) {
259 sigpause(SIGCHLD);
260 goto loop;
261 }
262 sigrelse(SIGCHLD);
263 pjobs = 0;
264}
265
266/*
267 * pflushall - flush all jobs from list (e.g. at fork())
268 */
269pflushall()
270{
271 register struct process *pp;
272
273 for (pp = proclist.p_next; pp != PNULL; pp = pp->p_next)
274 if (pp->p_pid)
275 pflush(pp);
276}
277
278/*
279 * pflush - flag all process structures in the same job as the
280 * the argument process for deletion. The actual free of the
281 * space is not done here since pflush is called at interrupt level.
282 */
283pflush(pp)
284 register struct process *pp;
285{
286 register struct process *np;
287 register int index;
288
289 if (pp->p_pid == 0) {
290 printf("BUG: process flushed twice");
291 return;
292 }
293 while (pp->p_pid != pp->p_jobid)
294 pp = pp->p_friends;
295 pclrcurr(pp);
296 if (pp == pcurrjob)
297 pcurrjob = 0;
298 index = pp->p_index;
299 np = pp;
300 do {
301 np->p_index = np->p_pid = 0;
302 np->p_flags &= ~PNEEDNOTE;
303 } while ((np = np->p_friends) != pp);
304 if (index == pmaxindex) {
305 for (np = proclist.p_next, index = 0; np; np = np->p_next)
306 if (np->p_index > index)
307 index = np->p_index;
308 pmaxindex = index;
309 }
310}
311
312/*
313 * pclrcurr - make sure the given job is not the current or previous job;
314 * pp MUST be the job leader
315 */
316pclrcurr(pp)
317 register struct process *pp;
318{
319
320 if (pp == pcurrent)
321 if (pprevious != PNULL) {
322 pcurrent = pprevious;
323 pprevious = pgetcurr(pp);
324 } else {
325 pcurrent = pgetcurr(pp);
326 pprevious = pgetcurr(pp);
327 }
328 else if (pp == pprevious)
329 pprevious = pgetcurr(pp);
330}
331
332/* +4 here is 1 for '\0', 1 ea for << >& >> */
333char command[PMAXLEN+4];
334int cmdlen;
335char *cmdp;
336/*
337 * palloc - allocate a process structure and fill it up.
338 * an important assumption is made that the process is running.
339 */
340palloc(pid, t)
341 int pid;
342 register struct command *t;
343{
344 register struct process *pp;
345 int i;
346
347 pp = (struct process *)calloc(1, sizeof(struct process));
348 pp->p_pid = pid;
349 pp->p_flags = t->t_dflg & FAND ? PRUNNING : PRUNNING|PFOREGND;
350 if (t->t_dflg & FTIME)
351 pp->p_flags |= PPTIME;
352 cmdp = command;
353 cmdlen = 0;
354 padd(t);
355 *cmdp++ = 0;
356 if (t->t_dflg & FPOU) {
357 pp->p_flags |= PPOU;
358 if (t->t_dflg & FDIAG)
359 pp->p_flags |= PDIAG;
360 }
361 pp->p_command = savestr(command);
362 if (pcurrjob) {
363 struct process *fp;
364 /* careful here with interrupt level */
365 pp->p_cwd = 0;
366 pp->p_index = pcurrjob->p_index;
367 pp->p_friends = pcurrjob;
368 pp->p_jobid = pcurrjob->p_pid;
369 for (fp = pcurrjob; fp->p_friends != pcurrjob; fp = fp->p_friends)
370 ;
371 fp->p_friends = pp;
372 } else {
373 pcurrjob = pp;
374 pp->p_jobid = pid;
375 pp->p_friends = pp;
376 pp->p_cwd = dcwd;
377 dcwd->di_count++;
378 if (pmaxindex < BIGINDEX)
379 pp->p_index = ++pmaxindex;
380 else {
381 struct process *np;
382
383 for (i = 1; ; i++) {
384 for (np = proclist.p_next; np; np = np->p_next)
385 if (np->p_index == i)
386 goto tryagain;
a132d4ed
BJ
387 pp->p_index = i;
388 if (i > pmaxindex)
389 pmaxindex = i;
2d4bbda8
BJ
390 break;
391 tryagain:;
392 }
393 }
394 if (pcurrent == PNULL)
395 pcurrent = pp;
396 else if (pprevious == PNULL)
397 pprevious = pp;
398 }
399 pp->p_next = proclist.p_next;
400 proclist.p_next = pp;
401 time(&pp->p_btime);
402}
403
404padd(t)
405 register struct command *t;
406{
407 char **argp;
408
409 if (t == 0)
410 return;
411 switch (t->t_dtyp) {
412
413 case TPAR:
414 pads("( ");
415 padd(t->t_dspr);
416 pads(" )");
417 break;
418
419 case TCOM:
420 for (argp = t->t_dcom; *argp; argp++) {
421 pads(*argp);
422 if (argp[1])
423 pads(" ");
424 }
425 break;
426
427 case TFIL:
428 padd(t->t_dcar);
429 pads(" | ");
430 padd(t->t_dcdr);
431 return;
432
433 case TLST:
434 padd(t->t_dcar);
435 pads("; ");
436 padd(t->t_dcdr);
437 return;
438 }
439 if ((t->t_dflg & FPIN) == 0 && t->t_dlef) {
440 pads((t->t_dflg & FHERE) ? " << " : " < ");
441 pads(t->t_dlef);
442 }
443 if ((t->t_dflg & FPOU) == 0 && t->t_drit) {
444 pads((t->t_dflg & FCAT) ? " >>" : " >");
445 if (t->t_dflg & FDIAG)
446 pads("&");
447 pads(" ");
448 pads(t->t_drit);
449 }
450}
451
452pads(cp)
453 char *cp;
454{
455 register int i = strlen(cp);
456
457 if (cmdlen >= PMAXLEN)
458 return;
459 if (cmdlen + i >= PMAXLEN) {
460 strcpy(cmdp, " ...");
461 cmdlen = PMAXLEN;
462 cmdp += 4;
463 return;
464 }
465 strcpy(cmdp, cp);
466 cmdp += i;
467 cmdlen += i;
468}
469
470/*
471 * psavejob - temporarily save the current job on a one level stack
472 * so another job can be created. Used for { } in exp6
473 * and `` in globbing.
474 */
475psavejob()
476{
477
478 pholdjob = pcurrjob;
479 pcurrjob = PNULL;
480}
481
482/*
483 * prestjob - opposite of psavejob. This may be missed if we are interrupted
484 * somewhere, but pendjob cleans up anyway.
485 */
486prestjob()
487{
488
489 pcurrjob = pholdjob;
490 pholdjob = PNULL;
491}
492
493/*
494 * pendjob - indicate that a job (set of commands) has been completed
495 * or is about to begin.
496 */
497pendjob()
498{
499 register struct process *pp, *tp;
500
501 if (pcurrjob && (pcurrjob->p_flags&(PFOREGND|PSTOPPED)) == 0) {
502 pp = pcurrjob;
503 while (pp->p_pid != pp->p_jobid)
504 pp = pp->p_friends;
505 printf("[%d]", pp->p_index);
506 tp = pp;
507 do {
508 printf(" %d", pp->p_pid);
509 pp = pp->p_friends;
510 } while (pp != tp);
511 printf("\n");
512 }
513 pholdjob = pcurrjob = 0;
514}
515
516/*
517 * pprint - print a job
518 */
519pprint(pp, flag)
520 register struct process *pp;
521{
522 register status, reason;
523 struct process *tp;
524 extern char *linp, linbuf[];
525 int jobflags, pstatus;
526 char *format;
527
528 while (pp->p_pid != pp->p_jobid)
529 pp = pp->p_friends;
530 if (pp == pp->p_friends && (pp->p_flags & PPTIME)) {
531 pp->p_flags &= ~PPTIME;
532 pp->p_flags |= PTIME;
533 }
534 tp = pp;
535 status = reason = -1;
536 jobflags = 0;
537 do {
538 jobflags |= pp->p_flags;
539 pstatus = pp->p_flags & PALLSTATES;
540 if (tp != pp && linp != linbuf && !(flag&FANCY) &&
541 (pstatus == status && pp->p_reason == reason ||
542 !(flag&REASON)))
543 printf(" ");
544 else {
545 if (tp != pp && linp != linbuf)
546 printf("\n");
547 if(flag&NUMBER)
548 if (pp == tp)
549 printf("[%d]%s %c ", pp->p_index,
550 pp->p_index < 10 ? " " : "",
551 pp==pcurrent ? '+' :
552 (pp == pprevious ? '-' : ' '));
553 else
554 printf(" ");
555 if (flag&FANCY)
556 printf("%5d ", pp->p_pid);
557 if (flag&(REASON|AREASON)) {
558 if (flag&NAME)
559 format = "%-21s";
560 else
561 format = "%s";
562 if (pstatus == status)
563 if (pp->p_reason == reason) {
564 printf(format, "");
565 goto prcomd;
566 } else
567 reason = pp->p_reason;
568 else {
569 status = pstatus;
570 reason = pp->p_reason;
571 }
572 switch (status) {
573
574 case PRUNNING:
575 printf(format, "Running ");
576 break;
577
578 case PINTERRUPTED:
579 case PSTOPPED:
580 case PSIGNALED:
581 if (flag&REASON || reason != SIGINT ||
582 reason != SIGPIPE)
583 printf(format, mesg[pp->p_reason].pname);
584 break;
585
586 case PNEXITED:
587 case PAEXITED:
588 if (flag & REASON)
589 if (pp->p_reason)
590 printf("Exit %-16d", pp->p_reason);
591 else
592 printf(format, "Done");
593 break;
594
595 default:
596 printf("BUG: status=%-9o", status);
597 }
598 }
599 }
600prcomd:
601 if (flag&NAME) {
602 printf("%s", pp->p_command);
603 if (pp->p_flags & PPOU)
604 printf(" |");
605 if (pp->p_flags & PDIAG)
606 printf("&");
607 }
608 if (flag&(REASON|AREASON) && pp->p_flags&PDUMPED)
609 printf(" (core dumped)");
610 if (tp == pp->p_friends) {
611 if (flag&AMPERSAND)
612 printf(" &");
613 if (flag&JOBDIR &&
614 !eq(tp->p_cwd->di_name, dcwd->di_name)) {
615 printf(" (wd: ");
616 dtildepr(value("home"), tp->p_cwd->di_name);
617 printf(")");
618 }
619 }
620 if (pp->p_flags&PPTIME && !(status&(PSTOPPED|PRUNNING))) {
621 if (linp != linbuf)
622 printf("\n\t");
ea775389
SL
623 { static struct rusage zru;
624 prusage(&zru, &pp->p_rusage,
625 pp->p_etime - pp->p_btime);
626 }
2d4bbda8
BJ
627 }
628 if (tp == pp->p_friends) {
629 if (linp != linbuf)
630 printf("\n");
631 if (flag&SHELLDIR && !eq(tp->p_cwd->di_name, dcwd->di_name)) {
632 printf("(wd now: ");
633 dtildepr(value("home"), dcwd->di_name);
634 printf(")\n");
635 }
636 }
637 } while ((pp = pp->p_friends) != tp);
638 if (jobflags&PTIME && (jobflags&(PSTOPPED|PRUNNING)) == 0) {
639 if (jobflags & NUMBER)
640 printf(" ");
641 ptprint(tp);
642 }
643 return (jobflags);
644}
645
646ptprint(tp)
647 register struct process *tp;
648{
649 time_t tetime = 0;
ea775389
SL
650 struct rusage ru;
651 static struct rusage zru;
2d4bbda8
BJ
652 register struct process *pp = tp;
653
ea775389 654 ru = zru;
2d4bbda8 655 do {
ea775389 656 ruadd(&ru, &pp->p_rusage);
2d4bbda8
BJ
657 if (pp->p_etime - pp->p_btime > tetime)
658 tetime = pp->p_etime - pp->p_btime;
659 } while ((pp = pp->p_friends) != tp);
ea775389 660 prusage(&zru, &ru, tetime);
2d4bbda8
BJ
661}
662
663/*
664 * dojobs - print all jobs
665 */
666dojobs(v)
667 char **v;
668{
669 register struct process *pp;
670 register int flag = NUMBER|NAME|REASON;
671 int i;
672
673 if (chkstop)
674 chkstop = 2;
675 if (*++v) {
676 if (v[1] || !eq(*v, "-l"))
677 error("Usage: jobs [ -l ]");
678 flag |= FANCY|JOBDIR;
679 }
680 for (i = 1; i <= pmaxindex; i++)
681 for (pp = proclist.p_next; pp; pp = pp->p_next)
682 if (pp->p_index == i && pp->p_pid == pp->p_jobid) {
683 pp->p_flags &= ~PNEEDNOTE;
684 if (!(pprint(pp, flag) & (PRUNNING|PSTOPPED)))
685 pflush(pp);
686 break;
687 }
688}
689
690/*
691 * dofg - builtin - put the job into the foreground
692 */
693dofg(v)
694 char **v;
695{
696 register struct process *pp;
697
698 okpcntl();
699 ++v;
700 do {
701 pp = pfind(*v);
702 pstart(pp, 1);
703 if (setintr)
704 sigignore(SIGINT);
705 pjwait(pp);
706 } while (*v && *++v);
707}
708
709/*
710 * %... - builtin - put the job into the foreground
711 */
712dofg1(v)
713 char **v;
714{
715 register struct process *pp;
716
717 okpcntl();
718 pp = pfind(v[0]);
719 pstart(pp, 1);
720 if (setintr)
721 sigignore(SIGINT);
722 pjwait(pp);
723}
724
725/*
726 * dobg - builtin - put the job into the background
727 */
728dobg(v)
729 char **v;
730{
731 register struct process *pp;
732
733 okpcntl();
734 ++v;
735 do {
736 pp = pfind(*v);
737 pstart(pp, 0);
738 } while (*v && *++v);
739}
740
741/*
742 * %... & - builtin - put the job into the background
743 */
744dobg1(v)
745 char **v;
746{
747 register struct process *pp;
748
749 pp = pfind(v[0]);
750 pstart(pp, 0);
751}
752
753/*
754 * dostop - builtin - stop the job
755 */
756dostop(v)
757 char **v;
758{
759
760 pkill(++v, SIGSTOP);
761}
762
763/*
764 * dokill - builtin - superset of kill (1)
765 */
766dokill(v)
767 char **v;
768{
769 register int signum;
770 register char *name;
771
772 v++;
773 if (v[0] && v[0][0] == '-') {
774 if (v[0][1] == 'l') {
775 for (signum = 1; signum <= NSIG; signum++) {
776 if (name = mesg[signum].iname)
777 printf("%s ", name);
778 if (signum == 16)
779 printf("\n");
780 }
781 printf("\n");
782 return;
783 }
784 if (digit(v[0][1])) {
785 signum = atoi(v[0]+1);
786 if (signum < 1 || signum > NSIG)
787 bferr("Bad signal number");
788 } else {
789 name = &v[0][1];
790 for (signum = 1; signum <= NSIG; signum++)
791 if (mesg[signum].iname &&
792 eq(name, mesg[signum].iname))
793 goto gotsig;
794 setname(name);
795 bferr("Unknown signal; kill -l lists signals");
796 }
797gotsig:
798 v++;
799 } else
800 signum = SIGTERM;
801 pkill(v, signum);
802}
803
804pkill(v, signum)
805 char **v;
806 int signum;
807{
808 register struct process *pp, *np;
809 register int jobflags = 0;
810 int pid;
811 extern char *sys_errlist[];
812 int err = 0;
813
814 if (setintr)
815 sighold(SIGINT);
816 sighold(SIGCHLD);
817 while (*v) {
818 if (**v == '%') {
819 np = pp = pfind(*v);
820 do
821 jobflags |= np->p_flags;
822 while ((np = np->p_friends) != pp);
823 switch (signum) {
824
825 case SIGSTOP:
826 case SIGTSTP:
827 case SIGTTIN:
828 case SIGTTOU:
829 if ((jobflags & PRUNNING) == 0) {
830 printf("%s: Already stopped\n", *v);
831 err++;
832 goto cont;
833 }
834 }
835 killpg(pp->p_jobid, signum);
836 if (signum == SIGTERM || signum == SIGHUP)
837 killpg(pp->p_jobid, SIGCONT);
838 } else if (!digit(**v))
839 bferr("Arguments should be jobs or process id's");
840 else {
841 pid = atoi(*v);
842 if (kill(pid, signum) < 0) {
843 printf("%d: ", pid);
844 printf("%s\n", sys_errlist[errno]);
845 err++;
846 goto cont;
847 }
848 if (signum == SIGTERM || signum == SIGHUP)
849 kill(pid, SIGCONT);
850 }
851cont:
852 v++;
853 }
854 sigrelse(SIGCHLD);
855 if (setintr)
856 sigrelse(SIGINT);
857 if (err)
858 error(NOSTR);
859}
860
861/*
862 * pstart - start the job in foreground/background
863 */
864pstart(pp, foregnd)
865 register struct process *pp;
866 int foregnd;
867{
868 register struct process *np;
869 int jobflags = 0;
870
871 sighold(SIGCHLD);
872 np = pp;
873 do {
874 jobflags |= np->p_flags;
875 if (np->p_flags&(PRUNNING|PSTOPPED)) {
876 np->p_flags |= PRUNNING;
877 np->p_flags &= ~PSTOPPED;
878 if (foregnd)
879 np->p_flags |= PFOREGND;
880 else
881 np->p_flags &= ~PFOREGND;
882 }
883 } while((np = np->p_friends) != pp);
a132d4ed
BJ
884 if (!foregnd)
885 pclrcurr(pp);
2d4bbda8
BJ
886 pprint(pp, foregnd ? NAME|JOBDIR : NUMBER|NAME|AMPERSAND);
887 if (foregnd)
888 ioctl(FSHTTY, TIOCSPGRP, &pp->p_jobid);
889 if (jobflags&PSTOPPED)
890 killpg(pp->p_jobid, SIGCONT);
891 sigrelse(SIGCHLD);
892}
893
894panystop(neednl)
895{
896 register struct process *pp;
897
898 chkstop = 2;
899 for (pp = proclist.p_next; pp; pp = pp->p_next)
900 if (pp->p_flags & PSTOPPED)
901 error("\nThere are stopped jobs" + 1 - neednl);
902}
903
904struct process *
905pfind(cp)
906 char *cp;
907{
908 register struct process *pp, *np;
909
910 if (cp == 0 || cp[1] == 0 || eq(cp, "%%") || eq(cp, "%+")) {
911 if (pcurrent == PNULL)
912 bferr("No current job");
913 return (pcurrent);
914 }
915 if (eq(cp, "%-") || eq(cp, "%#")) {
916 if (pprevious == PNULL)
917 bferr("No previous job");
918 return (pprevious);
919 }
920 if (digit(cp[1])) {
921 int index = atoi(cp+1);
922 for (pp = proclist.p_next; pp; pp = pp->p_next)
923 if (pp->p_index == index && pp->p_pid == pp->p_jobid)
924 return (pp);
925 bferr("No such job");
926 }
927 np = PNULL;
928 for (pp = proclist.p_next; pp; pp = pp->p_next)
929 if (pp->p_pid == pp->p_jobid) {
930 if (cp[1] == '?') {
931 register char *dp;
932 for (dp = pp->p_command; *dp; dp++) {
933 if (*dp != cp[2])
934 continue;
935 if (prefix(cp+2, dp))
936 goto match;
937 }
938 } else if (prefix(cp+1, pp->p_command)) {
939match:
940 if (np)
941 bferr("Ambiguous");
942 np = pp;
943 }
944 }
945 if (np)
946 return (np);
947 if (cp[1] == '?')
948 bferr("No job matches pattern");
949 else
950 bferr("No such job");
951}
952
953/*
a132d4ed 954 * pgetcurr - find most recent job that is not pp, preferably stopped
2d4bbda8
BJ
955 */
956struct process *
957pgetcurr(pp)
958 register struct process *pp;
959{
960 register struct process *np;
a132d4ed 961 register struct process *xp = PNULL;
2d4bbda8
BJ
962
963 for (np = proclist.p_next; np; np = np->p_next)
964 if (np != pcurrent && np != pp && np->p_pid &&
965 np->p_pid == np->p_jobid) {
a132d4ed
BJ
966 if (np->p_flags & PSTOPPED)
967 return (np);
968 if (xp == PNULL)
969 xp = np;
2d4bbda8 970 }
a132d4ed 971 return (xp);
2d4bbda8
BJ
972}
973
974/*
975 * donotify - flag the job so as to report termination asynchronously
976 */
977donotify(v)
978 char **v;
979{
980 register struct process *pp;
981
982 pp = pfind(*++v);
983 pp->p_flags |= PNOTIFY;
984}
985
986/*
987 * Do the fork and whatever should be done in the child side that
988 * should not be done if we are not forking at all (like for simple builtin's)
989 * Also do everything that needs any signals fiddled with in the parent side
990 *
991 * Wanttty tells whether process and/or tty pgrps are to be manipulated:
992 * -1: leave tty alone; inherit pgrp from parent
993 * 0: already have tty; manipulate process pgrps only
994 * 1: want to claim tty; manipulate process and tty pgrps
995 * It is usually just the value of tpgrp.
996 */
997pfork(t, wanttty)
998 struct command *t; /* command we are forking for */
999 int wanttty;
1000{
1001 register int pid;
1002 bool ignint = 0;
1003 int pgrp;
1004
1005 /*
1006 * A child will be uninterruptible only under very special
1007 * conditions. Remember that the semantics of '&' is
1008 * implemented by disconnecting the process from the tty so
1009 * signals do not need to ignored just for '&'.
1010 * Thus signals are set to default action for children unless:
1011 * we have had an "onintr -" (then specifically ignored)
1012 * we are not playing with signals (inherit action)
1013 */
1014 if (setintr)
1015 ignint = (tpgrp == -1 && (t->t_dflg&FINT))
1016 || (gointr && eq(gointr, "-"));
1017 /*
1018 * Hold SIGCHLD until we have the process installed in our table.
1019 */
1020 sighold(SIGCHLD);
1021 while ((pid = fork()) < 0)
1022 if (setintr == 0)
1023 sleep(FORKSLEEP);
1024 else {
1025 sigrelse(SIGINT);
1026 sigrelse(SIGCHLD);
1027 error("No more processes");
1028 }
1029 if (pid == 0) {
1030 settimes();
1031 pgrp = pcurrjob ? pcurrjob->p_jobid : getpid();
1032 pflushall();
1033 pcurrjob = PNULL;
1034 timesdone = 0;
1035 child++;
1036 if (setintr) {
1037 setintr = 0; /* until I think otherwise */
1038 sigrelse(SIGCHLD);
1039 /*
1040 * Children just get blown away on SIGINT, SIGQUIT
1041 * unless "onintr -" seen.
1042 */
1043 signal(SIGINT, ignint ? SIG_IGN : SIG_DFL);
1044 signal(SIGQUIT, ignint ? SIG_IGN : SIG_DFL);
1045 if (wanttty >= 0) {
1046 /* make stoppable */
1047 signal(SIGTSTP, SIG_DFL);
1048 signal(SIGTTIN, SIG_DFL);
1049 signal(SIGTTOU, SIG_DFL);
1050 }
1051 signal(SIGTERM, parterm);
1052 } else if (tpgrp == -1 && (t->t_dflg&FINT)) {
1053 signal(SIGINT, SIG_IGN);
1054 signal(SIGQUIT, SIG_IGN);
1055 }
1056 if (wanttty > 0)
1057 ioctl(FSHTTY, TIOCSPGRP, &pgrp);
1058 if (wanttty >= 0 && tpgrp >= 0)
1059 setpgrp(0, pgrp);
1060 if (tpgrp > 0)
1061 tpgrp = 0; /* gave tty away */
1062 /*
1063 * Nohup and nice apply only to TCOM's but it would be
1064 * nice (?!?) if you could say "nohup (foo;bar)"
1065 * Then the parser would have to know about nice/nohup/time
1066 */
1067 if (t->t_dflg & FNOHUP)
1068 signal(SIGHUP, SIG_IGN);
1069 if (t->t_dflg & FNICE) {
1070/* sigh...
1071 nice(20);
1072 nice(-10);
1073*/
1074 nice(t->t_nice);
1075 }
1076
1077 } else {
1078 palloc(pid, t);
1079 sigrelse(SIGCHLD);
1080 }
1081
1082 return (pid);
1083}
1084
1085okpcntl()
1086{
1087
1088 if (tpgrp == -1)
1089 error("No job control in this shell");
1090 if (tpgrp == 0)
1091 error("No job control in subshells");
1092}