add :refresh command
[cmus.git] / spawn.c
blob7d253fbef203d8dc8e11b385b895fabec7889050
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;
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 execvp(argv[0], argv);
61 /* error */
62 err = errno;
63 write_all(err_pipe[1], &err, sizeof(int));
64 exit(1);
65 } else {
66 /* parent */
67 int rc, errno_save, child_errno;
69 close(err_pipe[1]);
70 rc = read_all(err_pipe[0], &child_errno, sizeof(int));
71 errno_save = errno;
72 close(err_pipe[0]);
74 waitpid(pid, status, 0);
76 if (rc == -1) {
77 errno = errno_save;
78 return -1;
80 if (rc == sizeof(int)) {
81 errno = child_errno;
82 return -1;
84 if (rc != 0) {
85 errno = EMSGSIZE;
86 return -1;
88 return 0;