-fixing #2546
[oweals/gnunet.git] / src / arm / do_start_process.c
1 /**
2  * Actually start a process.  All of the arguments given to this
3  * function are strings that are used for the "argv" array.  However,
4  * if those strings contain spaces, the given argument is split into
5  * multiple argv entries without spaces.  Similarly, if an argument is
6  * the empty string, it is skipped.  This function has the inherent
7  * limitation that it does NOT allow passing command line arguments
8  * with spaces to the new process.
9  *
10  * @param pipe_control should a pipe be used to send signals to the child?
11  * @param std_inheritance a set of GNUNET_OS_INHERIT_STD_* flags
12  * @param lsocks array of listen sockets to dup starting at fd3 (systemd-style), or NULL
13  * @param first_arg first argument for argv (may be an empty string)
14  * @param ... more arguments, NULL terminated
15  * @return handle of the started process, NULL on error
16  */
17 static struct GNUNET_OS_Process *
18 do_start_process (int pipe_control, unsigned int std_inheritance,
19                   const SOCKTYPE * lsocks, const char *first_arg, ...)
20 {
21   va_list ap;
22   char **argv;
23   unsigned int argv_size;
24   const char *arg;
25   const char *rpos;
26   char *pos;
27   char *cp;
28   const char *last;
29   struct GNUNET_OS_Process *proc;
30
31   argv_size = 1;
32   va_start (ap, first_arg);
33   arg = first_arg;
34   last = NULL;
35 /* *INDENT-OFF* */
36   do
37     {
38 /* *INDENT-ON* */
39   rpos = arg;
40   while ('\0' != *rpos)
41     {
42       if (' ' == *rpos)
43         {
44           if (last != NULL)
45             argv_size++;
46           last = NULL;
47           while (' ' == *rpos)
48             rpos++;
49         }
50       if ((last == NULL) && (*rpos != '\0'))
51         last = rpos;
52       if (*rpos != '\0')
53         rpos++;
54     }
55   if (last != NULL)
56     argv_size++;
57 /* *INDENT-OFF* */
58     }
59   while (NULL != (arg = (va_arg (ap, const char*))));
60 /* *INDENT-ON* */
61   va_end (ap);
62
63   argv = GNUNET_malloc (argv_size * sizeof (char *));
64   argv_size = 0;
65   va_start (ap, first_arg);
66   arg = first_arg;
67   last = NULL;
68 /* *INDENT-OFF* */
69   do
70     {
71 /* *INDENT-ON* */
72   cp = GNUNET_strdup (arg);
73   pos = cp;
74   while ('\0' != *pos)
75     {
76       if (' ' == *pos)
77         {
78           *pos = '\0';
79           if (last != NULL)
80             argv[argv_size++] = GNUNET_strdup (last);
81           last = NULL;
82           pos++;
83           while (' ' == *pos)
84             pos++;
85         }
86       if ((last == NULL) && (*pos != '\0'))
87         last = pos;
88       if (*pos != '\0')
89         pos++;
90     }
91   if (last != NULL)
92     argv[argv_size++] = GNUNET_strdup (last);
93   last = NULL;
94   GNUNET_free (cp);
95 /* *INDENT-OFF* */
96     }
97   while (NULL != (arg = (va_arg (ap, const char*))));
98 /* *INDENT-ON* */
99   va_end (ap);
100   argv[argv_size] = NULL;
101   proc = GNUNET_OS_start_process_v (pipe_control, std_inheritance, lsocks, argv[0], argv);
102   while (argv_size > 0)
103     GNUNET_free (argv[--argv_size]);
104   GNUNET_free (argv);
105   return proc;
106 }