small cleanup.
[ardour.git] / libs / vfork / exec_wrapper.c
1 #include <stdio.h>
2 #include <unistd.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <fcntl.h>
6 #include <signal.h>
7
8 #ifndef STDIN_FILENO
9 #define STDIN_FILENO 0
10 #endif
11 #ifndef STDOUT_FILENO
12 #define STDOUT_FILENO 1
13 #endif
14 #ifndef STDERR_FILENO
15 #define STDERR_FILENO 2
16 #endif
17
18 extern char **environ;
19 static void close_fd (int *fd) { if ((*fd) >= 0) close (*fd); *fd = -1; }
20
21 int main(int argc, char *argv[]) {
22         if (argc < 10) {
23                 // TODO: if argv > 3, assume pok[] is given, notifify parent.
24                 // usage() and a man-page (help2man) would not be bad, either :)
25                 return -1;
26         }
27
28         int pok[2];
29         int pin[2];
30         int pout[2];
31
32         pok[0]  = atoi(argv[1]);
33         pok[1]  = atoi(argv[2]);
34         pin[0]  = atoi(argv[3]);
35         pin[1]  = atoi(argv[4]);
36         pout[0] = atoi(argv[5]);
37         pout[1] = atoi(argv[6]);
38
39         int stderr_mode = atoi(argv[7]);
40         int nicelevel = atoi(argv[8]);
41
42         /* vfork()ed child process - exec external process */
43         close_fd(&pok[0]);
44         fcntl(pok[1], F_SETFD, FD_CLOEXEC);
45
46         close_fd(&pin[1]);
47         if (pin[0] != STDIN_FILENO) {
48                 dup2(pin[0], STDIN_FILENO);
49         }
50         close_fd(&pin[0]);
51         close_fd(&pout[0]);
52         if (pout[1] != STDOUT_FILENO) {
53                 dup2(pout[1], STDOUT_FILENO);
54         }
55
56         if (stderr_mode == 2) {
57                 /* merge STDERR into output */
58                 if (pout[1] != STDERR_FILENO) {
59                         dup2(pout[1], STDERR_FILENO);
60                 }
61         } else if (stderr_mode == 1) {
62                 /* ignore STDERR */
63                 close(STDERR_FILENO);
64         } else {
65                 /* keep STDERR */
66         }
67
68         if (pout[1] != STDOUT_FILENO && pout[1] != STDERR_FILENO) {
69                 close_fd(&pout[1]);
70         }
71
72         if (nicelevel !=0) {
73                 nice(nicelevel);
74         }
75
76         /* copy current environment */
77         char **envp = NULL;
78         int i=0;
79         envp = (char **) calloc(1, sizeof(char*));
80         for (i=0;environ[i];++i) {
81                 envp[i] = strdup(environ[i]);
82                 envp = (char **) realloc(envp, (i+2) * sizeof(char*));
83         }
84         envp[i] = 0;
85
86 #ifdef HAVE_SIGSET
87         sigset(SIGPIPE, SIG_DFL);
88 #else
89         signal(SIGPIPE, SIG_DFL);
90 #endif
91
92         /* all systems go */
93         execve(argv[9], &argv[9], envp);
94
95         /* if we reach here something went wrong.. */
96         char buf = 0;
97         (void) write(pok[1], &buf, 1 );
98         close_fd(&pok[1]);
99         return -1;
100 }