=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/sudo/Attic/visudo.c,v retrieving revision 1.9.4.1 retrieving revision 1.10 diff -u -r1.9.4.1 -r1.10 --- src/usr.bin/sudo/Attic/visudo.c 2002/01/18 16:14:46 1.9.4.1 +++ src/usr.bin/sudo/Attic/visudo.c 2001/11/02 17:59:06 1.10 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 1998-2001 Todd C. Miller + * Copyright (c) 1996, 1998-2000 Todd C. Miller * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -38,42 +38,50 @@ #include "config.h" -#include -#include -#include -#include -#include #include #ifdef STDC_HEADERS -# include -# include -#else -# ifdef HAVE_STDLIB_H -# include -# endif +#include #endif /* STDC_HEADERS */ -#ifdef HAVE_STRING_H -# include -#else -# ifdef HAVE_STRINGS_H -# include -# endif -#endif /* HAVE_STRING_H */ #ifdef HAVE_UNISTD_H #include #endif /* HAVE_UNISTD_H */ +#ifdef HAVE_STRING_H +#include +#endif /* HAVE_STRING_H */ +#ifdef HAVE_STRINGS_H +#include +#endif /* HAVE_STRINGS_H */ +#if defined(HAVE_MALLOC_H) && !defined(STDC_HEADERS) +#include +#endif /* HAVE_MALLOC_H && !STDC_HEADERS */ #include #include #include #include #include #include +#include +#include +#include +#include #include "sudo.h" #include "version.h" +#ifndef STDC_HEADERS +#ifndef __GNUC__ /* gcc has its own malloc */ +extern char *malloc __P((size_t)); +#endif /* __GNUC__ */ +extern char *getenv __P((const char *)); +extern int stat __P((const char *, struct stat *)); +#endif /* !STDC_HEADERS */ + +#if defined(POSIX_SIGNALS) && !defined(SA_RESETHAND) +#define SA_RESETHAND 0 +#endif /* POSIX_SIGNALS && !SA_RESETHAND */ + #ifndef lint -static const char rcsid[] = "$Sudo: visudo.c,v 1.146 2002/01/17 15:35:54 millert Exp $"; +static const char rcsid[] = "$Sudo: visudo.c,v 1.126 2000/03/23 04:38:22 millert Exp $"; #endif /* lint */ /* @@ -83,8 +91,6 @@ static char whatnow __P((void)); static RETSIGTYPE Exit __P((int)); static void setup_signals __P((void)); -static int run_command __P((char *, char **)); -static int check_syntax __P((int)); int command_matches __P((char *, char *, char *, char *)); int addr_matches __P((char *)); int hostname_matches __P((char *, char *, char *)); @@ -99,12 +105,7 @@ extern FILE *yyin, *yyout; extern int errorlineno; extern int pedantic; -extern int quiet; -/* For getopt(3) */ -extern char *optarg; -extern int optind; - /* * Globals */ @@ -114,6 +115,7 @@ struct sudo_user sudo_user; int parse_error = FALSE; + int main(argc, argv) int argc; @@ -121,14 +123,9 @@ { char buf[MAXPATHLEN*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 */ time_t now; /* time now */ struct stat stmp_sb, sudoers_sb; /* to check for changes */ @@ -143,33 +140,16 @@ /* * Arg handling. */ - checkonly = 0; - while ((ch = getopt(argc, argv, "Vcf:sq")) != -1) { - switch (ch) { - case 'V': - (void) printf("visudo version %s\n", version); - exit(0); - case 'c': - checkonly++; /* check mode */ - break; - case 'f': - sudoers = optarg; /* sudoers file path */ - easprintf(&stmp, "%s.tmp", optarg); - break; - case 's': - pedantic++; /* strict mode */ - break; - case 'q': - quiet++; /* quiet mode */ - break; - default: - usage(); + while (--argc) { + if (!strcmp(argv[argc], "-V")) { + (void) printf("visudo version %s\n", version); + exit(0); + } else if (!strcmp(argv[argc], "-s")) { + pedantic++; /* strict mode */ + } else { + usage(); } } - argc -= optind; - argv += optind; - if (argc) - usage(); /* Mock up a fake sudo_user struct. */ user_host = user_shost = user_cmnd = ""; @@ -182,9 +162,6 @@ /* Setup defaults data structures. */ init_defaults(); - if (checkonly) - exit(check_syntax(quiet)); - /* * Open sudoers, lock it and stat it. * sudoers_fd must remain open throughout in order to hold the lock. @@ -247,128 +224,34 @@ (void) close(stmp_fd); /* - * Check EDITOR and VISUAL 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 we are allowing EDITOR and VISUAL envariables set Editor + * base on whichever exists... */ - if ((UserEditor = getenv("EDITOR")) == NULL || *UserEditor == '\0') - UserEditor = getenv("VISUAL"); - if (UserEditor && *UserEditor == '\0') - UserEditor = NULL; - else if (UserEditor) { - if (find_path(UserEditor, &Editor, getenv("PATH")) == FOUND) { - UserEditor = Editor; - } else { - if (def_flag(I_ENV_EDITOR)) { - /* If we are honoring $EDITOR this is a fatal error. */ - (void) fprintf(stderr, - "%s: specified editor (%s) doesn't exist!\n", - Argv[0], UserEditor); - Exit(-1); - } else { - /* Otherwise, just ignore $EDITOR. */ - UserEditor = NULL; - } - } - } + if (!def_flag(I_ENV_EDITOR) || + (!(Editor = getenv("EDITOR")) && !(Editor = getenv("VISUAL")))) + Editor = estrdup(def_str(I_EDITOR)); /* - * 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 = EditorPath = NULL; - if (def_flag(I_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. */ - (void) fprintf(stderr, "%s: unable to stat editor (%s): %s\n", - Argv[0], UserEditor, strerror(errno)); - Exit(-1); - } - EditorPath = estrdup(def_str(I_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, ":"))); - } - - /* - * Can't use $EDITOR, try each element of I_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_str(I_EDITOR)); - Editor = strtok(EditorPath, ":"); - do { - if (sudo_goodpath(Editor)) - break; - } while ((Editor = strtok(NULL, ":"))); - - /* Bleah, none of the editors existed! */ - if (Editor == NULL || *Editor == '\0') { - (void) fprintf(stderr, "%s: no editor found (editor path = %s)\n", - Argv[0], def_str(I_EDITOR)); - Exit(-1); - } - } - - /* * Edit the temp file and parse it (for sanity checking) */ do { - char linestr[64]; - - /* 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; - } - 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 (?!?!). + * Build up a buffer to execute */ + if (strlen(Editor) + strlen(stmp) + 30 > sizeof(buf)) { + (void) fprintf(stderr, "%s: Buffer too short (line %d).\n", + Argv[0], __LINE__); + Exit(-1); + } + if (parse_error == TRUE) + (void) sprintf(buf, "%s +%d %s", Editor, errorlineno, stmp); + else + (void) sprintf(buf, "%s %s", Editor, stmp); + + /* Do the edit -- some SYSV editors exit with 1 instead of 0 */ now = time(NULL); - if (run_command(Editor, av) != -1) { + n = system(buf); + if (n != -1 && ((n >> 8) == 0 || (n >> 8) == 1)) { /* * Sanity checks. */ @@ -415,8 +298,8 @@ } } else { (void) fprintf(stderr, - "%s: Editor (%s) failed, %s unchanged.\n", Argv[0], - Editor, sudoers); + "%s: Editor (%s) failed with exit status %d, %s unchanged.\n", + Argv[0], Editor, n, sudoers); Exit(-1); } @@ -469,26 +352,31 @@ */ if (rename(stmp, sudoers)) { if (errno == EXDEV) { + char *tmpbuf; + (void) fprintf(stderr, "%s: %s and %s not on the same filesystem, using mv to rename.\n", Argv[0], stmp, sudoers); - /* 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[3] = NULL; + /* Allocate just enough space for tmpbuf */ + n = sizeof(char) * (strlen(_PATH_MV) + strlen(stmp) + + strlen(sudoers) + 4); + if ((tmpbuf = (char *) malloc(n)) == NULL) { + (void) fprintf(stderr, + "%s: Cannot alocate memory, %s unchanged: %s\n", + Argv[0], sudoers, strerror(errno)); + Exit(-1); + } - /* And run it... */ - if (run_command(_PATH_MV, av)) { + /* Build up command and execute it */ + (void) sprintf(tmpbuf, "%s %s %s", _PATH_MV, stmp, sudoers); + if (system(tmpbuf)) { (void) fprintf(stderr, - "%s: Command failed: '%s %s %s', %s unchanged.\n", - Argv[0], _PATH_MV, stmp, sudoers, sudoers); + "%s: Command failed: '%s', %s unchanged.\n", + Argv[0], tmpbuf, sudoers); Exit(-1); } + free(tmpbuf); } else { (void) fprintf(stderr, "%s: Error renaming %s, %s unchanged: %s\n", Argv[0], stmp, sudoers, strerror(errno)); @@ -547,18 +435,6 @@ return; } -int -user_is_exempt() -{ - return(TRUE); -} - -void -init_envtables() -{ - return; -} - /* * Assuming a parse error occurred, prompt the user for what they want * to do now. Returns the first letter of their choice. @@ -597,91 +473,29 @@ static void setup_signals() { - sigaction_t sa; +#ifdef POSIX_SIGNALS + struct sigaction action; /* POSIX signal structure */ +#endif /* POSIX_SIGNALS */ /* * Setup signal handlers to cleanup nicely. */ - sigemptyset(&sa.sa_mask); - sa.sa_flags = SA_RESTART; - sa.sa_handler = Exit; - (void) sigaction(SIGTERM, &sa, NULL); - (void) sigaction(SIGHUP, &sa, NULL); - (void) sigaction(SIGINT, &sa, NULL); - (void) sigaction(SIGQUIT, &sa, NULL); -} - -static int -run_command(path, argv) - char *path; - char **argv; -{ - int status; - pid_t pid; - sigset_t set, oset; - - (void) sigemptyset(&set); - (void) sigaddset(&set, SIGCHLD); - (void) sigprocmask(SIG_BLOCK, &set, &oset); - - switch (pid = fork()) { - case -1: - (void) fprintf(stderr, - "%s: unable to run %s: %s\n", Argv[0], path, strerror(errno)); - Exit(-1); - break; /* NOTREACHED */ - case 0: - (void) sigprocmask(SIG_SETMASK, &oset, NULL); - execv(path, argv); - (void) fprintf(stderr, - "%s: unable to run %s: %s\n", Argv[0], path, strerror(errno)); - _exit(127); - break; /* NOTREACHED */ - } - -#ifdef sudo_waitpid - pid = sudo_waitpid(pid, &status, 0); +#ifdef POSIX_SIGNALS + (void) memset((VOID *)&action, 0, sizeof(action)); + action.sa_handler = Exit; + action.sa_flags = SA_RESETHAND; + (void) sigaction(SIGTERM, &action, NULL); + (void) sigaction(SIGHUP, &action, NULL); + (void) sigaction(SIGINT, &action, NULL); + (void) sigaction(SIGQUIT, &action, NULL); #else - pid = wait(&status); -#endif - - (void) sigprocmask(SIG_SETMASK, &oset, NULL); - - /* XXX - should use WEXITSTATUS() */ - return(pid == -1 ? -1 : (status >> 8)); + (void) signal(SIGTERM, Exit); + (void) signal(SIGHUP, Exit); + (void) signal(SIGINT, Exit); + (void) signal(SIGQUIT, Exit); +#endif /* POSIX_SIGNALS */ } -static int -check_syntax(quiet) - int quiet; -{ - - if ((yyin = fopen(sudoers, "r")) == NULL) { - if (!quiet) - (void) fprintf(stderr, "%s: unable to open %s: %s\n", Argv[0], - sudoers, strerror(errno)); - exit(1); - } - yyout = stdout; - init_parser(); - if (yyparse() && parse_error != TRUE) { - if (!quiet) - (void) fprintf(stderr, - "%s: failed to parse %s file, unknown error.\n", - Argv[0], sudoers); - parse_error = TRUE; - } - if (!quiet){ - if (parse_error) - (void) printf("parse error in %s near line %d\n", sudoers, - errorlineno); - else - (void) printf("%s file parsed OK\n", sudoers); - } - - return(parse_error == TRUE); -} - /* * Unlink the sudoers temp file (if it exists) and exit. * Used in place of a normal exit() and as a signal handler. @@ -706,7 +520,6 @@ static void usage() { - (void) fprintf(stderr, "usage: %s [-c] [-f sudoers] [-q] [-s] [-V]\n", - Argv[0]); + (void) fprintf(stderr, "usage: %s [-s] [-V]\n", Argv[0]); exit(1); }