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