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