1 /* $OpenBSD: proc.c,v 1.36 2024/07/28 15:31:22 deraadt 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 sigaddset(&sigset, SIGHUP);
211 for (pp = proclist.p_next; pp != NULL; pp = pp->p_next) {
212 if (pp->p_flags & PNEEDNOTE) {
213 sigprocmask(SIG_BLOCK, &sigset, &osigset);
214 pp->p_flags &= ~PNEEDNOTE;
215 flags = pprint(pp, NUMBER | NAME | REASON);
216 if ((flags & (PRUNNING | PSTOPPED)) == 0)
217 pflush(pp);
218 sigprocmask(SIG_SETMASK, &osigset, NULL);
219 }
220 }
221 }
222
223 /*
224 * pwait - wait for current job to terminate, maintaining integrity
225 * of current and previous job indicators.
226 */
227 void
pwait(void)228 pwait(void)
229 {
230 struct process *fp, *pp;
231 sigset_t sigset, osigset;
232
233 /*
234 * Here's where dead procs get flushed.
235 */
236 sigemptyset(&sigset);
237 sigaddset(&sigset, SIGCHLD);
238 sigaddset(&sigset, SIGHUP);
239 sigprocmask(SIG_BLOCK, &sigset, &osigset);
240 for (pp = (fp = &proclist)->p_next; pp != NULL; pp = (fp = pp)->p_next)
241 if (pp->p_pid == 0) {
242 fp->p_next = pp->p_next;
243 free(pp->p_command);
244 if (pp->p_cwd && --pp->p_cwd->di_count == 0)
245 if (pp->p_cwd->di_next == 0)
246 dfree(pp->p_cwd);
247 free(pp);
248 pp = fp;
249 }
250 sigprocmask(SIG_SETMASK, &osigset, NULL);
251 pjwait(pcurrjob);
252 }
253
254
255 /*
256 * pjwait - wait for a job to finish or become stopped
257 * It is assumed to be in the foreground state (PFOREGND)
258 */
259 void
pjwait(struct process * pp)260 pjwait(struct process *pp)
261 {
262 struct process *fp;
263 int jobflags, reason;
264 sigset_t sigset, osigset;
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 sigemptyset(&sigset);
280 sigaddset(&sigset, SIGCHLD);
281 sigaddset(&sigset, SIGHUP);
282 sigprocmask(SIG_BLOCK, &sigset, &osigset);
283 for (;;) {
284 sigemptyset(&sigset);
285 sigaddset(&sigset, SIGCHLD);
286 sigaddset(&sigset, SIGHUP);
287 sigprocmask(SIG_BLOCK, &sigset, NULL);
288 jobflags = 0;
289 do
290 jobflags |= fp->p_flags;
291 while ((fp = (fp->p_friends)) != pp);
292 if ((jobflags & PRUNNING) == 0)
293 break;
294 sigset = osigset;
295 sigdelset(&sigset, SIGCHLD);
296 sigdelset(&sigset, SIGHUP);
297 sigsuspend(&sigset);
298 }
299 sigprocmask(SIG_SETMASK, &osigset, NULL);
300 if (tpgrp > 0) /* get tty back */
301 (void) tcsetpgrp(FSHTTY, tpgrp);
302 if ((jobflags & (PSIGNALED | PSTOPPED | PTIME)) ||
303 !eq(dcwd->di_name, fp->p_cwd->di_name)) {
304 if (jobflags & PSTOPPED) {
305 (void) fputc('\n', cshout);
306 if (adrof(STRlistjobs)) {
307 Char *jobcommand[3];
308
309 jobcommand[0] = STRjobs;
310 if (eq(value(STRlistjobs), STRlong))
311 jobcommand[1] = STRml;
312 else
313 jobcommand[1] = NULL;
314 jobcommand[2] = NULL;
315
316 dojobs(jobcommand, NULL);
317 (void) pprint(pp, SHELLDIR);
318 }
319 else
320 (void) pprint(pp, AREASON | SHELLDIR);
321 }
322 else
323 (void) pprint(pp, AREASON | SHELLDIR);
324 }
325 if ((jobflags & (PINTERRUPTED | PSTOPPED)) && setintr &&
326 (!gointr || !eq(gointr, STRminus))) {
327 if ((jobflags & PSTOPPED) == 0)
328 pflush(pp);
329 pintr1(0);
330 /* NOTREACHED */
331 }
332 reason = 0;
333 fp = pp;
334 do {
335 if (fp->p_reason)
336 reason = fp->p_flags & (PSIGNALED | PINTERRUPTED) ?
337 fp->p_reason | META : fp->p_reason;
338 } while ((fp = fp->p_friends) != pp);
339 if ((reason != 0) && (adrof(STRprintexitvalue))) {
340 (void) fprintf(cshout, "Exit %d\n", reason);
341 }
342 set(STRstatus, putn(reason));
343 if (reason && exiterr)
344 exitstat();
345 pflush(pp);
346 }
347
348 /*
349 * dowait - wait for all processes to finish
350 */
351 void
dowait(Char ** v,struct command * t)352 dowait(Char **v, struct command *t)
353 {
354 struct process *pp;
355 sigset_t sigset, osigset;
356
357 pjobs++;
358 sigemptyset(&sigset);
359 sigaddset(&sigset, SIGCHLD);
360 sigaddset(&sigset, SIGHUP);
361 sigprocmask(SIG_BLOCK, &sigset, &osigset);
362 loop:
363 for (pp = proclist.p_next; pp; pp = pp->p_next)
364 if (pp->p_pid && /* pp->p_pid == pp->p_jobid && */
365 pp->p_flags & PRUNNING) {
366 sigemptyset(&sigset);
367 sigsuspend(&sigset);
368 goto loop;
369 }
370 sigprocmask(SIG_SETMASK, &osigset, NULL);
371 pjobs = 0;
372 }
373
374 /*
375 * pflushall - flush all jobs from list (e.g. at fork())
376 */
377 static void
pflushall(void)378 pflushall(void)
379 {
380 struct process *pp;
381
382 for (pp = proclist.p_next; pp != NULL; pp = pp->p_next)
383 if (pp->p_pid)
384 pflush(pp);
385 }
386
387 /*
388 * pflush - flag all process structures in the same job as the
389 * the argument process for deletion. The actual free of the
390 * space is not done here since pflush is called at interrupt level.
391 */
392 static void
pflush(struct process * pp)393 pflush(struct process *pp)
394 {
395 struct process *np;
396 int idx;
397
398 if (pp->p_pid == 0) {
399 (void) fprintf(csherr, "BUG: process flushed twice");
400 return;
401 }
402 while (pp->p_pid != pp->p_jobid)
403 pp = pp->p_friends;
404 pclrcurr(pp);
405 if (pp == pcurrjob)
406 pcurrjob = 0;
407 idx = pp->p_index;
408 np = pp;
409 do {
410 np->p_index = np->p_pid = 0;
411 np->p_flags &= ~PNEEDNOTE;
412 } while ((np = np->p_friends) != pp);
413 if (idx == pmaxindex) {
414 for (np = proclist.p_next, idx = 0; np; np = np->p_next)
415 if (np->p_index > idx)
416 idx = np->p_index;
417 pmaxindex = idx;
418 }
419 }
420
421 /*
422 * pclrcurr - make sure the given job is not the current or previous job;
423 * pp MUST be the job leader
424 */
425 static void
pclrcurr(struct process * pp)426 pclrcurr(struct process *pp)
427 {
428
429 if (pp == pcurrent)
430 if (pprevious != NULL) {
431 pcurrent = pprevious;
432 pprevious = pgetcurr(pp);
433 }
434 else {
435 pcurrent = pgetcurr(pp);
436 pprevious = pgetcurr(pp);
437 }
438 else if (pp == pprevious)
439 pprevious = pgetcurr(pp);
440 }
441
442 /* +4 here is 1 for '\0', 1 ea for << >& >> */
443 static Char command[PMAXLEN + 4];
444 static int cmdlen;
445 static Char *cmdp;
446
447 /*
448 * palloc - allocate a process structure and fill it up.
449 * an important assumption is made that the process is running.
450 */
451 void
palloc(int pid,struct command * t)452 palloc(int pid, struct command *t)
453 {
454 struct process *pp;
455 int i;
456
457 pp = xcalloc(1, (size_t) sizeof(struct process));
458 pp->p_pid = pid;
459 pp->p_flags = t->t_dflg & F_AMPERSAND ? PRUNNING : PRUNNING | PFOREGND;
460 if (t->t_dflg & F_TIME)
461 pp->p_flags |= PPTIME;
462 cmdp = command;
463 cmdlen = 0;
464 padd(t);
465 *cmdp++ = 0;
466 if (t->t_dflg & F_PIPEOUT) {
467 pp->p_flags |= PPOU;
468 if (t->t_dflg & F_STDERR)
469 pp->p_flags |= PERR;
470 }
471 pp->p_command = Strsave(command);
472 if (pcurrjob) {
473 struct process *fp;
474
475 /* careful here with interrupt level */
476 pp->p_cwd = 0;
477 pp->p_index = pcurrjob->p_index;
478 pp->p_friends = pcurrjob;
479 pp->p_jobid = pcurrjob->p_pid;
480 for (fp = pcurrjob; fp->p_friends != pcurrjob; fp = fp->p_friends)
481 continue;
482 fp->p_friends = pp;
483 }
484 else {
485 pcurrjob = pp;
486 pp->p_jobid = pid;
487 pp->p_friends = pp;
488 pp->p_cwd = dcwd;
489 dcwd->di_count++;
490 if (pmaxindex < BIGINDEX)
491 pp->p_index = ++pmaxindex;
492 else {
493 struct process *np;
494
495 for (i = 1;; i++) {
496 for (np = proclist.p_next; np; np = np->p_next)
497 if (np->p_index == i)
498 goto tryagain;
499 pp->p_index = i;
500 if (i > pmaxindex)
501 pmaxindex = i;
502 break;
503 tryagain:;
504 }
505 }
506 if (pcurrent == NULL)
507 pcurrent = pp;
508 else if (pprevious == NULL)
509 pprevious = pp;
510 }
511 pp->p_next = proclist.p_next;
512 proclist.p_next = pp;
513 (void) clock_gettime(CLOCK_MONOTONIC, &pp->p_btime);
514 }
515
516 static void
padd(struct command * t)517 padd(struct command *t)
518 {
519 Char **argp;
520
521 if (t == 0)
522 return;
523 switch (t->t_dtyp) {
524
525 case NODE_PAREN:
526 pads(STRLparensp);
527 padd(t->t_dspr);
528 pads(STRspRparen);
529 break;
530
531 case NODE_COMMAND:
532 for (argp = t->t_dcom; *argp; argp++) {
533 pads(*argp);
534 if (argp[1])
535 pads(STRspace);
536 }
537 break;
538
539 case NODE_OR:
540 case NODE_AND:
541 case NODE_PIPE:
542 case NODE_LIST:
543 padd(t->t_dcar);
544 switch (t->t_dtyp) {
545 case NODE_OR:
546 pads(STRspor2sp);
547 break;
548 case NODE_AND:
549 pads(STRspand2sp);
550 break;
551 case NODE_PIPE:
552 pads(STRsporsp);
553 break;
554 case NODE_LIST:
555 pads(STRsemisp);
556 break;
557 }
558 padd(t->t_dcdr);
559 return;
560 }
561 if ((t->t_dflg & F_PIPEIN) == 0 && t->t_dlef) {
562 pads((t->t_dflg & F_READ) ? STRspLarrow2sp : STRspLarrowsp);
563 pads(t->t_dlef);
564 }
565 if ((t->t_dflg & F_PIPEOUT) == 0 && t->t_drit) {
566 pads((t->t_dflg & F_APPEND) ? STRspRarrow2 : STRspRarrow);
567 if (t->t_dflg & F_STDERR)
568 pads(STRand);
569 pads(STRspace);
570 pads(t->t_drit);
571 }
572 }
573
574 static void
pads(Char * cp)575 pads(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) Strlcpy(cmdp, STRsp3dots, PMAXLEN - cmdlen);
592 cmdlen = PMAXLEN;
593 cmdp += 4;
594 return;
595 }
596 (void) Strlcpy(cmdp, cp, PMAXLEN - cmdlen);
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(void)607 psavejob(void)
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(void)619 prestjob(void)
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(void)631 pendjob(void)
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(struct process * pp,bool flag)654 pprint(struct process *pp, bool flag)
655 {
656 int status, reason;
657 struct process *tp;
658 int jobflags, pstatus;
659 bool hadnl = 1; /* did we just have a newline */
660
661 (void) fpurge(cshout);
662
663 while (pp->p_pid != pp->p_jobid)
664 pp = pp->p_friends;
665 if (pp == pp->p_friends && (pp->p_flags & PPTIME)) {
666 pp->p_flags &= ~PPTIME;
667 pp->p_flags |= PTIME;
668 }
669 tp = pp;
670 status = reason = -1;
671 jobflags = 0;
672 do {
673 jobflags |= pp->p_flags;
674 pstatus = pp->p_flags & PALLSTATES;
675 if (tp != pp && !hadnl && !(flag & FANCY) &&
676 ((pstatus == status && pp->p_reason == reason) ||
677 !(flag & REASON))) {
678 (void) fputc(' ', cshout);
679 hadnl = 0;
680 }
681 else {
682 if (tp != pp && !hadnl) {
683 (void) fputc('\n', cshout);
684 hadnl = 1;
685 }
686 if (flag & NUMBER) {
687 if (pp == tp)
688 (void) fprintf(cshout, "[%d]%s %c ", pp->p_index,
689 pp->p_index < 10 ? " " : "",
690 pp == pcurrent ? '+' :
691 (pp == pprevious ? '-' : ' '));
692 else
693 (void) fprintf(cshout, " ");
694 hadnl = 0;
695 }
696 if (flag & FANCY) {
697 (void) fprintf(cshout, "%5d ", pp->p_pid);
698 hadnl = 0;
699 }
700 if (flag & (REASON | AREASON)) {
701 int width = 0;
702 if (flag & NAME)
703 width = -23;
704 if (pstatus == status)
705 if (pp->p_reason == reason) {
706 (void) fprintf(cshout, "%*s", width, "");
707 hadnl = 0;
708 goto prcomd;
709 }
710 else
711 reason = pp->p_reason;
712 else {
713 status = pstatus;
714 reason = pp->p_reason;
715 }
716 switch (status) {
717
718 case PRUNNING:
719 (void) fprintf(cshout, "%*s", width, "Running ");
720 hadnl = 0;
721 break;
722
723 case PINTERRUPTED:
724 case PSTOPPED:
725 case PSIGNALED:
726 /*
727 * tell what happened to the background job
728 * From: Michael Schroeder
729 * <mlschroe@immd4.informatik.uni-erlangen.de>
730 */
731 if ((flag & REASON)
732 || ((flag & AREASON)
733 && reason != SIGINT
734 && (reason != SIGPIPE
735 || (pp->p_flags & PPOU) == 0))) {
736 (void) fprintf(cshout, "%*s", width,
737 sys_siglist[(unsigned char)
738 pp->p_reason]);
739 hadnl = 0;
740 }
741 break;
742
743 case PNEXITED:
744 case PAEXITED:
745 if (flag & REASON) {
746 if (pp->p_reason)
747 (void) fprintf(cshout, "Exit %-18d", pp->p_reason);
748 else
749 (void) fprintf(cshout, "%*s", width, "Done");
750 hadnl = 0;
751 }
752 break;
753
754 default:
755 (void) fprintf(csherr, "BUG: status=%-9o", status);
756 }
757 }
758 }
759 prcomd:
760 if (flag & NAME) {
761 (void) fprintf(cshout, "%s", vis_str(pp->p_command));
762 if (pp->p_flags & PPOU)
763 (void) fprintf(cshout, " |");
764 if (pp->p_flags & PERR)
765 (void) fputc('&', cshout);
766 hadnl = 0;
767 }
768 if (flag & (REASON | AREASON) && pp->p_flags & PDUMPED) {
769 (void) fprintf(cshout, " (core dumped)");
770 hadnl = 0;
771 }
772 if (tp == pp->p_friends) {
773 if (flag & AMPERSAND) {
774 (void) fprintf(cshout, " &");
775 hadnl = 0;
776 }
777 if (flag & JOBDIR &&
778 !eq(tp->p_cwd->di_name, dcwd->di_name)) {
779 (void) fprintf(cshout, " (wd: ");
780 dtildepr(value(STRhome), tp->p_cwd->di_name);
781 (void) fputc(')', cshout);
782 hadnl = 0;
783 }
784 }
785 if (pp->p_flags & PPTIME && !(status & (PSTOPPED | PRUNNING))) {
786 if (!hadnl)
787 (void) fprintf(cshout, "\n\t");
788 prusage(&zru, &pp->p_rusage, &pp->p_etime,
789 &pp->p_btime);
790 hadnl = 1;
791 }
792 if (tp == pp->p_friends) {
793 if (!hadnl) {
794 (void) fputc('\n', cshout);
795 hadnl = 1;
796 }
797 if (flag & SHELLDIR && !eq(tp->p_cwd->di_name, dcwd->di_name)) {
798 (void) fprintf(cshout, "(wd now: ");
799 dtildepr(value(STRhome), dcwd->di_name);
800 (void) fprintf(cshout, ")\n");
801 hadnl = 1;
802 }
803 }
804 } while ((pp = pp->p_friends) != tp);
805 if (jobflags & PTIME && (jobflags & (PSTOPPED | PRUNNING)) == 0) {
806 if (jobflags & NUMBER)
807 (void) fprintf(cshout, " ");
808 ptprint(tp);
809 hadnl = 1;
810 }
811 (void) fflush(cshout);
812 return (jobflags);
813 }
814
815 static void
ptprint(struct process * tp)816 ptprint(struct process *tp)
817 {
818 struct timespec tetime, diff;
819 static struct timespec ztime;
820 struct rusage ru;
821 static struct rusage zru;
822 struct process *pp = tp;
823
824 ru = zru;
825 tetime = ztime;
826 do {
827 ruadd(&ru, &pp->p_rusage);
828 timespecsub(&pp->p_etime, &pp->p_btime, &diff);
829 if (timespeccmp(&diff, &tetime, >))
830 tetime = diff;
831 } while ((pp = pp->p_friends) != tp);
832 prusage(&zru, &ru, &tetime, &ztime);
833 }
834
835 /*
836 * dojobs - print all jobs
837 */
838 void
dojobs(Char ** v,struct command * t)839 dojobs(Char **v, struct command *t)
840 {
841 struct process *pp;
842 int flag = NUMBER | NAME | REASON;
843 int i;
844
845 if (chkstop)
846 chkstop = 2;
847 if (*++v) {
848 if (v[1] || !eq(*v, STRml))
849 stderror(ERR_JOBS);
850 flag |= FANCY | JOBDIR;
851 }
852 for (i = 1; i <= pmaxindex; i++)
853 for (pp = proclist.p_next; pp; pp = pp->p_next)
854 if (pp->p_index == i && pp->p_pid == pp->p_jobid) {
855 pp->p_flags &= ~PNEEDNOTE;
856 if (!(pprint(pp, flag) & (PRUNNING | PSTOPPED)))
857 pflush(pp);
858 break;
859 }
860 }
861
862 /*
863 * dofg - builtin - put the job into the foreground
864 */
865 void
dofg(Char ** v,struct command * t)866 dofg(Char **v, struct command *t)
867 {
868 struct process *pp;
869
870 okpcntl();
871 ++v;
872 do {
873 pp = pfind(*v);
874 pstart(pp, 1);
875 pjwait(pp);
876 } while (*v && *++v);
877 }
878
879 /*
880 * %... - builtin - put the job into the foreground
881 */
882 void
dofg1(Char ** v,struct command * t)883 dofg1(Char **v, struct command *t)
884 {
885 struct process *pp;
886
887 okpcntl();
888 pp = pfind(v[0]);
889 pstart(pp, 1);
890 pjwait(pp);
891 }
892
893 /*
894 * dobg - builtin - put the job into the background
895 */
896 void
dobg(Char ** v,struct command * t)897 dobg(Char **v, struct command *t)
898 {
899 struct process *pp;
900
901 okpcntl();
902 ++v;
903 do {
904 pp = pfind(*v);
905 pstart(pp, 0);
906 } while (*v && *++v);
907 }
908
909 /*
910 * %... & - builtin - put the job into the background
911 */
912 void
dobg1(Char ** v,struct command * t)913 dobg1(Char **v, struct command *t)
914 {
915 struct process *pp;
916
917 pp = pfind(v[0]);
918 pstart(pp, 0);
919 }
920
921 /*
922 * dostop - builtin - stop the job
923 */
924 void
dostop(Char ** v,struct command * t)925 dostop(Char **v, struct command *t)
926 {
927 pkill(++v, SIGSTOP);
928 }
929
930 /*
931 * dokill - builtin - superset of kill (1)
932 */
933 void
dokill(Char ** v,struct command * t)934 dokill(Char **v, struct command *t)
935 {
936 int signum = SIGTERM;
937 const char *errstr;
938 char *name;
939
940 v++;
941 if (v[0] && v[0][0] == '-') {
942 if (v[0][1] == 'l') {
943 if (v[1]) {
944 if (!Isdigit(v[1][0]))
945 stderror(ERR_NAME | ERR_BADSIG);
946
947 signum = strtonum(short2str(v[1]), 0, NSIG-1, &errstr);
948 if (errstr)
949 stderror(ERR_NAME | ERR_BADSIG);
950 else if (signum == 0)
951 (void) fputc('0', cshout); /* 0's symbolic name is '0' */
952 else
953 (void) fprintf(cshout, "%s ", sys_signame[signum]);
954 } else {
955 for (signum = 1; signum < NSIG; signum++) {
956 (void) fprintf(cshout, "%s ", sys_signame[signum]);
957 if (signum == NSIG / 2)
958 (void) fputc('\n', cshout);
959 }
960 }
961 (void) fputc('\n', cshout);
962 return;
963 }
964 if (Isdigit(v[0][1])) {
965 signum = strtonum(short2str(v[0] + 1), 0, NSIG-1, &errstr);
966 if (errstr)
967 stderror(ERR_NAME | ERR_BADSIG);
968 }
969 else {
970 if (v[0][1] == 's' && (Isspace(v[0][2]) || v[0][2] == '\0')) {
971 v++;
972 name = short2str(&v[0][0]);
973 } else {
974 name = short2str(&v[0][1]);
975 }
976
977 if (v[0] == NULL || v[1] == NULL) {
978 stderror(ERR_NAME | ERR_TOOFEW);
979 return;
980 }
981
982 for (signum = 1; signum < NSIG; signum++)
983 if (!strcasecmp(sys_signame[signum], name) ||
984 (strlen(name) > 3 && !strncasecmp("SIG", name, 3) &&
985 !strcasecmp(sys_signame[signum], name + 3)))
986 break;
987
988 if (signum == NSIG) {
989 if (name[0] == '0')
990 signum = 0;
991 else {
992 setname(vis_str(&v[0][0]));
993 stderror(ERR_NAME | ERR_UNKSIG);
994 }
995 }
996 }
997 v++;
998 }
999 pkill(v, signum);
1000 }
1001
1002 static void
pkill(Char ** v,int signum)1003 pkill(Char **v, int signum)
1004 {
1005 struct process *pp, *np;
1006 int jobflags = 0;
1007 int pid, err1 = 0;
1008 sigset_t sigset;
1009 Char *cp;
1010
1011 sigemptyset(&sigset);
1012 sigaddset(&sigset, SIGCHLD);
1013 sigaddset(&sigset, SIGHUP);
1014 if (setintr)
1015 sigaddset(&sigset, SIGINT);
1016 sigprocmask(SIG_BLOCK, &sigset, NULL);
1017 gflag = 0, tglob(v);
1018 if (gflag) {
1019 v = globall(v);
1020 if (v == 0)
1021 stderror(ERR_NAME | ERR_NOMATCH);
1022 }
1023 else {
1024 v = gargv = saveblk(v);
1025 trim(v);
1026 }
1027
1028 while (v && (cp = *v)) {
1029 if (*cp == '%') {
1030 np = pp = pfind(cp);
1031 do
1032 jobflags |= np->p_flags;
1033 while ((np = np->p_friends) != pp);
1034 switch (signum) {
1035
1036 case SIGSTOP:
1037 case SIGTSTP:
1038 case SIGTTIN:
1039 case SIGTTOU:
1040 if ((jobflags & PRUNNING) == 0) {
1041 (void) fprintf(csherr, "%s: Already suspended\n",
1042 vis_str(cp));
1043 err1++;
1044 goto cont;
1045 }
1046 break;
1047 /*
1048 * suspend a process, kill -CONT %, then type jobs; the shell
1049 * says it is suspended, but it is running; thanks jaap..
1050 */
1051 case SIGCONT:
1052 pstart(pp, 0);
1053 goto cont;
1054 }
1055 if (kill(-pp->p_jobid, signum) == -1) {
1056 (void) fprintf(csherr, "%s: %s\n", vis_str(cp),
1057 strerror(errno));
1058 err1++;
1059 }
1060 if (signum == SIGTERM || signum == SIGHUP)
1061 (void) kill(-pp->p_jobid, SIGCONT);
1062 }
1063 else if (!(Isdigit(*cp) || *cp == '-'))
1064 stderror(ERR_NAME | ERR_JOBARGS);
1065 else {
1066 char *ep;
1067 char *pidnam = short2str(cp);
1068
1069 pid = strtol(pidnam, &ep, 10);
1070 if (!*pidnam || *ep) {
1071 (void) fprintf(csherr, "%s: illegal process id\n", pidnam);
1072 err1++;
1073 goto cont;
1074 }
1075 if (kill((pid_t) pid, signum) == -1) {
1076 (void) fprintf(csherr, "%d: %s\n", pid, strerror(errno));
1077 err1++;
1078 goto cont;
1079 }
1080 if (signum == SIGTERM || signum == SIGHUP)
1081 (void) kill((pid_t) pid, SIGCONT);
1082 }
1083 cont:
1084 v++;
1085 }
1086 blkfree(gargv);
1087 gargv = NULL;
1088 sigprocmask(SIG_UNBLOCK, &sigset, NULL);
1089 if (err1)
1090 stderror(ERR_SILENT);
1091 }
1092
1093 /*
1094 * pstart - start the job in foreground/background
1095 */
1096 void
pstart(struct process * pp,int foregnd)1097 pstart(struct process *pp, int foregnd)
1098 {
1099 struct process *np;
1100 sigset_t sigset, osigset;
1101 long jobflags = 0;
1102
1103 sigemptyset(&sigset);
1104 sigaddset(&sigset, SIGCHLD);
1105 sigaddset(&sigset, SIGHUP);
1106 sigprocmask(SIG_BLOCK, &sigset, &osigset);
1107 np = pp;
1108 do {
1109 jobflags |= np->p_flags;
1110 if (np->p_flags & (PRUNNING | PSTOPPED)) {
1111 np->p_flags |= PRUNNING;
1112 np->p_flags &= ~PSTOPPED;
1113 if (foregnd)
1114 np->p_flags |= PFOREGND;
1115 else
1116 np->p_flags &= ~PFOREGND;
1117 }
1118 } while ((np = np->p_friends) != pp);
1119 if (!foregnd)
1120 pclrcurr(pp);
1121 (void) pprint(pp, foregnd ? NAME | JOBDIR : NUMBER | NAME | AMPERSAND);
1122 if (foregnd)
1123 (void) tcsetpgrp(FSHTTY, pp->p_jobid);
1124 if (jobflags & PSTOPPED)
1125 (void) kill(-pp->p_jobid, SIGCONT);
1126 sigprocmask(SIG_SETMASK, &osigset, NULL);
1127 }
1128
1129 void
panystop(bool neednl)1130 panystop(bool neednl)
1131 {
1132 struct process *pp;
1133
1134 chkstop = 2;
1135 for (pp = proclist.p_next; pp; pp = pp->p_next)
1136 if (pp->p_flags & PSTOPPED)
1137 stderror(ERR_STOPPED, neednl ? "\n" : "");
1138 }
1139
1140 struct process *
pfind(Char * cp)1141 pfind(Char *cp)
1142 {
1143 struct process *pp, *np;
1144
1145 if (cp == 0 || cp[1] == 0 || eq(cp, STRcent2) || eq(cp, STRcentplus)) {
1146 if (pcurrent == NULL)
1147 stderror(ERR_NAME | ERR_JOBCUR);
1148 return (pcurrent);
1149 }
1150 if (eq(cp, STRcentminus) || eq(cp, STRcenthash)) {
1151 if (pprevious == NULL)
1152 stderror(ERR_NAME | ERR_JOBPREV);
1153 return (pprevious);
1154 }
1155 if (Isdigit(cp[1])) {
1156 const char *errstr;
1157 int idx = strtonum(short2str(cp + 1), 1, INT_MAX, &errstr);
1158
1159 if (errstr) {
1160 stderror(ERR_NAME | ERR_NOSUCHJOB);
1161 return (0);
1162 }
1163 for (pp = proclist.p_next; pp; pp = pp->p_next)
1164 if (pp->p_index == idx && pp->p_pid == pp->p_jobid)
1165 return (pp);
1166 stderror(ERR_NAME | ERR_NOSUCHJOB);
1167 return (0);
1168 }
1169 np = NULL;
1170 for (pp = proclist.p_next; pp; pp = pp->p_next)
1171 if (pp->p_pid == pp->p_jobid) {
1172 if (cp[1] == '?') {
1173 Char *dp;
1174
1175 for (dp = pp->p_command; *dp; dp++) {
1176 if (*dp != cp[2])
1177 continue;
1178 if (prefix(cp + 2, dp))
1179 goto match;
1180 }
1181 }
1182 else if (prefix(cp + 1, pp->p_command)) {
1183 match:
1184 if (np)
1185 stderror(ERR_NAME | ERR_AMBIG);
1186 np = pp;
1187 }
1188 }
1189 if (np)
1190 return (np);
1191 stderror(ERR_NAME | (cp[1] == '?' ? ERR_JOBPAT : ERR_NOSUCHJOB));
1192 /* NOTREACHED */
1193 return (0);
1194 }
1195
1196
1197 /*
1198 * pgetcurr - find most recent job that is not pp, preferably stopped
1199 */
1200 static struct process *
pgetcurr(struct process * pp)1201 pgetcurr(struct process *pp)
1202 {
1203 struct process *np;
1204 struct process *xp = NULL;
1205
1206 for (np = proclist.p_next; np; np = np->p_next)
1207 if (np != pcurrent && np != pp && np->p_pid &&
1208 np->p_pid == np->p_jobid) {
1209 if (np->p_flags & PSTOPPED)
1210 return (np);
1211 if (xp == NULL)
1212 xp = np;
1213 }
1214 return (xp);
1215 }
1216
1217 /*
1218 * donotify - flag the job so as to report termination asynchronously
1219 */
1220 void
donotify(Char ** v,struct command * t)1221 donotify(Char **v, struct command *t)
1222 {
1223 struct process *pp;
1224
1225 pp = pfind(*++v);
1226 pp->p_flags |= PNOTIFY;
1227 }
1228
1229 /*
1230 * Do the fork and whatever should be done in the child side that
1231 * should not be done if we are not forking at all (like for simple builtin's)
1232 * Also do everything that needs any signals fiddled with in the parent side
1233 *
1234 * Wanttty tells whether process and/or tty pgrps are to be manipulated:
1235 * -1: leave tty alone; inherit pgrp from parent
1236 * 0: already have tty; manipulate process pgrps only
1237 * 1: want to claim tty; manipulate process and tty pgrps
1238 * It is usually just the value of tpgrp.
1239 */
1240
1241 int
pfork(struct command * t,int wanttty)1242 pfork(struct command *t, int wanttty)
1243 {
1244 int pid;
1245 bool ignint = 0;
1246 int pgrp;
1247 sigset_t sigset, osigset;
1248
1249 /*
1250 * A child will be uninterruptible only under very special conditions.
1251 * Remember that the semantics of '&' is implemented by disconnecting the
1252 * process from the tty so signals do not need to ignored just for '&'.
1253 * Thus signals are set to default action for children unless: we have had
1254 * an "onintr -" (then specifically ignored) we are not playing with
1255 * signals (inherit action)
1256 */
1257 if (setintr)
1258 ignint = (tpgrp == -1 && (t->t_dflg & F_NOINTERRUPT))
1259 || (gointr && eq(gointr, STRminus));
1260 /*
1261 * Check for maximum nesting of 16 processes to avoid Forking loops
1262 */
1263 if (child == 16)
1264 stderror(ERR_NESTING, 16);
1265 /*
1266 * Hold SIGCHLD/SIGHUP until we have the process installed in our table.
1267 */
1268 sigemptyset(&sigset);
1269 sigaddset(&sigset, SIGCHLD);
1270 sigaddset(&sigset, SIGHUP);
1271 sigprocmask(SIG_BLOCK, &sigset, &osigset);
1272 while ((pid = fork()) == -1)
1273 if (setintr == 0)
1274 (void) sleep(FORKSLEEP);
1275 else {
1276 sigprocmask(SIG_SETMASK, &osigset, NULL);
1277 stderror(ERR_NOPROC);
1278 }
1279 if (pid == 0) {
1280 settimes();
1281 pgrp = pcurrjob ? pcurrjob->p_jobid : getpid();
1282 pflushall();
1283 pcurrjob = NULL;
1284 child++;
1285 if (setintr) {
1286 setintr = 0; /* until I think otherwise */
1287 /*
1288 * Children just get blown away on SIGINT, SIGQUIT unless "onintr
1289 * -" seen.
1290 */
1291 (void) signal(SIGINT, ignint ? SIG_IGN : SIG_DFL);
1292 (void) signal(SIGQUIT, ignint ? SIG_IGN : SIG_DFL);
1293 if (wanttty >= 0) {
1294 /* make stoppable */
1295 (void) signal(SIGTSTP, SIG_DFL);
1296 (void) signal(SIGTTIN, SIG_DFL);
1297 (void) signal(SIGTTOU, SIG_DFL);
1298 }
1299 (void) signal(SIGTERM, parterm);
1300 }
1301 else if (tpgrp == -1 && (t->t_dflg & F_NOINTERRUPT)) {
1302 (void) signal(SIGINT, SIG_IGN);
1303 (void) signal(SIGQUIT, SIG_IGN);
1304 }
1305 pgetty(wanttty, pgrp);
1306 /*
1307 * Nohup and nice apply only to NODE_COMMAND's but it would be nice
1308 * (?!?) if you could say "nohup (foo;bar)" Then the parser would have
1309 * to know about nice/nohup/time
1310 */
1311 if (t->t_dflg & F_NOHUP)
1312 (void) signal(SIGHUP, SIG_IGN);
1313 if (t->t_dflg & F_NICE)
1314 (void) setpriority(PRIO_PROCESS, 0, t->t_nice);
1315 }
1316 else {
1317 if (wanttty >= 0)
1318 (void) setpgid(pid, pcurrjob ? pcurrjob->p_jobid : pid);
1319 palloc(pid, t);
1320 sigprocmask(SIG_SETMASK, &osigset, NULL);
1321 }
1322
1323 return (pid);
1324 }
1325
1326 static void
okpcntl(void)1327 okpcntl(void)
1328 {
1329 if (tpgrp == -1)
1330 stderror(ERR_JOBCONTROL);
1331 if (tpgrp == 0)
1332 stderror(ERR_JOBCTRLSUB);
1333 }
1334
1335 /*
1336 * if we don't have vfork(), things can still go in the wrong order
1337 * resulting in the famous 'Stopped (tty output)'. But some systems
1338 * don't permit the setpgid() call, (these are more recent secure
1339 * systems such as ibm's aix). Then we'd rather print an error message
1340 * than hang the shell!
1341 * I am open to suggestions how to fix that.
1342 */
1343 void
pgetty(int wanttty,int pgrp)1344 pgetty(int wanttty, int pgrp)
1345 {
1346 sigset_t sigset, osigset;
1347
1348 /*
1349 * christos: I am blocking the tty signals till I've set things
1350 * correctly....
1351 */
1352 if (wanttty > 0) {
1353 sigemptyset(&sigset);
1354 sigaddset(&sigset, SIGTSTP);
1355 sigaddset(&sigset, SIGTTIN);
1356 sigaddset(&sigset, SIGTTOU);
1357 sigprocmask(SIG_BLOCK, &sigset, &osigset);
1358 }
1359 /*
1360 * From: Michael Schroeder <mlschroe@immd4.informatik.uni-erlangen.de>
1361 * Don't check for tpgrp >= 0 so even non-interactive shells give
1362 * background jobs process groups Same for the comparison in the other part
1363 * of the #ifdef
1364 */
1365 if (wanttty >= 0)
1366 if (setpgid(0, pgrp) == -1) {
1367 (void) fprintf(csherr, "csh: setpgid error.\n");
1368 xexit(0);
1369 }
1370
1371 if (wanttty > 0) {
1372 (void) tcsetpgrp(FSHTTY, pgrp);
1373 sigprocmask(SIG_SETMASK, &osigset, NULL);
1374 }
1375
1376 if (tpgrp > 0)
1377 tpgrp = 0; /* gave tty away */
1378 }
1379