Bug Summary

File:src/bin/csh/sem.c
Warning:line 261, column 3
This assignment is prohibited after a successful vfork

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 sem.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/sem.c
1/* $OpenBSD: sem.c,v 1.23 2019/06/28 13:34:58 deraadt Exp $ */
2/* $NetBSD: sem.c,v 1.9 1995/09/27 00:38:50 jtc 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/stat.h>
35#include <errno(*__errno()).h>
36#include <fcntl.h>
37#include <stdlib.h>
38#include <string.h>
39#include <unistd.h>
40#include <limits.h>
41#include <stdarg.h>
42
43#include "csh.h"
44#include "proc.h"
45#include "extern.h"
46
47static void vffree(int);
48static Char *splicepipe(struct command *t, Char *);
49static void doio(struct command *t, int *, int *);
50static void chkclob(char *);
51
52void
53execute(struct command *t, int wanttty, int *pipein, int *pipeout)
54{
55 bool forked = 0;
56 struct biltins *bifunc;
57 int pid = 0;
58 int pv[2];
59 sigset_t sigset;
60
61 static sigset_t csigset;
62
63 static sigset_t ocsigset;
64 static int onosigchld = 0;
65 static int nosigchld = 0;
66
67 UNREGISTER(forked)(void) &forked;
68 UNREGISTER(bifunc)(void) &bifunc;
69 UNREGISTER(wanttty)(void) &wanttty;
70
71 if (t == 0)
1
Assuming 't' is not equal to null
2
Taking false branch
72 return;
73
74 if (t->t_dflg & F_AMPERSAND(1<<0))
3
Assuming the condition is false
4
Taking false branch
75 wanttty = 0;
76 switch (t->t_dtyp) {
5
Control jumps to 'case 1:' at line 78
77
78 case NODE_COMMAND1:
79 if ((t->t_dcom[0][0] & (QUOTE0100000U | TRIM0077777)) == QUOTE0100000U)
6
Assuming the condition is false
7
Taking false branch
80 (void) memmove(t->t_dcom[0], t->t_dcom[0] + 1,
81 (Strlen(t->t_dcom[0] + 1) + 1) * sizeof(Char));
82 if ((t->t_dflg & F_REPEAT(1<<10)) == 0)
8
Assuming the condition is false
9
Taking false branch
83 Dfix(t); /* $ " ' \ */
84 if (t->t_dcom[0] == 0)
10
Taking false branch
85 return;
86 /* fall into... */
87
88 case NODE_PAREN2:
89 if (t->t_dflg & F_PIPEOUT(1<<3))
11
Assuming the condition is false
12
Taking false branch
90 mypipe(pipeout);
91 /*
92 * Must do << early so parent will know where input pointer should be.
93 * If noexec then this is all we do.
94 */
95 if (t->t_dflg & F_READ(1<<9)) {
13
Assuming the condition is false
14
Taking false branch
96 (void) close(0);
97 heredoc(t->t_dlefL.T_dlef);
98 if (noexec)
99 (void) close(0);
100 }
101
102 set(STRstatus, Strsave(STR0));
103
104 /*
105 * This mess is the necessary kludge to handle the prefix builtins:
106 * nice, nohup, time. These commands can also be used by themselves,
107 * and this is not handled here. This will also work when loops are
108 * parsed.
109 */
110 while (t->t_dtyp == NODE_COMMAND1)
15
Loop condition is true. Entering loop body
111 if (eq(t->t_dcom[0], STRnice)(Strcmp(t->t_dcom[0], STRnice) == 0))
16
Assuming the condition is true
17
Taking true branch
112 if (t->t_dcom[1])
18
Assuming the condition is false
19
Taking false branch
113 if (strchr("+-", t->t_dcom[1][0]))
114 if (t->t_dcom[2]) {
115 setname("nice")(bname = ("nice"));
116 t->t_nice =
117 getn(t->t_dcom[1]);
118 lshift(t->t_dcom, 2);
119 t->t_dflg |= F_NICE(1<<11);
120 }
121 else
122 break;
123 else {
124 t->t_nice = 4;
125 lshift(t->t_dcom, 1);
126 t->t_dflg |= F_NICE(1<<11);
127 }
128 else
129 break;
20
Execution continues on line 148
130 else if (eq(t->t_dcom[0], STRnohup)(Strcmp(t->t_dcom[0], STRnohup) == 0))
131 if (t->t_dcom[1]) {
132 t->t_dflg |= F_NOHUP(1<<12);
133 lshift(t->t_dcom, 1);
134 }
135 else
136 break;
137 else if (eq(t->t_dcom[0], STRtime)(Strcmp(t->t_dcom[0], STRtime) == 0))
138 if (t->t_dcom[1]) {
139 t->t_dflg |= F_TIME(1<<13);
140 lshift(t->t_dcom, 1);
141 }
142 else
143 break;
144 else
145 break;
146
147 /* is it a command */
148 if (t->t_dtyp
20.1
Field 't_dtyp' is equal to NODE_COMMAND
== NODE_COMMAND1) {
21
Taking true branch
149 /*
150 * Check if we have a builtin function and remember which one.
151 */
152 bifunc = isbfunc(t);
153 if (noexec) {
22
Assuming 'noexec' is 0
23
Taking false branch
154 /*
155 * Continue for builtins that are part of the scripting language
156 */
157 if (bifunc &&
158 bifunc->bfunct != dobreak && bifunc->bfunct != docontin &&
159 bifunc->bfunct != doelse && bifunc->bfunct != doend &&
160 bifunc->bfunct != doforeach && bifunc->bfunct != dogoto &&
161 bifunc->bfunct != doif && bifunc->bfunct != dorepeat &&
162 bifunc->bfunct != doswbrk && bifunc->bfunct != doswitch &&
163 bifunc->bfunct != dowhile && bifunc->bfunct != dozip)
164 break;
165 }
166 }
167 else { /* not a command */
168 bifunc = NULL((void *)0);
169 if (noexec)
170 break;
171 }
172
173 /*
174 * We fork only if we are timed, or are not the end of a parenthesized
175 * list and not a simple builtin function. Simple meaning one that is
176 * not pipedout, niced, nohupped, or &'d. It would be nice(?) to not
177 * fork in some of these cases.
178 */
179 /*
180 * Prevent forking cd, pushd, popd, chdir cause this will cause the
181 * shell not to change dir!
182 */
183 if (bifunc && (bifunc->bfunct == dochngd ||
24
Assuming 'bifunc' is null
184 bifunc->bfunct == dopushd ||
185 bifunc->bfunct == dopopd))
186 t->t_dflg &= ~(F_NICE(1<<11));
187 if (((t->t_dflg & F_TIME(1<<13)) || ((t->t_dflg & F_NOFORK(1<<4)) == 0 &&
25
Assuming the condition is true
188 (!bifunc || t->t_dflg &
189 (F_PIPEOUT(1<<3) | F_AMPERSAND(1<<0) | F_NICE(1<<11) | F_NOHUP(1<<12))))) ||
190 /*
191 * We have to fork for eval too.
192 */
193 (bifunc && (t->t_dflg & (F_PIPEIN(1<<2) | F_PIPEOUT(1<<3))) != 0 &&
194 bifunc->bfunct == doeval)) {
195 if (t->t_dtyp == NODE_PAREN2 ||
26
Assuming field 't_dtyp' is not equal to NODE_PAREN
28
Taking false branch
196 t->t_dflg & (F_REPEAT(1<<10) | F_AMPERSAND(1<<0)) || bifunc
27.1
'bifunc' is null
) {
27
Assuming the condition is false
197 forked++;
198 /*
199 * We need to block SIGCHLD here, so that if the process does
200 * not die before we can set the process group
201 */
202 if (wanttty >= 0 && !nosigchld) {
203 sigemptyset(&sigset);
204 sigaddset(&sigset, SIGCHLD20);
205 sigprocmask(SIG_BLOCK1, &sigset, &csigset);
206 nosigchld = 1;
207 }
208
209 pid = pfork(t, wanttty);
210 if (pid == 0 && nosigchld) {
211 sigprocmask(SIG_SETMASK3, &csigset, NULL((void *)0));
212 nosigchld = 0;
213 }
214 else if (pid != 0 && (t->t_dflg & F_AMPERSAND(1<<0)))
215 backpid = pid;
216
217 }
218 else {
219 int ochild, osetintr, ohaderr, odidfds;
220 int oSHIN, oSHOUT, oSHERR, oOLDSTD, otpgrp;
221 sigset_t osigset;
222
223 /*
224 * Prepare for the vfork by saving everything that the child
225 * corrupts before it exec's. Note that in some signal
226 * implementations which keep the signal info in user space
227 * (e.g. Sun's) it will also be necessary to save and restore
228 * the current sigaction's for the signals the child touches
229 * before it exec's.
230 */
231 if (wanttty >= 0 && !nosigchld && !noexec) {
29
Assuming 'wanttty' is < 0
232 sigemptyset(&sigset);
233 sigaddset(&sigset, SIGCHLD20);
234 sigprocmask(SIG_BLOCK1, &sigset, &csigset);
235 nosigchld = 1;
236 }
237 sigemptyset(&sigset);
238 sigaddset(&sigset, SIGCHLD20);
239 sigaddset(&sigset, SIGINT2);
240 sigprocmask(SIG_BLOCK1, &sigset, &osigset);
241 ochild = child;
242 osetintr = setintr;
243 ohaderr = haderr;
244 odidfds = didfds;
245 oSHIN = SHIN;
246 oSHOUT = SHOUT;
247 oSHERR = SHERR;
248 oOLDSTD = OLDSTD;
249 otpgrp = tpgrp;
250 ocsigset = csigset;
251 onosigchld = nosigchld;
252 Vsav = Vdp = NULL((void *)0);
253 Vexpath = 0;
254 Vt = 0;
255 pid = vfork();
256
257 if (pid == -1) {
30
Taking false branch
258 sigprocmask(SIG_SETMASK3, &osigset, NULL((void *)0));
259 stderror(ERR_NOPROC49);
260 }
261 forked++;
31
This assignment is prohibited after a successful vfork
262 if (pid) { /* parent */
263 child = ochild;
264 setintr = osetintr;
265 haderr = ohaderr;
266 didfds = odidfds;
267 SHIN = oSHIN;
268 SHOUT = oSHOUT;
269 SHERR = oSHERR;
270 OLDSTD = oOLDSTD;
271 tpgrp = otpgrp;
272 csigset = ocsigset;
273 nosigchld = onosigchld;
274
275 free(Vsav);
276 Vsav = NULL((void *)0);
277 free(Vdp);
278 Vdp = NULL((void *)0);
279 free(Vexpath);
280 Vexpath = NULL((void *)0);
281 blkfree((Char **) Vt);
282 Vt = NULL((void *)0);
283 /* this is from pfork() */
284 palloc(pid, t);
285 sigprocmask(SIG_SETMASK3, &osigset, NULL((void *)0));
286 }
287 else { /* child */
288 /* this is from pfork() */
289 int pgrp;
290 bool ignint = 0;
291
292 if (nosigchld) {
293 sigprocmask(SIG_SETMASK3, &csigset, NULL((void *)0));
294 nosigchld = 0;
295 }
296
297 if (setintr)
298 ignint =
299 (tpgrp == -1 &&
300 (t->t_dflg & F_NOINTERRUPT(1<<5)))
301 || (gointr && eq(gointr, STRminus)(Strcmp(gointr, STRminus) == 0));
302 pgrp = pcurrjob ? pcurrjob->p_jobid : getpid();
303 child++;
304 if (setintr) {
305 setintr = 0;
306 if (ignint) {
307 (void) signal(SIGINT2, SIG_IGN(void (*)(int))1);
308 (void) signal(SIGQUIT3, SIG_IGN(void (*)(int))1);
309 }
310 else {
311 (void) signal(SIGINT2, vffree);
312 (void) signal(SIGQUIT3, SIG_DFL(void (*)(int))0);
313 }
314
315 if (wanttty >= 0) {
316 (void) signal(SIGTSTP18, SIG_DFL(void (*)(int))0);
317 (void) signal(SIGTTIN21, SIG_DFL(void (*)(int))0);
318 (void) signal(SIGTTOU22, SIG_DFL(void (*)(int))0);
319 }
320
321 (void) signal(SIGTERM15, parterm);
322 }
323 else if (tpgrp == -1 &&
324 (t->t_dflg & F_NOINTERRUPT(1<<5))) {
325 (void) signal(SIGINT2, SIG_IGN(void (*)(int))1);
326 (void) signal(SIGQUIT3, SIG_IGN(void (*)(int))1);
327 }
328
329 pgetty(wanttty, pgrp);
330 if (t->t_dflg & F_NOHUP(1<<12))
331 (void) signal(SIGHUP1, SIG_IGN(void (*)(int))1);
332 if (t->t_dflg & F_NICE(1<<11))
333 (void) setpriority(PRIO_PROCESS0, 0, t->t_nice);
334 }
335
336 }
337 }
338 if (pid != 0) {
339 /*
340 * It would be better if we could wait for the whole job when we
341 * knew the last process had been started. Pwait, in fact, does
342 * wait for the whole job anyway, but this test doesn't really
343 * express our intentions.
344 */
345 if (didfds == 0 && t->t_dflg & F_PIPEIN(1<<2)) {
346 (void) close(pipein[0]);
347 (void) close(pipein[1]);
348 }
349 if ((t->t_dflg & F_PIPEOUT(1<<3)) == 0) {
350 if (nosigchld) {
351 sigprocmask(SIG_SETMASK3, &csigset, NULL((void *)0));
352 nosigchld = 0;
353 }
354 if ((t->t_dflg & F_AMPERSAND(1<<0)) == 0)
355 pwait();
356 }
357 break;
358 }
359 doio(t, pipein, pipeout);
360 if (t->t_dflg & F_PIPEOUT(1<<3)) {
361 (void) close(pipeout[0]);
362 (void) close(pipeout[1]);
363 }
364 /*
365 * Perform a builtin function. If we are not forked, arrange for
366 * possible stopping
367 */
368 if (bifunc) {
369 func(t, bifunc);
370 if (forked)
371 exitstat();
372 break;
373 }
374 if (t->t_dtyp != NODE_PAREN2) {
375 doexec(NULL((void *)0), t);
376 /* NOTREACHED */
377 }
378 /*
379 * For () commands must put new 0,1,2 in FSH* and recurse
380 */
381 OLDSTD = dcopy(0, FOLDSTD19);
382 SHOUT = dcopy(1, FSHOUT17);
383 SHERR = dcopy(2, FSHERR18);
384 (void) close(SHIN);
385 SHIN = -1;
386 didfds = 0;
387 wanttty = -1;
388 t->t_dspr->t_dflg |= t->t_dflg & F_NOINTERRUPT(1<<5);
389 execute(t->t_dspr, wanttty, NULL((void *)0), NULL((void *)0));
390 exitstat();
391
392 case NODE_PIPE3:
393 t->t_dcarL.T_dcar->t_dflg |= F_PIPEOUT(1<<3) |
394 (t->t_dflg & (F_PIPEIN(1<<2) | F_AMPERSAND(1<<0) | F_STDERR(1<<7) | F_NOINTERRUPT(1<<5)));
395 execute(t->t_dcarL.T_dcar, wanttty, pipein, pv);
396 t->t_dcdrR.T_dcdr->t_dflg |= F_PIPEIN(1<<2) | (t->t_dflg &
397 (F_PIPEOUT(1<<3) | F_AMPERSAND(1<<0) | F_NOFORK(1<<4) | F_NOINTERRUPT(1<<5)));
398 if (wanttty > 0)
399 wanttty = 0; /* got tty already */
400 execute(t->t_dcdrR.T_dcdr, wanttty, pv, pipeout);
401 break;
402
403 case NODE_LIST4:
404 if (t->t_dcarL.T_dcar) {
405 t->t_dcarL.T_dcar->t_dflg |= t->t_dflg & F_NOINTERRUPT(1<<5);
406 execute(t->t_dcarL.T_dcar, wanttty, NULL((void *)0), NULL((void *)0));
407 /*
408 * In strange case of A&B make a new job after A
409 */
410 if (t->t_dcarL.T_dcar->t_dflg & F_AMPERSAND(1<<0) && t->t_dcdrR.T_dcdr &&
411 (t->t_dcdrR.T_dcdr->t_dflg & F_AMPERSAND(1<<0)) == 0)
412 pendjob();
413 }
414 if (t->t_dcdrR.T_dcdr) {
415 t->t_dcdrR.T_dcdr->t_dflg |= t->t_dflg &
416 (F_NOFORK(1<<4) | F_NOINTERRUPT(1<<5));
417 execute(t->t_dcdrR.T_dcdr, wanttty, NULL((void *)0), NULL((void *)0));
418 }
419 break;
420
421 case NODE_OR5:
422 case NODE_AND6:
423 if (t->t_dcarL.T_dcar) {
424 t->t_dcarL.T_dcar->t_dflg |= t->t_dflg & F_NOINTERRUPT(1<<5);
425 execute(t->t_dcarL.T_dcar, wanttty, NULL((void *)0), NULL((void *)0));
426 if ((getn(value(STRstatus)value1(STRstatus, &shvhed)) == 0) !=
427 (t->t_dtyp == NODE_AND6))
428 return;
429 }
430 if (t->t_dcdrR.T_dcdr) {
431 t->t_dcdrR.T_dcdr->t_dflg |= t->t_dflg &
432 (F_NOFORK(1<<4) | F_NOINTERRUPT(1<<5));
433 execute(t->t_dcdrR.T_dcdr, wanttty, NULL((void *)0), NULL((void *)0));
434 }
435 break;
436 }
437 /*
438 * Fall through for all breaks from switch
439 *
440 * If there will be no more executions of this command, flush all file
441 * descriptors. Places that turn on the F_REPEAT bit are responsible for
442 * doing donefds after the last re-execution
443 */
444 if (didfds && !(t->t_dflg & F_REPEAT(1<<10)))
445 donefds();
446}
447
448static void
449vffree(int i)
450{
451 _exit(i);
452}
453
454/*
455 * Expand and glob the words after an i/o redirection.
456 * If more than one word is generated, then update the command vector.
457 *
458 * This is done differently in all the shells:
459 * 1. in the bourne shell and ksh globbing is not performed
460 * 2. Bash/csh say ambiguous
461 * 3. zsh does i/o to/from all the files
462 * 4. itcsh concatenates the words.
463 *
464 * I don't know what is best to do. I think that Ambiguous is better
465 * than restructuring the command vector, because the user can get
466 * unexpected results. In any case, the command vector restructuring
467 * code is present and the user can choose it by setting noambiguous
468 */
469static Char *
470splicepipe(struct command *t, Char *cp) /* word after < or > */
471{
472 Char *blk[2];
473
474 if (adrof(STRnoambiguous)adrof1(STRnoambiguous, &shvhed)) {
475 Char **pv;
476
477 blk[0] = Dfix1(cp); /* expand $ */
478 blk[1] = NULL((void *)0);
479
480 gflag = 0, tglob(blk);
481 if (gflag) {
482 pv = globall(blk);
483 if (pv == NULL((void *)0)) {
484 setname(vis_str(blk[0]))(bname = (vis_str(blk[0])));
485 free(blk[0]);
486 stderror(ERR_NAME0x10000000 | ERR_NOMATCH50);
487 }
488 gargv = NULL((void *)0);
489 if (pv[1] != NULL((void *)0)) { /* we need to fix the command vector */
490 Char **av = blkspl(t->t_dcom, &pv[1]);
491 free(t->t_dcom);
492 t->t_dcom = av;
493 }
494 free(blk[0]);
495 blk[0] = pv[0];
496 free(pv);
497 }
498 }
499 else {
500 blk[0] = globone(blk[1] = Dfix1(cp), G_ERROR0);
501 free(blk[1]);
502 }
503 return(blk[0]);
504}
505
506/*
507 * Perform io redirection.
508 * We may or maynot be forked here.
509 */
510static void
511doio(struct command *t, int *pipein, int *pipeout)
512{
513 int fd;
514 Char *cp;
515 int flags = t->t_dflg;
516
517 if (didfds || (flags & F_REPEAT(1<<10)))
518 return;
519 if ((flags & F_READ(1<<9)) == 0) {/* F_READ already done */
520 if (t->t_dlefL.T_dlef) {
521 char tmp[PATH_MAX1024];
522
523 /*
524 * so < /dev/std{in,out,err} work
525 */
526 (void) dcopy(SHIN, 0);
527 (void) dcopy(SHOUT, 1);
528 (void) dcopy(SHERR, 2);
529 cp = splicepipe(t, t->t_dlefL.T_dlef);
530 strlcpy(tmp, short2str(cp), sizeof tmp);
531 free(cp);
532 if ((fd = open(tmp, O_RDONLY0x0000)) == -1)
533 stderror(ERR_SYSTEM55, tmp, strerror(errno(*__errno())));
534 (void) dmove(fd, 0);
535 }
536 else if (flags & F_PIPEIN(1<<2)) {
537 (void) close(0);
538 (void) dup(pipein[0]);
539 (void) close(pipein[0]);
540 (void) close(pipein[1]);
541 }
542 else if ((flags & F_NOINTERRUPT(1<<5)) && tpgrp == -1) {
543 (void) close(0);
544 (void) open(_PATH_DEVNULL"/dev/null", O_RDONLY0x0000);
545 }
546 else {
547 (void) close(0);
548 (void) dup(OLDSTD);
549 (void) fcntl(STDIN_FILENO0, F_SETFD2, 0);
550 }
551 }
552 if (t->t_dritR.T_drit) {
553 char tmp[PATH_MAX1024];
554
555 cp = splicepipe(t, t->t_dritR.T_drit);
556 strlcpy(tmp, short2str(cp), sizeof tmp);
557 free(cp);
558 /*
559 * so > /dev/std{out,err} work
560 */
561 (void) dcopy(SHOUT, 1);
562 (void) dcopy(SHERR, 2);
563 if ((flags & F_APPEND(1<<1)) &&
564 (fd = open(tmp, O_WRONLY0x0001 | O_APPEND0x0008)) >= 0);
565 else {
566 if (!(flags & F_OVERWRITE(1<<8)) && adrof(STRnoclobber)adrof1(STRnoclobber, &shvhed)) {
567 if (flags & F_APPEND(1<<1))
568 stderror(ERR_SYSTEM55, tmp, strerror(errno(*__errno())));
569 chkclob(tmp);
570 }
571 if ((fd = open(tmp, O_WRONLY0x0001 | O_CREAT0x0200 | O_TRUNC0x0400, 0666)) == -1)
572 stderror(ERR_SYSTEM55, tmp, strerror(errno(*__errno())));
573 }
574 (void) dmove(fd, 1);
575 }
576 else if (flags & F_PIPEOUT(1<<3)) {
577 (void) close(1);
578 (void) dup(pipeout[1]);
579 }
580 else {
581 (void) close(1);
582 (void) dup(SHOUT);
583 (void) fcntl(STDOUT_FILENO1, F_SETFD2, 0);
584 }
585
586 (void) close(2);
587 if (flags & F_STDERR(1<<7)) {
588 (void) dup(1);
589 }
590 else {
591 (void) dup(SHERR);
592 (void) fcntl(STDERR_FILENO2, F_SETFD2, 0);
593 }
594 didfds = 1;
595}
596
597void
598mypipe(int *pv)
599{
600
601 if (pipe(pv) == -1)
602 goto oops;
603 pv[0] = dmove(pv[0], -1);
604 pv[1] = dmove(pv[1], -1);
605 if (pv[0] >= 0 && pv[1] >= 0)
606 return;
607oops:
608 stderror(ERR_PIPE54);
609}
610
611static void
612chkclob(char *cp)
613{
614 struct stat stb;
615
616 if (stat(cp, &stb) == -1)
617 return;
618 if (S_ISCHR(stb.st_mode)((stb.st_mode & 0170000) == 0020000))
619 return;
620 stderror(ERR_EXISTS41, cp);
621}