Bug Summary

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

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name proc.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -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 -fno-rounding-math -mconstructor-aliases -munwind-tables -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/lib/clang/13.0.0 -I /usr/src/bin/csh -I . -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/bin/csh/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -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/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/bin/csh/proc.c
1/* $OpenBSD: proc.c,v 1.34 2020/08/30 22:23:47 mortimer 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) ? WNOHANG1 | WUNTRACED2 : WNOHANG1), &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
347/*ARGSUSED*/
348dowait(Char **v, struct command *t)
349{
350 struct process *pp;
351 sigset_t sigset, osigset;
352
353 pjobs++;
354 sigemptyset(&sigset);
355 sigaddset(&sigset, SIGCHLD20);
356 sigprocmask(SIG_BLOCK1, &sigset, &osigset);
357loop:
358 for (pp = proclist.p_next; pp; pp = pp->p_next)
359 if (pp->p_pid && /* pp->p_pid == pp->p_jobid && */
360 pp->p_flags & PRUNNING(1<<0)) {
361 sigemptyset(&sigset);
362 sigsuspend(&sigset);
363 goto loop;
364 }
365 sigprocmask(SIG_SETMASK3, &osigset, NULL((void *)0));
366 pjobs = 0;
367}
368
369/*
370 * pflushall - flush all jobs from list (e.g. at fork())
371 */
372static void
373pflushall(void)
374{
375 struct process *pp;
376
377 for (pp = proclist.p_next; pp != NULL((void *)0); pp = pp->p_next)
378 if (pp->p_pid)
379 pflush(pp);
380}
381
382/*
383 * pflush - flag all process structures in the same job as the
384 * the argument process for deletion. The actual free of the
385 * space is not done here since pflush is called at interrupt level.
386 */
387static void
388pflush(struct process *pp)
389{
390 struct process *np;
391 int idx;
392
393 if (pp->p_pid == 0) {
394 (void) fprintf(csherr, "BUG: process flushed twice");
395 return;
396 }
397 while (pp->p_pid != pp->p_jobid)
398 pp = pp->p_friends;
399 pclrcurr(pp);
400 if (pp == pcurrjob)
401 pcurrjob = 0;
402 idx = pp->p_index;
403 np = pp;
404 do {
405 np->p_index = np->p_pid = 0;
406 np->p_flags &= ~PNEEDNOTE(1<<15);
407 } while ((np = np->p_friends) != pp);
408 if (idx == pmaxindex) {
409 for (np = proclist.p_next, idx = 0; np; np = np->p_next)
410 if (np->p_index > idx)
411 idx = np->p_index;
412 pmaxindex = idx;
413 }
414}
415
416/*
417 * pclrcurr - make sure the given job is not the current or previous job;
418 * pp MUST be the job leader
419 */
420static void
421pclrcurr(struct process *pp)
422{
423
424 if (pp == pcurrent)
425 if (pprevious != NULL((void *)0)) {
426 pcurrent = pprevious;
427 pprevious = pgetcurr(pp);
428 }
429 else {
430 pcurrent = pgetcurr(pp);
431 pprevious = pgetcurr(pp);
432 }
433 else if (pp == pprevious)
434 pprevious = pgetcurr(pp);
435}
436
437/* +4 here is 1 for '\0', 1 ea for << >& >> */
438static Char command[PMAXLEN80 + 4];
439static int cmdlen;
440static Char *cmdp;
441
442/*
443 * palloc - allocate a process structure and fill it up.
444 * an important assumption is made that the process is running.
445 */
446void
447palloc(int pid, struct command *t)
448{
449 struct process *pp;
450 int i;
451
452 pp = xcalloc(1, (size_t) sizeof(struct process));
453 pp->p_pid = pid;
454 pp->p_flags = t->t_dflg & F_AMPERSAND(1<<0) ? PRUNNING(1<<0) : PRUNNING(1<<0) | PFOREGND(1<<8);
455 if (t->t_dflg & F_TIME(1<<13))
456 pp->p_flags |= PPTIME(1<<14);
457 cmdp = command;
458 cmdlen = 0;
459 padd(t);
460 *cmdp++ = 0;
461 if (t->t_dflg & F_PIPEOUT(1<<3)) {
462 pp->p_flags |= PPOU(1<<11);
463 if (t->t_dflg & F_STDERR(1<<7))
464 pp->p_flags |= PERR(1<<10);
465 }
466 pp->p_command = Strsave(command);
467 if (pcurrjob) {
468 struct process *fp;
469
470 /* careful here with interrupt level */
471 pp->p_cwd = 0;
472 pp->p_index = pcurrjob->p_index;
473 pp->p_friends = pcurrjob;
474 pp->p_jobid = pcurrjob->p_pid;
475 for (fp = pcurrjob; fp->p_friends != pcurrjob; fp = fp->p_friends)
476 continue;
477 fp->p_friends = pp;
478 }
479 else {
480 pcurrjob = pp;
481 pp->p_jobid = pid;
482 pp->p_friends = pp;
483 pp->p_cwd = dcwd;
484 dcwd->di_count++;
485 if (pmaxindex < BIGINDEX9)
486 pp->p_index = ++pmaxindex;
487 else {
488 struct process *np;
489
490 for (i = 1;; i++) {
491 for (np = proclist.p_next; np; np = np->p_next)
492 if (np->p_index == i)
493 goto tryagain;
494 pp->p_index = i;
495 if (i > pmaxindex)
496 pmaxindex = i;
497 break;
498 tryagain:;
499 }
500 }
501 if (pcurrent == NULL((void *)0))
502 pcurrent = pp;
503 else if (pprevious == NULL((void *)0))
504 pprevious = pp;
505 }
506 pp->p_next = proclist.p_next;
507 proclist.p_next = pp;
508 (void) clock_gettime(CLOCK_MONOTONIC3, &pp->p_btime);
509}
510
511static void
512padd(struct command *t)
513{
514 Char **argp;
515
516 if (t == 0)
517 return;
518 switch (t->t_dtyp) {
519
520 case NODE_PAREN2:
521 pads(STRLparensp);
522 padd(t->t_dspr);
523 pads(STRspRparen);
524 break;
525
526 case NODE_COMMAND1:
527 for (argp = t->t_dcom; *argp; argp++) {
528 pads(*argp);
529 if (argp[1])
530 pads(STRspace);
531 }
532 break;
533
534 case NODE_OR5:
535 case NODE_AND6:
536 case NODE_PIPE3:
537 case NODE_LIST4:
538 padd(t->t_dcarL.T_dcar);
539 switch (t->t_dtyp) {
540 case NODE_OR5:
541 pads(STRspor2sp);
542 break;
543 case NODE_AND6:
544 pads(STRspand2sp);
545 break;
546 case NODE_PIPE3:
547 pads(STRsporsp);
548 break;
549 case NODE_LIST4:
550 pads(STRsemisp);
551 break;
552 }
553 padd(t->t_dcdrR.T_dcdr);
554 return;
555 }
556 if ((t->t_dflg & F_PIPEIN(1<<2)) == 0 && t->t_dlefL.T_dlef) {
557 pads((t->t_dflg & F_READ(1<<9)) ? STRspLarrow2sp : STRspLarrowsp);
558 pads(t->t_dlefL.T_dlef);
559 }
560 if ((t->t_dflg & F_PIPEOUT(1<<3)) == 0 && t->t_dritR.T_drit) {
561 pads((t->t_dflg & F_APPEND(1<<1)) ? STRspRarrow2 : STRspRarrow);
562 if (t->t_dflg & F_STDERR(1<<7))
563 pads(STRand);
564 pads(STRspace);
565 pads(t->t_dritR.T_drit);
566 }
567}
568
569static void
570pads(Char *cp)
571{
572 int i;
573
574 /*
575 * Avoid the Quoted Space alias hack! Reported by:
576 * sam@john-bigboote.ICS.UCI.EDU (Sam Horrocks)
577 */
578 if (cp[0] == STRQNULL[0])
579 cp++;
580
581 i = Strlen(cp);
582
583 if (cmdlen >= PMAXLEN80)
584 return;
585 if (cmdlen + i >= PMAXLEN80) {
586 (void) Strlcpy(cmdp, STRsp3dots, PMAXLEN80 - cmdlen);
587 cmdlen = PMAXLEN80;
588 cmdp += 4;
589 return;
590 }
591 (void) Strlcpy(cmdp, cp, PMAXLEN80 - cmdlen);
592 cmdp += i;
593 cmdlen += i;
594}
595
596/*
597 * psavejob - temporarily save the current job on a one level stack
598 * so another job can be created. Used for { } in exp6
599 * and `` in globbing.
600 */
601void
602psavejob(void)
603{
604
605 pholdjob = pcurrjob;
606 pcurrjob = NULL((void *)0);
607}
608
609/*
610 * prestjob - opposite of psavejob. This may be missed if we are interrupted
611 * somewhere, but pendjob cleans up anyway.
612 */
613void
614prestjob(void)
615{
616
617 pcurrjob = pholdjob;
618 pholdjob = NULL((void *)0);
619}
620
621/*
622 * pendjob - indicate that a job (set of commands) has been completed
623 * or is about to begin.
624 */
625void
626pendjob(void)
627{
628 struct process *pp, *tp;
629
630 if (pcurrjob && (pcurrjob->p_flags & (PFOREGND(1<<8) | PSTOPPED(1<<1))) == 0) {
631 pp = pcurrjob;
632 while (pp->p_pid != pp->p_jobid)
633 pp = pp->p_friends;
634 (void) fprintf(cshout, "[%d]", pp->p_index);
635 tp = pp;
636 do {
637 (void) fprintf(cshout, " %d", pp->p_pid);
638 pp = pp->p_friends;
639 } while (pp != tp);
640 (void) fputc('\n', cshout);
641 }
642 pholdjob = pcurrjob = 0;
643}
644
645/*
646 * pprint - print a job
647 */
648static int
649pprint(struct process *pp, bool flag)
650{
651 int status, reason;
652 struct process *tp;
653 int jobflags, pstatus;
654 bool hadnl = 1; /* did we just have a newline */
655
656 (void) fpurge(cshout);
657
658 while (pp->p_pid != pp->p_jobid)
659 pp = pp->p_friends;
660 if (pp == pp->p_friends && (pp->p_flags & PPTIME(1<<14))) {
661 pp->p_flags &= ~PPTIME(1<<14);
662 pp->p_flags |= PTIME(1<<6);
663 }
664 tp = pp;
665 status = reason = -1;
666 jobflags = 0;
667 do {
668 jobflags |= pp->p_flags;
669 pstatus = pp->p_flags & PALLSTATES((1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<
4)|(1<<13))
;
670 if (tp != pp && !hadnl && !(flag & FANCY020) &&
671 ((pstatus == status && pp->p_reason == reason) ||
672 !(flag & REASON04))) {
673 (void) fputc(' ', cshout);
674 hadnl = 0;
675 }
676 else {
677 if (tp != pp && !hadnl) {
678 (void) fputc('\n', cshout);
679 hadnl = 1;
680 }
681 if (flag & NUMBER01) {
682 if (pp == tp)
683 (void) fprintf(cshout, "[%d]%s %c ", pp->p_index,
684 pp->p_index < 10 ? " " : "",
685 pp == pcurrent ? '+' :
686 (pp == pprevious ? '-' : ' '));
687 else
688 (void) fprintf(cshout, " ");
689 hadnl = 0;
690 }
691 if (flag & FANCY020) {
692 (void) fprintf(cshout, "%5d ", pp->p_pid);
693 hadnl = 0;
694 }
695 if (flag & (REASON04 | AREASON0200)) {
696 int width = 0;
697 if (flag & NAME02)
698 width = -23;
699 if (pstatus == status)
700 if (pp->p_reason == reason) {
701 (void) fprintf(cshout, "%*s", width, "");
702 hadnl = 0;
703 goto prcomd;
704 }
705 else
706 reason = pp->p_reason;
707 else {
708 status = pstatus;
709 reason = pp->p_reason;
710 }
711 switch (status) {
712
713 case PRUNNING(1<<0):
714 (void) fprintf(cshout, "%*s", width, "Running ");
715 hadnl = 0;
716 break;
717
718 case PINTERRUPTED(1<<13):
719 case PSTOPPED(1<<1):
720 case PSIGNALED(1<<4):
721 /*
722 * tell what happened to the background job
723 * From: Michael Schroeder
724 * <mlschroe@immd4.informatik.uni-erlangen.de>
725 */
726 if ((flag & REASON04)
727 || ((flag & AREASON0200)
728 && reason != SIGINT2
729 && (reason != SIGPIPE13
730 || (pp->p_flags & PPOU(1<<11)) == 0))) {
731 (void) fprintf(cshout, "%*s", width,
732 sys_siglist[(unsigned char)
733 pp->p_reason]);
734 hadnl = 0;
735 }
736 break;
737
738 case PNEXITED(1<<2):
739 case PAEXITED(1<<3):
740 if (flag & REASON04) {
741 if (pp->p_reason)
742 (void) fprintf(cshout, "Exit %-18d", pp->p_reason);
743 else
744 (void) fprintf(cshout, "%*s", width, "Done");
745 hadnl = 0;
746 }
747 break;
748
749 default:
750 (void) fprintf(csherr, "BUG: status=%-9o", status);
751 }
752 }
753 }
754prcomd:
755 if (flag & NAME02) {
756 (void) fprintf(cshout, "%s", vis_str(pp->p_command));
757 if (pp->p_flags & PPOU(1<<11))
758 (void) fprintf(cshout, " |");
759 if (pp->p_flags & PERR(1<<10))
760 (void) fputc('&', cshout);
761 hadnl = 0;
762 }
763 if (flag & (REASON04 | AREASON0200) && pp->p_flags & PDUMPED(1<<9)) {
764 (void) fprintf(cshout, " (core dumped)");
765 hadnl = 0;
766 }
767 if (tp == pp->p_friends) {
768 if (flag & AMPERSAND010) {
769 (void) fprintf(cshout, " &");
770 hadnl = 0;
771 }
772 if (flag & JOBDIR0100 &&
773 !eq(tp->p_cwd->di_name, dcwd->di_name)(Strcmp(tp->p_cwd->di_name, dcwd->di_name) == 0)) {
774 (void) fprintf(cshout, " (wd: ");
775 dtildepr(value(STRhome)value1(STRhome, &shvhed), tp->p_cwd->di_name);
776 (void) fputc(')', cshout);
777 hadnl = 0;
778 }
779 }
780 if (pp->p_flags & PPTIME(1<<14) && !(status & (PSTOPPED(1<<1) | PRUNNING(1<<0)))) {
781 if (!hadnl)
782 (void) fprintf(cshout, "\n\t");
783 prusage(&zru, &pp->p_rusage, &pp->p_etime,
784 &pp->p_btime);
785 hadnl = 1;
786 }
787 if (tp == pp->p_friends) {
788 if (!hadnl) {
789 (void) fputc('\n', cshout);
790 hadnl = 1;
791 }
792 if (flag & SHELLDIR040 && !eq(tp->p_cwd->di_name, dcwd->di_name)(Strcmp(tp->p_cwd->di_name, dcwd->di_name) == 0)) {
793 (void) fprintf(cshout, "(wd now: ");
794 dtildepr(value(STRhome)value1(STRhome, &shvhed), dcwd->di_name);
795 (void) fprintf(cshout, ")\n");
796 hadnl = 1;
797 }
798 }
799 } while ((pp = pp->p_friends) != tp);
800 if (jobflags & PTIME(1<<6) && (jobflags & (PSTOPPED(1<<1) | PRUNNING(1<<0))) == 0) {
801 if (jobflags & NUMBER01)
802 (void) fprintf(cshout, " ");
803 ptprint(tp);
804 hadnl = 1;
Value stored to 'hadnl' is never read
805 }
806 (void) fflush(cshout);
807 return (jobflags);
808}
809
810static void
811ptprint(struct process *tp)
812{
813 struct timespec tetime, diff;
814 static struct timespec ztime;
815 struct rusage ru;
816 static struct rusage zru;
817 struct process *pp = tp;
818
819 ru = zru;
820 tetime = ztime;
821 do {
822 ruadd(&ru, &pp->p_rusage);
823 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)
;
824 if (timespeccmp(&diff, &tetime, >)(((&diff)->tv_sec == (&tetime)->tv_sec) ? ((&
diff)->tv_nsec > (&tetime)->tv_nsec) : ((&diff
)->tv_sec > (&tetime)->tv_sec))
)
825 tetime = diff;
826 } while ((pp = pp->p_friends) != tp);
827 prusage(&zru, &ru, &tetime, &ztime);
828}
829
830/*
831 * dojobs - print all jobs
832 */
833void
834/*ARGSUSED*/
835dojobs(Char **v, struct command *t)
836{
837 struct process *pp;
838 int flag = NUMBER01 | NAME02 | REASON04;
839 int i;
840
841 if (chkstop)
842 chkstop = 2;
843 if (*++v) {
844 if (v[1] || !eq(*v, STRml)(Strcmp(*v, STRml) == 0))
845 stderror(ERR_JOBS57);
846 flag |= FANCY020 | JOBDIR0100;
847 }
848 for (i = 1; i <= pmaxindex; i++)
849 for (pp = proclist.p_next; pp; pp = pp->p_next)
850 if (pp->p_index == i && pp->p_pid == pp->p_jobid) {
851 pp->p_flags &= ~PNEEDNOTE(1<<15);
852 if (!(pprint(pp, flag) & (PRUNNING(1<<0) | PSTOPPED(1<<1))))
853 pflush(pp);
854 break;
855 }
856}
857
858/*
859 * dofg - builtin - put the job into the foreground
860 */
861void
862/*ARGSUSED*/
863dofg(Char **v, struct command *t)
864{
865 struct process *pp;
866
867 okpcntl();
868 ++v;
869 do {
870 pp = pfind(*v);
871 pstart(pp, 1);
872 pjwait(pp);
873 } while (*v && *++v);
874}
875
876/*
877 * %... - builtin - put the job into the foreground
878 */
879void
880/*ARGSUSED*/
881dofg1(Char **v, struct command *t)
882{
883 struct process *pp;
884
885 okpcntl();
886 pp = pfind(v[0]);
887 pstart(pp, 1);
888 pjwait(pp);
889}
890
891/*
892 * dobg - builtin - put the job into the background
893 */
894void
895/*ARGSUSED*/
896dobg(Char **v, struct command *t)
897{
898 struct process *pp;
899
900 okpcntl();
901 ++v;
902 do {
903 pp = pfind(*v);
904 pstart(pp, 0);
905 } while (*v && *++v);
906}
907
908/*
909 * %... & - builtin - put the job into the background
910 */
911void
912/*ARGSUSED*/
913dobg1(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 */
924void
925/*ARGSUSED*/
926dostop(Char **v, struct command *t)
927{
928 pkill(++v, SIGSTOP17);
929}
930
931/*
932 * dokill - builtin - superset of kill (1)
933 */
934void
935/*ARGSUSED*/
936dokill(Char **v, struct command *t)
937{
938 int signum = SIGTERM15;
939 const char *errstr;
940 char *name;
941
942 v++;
943 if (v[0] && v[0][0] == '-') {
944 if (v[0][1] == 'l') {
945 if (v[1]) {
946 if (!Isdigit(v[1][0])(((v[1][0]) & 0100000U) ? 0 : isdigit((unsigned char) (v[
1][0])))
)
947 stderror(ERR_NAME0x10000000 | ERR_BADSIG28);
948
949 signum = strtonum(short2str(v[1]), 0, NSIG33-1, &errstr);
950 if (errstr)
951 stderror(ERR_NAME0x10000000 | ERR_BADSIG28);
952 else if (signum == 0)
953 (void) fputc('0', cshout); /* 0's symbolic name is '0' */
954 else
955 (void) fprintf(cshout, "%s ", sys_signame[signum]);
956 } else {
957 for (signum = 1; signum < NSIG33; signum++) {
958 (void) fprintf(cshout, "%s ", sys_signame[signum]);
959 if (signum == NSIG33 / 2)
960 (void) fputc('\n', cshout);
961 }
962 }
963 (void) fputc('\n', cshout);
964 return;
965 }
966 if (Isdigit(v[0][1])(((v[0][1]) & 0100000U) ? 0 : isdigit((unsigned char) (v[
0][1])))
) {
967 signum = strtonum(short2str(v[0] + 1), 0, NSIG33-1, &errstr);
968 if (errstr)
969 stderror(ERR_NAME0x10000000 | ERR_BADSIG28);
970 }
971 else {
972 if (v[0][1] == 's' && (Isspace(v[0][2])(((v[0][2]) & 0100000U) ? 0 : isspace((unsigned char) (v[
0][2])))
|| v[0][2] == '\0')) {
973 v++;
974 name = short2str(&v[0][0]);
975 } else {
976 name = short2str(&v[0][1]);
977 }
978
979 if (v[0] == NULL((void *)0) || v[1] == NULL((void *)0)) {
980 stderror(ERR_NAME0x10000000 | ERR_TOOFEW15);
981 return;
982 }
983
984 for (signum = 1; signum < NSIG33; signum++)
985 if (!strcasecmp(sys_signame[signum], name) ||
986 (strlen(name) > 3 && !strncasecmp("SIG", name, 3) &&
987 !strcasecmp(sys_signame[signum], name + 3)))
988 break;
989
990 if (signum == NSIG33) {
991 if (name[0] == '0')
992 signum = 0;
993 else {
994 setname(vis_str(&v[0][0]))(bname = (vis_str(&v[0][0])));
995 stderror(ERR_NAME0x10000000 | ERR_UNKSIG29);
996 }
997 }
998 }
999 v++;
1000 }
1001 pkill(v, signum);
1002}
1003
1004static void
1005pkill(Char **v, int signum)
1006{
1007 struct process *pp, *np;
1008 int jobflags = 0;
1009 int pid, err1 = 0;
1010 sigset_t sigset;
1011 Char *cp;
1012
1013 sigemptyset(&sigset);
1014 sigaddset(&sigset, SIGCHLD20);
1015 if (setintr)
1016 sigaddset(&sigset, SIGINT2);
1017 sigprocmask(SIG_BLOCK1, &sigset, NULL((void *)0));
1018 gflag = 0, tglob(v);
1019 if (gflag) {
1020 v = globall(v);
1021 if (v == 0)
1022 stderror(ERR_NAME0x10000000 | ERR_NOMATCH50);
1023 }
1024 else {
1025 v = gargv = saveblk(v);
1026 trim(v);
1027 }
1028
1029 while (v && (cp = *v)) {
1030 if (*cp == '%') {
1031 np = pp = pfind(cp);
1032 do
1033 jobflags |= np->p_flags;
1034 while ((np = np->p_friends) != pp);
1035 switch (signum) {
1036
1037 case SIGSTOP17:
1038 case SIGTSTP18:
1039 case SIGTTIN21:
1040 case SIGTTOU22:
1041 if ((jobflags & PRUNNING(1<<0)) == 0) {
1042 (void) fprintf(csherr, "%s: Already suspended\n",
1043 vis_str(cp));
1044 err1++;
1045 goto cont;
1046 }
1047 break;
1048 /*
1049 * suspend a process, kill -CONT %, then type jobs; the shell
1050 * says it is suspended, but it is running; thanks jaap..
1051 */
1052 case SIGCONT19:
1053 pstart(pp, 0);
1054 goto cont;
1055 }
1056 if (kill(-pp->p_jobid, signum) == -1) {
1057 (void) fprintf(csherr, "%s: %s\n", vis_str(cp),
1058 strerror(errno(*__errno())));
1059 err1++;
1060 }
1061 if (signum == SIGTERM15 || signum == SIGHUP1)
1062 (void) kill(-pp->p_jobid, SIGCONT19);
1063 }
1064 else if (!(Isdigit(*cp)(((*cp) & 0100000U) ? 0 : isdigit((unsigned char) (*cp))) || *cp == '-'))
1065 stderror(ERR_NAME0x10000000 | ERR_JOBARGS58);
1066 else {
1067 char *ep;
1068 char *pidnam = short2str(cp);
1069
1070 pid = strtol(pidnam, &ep, 10);
1071 if (!*pidnam || *ep) {
1072 (void) fprintf(csherr, "%s: illegal process id\n", pidnam);
1073 err1++;
1074 goto cont;
1075 }
1076 if (kill((pid_t) pid, signum) == -1) {
1077 (void) fprintf(csherr, "%d: %s\n", pid, strerror(errno(*__errno())));
1078 err1++;
1079 goto cont;
1080 }
1081 if (signum == SIGTERM15 || signum == SIGHUP1)
1082 (void) kill((pid_t) pid, SIGCONT19);
1083 }
1084cont:
1085 v++;
1086 }
1087 blkfree(gargv);
1088 gargv = NULL((void *)0);
1089 sigprocmask(SIG_UNBLOCK2, &sigset, NULL((void *)0));
1090 if (err1)
1091 stderror(ERR_SILENT0x20000000);
1092}
1093
1094/*
1095 * pstart - start the job in foreground/background
1096 */
1097void
1098pstart(struct process *pp, int foregnd)
1099{
1100 struct process *np;
1101 sigset_t sigset, osigset;
1102 long jobflags = 0;
1103
1104 sigemptyset(&sigset);
1105 sigaddset(&sigset, SIGCHLD20);
1106 sigprocmask(SIG_BLOCK1, &sigset, &osigset);
1107 np = pp;
1108 do {
1109 jobflags |= np->p_flags;
1110 if (np->p_flags & (PRUNNING(1<<0) | PSTOPPED(1<<1))) {
1111 np->p_flags |= PRUNNING(1<<0);
1112 np->p_flags &= ~PSTOPPED(1<<1);
1113 if (foregnd)
1114 np->p_flags |= PFOREGND(1<<8);
1115 else
1116 np->p_flags &= ~PFOREGND(1<<8);
1117 }
1118 } while ((np = np->p_friends) != pp);
1119 if (!foregnd)
1120 pclrcurr(pp);
1121 (void) pprint(pp, foregnd ? NAME02 | JOBDIR0100 : NUMBER01 | NAME02 | AMPERSAND010);
1122 if (foregnd)
1123 (void) tcsetpgrp(FSHTTY15, pp->p_jobid);
1124 if (jobflags & PSTOPPED(1<<1))
1125 (void) kill(-pp->p_jobid, SIGCONT19);
1126 sigprocmask(SIG_SETMASK3, &osigset, NULL((void *)0));
1127}
1128
1129void
1130panystop(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(1<<1))
1137 stderror(ERR_STOPPED65, neednl ? "\n" : "");
1138}
1139
1140struct process *
1141pfind(Char *cp)
1142{
1143 struct process *pp, *np;
1144
1145 if (cp == 0 || cp[1] == 0 || eq(cp, STRcent2)(Strcmp(cp, STRcent2) == 0) || eq(cp, STRcentplus)(Strcmp(cp, STRcentplus) == 0)) {
1146 if (pcurrent == NULL((void *)0))
1147 stderror(ERR_NAME0x10000000 | ERR_JOBCUR59);
1148 return (pcurrent);
1149 }
1150 if (eq(cp, STRcentminus)(Strcmp(cp, STRcentminus) == 0) || eq(cp, STRcenthash)(Strcmp(cp, STRcenthash) == 0)) {
1151 if (pprevious == NULL((void *)0))
1152 stderror(ERR_NAME0x10000000 | ERR_JOBPREV60);
1153 return (pprevious);
1154 }
1155 if (Isdigit(cp[1])(((cp[1]) & 0100000U) ? 0 : isdigit((unsigned char) (cp[1
])))
) {
1156 const char *errstr;
1157 int idx = strtonum(short2str(cp + 1), 1, INT_MAX2147483647, &errstr);
1158
1159 if (errstr) {
1160 stderror(ERR_NAME0x10000000 | ERR_NOSUCHJOB46);
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_NAME0x10000000 | ERR_NOSUCHJOB46);
1167 return (0);
1168 }
1169 np = NULL((void *)0);
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_NAME0x10000000 | ERR_AMBIG40);
1186 np = pp;
1187 }
1188 }
1189 if (np)
1190 return (np);
1191 stderror(ERR_NAME0x10000000 | (cp[1] == '?' ? ERR_JOBPAT61 : ERR_NOSUCHJOB46));
1192 /* NOTREACHED */
1193 return (0);
1194}
1195
1196
1197/*
1198 * pgetcurr - find most recent job that is not pp, preferably stopped
1199 */
1200static struct process *
1201pgetcurr(struct process *pp)
1202{
1203 struct process *np;
1204 struct process *xp = NULL((void *)0);
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(1<<1))
1210 return (np);
1211 if (xp == NULL((void *)0))
1212 xp = np;
1213 }
1214 return (xp);
1215}
1216
1217/*
1218 * donotify - flag the job so as to report termination asynchronously
1219 */
1220void
1221/*ARGSUSED*/
1222donotify(Char **v, struct command *t)
1223{
1224 struct process *pp;
1225
1226 pp = pfind(*++v);
1227 pp->p_flags |= PNOTIFY(1<<5);
1228}
1229
1230/*
1231 * Do the fork and whatever should be done in the child side that
1232 * should not be done if we are not forking at all (like for simple builtin's)
1233 * Also do everything that needs any signals fiddled with in the parent side
1234 *
1235 * Wanttty tells whether process and/or tty pgrps are to be manipulated:
1236 * -1: leave tty alone; inherit pgrp from parent
1237 * 0: already have tty; manipulate process pgrps only
1238 * 1: want to claim tty; manipulate process and tty pgrps
1239 * It is usually just the value of tpgrp.
1240 */
1241
1242int
1243pfork(struct command *t, int wanttty)
1244{
1245 int pid;
1246 bool ignint = 0;
1247 int pgrp;
1248 sigset_t sigset, osigset;
1249
1250 /*
1251 * A child will be uninterruptible only under very special conditions.
1252 * Remember that the semantics of '&' is implemented by disconnecting the
1253 * process from the tty so signals do not need to ignored just for '&'.
1254 * Thus signals are set to default action for children unless: we have had
1255 * an "onintr -" (then specifically ignored) we are not playing with
1256 * signals (inherit action)
1257 */
1258 if (setintr)
1259 ignint = (tpgrp == -1 && (t->t_dflg & F_NOINTERRUPT(1<<5)))
1260 || (gointr && eq(gointr, STRminus)(Strcmp(gointr, STRminus) == 0));
1261 /*
1262 * Check for maximum nesting of 16 processes to avoid Forking loops
1263 */
1264 if (child == 16)
1265 stderror(ERR_NESTING62, 16);
1266 /*
1267 * Hold SIGCHLD until we have the process installed in our table.
1268 */
1269 sigemptyset(&sigset);
1270 sigaddset(&sigset, SIGCHLD20);
1271 sigprocmask(SIG_BLOCK1, &sigset, &osigset);
1272 while ((pid = fork()) == -1)
1273 if (setintr == 0)
1274 (void) sleep(FORKSLEEP10);
1275 else {
1276 sigprocmask(SIG_SETMASK3, &osigset, NULL((void *)0));
1277 stderror(ERR_NOPROC49);
1278 }
1279 if (pid == 0) {
1280 settimes();
1281 pgrp = pcurrjob ? pcurrjob->p_jobid : getpid();
1282 pflushall();
1283 pcurrjob = NULL((void *)0);
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(SIGINT2, ignint ? SIG_IGN(void (*)(int))1 : SIG_DFL(void (*)(int))0);
1292 (void) signal(SIGQUIT3, ignint ? SIG_IGN(void (*)(int))1 : SIG_DFL(void (*)(int))0);
1293 if (wanttty >= 0) {
1294 /* make stoppable */
1295 (void) signal(SIGTSTP18, SIG_DFL(void (*)(int))0);
1296 (void) signal(SIGTTIN21, SIG_DFL(void (*)(int))0);
1297 (void) signal(SIGTTOU22, SIG_DFL(void (*)(int))0);
1298 }
1299 (void) signal(SIGTERM15, parterm);
1300 }
1301 else if (tpgrp == -1 && (t->t_dflg & F_NOINTERRUPT(1<<5))) {
1302 (void) signal(SIGINT2, SIG_IGN(void (*)(int))1);
1303 (void) signal(SIGQUIT3, SIG_IGN(void (*)(int))1);
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(1<<12))
1312 (void) signal(SIGHUP1, SIG_IGN(void (*)(int))1);
1313 if (t->t_dflg & F_NICE(1<<11))
1314 (void) setpriority(PRIO_PROCESS0, 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_SETMASK3, &osigset, NULL((void *)0));
1321 }
1322
1323 return (pid);
1324}
1325
1326static void
1327okpcntl(void)
1328{
1329 if (tpgrp == -1)
1330 stderror(ERR_JOBCONTROL33);
1331 if (tpgrp == 0)
1332 stderror(ERR_JOBCTRLSUB63);
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 */
1343void
1344pgetty(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, SIGTSTP18);
1355 sigaddset(&sigset, SIGTTIN21);
1356 sigaddset(&sigset, SIGTTOU22);
1357 sigprocmask(SIG_BLOCK1, &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(FSHTTY15, pgrp);
1373 sigprocmask(SIG_SETMASK3, &osigset, NULL((void *)0));
1374 }
1375
1376 if (tpgrp > 0)
1377 tpgrp = 0; /* gave tty away */
1378}