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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
|
/**
* Actually start a process. All of the arguments given to this
* function are strings that are used for the "argv" array. However,
* if those strings contain spaces, the given argument is split into
* multiple argv entries without spaces. Similarly, if an argument is
* the empty string, it is skipped. This function has the inherent
* limitation that it does NOT allow passing command line arguments
* with spaces to the new process.
*
* @param pipe_control should a pipe be used to send signals to the child?
* @param lsocks array of listen sockets to dup starting at fd3 (systemd-style), or NULL
* @param first_arg first argument for argv (may be an empty string)
* @param ... more arguments, NULL terminated
* @return handle of the started process, NULL on error
*/
static struct GNUNET_OS_Process *
do_start_process (int pipe_control,
const SOCKTYPE * lsocks, const char *first_arg, ...)
{
va_list ap;
char **argv;
unsigned int argv_size;
const char *arg;
const char *rpos;
char *pos;
char *cp;
const char *last;
struct GNUNET_OS_Process *proc;
argv_size = 1;
va_start (ap, first_arg);
arg = first_arg;
last = NULL;
/* *INDENT-OFF* */
do
{
/* *INDENT-ON* */
rpos = arg;
while ('\0' != *rpos)
{
if (' ' == *rpos)
{
if (last != NULL)
argv_size++;
last = NULL;
while (' ' == *rpos)
rpos++;
}
if ((last == NULL) && (*rpos != '\0'))
last = rpos;
if (*rpos != '\0')
rpos++;
}
if (last != NULL)
argv_size++;
/* *INDENT-OFF* */
}
while (NULL != (arg = (va_arg (ap, const char*))));
/* *INDENT-ON* */
va_end (ap);
argv = GNUNET_malloc (argv_size * sizeof (char *));
argv_size = 0;
va_start (ap, first_arg);
arg = first_arg;
last = NULL;
/* *INDENT-OFF* */
do
{
/* *INDENT-ON* */
cp = GNUNET_strdup (arg);
pos = cp;
while ('\0' != *pos)
{
if (' ' == *pos)
{
*pos = '\0';
if (last != NULL)
argv[argv_size++] = GNUNET_strdup (last);
last = NULL;
pos++;
while (' ' == *pos)
pos++;
}
if ((last == NULL) && (*pos != '\0'))
last = pos;
if (*pos != '\0')
pos++;
}
if (last != NULL)
argv[argv_size++] = GNUNET_strdup (last);
last = NULL;
GNUNET_free (cp);
/* *INDENT-OFF* */
}
while (NULL != (arg = (va_arg (ap, const char*))));
/* *INDENT-ON* */
va_end (ap);
argv[argv_size] = NULL;
proc = GNUNET_OS_start_process_v (pipe_control, lsocks, argv[0], argv);
while (argv_size > 0)
GNUNET_free (argv[--argv_size]);
GNUNET_free (argv);
return proc;
}
|