=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/sudo/Attic/visudo.c,v retrieving revision 1.18 retrieving revision 1.19 diff -u -r1.18 -r1.19 --- src/usr.bin/sudo/Attic/visudo.c 2004/11/29 17:29:05 1.18 +++ src/usr.bin/sudo/Attic/visudo.c 2007/07/26 16:10:16 1.19 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 1998-2004 Todd C. Miller + * Copyright (c) 1996, 1998-2005 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 @@ -28,7 +28,7 @@ # include #endif -#include "config.h" +#include #include #include @@ -64,27 +64,47 @@ #endif /* HAVE_ERR_H */ #include #include -#include +#if TIME_WITH_SYS_TIME +# include +#endif #include #include #include +#ifndef HAVE_TIMESPEC +# include +#endif #include "sudo.h" #include "version.h" #ifndef lint -static const char rcsid[] = "$Sudo: visudo.c,v 1.170 2004/09/08 15:48:23 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: visudo.c,v 1.166.2.9 2007/07/22 19:21:01 millert Exp $"; #endif /* lint */ +struct sudoersfile { + char *path; + char *tpath; + int fd; + off_t orig_size; + struct timespec orig_mtim; +}; + /* * Function prototypes */ -static void usage __P((void)); +static void usage __P((void)) __attribute__((__noreturn__)); static char whatnow __P((void)); static RETSIGTYPE Exit __P((int)); +static void edit_sudoers __P((struct sudoersfile *, char *, char *, int)); +static void visudo __P((struct sudoersfile *, char *, char *)); static void setup_signals __P((void)); +static void install_sudoers __P((struct sudoersfile *)); +static int check_syntax __P(()); static int run_command __P((char *, char **)); -static int check_syntax __P((int)); +static char *get_args __P((char *)); +static char *get_editor __P((char **)); +static FILE *open_sudoers __P((struct sudoersfile *)); + int command_matches __P((char *, char *)); int addr_matches __P((char *)); int hostname_matches __P((char *, char *, char *)); @@ -98,7 +118,7 @@ /* * External globals exported by the parser */ -extern FILE *yyin, *yyout; +extern FILE *yyin; extern int errorlineno; extern int pedantic; extern int quiet; @@ -111,31 +131,23 @@ * Globals */ char **Argv; -char *sudoers = _PATH_SUDOERS; -char *stmp = _PATH_SUDOERS_TMP; struct sudo_user sudo_user; int Argc, parse_error = FALSE; +static struct sudoersfile sudoers; int main(argc, argv) int argc; char **argv; { - char buf[PATH_MAX*2]; /* buffer used for copying files */ - char *Editor; /* editor to use */ - char *UserEditor; /* editor user wants to use */ - char *EditorPath; /* colon-separated list of editors */ - char *av[4]; /* argument vector for run_command */ - int checkonly; /* only check existing file? */ - int sudoers_fd; /* sudoers file descriptor */ - int stmp_fd; /* stmp file descriptor */ - int n; /* length parameter */ - int ch; /* getopt char */ - struct timespec ts1, ts2; /* time before and after edit */ - struct timespec sudoers_mtim; /* starting mtime of sudoers file */ - off_t sudoers_size; /* starting size of sudoers file */ - struct stat sb; /* stat buffer */ + char *args, *editor; + int ch, checkonly, n; + /* Initialize sudoers struct. */ + sudoers.path = _PATH_SUDOERS; + sudoers.tpath = _PATH_SUDOERS_TMP; + sudoers.fd = -1; + /* Warn about aliases that are used before being defined. */ pedantic = 1; @@ -155,9 +167,9 @@ case 'c': checkonly++; /* check mode */ break; - case 'f': - sudoers = optarg; /* sudoers file path */ - easprintf(&stmp, "%s.tmp", optarg); + case 'f': /* sudoers file path */ + sudoers.path = optarg; + easprintf(&sudoers.tpath, "%s.tmp", optarg); break; case 's': pedantic++; /* strict mode */ @@ -183,317 +195,242 @@ init_defaults(); if (checkonly) - exit(check_syntax(quiet)); + exit(check_syntax()); /* - * Open sudoers, lock it and stat it. - * sudoers_fd must remain open throughout in order to hold the lock. - */ - sudoers_fd = open(sudoers, O_RDWR | O_CREAT, SUDOERS_MODE); - if (sudoers_fd == -1) - err(1, "%s", sudoers); - if (!lock_file(sudoers_fd, SUDO_TLOCK)) - errx(1, "sudoers file busy, try again later"); -#ifdef HAVE_FSTAT - if (fstat(sudoers_fd, &sb) == -1) -#else - if (stat(sudoers, &sb) == -1) -#endif - err(1, "can't stat %s", sudoers); - sudoers_size = sb.st_size; - sudoers_mtim.tv_sec = mtim_getsec(sb); - sudoers_mtim.tv_nsec = mtim_getnsec(sb); + * Open and parse the existing sudoers file(s) in quiet mode to highlight + * any existing errors and to pull in editor and env_editor conf values. + */ + if ((yyin = open_sudoers(&sudoers)) == NULL) + err(1, "%s", sudoers.path); + n = quiet; + quiet = 1; + init_parser(); + yyparse(); + parse_error = FALSE; + quiet = n; - /* - * Open sudoers temp file. - */ - stmp_fd = open(stmp, O_WRONLY | O_CREAT | O_TRUNC, 0600); - if (stmp_fd < 0) - err(1, "%s", stmp); + /* Edit sudoers, check for parse errors and re-edit on failure. */ + editor = get_editor(&args); + visudo(&sudoers, editor, args); - /* Install signal handlers to clean up stmp if we are killed. */ - setup_signals(); + /* Install the new sudoers file. */ + install_sudoers(&sudoers); - /* Copy sudoers -> stmp and reset the mtime */ - if (sudoers_size) { - while ((n = read(sudoers_fd, buf, sizeof(buf))) > 0) - if (write(stmp_fd, buf, n) != n) - err(1, "write error"); + exit(0); +} - /* Add missing newline at EOF if needed. */ - if (n > 0 && buf[n - 1] != '\n') { - buf[0] = '\n'; - write(stmp_fd, buf, 1); - } +/* + * Edit the sudoers file. + * Returns TRUE on success, else FALSE. + */ +static void +edit_sudoers(sp, editor, args, lineno) + struct sudoersfile *sp; + char *editor, *args; + int lineno; +{ + int ac; /* argument count */ + char **av; /* argument vector for run_command */ + char *cp; /* scratch char pointer */ + char linestr[64]; /* string version of lineno */ + struct timespec ts1, ts2; /* time before and after edit */ + struct stat sb; /* stat buffer */ - (void) touch(stmp_fd, stmp, &sudoers_mtim); - (void) close(stmp_fd); + /* Make timestamp on temp file match original. */ + (void) touch(-1, sp->tpath, &sp->orig_mtim); - /* Parse sudoers to pull in editor and env_editor conf values. */ - if ((yyin = fopen(stmp, "r"))) { - yyout = stdout; - n = quiet; - quiet = 1; - init_parser(); - yyparse(); - parse_error = FALSE; - quiet = n; - fclose(yyin); - } - } else - (void) close(stmp_fd); + /* Find the length of the argument vector */ + ac = 3 + (lineno > 0); + if (args) { + int wasblank; - /* - * Check VISUAL and EDITOR environment variables to see which editor - * the user wants to use (we may not end up using it though). - * If the path is not fully-qualified, make it so and check that - * the specified executable actually exists. - */ - if ((UserEditor = getenv("VISUAL")) == NULL || *UserEditor == '\0') - UserEditor = getenv("EDITOR"); - if (UserEditor && *UserEditor == '\0') - UserEditor = NULL; - else if (UserEditor) { - if (find_path(UserEditor, &Editor, NULL, getenv("PATH")) == FOUND) { - UserEditor = Editor; - } else { - if (def_env_editor) { - /* If we are honoring $EDITOR this is a fatal error. */ - warnx("specified editor (%s) doesn't exist!", UserEditor); - Exit(-1); - } else { - /* Otherwise, just ignore $EDITOR. */ - UserEditor = NULL; - } - } + ac++; + for (wasblank = FALSE, cp = args; *cp; cp++) { + if (isblank((unsigned char) *cp)) + wasblank = TRUE; + else if (wasblank) { + wasblank = FALSE; + ac++; + } + } } + /* Build up argument vector for the command */ + av = emalloc2(ac, sizeof(char *)); + if ((av[0] = strrchr(editor, '/')) != NULL) + av[0]++; + else + av[0] = editor; + ac = 1; + if (lineno > 0) { + (void) snprintf(linestr, sizeof(linestr), "+%d", lineno); + av[ac++] = linestr; + } + if (args) { + for ((cp = strtok(args, " \t")); cp; (cp = strtok(NULL, " \t"))) + av[ac++] = cp; + } + av[ac++] = sp->tpath; + av[ac++] = NULL; + /* - * See if we can use the user's choice of editors either because - * we allow any $EDITOR or because $EDITOR is in the allowable list. + * Do the edit: + * We cannot check the editor's exit value against 0 since + * XPG4 specifies that vi's exit value is a function of the + * number of errors during editing (?!?!). */ - Editor = EditorPath = NULL; - if (def_env_editor && UserEditor) - Editor = UserEditor; - else if (UserEditor) { - struct stat editor_sb; - struct stat user_editor_sb; - char *base, *userbase; - - if (stat(UserEditor, &user_editor_sb) != 0) { - /* Should never happen since we already checked above. */ - warn("unable to stat editor (%s)", UserEditor); + gettime(&ts1); + if (run_command(editor, av) != -1) { + gettime(&ts2); + /* + * Sanity checks. + */ + if (stat(sp->tpath, &sb) < 0) { + warnx("cannot stat temporary file (%s), %s unchanged", + sp->tpath, sp->path); Exit(-1); } - EditorPath = estrdup(def_editor); - Editor = strtok(EditorPath, ":"); - do { - /* - * Both Editor and UserEditor should be fully qualified but - * check anyway... - */ - if ((base = strrchr(Editor, '/')) == NULL) - continue; - if ((userbase = strrchr(UserEditor, '/')) == NULL) { - Editor = NULL; - break; - } - base++, userbase++; - - /* - * We compare the basenames first and then use stat to match - * for sure. - */ - if (strcmp(base, userbase) == 0) { - if (stat(Editor, &editor_sb) == 0 && S_ISREG(editor_sb.st_mode) - && (editor_sb.st_mode & 0000111) && - editor_sb.st_dev == user_editor_sb.st_dev && - editor_sb.st_ino == user_editor_sb.st_ino) - break; - } - } while ((Editor = strtok(NULL, ":"))); + if (sb.st_size == 0) { + warnx("zero length temporary file (%s), %s unchanged", + sp->tpath, sp->path); + Exit(-1); + } + } else { + warnx("editor (%s) failed, %s unchanged", editor, sp->path); + Exit(-1); } - /* - * Can't use $EDITOR, try each element of def_editor until we - * find one that exists, is regular, and is executable. - */ - if (Editor == NULL || *Editor == '\0') { - if (EditorPath != NULL) - free(EditorPath); - EditorPath = estrdup(def_editor); - Editor = strtok(EditorPath, ":"); - do { - if (sudo_goodpath(Editor, NULL)) - break; - } while ((Editor = strtok(NULL, ":"))); - - /* Bleah, none of the editors existed! */ - if (Editor == NULL || *Editor == '\0') { - warnx("no editor found (editor path = %s)", def_editor); - Exit(-1); + /* Check to see if the user changed the file. */ + if (sp->orig_size == sb.st_size && + sp->orig_mtim.tv_sec == mtim_getsec(sb) && + sp->orig_mtim.tv_nsec == mtim_getnsec(sb)) { + /* + * If mtime and size match but the user spent no measurable + * time in the editor we can't tell if the file was changed. + */ +#ifdef HAVE_TIMESPECSUB2 + timespecsub(&ts1, &ts2); +#else + timespecsub(&ts1, &ts2, &ts2); +#endif + if (timespecisset(&ts2)) { + warnx("%s unchanged", sp->tpath); + Exit(0); } } +} +/* + * Parse sudoers after editing and re-edit any ones that caused a parse error. + * Returns TRUE on success, else FALSE. + */ +static void +visudo(sp, editor, args) + struct sudoersfile *sp; + char *editor, *args; +{ + int ch; + /* - * Edit the temp file and parse it (for sanity checking) + * Parse the edited sudoers file and do sanity checking */ do { - char linestr[64]; + edit_sudoers(sp, editor, args, errorlineno); - /* Build up argument vector for the command */ - if ((av[0] = strrchr(Editor, '/')) != NULL) - av[0]++; - else - av[0] = Editor; - n = 1; - if (parse_error == TRUE) { - (void) snprintf(linestr, sizeof(linestr), "+%d", errorlineno); - av[n++] = linestr; + yyin = fopen(sp->tpath, "r+"); + if (yyin == NULL) { + warnx("can't re-open temporary file (%s), %s unchanged.", + sp->tpath, sp->path); + Exit(-1); } - av[n++] = stmp; - av[n++] = NULL; - /* - * Do the edit: - * We cannot check the editor's exit value against 0 since - * XPG4 specifies that vi's exit value is a function of the - * number of errors during editing (?!?!). - */ - gettime(&ts1); - if (run_command(Editor, av) != -1) { - gettime(&ts2); - /* - * Sanity checks. - */ - if (stat(stmp, &sb) < 0) { - warnx("cannot stat temporary file (%s), %s unchanged", - stmp, sudoers); - Exit(-1); - } - if (sb.st_size == 0) { - warnx("zero length temporary file (%s), %s unchanged", - stmp, sudoers); - Exit(-1); - } + /* Add missing newline at EOF if needed. */ + if (fseek(yyin, -1, SEEK_END) == 0 && (ch = fgetc(yyin)) != '\n') + fputc('\n', yyin); + rewind(yyin); - /* - * Passed sanity checks so reopen stmp file and check - * for parse errors. - */ - yyout = stdout; - yyin = fopen(stmp, "r+"); - if (yyin == NULL) { - warnx("can't re-open temporary file (%s), %s unchanged.", - stmp, sudoers); - Exit(-1); - } + /* Clean slate for each parse */ + user_runas = NULL; + init_defaults(); + init_parser(); - /* Add missing newline at EOF if needed. */ - if (fseek(yyin, -1, SEEK_END) == 0 && (ch = fgetc(yyin)) != '\n') - fputc('\n', yyin); - rewind(yyin); - - /* Clean slate for each parse */ - user_runas = NULL; - init_defaults(); - init_parser(); - - /* Parse the sudoers temp file */ - yyrestart(yyin); - if (yyparse() && parse_error != TRUE) { - warnx("unabled to parse temporary file (%s), unknown error", - stmp); - parse_error = TRUE; - } - fclose(yyin); - } else { - warnx("editor (%s) failed, %s unchanged", Editor, sudoers); - Exit(-1); + /* Parse the sudoers temp file */ + yyrestart(yyin); + if (yyparse() && parse_error != TRUE) { + warnx("unabled to parse temporary file (%s), unknown error", + sp->tpath); + parse_error = TRUE; } + fclose(yyin); /* * Got an error, prompt the user for what to do now */ - if (parse_error == TRUE) { + if (parse_error) { switch (whatnow()) { case 'Q' : parse_error = FALSE; /* ignore parse error */ break; - case 'x' : if (sudoers_size == 0) - unlink(sudoers); - Exit(0); + case 'x' : Exit(0); break; } } - } while (parse_error == TRUE); + } while (parse_error); +} +/* + * Set the owner and mode on a sudoers temp file and + * move it into place. Returns TRUE on success, else FALSE. + */ +static void +install_sudoers(sp) + struct sudoersfile *sp; +{ /* - * If the user didn't change the temp file, just unlink it. - */ - if (sudoers_size == sb.st_size && - sudoers_mtim.tv_sec == mtim_getsec(sb) && - sudoers_mtim.tv_nsec == mtim_getnsec(sb)) { - /* - * If mtime and size match but the user spent no measurable - * time in the editor we can't tell if the file was changed. - */ -#ifdef HAVE_TIMESPECSUB2 - timespecsub(&ts1, &ts2); -#else - timespecsub(&ts1, &ts2, &ts2); -#endif - if (timespecisset(&ts2)) { - warnx("sudoers file unchanged"); - Exit(0); - } - } - - /* * Change mode and ownership of temp file so when - * we move it to sudoers things are kosher. + * we move it to sp->path things are kosher. */ - if (chown(stmp, SUDOERS_UID, SUDOERS_GID)) { + if (chown(sp->tpath, SUDOERS_UID, SUDOERS_GID) != 0) { warn("unable to set (uid, gid) of %s to (%d, %d)", - stmp, SUDOERS_UID, SUDOERS_GID); + sp->tpath, SUDOERS_UID, SUDOERS_GID); Exit(-1); } - if (chmod(stmp, SUDOERS_MODE)) { - warn("unable to change mode of %s to 0%o", stmp, SUDOERS_MODE); + if (chmod(sp->tpath, SUDOERS_MODE) != 0) { + warn("unable to change mode of %s to 0%o", sp->tpath, SUDOERS_MODE); Exit(-1); } /* - * Now that we have a sane stmp file (parses ok) it needs to be - * rename(2)'d to sudoers. If the rename(2) fails we try using - * mv(1) in case stmp and sudoers are on different file systems. + * Now that sp->tpath is sane (parses ok) it needs to be + * rename(2)'d to sp->path. If the rename(2) fails we try using + * mv(1) in case sp->tpath and sp->path are on different file systems. */ - if (rename(stmp, sudoers)) { + if (rename(sp->tpath, sp->path) != 0) { if (errno == EXDEV) { + char *av[4]; warnx("%s and %s not on the same file system, using mv to rename", - stmp, sudoers); + sp->tpath, sp->path); /* Build up argument vector for the command */ if ((av[0] = strrchr(_PATH_MV, '/')) != NULL) av[0]++; else av[0] = _PATH_MV; - av[1] = stmp; - av[2] = sudoers; + av[1] = sp->tpath; + av[2] = sp->path; av[3] = NULL; /* And run it... */ if (run_command(_PATH_MV, av)) { warnx("command failed: '%s %s %s', %s unchanged", - _PATH_MV, stmp, sudoers, sudoers); + _PATH_MV, sp->tpath, sp->path, sp->path); Exit(-1); } } else { - warn("error renaming %s, %s unchanged", stmp, sudoers); + warn("error renaming %s, %s unchanged", sp->tpath, sp->path); Exit(-1); } } - - exit(0); } /* @@ -651,6 +588,8 @@ break; /* NOTREACHED */ case 0: (void) sigprocmask(SIG_SETMASK, &oset, NULL); + endpwent(); + closefrom(STDERR_FILENO + 1); execv(path, argv); warn("unable to run %s", path); _exit(127); @@ -671,34 +610,215 @@ } static int -check_syntax(quiet) - int quiet; +check_syntax() { - if ((yyin = fopen(sudoers, "r")) == NULL) { + if ((yyin = fopen(sudoers.path, "r")) == NULL) { if (!quiet) - warn("unable to open %s", sudoers); + warn("unable to open %s", sudoers.path); exit(1); } - yyout = stdout; init_parser(); if (yyparse() && parse_error != TRUE) { if (!quiet) - warnx("failed to parse %s file, unknown error", sudoers); + warnx("failed to parse %s file, unknown error", sudoers.path); parse_error = TRUE; } if (!quiet){ if (parse_error) - (void) printf("parse error in %s near line %d\n", sudoers, + (void) printf("parse error in %s near line %d\n", sudoers.path, errorlineno); else - (void) printf("%s file parsed OK\n", sudoers); + (void) printf("%s file parsed OK\n", sudoers.path); } return(parse_error == TRUE); } +static FILE * +open_sudoers(sp) + struct sudoersfile *sp; +{ + struct stat sb; + ssize_t nread; + FILE *fp; + char buf[PATH_MAX*2]; + int tfd; + + /* Open and lock sudoers. */ + sp->fd = open(sp->path, O_RDWR | O_CREAT, SUDOERS_MODE); + if (sp->fd == -1) + err(1, "%s", sp->path); + if (!lock_file(sp->fd, SUDO_TLOCK)) + errx(1, "%s busy, try again later", sp->path); + if ((fp = fdopen(sp->fd, "r")) == NULL) + err(1, "%s", sp->path); + + /* Stash sudoers size and mtime. */ +#ifdef HAVE_FSTAT + if (fstat(sp->fd, &sb) == -1) +#else + if (stat(sp->path, &sb) == -1) +#endif + err(1, "can't stat %s", sp->path); + sp->orig_size = sb.st_size; + sp->orig_mtim.tv_sec = mtim_getsec(sb); + sp->orig_mtim.tv_nsec = mtim_getnsec(sb); + + /* Create the temp file. */ + tfd = open(sp->tpath, O_WRONLY | O_CREAT | O_TRUNC, 0600); + if (tfd < 0) + err(1, "%s", sp->tpath); + + /* Install signal handlers to clean up temp file if we are killed. */ + setup_signals(); + + /* Copy sp->path -> sp->tpath. */ + if (sp->orig_size != 0) { + while ((nread = read(sp->fd, buf, sizeof(buf))) > 0) + if (write(tfd, buf, nread) != nread) { + warn("write error"); + Exit(-1); + } + + /* Add missing newline at EOF if needed. */ + if (nread > 0 && buf[nread - 1] != '\n') { + buf[0] = '\n'; + write(tfd, buf, 1); + } + } + (void) close(tfd); + rewind(fp); + + return(fp); +} + +static char * +get_editor(args) + char **args; +{ + char *Editor, *EditorArgs, *EditorPath, *UserEditor, *UserEditorArgs; + + /* + * Check VISUAL and EDITOR environment variables to see which editor + * the user wants to use (we may not end up using it though). + * If the path is not fully-qualified, make it so and check that + * the specified executable actually exists. + */ + UserEditorArgs = NULL; + if ((UserEditor = getenv("VISUAL")) == NULL || *UserEditor == '\0') + UserEditor = getenv("EDITOR"); + if (UserEditor && *UserEditor == '\0') + UserEditor = NULL; + else if (UserEditor) { + UserEditorArgs = get_args(UserEditor); + if (find_path(UserEditor, &Editor, NULL, getenv("PATH")) == FOUND) { + UserEditor = Editor; + } else { + if (def_env_editor) { + /* If we are honoring $EDITOR this is a fatal error. */ + warnx("specified editor (%s) doesn't exist!", UserEditor); + Exit(-1); + } else { + /* Otherwise, just ignore $EDITOR. */ + UserEditor = NULL; + } + } + } + + /* + * See if we can use the user's choice of editors either because + * we allow any $EDITOR or because $EDITOR is in the allowable list. + */ + Editor = EditorArgs = EditorPath = NULL; + if (def_env_editor && UserEditor) { + Editor = UserEditor; + EditorArgs = UserEditorArgs; + } else if (UserEditor) { + struct stat editor_sb; + struct stat user_editor_sb; + char *base, *userbase; + + if (stat(UserEditor, &user_editor_sb) != 0) { + /* Should never happen since we already checked above. */ + warn("unable to stat editor (%s)", UserEditor); + Exit(-1); + } + EditorPath = estrdup(def_editor); + Editor = strtok(EditorPath, ":"); + do { + EditorArgs = get_args(Editor); + /* + * Both Editor and UserEditor should be fully qualified but + * check anyway... + */ + if ((base = strrchr(Editor, '/')) == NULL) + continue; + if ((userbase = strrchr(UserEditor, '/')) == NULL) { + Editor = NULL; + break; + } + base++, userbase++; + + /* + * We compare the basenames first and then use stat to match + * for sure. + */ + if (strcmp(base, userbase) == 0) { + if (stat(Editor, &editor_sb) == 0 && S_ISREG(editor_sb.st_mode) + && (editor_sb.st_mode & 0000111) && + editor_sb.st_dev == user_editor_sb.st_dev && + editor_sb.st_ino == user_editor_sb.st_ino) + break; + } + } while ((Editor = strtok(NULL, ":"))); + } + + /* + * Can't use $EDITOR, try each element of def_editor until we + * find one that exists, is regular, and is executable. + */ + if (Editor == NULL || *Editor == '\0') { + efree(EditorPath); + EditorPath = estrdup(def_editor); + Editor = strtok(EditorPath, ":"); + do { + EditorArgs = get_args(Editor); + if (sudo_goodpath(Editor, NULL)) + break; + } while ((Editor = strtok(NULL, ":"))); + + /* Bleah, none of the editors existed! */ + if (Editor == NULL || *Editor == '\0') { + warnx("no editor found (editor path = %s)", def_editor); + Exit(-1); + } + } + *args = EditorArgs; + return(Editor); +} + /* + * Split out any command line arguments and return them. + */ +static char * +get_args(cmnd) + char *cmnd; +{ + char *args; + + args = cmnd; + while (*args && !isblank((unsigned char) *args)) + args++; + if (*args) { + *args++ = '\0'; + while (*args && isblank((unsigned char) *args)) + args++; + } + return(*args ? args : NULL); +} + +/* * Unlink the sudoers temp file (if it exists) and exit. * Used in place of a normal exit() and as a signal handler. * A positive parameter indicates we were called as a signal handler. @@ -709,7 +829,7 @@ { #define emsg " exiting due to signal.\n" - (void) unlink(stmp); + (void) unlink(sudoers.tpath); if (sig > 0) { write(STDERR_FILENO, getprogname(), strlen(getprogname())); @@ -722,7 +842,7 @@ static void usage() { - (void) fprintf(stderr, "usage: %s [-c] [-f sudoers] [-q] [-s] [-V]\n", + (void) fprintf(stderr, "usage: %s [-c] [-q] [-s] [-V] [-f sudoers]\n", getprogname()); exit(1); }