346) Sudo is now available under a BSD/Apache style license. This is
possible because it no longer contains any of the original 1.1 code.
+
+347) Added configuration info when sudo is run with the -V flag by root.
+
+348) Change visudo tmp file from /etc/stmp -> /etc/sudoers.tmp since
+ Solaris uses stmp for shadow temp file. Also rename _PATH_SUDO_SUDOERS
+ to _PATH_SUDOERS and _PATH_SUDO_STMP to _PATH_SUDOERS_TMP.
+
+349) Added configure option to set syslog priorities.
+
+350) Sudo now locks its log file to prevent mangled entries.
+
+351) Visudo now locks the sudoers temp file instead of bailing when
+ the temp file already exists. This fixes the problem of stale
+ temp files but it does *require* that you not try to put the
+ temp file in a world-writable directory. This shoud not be
+ an issue as the temp file should live in the same dir as sudoers.
PROGS = @PROGS@
-SRCS = alloc.c check.c find_path.c getspwuid.c goodpath.c interfaces.c \
- logging.c parse.c parse.lex parse.yacc sudo.c sudo_setenv.c tgetpass.c \
- version.c visudo.c $(AUTH_SRCS)
+SRCS = alloc.c check.c fileops.c find_path.c getspwuid.c goodpath.c \
+ interfaces.c logging.c parse.c parse.lex parse.yacc sudo.c \
+ sudo_setenv.c tgetpass.c version.c visudo.c $(AUTH_SRCS)
AUTH_SRCS = auth/afs.c auth/aix_auth.c auth/dce.c auth/fwtk.c auth/kerb4.c \
auth/kerb5.c auth/pam.c auth/passwd.c auth/rfc1938.c \
PARSEOBJS = sudo.tab.o lex.yy.o alloc.o
-SUDOBJS = check.o getspwuid.o goodpath.o find_path.o interfaces.o logging.o \
- parse.o sudo.o sudo_setenv.o tgetpass.o version.o \
+SUDOBJS = check.o getspwuid.o goodpath.o fileops.o find_path.o interfaces.o \
+ logging.o parse.o sudo.o sudo_setenv.o tgetpass.o version.o \
$(AUTH_OBJS) $(PARSEOBJS)
-VISUDOBJS = visudo.o $(PARSEOBJS)
+VISUDOBJS = visudo.o fileops.o $(PARSEOBJS)
TESTOBJS = interfaces.o testsudoers.o $(PARSEOBJS)
19) Sudo should have a separate error message for when the user is in sudoers
but not allowed to run stuff on that host, and send mail.
-
-20) Add configure check for locking functions and lock logfile.
Q) When I run "visudo" it says "sudoers file busy, try again later."
and doesn't do anything.
-A) You have a stale sudoers temporary file. The default location is
- /etc/sudoers.tmp. If you delete this file visudo will be happy again,
- but make sure to check that no one else is running visudo at
- the time.
+A) Someone else is currently editing the sudoers file with visudo.
Q) When I try to use "cd" with sudo it says "cd: command not found".
A) "cd" is a shell builtin, you can't run it as a command since
#include <sys/file.h>
#include <pwd.h>
#include <grp.h>
-#ifdef HAVE_UTIME
-# ifdef HAVE_UTIME_H
-# include <utime.h>
-# endif /* HAVE_UTIME_H */
-#else
-# include "emul/utime.h"
-#endif /* HAVE_UTIME */
#include "sudo.h"
int user_is_exempt __P((void));
static void build_timestamp __P((char **, char **));
static int timestamp_status __P((char *, char *, char *, int));
-static int touch __P((char *, time_t));
#ifndef NO_PASSWD
static char *expand_prompt __P((char *, char *, char *));
static void lecture __P((void));
return(FALSE);
}
-/*
- * Update the access and modify times on a file.
- */
-static int
-touch(path, when)
- char *path;
- time_t when;
-{
-#ifdef HAVE_UTIME_POSIX
- struct utimbuf ut, *utp;
-
- ut.actime = ut.modtime = when;
- utp = &ut;
-#else
- /* BSD <= 4.3 has no struct utimbuf */
- time_t utp[2];
-
- utp[0] = utp[1] = when;
-#endif /* HAVE_UTIME_POSIX */
-
- return(utime(path, utp));
-}
-
/*
* Fills in timestampdir as well as timestampfile if using tty tickets.
*/
/* Deal with ANSI stuff reasonably. */
#ifndef __P
-# if defined (__cplusplus) || defined (__STDC__)
-# define __P(args) args
-# else
-# define __P(args) ()
-# endif
+# if defined (__cplusplus) || defined (__STDC__)
+# define __P(args) args
+# else
+# define __P(args) ()
+# endif
#endif /* __P */
/*
* Some systems (ie ISC V/386) do not define MAXPATHLEN even in param.h
*/
#ifndef MAXPATHLEN
-# define MAXPATHLEN 1024
+# define MAXPATHLEN 1024
#endif
/*
* Some systems do not define MAXHOSTNAMELEN.
*/
#ifndef MAXHOSTNAMELEN
-# define MAXHOSTNAMELEN 64
+# define MAXHOSTNAMELEN 64
#endif
/*
* 4.2BSD lacks FD_* macros (we only use FD_SET and FD_ZERO)
*/
#ifndef FD_SETSIZE
-#define FD_SET(fd, fds) ((fds) -> fds_bits[0] |= (1 << (fd)))
-#define FD_ZERO(fds) ((fds) -> fds_bits[0] = 0)
+# define FD_SET(fd, fds) ((fds) -> fds_bits[0] |= (1 << (fd)))
+# define FD_ZERO(fds) ((fds) -> fds_bits[0] = 0)
#endif /* !FD_SETSIZE */
/*
* Posix versions for those without...
*/
#ifndef _S_IFMT
-# define _S_IFMT S_IFMT
+# define _S_IFMT S_IFMT
#endif /* _S_IFMT */
#ifndef _S_IFREG
-# define _S_IFREG S_IFREG
+# define _S_IFREG S_IFREG
#endif /* _S_IFREG */
#ifndef _S_IFDIR
-# define _S_IFDIR S_IFDIR
+# define _S_IFDIR S_IFDIR
#endif /* _S_IFDIR */
#ifndef _S_IFLNK
-#define _S_IFLNK S_IFLNK
+# define _S_IFLNK S_IFLNK
#endif /* _S_IFLNK */
#ifndef S_ISREG
-# define S_ISREG(m) (((m) & _S_IFMT) == _S_IFREG)
+# define S_ISREG(m) (((m) & _S_IFMT) == _S_IFREG)
#endif /* S_ISREG */
#ifndef S_ISDIR
-# define S_ISDIR(m) (((m) & _S_IFMT) == _S_IFDIR)
+# define S_ISDIR(m) (((m) & _S_IFMT) == _S_IFDIR)
#endif /* S_ISDIR */
/*
* Some OS's may not have this.
*/
#ifndef S_IRWXU
-# define S_IRWXU 0000700 /* rwx for owner */
+# define S_IRWXU 0000700 /* rwx for owner */
#endif /* S_IRWXU */
/*
* In case this is not defined in <sys/types.h> or <sys/select.h>
*/
#ifndef howmany
-#define howmany(x, y) (((x) + ((y) - 1)) / (y))
+# define howmany(x, y) (((x) + ((y) - 1)) / (y))
#endif
/*
* These should be defined in <unistd.h> but not everyone has them.
*/
#ifndef STDIN_FILENO
-# define STDIN_FILENO 0
+# define STDIN_FILENO 0
#endif
#ifndef STDOUT_FILENO
-# define STDOUT_FILENO 1
+# define STDOUT_FILENO 1
#endif
#ifndef STDERR_FILENO
-# define STDERR_FILENO 2
+# define STDERR_FILENO 2
+#endif
+
+/*
+ * These should be defined in <unistd.h> but not everyone has them.
+ */
+#ifndef SEEK_SET
+# define SEEK_SET 0
+#endif
+#ifndef SEEK_CUR
+# define SEEK_CUR 1
+#endif
+#ifndef SEEK_END
+# define SEEK_END 2
#endif
/*
* BSD defines these in <sys/param.h> but others may not.
*/
#ifndef MIN
-#define MIN(a,b) (((a)<(b))?(a):(b))
+# define MIN(a,b) (((a)<(b))?(a):(b))
#endif
#ifndef MAX
-#define MAX(a,b) (((a)>(b))?(a):(b))
+# define MAX(a,b) (((a)>(b))?(a):(b))
#endif
/*
* Emulate seteuid() for HP-UX via setresuid(2) and seteuid(2) for others.
*/
#ifndef HAVE_SETEUID
-# ifdef __hpux
-# define seteuid(_EUID) (setresuid((uid_t) -1, _EUID, (uid_t) -1))
-# else
-# define seteuid(_EUID) (setreuid((uid_t) -1, _EUID))
-# endif /* __hpux */
+# ifdef __hpux
+# define seteuid(_EUID) (setresuid((uid_t) -1, _EUID, (uid_t) -1))
+# else
+# define seteuid(_EUID) (setreuid((uid_t) -1, _EUID))
+# endif /* __hpux */
#endif /* HAVE_SETEUID */
#endif /* _SUDO_COMPAT_H */
/* Define if you have flock(2). */
#undef HAVE_FLOCK
+/* Define if you have ftruncate(2). */
+#undef HAVE_FTRUNCATE
+
/* Define if you have snprintf(3). */
#undef HAVE_SNPRINTF
;;
esac
-for ac_func in strchr strrchr memcpy memset sysconf sigaction tzset strcasecmp seteuid
+for ac_func in strchr strrchr memcpy memset sysconf sigaction tzset strcasecmp seteuid ftruncate
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
echo "configure:5261: checking for $ac_func" >&5
dnl
dnl Function checks
dnl
-AC_CHECK_FUNCS(strchr strrchr memcpy memset sysconf sigaction tzset strcasecmp seteuid)
+AC_CHECK_FUNCS(strchr strrchr memcpy memset sysconf sigaction tzset strcasecmp seteuid ftruncate)
if test -n "$SECUREWARE"; then
AC_CHECK_FUNCS(bigcrypt)
AC_CHECK_FUNCS(set_auth_parameters)
--- /dev/null
+/*
+ * Copyright (c) 1999 Todd C. Miller <Todd.Miller@courtesan.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * 4. Products derived from this software may not be called "Sudo" nor
+ * may "Sudo" appear in their names without specific prior written
+ * permission from the author.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#include <fcntl.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#ifdef HAVE_UTIME
+# ifdef HAVE_UTIME_H
+# include <utime.h>
+# endif /* HAVE_UTIME_H */
+#else
+# include "emul/utime.h"
+#endif /* HAVE_UTIME */
+
+#include "sudo.h"
+
+#ifndef lint
+static const char rcsid[] = "$Sudo$";
+#endif /* lint */
+
+/*
+ * Update the access and modify times on a file.
+ */
+int
+touch(path, when)
+ char *path;
+ time_t when;
+{
+#ifdef HAVE_UTIME_POSIX
+ struct utimbuf ut, *utp;
+
+ ut.actime = ut.modtime = when;
+ utp = &ut;
+#else
+ /* BSD <= 4.3 has no struct utimbuf */
+ time_t utp[2];
+
+ utp[0] = utp[1] = when;
+#endif /* HAVE_UTIME_POSIX */
+
+ return(utime(path, utp));
+}
+
+/*
+ * Lock/unlock a file.
+ */
+#ifdef HAVE_LOCKF
+int
+lock_file(fd, lockit)
+ int fd;
+ int lockit;
+{
+ int op = 0;
+
+ switch (lockit) {
+ case SUDO_LOCK:
+ op = F_LOCK;
+ break;
+ case SUDO_TLOCK:
+ op = F_TLOCK;
+ break;
+ case SUDO_UNLOCK:
+ op = F_ULOCK;
+ break;
+ }
+ return(lockf(fd, op, 0) == 0);
+}
+#elif HAVE_FLOCK
+int
+lock_file(fd, lockit)
+ int fd;
+ int lockit;
+{
+ int op = 0;
+
+ switch (lockit) {
+ case SUDO_LOCK:
+ op = LOCK_EX;
+ break;
+ case SUDO_TLOCK:
+ op = LOCK_EX | LOCK_NB;
+ break;
+ case SUDO_UNLOCK:
+ op = LOCK_EX;
+ break;
+ }
+ return(flock(fd, op) == 0);
+}
+#else
+int
+lock_file(fd, lockit)
+ int fd;
+ int lockit;
+{
+#ifdef F_SETLK
+ int func;
+ struct flock lock;
+
+ lock.l_start = 0;
+ lock.l_len = 0;
+ lock.l_pid = getpid();
+ lock.l_type = (lockit == SUDO_UNLOCK) ? F_UNLCK : F_WRLCK;
+ lock.l_whence = SEEK_SET;
+ func = (lockit == SUDO_TLOCK) ? F_SETLK : F_SETLKW;
+
+ return(fcntl(fd, func, &lock) == 0);
+#else
+ return(TRUE);
+#endif
+}
+#endif
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif /* HAVE_STRINGS_H */
-#include <fcntl.h>
#include <pwd.h>
#include <signal.h>
#include <time.h>
#endif
#if (LOGGING & SLOG_FILE)
static void do_logfile __P((char *));
-static int lock_file __P((FILE *, int));
#endif
static void send_mail __P((char *));
_PATH_SUDO_LOGFILE, strerror(errno));
send_mail(full_line);
free(full_line);
- } else if (!lock_file(fp, TRUE)) {
+ } else if (!lock_file(fileno(fp), SUDO_LOCK)) {
easprintf(&full_line, "Can't lock log file: %s: %s",
_PATH_SUDO_LOGFILE, strerror(errno));
send_mail(full_line);
free(full_line);
# endif
(void) fflush(fp);
- (void) lock_file(fp, FALSE);
+ (void) lock_file(fileno(fp), SUDO_UNLOCK);
(void) fclose(fp);
}
#endif /* POSIX_SIGNALS */
errno = serrno;
}
-
-/*
- * Lock/unlock a file.
- */
-#ifdef HAVE_LOCKF
-static int
-lock_file(fp, lockit)
- FILE *fp;
- int lockit;
-{
- int op;
-
- op = lockit ? F_LOCK : F_ULOCK;
- return(lockf(fileno(fp), op, 0) == 0);
-}
-#elif HAVE_FLOCK
-static int
-lock_file(fp, lockit)
- FILE *fp;
- int lockit;
-{
- int op;
-
- op = lockit ? LOCK_EX : LOCK_UN;
- return(flock(fileno(fp), op) == 0);
-}
-#else
-static int
-lock_file(fp, lockit)
- FILE *fp;
- int lockit;
-{
-#ifdef F_SETLK
- struct flock lock;
-
- lock.l_start = 0;
- lock.l_len = 0;
- lock.l_pid = getpid();
- lock.l_type = lockit ? F_WRLCK : F_UNLCK;
- lock.l_whence = SEEK_SET;
-
- return(fcntl(fileno(fp), F_SETLKW, &lock) == 0);
-#else
- return(TRUE);
-#endif
-}
-#endif
*/
#define SUDO_PASS_MAX 256
+/*
+ * Flags for lock_file()
+ */
+#define SUDO_LOCK 1 /* lock a file */
+#define SUDO_TLOCK 2 /* test & lock a file (non-blocking) */
+#define SUDO_UNLOCK 4 /* unlock a file */
+
/*
* Function prototypes
*/
void easprintf __P((char **, const char *, ...));
void evasprintf __P((char **, const char *, va_list));
void print_version __P((void));
+int lock_file __P((int, int));
+int touch __P((char *, time_t));
YY_DECL;
/* Only provide extern declarations outside of sudo.c. */
/*
* Print compile-time options if root.
+ * At some point these will all be in a structure of some kind
+ * to allow overriding the defaults from sudoers.
+ * XXX - reorganize for readability.
*/
if (getuid() == 0) {
+ (void) printf("\nSudoers file: %s, mode 0%o, uid %d, gid %d\n",
+ _PATH_SUDOERS, SUDOERS_MODE, SUDOERS_UID, SUDOERS_GID);
+ (void) printf("Sudoers temp file: %s\n", _PATH_SUDOERS_TMP);
+
#ifdef WITHOUT_PASSWD
- (void) puts("\nNo Authentication configured\n");
+ (void) puts("No Authentication configured\n");
#else
- (void) fputs("\nAuthentication methods:", stdout);
+ (void) fputs("Authentication methods:", stdout);
for (auth = auth_switch; auth->name; auth++) {
(void) putchar(' ');
(void) fputs(auth->name, stdout);
(void) fputs(" goons", stdout);
# endif
(void) putchar('\n');
+# else
+ (void) printf("Incorrect password message: %s\n", INCORRECT_PASSWORD);
#endif
#ifdef SUDO_UMASK
(void) printf("Editor for visudo: %s\n", EDITOR);
#endif
+#if defined(IGNORE_DOT_PATH) || defined(DONT_LEAK_PATH_INFO) || defined(SECURE_PATH)
+ puts("$PATH options:");
#ifdef SECURE_PATH
- (void) printf("Secure PATH: %s\n", SECURE_PATH);
+ (void) printf(" PATH override: %s\n", SECURE_PATH);
+#endif
+# ifdef IGNORE_DOT_PATH
+ (void) puts(" ignore '.'");
+# endif
+# ifdef DONT_LEAK_PATH_INFO
+ (void) puts(" no information leakage");
+# endif
#endif
#ifdef _PATH_SENDMAIL
(void) printf("Mailer path: %s\n", _PATH_SENDMAIL);
(void) printf("Send mail to: %s\n", ALERTMAIL);
(void) printf("Mail subject: %s\n", MAILSUBJECT);
+ (void) fputs("Send mail on: 'error'", stdout);
+# ifdef SEND_MAIL_WHEN_NO_USER
+ (void) fputs(" 'unlisted user'", stdout);
+# endif
+# ifdef SEND_MAIL_WHEN_NOT_OK
+ (void) fputs(" 'authentication failure'", stdout);
+# endif
+ (void) putchar('\n');
+#endif
+
+#ifdef SHELL_IF_NO_ARGS
+ puts("When invoked with no arguments sudo will start a shell")
+#endif
+
+#ifdef SHELL_SETS_HOME
+ puts("Sudo will set $HOME to the homedir of the target user");
#endif
(void) printf("Default password prompt: %s\n", PASSPROMPT);
#else
(void) puts("no");
#endif
-
-/* stopped at INCORRECT_PASSWORD */
-
- /* XXX - more */
-
-/*
--D_PATH_SUDO_SUDOERS=\"/etc/sudoers\" -D_PATH_SUDO_STMP=\"/etc/stmp\" -DSUDOERS_UID=0 -DSUDOERS_GID=0 -DSUDOERS_MODE=0440
-*/
}
}
#endif /* HAVE_MALLOC_H && !STDC_HEADERS */
#include <ctype.h>
#include <pwd.h>
+#include <time.h>
#include <signal.h>
#include <errno.h>
#include <fcntl.h>
int sudoers_fd; /* sudoers file descriptor */
int stmp_fd; /* stmp file descriptor */
int n; /* length parameter */
+ time_t now; /* time now */
+ struct stat stmp_sb, sudoers_sb; /* to check for changes */
- (void) setbuf(stderr, (char *)NULL); /* unbuffered stderr */
/*
* Parse command line options
#endif /* ENV_EDITOR */
/*
- * Copy sudoers file to stmp
+ * Open sudoers temp file and grab a lock.
*/
- stmp_fd = open(stmp, O_WRONLY | O_CREAT | O_EXCL, 0600);
+ stmp_fd = open(stmp, O_WRONLY | O_CREAT, 0600);
if (stmp_fd < 0) {
- if (errno == EEXIST) {
- (void) fprintf(stderr, "%s: sudoers file busy, try again later.\n",
- Argv[0]);
- exit(1);
- }
(void) fprintf(stderr, "%s: %s\n", Argv[0], strerror(errno));
+ exit(1);
+ }
+ if (!lock_file(stmp_fd, SUDO_TLOCK)) {
+ (void) fprintf(stderr, "%s: sudoers file busy, try again later.\n",
+ Argv[0]);
+ exit(1);
+ }
+#ifdef HAVE_FTRUNCATE
+ if (ftruncate(stmp_fd, 0) == -1) {
+#else
+ if (truncate(stmp, 0) == -1) {
+#endif
+ (void) fprintf(stderr, "%s: can't truncate %s: %s\n", Argv[0],
+ stmp, strerror(errno));
Exit(-1);
}
/* Install signal handlers to clean up stmp if we are killed. */
setup_signals();
+ (void) memset(&sudoers_sb, 0, sizeof(sudoers_sb));
+ if (stat(sudoers, &sudoers_sb) == -1 && errno != ENOENT) {
+ (void) fprintf(stderr, "%s: %s\n", Argv[0], strerror(errno));
+ Exit(-1);
+ }
sudoers_fd = open(sudoers, O_RDONLY);
- if (sudoers_fd < 0 && errno != ENOENT) {
+ if (sudoers_fd == -1 && errno != ENOENT) {
(void) fprintf(stderr, "%s: %s\n", Argv[0], strerror(errno));
Exit(-1);
}
- /* Copy sudoers -> stmp */
- if (sudoers_fd >= 0) {
+ /* Copy sudoers -> stmp and reset the mtime */
+ if (sudoers_fd != -1) {
while ((n = read(sudoers_fd, buf, sizeof(buf))) > 0)
if (write(stmp_fd, buf, n) != n) {
(void) fprintf(stderr, "%s: Write failed: %s\n", Argv[0],
(void) close(sudoers_fd);
}
(void) close(stmp_fd);
+ (void) touch(stmp, sudoers_sb.st_mtime);
/*
* Edit the temp file and parse it (for sanity checking)
(void) sprintf(buf, "%s %s", Editor, stmp);
/* Do the edit -- some SYSV editors exit with 1 instead of 0 */
+ now = time(NULL);
n = system(buf);
if (n != -1 && ((n >> 8) == 0 || (n >> 8) == 1)) {
- struct stat statbuf; /* for sanity checking */
-
/*
* Sanity checks.
*/
- if (stat(stmp, &statbuf) < 0) {
+ if (stat(stmp, &stmp_sb) < 0) {
(void) fprintf(stderr,
"%s: Can't stat temporary file (%s), %s unchanged.\n",
Argv[0], stmp, sudoers);
Exit(-1);
}
- if (statbuf.st_size == 0) {
+ if (stmp_sb.st_size == 0) {
(void) fprintf(stderr,
"%s: Zero length temporary file (%s), %s unchanged.\n",
Argv[0], stmp, sudoers);
}
} while (parse_error == TRUE);
+ /*
+ * If the user didn't change the temp file, just unlink it.
+ */
+ if (sudoers_sb.st_mtime != now && sudoers_sb.st_mtime == stmp_sb.st_mtime &&
+ sudoers_sb.st_size == stmp_sb.st_size) {
+ (void) fprintf(stderr, "%s: sudoers file unchanged.\n", Argv[0]);
+ Exit(0);
+ }
+
/*
* Change mode and ownership of temp file so when
* we move it to sudoers things are kosher.
usage()
{
(void) fprintf(stderr, "usage: %s [-V]\n", Argv[0]);
- Exit(-1);
+ exit(1);
}