flac: Saner EOF handling
[cmus.git] / spawn.c
blob77f519aeabfe968ace34d766fd8d061792dd56cb
1 /*
2 * Copyright 2005 Timo Hirvonen
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
17 * 02111-1307, USA.
20 #include "spawn.h"
21 #include "file.h"
23 #include <sys/types.h>
24 #include <sys/wait.h>
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include <fcntl.h>
28 #include <errno.h>
30 int spawn(char *argv[], int *status)
32 pid_t pid;
33 int err_pipe[2];
35 if (pipe(err_pipe) == -1)
36 return -1;
38 pid = fork();
39 if (pid == -1) {
40 /* error */
41 return -1;
42 } else if (pid == 0) {
43 /* child */
44 int dev_null, err, i;
46 close(err_pipe[0]);
47 fcntl(err_pipe[1], F_SETFD, FD_CLOEXEC);
49 /* redirect stdout and stderr to /dev/null if possible */
50 dev_null = open("/dev/null", O_WRONLY);
51 if (dev_null != -1) {
52 dup2(dev_null, 1);
53 dup2(dev_null, 2);
56 /* not interactive, close stdin */
57 close(0);
59 /* close unused fds */
60 for (i = 3; i < 30; i++)
61 close(i);
63 execvp(argv[0], argv);
65 /* error */
66 err = errno;
67 write_all(err_pipe[1], &err, sizeof(int));
68 exit(1);
69 } else {
70 /* parent */
71 int rc, errno_save, child_errno;
73 close(err_pipe[1]);
74 rc = read_all(err_pipe[0], &child_errno, sizeof(int));
75 errno_save = errno;
76 close(err_pipe[0]);
78 waitpid(pid, status, 0);
80 if (rc == -1) {
81 errno = errno_save;
82 return -1;
84 if (rc == sizeof(int)) {
85 errno = child_errno;
86 return -1;
88 if (rc != 0) {
89 errno = EMSGSIZE;
90 return -1;
92 return 0;