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