1 /***********************************************************************
2 * *
3 * This software is part of the ast package *
4 * Copyright (c) 1985-2010 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Common Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
8 * *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
12 * *
13 * Information and Software Systems Research *
14 * AT&T Research *
15 * Florham Park NJ *
16 * *
17 * Glenn Fowler <gsf@research.att.com> *
18 * David Korn <dgk@research.att.com> *
19 * Phong Vo <kpv@research.att.com> *
20 * *
21 ***********************************************************************/
22 #pragma prototyped
23 /*
24 * Glenn Fowler
25 * AT&T Research
26 *
27 * common process execution support with
28 * proper sfio, signal and wait() syncronization
29 *
30 * _ contains the process path name and is
31 * placed at the top of the environment
32 */
33
34 #include "proclib.h"
35
36 #include <ls.h>
37
38 /*
39 * not quite ready for _use_spawnveg
40 */
41
42 #if _use_spawnveg && _lib_fork
43 #undef _use_spawnveg
44 #endif
45
46 #ifndef DEBUG_PROC
47 #define DEBUG_PROC 1
48 #endif
49
50 #if _lib_socketpair
51 #if _sys_socket
52 #include <sys/types.h>
53 #include <sys/socket.h>
54 #else
55 #undef _lib_socketpair
56 #endif
57 #endif
58
59 Proc_t proc_default = { -1 };
60
61 #if DEBUG_PROC
62
63 #include <namval.h>
64
65 #define PROC_ENV_OPTIONS "PROC_OPTIONS"
66
67 #define PROC_OPT_ENVIRONMENT (1<<0)
68 #define PROC_OPT_EXEC (1<<1)
69 #define PROC_OPT_TRACE (1<<2)
70 #define PROC_OPT_VERBOSE (1<<3)
71
72 static const Namval_t options[] =
73 {
74 "debug", PROC_OPT_VERBOSE,
75 "environment", PROC_OPT_ENVIRONMENT,
76 "exec", PROC_OPT_EXEC,
77 "trace", PROC_OPT_TRACE,
78 "verbose", PROC_OPT_VERBOSE,
79 0, 0
80 };
81
82 /*
83 * called by stropt() to set options
84 */
85
86 static int
setopt(register void * a,register const void * p,register int n,const char * v)87 setopt(register void* a, register const void* p, register int n, const char* v)
88 {
89 NoP(v);
90 if (p)
91 {
92 if (n)
93 *((int*)a) |= ((Namval_t*)p)->value;
94 else
95 *((int*)a) &= ~((Namval_t*)p)->value;
96 }
97 return 0;
98 }
99
100 #endif
101
102 #if _use_spawnveg
103
104 typedef struct Fd_s
105 {
106 short fd;
107 short flag;
108 } Fd_t;
109
110 typedef struct Mod_s
111 {
112 struct Mod_s* next;
113 short op;
114 short save;
115
116 union
117 {
118
119 struct
120 {
121 Fd_t parent;
122 Fd_t child;
123 } fd;
124
125 Handler_t handler;
126
127 } arg;
128
129 } Modify_t;
130
131 #endif
132
133 #ifdef SIGPIPE
134
135 /*
136 * catch but ignore sig
137 * avoids SIG_IGN being passed to children
138 */
139
140 static void
ignoresig(int sig)141 ignoresig(int sig)
142 {
143 signal(sig, ignoresig);
144 }
145
146 #endif
147
148 /*
149 * do modification op and save previous state for restore()
150 */
151
152 static int
modify(Proc_t * proc,int forked,int op,long arg1,long arg2)153 modify(Proc_t* proc, int forked, int op, long arg1, long arg2)
154 {
155 #if _lib_fork
156 if (forked)
157 {
158 switch (op)
159 {
160 case PROC_fd_dup:
161 case PROC_fd_dup|PROC_FD_PARENT:
162 case PROC_fd_dup|PROC_FD_CHILD:
163 case PROC_fd_dup|PROC_FD_PARENT|PROC_FD_CHILD:
164 if (arg1 != arg2)
165 {
166 if (arg2 != PROC_ARG_NULL)
167 {
168 close(arg2);
169 if (fcntl(arg1, F_DUPFD, arg2) != arg2)
170 return -1;
171 }
172 if (op & PROC_FD_CHILD)
173 close(arg1);
174 }
175 break;
176 case PROC_sig_dfl:
177 signal(arg1, SIG_DFL);
178 break;
179 case PROC_sig_ign:
180 signal(arg1, SIG_IGN);
181 break;
182 case PROC_sys_pgrp:
183 if (arg1 < 0)
184 setsid();
185 else if (arg1 > 0)
186 {
187 if (arg1 == 1)
188 arg1 = 0;
189 if (setpgid(0, arg1) < 0 && arg1 && errno == EPERM)
190 setpgid(0, 0);
191 }
192 break;
193 case PROC_sys_umask:
194 umask(arg1);
195 break;
196 default:
197 return -1;
198 }
199 }
200 #if _use_spawnveg
201 else
202 #endif
203 #else
204 NoP(forked);
205 #endif
206 #if _use_spawnveg
207 {
208 register Modify_t* m;
209
210 if (!(m = newof(NiL, Modify_t, 1, 0)))
211 return -1;
212 m->next = proc->mods;
213 proc->mods = m;
214 switch (m->op = op)
215 {
216 case PROC_fd_dup:
217 case PROC_fd_dup|PROC_FD_PARENT:
218 case PROC_fd_dup|PROC_FD_CHILD:
219 case PROC_fd_dup|PROC_FD_PARENT|PROC_FD_CHILD:
220 m->arg.fd.parent.fd = (short)arg1;
221 m->arg.fd.parent.flag = fcntl(arg1, F_GETFD, 0);
222 if ((m->arg.fd.child.fd = (short)arg2) != arg1)
223 {
224 if (arg2 != PROC_ARG_NULL)
225 {
226 m->arg.fd.child.flag = fcntl(arg2, F_GETFD, 0);
227 if ((m->save = fcntl(arg2, F_DUPFD, 3)) < 0)
228 {
229 m->op = 0;
230 return -1;
231 }
232 fcntl(m->save, F_SETFD, FD_CLOEXEC);
233 close(arg2);
234 if (fcntl(arg1, F_DUPFD, arg2) != arg2)
235 return -1;
236 if (op & PROC_FD_CHILD)
237 close(arg1);
238 }
239 else if (op & PROC_FD_CHILD)
240 {
241 if (m->arg.fd.parent.flag)
242 break;
243 fcntl(arg1, F_SETFD, FD_CLOEXEC);
244 }
245 else if (!m->arg.fd.parent.flag)
246 break;
247 else
248 fcntl(arg1, F_SETFD, 0);
249 return 0;
250 }
251 break;
252 case PROC_sig_dfl:
253 if ((m->arg.handler = signal(arg1, SIG_DFL)) == SIG_DFL)
254 break;
255 m->save = (short)arg1;
256 return 0;
257 case PROC_sig_ign:
258 if ((m->arg.handler = signal(arg1, SIG_IGN)) == SIG_IGN)
259 break;
260 m->save = (short)arg1;
261 return 0;
262 case PROC_sys_pgrp:
263 proc->pgrp = arg1;
264 break;
265 case PROC_sys_umask:
266 if ((m->save = (short)umask(arg1)) == arg1)
267 break;
268 return 0;
269 default:
270 proc->mods = m->next;
271 free(m);
272 return -1;
273 }
274 proc->mods = m->next;
275 free(m);
276 }
277 #else
278 NoP(proc);
279 #endif
280 return 0;
281 }
282
283 #if _use_spawnveg
284
285 /*
286 * restore modifications
287 */
288
289 static void
restore(Proc_t * proc)290 restore(Proc_t* proc)
291 {
292 register Modify_t* m;
293 register Modify_t* p;
294 int oerrno;
295
296 NoP(proc);
297 oerrno = errno;
298 m = proc->mods;
299 proc->mods = 0;
300 while (m)
301 {
302 switch (m->op)
303 {
304 case PROC_fd_dup:
305 case PROC_fd_dup|PROC_FD_PARENT:
306 case PROC_fd_dup|PROC_FD_CHILD:
307 case PROC_fd_dup|PROC_FD_PARENT|PROC_FD_CHILD:
308 if (m->op & PROC_FD_PARENT)
309 close(m->arg.fd.parent.fd);
310 if (m->arg.fd.child.fd != m->arg.fd.parent.fd && m->arg.fd.child.fd != PROC_ARG_NULL)
311 {
312 if (!(m->op & PROC_FD_PARENT))
313 {
314 if (m->op & PROC_FD_CHILD)
315 {
316 close(m->arg.fd.parent.fd);
317 fcntl(m->arg.fd.child.fd, F_DUPFD, m->arg.fd.parent.fd);
318 }
319 fcntl(m->arg.fd.parent.fd, F_SETFD, m->arg.fd.parent.flag);
320 }
321 close(m->arg.fd.child.fd);
322 fcntl(m->save, F_DUPFD, m->arg.fd.child.fd);
323 close(m->save);
324 if (m->arg.fd.child.flag)
325 fcntl(m->arg.fd.child.fd, F_SETFD, FD_CLOEXEC);
326 }
327 else if ((m->op & (PROC_FD_PARENT|PROC_FD_CHILD)) == PROC_FD_CHILD)
328 fcntl(m->arg.fd.parent.fd, F_SETFD, 0);
329 break;
330 case PROC_sig_dfl:
331 case PROC_sig_ign:
332 signal(m->save, m->arg.handler);
333 break;
334 case PROC_sys_umask:
335 umask(m->save);
336 break;
337 }
338 p = m;
339 m = m->next;
340 free(p);
341 }
342 errno = oerrno;
343 }
344
345 #else
346
347 #define restore(p)
348
349 #endif
350
351 /*
352 * fork and exec or spawn proc(argv) and return a Proc_t handle
353 *
354 * pipe not used when PROC_READ|PROC_WRITE omitted
355 * argv==0 duplicates current process if possible
356 * cmd==0 names the current shell
357 * cmd=="" does error cleanup
358 * envv is the child environment
359 * modv is the child modification vector of PROC_*() ops
360 */
361
362 Proc_t*
procopen(const char * cmd,char ** argv,char ** envv,long * modv,int flags)363 procopen(const char* cmd, char** argv, char** envv, long* modv, int flags)
364 {
365 register Proc_t* proc = 0;
366 register int procfd;
367 register char** p;
368 char** v;
369 int i;
370 int forked = 0;
371 int signalled = 0;
372 long n;
373 char path[PATH_MAX];
374 char env[PATH_MAX + 2];
375 int pio[2];
376 #if !_pipe_rw && !_lib_socketpair
377 int poi[2];
378 #endif
379 #if defined(SIGCHLD) && ( _lib_sigprocmask || _lib_sigsetmask )
380 Sig_mask_t mask;
381 #endif
382 #if _use_spawnveg
383 int newenv = 0;
384 #endif
385 #if DEBUG_PROC
386 int debug = PROC_OPT_EXEC;
387 #endif
388
389 #if _lib_fork
390 if (!argv && (flags & PROC_OVERLAY))
391 #else
392 if (!argv)
393 #endif
394 {
395 errno = ENOEXEC;
396 return 0;
397 }
398 pio[0] = pio[1] = -1;
399 #if !_pipe_rw && !_lib_socketpair
400 poi[0] = poi[1] = -1;
401 #endif
402 if (cmd && (!*cmd || !pathpath(path, cmd, NiL, PATH_REGULAR|PATH_EXECUTE)))
403 goto bad;
404 switch (flags & (PROC_READ|PROC_WRITE))
405 {
406 case 0:
407 procfd = -1;
408 break;
409 case PROC_READ:
410 procfd = 1;
411 break;
412 case PROC_WRITE:
413 procfd = 0;
414 break;
415 case PROC_READ|PROC_WRITE:
416 procfd = 2;
417 break;
418 }
419 if (proc_default.pid == -1)
420 proc = &proc_default;
421 else if (!(proc = newof(0, Proc_t, 1, 0)))
422 goto bad;
423 proc->pid = -1;
424 proc->pgrp = 0;
425 proc->rfd = -1;
426 proc->wfd = -1;
427 proc->flags = flags;
428 sfsync(NiL);
429 if (environ && envv != (char**)environ && (envv || (flags & PROC_PARANOID) || argv && (environ[0][0] != '_' || environ[0][1] != '=')))
430 {
431 if (!setenviron(NiL))
432 goto bad;
433 #if _use_spawnveg
434 newenv = 1;
435 #endif
436 }
437 if (procfd >= 0)
438 {
439 #if _pipe_rw
440 if (pipe(pio))
441 goto bad;
442 #else
443 if (procfd > 1)
444 {
445 #if _lib_socketpair
446 if (socketpair(AF_UNIX, SOCK_STREAM, 0, pio))
447 goto bad;
448 #else
449 if (pipe(pio) || pipe(poi))
450 goto bad;
451 #endif
452 }
453 else if (pipe(pio))
454 goto bad;
455 #endif
456 }
457 if (flags & PROC_OVERLAY)
458 {
459 proc->pid = 0;
460 forked = 1;
461 }
462 #if _use_spawnveg
463 else if (argv)
464 proc->pid = 0;
465 #endif
466 #if _lib_fork
467 else
468 {
469 if (!(flags & PROC_FOREGROUND))
470 sigcritical(SIG_REG_EXEC|SIG_REG_PROC);
471 else
472 {
473 signalled = 1;
474 proc->sigint = signal(SIGINT, SIG_IGN);
475 proc->sigquit = signal(SIGQUIT, SIG_IGN);
476 #if defined(SIGCHLD)
477 #if _lib_sigprocmask
478 sigemptyset(&mask);
479 sigaddset(&mask, SIGCHLD);
480 sigprocmask(SIG_BLOCK, &mask, &proc->mask);
481 #else
482 #if _lib_sigsetmask
483 mask = sigmask(SIGCHLD);
484 proc->mask = sigblock(mask);
485 #else
486 proc->sigchld = signal(SIGCHLD, SIG_DFL);
487 #endif
488 #endif
489 #endif
490 }
491 proc->pid = fork();
492 if (!(flags & PROC_FOREGROUND))
493 sigcritical(0);
494 else if (!proc->pid)
495 {
496 if (proc->sigint != SIG_IGN)
497 {
498 proc->sigint = SIG_DFL;
499 signal(SIGINT, proc->sigint);
500 }
501 if (proc->sigquit != SIG_IGN)
502 {
503 proc->sigquit = SIG_DFL;
504 signal(SIGQUIT, proc->sigquit);
505 }
506 #if defined(SIGCHLD)
507 #if _lib_sigprocmask
508 sigprocmask(SIG_SETMASK, &proc->mask, NiL);
509 #else
510 #if _lib_sigsetmask
511 sigsetmask(proc->mask);
512 #else
513 if (proc->sigchld != SIG_IGN)
514 signal(SIGCHLD, SIG_DFL);
515 #endif
516 #endif
517 #endif
518 }
519 else if (proc->pid == -1)
520 goto bad;
521 forked = 1;
522 }
523 #endif
524 if (!proc->pid)
525 {
526 #if _use_spawnveg
527 char** oenviron = 0;
528 char* oenviron0 = 0;
529
530 v = 0;
531 #endif
532 #if DEBUG_PROC
533 stropt(getenv(PROC_ENV_OPTIONS), options, sizeof(*options), setopt, &debug);
534 #if _lib_fork
535 if (debug & PROC_OPT_TRACE)
536 {
537 if (!fork())
538 {
539 sfsprintf(path, sizeof(path), "%d", getppid());
540 execlp("trace", "trace", "-p", path, NiL);
541 _exit(EXIT_NOTFOUND);
542 }
543 sleep(2);
544 }
545 #endif
546 #endif
547 if (flags & PROC_DAEMON)
548 {
549 #ifdef SIGHUP
550 modify(proc, forked, PROC_sig_ign, SIGHUP, 0);
551 #endif
552 modify(proc, forked, PROC_sig_dfl, SIGTERM, 0);
553 #ifdef SIGTSTP
554 modify(proc, forked, PROC_sig_ign, SIGTSTP, 0);
555 #endif
556 #ifdef SIGTTIN
557 modify(proc, forked, PROC_sig_ign, SIGTTIN, 0);
558 #endif
559 #ifdef SIGTTOU
560 modify(proc, forked, PROC_sig_ign, SIGTTOU, 0);
561 #endif
562 }
563 if (flags & (PROC_BACKGROUND|PROC_DAEMON))
564 {
565 modify(proc, forked, PROC_sig_ign, SIGINT, 0);
566 #ifdef SIGQUIT
567 modify(proc, forked, PROC_sig_ign, SIGQUIT, 0);
568 #endif
569 }
570 if (flags & (PROC_DAEMON|PROC_SESSION))
571 modify(proc, forked, PROC_sys_pgrp, -1, 0);
572 if (forked || (flags & PROC_OVERLAY))
573 {
574 if ((flags & PROC_PRIVELEGED) && !geteuid())
575 {
576 setuid(geteuid());
577 setgid(getegid());
578 }
579 if (flags & (PROC_PARANOID|PROC_GID))
580 setgid(getgid());
581 if (flags & (PROC_PARANOID|PROC_UID))
582 setuid(getuid());
583 }
584 if (procfd > 1)
585 {
586 if (modify(proc, forked, PROC_fd_dup|PROC_FD_CHILD, pio[0], PROC_ARG_NULL))
587 goto cleanup;
588 if (modify(proc, forked, PROC_fd_dup|PROC_FD_CHILD, pio[1], 1))
589 goto cleanup;
590 #if _pipe_rw || _lib_socketpair
591 if (modify(proc, forked, PROC_fd_dup, 1, 0))
592 goto cleanup;
593 #else
594 if (modify(proc, forked, PROC_fd_dup|PROC_FD_CHILD, poi[0], 0))
595 goto cleanup;
596 if (poi[1] != 0 && modify(proc, forked, PROC_fd_dup|PROC_FD_CHILD, poi[1], PROC_ARG_NULL))
597 goto cleanup;
598 #endif
599 }
600 else if (procfd >= 0)
601 {
602 if (modify(proc, forked, PROC_fd_dup|PROC_FD_CHILD, pio[!!procfd], !!procfd))
603 goto cleanup;
604 if (pio[!procfd] != !!procfd && modify(proc, forked, PROC_fd_dup|PROC_FD_CHILD, pio[!procfd], PROC_ARG_NULL))
605 goto cleanup;
606 }
607 if (modv)
608 for (i = 0; n = modv[i]; i++)
609 switch (PROC_OP(n))
610 {
611 case PROC_fd_dup:
612 case PROC_fd_dup|PROC_FD_PARENT:
613 case PROC_fd_dup|PROC_FD_CHILD:
614 case PROC_fd_dup|PROC_FD_PARENT|PROC_FD_CHILD:
615 if (modify(proc, forked, PROC_OP(n), PROC_ARG(n, 1), PROC_ARG(n, 2)))
616 goto cleanup;
617 break;
618 default:
619 if (modify(proc, forked, PROC_OP(n), PROC_ARG(n, 1), 0))
620 goto cleanup;
621 break;
622 }
623 #if _lib_fork
624 if (forked && (flags & PROC_ENVCLEAR))
625 environ = 0;
626 #if _use_spawnveg
627 else
628 #endif
629 #endif
630 #if _use_spawnveg
631 if (newenv)
632 {
633 p = environ;
634 while (*p++);
635 if (!(oenviron = (char**)memdup(environ, (p - environ) * sizeof(char*))))
636 goto cleanup;
637 }
638 #endif
639 if (argv && envv != (char**)environ)
640 {
641 #if _use_spawnveg
642 if (!newenv && environ[0][0] == '_' && environ[0][1] == '=')
643 oenviron0 = environ[0];
644 #endif
645 env[0] = '_';
646 env[1] = '=';
647 env[2] = 0;
648 if (!setenviron(env))
649 goto cleanup;
650 }
651 if ((flags & PROC_PARANOID) && setenv("PATH", astconf("PATH", NiL, NiL), 1))
652 goto cleanup;
653 if ((p = envv) && p != (char**)environ)
654 while (*p)
655 if (!setenviron(*p++))
656 goto cleanup;
657 p = argv;
658 #if _lib_fork
659 if (forked && !p)
660 return proc;
661 #endif
662 #if DEBUG_PROC
663 if (!(debug & PROC_OPT_EXEC) || (debug & PROC_OPT_VERBOSE))
664 {
665 if ((debug & PROC_OPT_ENVIRONMENT) && (p = environ))
666 while (*p)
667 sfprintf(sfstderr, "%s\n", *p++);
668 sfprintf(sfstderr, "+ %s", cmd ? path : "sh");
669 if ((p = argv) && *p)
670 while (*++p)
671 sfprintf(sfstderr, " %s", *p);
672 sfprintf(sfstderr, "\n");
673 sfsync(sfstderr);
674 if (!(debug & PROC_OPT_EXEC))
675 _exit(0);
676 p = argv;
677 }
678 #endif
679 if (cmd)
680 {
681 strcpy(env + 2, path);
682 if (forked || (flags & PROC_OVERLAY))
683 execve(path, p, environ);
684 #if _use_spawnveg
685 else if ((proc->pid = spawnveg(path, p, environ, proc->pgrp)) != -1)
686 goto cleanup;
687 #endif
688 if (errno != ENOEXEC)
689 goto cleanup;
690
691 /*
692 * try cmd as a shell script
693 */
694
695 if (!(flags & PROC_ARGMOD))
696 {
697 while (*p++);
698 if (!(v = newof(0, char*, p - argv + 2, 0)))
699 goto cleanup;
700 p = v + 2;
701 if (*argv)
702 argv++;
703 while (*p++ = *argv++);
704 p = v + 1;
705 }
706 *p = path;
707 *--p = "sh";
708 }
709 strcpy(env + 2, (flags & PROC_PARANOID) ? astconf("SH", NiL, NiL) : pathshell());
710 if (forked || (flags & PROC_OVERLAY))
711 execve(env + 2, p, environ);
712 #if _use_spawnveg
713 else
714 proc->pid = spawnveg(env + 2, p, environ, proc->pgrp);
715 #endif
716 cleanup:
717 if (forked)
718 {
719 if (!(flags & PROC_OVERLAY))
720 _exit(errno == ENOENT ? EXIT_NOTFOUND : EXIT_NOEXEC);
721 goto bad;
722 }
723 #if _use_spawnveg
724 if (v)
725 free(v);
726 if (p = oenviron)
727 {
728 environ = 0;
729 while (*p)
730 if (!setenviron(*p++))
731 goto bad;
732 free(oenviron);
733 }
734 else if (oenviron0)
735 environ[0] = oenviron0;
736 restore(proc);
737 if (flags & PROC_OVERLAY)
738 exit(0);
739 #endif
740 }
741 if (proc->pid != -1)
742 {
743 if (!forked)
744 {
745 if (flags & PROC_FOREGROUND)
746 {
747 signalled = 1;
748 proc->sigint = signal(SIGINT, SIG_IGN);
749 proc->sigquit = signal(SIGQUIT, SIG_IGN);
750 #if defined(SIGCHLD)
751 #if _lib_sigprocmask
752 sigemptyset(&mask);
753 sigaddset(&mask, SIGCHLD);
754 sigprocmask(SIG_BLOCK, &mask, &proc->mask);
755 #else
756 #if _lib_sigsetmask
757 mask = sigmask(SIGCHLD);
758 proc->mask = sigblock(mask);
759 #else
760 proc->sigchld = signal(SIGCHLD, SIG_DFL);
761 #endif
762 #endif
763 #endif
764 }
765 }
766 else if (modv)
767 for (i = 0; n = modv[i]; i++)
768 switch (PROC_OP(n))
769 {
770 case PROC_fd_dup|PROC_FD_PARENT:
771 case PROC_fd_dup|PROC_FD_PARENT|PROC_FD_CHILD:
772 close(PROC_ARG(n, 1));
773 break;
774 case PROC_sys_pgrp:
775 if (proc->pgrp < 0)
776 proc->pgrp = proc->pid;
777 else if (proc->pgrp > 0)
778 {
779 if (proc->pgrp == 1)
780 proc->pgrp = proc->pid;
781 if (setpgid(proc->pid, proc->pgrp) < 0 && proc->pid != proc->pgrp && errno == EPERM)
782 setpgid(proc->pid, proc->pid);
783 }
784 break;
785 }
786 if (procfd >= 0)
787 {
788 #ifdef SIGPIPE
789 if ((flags & (PROC_WRITE|PROC_IGNORE)) == (PROC_WRITE|PROC_IGNORE))
790 {
791 Handler_t handler;
792
793 if ((handler = signal(SIGPIPE, ignoresig)) != SIG_DFL && handler != ignoresig)
794 signal(SIGPIPE, handler);
795 }
796 #endif
797 switch (procfd)
798 {
799 case 0:
800 proc->wfd = pio[1];
801 close(pio[0]);
802 break;
803 default:
804 #if _pipe_rw || _lib_socketpair
805 proc->wfd = pio[0];
806 #else
807 proc->wfd = poi[1];
808 close(poi[0]);
809 #endif
810 /*FALLTHROUGH*/
811 case 1:
812 proc->rfd = pio[0];
813 close(pio[1]);
814 break;
815 }
816 if (proc->rfd > 2)
817 fcntl(proc->rfd, F_SETFD, FD_CLOEXEC);
818 if (proc->wfd > 2)
819 fcntl(proc->wfd, F_SETFD, FD_CLOEXEC);
820 }
821 if (!proc->pid)
822 proc->pid = getpid();
823 return proc;
824 }
825 bad:
826 if (signalled)
827 {
828 if (proc->sigint != SIG_IGN)
829 signal(SIGINT, proc->sigint);
830 if (proc->sigquit != SIG_IGN)
831 signal(SIGQUIT, proc->sigquit);
832 #if defined(SIGCHLD)
833 #if _lib_sigprocmask
834 sigprocmask(SIG_SETMASK, &proc->mask, NiL);
835 #else
836 #if _lib_sigsetmask
837 sigsetmask(proc->mask);
838 #else
839 if (proc->sigchld != SIG_DFL)
840 signal(SIGCHLD, proc->sigchld);
841 #endif
842 #endif
843 #endif
844 }
845 if ((flags & PROC_CLEANUP) && modv)
846 for (i = 0; n = modv[i]; i++)
847 switch (PROC_OP(n))
848 {
849 case PROC_fd_dup:
850 case PROC_fd_dup|PROC_FD_PARENT:
851 case PROC_fd_dup|PROC_FD_CHILD:
852 case PROC_fd_dup|PROC_FD_PARENT|PROC_FD_CHILD:
853 if (PROC_ARG(n, 2) != PROC_ARG_NULL)
854 close(PROC_ARG(n, 1));
855 break;
856 }
857 if (pio[0] >= 0)
858 close(pio[0]);
859 if (pio[1] >= 0)
860 close(pio[1]);
861 #if !_pipe_rw && !_lib_socketpair
862 if (poi[0] >= 0)
863 close(poi[0]);
864 if (poi[1] >= 0)
865 close(poi[1]);
866 #endif
867 procfree(proc);
868 return 0;
869 }
870