561) Fixed setting of $USER when env_reset is enabled.
Sudo 1.6.8p7 released.
+
+562) Fixed noexec functionality on Linux.
+
+563) Fixed minor format string mismatches in some error cases.
+
+564) Fixed a bug that prevented Heimdal authentication from working.
+
+Sudo 1.6.8p8 released.
+
+565) Updated config.guess and config.sub entries for OpenBSD.
+
+566) A sudoers entry with sudo ALL no longer overwrites the value of
+ safe_cmnd.
+
+Sudo 1.6.8p9 released.
LIBOBJS = @LIBOBJS@ @ALLOCA@
-VERSION = 1.6.8p7
+VERSION = 1.6.8p9
DISTFILES = $(SRCS) $(HDRS) BUGS CHANGES HISTORY INSTALL INSTALL.configure \
LICENSE Makefile.in PORTING README README.LDAP RUNSON TODO \
#endif /* lint */
#ifdef HAVE_HEIMDAL
-# define extract_name(c, p) krb5_principal_get_comp_string(c, p, 0)
+# define extract_name(c, p) krb5_principal_get_comp_string(c, p, 1)
# define krb5_free_data_contents(c, d) krb5_data_free(d)
# define ENCTYPE_DES_CBC_MD5 ETYPE_DES_CBC_MD5 /* XXX */
#else
dirparent = def_timestampdir;
len = easprintf(timestampdir, "%s/%s", dirparent, user_name);
if (len >= PATH_MAX)
- log_error(0, "timestamp path too long: %s", timestampdir);
+ log_error(0, "timestamp path too long: %s", *timestampdir);
/*
* Timestamp file may be a file in the directory or NUL to use
else
len = easprintf(timestampfile, "%s/%s/%s", dirparent, user_name, p);
if (len >= PATH_MAX)
- log_error(0, "timestamp path too long: %s", timestampfile);
+ log_error(0, "timestamp path too long: %s", *timestampfile);
} else if (def_targetpw) {
len = easprintf(timestampfile, "%s/%s/%s", dirparent, user_name,
*user_runas);
if (len >= PATH_MAX)
- log_error(0, "timestamp path too long: %s", timestampfile);
+ log_error(0, "timestamp path too long: %s", *timestampfile);
} else
*timestampfile = NULL;
}
/* If bad uid or file mode, complain and kill the bogus file. */
if (sb.st_uid != timestamp_uid) {
log_error(NO_EXIT,
- "%s owned by uid %ud, should be uid %lu",
+ "%s owned by uid %lu, should be uid %lu",
timestampfile, (unsigned long) sb.st_uid,
(unsigned long) timestamp_uid);
(void) unlink(timestampfile);
#! /bin/sh
# Attempt to guess a canonical system name.
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-# 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
-timestamp='2004-11-12'
+timestamp='2005-04-22'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
GNU config.guess ($timestamp)
Originally written by Per Bothner.
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
i*:UWIN*:*)
echo ${UNAME_MACHINE}-pc-uwin
exit 0 ;;
+ amd64:CYGWIN*:*:*)
+ echo x86_64-unknown-cygwin
+ exit 0 ;;
p*:CYGWIN*:*)
echo powerpcle-unknown-cygwin
exit 0 ;;
# From seanf@swdc.stratus.com.
echo i860-stratus-sysv4
exit 0 ;;
+ i*86:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo ${UNAME_MACHINE}-stratus-vos
+ exit 0 ;;
*:VOS:*:*)
# From Paul.Green@stratus.com.
echo hppa1.1-stratus-vos
*:QNX:*:4*)
echo i386-pc-qnx
exit 0 ;;
+ NSE-?:NONSTOP_KERNEL:*:*)
+ echo nse-tandem-nsk${UNAME_RELEASE}
+ exit 0 ;;
NSR-?:NONSTOP_KERNEL:*:*)
echo nsr-tandem-nsk${UNAME_RELEASE}
exit 0 ;;
the operating system you are using. It is advised that you
download the most up to date version of the config scripts from
- ftp://ftp.gnu.org/pub/gnu/config/
+ http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.guess
+and
+ http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.sub
If the version you run ($0) is already up to date, please
send the following data and any information you think might be
#! /bin/sh
# Configuration validation subroutine script.
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-# 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
-timestamp='2004-11-30'
+timestamp='2005-04-22'
# This file is (in principle) common to ALL GNU software.
# The presence of a machine in this file suggests that SOME GNU software
version="\
GNU config.sub ($timestamp)
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
| am33_2.0 \
| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
+ | bfin \
| c4x | clipper \
| d10v | d30v | dlx | dsp16xx \
| fr30 | frv \
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
| i370 | i860 | i960 | ia64 \
| ip2k | iq2000 \
- | m32r | m32rle | m68000 | m68k | m88k | mcore \
+ | m32r | m32rle | m68000 | m68k | m88k | maxq | mcore \
| mips | mipsbe | mipseb | mipsel | mipsle \
| mips16 \
| mips64 | mips64el \
| pyramid \
| sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
| sh64 | sh64le \
- | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv8 | sparcv9 | sparcv9b \
+ | sparc | sparc64 | sparc64b | sparc86x | sparclet | sparclite \
+ | sparcv8 | sparcv9 | sparcv9b \
| strongarm \
| tahoe | thumb | tic4x | tic80 | tron \
| v850 | v850e \
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
| avr-* \
- | bs2000-* \
+ | bfin-* | bs2000-* \
| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
| clipper-* | craynv-* | cydra-* \
| d10v-* | d30v-* | dlx-* \
| ip2k-* | iq2000-* \
| m32r-* | m32rle-* \
| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
- | m88110-* | m88k-* | mcore-* \
+ | m88110-* | m88k-* | maxq-* | mcore-* \
| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
| mips16-* \
| mips64-* | mips64el-* \
| romp-* | rs6000-* \
| sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
- | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \
+ | sparc-* | sparc64-* | sparc64b-* | sparc86x-* | sparclet-* \
+ | sparclite-* \
| sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
| tahoe-* | thumb-* \
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+sudo (1.6.8p9-1) unstable; urgency=high
+
+ * new upstream version, fixes a race condition in sudo's pathname
+ validation, which is a security issue (CAN-2005-1993),
+ closes: #315115, #315718
+
+ -- Bdale Garbee <bdale@gag.com> Tue, 28 Jun 2005 15:33:11 -0400
+
sudo (1.6.8p7-1) unstable; urgency=low
* new upstream version, closes: #299585
/* Match against ALL ? */
if (!strcasecmp(*p,"ALL")) {
ret=1;
- if (safe_cmnd) free (safe_cmnd);
- safe_cmnd=estrdup(user_cmnd);
if (ldap_conf.debug>1) printf(" MATCH!\n");
continue;
}
}
$$ = TRUE;
-
- if (safe_cmnd)
- free(safe_cmnd);
- safe_cmnd = estrdup(user_cmnd);
}
| ALIAS {
aliasinfo *aip;
/* Validate the user but don't search for pseudo-commands. */
validated = sudoers_lookup(pwflag);
}
+ if (safe_cmnd == NULL)
+ safe_cmnd = user_cmnd;
/*
* If we are using set_perms_posix() and the stay_setuid flag was not set,
exit(0);
}
- /* This *must* have been set if we got a match but... */
- if (safe_cmnd == NULL) {
- log_error(MSG_ONLY,
- "internal error, safe_cmnd never got set for %s; %s",
- user_cmnd,
- "please report this error at http://courtesan.com/sudo/bugs/");
- }
-
/* Override user's umask if configured to do so. */
if (def_umask != 0777)
(void) umask(def_umask);
(statbuf.st_mode & 07777), SUDOERS_MODE);
else if (statbuf.st_uid != SUDOERS_UID)
log_error(0, "%s is owned by uid %lu, should be %lu", _PATH_SUDOERS,
- (unsigned long) statbuf.st_uid, SUDOERS_UID);
+ (unsigned long) statbuf.st_uid, (unsigned long) SUDOERS_UID);
else if (statbuf.st_gid != SUDOERS_GID)
log_error(0, "%s is owned by gid %lu, should be %lu", _PATH_SUDOERS,
- (unsigned long) statbuf.st_gid, SUDOERS_GID);
+ (unsigned long) statbuf.st_gid, (unsigned long) SUDOERS_GID);
else {
/* Solaris sometimes returns EAGAIN so try 10 times */
for (i = 0; i < 10 ; i++) {
} else if (def_targetpw) {
if (runas_pw->pw_name == NULL)
log_error(NO_MAIL|MSG_ONLY, "no passwd entry for %lu!",
- runas_pw->pw_uid);
+ (unsigned long) runas_pw->pw_uid);
pw = runas_pw;
} else
pw = sudo_user.pw;
-1.6.8p7 February 5, 2005 1
+1.6.8p9 June, 20 2005 1
-1.6.8p7 February 5, 2005 2
+1.6.8p9 June, 20 2005 2
-1.6.8p7 February 5, 2005 3
+1.6.8p9 June, 20 2005 3
-1.6.8p7 February 5, 2005 4
+1.6.8p9 June, 20 2005 4
-1.6.8p7 February 5, 2005 5
+1.6.8p9 June, 20 2005 5
-1.6.8p7 February 5, 2005 6
+1.6.8p9 June, 20 2005 6
-1.6.8p7 February 5, 2005 7
+1.6.8p9 June, 20 2005 7
-1.6.8p7 February 5, 2005 8
+1.6.8p9 June, 20 2005 8
-1.6.8p7 February 5, 2005 9
+1.6.8p9 June, 20 2005 9
.\" ========================================================================
.\"
.IX Title "SUDO @mansectsu@"
-.TH SUDO @mansectsu@ "February 5, 2005" "1.6.8p7" "MAINTENANCE COMMANDS"
+.TH SUDO @mansectsu@ "June 20, 2005" "1.6.8p9" "MAINTENANCE COMMANDS"
.SH "NAME"
sudo, sudoedit \- execute a command as another user
.SH "SYNOPSIS"
#if __GNUC__ >= 2
__attribute__ ((unused))
#endif /* __GNUC__ >= 2 */
- = "$OpenBSD: skeleton.c,v 1.23 2004/03/12 13:39:50 henning Exp $";
+ = "$OpenBSD: skeleton.c,v 1.24 2005/06/10 16:40:45 pvalchev Exp $";
#endif
#include <stdlib.h>
#define YYBYACC 1
#endif /* HAVE_LSEARCH */
#ifndef lint
-static const char rcsid[] = "$Sudo: sudo.tab.c,v 1.76 2004/08/11 18:29:36 millert Exp $";
+static const char rcsid[] = "$Sudo: parse.yacc,v 1.204 2004/08/11 18:29:10 millert Exp $";
#endif /* lint */
/*
short *yysslim;
YYSTYPE *yyvs;
int yystacksize;
-#line 890 "parse.yacc"
+#line 886 "parse.yacc"
#define MOREALIASES (32)
aliasinfo *aliases = NULL;
}
yyval.BOOLEAN = TRUE;
-
- if (safe_cmnd)
- free(safe_cmnd);
- safe_cmnd = estrdup(user_cmnd);
}
break;
case 61:
-#line 684 "parse.yacc"
+#line 680 "parse.yacc"
{
aliasinfo *aip;
}
break;
case 62:
-#line 713 "parse.yacc"
+#line 709 "parse.yacc"
{
if (printmatches == TRUE) {
if (in_alias == TRUE) {
}
break;
case 65:
-#line 744 "parse.yacc"
+#line 740 "parse.yacc"
{ push; }
break;
case 66:
-#line 744 "parse.yacc"
+#line 740 "parse.yacc"
{
if ((MATCHED(host_matches) || pedantic) &&
!add_alias(yyvsp[-3].string, HOST_ALIAS, host_matches)) {
}
break;
case 71:
-#line 762 "parse.yacc"
+#line 758 "parse.yacc"
{
push;
if (printmatches == TRUE) {
}
break;
case 72:
-#line 771 "parse.yacc"
+#line 767 "parse.yacc"
{
if ((MATCHED(cmnd_matches) || pedantic) &&
!add_alias(yyvsp[-3].string, CMND_ALIAS, cmnd_matches)) {
}
break;
case 73:
-#line 785 "parse.yacc"
+#line 781 "parse.yacc"
{ ; }
break;
case 77:
-#line 793 "parse.yacc"
+#line 789 "parse.yacc"
{
if (printmatches == TRUE) {
in_alias = TRUE;
}
break;
case 78:
-#line 801 "parse.yacc"
+#line 797 "parse.yacc"
{
if ((yyvsp[0].BOOLEAN != NOMATCH || pedantic) &&
!add_alias(yyvsp[-3].string, RUNAS_ALIAS, yyvsp[0].BOOLEAN)) {
}
break;
case 81:
-#line 818 "parse.yacc"
+#line 814 "parse.yacc"
{ push; }
break;
case 82:
-#line 818 "parse.yacc"
+#line 814 "parse.yacc"
{
if ((MATCHED(user_matches) || pedantic) &&
!add_alias(yyvsp[-3].string, USER_ALIAS, user_matches)) {
}
break;
case 85:
-#line 833 "parse.yacc"
+#line 829 "parse.yacc"
{
SETMATCH(user_matches, yyvsp[0].BOOLEAN);
}
break;
case 86:
-#line 836 "parse.yacc"
+#line 832 "parse.yacc"
{
SETNMATCH(user_matches, yyvsp[0].BOOLEAN);
}
break;
case 87:
-#line 841 "parse.yacc"
+#line 837 "parse.yacc"
{
if (userpw_matches(yyvsp[0].string, user_name, sudo_user.pw))
yyval.BOOLEAN = TRUE;
}
break;
case 88:
-#line 848 "parse.yacc"
+#line 844 "parse.yacc"
{
if (usergr_matches(yyvsp[0].string, user_name, sudo_user.pw))
yyval.BOOLEAN = TRUE;
}
break;
case 89:
-#line 855 "parse.yacc"
+#line 851 "parse.yacc"
{
if (netgr_matches(yyvsp[0].string, NULL, NULL, user_name))
yyval.BOOLEAN = TRUE;
}
break;
case 90:
-#line 862 "parse.yacc"
+#line 858 "parse.yacc"
{
aliasinfo *aip = find_alias(yyvsp[0].string, USER_ALIAS);
}
break;
case 91:
-#line 884 "parse.yacc"
+#line 880 "parse.yacc"
{
yyval.BOOLEAN = TRUE;
}
break;
-#line 1920 "sudo.tab.c"
+#line 1916 "sudo.tab.c"
}
yyssp -= yym;
yystate = *yyssp;
/*
- * Copyright (c) 2004 Todd C. Miller <Todd.Miller@courtesan.com>
+ * Copyright (c) 2004-2005 Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
#include "config.h"
#include <errno.h>
+#ifdef __STDC__
+# include <stdarg.h>
+#else
+# include <varargs.h>
+#endif
#ifndef lint
-static const char rcsid[] = "$Sudo: sudo_noexec.c,v 1.5 2004/02/13 21:36:43 millert Exp $";
+static const char rcsid[] = "$Sudo: sudo_noexec.c,v 1.11 2005/03/10 15:09:28 millert Exp $";
#endif /* lint */
/*
extern int errno;
#endif
-#define DUMMY(fn, args, atypes) \
-int \
-fn args \
- atypes \
-{ \
- errno = EACCES; \
- return(-1); \
+#define DUMMY_BODY \
+{ \
+ errno = EACCES; \
+ return(-1); \
}
-DUMMY(execve, (path, argv, envp),
- const char *path; char *const argv[]; char *const envp[];)
-DUMMY(_execve, (path, argv, envp),
- const char *path; char *const argv[]; char *const envp[];)
-DUMMY(execv, (path, argv, envp),
- const char *path; char *const argv[];)
-DUMMY(_execv, (path, argv, envp),
- const char *path; char *const argv[];)
-DUMMY(fexecve, (fd, argv, envp),
- int fd; char *const argv[]; char *const envp[];)
-DUMMY(_fexecve, (fd, argv, envp),
- int fd; char *const argv[]; char *const envp[];)
+#ifdef __STDC__
+
+#define DUMMY2(fn, t1, t2) \
+int \
+fn(t1 a1, t2 a2) \
+DUMMY_BODY
+
+#define DUMMY3(fn, t1, t2, t3) \
+int \
+fn(t1 a1, t2 a2, t3 a3) \
+DUMMY_BODY
+
+#define DUMMY_VA(fn, t1, t2) \
+int \
+fn(t1 a1, t2 a2, ...) \
+DUMMY_BODY
+
+#else /* !__STDC__ */
+
+#define DUMMY2(fn, t1, t2) \
+int \
+fn(a1, a2) \
+t1 a1; t2 a2; \
+DUMMY_BODY
+
+#define DUMMY3(fn, t1, t2, t3) \
+int \
+fn(a1, a2, a3) \
+t1 a1; t2 a2; t3 a3; \
+DUMMY_BODY
+
+#define DUMMY_VA(fn, t1, t2) \
+int \
+fn(a1, a2, va_alist) \
+t1 a1; t2 a2; va_dcl \
+DUMMY_BODY
+
+#endif /* !__STDC__ */
+
+DUMMY_VA(execl, const char *, const char *)
+DUMMY_VA(_execl, const char *, const char *)
+DUMMY_VA(__execl, const char *, const char *)
+DUMMY_VA(execle, const char *, const char *)
+DUMMY_VA(_execle, const char *, const char *)
+DUMMY_VA(__execle, const char *, const char *)
+DUMMY_VA(execlp, const char *, const char *)
+DUMMY_VA(_execlp, const char *, const char *)
+DUMMY_VA(__execlp, const char *, const char *)
+DUMMY2(execv, const char *, char * const *)
+DUMMY2(_execv, const char *, char * const *)
+DUMMY2(__execv, const char *, char * const *)
+DUMMY2(execvp, const char *, char * const *)
+DUMMY2(_execvp, const char *, char * const *)
+DUMMY2(__execvp, const char *, char * const *)
+DUMMY3(execvP, const char *, const char *, char * const *)
+DUMMY3(_execvP, const char *, const char *, char * const *)
+DUMMY3(__execvP, const char *, const char *, char * const *)
+DUMMY3(execve, const char *, char * const *, char * const *)
+DUMMY3(_execve, const char *, char * const *, char * const *)
+DUMMY3(__execve, const char *, char * const *, char * const *)
+DUMMY3(fexecve, int , char * const *, char * const *)
+DUMMY3(_fexecve, int , char * const *, char * const *)
+DUMMY3(__fexecve, int , char * const *, char * const *)
-1.6.8p7 February 5, 2005 1
+1.6.8p9 June, 20 2005 1
-1.6.8p7 February 5, 2005 2
+1.6.8p9 June, 20 2005 2
-1.6.8p7 February 5, 2005 3
+1.6.8p9 June, 20 2005 3
-1.6.8p7 February 5, 2005 4
+1.6.8p9 June, 20 2005 4
-1.6.8p7 February 5, 2005 5
+1.6.8p9 June, 20 2005 5
-1.6.8p7 February 5, 2005 6
+1.6.8p9 June, 20 2005 6
-1.6.8p7 February 5, 2005 7
+1.6.8p9 June, 20 2005 7
-1.6.8p7 February 5, 2005 8
+1.6.8p9 June, 20 2005 8
-1.6.8p7 February 5, 2005 9
+1.6.8p9 June, 20 2005 9
-1.6.8p7 February 5, 2005 10
+1.6.8p9 June, 20 2005 10
-1.6.8p7 February 5, 2005 11
+1.6.8p9 June, 20 2005 11
-1.6.8p7 February 5, 2005 12
+1.6.8p9 June, 20 2005 12
-1.6.8p7 February 5, 2005 13
+1.6.8p9 June, 20 2005 13
-1.6.8p7 February 5, 2005 14
+1.6.8p9 June, 20 2005 14
-1.6.8p7 February 5, 2005 15
+1.6.8p9 June, 20 2005 15
-1.6.8p7 February 5, 2005 16
+1.6.8p9 June, 20 2005 16
-1.6.8p7 February 5, 2005 17
+1.6.8p9 June, 20 2005 17
-1.6.8p7 February 5, 2005 18
+1.6.8p9 June, 20 2005 18
-1.6.8p7 February 5, 2005 19
+1.6.8p9 June, 20 2005 19
-1.6.8p7 February 5, 2005 20
+1.6.8p9 June, 20 2005 20
-1.6.8p7 February 5, 2005 21
+1.6.8p9 June, 20 2005 21
-1.6.8p7 February 5, 2005 22
+1.6.8p9 June, 20 2005 22
-1.6.8p7 February 5, 2005 23
+1.6.8p9 June, 20 2005 23
.\" ========================================================================
.\"
.IX Title "SUDOERS @mansectform@"
-.TH SUDOERS @mansectform@ "February 5, 2005" "1.6.8p7" "MAINTENANCE COMMANDS"
+.TH SUDOERS @mansectform@ "June 20, 2005" "1.6.8p9" "MAINTENANCE COMMANDS"
.SH "NAME"
sudoers \- list of which users may execute what
.SH "DESCRIPTION"
#ifndef _SUDO_VERSION_H
#define _SUDO_VERSION_H
-static const char version[] = "1.6.8p7";
+static const char version[] = "1.6.8p9";
#endif /* _SUDO_VERSION_H */
-1.6.8p7 February 5, 2005 1
+1.6.8p9 June, 20 2005 1
-1.6.8p7 February 5, 2005 2
+1.6.8p9 June, 20 2005 2
-1.6.8p7 February 5, 2005 3
+1.6.8p9 June, 20 2005 3
.\" ========================================================================
.\"
.IX Title "VISUDO @mansectsu@"
-.TH VISUDO @mansectsu@ "February 5, 2005" "1.6.8p7" "MAINTENANCE COMMANDS"
+.TH VISUDO @mansectsu@ "June 20, 2005" "1.6.8p9" "MAINTENANCE COMMANDS"
.SH "NAME"
visudo \- edit the sudoers file
.SH "SYNOPSIS"