minor optimizations
[util-vserver.git] / util-vserver / lib_internal / command-exec.c
1 // $Id$    --*- c -*--
2
3 // Copyright (C) 2004 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
4 //  
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; version 2 of the License.
8 //  
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // GNU General Public License for more details.
13 //  
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 02111-1307, USA.
17
18
19 #ifdef HAVE_CONFIG_H
20 #  include <config.h>
21 #endif
22
23 #include "command.h"
24
25 #include <unistd.h>
26 #include <fcntl.h>
27 #include <errno.h>
28 #include <assert.h>
29
30 static inline bool
31 initPipes(int p[2])
32 {
33   return (pipe(p)!=-1 &&
34           fcntl(p[1], F_SETFD, FD_CLOEXEC)!=-1);
35 }
36
37 bool
38 Command_exec(struct Command *cmd, bool do_fork)
39 {
40   int           p[2];
41
42   Vector_zeroEnd(&cmd->params);
43
44   if (!do_fork)
45     cmd->pid = 0;
46   else if (!initPipes(p) ||
47            (cmd->pid = fork())==-1) {
48     cmd->err = errno;
49     return false;
50   }
51   
52   if (cmd->pid==0) {
53     if (do_fork) close(p[0]);
54
55     execv(cmd->filename ? cmd->filename : ((char **)(Vector_begin(&cmd->params)))[0],
56           cmd->params.data);
57     cmd->err = errno;
58     assert(cmd->err != 0);
59
60     if (do_fork) {
61       write(p[1], &cmd->err, sizeof(cmd->err));
62       _exit(1); // implicates 'close(p[1])'
63     }
64   }
65   else {
66     close(p[1]);
67     if (read(p[0], &cmd->err, sizeof(cmd->err))==0)
68       cmd->err = 0;
69     else        // cleanup zombies
70       while (wait4(cmd->pid, 0,0,0)==-1 &&
71              (errno==EINTR || errno==EAGAIN)) {};
72     close(p[0]);
73   }
74
75   return cmd->err==0;
76 }