]> git.cworth.org Git - apitrace/blobdiff - common/os_posix.cpp
Abstract execv().
[apitrace] / common / os_posix.cpp
index e797220189f4373f27198ef46ad6b12eb42bd304..da7878311a72f970a309fd11a3f3c5cf90fddc58 100644 (file)
 
 #include <unistd.h>
 #include <sys/time.h>
+#include <sys/wait.h>
 #include <pthread.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <signal.h>
 
+#if defined(__linux__)
+#include <linux/limits.h> // PATH_MAX
+#endif
+
 #ifdef __APPLE__
+#include <sys/syslimits.h> // PATH_MAX
 #include <mach-o/dyld.h>
 #endif
 
+#ifndef PATH_MAX
+#warning PATH_MAX undefined
+#define PATH_MAX 4096
+#endif
+
 #include "os.hpp"
+#include "os_path.hpp"
 
 
 namespace os {
@@ -64,55 +76,92 @@ releaseMutex(void)
 }
 
 
-bool
-getProcessName(char *str, size_t size)
+Path
+getProcessName(void)
 {
-    char szProcessPath[PATH_MAX + 1];
-    char *lpProcessName;
+    Path path;
+    size_t size = PATH_MAX;
+    char *buf = path.buf(size);
 
     // http://stackoverflow.com/questions/1023306/finding-current-executables-path-without-proc-self-exe
 #ifdef __APPLE__
-    uint32_t len = sizeof szProcessPath;
-    if (_NSGetExecutablePath(szProcessPath, &len) != 0) {
-        *str = 0;
-        return false;
+    uint32_t len = size;
+    if (_NSGetExecutablePath(buf, &len) != 0) {
+        *buf = 0;
+        return path;
     }
+    len = strlen(buf);
 #else
     ssize_t len;
-    len = readlink("/proc/self/exe", szProcessPath, sizeof(szProcessPath) - 1);
+    len = readlink("/proc/self/exe", buf, size - 1);
     if (len == -1) {
         // /proc/self/exe is not available on setuid processes, so fallback to
         // /proc/self/cmdline.
         int fd = open("/proc/self/cmdline", O_RDONLY);
         if (fd >= 0) {
-            len = read(fd, szProcessPath, sizeof(szProcessPath) - 1);
+            len = read(fd, buf, size - 1);
             close(fd);
         }
     }
     if (len <= 0) {
-        snprintf(str, size, "%i", (int)getpid());
-        return true;
+        snprintf(buf, size, "%i", (int)getpid());
+        return path;
     }
 #endif
-    szProcessPath[len] = 0;
+    path.truncate(len);
 
-    lpProcessName = strrchr(szProcessPath, '/');
-    lpProcessName = lpProcessName ? lpProcessName + 1 : szProcessPath;
+    return path;
+}
 
-    strncpy(str, lpProcessName, size);
-    if (size)
-        str[size - 1] = 0;
+Path
+getCurrentDir(void)
+{
+    Path path;
+    size_t size = PATH_MAX;
+    char *buf = path.buf(size);
+
+    getcwd(buf, size);
+    buf[size - 1] = 0;
+    
+    path.truncate();
+    return path;
+}
+
+bool
+Path::exists(void) const
+{
+    struct stat st;
+    int err;
+
+    err = stat(str(), &st);
+    if (err) {
+        return false;
+    }
+
+    if (!S_ISREG(st.st_mode))
+        return false;
 
     return true;
 }
 
-bool
-getCurrentDir(char *str, size_t size)
+int execute(char * const * args)
 {
-    char *ret;
-    ret = getcwd(str, size);
-    str[size - 1] = 0;
-    return ret ? true : false;
+    pid_t pid = fork();
+    if (pid == 0) {
+        // child
+        execvp(args[0], args);
+        fprintf(stderr, "error: failed to execute %s\n", args[0]);
+        exit(-1);
+    } else {
+        // parent
+        if (pid == -1) {
+            fprintf(stderr, "error: failed to fork\n");
+            return -1;
+        }
+        int status = -1;
+        waitpid(pid, &status, 0);
+        return status;
+    }
 }
 
 void