Commit Diff


commit - 23594da913ed0592b12a675484709d8ab5c1ca07
commit + 0ee7065d8d7e2f4c85b8e806bda98645435f08ac
blob - 0aeb6274d0d70a65e99f8604a5078a551ecd2f8f
blob + 23370a0ae3daea7b02c31c7e2a767bf51d0ba581
--- got/got.c
+++ got/got.c
@@ -197,27 +197,33 @@ usage(void)
 }
 
 static const struct got_error *
-get_editor(char **editorp)
+get_editor(char **abspath)
 {
+	const struct got_error *err = NULL;
 	const char *editor;
 
 	editor = getenv("VISUAL");
 	if (editor == NULL)
 		editor = getenv("EDITOR");
-	if (editor == NULL)
-		editor = "/bin/ed";
 
-	*editorp = realpath(editor, NULL);
-	if (*editorp == NULL)
-		return got_error_from_errno("relpath");
+	if (editor) {
+		err = got_path_find_prog(abspath, editor);
+		if (err)
+			return err;
+	}
 
+	if (*abspath == NULL) {
+		*abspath = strdup("/bin/ed");
+		if (*abspath == NULL)
+			return got_error_from_errno("strdup");
+	}
+
 	return NULL;
 }
 
 static const struct got_error *
 apply_unveil(const char *repo_path, int repo_read_only,
-    const char *worktree_path, int create_worktree,
-    int unveil_editor)
+    const char *worktree_path, int create_worktree, char **editor)
 {
 	const struct got_error *err;
 	static char err_msg[MAXPATHLEN + 36];
@@ -243,17 +249,16 @@ apply_unveil(const char *repo_path, int repo_read_only
 			return err;
 	}
 
-	if (unveil_editor) {
-		char *editor;
-		err = get_editor(&editor);
+	if (editor) {
+		err = get_editor(editor);
 		if (err)
 			return err;
-		if (unveil(editor, "x") != 0) {
-			err = got_error_from_errno2("unveil", editor);
-			free(editor);
+		if (unveil(*editor, "x") != 0) {
+			err = got_error_from_errno2("unveil", *editor);
+			free(*editor);
+			*editor = NULL;
 			return err;
 		}
-		free(editor);
 	}
 
 	if (repo_path && unveil(repo_path, repo_read_only ? "r" : "rwc") != 0)
@@ -437,7 +442,8 @@ cmd_checkout(int argc, char *argv[])
 	if (error != NULL)
 		goto done;
 
-	error = apply_unveil(got_repo_get_path(repo), 0, worktree_path, 1, 0);
+	error = apply_unveil(got_repo_get_path(repo), 0, worktree_path, 1,
+	    NULL);
 	if (error)
 		goto done;
 
@@ -575,7 +581,7 @@ cmd_update(int argc, char *argv[])
 		goto done;
 
 	error = apply_unveil(got_repo_get_path(repo), 0,
-	    got_worktree_get_root_path(worktree), 0, 0);
+	    got_worktree_get_root_path(worktree), 0, NULL);
 	if (error)
 		goto done;
 
@@ -947,7 +953,7 @@ cmd_log(int argc, char *argv[])
 		goto done;
 
 	error = apply_unveil(got_repo_get_path(repo), 1,
-	    worktree ? got_worktree_get_root_path(worktree) : NULL, 0, 0);
+	    worktree ? got_worktree_get_root_path(worktree) : NULL, 0, NULL);
 	if (error)
 		goto done;
 
@@ -1209,7 +1215,7 @@ cmd_diff(int argc, char *argv[])
 		goto done;
 
 	error = apply_unveil(got_repo_get_path(repo), 1,
-	    worktree ? got_worktree_get_root_path(worktree) : NULL, 0, 0);
+	    worktree ? got_worktree_get_root_path(worktree) : NULL, 0, NULL);
 	if (error)
 		goto done;
 
@@ -1369,7 +1375,7 @@ cmd_blame(int argc, char *argv[])
 	if (error != NULL)
 		goto done;
 
-	error = apply_unveil(got_repo_get_path(repo), 1, NULL, 0, 0);
+	error = apply_unveil(got_repo_get_path(repo), 1, NULL, 0, NULL);
 	if (error)
 		goto done;
 
@@ -1597,7 +1603,7 @@ cmd_tree(int argc, char *argv[])
 	if (error != NULL)
 		goto done;
 
-	error = apply_unveil(got_repo_get_path(repo), 1, NULL, 0, 0);
+	error = apply_unveil(got_repo_get_path(repo), 1, NULL, 0, NULL);
 	if (error)
 		goto done;
 
@@ -1726,7 +1732,7 @@ cmd_status(int argc, char *argv[])
 		goto done;
 
 	error = apply_unveil(got_repo_get_path(repo), 1,
-	    got_worktree_get_root_path(worktree), 0, 0);
+	    got_worktree_get_root_path(worktree), 0, NULL);
 	if (error)
 		goto done;
 
