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