commit 0ee7065d8d7e2f4c85b8e806bda98645435f08ac from: Stefan Sperling date: Mon May 13 17:56:40 2019 UTC make 'got commit' look up EDITOR in PATH The previous code only worked if EDITOR contained an absolute path. 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 * Copyright (c) 2015 Theo de Raadt + * Copyright (c) 1997 Todd C. Miller * * 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 #include #include +#include #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; }