fix
[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 first_arg first argument for argv (may be an empty string)
11  * @param ... more arguments, NULL terminated
12  * @return PID of the started process, -1 on error
13  */
14 static pid_t
15 do_start_process (const char *first_arg, ...)
16 {
17   va_list ap;
18   char **argv;
19   unsigned int argv_size;
20   const char *arg;
21   const char *rpos;
22   char *pos;
23   char *cp;
24   const char *last;
25   pid_t pid;
26
27   argv_size = 1;
28   va_start (ap, first_arg);
29   arg = first_arg;
30   last = NULL;
31   do
32     {
33       rpos = arg;
34       while ('\0' != *rpos)
35         {
36           if (' ' == *rpos)
37             {
38               if (last != NULL)
39                 argv_size++;
40               last = NULL;
41               while (' ' == *rpos)
42                 rpos++;
43             } 
44           if ( (last == NULL) && (*rpos != '\0') )
45             last = rpos;
46           if (*rpos != '\0')
47             rpos++;
48         }      
49       if (last != NULL)
50         argv_size++;
51     }
52   while (NULL != (arg = (va_arg (ap, const char*))));
53   va_end (ap);
54
55   argv = GNUNET_malloc (argv_size * sizeof (char *));
56   argv_size = 0;
57   va_start (ap, first_arg);
58   arg = first_arg;
59   last = NULL;
60   do
61     {
62       cp = GNUNET_strdup (arg);
63       pos = cp;
64       while ('\0' != *pos)
65         {
66           if (' ' == *pos)
67             {
68               *pos = '\0';
69               if (last != NULL)
70                 argv[argv_size++] = GNUNET_strdup (last);
71               last = NULL;
72               pos++;
73               while (' ' == *pos)
74                 pos++;
75             }
76           if ( (last == NULL) && (*pos != '\0') ) 
77             last = pos;
78           if (*pos != '\0')
79             pos++;
80         }
81       if (last != NULL)
82         argv[argv_size++] = GNUNET_strdup (last);
83       last = NULL;
84       GNUNET_free (cp);
85     }
86   while (NULL != (arg = (va_arg (ap, const char*))));
87   va_end (ap);
88   argv[argv_size] = NULL;
89   pid = GNUNET_OS_start_process_v (argv[0], argv);
90   while (argv_size > 0)
91     GNUNET_free (argv[--argv_size]);
92   GNUNET_free (argv);
93   return pid;
94 }