Bug Summary

File:src/bin/csh/proc.c
Warning:line 803, column 2
Value stored to 'hadnl' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name proc.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/bin/csh/obj -resource-dir /usr/local/llvm16/lib/clang/16 -I /usr/src/bin/csh -I . -internal-isystem /usr/local/llvm16/lib/clang/16/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/bin/csh/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fno-jump-tables -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/scan/2024-01-11-140451-98009-1 -x c /usr/src/bin/csh/proc.c
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(*__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 BIGINDEX9 9 /* largest desirable job index */
48
49struct process proclist; /* list head of all processes */
50bool pnoprocesses; /* pchild found nothing to wait for */
51
52struct process *pholdjob; /* one level stack of current jobs */
53
54struct process *pcurrjob; /* current job */
55struct process *pcurrent; /* current job in table */
56struct process *pprevious; /* previous job in table */
57
58int pmaxindex; /* current maximum job index */
59
60static struct rusage zru;
61
62static void pflushall(void);
63static void pflush(struct process *);
64static void pclrcurr(struct process *);
65static void padd(struct command *);
66static int pprint(struct process *, int);
67static void ptprint(struct process *);
68static void pads(Char *);
69static void pkill(Char **v, int);
70static struct process
71 *pgetcurr(struct process *);
72static 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 */
82void
83pchild(int notused)
84{
85 struct process *pp;
86 struct process *fp;
87 int pid;
88 extern int insource;
89 int save_errno = errno(*__errno());
90 int w;
91 int jobflags;
92 struct rusage ru;
93
94loop:
95 errno(*__errno()) = 0; /* reset, just in case */
96 pid = wait3(&w,
97 (setintr && (intty || insource) ? WNOHANG0x01 | WUNTRACED0x02 : WNOHANG0x01), &ru);
98
99 if (pid <= 0) {
100 if (errno(*__errno()) == EINTR4) {
101 errno(*__errno()) = 0;
102 goto loop;
103 }
104 pnoprocesses = pid == -1;
105 errno(*__errno()) = save_errno;
106 return;
107 }
108 for (pp = proclist.p_next; pp != NULL((void *)0); pp = pp->p_next)
109 if (pid == pp->p_pid)
110 goto found;
111 goto loop;
112found:
113 if (pid == atoi(short2str(value(STRchild)value1(STRchild, &shvhed))))
114 unsetv(STRchild);
115 pp->p_flags &= ~(PRUNNING(1<<0) | PSTOPPED(1<<1) | PREPORTED(1<<12));
116 if (WIFSTOPPED(w)(((w) & 0xff) == 0177)) {
117 pp->p_flags |= PSTOPPED(1<<1);
118 pp->p_reason = WSTOPSIG(w)(int)(((unsigned)(w) >> 8) & 0xff);
119 }
120 else {
121 if (pp->p_flags & (PTIME(1<<6) | PPTIME(1<<14)) || adrof(STRtime)adrof1(STRtime, &shvhed))
122 (void) clock_gettime(CLOCK_MONOTONIC3, &pp->p_etime);
123
124 pp->p_rusage = ru;
125 if (WIFSIGNALED(w)(((w) & 0177) != 0177 && ((w) & 0177) != 0)) {
126 if (WTERMSIG(w)(((w) & 0177)) == SIGINT2)
127 pp->p_flags |= PINTERRUPTED(1<<13);
128 else
129 pp->p_flags |= PSIGNALED(1<<4);
130 if (WCOREDUMP(w)((w) & 0200))
131 pp->p_flags |= PDUMPED(1<<9);
132 pp->p_reason = WTERMSIG(w)(((w) & 0177));
133 }
134 else {
135 pp->p_reason = WEXITSTATUS(w)(int)(((unsigned)(w) >> 8) & 0xff);
136 if (pp->p_reason != 0)
137 pp->p_flags |= PAEXITED(1<<3);
138 else
139 pp->p_flags |= PNEXITED(1<<2);
140 }
141 }
142 jobflags = 0;
143 fp = pp;
144 do {
145 if ((fp->p_flags & (PPTIME(1<<14) | PRUNNING(1<<0) | PSTOPPED(1<<1))) == 0 &&
146 !child && adrof(STRtime)adrof1(STRtime, &shvhed) &&
147 fp->p_rusage.ru_utime.tv_sec + fp->p_rusage.ru_stime.tv_sec
148 >= atoi(short2str(value(STRtime)value1(STRtime, &shvhed))))
149 fp->p_flags |= PTIME(1<<6);
150 jobflags |= fp->p_flags;
151 } while ((fp = fp->p_friends) != pp);
152 pp->p_flags &= ~PFOREGND(1<<8);
153 if (pp == pp->p_friends && (pp->p_flags & PPTIME(1<<14))) {
154 pp->p_flags &= ~PPTIME(1<<14);
155 pp->p_flags |= PTIME(1<<6);
156 }
157 if ((jobflags & (PRUNNING(1<<0) | PREPORTED(1<<12))) == 0) {
158 fp = pp;
159 do {
160 if (fp->p_flags & PSTOPPED(1<<1))
161 fp->p_flags |= PREPORTED(1<<12);
162 } while ((fp = fp->p_friends) != pp);
163 while (fp->p_pid != fp->p_jobid)
164 fp = fp->p_friends;
165 if (jobflags & PSTOPPED(1<<1)) {
166 if (pcurrent && pcurrent != fp)
167 pprevious = pcurrent;
168 pcurrent = fp;
169 }
170 else
171 pclrcurr(fp);
172 if (jobflags & PFOREGND(1<<8)) {
173 if (jobflags & (PSIGNALED(1<<4) | PSTOPPED(1<<1) | PPTIME(1<<14)) ||
174 !eq(dcwd->di_name, fp->p_cwd->di_name)(Strcmp(dcwd->di_name, fp->p_cwd->di_name) == 0)) {
175 ; /* print in pjwait */
176 }
177 /* PWP: print a newline after ^C */
178 else if (jobflags & PINTERRUPTED(1<<13)) {
179 (void) vis_fputc('\r' | QUOTE0100000U, cshout);
180 (void) fputc('\n', cshout);
181 }
182 }
183 else {
184 if (jobflags & PNOTIFY(1<<5) || adrof(STRnotify)adrof1(STRnotify, &shvhed)) {
185 (void) vis_fputc('\r' | QUOTE0100000U, cshout);
186 (void) fputc('\n', cshout);
187 (void) pprint(pp, NUMBER01 | NAME02 | REASON04);
188 if ((jobflags & PSTOPPED(1<<1)) == 0)
189 pflush(pp);
190 }
191 else {
192 fp->p_flags |= PNEEDNOTE(1<<15);
193 neednote++;
194 }
195 }
196 }
197 goto loop;
198}
199
200void
201pnote(void)
202{
203 struct process *pp;
204 int flags;
205 sigset_t sigset, osigset;
206
207 neednote = 0;
208 sigemptyset(&sigset);
209 sigaddset(&sigset, SIGCHLD20);
210 for (pp = proclist.p_next; pp != NULL((void *)0); pp = pp->p_next) {
211 if (pp->p_flags & PNEEDNOTE(1<<15)) {
212 sigprocmask(SIG_BLOCK1, &sigset, &osigset);
213 pp->p_flags &= ~PNEEDNOTE(1<<15);
214 flags = pprint(pp, NUMBER01 | NAME02 | REASON04);
215 if ((flags & (PRUNNING(1<<0) | PSTOPPED(1<<1))) == 0)
216 pflush(pp);
217 sigprocmask(SIG_SETMASK3, &osigset, NULL((void *)0));
218 }
219 }
220}
221
222/*
223 * pwait - wait for current job to terminate, maintaining integrity
224 * of current and previous job indicators.
225 */
226void
227pwait(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, SIGCHLD20);
237 sigprocmask(SIG_BLOCK1, &sigset, &osigset);
238 for (pp = (fp = &proclist)->p_next; pp != NULL((void *)0); 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_SETMASK3, &osigset, NULL((void *)0));
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 */
257void
258pjwait(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(1<<8) | PRUNNING(1<<0))) == PRUNNING(1<<0))
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, SIGCHLD20);
279 sigprocmask(SIG_BLOCK1, &sigset, &osigset);
280 for (;;) {
281 sigemptyset(&sigset);
282 sigaddset(&sigset, SIGCHLD20);
283 sigprocmask(SIG_BLOCK1, &sigset, NULL((void *)0));
284 jobflags = 0;
285 do
286 jobflags |= fp->p_flags;
287 while ((fp = (fp->p_friends)) != pp);
288 if ((jobflags & PRUNNING(1<<0)) == 0)
289 break;
290 sigset = osigset;
291 sigdelset(&sigset, SIGCHLD20);
292 sigsuspend(&sigset);
293 }
294 sigprocmask(SIG_SETMASK3, &osigset, NULL((void *)0));
295 if (tpgrp > 0) /* get tty back */
296 (void) tcsetpgrp(FSHTTY15, tpgrp);
297 if ((jobflags & (PSIGNALED(1<<4) | PSTOPPED(1<<1) | PTIME(1<<6))) ||
298 !eq(dcwd->di_name, fp->p_cwd->di_name)(Strcmp(dcwd->di_name, fp->p_cwd->di_name) == 0)) {
299 if (jobflags & PSTOPPED(1<<1)) {
300 (void) fputc('\n', cshout);
301 if (adrof(STRlistjobs)adrof1(STRlistjobs, &shvhed)) {
302 Char *jobcommand[3];
303
304 jobcommand[0] = STRjobs;
305 if (eq(value(STRlistjobs), STRlong)(Strcmp(value1(STRlistjobs, &shvhed), STRlong) == 0))
306 jobcommand[1] = STRml;
307 else
308 jobcommand[1] = NULL((void *)0);
309 jobcommand[2] = NULL((void *)0);
310
311 dojobs(jobcommand, NULL((void *)0));
312 (void) pprint(pp, SHELLDIR040);
313 }
314 else
315 (void) pprint(pp, AREASON0200 | SHELLDIR040);
316 }
317 else
318 (void) pprint(pp, AREASON0200 | SHELLDIR040);
319 }
320 if ((jobflags & (PINTERRUPTED(1<<13) | PSTOPPED(1<<1))) && setintr &&
321 (!gointr || !eq(gointr, STRminus)(Strcmp(gointr, STRminus) == 0))) {
322 if ((jobflags & PSTOPPED(1<<1)) == 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(1<<4) | PINTERRUPTED(1<<13)) ?
332 fp->p_reason | META0200 : fp->p_reason;
333 } while ((fp = fp->p_friends) != pp);
334 if ((reason != 0) && (adrof(STRprintexitvalue)adrof1(STRprintexitvalue, &shvhed))) {
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 */
346void
347dowait(Char **v, struct command *t)
348{
349 struct process *pp;
350 sigset_t sigset, osigset;
351
352 pjobs++;
353 sigemptyset(&sigset);
354 sigaddset(&sigset, SIGCHLD20);
355 sigprocmask(SIG_BLOCK1, &sigset, &osigset);
356loop:
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(1<<0)) {
360 sigemptyset(&sigset);
361 sigsuspend(&sigset);
362 goto loop;
363 }
364 sigprocmask(SIG_SETMASK3, &osigset, NULL((void *)0));
365 pjobs = 0;
366}
367
368/*
369 * pflushall - flush all jobs from list (e.g. at fork())
370 */
371static void
372pflushall(void)
373{
374 struct process *pp;
375
376 for (pp = proclist.p_next; pp != NULL((void *)0); 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 */
386static void
387pflush(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(1<<15);
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 */
419static void
420pclrcurr(struct process *pp)
421{
422
423 if (pp == pcurrent)
424 if (pprevious != NULL((void *)0)) {
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 << >& >> */
437static Char command[PMAXLEN80 + 4];
438static int cmdlen;
439static 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 */
445void
446palloc(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(1<<0) ? PRUNNING(1<<0) : PRUNNING(1<<0) | PFOREGND(1<<8);
454 if (t->t_dflg & F_TIME(1<<13))
455 pp->p_flags |= PPTIME(1<<14);
456 cmdp = command;
457 cmdlen = 0;
458 padd(t);
459 *cmdp++ = 0;
460 if (t->t_dflg & F_PIPEOUT(1<<3)) {
461 pp->p_flags |= PPOU(1<<11);
462 if (t->t_dflg & F_STDERR(1<<7))
463 pp->p_flags |= PERR(1<<10);
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 < BIGINDEX9)
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((void *)0))
501 pcurrent = pp;
502 else if (pprevious == NULL((void *)0))
503 pprevious = pp;
504 }
505 pp->p_next = proclist.p_next;
506 proclist.p_next = pp;
507 (void) clock_gettime(CLOCK_MONOTONIC3, &pp->p_btime);
508}
509
510static void
511padd(struct command *t)
512{
513 Char **argp;
514
515 if (t == 0)
516 return;
517 switch (t->t_dtyp) {
518
519 case NODE_PAREN2:
520 pads(STRLparensp);
521 padd(t->t_dspr);
522 pads(STRspRparen);
523 break;
524
525 case NODE_COMMAND1:
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_OR5:
534 case NODE_AND6:
535 case NODE_PIPE3:
536 case NODE_LIST4:
537 padd(t->t_dcarL.T_dcar);
538 switch (t->t_dtyp) {
539 case NODE_OR5:
540 pads(STRspor2sp);
541 break;
542 case NODE_AND6:
543 pads(STRspand2sp);
544 break;
545 case NODE_PIPE3:
546 pads(STRsporsp);
547 break;
548 case NODE_LIST4:
549 pads(STRsemisp);
550 break;
551 }
552 padd(t->t_dcdrR.T_dcdr);
553 return;
554 }
555 if ((t->t_dflg & F_PIPEIN(1<<2)) == 0 && t->t_dlefL.T_dlef) {
556 pads((t->t_dflg & F_READ(1<<9)) ? STRspLarrow2sp : STRspLarrowsp);
557 pads(t->t_dlefL.T_dlef);
558 }
559 if ((t->t_dflg & F_PIPEOUT(1<<3)) == 0 && t->t_dritR.T_drit) {
560 pads((t->t_dflg & F_APPEND(1<<1)) ? STRspRarrow2 : STRspRarrow);
561 if (t->t_dflg & F_STDERR(1<<7))
562 pads(STRand);
563 pads(STRspace);
564 pads(t->t_dritR.T_drit);
565 }
566}
567
568static void
569pads(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 >= PMAXLEN80)
583 return;
584 if (cmdlen + i >= PMAXLEN80) {
585 (void) Strlcpy(cmdp, STRsp3dots, PMAXLEN80 - cmdlen);
586 cmdlen = PMAXLEN80;
587 cmdp += 4;
588 return;
589 }
590 (void) Strlcpy(cmdp, cp, PMAXLEN80 - 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 */
600void
601psavejob(void)
602{
603
604 pholdjob = pcurrjob;
605 pcurrjob = NULL((void *)0);
606}
607
608/*
609 * prestjob - opposite of psavejob. This may be missed if we are interrupted
610 * somewhere, but pendjob cleans up anyway.
611 */
612void
613prestjob(void)
614{
615
616 pcurrjob = pholdjob;
617 pholdjob = NULL((void *)0);
618}
619
620/*
621 * pendjob - indicate that a job (set of commands) has been completed
622 * or is about to begin.
623 */
624void
625pendjob(void)
626{
627 struct process *pp, *tp;
628
629 if (pcurrjob && (pcurrjob->p_flags & (PFOREGND(1<<8) | PSTOPPED(1<<1))) == 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 */
647static int
648pprint(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(1<<14))) {
660 pp->p_flags &= ~PPTIME(1<<14);
661 pp->p_flags |= PTIME(1<<6);
662 }
663 tp = pp;
664 status = reason = -1;
665 jobflags = 0;
666 do {
667 jobflags |= pp->p_flags;
668 pstatus = pp->p_flags & PALLSTATES((1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<
4)|(1<<13))
;
669 if (tp != pp && !hadnl && !(flag & FANCY020) &&
670 ((pstatus == status && pp->p_reason == reason) ||
671 !(flag & REASON04))) {
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 & NUMBER01) {
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 & FANCY020) {
691 (void) fprintf(cshout, "%5d ", pp->p_pid);
692 hadnl = 0;
693 }
694 if (flag & (REASON04 | AREASON0200)) {
695 int width = 0;
696 if (flag & NAME02)
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(1<<0):
713 (void) fprintf(cshout, "%*s", width, "Running ");
714 hadnl = 0;
715 break;
716
717 case PINTERRUPTED(1<<13):
718 case PSTOPPED(1<<1):
719 case PSIGNALED(1<<4):
720 /*
721 * tell what happened to the background job
722 * From: Michael Schroeder
723 * <mlschroe@immd4.informatik.uni-erlangen.de>
724 */
725 if ((flag & REASON04)
726 || ((flag & AREASON0200)
727 && reason != SIGINT2
728 && (reason != SIGPIPE13
729 || (pp->p_flags & PPOU(1<<11)) == 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(1<<2):
738 case PAEXITED(1<<3):
739 if (flag & REASON04) {
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 }
753prcomd:
754 if (flag & NAME02) {
755 (void) fprintf(cshout, "%s", vis_str(pp->p_command));
756 if (pp->p_flags & PPOU(1<<11))
757 (void) fprintf(cshout, " |");
758 if (pp->p_flags & PERR(1<<10))
759 (void) fputc('&', cshout);
760 hadnl = 0;
761 }
762 if (flag & (REASON04 | AREASON0200) && pp->p_flags & PDUMPED(1<<9)) {
763 (void) fprintf(cshout, " (core dumped)");
764 hadnl = 0;
765 }
766 if (tp == pp->p_friends) {
767 if (flag & AMPERSAND010) {
768 (void) fprintf(cshout, " &");
769 hadnl = 0;
770 }
771 if (flag & JOBDIR0100 &&
772 !eq(tp->p_cwd->di_name, dcwd->di_name)(Strcmp(tp->p_cwd->di_name, dcwd->di_name) == 0)) {
773 (void) fprintf(cshout, " (wd: ");
774 dtildepr(value(STRhome)value1(STRhome, &shvhed), tp->p_cwd->di_name);
775 (void) fputc(')', cshout);
776 hadnl = 0;
777 }
778 }
779 if (pp->p_flags & PPTIME(1<<14) && !(status & (PSTOPPED(1<<1) | PRUNNING(1<<0)))) {
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 & SHELLDIR040 && !eq(tp->p_cwd->di_name, dcwd->di_name)(Strcmp(tp->p_cwd->di_name, dcwd->di_name) == 0)) {
792 (void) fprintf(cshout, "(wd now: ");
793 dtildepr(value(STRhome)value1(STRhome, &shvhed), dcwd->di_name);
794 (void) fprintf(cshout, ")\n");
795 hadnl = 1;
796 }
797 }
798 } while ((pp = pp->p_friends) != tp);
799 if (jobflags & PTIME(1<<6) && (jobflags & (PSTOPPED(1<<1) | PRUNNING(1<<0))) == 0) {
800 if (jobflags & NUMBER01)
801 (void) fprintf(cshout, " ");
802 ptprint(tp);
803 hadnl = 1;
Value stored to 'hadnl' is never read
804 }
805 (void) fflush(cshout);
806 return (jobflags);
807}
808
809static void
810ptprint(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)do { (&diff)->tv_sec = (&pp->p_etime)->tv_sec
- (&pp->p_btime)->tv_sec; (&diff)->tv_nsec =
(&pp->p_etime)->tv_nsec - (&pp->p_btime)->
tv_nsec; if ((&diff)->tv_nsec < 0) { (&diff)->
tv_sec--; (&diff)->tv_nsec += 1000000000L; } } while (
0)
;
823 if (timespeccmp(&diff, &tetime, >)(((&diff)->tv_sec == (&tetime)->tv_sec) ? ((&
diff)->tv_nsec > (&tetime)->tv_nsec) : ((&diff
)->tv_sec > (&tetime)->tv_sec))
)
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 */
832void
833dojobs(Char **v, struct command *t)
834{
835 struct process *pp;
836 int flag = NUMBER01 | NAME02 | REASON04;
837 int i;
838
839 if (chkstop)
840 chkstop = 2;
841 if (*++v) {
842 if (v[1] || !eq(*v, STRml)(Strcmp(*v, STRml) == 0))
843 stderror(ERR_JOBS57);
844 flag |= FANCY020 | JOBDIR0100;
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(1<<15);
850 if (!(pprint(pp, flag) & (PRUNNING(1<<0) | PSTOPPED(1<<1))))
851 pflush(pp);
852 break;
853 }
854}
855
856/*
857 * dofg - builtin - put the job into the foreground
858 */
859void
860dofg(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 */
876void
877dofg1(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 */
890void
891dobg(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 */
906void
907dobg1(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 */
918void
919dostop(Char **v, struct command *t)
920{
921 pkill(++v, SIGSTOP17);
922}
923
924/*
925 * dokill - builtin - superset of kill (1)
926 */
927void
928dokill(Char **v, struct command *t)
929{
930 int signum = SIGTERM15;
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])(((v[1][0]) & 0100000U) ? 0 : isdigit((unsigned char) (v[
1][0])))
)
939 stderror(ERR_NAME0x10000000 | ERR_BADSIG28);
940
941 signum = strtonum(short2str(v[1]), 0, NSIG33-1, &errstr);
942 if (errstr)
943 stderror(ERR_NAME0x10000000 | ERR_BADSIG28);
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 < NSIG33; signum++) {
950 (void) fprintf(cshout, "%s ", sys_signame[signum]);
951 if (signum == NSIG33 / 2)
952 (void) fputc('\n', cshout);
953 }
954 }
955 (void) fputc('\n', cshout);
956 return;
957 }
958 if (Isdigit(v[0][1])(((v[0][1]) & 0100000U) ? 0 : isdigit((unsigned char) (v[
0][1])))
) {
959 signum = strtonum(short2str(v[0] + 1), 0, NSIG33-1, &errstr);
960 if (errstr)
961 stderror(ERR_NAME0x10000000 | ERR_BADSIG28);
962 }
963 else {
964 if (v[0][1] == 's' && (Isspace(v[0][2])(((v[0][2]) & 0100000U) ? 0 : isspace((unsigned char) (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((void *)0) || v[1] == NULL((void *)0)) {
972 stderror(ERR_NAME0x10000000 | ERR_TOOFEW15);
973 return;
974 }
975
976 for (signum = 1; signum < NSIG33; 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 == NSIG33) {
983 if (name[0] == '0')
984 signum = 0;
985 else {
986 setname(vis_str(&v[0][0]))(bname = (vis_str(&v[0][0])));
987 stderror(ERR_NAME0x10000000 | ERR_UNKSIG29);
988 }
989 }
990 }
991 v++;
992 }
993 pkill(v, signum);
994}
995
996static void
997pkill(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, SIGCHLD20);
1007 if (setintr)
1008 sigaddset(&sigset, SIGINT2);
1009 sigprocmask(SIG_BLOCK1, &sigset, NULL((void *)0));
1010 gflag = 0, tglob(v);
1011 if (gflag) {
1012 v = globall(v);
1013 if (v == 0)
1014 stderror(ERR_NAME0x10000000 | ERR_NOMATCH50);
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 SIGSTOP17:
1030 case SIGTSTP18:
1031 case SIGTTIN21:
1032 case SIGTTOU22:
1033 if ((jobflags & PRUNNING(1<<0)) == 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 SIGCONT19:
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(*__errno())));
1051 err1++;
1052 }
1053 if (signum == SIGTERM15 || signum == SIGHUP1)
1054 (void) kill(-pp->p_jobid, SIGCONT19);
1055 }
1056 else if (!(Isdigit(*cp)(((*cp) & 0100000U) ? 0 : isdigit((unsigned char) (*cp))) || *cp == '-'))
1057 stderror(ERR_NAME0x10000000 | ERR_JOBARGS58);
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(*__errno())));
1070 err1++;
1071 goto cont;
1072 }
1073 if (signum == SIGTERM15 || signum == SIGHUP1)
1074 (void) kill((pid_t) pid, SIGCONT19);
1075 }
1076cont:
1077 v++;
1078 }
1079 blkfree(gargv);
1080 gargv = NULL((void *)0);
1081 sigprocmask(SIG_UNBLOCK2, &sigset, NULL((void *)0));
1082 if (err1)
1083 stderror(ERR_SILENT0x20000000);
1084}
1085
1086/*
1087 * pstart - start the job in foreground/background
1088 */
1089void
1090pstart(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, SIGCHLD20);
1098 sigprocmask(SIG_BLOCK1, &sigset, &osigset);
1099 np = pp;
1100 do {
1101 jobflags |= np->p_flags;
1102 if (np->p_flags & (PRUNNING(1<<0) | PSTOPPED(1<<1))) {
1103 np->p_flags |= PRUNNING(1<<0);
1104 np->p_flags &= ~PSTOPPED(1<<1);
1105 if (foregnd)
1106 np->p_flags |= PFOREGND(1<<8);
1107 else
1108 np->p_flags &= ~PFOREGND(1<<8);
1109 }
1110 } while ((np = np->p_friends) != pp);
1111 if (!foregnd)
1112 pclrcurr(pp);
1113 (void) pprint(pp, foregnd ? NAME02 | JOBDIR0100 : NUMBER01 | NAME02 | AMPERSAND010);
1114 if (foregnd)
1115 (void) tcsetpgrp(FSHTTY15, pp->p_jobid);
1116 if (jobflags & PSTOPPED(1<<1))
1117 (void) kill(-pp->p_jobid, SIGCONT19);
1118 sigprocmask(SIG_SETMASK3, &osigset, NULL((void *)0));
1119}
1120
1121void
1122panystop(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(1<<1))
1129 stderror(ERR_STOPPED65, neednl ? "\n" : "");
1130}
1131
1132struct process *
1133pfind(Char *cp)
1134{
1135 struct process *pp, *np;
1136
1137 if (cp == 0 || cp[1] == 0 || eq(cp, STRcent2)(Strcmp(cp, STRcent2) == 0) || eq(cp, STRcentplus)(Strcmp(cp, STRcentplus) == 0)) {
1138 if (pcurrent == NULL((void *)0))
1139 stderror(ERR_NAME0x10000000 | ERR_JOBCUR59);
1140 return (pcurrent);
1141 }
1142 if (eq(cp, STRcentminus)(Strcmp(cp, STRcentminus) == 0) || eq(cp, STRcenthash)(Strcmp(cp, STRcenthash) == 0)) {
1143 if (pprevious == NULL((void *)0))
1144 stderror(ERR_NAME0x10000000 | ERR_JOBPREV60);
1145 return (pprevious);
1146 }
1147 if (Isdigit(cp[1])(((cp[1]) & 0100000U) ? 0 : isdigit((unsigned char) (cp[1
])))
) {
1148 const char *errstr;
1149 int idx = strtonum(short2str(cp + 1), 1, INT_MAX0x7fffffff, &errstr);
1150
1151 if (errstr) {
1152 stderror(ERR_NAME0x10000000 | ERR_NOSUCHJOB46);
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_NAME0x10000000 | ERR_NOSUCHJOB46);
1159 return (0);
1160 }
1161 np = NULL((void *)0);
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_NAME0x10000000 | ERR_AMBIG40);
1178 np = pp;
1179 }
1180 }
1181 if (np)
1182 return (np);
1183 stderror(ERR_NAME0x10000000 | (cp[1] == '?' ? ERR_JOBPAT61 : ERR_NOSUCHJOB46));
1184 /* NOTREACHED */
1185 return (0);
1186}
1187
1188
1189/*
1190 * pgetcurr - find most recent job that is not pp, preferably stopped
1191 */
1192static struct process *
1193pgetcurr(struct process *pp)
1194{
1195 struct process *np;
1196 struct process *xp = NULL((void *)0);
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(1<<1))
1202 return (np);
1203 if (xp == NULL((void *)0))
1204 xp = np;
1205 }
1206 return (xp);
1207}
1208
1209/*
1210 * donotify - flag the job so as to report termination asynchronously
1211 */
1212void
1213donotify(Char **v, struct command *t)
1214{
1215 struct process *pp;
1216
1217 pp = pfind(*++v);
1218 pp->p_flags |= PNOTIFY(1<<5);
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
1233int
1234pfork(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(1<<5)))
1251 || (gointr && eq(gointr, STRminus)(Strcmp(gointr, STRminus) == 0));
1252 /*
1253 * Check for maximum nesting of 16 processes to avoid Forking loops
1254 */
1255 if (child == 16)
1256 stderror(ERR_NESTING62, 16);
1257 /*
1258 * Hold SIGCHLD until we have the process installed in our table.
1259 */
1260 sigemptyset(&sigset);
1261 sigaddset(&sigset, SIGCHLD20);
1262 sigprocmask(SIG_BLOCK1, &sigset, &osigset);
1263 while ((pid = fork()) == -1)
1264 if (setintr == 0)
1265 (void) sleep(FORKSLEEP10);
1266 else {
1267 sigprocmask(SIG_SETMASK3, &osigset, NULL((void *)0));
1268 stderror(ERR_NOPROC49);
1269 }
1270 if (pid == 0) {
1271 settimes();
1272 pgrp = pcurrjob ? pcurrjob->p_jobid : getpid();
1273 pflushall();
1274 pcurrjob = NULL((void *)0);
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(SIGINT2, ignint ? SIG_IGN(void (*)(int))1 : SIG_DFL(void (*)(int))0);
1283 (void) signal(SIGQUIT3, ignint ? SIG_IGN(void (*)(int))1 : SIG_DFL(void (*)(int))0);
1284 if (wanttty >= 0) {
1285 /* make stoppable */
1286 (void) signal(SIGTSTP18, SIG_DFL(void (*)(int))0);
1287 (void) signal(SIGTTIN21, SIG_DFL(void (*)(int))0);
1288 (void) signal(SIGTTOU22, SIG_DFL(void (*)(int))0);
1289 }
1290 (void) signal(SIGTERM15, parterm);
1291 }
1292 else if (tpgrp == -1 && (t->t_dflg & F_NOINTERRUPT(1<<5))) {
1293 (void) signal(SIGINT2, SIG_IGN(void (*)(int))1);
1294 (void) signal(SIGQUIT3, SIG_IGN(void (*)(int))1);
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(1<<12))
1303 (void) signal(SIGHUP1, SIG_IGN(void (*)(int))1);
1304 if (t->t_dflg & F_NICE(1<<11))
1305 (void) setpriority(PRIO_PROCESS0, 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_SETMASK3, &osigset, NULL((void *)0));
1312 }
1313
1314 return (pid);
1315}
1316
1317static void
1318okpcntl(void)
1319{
1320 if (tpgrp == -1)
1321 stderror(ERR_JOBCONTROL33);
1322 if (tpgrp == 0)
1323 stderror(ERR_JOBCTRLSUB63);
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 */
1334void
1335pgetty(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, SIGTSTP18);
1346 sigaddset(&sigset, SIGTTIN21);
1347 sigaddset(&sigset, SIGTTOU22);
1348 sigprocmask(SIG_BLOCK1, &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(FSHTTY15, pgrp);
1364 sigprocmask(SIG_SETMASK3, &osigset, NULL((void *)0));
1365 }
1366
1367 if (tpgrp > 0)
1368 tpgrp = 0; /* gave tty away */
1369}