aboutsummaryrefslogtreecommitdiff
path: root/src/arm/do_start_process.c
blob: 139d0c42983c80908dbe662d02d1121d07601c76 (plain) (blame)
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
/**
 * 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 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 PID of the started process, -1 on error
 */
static struct GNUNET_OS_Process *
do_start_process (const int *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;
  do
    {
      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++;
    }
  while (NULL != (arg = (va_arg (ap, const char*))));
  va_end (ap);

  argv = GNUNET_malloc (argv_size * sizeof (char *));
  argv_size = 0;
  va_start (ap, first_arg);
  arg = first_arg;
  last = NULL;
  do
    {
      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);
    }
  while (NULL != (arg = (va_arg (ap, const char*))));
  va_end (ap);
  argv[argv_size] = NULL;
  proc = GNUNET_OS_start_process_v (lsocks, argv[0], argv);
  while (argv_size > 0)
    GNUNET_free (argv[--argv_size]);
  GNUNET_free (argv);
  return proc;
}