- assert hard
[oweals/gnunet.git] / src / arm / do_start_process.c
1 /*
2      This file is part of GNUnet.
3      (C) 2011, 2012 Christian Grothoff (and other contributing authors)
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20
21 /**
22  * Actually start a process.  All of the arguments given to this
23  * function are strings that are used for the "argv" array.  However,
24  * if those strings contain spaces, the given argument is split into
25  * multiple argv entries without spaces.  Similarly, if an argument is
26  * the empty string, it is skipped.  This function has the inherent
27  * limitation that it does NOT allow passing command line arguments
28  * with spaces to the new process.
29  *
30  * @param pipe_control should a pipe be used to send signals to the child?
31  * @param std_inheritance a set of GNUNET_OS_INHERIT_STD_* flags
32  * @param lsocks array of listen sockets to dup starting at fd3 (systemd-style), or NULL
33  * @param first_arg first argument for argv (may be an empty string)
34  * @param ... more arguments, NULL terminated
35  * @return handle of the started process, NULL on error
36  */
37 static struct GNUNET_OS_Process *
38 do_start_process (int pipe_control, unsigned int std_inheritance,
39                   const SOCKTYPE * lsocks, const char *first_arg, ...)
40 {
41   va_list ap;
42   char **argv;
43   unsigned int argv_size;
44   const char *arg;
45   const char *rpos;
46   char *pos;
47   char *cp;
48   const char *last;
49   struct GNUNET_OS_Process *proc;
50   char *binary_path;
51
52   argv_size = 1;
53   va_start (ap, first_arg);
54   arg = first_arg;
55   last = NULL;
56 /* *INDENT-OFF* */
57   do
58     {
59 /* *INDENT-ON* */
60   rpos = arg;
61   while ('\0' != *rpos)
62     {
63       if (' ' == *rpos)
64         {
65           if (last != NULL)
66             argv_size++;
67           last = NULL;
68           while (' ' == *rpos)
69             rpos++;
70         }
71       if ((last == NULL) && (*rpos != '\0'))
72         last = rpos;
73       if (*rpos != '\0')
74         rpos++;
75     }
76   if (last != NULL)
77     argv_size++;
78 /* *INDENT-OFF* */
79     }
80   while (NULL != (arg = (va_arg (ap, const char*))));
81 /* *INDENT-ON* */
82   va_end (ap);
83
84   argv = GNUNET_malloc (argv_size * sizeof (char *));
85   argv_size = 0;
86   va_start (ap, first_arg);
87   arg = first_arg;
88   last = NULL;
89 /* *INDENT-OFF* */
90   do
91     {
92 /* *INDENT-ON* */
93   cp = GNUNET_strdup (arg);
94   pos = cp;
95   while ('\0' != *pos)
96     {
97       if (' ' == *pos)
98         {
99           *pos = '\0';
100           if (last != NULL)
101             argv[argv_size++] = GNUNET_strdup (last);
102           last = NULL;
103           pos++;
104           while (' ' == *pos)
105             pos++;
106         }
107       if ((last == NULL) && (*pos != '\0'))
108         last = pos;
109       if (*pos != '\0')
110         pos++;
111     }
112   if (last != NULL)
113     argv[argv_size++] = GNUNET_strdup (last);
114   last = NULL;
115   GNUNET_free (cp);
116 /* *INDENT-OFF* */
117     }
118   while (NULL != (arg = (va_arg (ap, const char*))));
119 /* *INDENT-ON* */
120   va_end (ap);
121   argv[argv_size] = NULL;
122   binary_path = argv[0];
123   proc = GNUNET_OS_start_process_v (pipe_control, std_inheritance, lsocks, 
124                                     binary_path, argv);
125   while (argv_size > 0)
126     GNUNET_free (argv[--argv_size]);
127   GNUNET_free (argv);
128   return proc;
129 }
130
131 /* end of do_start_process.c */