process: New function process_search_path().
authorBen Pfaff <blp@nicira.com>
Fri, 20 Mar 2009 20:47:35 +0000 (13:47 -0700)
committerBen Pfaff <blp@nicira.com>
Fri, 20 Mar 2009 20:51:23 +0000 (13:51 -0700)
The process code already had the logic to search PATH for a file, but
it didn't export it, and it didn't return the executable that was found.
This exports it and returns the name, for the benefit of an upcoming
commit that wants to search the PATH for an executable only once per
program run.

lib/process.c
lib/process.h

index a06f5dc13e82e0b401d70c9559b1a73520ce3187..e27f6547ff1f34383c2d1d6222e74567998d37e0 100644 (file)
@@ -71,7 +71,6 @@ static void block_sigchld(sigset_t *);
 static void unblock_sigchld(const sigset_t *);
 static void sigchld_handler(int signr UNUSED);
 static bool is_member(int x, const int *array, size_t);
-static bool find_in_path(const char *name);
 
 /* Initializes the process subsystem (if it is not already initialized).  Calls
  * exit() if initialization fails.
@@ -152,6 +151,7 @@ process_start(char **argv,
               struct process **pp)
 {
     sigset_t oldsigs;
+    char *binary;
     pid_t pid;
 
     *pp = NULL;
@@ -165,10 +165,12 @@ process_start(char **argv,
 
     /* execvp() will search PATH too, but the error in that case is more
      * obscure, since it is only reported post-fork. */
-    if (!find_in_path(argv[0])) {
+    binary = process_search_path(argv[0]);
+    if (!binary) {
         VLOG_ERR("%s not found in PATH", argv[0]);
         return ENOENT;
     }
+    free(binary);
 
     block_sigchld(&oldsigs);
     pid = fork();
@@ -344,6 +346,31 @@ process_wait(struct process *p)
         poll_fd_wait(fds[0], POLLIN);
     }
 }
+
+char *
+process_search_path(const char *name)
+{
+    char *save_ptr = NULL;
+    char *path, *dir;
+    struct stat s;
+
+    if (strchr(name, '/') || !getenv("PATH")) {
+        return stat(name, &s) == 0 ? xstrdup(name) : NULL;
+    }
+
+    path = xstrdup(getenv("PATH"));
+    for (dir = strtok_r(path, ":", &save_ptr); dir;
+         dir = strtok_r(NULL, ":", &save_ptr)) {
+        char *file = xasprintf("%s/%s", dir, name);
+        if (stat(file, &s) == 0) {
+            free(path);
+            return file;
+        }
+        free(file);
+    }
+    free(path);
+    return NULL;
+}
 \f
 static void
 sigchld_handler(int signr UNUSED)
@@ -401,29 +428,3 @@ unblock_sigchld(const sigset_t *oldsigs)
         ofp_fatal(errno, "sigprocmask");
     }
 }
-
-static bool
-find_in_path(const char *name)
-{
-    char *save_ptr = NULL;
-    char *path, *dir;
-    struct stat s;
-
-    if (strchr(name, '/') || !getenv("PATH")) {
-        return stat(name, &s) == 0;
-    }
-
-    path = xstrdup(getenv("PATH"));
-    for (dir = strtok_r(path, ":", &save_ptr); dir;
-         dir = strtok_r(NULL, ":", &save_ptr)) {
-        char *file = xasprintf("%s/%s", dir, name);
-        if (stat(file, &s) == 0) {
-            free(file);
-            free(path);
-            return true;
-        }
-        free(file);
-    }
-    free(path);
-    return false;
-}
index ee7876e115329ae8d4ba6f4514bf584c5ebf2494..c47628cd586101473a5e1e596eeeae025dc5d783 100644 (file)
@@ -60,4 +60,6 @@ char *process_status_msg(int);
 
 void process_wait(struct process *);
 
+char *process_search_path(const char *);
+
 #endif /* process.h */