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