aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog.txt3
-rw-r--r--guts/execv.c4
-rw-r--r--guts/execve.c4
-rw-r--r--guts/execvp.c4
-rw-r--r--pseudo_client.c145
-rw-r--r--pseudo_client.h1
-rw-r--r--pseudo_util.c6
7 files changed, 160 insertions, 7 deletions
diff --git a/ChangeLog.txt b/ChangeLog.txt
index 6850e42..aea94d3 100644
--- a/ChangeLog.txt
+++ b/ChangeLog.txt
@@ -1,3 +1,6 @@
+2011-02-08:
+ * (seebs) Get full paths for exec*()
+
2011-01-24:
* (mhatle) Revert last result cache and related commits.
caching proved to be unreliable.
diff --git a/guts/execv.c b/guts/execv.c
index a72556b..15ad51e 100644
--- a/guts/execv.c
+++ b/guts/execv.c
@@ -13,7 +13,9 @@
* design will likely be revisited.
*/
if (antimagic == 0) {
- pseudo_client_op(OP_EXEC, PSA_EXEC, -1, -1, file, 0);
+ char *path_guess = pseudo_exec_path(file, 0);
+ pseudo_client_op(OP_EXEC, PSA_EXEC, -1, -1, path_guess, 0);
+ free(path_guess);
}
if (!pseudo_get_value("PSEUDO_RELOADED"))
diff --git a/guts/execve.c b/guts/execve.c
index fafc154..a47b9a7 100644
--- a/guts/execve.c
+++ b/guts/execve.c
@@ -14,7 +14,9 @@
* design will likely be revisited.
*/
if (antimagic == 0) {
- pseudo_client_op(OP_EXEC, PSA_EXEC, -1, -1, file, 0);
+ char *path_guess = pseudo_exec_path(file, 0);
+ pseudo_client_op(OP_EXEC, PSA_EXEC, -1, -1, path_guess, 0);
+ free(path_guess);
}
if (!pseudo_get_value("PSEUDO_RELOADED"))
diff --git a/guts/execvp.c b/guts/execvp.c
index a3ce05b..419f41b 100644
--- a/guts/execvp.c
+++ b/guts/execvp.c
@@ -14,7 +14,9 @@
* design will likely be revisited.
*/
if (antimagic == 0) {
- pseudo_client_op(OP_EXEC, PSA_EXEC, -1, -1, file, 0);
+ char *path_guess = pseudo_exec_path(file, 1);
+ pseudo_client_op(OP_EXEC, PSA_EXEC, -1, -1, path_guess, 0);
+ free(path_guess);
}
if (!pseudo_get_value("PSEUDO_RELOADED"))
diff --git a/pseudo_client.c b/pseudo_client.c
index e96cd31..507796f 100644
--- a/pseudo_client.c
+++ b/pseudo_client.c
@@ -1240,3 +1240,148 @@ pseudo_stat64_from32(struct stat64 *buf64, struct stat *buf) {
buf64->st_mtime = buf->st_mtime;
buf64->st_ctime = buf->st_ctime;
}
+
+/* stuff for handling paths and execs */
+static char *previous_path;
+static char *previous_path_segs;
+static char **path_segs;
+static size_t *path_lens;
+
+/* Makes an array of strings which are the path components
+ * of previous_path. Does this by duping the path, then replacing
+ * colons with null terminators, and storing the addresses of the
+ * starts of the substrings.
+ */
+static void
+populate_path_segs(void) {
+ size_t len = 0;
+ char *s;
+ int c;
+
+ free(path_segs);
+ free(previous_path_segs);
+ free(path_lens);
+ path_segs = NULL;
+ path_lens = NULL;
+ previous_path_segs = NULL;
+
+ if (!previous_path)
+ return;
+
+ for (s = previous_path; *s; ++s) {
+ if (*s == ':')
+ ++c;
+ }
+ path_segs = malloc((c+2) * sizeof(*path_segs));
+ if (!path_segs) {
+ pseudo_diag("warning: failed to allocate space for %d path segments.\n",
+ c);
+ return;
+ }
+ path_lens = malloc((c + 2) * sizeof(*path_lens));
+ if (!path_lens) {
+ pseudo_diag("warning: failed to allocate space for %d path lengths.\n",
+ c);
+ free(path_segs);
+ path_segs = 0;
+ return;
+ }
+ previous_path_segs = strdup(previous_path);
+ if (!previous_path_segs) {
+ pseudo_diag("warning: failed to allocate space for path copy.\n");
+ free(path_segs);
+ path_segs = NULL;
+ free(path_lens);
+ path_lens = NULL;
+ return;
+ }
+ c = 0;
+ path_segs[c++] = previous_path;
+ len = 0;
+ for (s = previous_path; *s; ++s) {
+ if (*s == ':') {
+ *s = '\0';
+ path_lens[c - 1] = len;
+ len = 0;
+ path_segs[c++] = s + 1;
+ } else {
+ ++len;
+ }
+ }
+ path_lens[c - 1] = len;
+ path_segs[c] = NULL;
+ path_lens[c] = 0;
+}
+
+char *
+pseudo_exec_path(const char *filename, int search_path) {
+ char *path = getenv("PATH");
+ char *candidate;
+ int i;
+ struct stat buf;
+
+ if (!filename)
+ return NULL;
+
+ pseudo_antimagic();
+ if (!path) {
+ free(path_segs);
+ free(previous_path);
+ path_segs = 0;
+ previous_path = 0;
+ } else if (!previous_path || strcmp(previous_path, path)) {
+ free(previous_path);
+ previous_path = strdup(path);
+ populate_path_segs();
+ }
+
+ /* absolute paths just get canonicalized. */
+ if (*filename == '/') {
+ candidate = pseudo_fix_path(NULL, filename, 0, 0, NULL, 0);
+ pseudo_magic();
+ return candidate;
+ }
+
+ if (!search_path) {
+ candidate = pseudo_fix_path(pseudo_cwd, filename, 0, pseudo_cwd_len, NULL, 0);
+ /* executable or not, it's the only thing we can try */
+ pseudo_magic();
+ return candidate;
+ }
+
+ for (i = 0; path_segs[i]; ++i) {
+ path = path_segs[i];
+ pseudo_debug(2, "exec_path: checking %s for %s\n", path, filename);
+ if (!*path || (*path == '.' && path_lens[i] == 1)) {
+ /* empty path or . is cwd */
+ candidate = pseudo_fix_path(pseudo_cwd, filename, 0, pseudo_cwd_len, NULL, 0);
+ pseudo_debug(2, "exec_path: in cwd, got %s\n", candidate);
+ } else if (*path == '/') {
+ candidate = pseudo_fix_path(path, filename, 0, path_lens[i], NULL, 0);
+ pseudo_debug(2, "exec_path: got %s\n", candidate);
+ } else {
+ /* oh you jerk, making me do extra work */
+ size_t len;
+ char *dir = pseudo_fix_path(pseudo_cwd, path, 0, pseudo_cwd_len, &len, 0);
+ if (dir) {
+ candidate = pseudo_fix_path(dir, filename, 0, len, NULL, 0);
+ pseudo_debug(2, "exec_path: got %s for non-absolute path\n", candidate);
+ } else {
+ pseudo_diag("couldn't allocate intermediate path.\n");
+ candidate = NULL;
+ }
+ free(dir);
+ }
+ if (candidate && !stat(candidate, &buf) && !S_ISDIR(buf.st_mode) && (buf.st_mode & 0111)) {
+ pseudo_debug(1, "exec_path: %s => %s\n", filename, candidate);
+ pseudo_magic();
+ return candidate;
+ } else {
+ free(candidate);
+ }
+ }
+ /* blind guess being as good as anything */
+ pseudo_magic();
+ return strdup(filename);
+}
+
diff --git a/pseudo_client.h b/pseudo_client.h
index 4dc13d0..44d697b 100644
--- a/pseudo_client.h
+++ b/pseudo_client.h
@@ -53,6 +53,7 @@ extern FILE *pseudo_grp;
extern int pseudo_client_getcwd(void);
extern int pseudo_client_chroot(const char *);
extern char *pseudo_root_path(const char *, int, int, const char *, int);
+extern char *pseudo_exec_path(const char *filename, int);
#define PSEUDO_ROOT_PATH(x, y, z) pseudo_root_path(__func__, __LINE__, (x), (y), (z));
extern char *pseudo_cwd;
extern size_t pseudo_cwd_len;
diff --git a/pseudo_util.c b/pseudo_util.c
index dc55b0c..704655e 100644
--- a/pseudo_util.c
+++ b/pseudo_util.c
@@ -590,11 +590,9 @@ pseudo_fix_path(const char *base, const char *path, size_t rootlen, size_t basel
*current = '\0';
/* at any given point:
* current points to just after the last / of newpath
- * path points to the next path element of path
+ * path points to the next element of path
* newpathlen is the total allocated length of newpath
- * (current - newpathlen) is the used length of newpath
- * oldpath is the starting point of path
- * (path - oldpath) is how far into path we are
+ * (current - newpath) is the used length of newpath
*/
if (pseudo_append_elements(&newpath, &effective_root, &newpathlen, &current, path, pathlen, leave_last) != -1) {
--current;