+/* Prepare to start a process whose command-line arguments are given by the
+ * null-terminated 'argv' array. Returns 0 if successful, otherwise a
+ * positive errno value. */
+static int
+process_prestart(char **argv)
+{
+ char *binary;
+
+ process_init();
+
+ /* Log the process to be started. */
+ if (VLOG_IS_DBG_ENABLED()) {
+ char *args = process_escape_args(argv);
+ VLOG_DBG("starting subprocess: %s", args);
+ free(args);
+ }
+
+ /* execvp() will search PATH too, but the error in that case is more
+ * obscure, since it is only reported post-fork. */
+ binary = process_search_path(argv[0]);
+ if (!binary) {
+ VLOG_ERR("%s not found in PATH", argv[0]);
+ return ENOENT;
+ }
+ free(binary);
+
+ return 0;
+}
+
+/* Creates and returns a new struct process with the specified 'name' and
+ * 'pid'.
+ *
+ * This is racy unless SIGCHLD is blocked (and has been blocked since before
+ * the fork()) that created the subprocess. */
+static struct process *
+process_register(const char *name, pid_t pid)
+{
+ struct process *p;
+ const char *slash;
+
+ assert(sigchld_is_blocked());
+
+ p = xcalloc(1, sizeof *p);
+ p->pid = pid;
+ slash = strrchr(name, '/');
+ p->name = xstrdup(slash ? slash + 1 : name);
+ p->exited = false;
+
+ list_push_back(&all_processes, &p->node);
+
+ return p;
+}
+