File: command-exec.c

package info (click to toggle)
util-vserver 0.30.212-1
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 6,648 kB
  • ctags: 3,145
  • sloc: ansic: 19,781; sh: 13,258; xml: 1,618; makefile: 364; perl: 85
file content (86 lines) | stat: -rw-r--r-- 2,195 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
// $Id: command-exec.c 1957 2005-03-22 15:25:54Z ensc $    --*- c -*--

// Copyright (C) 2004 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
//  
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//  
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//  
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.


#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

#include "command.h"
#include "util.h"

#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <assert.h>

static inline bool
initPipes(int p[2])
{
  return (pipe(p)!=-1 &&
	  fcntl(p[1], F_SETFD, FD_CLOEXEC)!=-1);
}

bool
Command_exec(struct Command *cmd, bool do_fork)
{
  int		p[2];

  if (cmd->params_style_==parVEC)
    Vector_zeroEnd(&cmd->params.v);

  if (!do_fork)
    cmd->pid = 0;
  else if (!initPipes(p) ||
	   (cmd->pid = fork())==-1) {
    cmd->err = errno;
    return false;
  }
  
  if (cmd->pid==0) {
    char const **	argv = { 0 };
    
    if (do_fork) close(p[0]);

    switch (cmd->params_style_) {
      case parVEC	:  argv = cmd->params.v.data; break;
      case parDATA	:  argv = cmd->params.d;      break;
      default		:  break;
    }

    execv(cmd->filename ? cmd->filename : argv[0],
	  reinterpret_cast(char **const)(argv));
    cmd->err = errno;
    assert(cmd->err != 0);

    if (do_fork) {
      TEMP_FAILURE_RETRY(write(p[1], &cmd->err, sizeof(cmd->err)));
      _exit(1);	// implicates 'close(p[1])'
    }
  }
  else {
    close(p[1]);
    if (read(p[0], &cmd->err, sizeof(cmd->err))==0)
      cmd->err = 0;
    else	// cleanup zombies
      while (wait4(cmd->pid, 0,0,0)==-1 &&
	     (errno==EINTR || errno==EAGAIN)) {};
    close(p[0]);
  }

  return cmd->err==0;
}