@@ -1897,7 +1903,7 @@ cmd_ref(int argc, char *argv[])
 		goto done;
 
 	error = apply_unveil(got_repo_get_path(repo), do_list,
-	    worktree ? got_worktree_get_root_path(worktree) : NULL, 0, 0);
+	    worktree ? got_worktree_get_root_path(worktree) : NULL, 0, NULL);
 	if (error)
 		goto done;
 
@@ -1976,7 +1982,7 @@ cmd_add(int argc, char *argv[])
 		goto done;
 
 	error = apply_unveil(got_repo_get_path(repo), 1,
-	    got_worktree_get_root_path(worktree), 0, 0);
+	    got_worktree_get_root_path(worktree), 0, NULL);
 	if (error)
 		goto done;
 
@@ -2062,7 +2068,7 @@ cmd_rm(int argc, char *argv[])
 		goto done;
 
 	error = apply_unveil(got_repo_get_path(repo), 1,
-	    got_worktree_get_root_path(worktree), 0, 0);
+	    got_worktree_get_root_path(worktree), 0, NULL);
 	if (error)
 		goto done;
 
@@ -2139,7 +2145,7 @@ cmd_revert(int argc, char *argv[])
 		goto done;
 
 	error = apply_unveil(got_repo_get_path(repo), 1,
-	    got_worktree_get_root_path(worktree), 0, 0);
+	    got_worktree_get_root_path(worktree), 0, NULL);
 	if (error)
 		goto done;
 
@@ -2366,13 +2372,10 @@ cmd_commit(int argc, char *argv[])
 		goto done;
 
 	error = apply_unveil(got_repo_get_path(repo), 0,
-	    got_worktree_get_root_path(worktree), 0, 1);
+	    got_worktree_get_root_path(worktree), 0, &editor);
 	if (error)
 		goto done;
 
-	error = get_editor(&editor);
-	if (error)
-		goto done;
 	cl_arg.editor = editor;
 	cl_arg.cmdline_log = logmsg;
 	cl_arg.worktree_path = got_worktree_get_root_path(worktree);
blob - c7b7e0f690e91e88eb1117ea6f211e847a6d17c9
blob + 999fdf6ddce081722e9bfc9da58ae4feafdc6c18
--- include/got_path.h
+++ include/got_path.h
@@ -98,3 +98,6 @@ const struct got_error *got_path_dirname(char **, cons
 
 /* Strip trailing slashes from a path; path will be modified in-place. */
 void got_path_strip_trailing_slashes(char *);
+
+/* Look up the absolute path of a program in $PATH */
+const struct got_error *got_path_find_prog(char **, const char *);
blob - 90f647ae849b1cdf8f1170cbf329f13755004def
blob + fa5d77b82f53ddb0305af33d2828ab46b8ec66f0
--- lib/path.c
+++ lib/path.c
@@ -1,6 +1,7 @@
 /*
  * Copyright (c) 2018, 2019 Stefan Sperling <stsp@openbsd.org>
  * Copyright (c) 2015 Theo de Raadt <deraadt@openbsd.org>
+ * Copyright (c) 1997 Todd C. Miller <millert@openbsd.org>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -26,6 +27,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <dirent.h>
+#include <paths.h>
 
 #include "got_error.h"
 #include "got_path.h"
@@ -376,4 +378,58 @@ got_path_strip_trailing_slashes(char *path)
 
 	while (path[x = strlen(path) - 1] == '/')
 		path[x] = '\0';
+}
+
+const struct got_error *
+got_path_find_prog(char **filename, const char *prog)
+{
+	char *p;
+	int len;
+	struct stat sbuf;
+	char *path, *pathcpy;
+
+	*filename = NULL;
+
+	path = getenv("PATH");
+	if (path == NULL)
+		path = _PATH_DEFPATH;
+
+	/* Special case if prog contains '/' */
+	if (strchr(prog, '/')) {
+		if ((stat(prog, &sbuf) == 0) && S_ISREG(sbuf.st_mode) &&
+		    access(prog, X_OK) == 0) {
+			*filename = strdup(prog);
+			if (*filename == NULL)
+				return got_error_from_errno("strdup");
+		}
+		return NULL;
+	}
+
+	if ((path = strdup(path)) == NULL)
+		return got_error_from_errno("strdup");
+	pathcpy = path;
+
+	while ((p = strsep(&pathcpy, ":")) != NULL) {
+		if (*p == '\0')
+			p = ".";
+
+		len = strlen(p);
+		while (len > 0 && p[len-1] == '/')
+			p[--len] = '\0';	/* strip trailing '/' */
+
+		if (asprintf(filename, "%s/%s", p, prog) == -1) {
+			free(path);
+			return got_error_from_errno("asprintf");
+		}
+		if ((stat(*filename, &sbuf) == 0) && S_ISREG(sbuf.st_mode) &&
+		    access(*filename, X_OK) == 0) {
+			free(path);
+			return NULL;
+		}
+		free(*filename);
+		*filename = NULL;
+		continue;
+	}
+	free(path);
+	return NULL;
 }