#include <config.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include <unistd.h>
#include <errno.h>
#include "sudoers.h"
static char *
resolve_editor(const char *ed, size_t edlen, int nfiles, char **files,
int *argc_out, char ***argv_out, char * const *whitelist)
{
char **nargv, *editor, *editor_path = NULL;
const char *cp, *ep, *tmp;
const char *edend = ed + edlen;
struct stat user_editor_sb;
int nargc;
debug_decl(resolve_editor, SUDOERS_DEBUG_UTIL)
cp = sudo_strsplit(ed, edend, " \t", &ep);
if (cp == NULL)
debug_return_str(NULL);
editor = strndup(cp, (size_t)(ep - cp));
if (editor == NULL) {
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
debug_return_str(NULL);
}
if (find_path(editor, &editor_path, &user_editor_sb, getenv("PATH"), 0, whitelist) != FOUND) {
free(editor);
errno = ENOENT;
debug_return_str(NULL);
}
for (nargc = 1, tmp = ep; sudo_strsplit(NULL, edend, " \t", &tmp) != NULL; )
nargc++;
if (nfiles != 0)
nargc += nfiles + 1;
nargv = reallocarray(NULL, nargc + 1, sizeof(char *));
if (nargv == NULL) {
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
free(editor);
free(editor_path);
debug_return_str(NULL);
}
nargv[0] = editor;
for (nargc = 1; (cp = sudo_strsplit(NULL, edend, " \t", &ep)) != NULL; nargc++) {
nargv[nargc] = strndup(cp, (size_t)(ep - cp));
if (nargv[nargc] == NULL) {
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
free(editor_path);
while (nargc--)
free(nargv[nargc]);
free(nargv);
debug_return_str(NULL);
}
}
if (nfiles != 0) {
nargv[nargc++] = "--";
while (nfiles--)
nargv[nargc++] = *files++;
}
nargv[nargc] = NULL;
*argc_out = nargc;
*argv_out = nargv;
debug_return_str(editor_path);
}
char *
find_editor(int nfiles, char **files, int *argc_out, char ***argv_out,
char * const *whitelist, const char **env_editor, bool env_error)
{
char *ev[3], *editor_path = NULL;
unsigned int i;
debug_decl(find_editor, SUDOERS_DEBUG_UTIL)
*env_editor = NULL;
ev[0] = "SUDO_EDITOR";
ev[1] = "VISUAL";
ev[2] = "EDITOR";
for (i = 0; i < nitems(ev); i++) {
char *editor = getenv(ev[i]);
if (editor != NULL && *editor != '\0') {
*env_editor = editor;
editor_path = resolve_editor(editor, strlen(editor),
nfiles, files, argc_out, argv_out, whitelist);
if (editor_path != NULL)
break;
if (errno != ENOENT)
debug_return_str(NULL);
}
}
if (editor_path == NULL) {
const char *def_editor_end = def_editor + strlen(def_editor);
const char *cp, *ep;
if (env_error && *env_editor != NULL) {
debug_return_str(NULL);
}
for (cp = sudo_strsplit(def_editor, def_editor_end, ":", &ep);
cp != NULL; cp = sudo_strsplit(NULL, def_editor_end, ":", &ep)) {
editor_path = resolve_editor(cp, (size_t)(ep - cp), nfiles,
files, argc_out, argv_out, whitelist);
if (editor_path != NULL)
break;
if (errno != ENOENT)
debug_return_str(NULL);
}
}
debug_return_str(editor_path);
}