proc.c revision 1.12 1 /* $NetBSD: proc.c,v 1.12 1998/05/10 18:32:46 kleink Exp $ */
2
3 /*-
4 * Copyright (c) 1980, 1991, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36 #include <sys/cdefs.h>
37 #ifndef lint
38 #if 0
39 static char sccsid[] = "@(#)proc.c 8.1 (Berkeley) 5/31/93";
40 #else
41 __RCSID("$NetBSD: proc.c,v 1.12 1998/05/10 18:32:46 kleink Exp $");
42 #endif
43 #endif /* not lint */
44
45 #include <sys/types.h>
46 #include <sys/wait.h>
47 #include <errno.h>
48 #include <unistd.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #if __STDC__
52 # include <stdarg.h>
53 #else
54 # include <varargs.h>
55 #endif
56
57 #include "csh.h"
58 #include "dir.h"
59 #include "proc.h"
60 #include "extern.h"
61
62 #define BIGINDEX 9 /* largest desirable job index */
63
64 static struct rusage zru;
65
66 static void pflushall __P((void));
67 static void pflush __P((struct process *));
68 static void pclrcurr __P((struct process *));
69 static void padd __P((struct command *));
70 static int pprint __P((struct process *, int));
71 static void ptprint __P((struct process *));
72 static void pads __P((Char *));
73 static void pkill __P((Char **v, int));
74 static struct process
75 *pgetcurr __P((struct process *));
76 static void okpcntl __P((void));
77
78 /*
79 * pchild - called at interrupt level by the SIGCHLD signal
80 * indicating that at least one child has terminated or stopped
81 * thus at least one wait system call will definitely return a
82 * childs status. Top level routines (like pwait) must be sure
83 * to mask interrupts when playing with the proclist data structures!
84 */
85 /* ARGUSED */
86 void
87 pchild(notused)
88 int notused;
89 {
90 struct process *pp;
91 struct process *fp;
92 int pid;
93 extern int insource;
94 union wait w;
95 int jobflags;
96 struct rusage ru;
97
98 loop:
99 errno = 0; /* reset, just in case */
100 pid = wait3(&w.w_status,
101 (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG), &ru);
102
103 if (pid <= 0) {
104 if (errno == EINTR) {
105 errno = 0;
106 goto loop;
107 }
108 pnoprocesses = pid == -1;
109 return;
110 }
111 for (pp = proclist.p_next; pp != NULL; pp = pp->p_next)
112 if (pid == pp->p_pid)
113 goto found;
114 goto loop;
115 found:
116 if (pid == atoi(short2str(value(STRchild))))
117 unsetv(STRchild);
118 pp->p_flags &= ~(PRUNNING | PSTOPPED | PREPORTED);
119 if (WIFSTOPPED(w)) {
120 pp->p_flags |= PSTOPPED;
121 pp->p_reason = w.w_stopsig;
122 }
123 else {
124 if (pp->p_flags & (PTIME | PPTIME) || adrof(STRtime))
125 (void) gettimeofday(&pp->p_etime, NULL);
126
127 pp->p_rusage = ru;
128 if (WIFSIGNALED(w)) {
129 if (w.w_termsig == SIGINT)
130 pp->p_flags |= PINTERRUPTED;
131 else
132 pp->p_flags |= PSIGNALED;
133 if (w.w_coredump)
134 pp->p_flags |= PDUMPED;
135 pp->p_reason = w.w_termsig;
136 }
137 else {
138 pp->p_reason = w.w_retcode;
139 if (pp->p_reason != 0)
140 pp->p_flags |= PAEXITED;
141 else
142 pp->p_flags |= PNEXITED;
143 }
144 }
145 jobflags = 0;
146 fp = pp;
147 do {
148 if ((fp->p_flags & (PPTIME | PRUNNING | PSTOPPED)) == 0 &&
149 !child && adrof(STRtime) &&
150 fp->p_rusage.ru_utime.tv_sec + fp->p_rusage.ru_stime.tv_sec
151 >= atoi(short2str(value(STRtime))))
152 fp->p_flags |= PTIME;
153 jobflags |= fp->p_flags;
154 } while ((fp = fp->p_friends) != pp);
155 pp->p_flags &= ~PFOREGND;
156 if (pp == pp->p_friends && (pp->p_flags & PPTIME)) {
157 pp->p_flags &= ~PPTIME;
158 pp->p_flags |= PTIME;
159 }
160 if ((jobflags & (PRUNNING | PREPORTED)) == 0) {
161 fp = pp;
162 do {
163 if (fp->p_flags & PSTOPPED)
164 fp->p_flags |= PREPORTED;
165 } while ((fp = fp->p_friends) != pp);
166 while (fp->p_pid != fp->p_jobid)
167 fp = fp->p_friends;
168 if (jobflags & PSTOPPED) {
169 if (pcurrent && pcurrent != fp)
170 pprevious = pcurrent;
171 pcurrent = fp;
172 }
173 else
174 pclrcurr(fp);
175 if (jobflags & PFOREGND) {
176 if (jobflags & (PSIGNALED | PSTOPPED | PPTIME) ||
177 #ifdef IIASA
178 jobflags & PAEXITED ||
179 #endif
180 !eq(dcwd->di_name, fp->p_cwd->di_name)) {
181 ; /* print in pjwait */
182 }
183 /* PWP: print a newline after ^C */
184 else if (jobflags & PINTERRUPTED) {
185 (void) vis_fputc('\r' | QUOTE, cshout);
186 (void) fputc('\n', cshout);
187 }
188 }
189 else {
190 if (jobflags & PNOTIFY || adrof(STRnotify)) {
191 (void) vis_fputc('\r' | QUOTE, cshout);
192 (void) fputc('\n', cshout);
193 (void) pprint(pp, NUMBER | NAME | REASON);
194 if ((jobflags & PSTOPPED) == 0)
195 pflush(pp);
196 }
197 else {
198 fp->p_flags |= PNEEDNOTE;
199 neednote++;
200 }
201 }
202 }
203 goto loop;
204 }
205
206 void
207 pnote()
208 {
209 struct process *pp;
210 int flags;
211 sigset_t sigset, osigset;
212
213 neednote = 0;
214 sigemptyset(&sigset);
215 sigaddset(&sigset, SIGCHLD);
216 for (pp = proclist.p_next; pp != NULL; pp = pp->p_next) {
217 if (pp->p_flags & PNEEDNOTE) {
218 sigprocmask(SIG_BLOCK, &sigset, &osigset);
219 pp->p_flags &= ~PNEEDNOTE;
220 flags = pprint(pp, NUMBER | NAME | REASON);
221 if ((flags & (PRUNNING | PSTOPPED)) == 0)
222 pflush(pp);
223 sigprocmask(SIG_SETMASK, &osigset, NULL);
224 }
225 }
226 }
227
228 /*
229 * pwait - wait for current job to terminate, maintaining integrity
230 * of current and previous job indicators.
231 */
232 void
233 pwait()
234 {
235 struct process *fp, *pp;
236 sigset_t sigset, osigset;
237
238 /*
239 * Here's where dead procs get flushed.
240 */
241 sigemptyset(&sigset);
242 sigaddset(&sigset, SIGCHLD);
243 sigprocmask(SIG_BLOCK, &sigset, &osigset);
244 for (pp = (fp = &proclist)->p_next; pp != NULL; pp = (fp = pp)->p_next)
245 if (pp->p_pid == 0) {
246 fp->p_next = pp->p_next;
247 xfree((ptr_t) pp->p_command);
248 if (pp->p_cwd && --pp->p_cwd->di_count == 0)
249 if (pp->p_cwd->di_next == 0)
250 dfree(pp->p_cwd);
251 xfree((ptr_t) pp);
252 pp = fp;
253 }
254 sigprocmask(SIG_SETMASK, &osigset, NULL);
255 pjwait(pcurrjob);
256 }
257
258
259 /*
260 * pjwait - wait for a job to finish or become stopped
261 * It is assumed to be in the foreground state (PFOREGND)
262 */
263 void
264 pjwait(pp)
265 struct process *pp;
266 {
267 struct process *fp;
268 int jobflags, reason;
269 sigset_t sigset, osigset;
270
271 while (pp->p_pid != pp->p_jobid)
272 pp = pp->p_friends;
273 fp = pp;
274
275 do {
276 if ((fp->p_flags & (PFOREGND | PRUNNING)) == PRUNNING)
277 (void) fprintf(csherr, "BUG: waiting for background job!\n");
278 } while ((fp = fp->p_friends) != pp);
279 /*
280 * Now keep pausing as long as we are not interrupted (SIGINT), and the
281 * target process, or any of its friends, are running
282 */
283 fp = pp;
284 sigemptyset(&sigset);
285 sigaddset(&sigset, SIGCHLD);
286 sigprocmask(SIG_BLOCK, &sigset, &osigset);
287 for (;;) {
288 sigemptyset(&sigset);
289 sigaddset(&sigset, SIGCHLD);
290 sigprocmask(SIG_BLOCK, &sigset, NULL);
291 jobflags = 0;
292 do
293 jobflags |= fp->p_flags;
294 while ((fp = (fp->p_friends)) != pp);
295 if ((jobflags & PRUNNING) == 0)
296 break;
297 #ifdef JOBDEBUG
298 (void) fprintf(csherr, "starting to sigsuspend for SIGCHLD on %d\n",
299 fp->p_pid);
300 #endif /* JOBDEBUG */
301 sigset = osigset;
302 sigdelset(&sigset, SIGCHLD);
303 sigsuspend(&sigset);
304 }
305 sigprocmask(SIG_SETMASK, &osigset, NULL);
306 if (tpgrp > 0) /* get tty back */
307 (void) tcsetpgrp(FSHTTY, tpgrp);
308 if ((jobflags & (PSIGNALED | PSTOPPED | PTIME)) ||
309 !eq(dcwd->di_name, fp->p_cwd->di_name)) {
310 if (jobflags & PSTOPPED) {
311 (void) fputc('\n', cshout);
312 if (adrof(STRlistjobs)) {
313 Char *jobcommand[3];
314
315 jobcommand[0] = STRjobs;
316 if (eq(value(STRlistjobs), STRlong))
317 jobcommand[1] = STRml;
318 else
319 jobcommand[1] = NULL;
320 jobcommand[2] = NULL;
321
322 dojobs(jobcommand, NULL);
323 (void) pprint(pp, SHELLDIR);
324 }
325 else
326 (void) pprint(pp, AREASON | SHELLDIR);
327 }
328 else
329 (void) pprint(pp, AREASON | SHELLDIR);
330 }
331 if ((jobflags & (PINTERRUPTED | PSTOPPED)) && setintr &&
332 (!gointr || !eq(gointr, STRminus))) {
333 if ((jobflags & PSTOPPED) == 0)
334 pflush(pp);
335 pintr1(0);
336 /* NOTREACHED */
337 }
338 reason = 0;
339 fp = pp;
340 do {
341 if (fp->p_reason)
342 reason = fp->p_flags & (PSIGNALED | PINTERRUPTED) ?
343 fp->p_reason | META : fp->p_reason;
344 } while ((fp = fp->p_friends) != pp);
345 if ((reason != 0) && (adrof(STRprintexitvalue))) {
346 (void) fprintf(cshout, "Exit %d\n", reason);
347 }
348 set(STRstatus, putn(reason));
349 if (reason && exiterr)
350 exitstat();
351 pflush(pp);
352 }
353
354 /*
355 * dowait - wait for all processes to finish
356 */
357 void
358 /*ARGSUSED*/
359 dowait(v, t)
360 Char **v;
361 struct command *t;
362 {
363 struct process *pp;
364 sigset_t sigset, osigset;
365
366 pjobs++;
367 sigemptyset(&sigset);
368 sigaddset(&sigset, SIGCHLD);
369 sigprocmask(SIG_BLOCK, &sigset, &osigset);
370 loop:
371 for (pp = proclist.p_next; pp; pp = pp->p_next)
372 if (pp->p_pid && /* pp->p_pid == pp->p_jobid && */
373 pp->p_flags & PRUNNING) {
374 sigemptyset(&sigset);
375 sigsuspend(&sigset);
376 goto loop;
377 }
378 sigprocmask(SIG_SETMASK, &osigset, NULL);
379 pjobs = 0;
380 }
381
382 /*
383 * pflushall - flush all jobs from list (e.g. at fork())
384 */
385 static void
386 pflushall()
387 {
388 struct process *pp;
389
390 for (pp = proclist.p_next; pp != NULL; pp = pp->p_next)
391 if (pp->p_pid)
392 pflush(pp);
393 }
394
395 /*
396 * pflush - flag all process structures in the same job as the
397 * the argument process for deletion. The actual free of the
398 * space is not done here since pflush is called at interrupt level.
399 */
400 static void
401 pflush(pp)
402 struct process *pp;
403 {
404 struct process *np;
405 int idx;
406
407 if (pp->p_pid == 0) {
408 (void) fprintf(csherr, "BUG: process flushed twice");
409 return;
410 }
411 while (pp->p_pid != pp->p_jobid)
412 pp = pp->p_friends;
413 pclrcurr(pp);
414 if (pp == pcurrjob)
415 pcurrjob = 0;
416 idx = pp->p_index;
417 np = pp;
418 do {
419 np->p_index = np->p_pid = 0;
420 np->p_flags &= ~PNEEDNOTE;
421 } while ((np = np->p_friends) != pp);
422 if (idx == pmaxindex) {
423 for (np = proclist.p_next, idx = 0; np; np = np->p_next)
424 if (np->p_index > idx)
425 idx = np->p_index;
426 pmaxindex = idx;
427 }
428 }
429
430 /*
431 * pclrcurr - make sure the given job is not the current or previous job;
432 * pp MUST be the job leader
433 */
434 static void
435 pclrcurr(pp)
436 struct process *pp;
437 {
438
439 if (pp == pcurrent)
440 if (pprevious != NULL) {
441 pcurrent = pprevious;
442 pprevious = pgetcurr(pp);
443 }
444 else {
445 pcurrent = pgetcurr(pp);
446 pprevious = pgetcurr(pp);
447 }
448 else if (pp == pprevious)
449 pprevious = pgetcurr(pp);
450 }
451
452 /* +4 here is 1 for '\0', 1 ea for << >& >> */
453 static Char command[PMAXLEN + 4];
454 static int cmdlen;
455 static Char *cmdp;
456
457 /*
458 * palloc - allocate a process structure and fill it up.
459 * an important assumption is made that the process is running.
460 */
461 void
462 palloc(pid, t)
463 int pid;
464 struct command *t;
465 {
466 struct process *pp;
467 int i;
468
469 pp = (struct process *) xcalloc(1, (size_t) sizeof(struct process));
470 pp->p_pid = pid;
471 pp->p_flags = t->t_dflg & F_AMPERSAND ? PRUNNING : PRUNNING | PFOREGND;
472 if (t->t_dflg & F_TIME)
473 pp->p_flags |= PPTIME;
474 cmdp = command;
475 cmdlen = 0;
476 padd(t);
477 *cmdp++ = 0;
478 if (t->t_dflg & F_PIPEOUT) {
479 pp->p_flags |= PPOU;
480 if (t->t_dflg & F_STDERR)
481 pp->p_flags |= PERR;
482 }
483 pp->p_command = Strsave(command);
484 if (pcurrjob) {
485 struct process *fp;
486
487 /* careful here with interrupt level */
488 pp->p_cwd = 0;
489 pp->p_index = pcurrjob->p_index;
490 pp->p_friends = pcurrjob;
491 pp->p_jobid = pcurrjob->p_pid;
492 for (fp = pcurrjob; fp->p_friends != pcurrjob; fp = fp->p_friends)
493 continue;
494 fp->p_friends = pp;
495 }
496 else {
497 pcurrjob = pp;
498 pp->p_jobid = pid;
499 pp->p_friends = pp;
500 pp->p_cwd = dcwd;
501 dcwd->di_count++;
502 if (pmaxindex < BIGINDEX)
503 pp->p_index = ++pmaxindex;
504 else {
505 struct process *np;
506
507 for (i = 1;; i++) {
508 for (np = proclist.p_next; np; np = np->p_next)
509 if (np->p_index == i)
510 goto tryagain;
511 pp->p_index = i;
512 if (i > pmaxindex)
513 pmaxindex = i;
514 break;
515 tryagain:;
516 }
517 }
518 if (pcurrent == NULL)
519 pcurrent = pp;
520 else if (pprevious == NULL)
521 pprevious = pp;
522 }
523 pp->p_next = proclist.p_next;
524 proclist.p_next = pp;
525 (void) gettimeofday(&pp->p_btime, NULL);
526 }
527
528 static void
529 padd(t)
530 struct command *t;
531 {
532 Char **argp;
533
534 if (t == 0)
535 return;
536 switch (t->t_dtyp) {
537
538 case NODE_PAREN:
539 pads(STRLparensp);
540 padd(t->t_dspr);
541 pads(STRspRparen);
542 break;
543
544 case NODE_COMMAND:
545 for (argp = t->t_dcom; *argp; argp++) {
546 pads(*argp);
547 if (argp[1])
548 pads(STRspace);
549 }
550 break;
551
552 case NODE_OR:
553 case NODE_AND:
554 case NODE_PIPE:
555 case NODE_LIST:
556 padd(t->t_dcar);
557 switch (t->t_dtyp) {
558 case NODE_OR:
559 pads(STRspor2sp);
560 break;
561 case NODE_AND:
562 pads(STRspand2sp);
563 break;
564 case NODE_PIPE:
565 pads(STRsporsp);
566 break;
567 case NODE_LIST:
568 pads(STRsemisp);
569 break;
570 }
571 padd(t->t_dcdr);
572 return;
573 }
574 if ((t->t_dflg & F_PIPEIN) == 0 && t->t_dlef) {
575 pads((t->t_dflg & F_READ) ? STRspLarrow2sp : STRspLarrowsp);
576 pads(t->t_dlef);
577 }
578 if ((t->t_dflg & F_PIPEOUT) == 0 && t->t_drit) {
579 pads((t->t_dflg & F_APPEND) ? STRspRarrow2 : STRspRarrow);
580 if (t->t_dflg & F_STDERR)
581 pads(STRand);
582 pads(STRspace);
583 pads(t->t_drit);
584 }
585 }
586
587 static void
588 pads(cp)
589 Char *cp;
590 {
591 int i;
592
593 /*
594 * Avoid the Quoted Space alias hack! Reported by:
595 * sam (at) john-bigboote.ICS.UCI.EDU (Sam Horrocks)
596 */
597 if (cp[0] == STRQNULL[0])
598 cp++;
599
600 i = Strlen(cp);
601
602 if (cmdlen >= PMAXLEN)
603 return;
604 if (cmdlen + i >= PMAXLEN) {
605 (void) Strcpy(cmdp, STRsp3dots);
606 cmdlen = PMAXLEN;
607 cmdp += 4;
608 return;
609 }
610 (void) Strcpy(cmdp, cp);
611 cmdp += i;
612 cmdlen += i;
613 }
614
615 /*
616 * psavejob - temporarily save the current job on a one level stack
617 * so another job can be created. Used for { } in exp6
618 * and `` in globbing.
619 */
620 void
621 psavejob()
622 {
623
624 pholdjob = pcurrjob;
625 pcurrjob = NULL;
626 }
627
628 /*
629 * prestjob - opposite of psavejob. This may be missed if we are interrupted
630 * somewhere, but pendjob cleans up anyway.
631 */
632 void
633 prestjob()
634 {
635
636 pcurrjob = pholdjob;
637 pholdjob = NULL;
638 }
639
640 /*
641 * pendjob - indicate that a job (set of commands) has been completed
642 * or is about to begin.
643 */
644 void
645 pendjob()
646 {
647 struct process *pp, *tp;
648
649 if (pcurrjob && (pcurrjob->p_flags & (PFOREGND | PSTOPPED)) == 0) {
650 pp = pcurrjob;
651 while (pp->p_pid != pp->p_jobid)
652 pp = pp->p_friends;
653 (void) fprintf(cshout, "[%d]", pp->p_index);
654 tp = pp;
655 do {
656 (void) fprintf(cshout, " %d", pp->p_pid);
657 pp = pp->p_friends;
658 } while (pp != tp);
659 (void) fputc('\n', cshout);
660 }
661 pholdjob = pcurrjob = 0;
662 }
663
664 /*
665 * pprint - print a job
666 */
667 static int
668 pprint(pp, flag)
669 struct process *pp;
670 bool flag;
671 {
672 int status, reason;
673 struct process *tp;
674 int jobflags, pstatus;
675 bool hadnl = 1; /* did we just have a newline */
676 char *format;
677
678 (void) fpurge(cshout);
679
680 while (pp->p_pid != pp->p_jobid)
681 pp = pp->p_friends;
682 if (pp == pp->p_friends && (pp->p_flags & PPTIME)) {
683 pp->p_flags &= ~PPTIME;
684 pp->p_flags |= PTIME;
685 }
686 tp = pp;
687 status = reason = -1;
688 jobflags = 0;
689 do {
690 jobflags |= pp->p_flags;
691 pstatus = pp->p_flags & PALLSTATES;
692 if (tp != pp && !hadnl && !(flag & FANCY) &&
693 ((pstatus == status && pp->p_reason == reason) ||
694 !(flag & REASON))) {
695 (void) fputc(' ', cshout);
696 hadnl = 0;
697 }
698 else {
699 if (tp != pp && !hadnl) {
700 (void) fputc('\n', cshout);
701 hadnl = 1;
702 }
703 if (flag & NUMBER) {
704 if (pp == tp)
705 (void) fprintf(cshout, "[%d]%s %c ", pp->p_index,
706 pp->p_index < 10 ? " " : "",
707 pp == pcurrent ? '+' :
708 (pp == pprevious ? '-' : ' '));
709 else
710 (void) fprintf(cshout, " ");
711 hadnl = 0;
712 }
713 if (flag & FANCY) {
714 (void) fprintf(cshout, "%5d ", pp->p_pid);
715 hadnl = 0;
716 }
717 if (flag & (REASON | AREASON)) {
718 if (flag & NAME)
719 format = "%-23s";
720 else
721 format = "%s";
722 if (pstatus == status)
723 if (pp->p_reason == reason) {
724 (void) fprintf(cshout, format, "");
725 hadnl = 0;
726 goto prcomd;
727 }
728 else
729 reason = pp->p_reason;
730 else {
731 status = pstatus;
732 reason = pp->p_reason;
733 }
734 switch (status) {
735
736 case PRUNNING:
737 (void) fprintf(cshout, format, "Running ");
738 hadnl = 0;
739 break;
740
741 case PINTERRUPTED:
742 case PSTOPPED:
743 case PSIGNALED:
744 /*
745 * tell what happened to the background job
746 * From: Michael Schroeder
747 * <mlschroe (at) immd4.informatik.uni-erlangen.de>
748 */
749 if ((flag & REASON)
750 || ((flag & AREASON)
751 && reason != SIGINT
752 && (reason != SIGPIPE
753 || (pp->p_flags & PPOU) == 0))) {
754 (void) fprintf(cshout, format,
755 sys_siglist[(unsigned char)
756 pp->p_reason]);
757 hadnl = 0;
758 }
759 break;
760
761 case PNEXITED:
762 case PAEXITED:
763 if (flag & REASON) {
764 if (pp->p_reason)
765 (void) fprintf(cshout, "Exit %-18d", pp->p_reason);
766 else
767 (void) fprintf(cshout, format, "Done");
768 hadnl = 0;
769 }
770 break;
771
772 default:
773 (void) fprintf(csherr, "BUG: status=%-9o", status);
774 }
775 }
776 }
777 prcomd:
778 if (flag & NAME) {
779 (void) fprintf(cshout, "%s", vis_str(pp->p_command));
780 if (pp->p_flags & PPOU)
781 (void) fprintf(cshout, " |");
782 if (pp->p_flags & PERR)
783 (void) fputc('&', cshout);
784 hadnl = 0;
785 }
786 if (flag & (REASON | AREASON) && pp->p_flags & PDUMPED) {
787 (void) fprintf(cshout, " (core dumped)");
788 hadnl = 0;
789 }
790 if (tp == pp->p_friends) {
791 if (flag & AMPERSAND) {
792 (void) fprintf(cshout, " &");
793 hadnl = 0;
794 }
795 if (flag & JOBDIR &&
796 !eq(tp->p_cwd->di_name, dcwd->di_name)) {
797 (void) fprintf(cshout, " (wd: ");
798 dtildepr(value(STRhome), tp->p_cwd->di_name);
799 (void) fputc(')', cshout);
800 hadnl = 0;
801 }
802 }
803 if (pp->p_flags & PPTIME && !(status & (PSTOPPED | PRUNNING))) {
804 if (!hadnl)
805 (void) fprintf(cshout, "\n\t");
806 prusage(&zru, &pp->p_rusage, &pp->p_etime,
807 &pp->p_btime);
808 hadnl = 1;
809 }
810 if (tp == pp->p_friends) {
811 if (!hadnl) {
812 (void) fputc('\n', cshout);
813 hadnl = 1;
814 }
815 if (flag & SHELLDIR && !eq(tp->p_cwd->di_name, dcwd->di_name)) {
816 (void) fprintf(cshout, "(wd now: ");
817 dtildepr(value(STRhome), dcwd->di_name);
818 (void) fprintf(cshout, ")\n");
819 hadnl = 1;
820 }
821 }
822 } while ((pp = pp->p_friends) != tp);
823 if (jobflags & PTIME && (jobflags & (PSTOPPED | PRUNNING)) == 0) {
824 if (jobflags & NUMBER)
825 (void) fprintf(cshout, " ");
826 ptprint(tp);
827 hadnl = 1;
828 }
829 (void) fflush(cshout);
830 return (jobflags);
831 }
832
833 static void
834 ptprint(tp)
835 struct process *tp;
836 {
837 struct timeval tetime, diff;
838 static struct timeval ztime;
839 struct rusage ru;
840 static struct rusage zru;
841 struct process *pp = tp;
842
843 ru = zru;
844 tetime = ztime;
845 do {
846 ruadd(&ru, &pp->p_rusage);
847 timersub(&pp->p_etime, &pp->p_btime, &diff);
848 if (timercmp(&diff, &tetime, >))
849 tetime = diff;
850 } while ((pp = pp->p_friends) != tp);
851 prusage(&zru, &ru, &tetime, &ztime);
852 }
853
854 /*
855 * dojobs - print all jobs
856 */
857 void
858 /*ARGSUSED*/
859 dojobs(v, t)
860 Char **v;
861 struct command *t;
862 {
863 struct process *pp;
864 int flag = NUMBER | NAME | REASON;
865 int i;
866
867 if (chkstop)
868 chkstop = 2;
869 if (*++v) {
870 if (v[1] || !eq(*v, STRml))
871 stderror(ERR_JOBS);
872 flag |= FANCY | JOBDIR;
873 }
874 for (i = 1; i <= pmaxindex; i++)
875 for (pp = proclist.p_next; pp; pp = pp->p_next)
876 if (pp->p_index == i && pp->p_pid == pp->p_jobid) {
877 pp->p_flags &= ~PNEEDNOTE;
878 if (!(pprint(pp, flag) & (PRUNNING | PSTOPPED)))
879 pflush(pp);
880 break;
881 }
882 }
883
884 /*
885 * dofg - builtin - put the job into the foreground
886 */
887 void
888 /*ARGSUSED*/
889 dofg(v, t)
890 Char **v;
891 struct command *t;
892 {
893 struct process *pp;
894
895 okpcntl();
896 ++v;
897 do {
898 pp = pfind(*v);
899 pstart(pp, 1);
900 pjwait(pp);
901 } while (*v && *++v);
902 }
903
904 /*
905 * %... - builtin - put the job into the foreground
906 */
907 void
908 /*ARGSUSED*/
909 dofg1(v, t)
910 Char **v;
911 struct command *t;
912 {
913 struct process *pp;
914
915 okpcntl();
916 pp = pfind(v[0]);
917 pstart(pp, 1);
918 pjwait(pp);
919 }
920
921 /*
922 * dobg - builtin - put the job into the background
923 */
924 void
925 /*ARGSUSED*/
926 dobg(v, t)
927 Char **v;
928 struct command *t;
929 {
930 struct process *pp;
931
932 okpcntl();
933 ++v;
934 do {
935 pp = pfind(*v);
936 pstart(pp, 0);
937 } while (*v && *++v);
938 }
939
940 /*
941 * %... & - builtin - put the job into the background
942 */
943 void
944 /*ARGSUSED*/
945 dobg1(v, t)
946 Char **v;
947 struct command *t;
948 {
949 struct process *pp;
950
951 pp = pfind(v[0]);
952 pstart(pp, 0);
953 }
954
955 /*
956 * dostop - builtin - stop the job
957 */
958 void
959 /*ARGSUSED*/
960 dostop(v, t)
961 Char **v;
962 struct command *t;
963 {
964 pkill(++v, SIGSTOP);
965 }
966
967 /*
968 * dokill - builtin - superset of kill (1)
969 */
970 void
971 /*ARGSUSED*/
972 dokill(v, t)
973 Char **v;
974 struct command *t;
975 {
976 int signum = SIGTERM;
977 char *name;
978
979 v++;
980 if (v[0] && v[0][0] == '-') {
981 if (v[0][1] == 'l') {
982 if (v[1]) {
983 if (!Isdigit(v[1][0]))
984 stderror(ERR_NAME | ERR_BADSIG);
985
986 signum = atoi(short2str(v[1]));
987 if (signum < 0 || signum >= NSIG)
988 stderror(ERR_NAME | ERR_BADSIG);
989 else if (signum == 0)
990 (void) fputc('0', cshout); /* 0's symbolic name is '0' */
991 else
992 (void) fprintf(cshout, "%s ", sys_signame[signum]);
993 } else {
994 for (signum = 1; signum < NSIG; signum++) {
995 (void) fprintf(cshout, "%s ", sys_signame[signum]);
996 if (signum == NSIG / 2)
997 (void) fputc('\n', cshout);
998 }
999 }
1000 (void) fputc('\n', cshout);
1001 return;
1002 }
1003 if (Isdigit(v[0][1])) {
1004 signum = atoi(short2str(v[0] + 1));
1005 if (signum < 0 || signum > NSIG)
1006 stderror(ERR_NAME | ERR_BADSIG);
1007 }
1008 else {
1009 if (v[0][1] == 's' && (Isspace(v[0][2]) || v[0][2] == '\0'))
1010 v++;
1011 else
1012 (*v)++;
1013
1014 if (v[0] == NULL || v[1] == NULL) {
1015 stderror(ERR_NAME | ERR_TOOFEW);
1016 return;
1017 }
1018
1019 name = short2str(&v[0][0]);
1020 for (signum = 1; signum < NSIG; signum++)
1021 if (!strcasecmp(sys_signame[signum], name))
1022 break;
1023
1024 if (signum == NSIG) {
1025 if (v[0][0] == '0')
1026 signum = 0;
1027 else {
1028 setname(vis_str(&v[0][0]));
1029 stderror(ERR_NAME | ERR_UNKSIG);
1030 }
1031 }
1032 }
1033 v++;
1034 }
1035 pkill(v, signum);
1036 }
1037
1038 static void
1039 pkill(v, signum)
1040 Char **v;
1041 int signum;
1042 {
1043 struct process *pp, *np;
1044 int jobflags = 0;
1045 int pid, err1 = 0;
1046 sigset_t sigset;
1047 Char *cp;
1048
1049 sigemptyset(&sigset);
1050 sigaddset(&sigset, SIGCHLD);
1051 if (setintr)
1052 sigaddset(&sigset, SIGINT);
1053 sigprocmask(SIG_BLOCK, &sigset, NULL);
1054 gflag = 0, tglob(v);
1055 if (gflag) {
1056 v = globall(v);
1057 if (v == 0)
1058 stderror(ERR_NAME | ERR_NOMATCH);
1059 }
1060 else {
1061 v = gargv = saveblk(v);
1062 trim(v);
1063 }
1064
1065 while (v && (cp = *v)) {
1066 if (*cp == '%') {
1067 np = pp = pfind(cp);
1068 do
1069 jobflags |= np->p_flags;
1070 while ((np = np->p_friends) != pp);
1071 switch (signum) {
1072
1073 case SIGSTOP:
1074 case SIGTSTP:
1075 case SIGTTIN:
1076 case SIGTTOU:
1077 if ((jobflags & PRUNNING) == 0) {
1078 (void) fprintf(csherr, "%s: Already suspended\n",
1079 vis_str(cp));
1080 err1++;
1081 goto cont;
1082 }
1083 break;
1084 /*
1085 * suspend a process, kill -CONT %, then type jobs; the shell
1086 * says it is suspended, but it is running; thanks jaap..
1087 */
1088 case SIGCONT:
1089 pstart(pp, 0);
1090 goto cont;
1091 }
1092 if (kill(-pp->p_jobid, signum) < 0) {
1093 (void) fprintf(csherr, "%s: %s\n", vis_str(cp),
1094 strerror(errno));
1095 err1++;
1096 }
1097 if (signum == SIGTERM || signum == SIGHUP)
1098 (void) kill(-pp->p_jobid, SIGCONT);
1099 }
1100 else if (!(Isdigit(*cp) || *cp == '-'))
1101 stderror(ERR_NAME | ERR_JOBARGS);
1102 else {
1103 pid = atoi(short2str(cp));
1104 if (kill((pid_t) pid, signum) < 0) {
1105 (void) fprintf(csherr, "%d: %s\n", pid, strerror(errno));
1106 err1++;
1107 goto cont;
1108 }
1109 if (signum == SIGTERM || signum == SIGHUP)
1110 (void) kill((pid_t) pid, SIGCONT);
1111 }
1112 cont:
1113 v++;
1114 }
1115 if (gargv)
1116 blkfree(gargv), gargv = 0;
1117 sigprocmask(SIG_UNBLOCK, &sigset, NULL);
1118 if (err1)
1119 stderror(ERR_SILENT);
1120 }
1121
1122 /*
1123 * pstart - start the job in foreground/background
1124 */
1125 void
1126 pstart(pp, foregnd)
1127 struct process *pp;
1128 int foregnd;
1129 {
1130 struct process *np;
1131 sigset_t sigset, osigset;
1132 long jobflags = 0;
1133
1134 sigemptyset(&sigset);
1135 sigaddset(&sigset, SIGCHLD);
1136 sigprocmask(SIG_BLOCK, &sigset, &osigset);
1137 np = pp;
1138 do {
1139 jobflags |= np->p_flags;
1140 if (np->p_flags & (PRUNNING | PSTOPPED)) {
1141 np->p_flags |= PRUNNING;
1142 np->p_flags &= ~PSTOPPED;
1143 if (foregnd)
1144 np->p_flags |= PFOREGND;
1145 else
1146 np->p_flags &= ~PFOREGND;
1147 }
1148 } while ((np = np->p_friends) != pp);
1149 if (!foregnd)
1150 pclrcurr(pp);
1151 (void) pprint(pp, foregnd ? NAME | JOBDIR : NUMBER | NAME | AMPERSAND);
1152 if (foregnd)
1153 (void) tcsetpgrp(FSHTTY, pp->p_jobid);
1154 if (jobflags & PSTOPPED)
1155 (void) kill(-pp->p_jobid, SIGCONT);
1156 sigprocmask(SIG_SETMASK, &osigset, NULL);
1157 }
1158
1159 void
1160 panystop(neednl)
1161 bool neednl;
1162 {
1163 struct process *pp;
1164
1165 chkstop = 2;
1166 for (pp = proclist.p_next; pp; pp = pp->p_next)
1167 if (pp->p_flags & PSTOPPED)
1168 stderror(ERR_STOPPED, neednl ? "\n" : "");
1169 }
1170
1171 struct process *
1172 pfind(cp)
1173 Char *cp;
1174 {
1175 struct process *pp, *np;
1176
1177 if (cp == 0 || cp[1] == 0 || eq(cp, STRcent2) || eq(cp, STRcentplus)) {
1178 if (pcurrent == NULL)
1179 stderror(ERR_NAME | ERR_JOBCUR);
1180 return (pcurrent);
1181 }
1182 if (eq(cp, STRcentminus) || eq(cp, STRcenthash)) {
1183 if (pprevious == NULL)
1184 stderror(ERR_NAME | ERR_JOBPREV);
1185 return (pprevious);
1186 }
1187 if (Isdigit(cp[1])) {
1188 int idx = atoi(short2str(cp + 1));
1189
1190 for (pp = proclist.p_next; pp; pp = pp->p_next)
1191 if (pp->p_index == idx && pp->p_pid == pp->p_jobid)
1192 return (pp);
1193 stderror(ERR_NAME | ERR_NOSUCHJOB);
1194 }
1195 np = NULL;
1196 for (pp = proclist.p_next; pp; pp = pp->p_next)
1197 if (pp->p_pid == pp->p_jobid) {
1198 if (cp[1] == '?') {
1199 Char *dp;
1200
1201 for (dp = pp->p_command; *dp; dp++) {
1202 if (*dp != cp[2])
1203 continue;
1204 if (prefix(cp + 2, dp))
1205 goto match;
1206 }
1207 }
1208 else if (prefix(cp + 1, pp->p_command)) {
1209 match:
1210 if (np)
1211 stderror(ERR_NAME | ERR_AMBIG);
1212 np = pp;
1213 }
1214 }
1215 if (np)
1216 return (np);
1217 stderror(ERR_NAME | (cp[1] == '?' ? ERR_JOBPAT : ERR_NOSUCHJOB));
1218 /* NOTREACHED */
1219 return (0);
1220 }
1221
1222
1223 /*
1224 * pgetcurr - find most recent job that is not pp, preferably stopped
1225 */
1226 static struct process *
1227 pgetcurr(pp)
1228 struct process *pp;
1229 {
1230 struct process *np;
1231 struct process *xp = NULL;
1232
1233 for (np = proclist.p_next; np; np = np->p_next)
1234 if (np != pcurrent && np != pp && np->p_pid &&
1235 np->p_pid == np->p_jobid) {
1236 if (np->p_flags & PSTOPPED)
1237 return (np);
1238 if (xp == NULL)
1239 xp = np;
1240 }
1241 return (xp);
1242 }
1243
1244 /*
1245 * donotify - flag the job so as to report termination asynchronously
1246 */
1247 void
1248 /*ARGSUSED*/
1249 donotify(v, t)
1250 Char **v;
1251 struct command *t;
1252 {
1253 struct process *pp;
1254
1255 pp = pfind(*++v);
1256 pp->p_flags |= PNOTIFY;
1257 }
1258
1259 /*
1260 * Do the fork and whatever should be done in the child side that
1261 * should not be done if we are not forking at all (like for simple builtin's)
1262 * Also do everything that needs any signals fiddled with in the parent side
1263 *
1264 * Wanttty tells whether process and/or tty pgrps are to be manipulated:
1265 * -1: leave tty alone; inherit pgrp from parent
1266 * 0: already have tty; manipulate process pgrps only
1267 * 1: want to claim tty; manipulate process and tty pgrps
1268 * It is usually just the value of tpgrp.
1269 */
1270
1271 int
1272 pfork(t, wanttty)
1273 struct command *t; /* command we are forking for */
1274 int wanttty;
1275 {
1276 int pid;
1277 bool ignint = 0;
1278 int pgrp;
1279 sigset_t sigset, osigset;
1280
1281 /*
1282 * A child will be uninterruptible only under very special conditions.
1283 * Remember that the semantics of '&' is implemented by disconnecting the
1284 * process from the tty so signals do not need to ignored just for '&'.
1285 * Thus signals are set to default action for children unless: we have had
1286 * an "onintr -" (then specifically ignored) we are not playing with
1287 * signals (inherit action)
1288 */
1289 if (setintr)
1290 ignint = (tpgrp == -1 && (t->t_dflg & F_NOINTERRUPT))
1291 || (gointr && eq(gointr, STRminus));
1292 /*
1293 * Check for maximum nesting of 16 processes to avoid Forking loops
1294 */
1295 if (child == 16)
1296 stderror(ERR_NESTING, 16);
1297 /*
1298 * Hold SIGCHLD until we have the process installed in our table.
1299 */
1300 sigemptyset(&sigset);
1301 sigaddset(&sigset, SIGCHLD);
1302 sigprocmask(SIG_BLOCK, &sigset, &osigset);
1303 while ((pid = fork()) < 0)
1304 if (setintr == 0)
1305 (void) sleep(FORKSLEEP);
1306 else {
1307 sigprocmask(SIG_SETMASK, &osigset, NULL);
1308 stderror(ERR_NOPROC);
1309 }
1310 if (pid == 0) {
1311 settimes();
1312 pgrp = pcurrjob ? pcurrjob->p_jobid : getpid();
1313 pflushall();
1314 pcurrjob = NULL;
1315 child++;
1316 if (setintr) {
1317 setintr = 0; /* until I think otherwise */
1318 /*
1319 * Children just get blown away on SIGINT, SIGQUIT unless "onintr
1320 * -" seen.
1321 */
1322 (void) signal(SIGINT, ignint ? SIG_IGN : SIG_DFL);
1323 (void) signal(SIGQUIT, ignint ? SIG_IGN : SIG_DFL);
1324 if (wanttty >= 0) {
1325 /* make stoppable */
1326 (void) signal(SIGTSTP, SIG_DFL);
1327 (void) signal(SIGTTIN, SIG_DFL);
1328 (void) signal(SIGTTOU, SIG_DFL);
1329 }
1330 (void) signal(SIGTERM, parterm);
1331 }
1332 else if (tpgrp == -1 && (t->t_dflg & F_NOINTERRUPT)) {
1333 (void) signal(SIGINT, SIG_IGN);
1334 (void) signal(SIGQUIT, SIG_IGN);
1335 }
1336 pgetty(wanttty, pgrp);
1337 /*
1338 * Nohup and nice apply only to NODE_COMMAND's but it would be nice
1339 * (?!?) if you could say "nohup (foo;bar)" Then the parser would have
1340 * to know about nice/nohup/time
1341 */
1342 if (t->t_dflg & F_NOHUP)
1343 (void) signal(SIGHUP, SIG_IGN);
1344 if (t->t_dflg & F_NICE)
1345 (void) setpriority(PRIO_PROCESS, 0, t->t_nice);
1346 }
1347 else {
1348 if (wanttty >= 0)
1349 (void) setpgid(pid, pcurrjob ? pcurrjob->p_jobid : pid);
1350 palloc(pid, t);
1351 sigprocmask(SIG_SETMASK, &osigset, NULL);
1352 }
1353
1354 return (pid);
1355 }
1356
1357 static void
1358 okpcntl()
1359 {
1360 if (tpgrp == -1)
1361 stderror(ERR_JOBCONTROL);
1362 if (tpgrp == 0)
1363 stderror(ERR_JOBCTRLSUB);
1364 }
1365
1366 /*
1367 * if we don't have vfork(), things can still go in the wrong order
1368 * resulting in the famous 'Stopped (tty output)'. But some systems
1369 * don't permit the setpgid() call, (these are more recent secure
1370 * systems such as ibm's aix). Then we'd rather print an error message
1371 * than hang the shell!
1372 * I am open to suggestions how to fix that.
1373 */
1374 void
1375 pgetty(wanttty, pgrp)
1376 int wanttty, pgrp;
1377 {
1378 sigset_t sigset, osigset;
1379
1380 /*
1381 * christos: I am blocking the tty signals till I've set things
1382 * correctly....
1383 */
1384 if (wanttty > 0) {
1385 sigemptyset(&sigset);
1386 sigaddset(&sigset, SIGTSTP);
1387 sigaddset(&sigset, SIGTTIN);
1388 sigaddset(&sigset, SIGTTOU);
1389 sigprocmask(SIG_BLOCK, &sigset, &osigset);
1390 }
1391 /*
1392 * From: Michael Schroeder <mlschroe (at) immd4.informatik.uni-erlangen.de>
1393 * Don't check for tpgrp >= 0 so even non-interactive shells give
1394 * background jobs process groups Same for the comparison in the other part
1395 * of the #ifdef
1396 */
1397 if (wanttty >= 0)
1398 if (setpgid(0, pgrp) == -1) {
1399 (void) fprintf(csherr, "csh: setpgid error.\n");
1400 xexit(0);
1401 }
1402
1403 if (wanttty > 0) {
1404 (void) tcsetpgrp(FSHTTY, pgrp);
1405 sigprocmask(SIG_SETMASK, &osigset, NULL);
1406 }
1407
1408 if (tpgrp > 0)
1409 tpgrp = 0; /* gave tty away */
1410 }
1411