diff --git a/sudoers.cat b/sudoers.cat
index 9adeec73b..1e4c85a73 100644
--- a/sudoers.cat
+++ b/sudoers.cat
@@ -1,155 +1,279 @@
 
 
 
-sudoers(5)                 FILE FORMATS                sudoers(5)
+SUDOERS(5)                 FILE FORMATS                SUDOERS(5)
 
 
 NNNNAAAAMMMMEEEE
-       sudoers - list of which users may execute what as root
+       sudoers - list of which users may execute what
 
 DDDDEEEESSSSCCCCRRRRIIIIPPPPTTTTIIIIOOOONNNN
-       The _s_u_d_o_e_r_s file is composed of an optional host alias
-       section, an optional command alias section and the user
-       specification section.  All command or host aliases need
-       to start with their respective keywords (ie: Host_Alias,
-       User_Alias, Runas_Alias or Cmnd_Alias).  If there are
-       multiple occurrences of a user, the logical union of the
-       entries will be used.  Note that if there is an entry that
-       denies access to a command that is followed by an entry
-       that grants access the user will be allowed to run the
-       command.
+       The _s_u_d_o_e_r_s file is composed two types of entries: aliases
+       (basically variables) and user specifications (which
+       specify who may run what).  The grammar of _s_u_d_o_e_r_s will be
+       described below in Extended Backus-Naur Form (EBNF).
+       Don't despair if you don't know what EBNF is, it is fairly
+       simple and the definitions below are annotated.
 
-       uuuusssseeeerrrr ssssppppeeeecccciiiiffffiiiiccccaaaattttiiiioooonnnn ffffoooorrrrmmmmaaaatttt::::
+       QQQQuuuuiiiicccckkkk gggguuuuiiiiddddeeee ttttoooo EEEEBBBBNNNNFFFF
 
+       EBNF is a concise and exact way of describing the grammar
+       of a language.  Each EBNF definition is made up of
+       _p_r_o_d_u_c_t_i_o_n _r_u_l_e_s.  Eg.
 
-         user access_group [: access_group] ...
+        symbol ::= definition | alternate1 | alternate2 ...
 
-           access_group ::= host-list = [(runas-list)] [NOPASSWD:] [op]cmnd_type
-                            [,[(user-list)] [NOPASSWD|PASSWD:] [op]cmnd_type] ...
-              cmnd_type ::= a command OR a command alias.
-                     op ::= the logical "!" NOT operator.
+       Each _p_r_o_d_u_c_t_i_o_n _r_u_l_e references others and thus makes up a
+       grammar for the language.  EBNF also contains the
+       following operators, which many readers will recognize
+       from regular expressions.  Do not, however, confuse them
+       with "wildcard" characters, which have different meanings.
 
+       ?       Means that the preceding symbol (or group of
+               symbols) is optional.  That is, it may appear once
+               or not at all.
 
-       hhhhoooosssstttt aaaalllliiiiaaaassss sssseeeeccccttttiiiioooonnnn ffffoooorrrrmmmmaaaatttt::::
+       *       Means that the preceding symbol (or group of
+               symbols) may appear zero or more times.
 
+       +       Means that the preceding symbol (or group of
+               symbols) may appear one or more times.
 
-         Host_Alias HOSTALIAS = host-list
+       Parentheses may be used to group symbols together.  For
+       clarity, we will use single quotes ('') to designate what
+       is a verbatim character string (as opposed to a symbol
+       name).
 
-             Host_Alias ::= a keyword.
-              HOSTALIAS ::= an upper-case alias name.
-              host-list ::= a comma separated list of hosts, netgroups,
-                            ip addresses, networks.  A logical "!"
-                            NOT operator may be prefixed to any of these.
+       AAAAlllliiiiaaaasssseeeessss
 
+       There are four kinds of aliases: the User_Alias,
+       Runas_Alias, Host_Alias and Cmnd_Alias.
 
-       uuuusssseeeerrrr aaaalllliiiiaaaassss sssseeeeccccttttiiiioooonnnn ffffoooorrrrmmmmaaaatttt::::
+        Alias ::= User_Alias = User_Alias (':' User_Alias)* |
+                  Runas_Alias (':' Runas_Alias)* |
+                  Host_Alias (':' Host_Alias)* |
+                  Cmnd_Alias (':' Cmnd_Alias)*
 
+        User_Alias ::= NAME '=' User_List
 
-         User_Alias USERALIAS = user-list
-
-             User_Alias ::= a keyword.
-              USERALIAS ::= an upper-case alias name.
-              user-list ::= a comma separated list of users, groups, netgroups.
-                            A logical "!" NOT operator may be prefixed to any
-                            of these.
-
-
-       rrrruuuunnnnaaaassss aaaalllliiiiaaaassss sssseeeeccccttttiiiioooonnnn ffffoooorrrrmmmmaaaatttt::::
-
-
-         Runas_Alias RUNASALIAS = runas-list
+        Runas_Alias ::= NAME '=' Runas_User_List
 
 
 
-22/Jun/1999                    1.6                              1
+
+25/Aug/1999                    1.6                              1
 
 
 
 
 
-sudoers(5)                 FILE FORMATS                sudoers(5)
+SUDOERS(5)                 FILE FORMATS                SUDOERS(5)
 
 
-             Runas_Alias ::= a keyword.
-              RUNASALIAS ::= an upper-case alias name.
-              runas-list ::= a comma separated list of users, groups, netgroups.
-                             A logical "!" NOT operator may be prefixed to any
-                             of these.
+        Host_Alias ::= NAME '=' Host_List
 
+        Cmnd_Alias ::= NAME '=' Cmnd_List
 
-       ccccoooommmmmmmmaaaannnndddd aaaalllliiiiaaaassss sssseeeeccccttttiiiioooonnnn ffffoooorrrrmmmmaaaatttt::::
+        NAME ::= [A-Z]([A-Z][0-9]_)*
 
+       Each _a_l_i_a_s definition is of the form
 
-         Cmnd_Alias CMNDALIAS = cmnd-list
+        Alias_Type NAME = item1, item2, ...
 
-             Cmnd_Alias ::= a keyword.
-              CMNDALIAS ::= an upper-case alias name.
-              cmnd-list ::= a comma separated list commands.
-                            A logical "!" NOT operator may be prefixed to any
-                            of these.
+       where _A_l_i_a_s___T_y_p_e is one of User_Alias, Runas_Alias,
+       Host_Alias, or Cmnd_Alias.  A NAME is a string of upper
+       case letters, numbers, and the underscore characters
+       ('_').  A NAME mmmmuuuusssstttt start with an upper case letter.  It
+       is possible to put several alias definitions of the same
+       type on a single line, joined by a semicolon (':').  Eg.
 
+        Alias_Type NAME = item1, item2, item3 : NAME = item4, item5
 
-       ccccoooommmmmmmmaaaannnndddd ssssppppeeeecccciiiiffffiiiiccccaaaattttiiiioooonnnn::::
+       The definitions of what constitutes a valid _a_l_i_a_s member
+       follow.
 
+        User_List ::= User |
+                      User ',' User_List
 
-         path arg1 arg2 .. argn = command
+        User ::= '!'* username |
+                 '!'* '#'uid |
+                 '!'* '%'group |
+                 '!'* '+'netgroup |
+                 '!'* User_Alias
 
-                   path ::= a fully qualified pathname.
-              arg[1..n] ::= optional command line arguments.
+       A User_List is made up of one or more usernames, uids
+       (prefixed with '#'), System groups (prefixed with '%'),
+       netgroups (prefixed with '+') and other aliases.  Each
+       list item may be prefixed with one or more '!' operators.
+       An odd number of '!' operators negates the value of the
+       item; an even number just cancel each other out.
 
+        Runas_List ::= Runas_User |
+                       Runas_User ',' Runas_List
 
-       ppppeeeerrrrssssiiiisssstttteeeennnncccceeee ooooffff mmmmooooddddiiiiffffiiiieeeerrrrssss
+        Runas_User ::= '!'* username |
+                       '!'* '#'uid |
+                       '!'* '%'group |
+                       '!'* +netgroup |
+                       '!'* Runas_Alias
 
-       When a _r_u_n_a_s_-_l_i_s_t is specified for an _a_c_c_e_s_s___g_r_o_u_p, it
-       affects all commands in the _a_c_c_e_s_s___g_r_o_u_p.  For example,
-       given:
+       Likewise, a Runas_List has the same possible elements as a
+       User_List, except that it can include a Runas_Alias,
+       instead of a User_Alias.
 
-           oper bigserver = (root, sysadm) /usr/bin/kill, /bin/rm
-
-       User oper will be able to run /usr/bin/kill and /bin/rm as
-       rrrrooooooootttt or ssssyyyyssssaaaaddddmmmm on the machine, bigserver.  The _r_u_n_a_s_-_l_i_s_t
-       is "sticky" across entries in the comma-separated
-       _a_c_c_e_s_s___g_r_o_u_p.  You can override the _r_u_n_a_s_-_l_i_s_t with
-       another one, at which point the new _r_u_n_a_s_-_l_i_s_t becomes the
-       default for that _a_c_c_e_s_s___g_r_o_u_p.  For example, given:
-
-           oper bigserver = (root, sysadm) /usr/bin/kill, (root) /bin/rm, \
-               /bin/rmdir
-
-       User oper can still run /usr/bin/kill as rrrrooooooootttt or ssssyyyyssssaaaaddddmmmm
-       but can only run /bin/rm and /bin/rmdir as rrrrooooooootttt.
-
-       Similarly, the NNNNOOOOPPPPAAAASSSSSSSSWWWWDDDD modifier is also persistent across
-       an _a_c_c_e_s_s___g_r_o_u_p. For example given:
-
-           oper bigserver = NOPASSWD: /usr/bin/kill, /bin/rm, /bin/rmdir
+        Host_List ::= Host |
+                      Host ',' Host_List
 
 
 
 
-22/Jun/1999                    1.6                              2
+25/Aug/1999                    1.6                              2
 
 
 
 
 
-sudoers(5)                 FILE FORMATS                sudoers(5)
+SUDOERS(5)                 FILE FORMATS                SUDOERS(5)
 
 
-       User oper will be able to run /usr/bin/kill, /bin/rm, and
-       /bin/rmdir as rrrrooooooootttt without a password.  If we change that
-       to:
+        Host ::= '!'* hostname |
+                 '!'* ip_addr |
+                 '!'* network(/netmask)? |
+                 '!'* '+'netgroup |
+                 '!'* Host_Alias
 
-           oper bigserver = NOPASSWD: /usr/bin/kill, PASSWD: /bin/rm, /bin/rmdir
+       A Host_List is made up of one or more hostnames, IP
+       addresses, network numbers, netgroups (prefixed with '+')
+       and other aliases.  Again, the value of an item may be
+       negated with the '!' operator.  If you do not specify a
+       netmask with a network number, the netmask of the host's
+       ethernet _i_n_t_e_r_f_a_c_e(s) will be used when matching.  The
+       netmask may be specified either in dotted quad notation
+       (eg.  255.255.255.0) or CIDR notation (number of bits, eg.
+       24).
 
-       User oper can still run /usr/bin/kill without a password
-       but must give a password to run /bin/rm and /bin/rmdir.
+        Cmnd_List ::= Cmnd |
+                      Cmnd ',' Cmnd_List
 
-       wwwwiiiillllddddccccaaaarrrrddddssss ((((aaaakkkkaaaa mmmmeeeettttaaaa cccchhhhaaaarrrraaaacccctttteeeerrrrssss))))::::
+        commandname ::= filename |
+                        filename args |
+                        filename '""'
 
-       ssssuuuuddddoooo allows shell-style _w_i_l_d_c_a_r_d_s along with command
-       arguments in the _s_u_d_o_e_r_s file.  Wildcard matching is done
-       via the PPPPOOOOSSSSIIIIXXXX fnmatch(3) routine.
+        Cmnd ::= '!'* commandname |
+                 '!'* directory |
+                 '!'* Cmnd_Alias
+
+       A Cmnd_List is a list of one or more commandnames,
+       directories, and other aliases.  A commandname is a fully-
+       qualified filename which may include shell-style wildcards
+       (see `Wildcards' section below).  A simple filename allows
+       the user to run the command with any arguments he/she
+       wishes.  However, you may also command line arguments
+       (including wildcards).  Alternately, you can specify "" to
+       indicate that the command may only be run wwwwiiiitttthhhhoooouuuutttt command
+       line arguments.  A directory is a fully qualified pathname
+       ending in a '/'.  When you specify a directory in a
+       Cmnd_List, the user will be able to run any file within
+       that directory (but not in any subdirectories therein).
+
+       If a Cmnd has associated command line arguments, then the
+       arguments in the Cmnd must match exactly those given by
+       the user on the command line (or match the wildcards if
+       there are any).  Note that the following characters must
+       be escaped with a '\' if they are used in command
+       arguments: ',', ':', '=', '\\'.
+
+       UUUUsssseeeerrrr SSSSppppeeeecccciiiiffffiiiiccccaaaattttiiiioooonnnn
+
+
+        Runas_Spec ::= '(' Runas_List ')'
+
+        Cmnd_Spec ::= Runas_Spec? ('NOPASSWD:' | 'PASSWD:')? Cmnd
+
+
+
+
+25/Aug/1999                    1.6                              3
+
+
+
+
+
+SUDOERS(5)                 FILE FORMATS                SUDOERS(5)
+
+
+        Cmnd_Spec_List ::= Cmnd_Spec |
+                           Cmnd_Spec ',' Cmnd_Spec_List
+
+        User_Spec ::= User_list Cmnd_Spec_List (':' User_Spec)*
+
+       A uuuusssseeeerrrr ssssppppeeeecccciiiiffffiiiiccccaaaattttiiiioooonnnn determines which commands a user may
+       run (and as what user) on specified hosts.  By default,
+       commands are run as rrrrooooooootttt but this can be changed on a per-
+       command basis.
+
+       Let's break that down into its constituent parts:
+
+       RRRRuuuunnnnaaaassss____SSSSppppeeeecccc
+
+       A Runas_Spec is simply a Runas_List (as defined above)
+       enclosed in a set of parentheses.  If you do not specify a
+       Runas_Spec in the user specification, a default Runas_Spec
+       of rrrrooooooootttt will be used.  A Runas_Spec sets the default for
+       commands that follow it.  What this means is that for the
+       entry:
+
+        dgb    boulder = (operator) /bin/ls, /bin/kill, /usr/bin/who
+
+       The user ddddggggbbbb may run _/_b_i_n_/_l_s, _/_b_i_n_/_k_i_l_l, and _/_u_s_r_/_b_i_n_/_l_p_r_m
+       -- but only as ooooppppeeeerrrraaaattttoooorrrr.  Eg.
+
+           sudo -u operator /bin/ls.
+
+       It is also possible to override a Runas_Spec later on in
+       an entry.  If we modify the entry like so:
+
+        dgb    boulder = (operator) /bin/ls, (root) /bin/kill, /usr/bin/lprm
+
+       Then user ddddggggbbbb is now allowed to run _/_b_i_n_/_l_s as ooooppppeeeerrrraaaattttoooorrrr,
+       but  _/_b_i_n_/_k_i_l_l and _/_u_s_r_/_b_i_n_/_l_p_r_m as rrrrooooooootttt.
+
+       NNNNOOOOPPPPAAAASSSSSSSSWWWWDDDD aaaannnndddd PPPPAAAASSSSSSSSWWWWDDDD
+
+       By default, ssssuuuuddddoooo requires that a user authenticate him or
+       herself before running a command.  This behavior can be
+       modified via the NOPASSWD tag.  Like a Runas_Spec, the
+       NOPASSWD tag sets a default for the commands that follow
+       it in the Cmnd_Spec_List.  Conversely, the PASSWD tag can
+       be used to reverse things.  For example:
+
+        ray    rushmore = NOPASSWD: /bin/kill, /bin/ls, /usr/bin/lprm
+
+       would allow the user rrrraaaayyyy to run _/_b_i_n_/_k_i_l_l, _/_b_i_n_/_l_s, and
+       _/_u_s_r_/_b_i_n_/_l_p_r_m as root on the machine rushmore as rrrrooooooootttt
+       without authenticating himself.  If we only want rrrraaaayyyy to be
+       able to run _/_b_i_n_/_k_i_l_l without a password the entry would
+       be:
+
+        ray    rushmore = NOPASSWD: /bin/kill, PASSWD: /bin/ls, /usr/bin/lprm
+
+
+
+25/Aug/1999                    1.6                              4
+
+
+
+
+
+SUDOERS(5)                 FILE FORMATS                SUDOERS(5)
+
+
+       WWWWiiiillllddddccccaaaarrrrddddssss ((((aaaakkkkaaaa mmmmeeeettttaaaa cccchhhhaaaarrrraaaacccctttteeeerrrrssss))))::::
+
+       ssssuuuuddddoooo allows shell-style _w_i_l_d_c_a_r_d_s to be used in pathnames
+       as well as command line arguments in the _s_u_d_o_e_r_s file.
+       Wildcard matching is done via the PPPPOOOOSSSSIIIIXXXX fnmatch(3)
+       routine.  Note that these are _n_o_t regular expressions.
 
        *       Matches any set of zero or more characters.
 
@@ -163,213 +287,282 @@ sudoers(5)                 FILE FORMATS                sudoers(5)
                used to escape special characters such as: "*",
                "?", "[", and "}".
 
-       eeeexxxxcccceeeeppppttttiiiioooonnnnssss ttttoooo wwwwiiiillllddddccccaaaarrrrdddd rrrruuuulllleeeessss::::
+       Note that a forward slash ('/') will nnnnooootttt be matched by
+       wildcards used in the pathname.  When matching the command
+       line arguments, however, as slash ddddooooeeeessss get matched by
+       wildcards.  This is to make a path like:
+
+           /usr/bin/*
+
+       match /usr/bin/who but not /usr/bin/X11/xterm.
+
+       EEEExxxxcccceeeeppppttttiiiioooonnnnssss ttttoooo wwwwiiiillllddddccccaaaarrrrdddd rrrruuuulllleeeessss::::
 
        The following exceptions apply to the above rules:
 
-       "       If the empty string "" is the only command line
+       ""      If the empty string "" is the only command line
                argument in the _s_u_d_o_e_r_s entry it means that
-               command may take nnnnoooo arguments.
+               command is not allowed to be run with aaaannnnyyyy
+               arguments.
 
-       ooootttthhhheeeerrrr ssssppppeeeecccciiiiaaaallll cccchhhhaaaarrrraaaacccctttteeeerrrrssss aaaannnndddd rrrreeeesssseeeerrrrvvvveeeedddd wwwwoooorrrrddddssss::::
+       OOOOtttthhhheeeerrrr ssssppppeeeecccciiiiaaaallll cccchhhhaaaarrrraaaacccctttteeeerrrrssss aaaannnndddd rrrreeeesssseeeerrrrvvvveeeedddd wwwwoooorrrrddddssss::::
 
-       Text after a pound sign (####) is considered a comment.
-       Words that begin with a percent sign (%%%%) are assumed to be
-       UN*X groups (%staff refers to users in the group _s_t_a_f_f).
-       Words that begin with a plus sign (++++) are assumed to be
-       netgroups (++++ccccsssshhhhoooossssttttssss refers to the netgroup _c_s_h_o_s_t_s).  Long
-       lines can be newline escaped with the backslash \\\\
-       character.
+       The pound sign ('#') is used to indicate a comment (unless
+       it occurs in the context of a user name and is followed by
+       one or more digits, in which case it is treated as a uid).
+       Both the comment character and any text after it, up to
+       the end of the line, are ignored.
 
-       The reserved word NNNNOOOOPPPPAAAASSSSSSSSWWWWDDDD indicates that a user need not
-       enter a password for the command listed in that entry.
-       The NNNNOOOOPPPPAAAASSSSSSSSWWWWDDDD modifier is persistent across entries in a
-       _u_s_e_r_-_l_i_s_t and can be reversed with the PPPPAAAASSSSSSSSWWWWDDDD modifier.
+       The reserved word AAAALLLLLLLL is a a built in _a_l_i_a_s that always
+       causes a match to succeed.  It can be used wherever one
+       might otherwise use a Cmnd_Alias, User_Alias, Runas_Alias,
+       or Host_Alias.  You should not try to define your own
+       _a_l_i_a_s called AAAALLLLLLLL as the built in alias will be used in
+       preference to your own.
 
-       The reserved alias _A_L_L can be used for both
-       {Host,User,Cmnd}_Alias.  DDDDOOOO NNNNOOOOTTTT define an alias of _A_L_L, it
-       will NNNNOOOOTTTT be used.  Note that _A_L_L implies the entire
-       universe of hosts/users/commands.  You can subtract
+       An exclamation point ('!') can be used as a logical _n_o_t
+       operator both in an _a_l_i_a_s and in front of a Cmnd.  This
 
 
 
-22/Jun/1999                    1.6                              3
+25/Aug/1999                    1.6                              5
 
 
 
 
 
-sudoers(5)                 FILE FORMATS                sudoers(5)
+SUDOERS(5)                 FILE FORMATS                SUDOERS(5)
 
 
-       elements from the universe by using the syntax:
+       allows one to exclude certain values.  Note, however, that
+       using a ! in conjunction with the built in ALL alias to
+       allow a user to run "all but a few" commands rarely works
+       as intended (see SECURITY NOTES below).
 
-          user  host=ALL,!ALIAS1,!/sbin/halt...
+       Long lines can be continued with a backslash ('\\') as the
+       last character on the line.
 
-       Commands may have optional command line arguments.  If
-       they do, then the arguments in the _s_u_d_o_e_r_s file must
-       exactly match those on the command line.  It is also
-       possible to have a command's arguments span multiple lines
-       as long as the line continuance character "\" is used.
-       The following characters must be escaped with a "\" if
-       used in command arguments: ",", ":", "=", "\".
+       Whitespace between elements in a list as well as specicial
+       syntactic characters in a _U_s_e_r _S_p_e_c_i_f_i_c_a_t_i_o_n ('=', ':',
+       '(', ')') is optional.
 
 EEEEXXXXAAAAMMMMPPPPLLLLEEEESSSS
-           # Host alias specification
-           Host_Alias  HUB=houdini:\
-                       REMOTE=merlin,kodiakthorn,spirit
-           Host_Alias  SERVERS=houdini,merlin,kodiakthorn,spirit
-           Host_Alias  CUNETS=128.138.0.0/255.255.0.0
-           Host_Alias  CSNETS=128.138.243.0,128.138.204.0,\
-                              128.138.205.192
+       Below are example _s_u_d_o_e_r_s entries.  Admittedly, some of
+       these are a bit contrived.  First, we define our _a_l_i_a_s_e_s:
 
-           # User alias specification
-           User_Alias  FULLTIME=millert,dowdy,mikef
-           User_Alias  PARTTIME=juola,mccreary,tor
+        # User alias specification
+        User_Alias     FULLTIMERS = millert, mikef, dowdy
+        User_Alias     PARTTIMERS = bostley, jwfox, crawl
+        User_Alias     WEBMASTERS = will, wendy, wim
 
-           # Runas alias specification
-           Runas_Alias OP=root,operator
+        # Runas alias specification
+        Runas_Alias    OP = root, operator
+        Runas_Alias    DB = oracle, sybase
 
-           # Command alias specification
-           Cmnd_Alias  LPCS=/usr/sbin/lpc,/usr/bin/lprm
-           Cmnd_Alias  SHELLS=/bin/sh,/bin/csh,/bin/tcsh,/bin/ksh
-           Cmnd_Alias  SU=/usr/bin/su
-           Cmnd_Alias  MISC=/bin/rm,/bin/cat:\
-                       SHUTDOWN=/sbin/halt,/sbin/shutdown
+        # Host alias specification
+        Host_Alias     SPARC = bigtime, eclipse, moet, anchor :\
+                       SGI = grolsch, dandelion, black :\
+                       ALPHA = widget, thalamus, foobar :\
+                       HPPA = boa, nag, python
+        Host_Alias     CUNETS = 128.138.0.0/255.255.0.0
+        Host_Alias     CSNETS = 128.138.243.0, 128.138.204.0/24, 128.138.242.0
+        Host_Alias     SERVERS = master, mail, www, ns
+        Host_Alias     CDROM = orion, perseus, hercules
 
-           # User specification
-           FULLTIME    ALL=(ALL) NOPASSWD: ALL
-           %wheel      ALL=ALL
-           PARTTIME    ALL=ALL,!SHELLS,!SU
-           +interns    +openlabs=ALL,!SHELLS,!SU
-           britt       REMOTE=SHUTDOWN:ALL=LPCS
-           jimbo       CUNETS=/usr/bin/su [!-]*,!/usr/bin/su *root*
-           nieusma     SERVERS=SHUTDOWN,/sbin/reboot:\
-                       HUB=ALL,!SHELLS
-           jill        houdini=/sbin/shutdown -[hr] now,MISC
-           markm       HUB=ALL,!MISC,!/sbin/shutdown,!/sbin/halt
-           davehieb    merlin=(OP) ALL:SERVERS=/sbin/halt:\
-                       kodiakthorn=NOPASSWD: ALL
-           steve       CSNETS=(operator) /usr/op_commands/
+        # Cmnd alias specification
+        Cmnd_Alias     DUMPS = /usr/bin/mt, /usr/sbin/dump, /usr/sbin/rdump,\
+                               /usr/sbin/restore, /usr/sbin/rrestore
+        Cmnd_Alias     KILL = /usr/bin/kill
+        Cmnd_Alias     PRINTING = /usr/sbin/lpc, /usr/bin/lprm
+        Cmnd_Alias     SHUTDOWN = /usr/sbin/shutdown
+        Cmnd_Alias     HALT = /usr/sbin/halt, /usr/sbin/fasthalt
+        Cmnd_Alias     REBOOT = /usr/sbin/reboot, /usr/sbin/fastboot
+        Cmnd_Alias     SHELLS = /usr/bin/sh, /usr/bin/csh, /usr/bin/ksh, \
+                                /usr/local/bin/tcsh, /usr/bin/rsh, \
+                                /usr/local/bin/zsh
+        Cmnd_Alias     SU = /usr/bin/su
+
+       The _U_s_e_r _s_p_e_c_i_f_i_c_a_t_i_o_n is the part that actually
+       determines who may run what.
+
+        root           ALL = (ALL) ALL
+        %wheel         ALL = (ALL) ALL
+
+
+
+
+25/Aug/1999                    1.6                              6
 
 
 
 
 
+SUDOERS(5)                 FILE FORMATS                SUDOERS(5)
+
+
+       We let rrrrooooooootttt and any user in group wwwwhhhheeeeeeeellll run any command on
+       any host as any user.
+
+        FULLTIMERS     ALL = NOPASSWD: ALL
+
+       Full time sysadmins (mmmmiiiilllllllleeeerrrrtttt, mmmmiiiikkkkeeeeffff, and ddddoooowwwwddddyyyy) may run
+       any command on any host without authenticating themselves.
+
+        PARTTIMERS     ALL = ALL
+
+       Part time sysadmins (bbbboooossssttttlllleeeeyyyy, jjjjwwwwffffooooxxxx, and ccccrrrraaaawwwwllll) may run
+       any command on any host but they must authenticate
+       themselves first (since the entry lacks the NOPASSWD tag).
+
+        jack           CSNETS = ALL
+
+       The user jjjjaaaacccckkkk may run any command on the machines in the
+       _C_S_N_E_T_S alias (the networks 128.138.243.0, 128.138.204.0,
+       and 128.138.242.0).  Of those networks, only
+       <128.138.204.0> has an explicit netmask (in CIDR notation)
+       indicating it is a class C network.  For the other
+       networks in _C_S_N_E_T_S, the local machine's netmask will be
+       used during matching.
+
+        lisa           CUNETS = ALL
+
+       The user lllliiiissssaaaa may run any command on any host in the
+       _C_U_N_E_T_S alias (the class B network 128.138.0.0).
+
+        operator       ALL = DUMPS, KILL, PRINTING, SHUTDOWN, HALT, REBOOT,\
+                       /usr/oper/bin/
+
+       The ooooppppeeeerrrraaaattttoooorrrr user may run commands limited to simple
+       maintenance.  Here, those are commands related to backups,
+       killing processes, the printing system, shutting down the
+       system, and any commands in the directory _/_u_s_r_/_o_p_e_r_/_b_i_n_/.
+
+        joe            ALL = /usr/bin/su operator
+
+       The user jjjjooooeeee may only _s_u(1) to operator.
+
+        pete           HPPA = /usr/bin/passwd [A-z]*, !/usr/bin/passwd root
+
+       The user ppppeeeetttteeee is allowed to change anyone's password
+       except for root on the _H_P_P_A machines.  Note that this
+       assumes _p_a_s_s_w_d(1) does not take multiple usernames on the
+       command line.
+
+        bob            SPARC = (OP) ALL : SGI = (OP) ALL
+
+       The user bbbboooobbbb may run anything on the _S_P_A_R_C and _S_G_I
+       machines as any user listed in the _O_P Runas_Alias (rrrrooooooootttt
+       and ooooppppeeeerrrraaaattttoooorrrr).
 
 
 
-22/Jun/1999                    1.6                              4
+
+25/Aug/1999                    1.6                              7
 
 
 
 
 
-sudoers(5)                 FILE FORMATS                sudoers(5)
+SUDOERS(5)                 FILE FORMATS                SUDOERS(5)
 
 
-       HHHHoooosssstttt AAAAlllliiiiaaaassss ssssppppeeeecccciiiiffffiiiiccccaaaattttiiiioooonnnnssss::::
+        jim            +biglab = ALL
 
-       The are four _h_o_s_t _a_l_i_a_s_e_s.  The first actually contains
-       two _a_l_i_a_s_e_s.  It sets HUB to be houdini and REMOTE to the
-       three machines merlin, kodiakthorn and spirit.  Similarly,
-       SERVERS is set to the machines houdini, merlin,
-       kodiakthorn and spirit.  The CSNETS alias will match any
-       host on the 128.138.243.0, 128.138.204.0, or
-       128.138.205.192 nets.  The CUNETS alias will match any
-       host on the 128.138.0.0 (class B) network.  Note that
-       these are nnnneeeettttwwwwoooorrrrkkkk addresses, not ip addresses.  Unless an
-       explicit netmask is given, the local _n_e_t_m_a_s_k is used to
-       determine whether or not the current host belongs to a
-       network.
+       The user jjjjiiiimmmm may run any command on machines in the _b_i_g_l_a_b
+       netgroup.  SSSSuuuuddddoooo knows that "biglab" is a netgroup due to
+       the '+' prefix.
 
-       UUUUsssseeeerrrr AAAAlllliiiiaaaassss ssssppppeeeecccciiiiffffiiiiccccaaaattttiiiioooonnnnssss::::
+        +secretaries   ALL = PRINTING, /usr/bin/adduser, /usr/bin/rmuser
 
-       The two _u_s_e_r _a_l_i_a_s_e_s simply groups the FULLTIME and
-       PARTTIME folks into two separate aliases.
+       Users in the sssseeeeccccrrrreeeettttaaaarrrriiiieeeessss netgroup need to help manage the
+       printers as well as add and remove users, so they are
+       allowed to run those commands on all machines.
 
-       CCCCoooommmmmmmmaaaannnndddd aaaalllliiiiaaaassss ssssppppeeeecccciiiiffffiiiiccccaaaattttiiiioooonnnnssss::::
+        fred           ALL = (DB) NOPASSWD: ALL
 
-       Command aliases are lists of commands with or without
-       associated command line arguments.  The entries above
-       should be self-explanatory.
+       The user ffffrrrreeeedddd can run commands as any user in the _D_B
+       Runas_Alias (oooorrrraaaacccclllleeee or ssssyyyybbbbaaaasssseeee) without giving a password.
 
-       UUUUsssseeeerrrr ssssppppeeeecccciiiiffffiiiiccccaaaattttiiiioooonnnnssss::::
+        john           ALPHA = /usr/bin/su [!-]*, !/usr/bin/su *root*
+
+       On the _A_L_P_H_A machines, user jjjjoooohhhhnnnn may su to anyone except
+       root but he is not allowed to give _s_u(1) any flags.
+
+        jen            ALL, !SERVERS = ALL
+
+       The user jjjjeeeennnn may run any command on any machine except for
+       those in the _S_E_R_V_E_R_S Host_Alias (master, mail, www and
+       ns).
+
+        jill           SERVERS = /usr/bin/, !SU, !SHELLS
+
+       For any machine in the _S_E_R_V_E_R_S Host_Alias, jjjjiiiillllllll may run
+       any commands in the directory /usr/bin/ except for those
+       commands belonging to the _S_U and _S_H_E_L_L_S Cmnd_Aliases.
+
+        steve          CSNETS = (operator) /usr/local/op_commands/
+
+       The user sssstttteeeevvvveeee may run any command in the directory
+       /usr/local/op_commands/ but only as user operator.
+
+        matt           valkyrie = KILL
+
+       On his personal workstation, valkyrie, mmmmaaaatttttttt needs to be
+       able to kill hung processes.
+
+        WEBMASTERS     www = (www) ALL, (root) /usr/bin/su www
+
+       On the host www, any user in the _W_E_B_M_A_S_T_E_R_S User_Alias
+       (will, wendy, and wim), may run any command as user www
+       (which owns the web pages) or simply _s_u(1) to www.
+
+        ALL            CDROM = NOPASSWD: /sbin/umount /CDROM,\
+                       /sbin/mount -o nosuid\,nodev /dev/cd0a /CDROM
+
+       Any user may mount or unmount a CD-ROM on the machines in
 
 
-       FULLTIME        Full-time sysadmins in the FULLTIME alias
-                       may run any command on any host as any
-                       user without a password.
 
-       %wheel          Any user in the UN*X group wheel may run
-                       any command on any host.
-
-       PARTTIME        Part-time sysadmins in the PARTTIME alias
-                       may run any command except those in the
-                       SHELLS and SU aliases on any host.
-
-       +interns        Any user in the netgroup interns may run
-                       any command except those in the SHELLS and
-                       SU aliases on any host that is in the
-                       openlabs netgroup.
-
-       britt           The user britt may run commands in the
-                       SHUTDOWN alias on the REMOTE machines and
-                       commands in the LPCS alias on any machine.
-
-       jimbo           The user jimbo may su to any user save
-                       root on the machines on CUNETS (which is
-                       explicitly listed as a class B network).
+25/Aug/1999                    1.6                              8
 
 
 
 
 
-22/Jun/1999                    1.6                              5
+SUDOERS(5)                 FILE FORMATS                SUDOERS(5)
 
 
+       the CDROM Host_Alias (orion, perseus, hercules) without
+       entering a password.  This is a bit tedious for users to
+       type, so it is a prime candiate for encapsulating in a
+       shell script.
 
+SSSSEEEECCCCUUUURRRRIIIITTTTYYYY NNNNOOOOTTTTEEEESSSS
+       It is generally not effective to "subtract" commands from
+       ALL using the '!' operator.  A user can trivially
+       circumvent this by copying the desired command to a
+       different name and then executing that.  For example:
 
+           bill        ALL = ALL, !SU, !SHELLS
 
-sudoers(5)                 FILE FORMATS                sudoers(5)
-
-
-       nieusma         The user nieusma may run commands in the
-                       SHUTDOWN alias as well as _/_s_b_i_n_/_r_e_b_o_o_t on
-                       the SERVER machines and any command except
-                       those in the SHELLS alias on the HUB
-                       machines.
-
-       jill            The user jill may run /sbin/shutdown -h
-                       now or /sbin/shutdown -r now as well as
-                       the commands in the MISC alias on houdini.
-
-       markm           The user markm may run any command on the
-                       HUB machines except _/_s_b_i_n_/_s_h_u_t_d_o_w_n,
-                       _/_s_b_i_n_/_h_a_l_t, and commands listed in the
-                       MISC alias.
-
-       davehieb        The user davehieb may run any command on
-                       merlin as any user in the Runas_Alias OP
-                       (ie: root or operator).  He may also run
-                       _/_s_b_i_n_/_h_a_l_t on the SERVERS and any command
-                       on kodiakthorn (no password required on
-                       kodiakthorn).
-
-       steve           The user steve may run any command in the
-                       _/_u_s_r_/_o_p___c_o_m_m_a_n_d_s_/ directory as user
-                       operator on the machines on CSNETS.
+       Doesn't really prevent bbbbiiiillllllll from running the commands
+       listed in _S_U or _S_H_E_L_L_S since he can simply copy those
+       commands to a different name, or use a shell escape from
+       an editor or other program.  Therefore, these kind of
+       restrictions should be considered advisory at best (and
+       reinforced by policy).
 
 CCCCAAAAVVVVEEEEAAAATTTTSSSS
        The _s_u_d_o_e_r_s file should aaaallllwwwwaaaayyyyssss be edited by the vvvviiiissssuuuuddddoooo
        command which locks the file and does grammatical
-       checking. It is imperative that the _s_u_d_o_e_r_s be free of
-       syntax errors since sudo will not run with a syntactically
+       checking. It is imperative that _s_u_d_o_e_r_s be free of syntax
+       errors since ssssuuuuddddoooo will not run with a syntactically
        incorrect _s_u_d_o_e_r_s file.
 
 FFFFIIIILLLLEEEESSSS
-        /etc/sudoers           file of authorized users.
-        /etc/netgroup          list of network groups.
+        /etc/sudoers           List of who can run what
+        /etc/group             Local groups file
+        /etc/netgroup          List of network groups
 
 
 SSSSEEEEEEEE AAAALLLLSSSSOOOO
@@ -391,18 +584,18 @@ SSSSEEEEEEEE AAAALLLLSSSSOOOO
 
 
 
-22/Jun/1999                    1.6                              6
 
 
 
 
 
-sudoers(5)                 FILE FORMATS                sudoers(5)
+25/Aug/1999                    1.6                              9
 
 
 
 
 
+SUDOERS(5)                 FILE FORMATS                SUDOERS(5)
 
 
 
@@ -457,6 +650,11 @@ sudoers(5)                 FILE FORMATS                sudoers(5)
 
 
 
-22/Jun/1999                    1.6                              7
+
+
+
+
+
+25/Aug/1999                    1.6                             10
 
 
diff --git a/sudoers.html b/sudoers.html
index abaa56140..c1839697c 100644
--- a/sudoers.html
+++ b/sudoers.html
@@ -14,27 +14,18 @@
 	<LI><A HREF="#DESCRIPTION">DESCRIPTION</A>
 	<UL>
 
-		<LI><A HREF="#user_specification_format_">user specification format:</A>
-		<LI><A HREF="#host_alias_section_format_">host alias section format:</A>
-		<LI><A HREF="#user_alias_section_format_">user alias section format:</A>
-		<LI><A HREF="#runas_alias_section_format_">runas alias section format:</A>
-		<LI><A HREF="#command_alias_section_format_">command alias section format:</A>
-		<LI><A HREF="#command_specification_">command specification:</A>
-		<LI><A HREF="#persistence_of_modifiers">persistence of modifiers</A>
-		<LI><A HREF="#wildcards_aka_meta_characters_">wildcards (aka meta characters):</A>
-		<LI><A HREF="#exceptions_to_wildcard_rules_">exceptions to wildcard rules:</A>
-		<LI><A HREF="#other_special_characters_and_res">other special characters and reserved words:</A>
+		<LI><A HREF="#Quick_guide_to_EBNF">Quick guide to EBNF</A>
+		<LI><A HREF="#Aliases">Aliases</A>
+		<LI><A HREF="#User_Specification">User Specification</A>
+		<LI><A HREF="#Runas_Spec">Runas_Spec</A>
+		<LI><A HREF="#NOPASSWD_and_PASSWD">NOPASSWD and PASSWD</A>
+		<LI><A HREF="#Wildcards_aka_meta_characters_">Wildcards (aka meta characters):</A>
+		<LI><A HREF="#Exceptions_to_wildcard_rules_">Exceptions to wildcard rules:</A>
+		<LI><A HREF="#Other_special_characters_and_res">Other special characters and reserved words:</A>
 	</UL>
 
 	<LI><A HREF="#EXAMPLES">EXAMPLES</A>
-	<UL>
-
-		<LI><A HREF="#Host_Alias_specifications_">Host Alias specifications:</A>
-		<LI><A HREF="#User_Alias_specifications_">User Alias specifications:</A>
-		<LI><A HREF="#Command_alias_specifications_">Command alias specifications:</A>
-		<LI><A HREF="#User_specifications_">User specifications:</A>
-	</UL>
-
+	<LI><A HREF="#SECURITY_NOTES">SECURITY NOTES</A>
 	<LI><A HREF="#CAVEATS">CAVEATS</A>
 	<LI><A HREF="#FILES">FILES</A>
 	<LI><A HREF="#SEE_ALSO">SEE ALSO</A>
@@ -46,147 +37,266 @@
 <HR>
 <H1><A NAME="NAME">NAME</A></H1>
 <P>
-sudoers - list of which users may execute what as root
+sudoers - list of which users may execute what
 
 <P>
 <HR>
 <H1><A NAME="DESCRIPTION">DESCRIPTION</A></H1>
 <P>
-The <EM>sudoers</EM> file is composed of an optional host alias section, an optional command
-alias section and the user specification section. All command or host
-aliases need to start with their respective keywords (ie: Host_Alias,
-User_Alias, Runas_Alias or Cmnd_Alias). If there are multiple occurrences
-of a user, the logical union of the entries will be used. Note that if
-there is an entry that denies access to a command that is followed by an
-entry that grants access the user will be allowed to run the command.
+The <EM>sudoers</EM> file is composed two types of entries: aliases (basically variables) and
+user specifications (which specify who may run what). The grammar of <EM>sudoers</EM>
+will be described below in Extended Backus-Naur Form (EBNF). Don't despair
+if you don't know what EBNF is, it is fairly simple and the definitions
+below are annotated.
 
 <P>
 <HR>
-<H2><A NAME="user_specification_format_">user specification format:</A></H2>
+<H2><A NAME="Quick_guide_to_EBNF">Quick guide to EBNF</A></H2>
 <P>
-<PRE>  user access_group [: access_group] ...
-</PRE>
-<P>
-<PRE>    access_group ::= host-list = [(runas-list)] [NOPASSWD:] [op]cmnd_type
-                     [,[(user-list)] [NOPASSWD|PASSWD:] [op]cmnd_type] ... 
-       cmnd_type ::= a command OR a command alias.
-              op ::= the logical &quot;!&quot; NOT operator.
-</PRE>
-<P>
-<HR>
-<H2><A NAME="host_alias_section_format_">host alias section format:</A></H2>
-<P>
-<PRE>  Host_Alias HOSTALIAS = host-list
-</PRE>
-<P>
-<PRE>      Host_Alias ::= a keyword.
-       HOSTALIAS ::= an upper-case alias name.
-       host-list ::= a comma separated list of hosts, netgroups,
-                     ip addresses, networks.  A logical &quot;!&quot;
-                     NOT operator may be prefixed to any of these.
-</PRE>
-<P>
-<HR>
-<H2><A NAME="user_alias_section_format_">user alias section format:</A></H2>
-<P>
-<PRE>  User_Alias USERALIAS = user-list
-</PRE>
-<P>
-<PRE>      User_Alias ::= a keyword.
-       USERALIAS ::= an upper-case alias name.
-       user-list ::= a comma separated list of users, groups, netgroups.
-                     A logical &quot;!&quot; NOT operator may be prefixed to any
-                     of these.
-</PRE>
-<P>
-<HR>
-<H2><A NAME="runas_alias_section_format_">runas alias section format:</A></H2>
-<P>
-<PRE>  Runas_Alias RUNASALIAS = runas-list
-</PRE>
-<P>
-<PRE>      Runas_Alias ::= a keyword.
-       RUNASALIAS ::= an upper-case alias name.
-       runas-list ::= a comma separated list of users, groups, netgroups.
-                      A logical &quot;!&quot; NOT operator may be prefixed to any
-                      of these.
-</PRE>
-<P>
-<HR>
-<H2><A NAME="command_alias_section_format_">command alias section format:</A></H2>
-<P>
-<PRE>  Cmnd_Alias CMNDALIAS = cmnd-list
-</PRE>
-<P>
-<PRE>      Cmnd_Alias ::= a keyword.
-       CMNDALIAS ::= an upper-case alias name.
-       cmnd-list ::= a comma separated list commands.
-                     A logical &quot;!&quot; NOT operator may be prefixed to any
-                     of these.
-</PRE>
-<P>
-<HR>
-<H2><A NAME="command_specification_">command specification:</A></H2>
-<P>
-<PRE>  path arg1 arg2 .. argn = command
-</PRE>
-<P>
-<PRE>            path ::= a fully qualified pathname.
-       arg[1..n] ::= optional command line arguments.
-</PRE>
-<P>
-<HR>
-<H2><A NAME="persistence_of_modifiers">persistence of modifiers</A></H2>
-<P>
-When a <EM>runas-list</EM> is specified for an <EM>access_group</EM>, it affects all commands in the <EM>access_group</EM>. For example, given:
+EBNF is a concise and exact way of describing the grammar of a language.
+Each EBNF definition is made up of <EM>production rules</EM>. Eg.
 
 <P>
-<PRE>    oper bigserver = (root, sysadm) /usr/bin/kill, /bin/rm
+<PRE> symbol ::= definition | alternate1 | alternate2 ...
 </PRE>
 <P>
-User <CODE>oper</CODE> will be able to run <CODE>/usr/bin/kill</CODE> and <CODE>/bin/rm</CODE>
-as <STRONG>root</STRONG> or <STRONG>sysadm</STRONG> on the machine, <CODE>bigserver</CODE>. The
-<EM>runas-list</EM> is ``sticky'' across entries in the comma-separated
-<EM>access_group</EM>. You can override the <EM>runas-list</EM> with another one, at which point the new <EM>runas-list</EM> becomes the default for that <EM>access_group</EM>. For example, given:
+Each <EM>production rule</EM> references others and thus makes up a grammar for the language. EBNF also
+contains the following operators, which many readers will recognize from
+regular expressions. Do not, however, confuse them with ``wildcard''
+characters, which have different meanings.
 
+<DL>
+<DT><STRONG><A NAME="item__">?</A></STRONG><DD>
 <P>
-<PRE>    oper bigserver = (root, sysadm) /usr/bin/kill, (root) /bin/rm, \
-        /bin/rmdir
-</PRE>
-<P>
-User <CODE>oper</CODE> can still run <CODE>/usr/bin/kill</CODE> as <STRONG>root</STRONG> or <STRONG>sysadm</STRONG> but can only run <CODE>/bin/rm</CODE> and <CODE>/bin/rmdir</CODE> as <STRONG>root</STRONG>.
+Means that the preceding symbol (or group of symbols) is optional. That is,
+it may appear once or not at all.
 
+<LI>
 <P>
-Similarly, the <STRONG>NOPASSWD</STRONG> modifier is also persistent across an
-<EM>access_group</EM>. For example given:
+Means that the preceding symbol (or group of symbols) may appear zero or
+more times.
 
+<DT><STRONG><A NAME="item__">+</A></STRONG><DD>
 <P>
-<PRE>    oper bigserver = NOPASSWD: /usr/bin/kill, /bin/rm, /bin/rmdir
-</PRE>
-<P>
-User <CODE>oper</CODE> will be able to run <CODE>/usr/bin/kill</CODE>, <CODE>/bin/rm</CODE>, and
-<CODE>/bin/rmdir</CODE> as <STRONG>root</STRONG> without a password. If we change that to:
+Means that the preceding symbol (or group of symbols) may appear one or
+more times.
 
+</DL>
 <P>
-<PRE>    oper bigserver = NOPASSWD: /usr/bin/kill, PASSWD: /bin/rm, /bin/rmdir
-</PRE>
-<P>
-User <CODE>oper</CODE> can still run <CODE>/usr/bin/kill</CODE> without a password but must give a password to run <CODE>/bin/rm</CODE> and <CODE>/bin/rmdir</CODE>.
+Parentheses may be used to group symbols together. For clarity, we will use
+single quotes ('') to designate what is a verbatim character string (as
+opposed to a symbol name).
 
 <P>
 <HR>
-<H2><A NAME="wildcards_aka_meta_characters_">wildcards (aka meta characters):</A></H2>
+<H2><A NAME="Aliases">Aliases</A></H2>
 <P>
-<STRONG>sudo</STRONG> allows shell-style <EM>wildcards</EM> along with command arguments in the <EM>sudoers</EM> file. Wildcard matching is done via the <STRONG>POSIX</STRONG>
+There are four kinds of aliases: the <CODE>User_Alias</CODE>, <CODE>Runas_Alias</CODE>,
+<CODE>Host_Alias</CODE> and <CODE>Cmnd_Alias</CODE>.
 
-<CODE>fnmatch(3)</CODE> routine.
+<P>
+<PRE> Alias ::= User_Alias = User_Alias (':' User_Alias)* |
+           Runas_Alias (':' Runas_Alias)* |
+           Host_Alias (':' Host_Alias)* |
+           Cmnd_Alias (':' Cmnd_Alias)*
+</PRE>
+<P>
+<PRE> User_Alias ::= NAME '=' User_List
+</PRE>
+<P>
+<PRE> Runas_Alias ::= NAME '=' Runas_User_List
+</PRE>
+<P>
+<PRE> Host_Alias ::= NAME '=' Host_List
+</PRE>
+<P>
+<PRE> Cmnd_Alias ::= NAME '=' Cmnd_List
+</PRE>
+<P>
+<PRE> NAME ::= [A-Z]([A-Z][0-9]_)*
+</PRE>
+<P>
+Each <EM>alias</EM> definition is of the form
+
+<P>
+<PRE> Alias_Type NAME = item1, item2, ...
+</PRE>
+<P>
+where <EM>Alias_Type</EM> is one of <CODE>User_Alias</CODE>, <CODE>Runas_Alias</CODE>, <CODE>Host_Alias</CODE>, or <CODE>Cmnd_Alias</CODE>. A <CODE>NAME</CODE> is a string of upper case letters, numbers, and the underscore characters
+('_'). A <CODE>NAME</CODE>  <STRONG>must</STRONG> start with an upper case letter. It is possible to put several alias
+definitions of the same type on a single line, joined by a semicolon (':').
+Eg.
+
+<P>
+<PRE> Alias_Type NAME = item1, item2, item3 : NAME = item4, item5
+</PRE>
+<P>
+The definitions of what constitutes a valid <EM>alias</EM> member follow.
+
+<P>
+<PRE> User_List ::= User |
+               User ',' User_List
+</PRE>
+<P>
+<PRE> User ::= '!'* username |
+          '!'* '#'uid |
+          '!'* '%'group |
+          '!'* '+'netgroup |
+          '!'* User_Alias
+</PRE>
+<P>
+A <CODE>User_List</CODE> is made up of one or more usernames, uids (prefixed with '#'), System
+groups (prefixed with '%'), netgroups (prefixed with '+') and other
+aliases. Each list item may be prefixed with one or more '!' operators. An
+odd number of '!' operators negates the value of the item; an even number
+just cancel each other out.
+
+<P>
+<PRE> Runas_List ::= Runas_User |
+                Runas_User ',' Runas_List
+</PRE>
+<P>
+<PRE> Runas_User ::= '!'* username |
+                '!'* '#'uid |
+                '!'* '%'group |
+                '!'* +netgroup |
+                '!'* Runas_Alias
+</PRE>
+<P>
+Likewise, a <CODE>Runas_List</CODE> has the same possible elements as a <CODE>User_List</CODE>, except that it can include a <CODE>Runas_Alias</CODE>, instead of a <CODE>User_Alias</CODE>.
+
+<P>
+<PRE> Host_List ::= Host |
+               Host ',' Host_List
+</PRE>
+<P>
+<PRE> Host ::= '!'* hostname |
+          '!'* ip_addr |
+          '!'* network(/netmask)? |
+          '!'* '+'netgroup |
+          '!'* Host_Alias
+</PRE>
+<P>
+A <CODE>Host_List</CODE> is made up of one or more hostnames, IP addresses, network numbers,
+netgroups (prefixed with '+') and other aliases. Again, the value of an
+item may be negated with the '!' operator. If you do not specify a netmask
+with a network number, the netmask of the host's ethernet
+<CODE>interface(s)</CODE> will be used when matching. The netmask may be
+specified either in dotted quad notation (eg. 255.255.255.0) or CIDR
+notation (number of bits, eg. 24).
+
+<P>
+<PRE> Cmnd_List ::= Cmnd |
+               Cmnd ',' Cmnd_List
+</PRE>
+<P>
+<PRE> commandname ::= filename |
+                 filename args |
+                 filename '&quot;&quot;'
+</PRE>
+<P>
+<PRE> Cmnd ::= '!'* commandname |
+          '!'* directory |
+          '!'* Cmnd_Alias
+</PRE>
+<P>
+A <CODE>Cmnd_List</CODE> is a list of one or more commandnames, directories, and other aliases. A
+commandname is a fully-qualified filename which may include shell-style
+wildcards (see `Wildcards' section below). A simple filename allows the
+user to run the command with any arguments he/she wishes. However, you may
+also command line arguments (including wildcards). Alternately, you can
+specify <CODE>&quot;&quot;</CODE> to indicate that the command may only be run <STRONG>without</STRONG> command line arguments. A directory is a fully qualified pathname ending in
+a '/'. When you specify a directory in a <CODE>Cmnd_List</CODE>, the user will be able to run any file within that directory (but not in
+any subdirectories therein).
+
+<P>
+If a <CODE>Cmnd</CODE> has associated command line arguments, then the arguments in the <CODE>Cmnd</CODE> must match exactly those given by the user on the command line (or match
+the wildcards if there are any). Note that the following characters must be
+escaped with a '\' if they are used in command arguments: ',', ':', '=',
+'\\'.
+
+<P>
+<HR>
+<H2><A NAME="User_Specification">User Specification</A></H2>
+<P>
+<PRE> Runas_Spec ::= '(' Runas_List ')'
+</PRE>
+<P>
+<PRE> Cmnd_Spec ::= Runas_Spec? ('NOPASSWD:' | 'PASSWD:')? Cmnd
+</PRE>
+<P>
+<PRE> Cmnd_Spec_List ::= Cmnd_Spec |
+                    Cmnd_Spec ',' Cmnd_Spec_List
+</PRE>
+<P>
+<PRE> User_Spec ::= User_list Cmnd_Spec_List (':' User_Spec)*
+</PRE>
+<P>
+A <STRONG>user specification</STRONG> determines which commands a user may run (and as what user) on specified
+hosts. By default, commands are run as <STRONG>root</STRONG> but this can be changed on a per-command basis.
+
+<P>
+Let's break that down into its constituent parts:
+
+<P>
+<HR>
+<H2><A NAME="Runas_Spec">Runas_Spec</A></H2>
+<P>
+A <CODE>Runas_Spec</CODE> is simply a <CODE>Runas_List</CODE> (as defined above) enclosed in a set of parentheses. If you do not specify
+a
+<CODE>Runas_Spec</CODE> in the user specification, a default <CODE>Runas_Spec</CODE>
+of <STRONG>root</STRONG> will be used. A <CODE>Runas_Spec</CODE> sets the default for commands that follow it. What this means is that for
+the entry:
+
+<P>
+<PRE> dgb    boulder = (operator) /bin/ls, /bin/kill, /usr/bin/who
+</PRE>
+<P>
+The user <STRONG>dgb</STRONG> may run <EM>/bin/ls</EM>, <EM>/bin/kill</EM>, and
+<EM>/usr/bin/lprm</EM> -- but only as <STRONG>operator</STRONG>. Eg.
+
+<P>
+<PRE>    sudo -u operator /bin/ls.
+</PRE>
+<P>
+It is also possible to override a <CODE>Runas_Spec</CODE> later on in an entry. If we modify the entry like so:
+
+<P>
+<PRE> dgb    boulder = (operator) /bin/ls, (root) /bin/kill, /usr/bin/lprm
+</PRE>
+<P>
+Then user <STRONG>dgb</STRONG> is now allowed to run <EM>/bin/ls</EM> as <STRONG>operator</STRONG>, but  <EM>/bin/kill</EM> and <EM>/usr/bin/lprm</EM> as <STRONG>root</STRONG>.
+
+<P>
+<HR>
+<H2><A NAME="NOPASSWD_and_PASSWD">NOPASSWD and PASSWD</A></H2>
+<P>
+By default, <STRONG>sudo</STRONG> requires that a user authenticate him or herself before running a command.
+This behavior can be modified via the
+<CODE>NOPASSWD</CODE> tag. Like a <CODE>Runas_Spec</CODE>, the <CODE>NOPASSWD</CODE> tag sets a default for the commands that follow it in the <CODE>Cmnd_Spec_List</CODE>. Conversely, the <CODE>PASSWD</CODE> tag can be used to reverse things. For example:
+
+<P>
+<PRE> ray    rushmore = NOPASSWD: /bin/kill, /bin/ls, /usr/bin/lprm
+</PRE>
+<P>
+would allow the user <STRONG>ray</STRONG> to run <EM>/bin/kill</EM>, <EM>/bin/ls</EM>, and
+<EM>/usr/bin/lprm</EM> as root on the machine rushmore as <STRONG>root</STRONG> without authenticating himself. If we only want <STRONG>ray</STRONG> to be able to run <EM>/bin/kill</EM> without a password the entry would be:
+
+<P>
+<PRE> ray    rushmore = NOPASSWD: /bin/kill, PASSWD: /bin/ls, /usr/bin/lprm
+</PRE>
+<P>
+<HR>
+<H2><A NAME="Wildcards_aka_meta_characters_">Wildcards (aka meta characters):</A></H2>
+<P>
+<STRONG>sudo</STRONG> allows shell-style <EM>wildcards</EM> to be used in pathnames as well as command line arguments in the <EM>sudoers</EM> file. Wildcard matching is done via the <STRONG>POSIX</STRONG>  <CODE>fnmatch(3)</CODE> routine. Note that these are <EM>not</EM> regular expressions.
 
 <UL>
 <LI>
 <P>
 Matches any set of zero or more characters.
 
-<DT><STRONG><A NAME="item__">?</A></STRONG><DD>
+<DT><STRONG>?</STRONG><DD>
 <P>
 Matches any single character.
 
@@ -204,9 +314,19 @@ For any character ``x'', evaluates to ``x''. This is used to escape special
 characters such as: ``*'', ``?'', ``['', and ``}''.
 
 </UL>
+<P>
+Note that a forward slash ('/') will <STRONG>not</STRONG> be matched by wildcards used in the pathname. When matching the command
+line arguments, however, as slash <STRONG>does</STRONG> get matched by wildcards. This is to make a path like:
+
+<P>
+<PRE>    /usr/bin/*
+</PRE>
+<P>
+match <CODE>/usr/bin/who</CODE> but not <CODE>/usr/bin/X11/xterm</CODE>.
+
 <P>
 <HR>
-<H2><A NAME="exceptions_to_wildcard_rules_">exceptions to wildcard rules:</A></H2>
+<H2><A NAME="Exceptions_to_wildcard_rules_">Exceptions to wildcard rules:</A></H2>
 <P>
 The following exceptions apply to the above rules:
 
@@ -214,175 +334,246 @@ The following exceptions apply to the above rules:
 <DT><STRONG><A NAME="item__">&quot;&quot;</A></STRONG><DD>
 <P>
 If the empty string <CODE>&quot;&quot;</CODE> is the only command line argument in the
-<EM>sudoers</EM> entry it means that command may take <STRONG>no</STRONG> arguments.
+<EM>sudoers</EM> entry it means that command is not allowed to be run with <STRONG>any</STRONG> arguments.
 
 </DL>
 <P>
 <HR>
-<H2><A NAME="other_special_characters_and_res">other special characters and reserved words:</A></H2>
+<H2><A NAME="Other_special_characters_and_res">Other special characters and reserved words:</A></H2>
 <P>
-Text after a pound sign (<STRONG>#</STRONG>) is considered a comment. Words that begin with a percent sign (<STRONG>%</STRONG>) are assumed to be UN*X groups (%staff refers to users in the group <EM>staff</EM>). Words that begin with a plus sign (<STRONG>+</STRONG>) are assumed to be netgroups (<STRONG>+cshosts</STRONG> refers to the netgroup <EM>cshosts</EM>). Long lines can be newline escaped with the backslash <STRONG>\</STRONG> character.
+The pound sign ('#') is used to indicate a comment (unless it occurs in the
+context of a user name and is followed by one or more digits, in which case
+it is treated as a uid). Both the comment character and any text after it,
+up to the end of the line, are ignored.
 
 <P>
-The reserved word <STRONG>NOPASSWD</STRONG> indicates that a user need not enter a password for the command listed in
-that entry. The
-<STRONG>NOPASSWD</STRONG> modifier is persistent across entries in a <EM>user-list</EM>
-and can be reversed with the <STRONG>PASSWD</STRONG> modifier.
+The reserved word <STRONG>ALL</STRONG> is a a built in <EM>alias</EM> that always causes a match to succeed. It can be used wherever one might
+otherwise use a <CODE>Cmnd_Alias</CODE>, <CODE>User_Alias</CODE>, <CODE>Runas_Alias</CODE>, or <CODE>Host_Alias</CODE>. You should not try to define your own <EM>alias</EM> called <STRONG>ALL</STRONG> as the built in alias will be used in preference to your own.
 
 <P>
-The reserved alias <EM>ALL</EM> can be used for both {Host,User,Cmnd}_Alias.
-<STRONG>DO NOT</STRONG> define an alias of <EM>ALL</EM>, it will <STRONG>NOT</STRONG> be used. Note that <EM>ALL</EM> implies the entire universe of hosts/users/commands. You can subtract
-elements from the universe by using the syntax:
+An exclamation point ('!') can be used as a logical <EM>not</EM> operator both in an <EM>alias</EM> and in front of a <CODE>Cmnd</CODE>. This allows one to exclude certain values. Note, however, that using a <CODE>!</CODE> in conjunction with the built in <CODE>ALL</CODE> alias to allow a user to run ``all but a few'' commands rarely works as
+intended (see SECURITY NOTES below).
 
 <P>
-<PRE>   user  host=ALL,!ALIAS1,!/sbin/halt...
-</PRE>
+Long lines can be continued with a backslash ('\\') as the last character
+on the line.
+
 <P>
-Commands may have optional command line arguments. If they do, then the
-arguments in the <EM>sudoers</EM> file must exactly match those on the command line. It is also possible to
-have a command's arguments span multiple lines as long as the line
-continuance character ``\'' is used. The following characters must be
-escaped with a ``\'' if used in command arguments: ``,'', ``:'', ``='',
-``\''.
+Whitespace between elements in a list as well as specicial syntactic
+characters in a <EM>User Specification</EM> ('=', ':', '(', ')') is optional.
 
 <P>
 <HR>
 <H1><A NAME="EXAMPLES">EXAMPLES</A></H1>
 <P>
-<PRE>    # Host alias specification
-    Host_Alias  HUB=houdini:\
-                REMOTE=merlin,kodiakthorn,spirit
-    Host_Alias  SERVERS=houdini,merlin,kodiakthorn,spirit
-    Host_Alias  CUNETS=128.138.0.0/255.255.0.0
-    Host_Alias  CSNETS=128.138.243.0,128.138.204.0,\
-                       128.138.205.192
+Below are example <EM>sudoers</EM> entries. Admittedly, some of these are a bit contrived. First, we define
+our <EM>aliases</EM>:
+
+<P>
+<PRE> # User alias specification
+ User_Alias     FULLTIMERS = millert, mikef, dowdy
+ User_Alias     PARTTIMERS = bostley, jwfox, crawl
+ User_Alias     WEBMASTERS = will, wendy, wim
 </PRE>
 <P>
-<PRE>    # User alias specification
-    User_Alias  FULLTIME=millert,dowdy,mikef
-    User_Alias  PARTTIME=juola,mccreary,tor
+<PRE> # Runas alias specification
+ Runas_Alias    OP = root, operator
+ Runas_Alias    DB = oracle, sybase
 </PRE>
 <P>
-<PRE>    # Runas alias specification
-    Runas_Alias OP=root,operator
+<PRE> # Host alias specification
+ Host_Alias     SPARC = bigtime, eclipse, moet, anchor :\
+                SGI = grolsch, dandelion, black :\
+                ALPHA = widget, thalamus, foobar :\
+                HPPA = boa, nag, python
+ Host_Alias     CUNETS = 128.138.0.0/255.255.0.0
+ Host_Alias     CSNETS = 128.138.243.0, 128.138.204.0/24, 128.138.242.0
+ Host_Alias     SERVERS = master, mail, www, ns
+ Host_Alias     CDROM = orion, perseus, hercules
 </PRE>
 <P>
-<PRE>    # Command alias specification
-    Cmnd_Alias  LPCS=/usr/sbin/lpc,/usr/bin/lprm
-    Cmnd_Alias  SHELLS=/bin/sh,/bin/csh,/bin/tcsh,/bin/ksh
-    Cmnd_Alias  SU=/usr/bin/su
-    Cmnd_Alias  MISC=/bin/rm,/bin/cat:\
-                SHUTDOWN=/sbin/halt,/sbin/shutdown
+<PRE> # Cmnd alias specification
+ Cmnd_Alias     DUMPS = /usr/bin/mt, /usr/sbin/dump, /usr/sbin/rdump,\
+                        /usr/sbin/restore, /usr/sbin/rrestore
+ Cmnd_Alias     KILL = /usr/bin/kill
+ Cmnd_Alias     PRINTING = /usr/sbin/lpc, /usr/bin/lprm
+ Cmnd_Alias     SHUTDOWN = /usr/sbin/shutdown
+ Cmnd_Alias     HALT = /usr/sbin/halt, /usr/sbin/fasthalt
+ Cmnd_Alias     REBOOT = /usr/sbin/reboot, /usr/sbin/fastboot
+ Cmnd_Alias     SHELLS = /usr/bin/sh, /usr/bin/csh, /usr/bin/ksh, \
+                         /usr/local/bin/tcsh, /usr/bin/rsh, \
+                         /usr/local/bin/zsh
+ Cmnd_Alias     SU = /usr/bin/su
 </PRE>
 <P>
-<PRE>    # User specification
-    FULLTIME    ALL=(ALL) NOPASSWD: ALL
-    %wheel      ALL=ALL
-    PARTTIME    ALL=ALL,!SHELLS,!SU
-    +interns    +openlabs=ALL,!SHELLS,!SU
-    britt       REMOTE=SHUTDOWN:ALL=LPCS
-    jimbo       CUNETS=/usr/bin/su [!-]*,!/usr/bin/su *root*
-    nieusma     SERVERS=SHUTDOWN,/sbin/reboot:\
-                HUB=ALL,!SHELLS
-    jill        houdini=/sbin/shutdown -[hr] now,MISC
-    markm       HUB=ALL,!MISC,!/sbin/shutdown,!/sbin/halt
-    davehieb    merlin=(OP) ALL:SERVERS=/sbin/halt:\
-                kodiakthorn=NOPASSWD: ALL
-    steve       CSNETS=(operator) /usr/op_commands/
+The <EM>User specification</EM> is the part that actually determines who may run what.
+
+<P>
+<PRE> root           ALL = (ALL) ALL
+ %wheel         ALL = (ALL) ALL
 </PRE>
 <P>
-<HR>
-<H2><A NAME="Host_Alias_specifications_">Host Alias specifications:</A></H2>
+We let <STRONG>root</STRONG> and any user in group <STRONG>wheel</STRONG> run any command on any host as any user.
+
 <P>
-The are four <EM>host aliases</EM>. The first actually contains two <EM>aliases</EM>. It sets <CODE>HUB</CODE> to be <CODE>houdini</CODE> and <CODE>REMOTE</CODE>
-to the three machines <CODE>merlin</CODE>, <CODE>kodiakthorn</CODE> and <CODE>spirit</CODE>. Similarly, <CODE>SERVERS</CODE> is set to the machines <CODE>houdini</CODE>, <CODE>merlin</CODE>,
-<CODE>kodiakthorn</CODE> and <CODE>spirit</CODE>. The <CODE>CSNETS</CODE> alias will match any host on the 128.138.243.0, 128.138.204.0, or
-128.138.205.192 nets. The <CODE>CUNETS</CODE> alias will match any host on the 128.138.0.0 (class B) network. Note that
-these are <STRONG>network</STRONG> addresses, not ip addresses. Unless an explicit netmask is given, the local <EM>netmask</EM>
-is used to determine whether or not the current host belongs to a network.
+<PRE> FULLTIMERS     ALL = NOPASSWD: ALL
+</PRE>
+<P>
+Full time sysadmins (<STRONG>millert</STRONG>, <STRONG>mikef</STRONG>, and <STRONG>dowdy</STRONG>) may run any command on any host without authenticating themselves.
+
+<P>
+<PRE> PARTTIMERS     ALL = ALL
+</PRE>
+<P>
+Part time sysadmins (<STRONG>bostley</STRONG>, <STRONG>jwfox</STRONG>, and <STRONG>crawl</STRONG>) may run any command on any host but they must authenticate themselves
+first (since the entry lacks the <CODE>NOPASSWD</CODE> tag).
+
+<P>
+<PRE> jack           CSNETS = ALL
+</PRE>
+<P>
+The user <STRONG>jack</STRONG> may run any command on the machines in the <EM>CSNETS</EM> alias (the networks <CODE>128.138.243.0</CODE>, <CODE>128.138.204.0</CODE>, and <CODE>128.138.242.0</CODE>). Of those networks, only &lt;128.138.204.0&gt; has an explicit netmask (in CIDR notation) indicating it
+is a class C network. For the other networks in <EM>CSNETS</EM>, the local machine's netmask will be used during matching.
+
+<P>
+<PRE> lisa           CUNETS = ALL
+</PRE>
+<P>
+The user <STRONG>lisa</STRONG> may run any command on any host in the <EM>CUNETS</EM> alias (the class B network <CODE>128.138.0.0</CODE>).
+
+<P>
+<PRE> operator       ALL = DUMPS, KILL, PRINTING, SHUTDOWN, HALT, REBOOT,\
+                /usr/oper/bin/
+</PRE>
+<P>
+The <STRONG>operator</STRONG> user may run commands limited to simple maintenance. Here, those are
+commands related to backups, killing processes, the printing system,
+shutting down the system, and any commands in the directory <EM>/usr/oper/bin/</EM>.
+
+<P>
+<PRE> joe            ALL = /usr/bin/su operator
+</PRE>
+<P>
+The user <STRONG>joe</STRONG> may only <CODE>su(1)</CODE> to operator.
+
+<P>
+<PRE> pete           HPPA = /usr/bin/passwd [A-z]*, !/usr/bin/passwd root
+</PRE>
+<P>
+The user <STRONG>pete</STRONG> is allowed to change anyone's password except for root on the <EM>HPPA</EM> machines. Note that this assumes <CODE>passwd(1)</CODE> does not take
+multiple usernames on the command line.
+
+<P>
+<PRE> bob            SPARC = (OP) ALL : SGI = (OP) ALL
+</PRE>
+<P>
+The user <STRONG>bob</STRONG> may run anything on the <EM>SPARC</EM> and <EM>SGI</EM> machines as any user listed in the <EM>OP</EM>  <CODE>Runas_Alias</CODE> (<STRONG>root</STRONG> and <STRONG>operator</STRONG>).
+
+<P>
+<PRE> jim            +biglab = ALL
+</PRE>
+<P>
+The user <STRONG>jim</STRONG> may run any command on machines in the <EM>biglab</EM> netgroup.
+<STRONG>Sudo</STRONG> knows that ``biglab'' is a netgroup due to the '+' prefix.
+
+<P>
+<PRE> +secretaries   ALL = PRINTING, /usr/bin/adduser, /usr/bin/rmuser
+</PRE>
+<P>
+Users in the <STRONG>secretaries</STRONG> netgroup need to help manage the printers as well as add and remove users,
+so they are allowed to run those commands on all machines.
+
+<P>
+<PRE> fred           ALL = (DB) NOPASSWD: ALL
+</PRE>
+<P>
+The user <STRONG>fred</STRONG> can run commands as any user in the <EM>DB</EM>  <CODE>Runas_Alias</CODE>
+(<STRONG>oracle</STRONG> or <STRONG>sybase</STRONG>) without giving a password.
+
+<P>
+<PRE> john           ALPHA = /usr/bin/su [!-]*, !/usr/bin/su *root*
+</PRE>
+<P>
+On the <EM>ALPHA</EM> machines, user <STRONG>john</STRONG> may su to anyone except root but he is not allowed to give
+<CODE>su(1)</CODE> any flags.
+
+<P>
+<PRE> jen            ALL, !SERVERS = ALL
+</PRE>
+<P>
+The user <STRONG>jen</STRONG> may run any command on any machine except for those in the <EM>SERVERS</EM>  <CODE>Host_Alias</CODE> (master, mail, www and ns).
+
+<P>
+<PRE> jill           SERVERS = /usr/bin/, !SU, !SHELLS
+</PRE>
+<P>
+For any machine in the <EM>SERVERS</EM>  <CODE>Host_Alias</CODE>, <STRONG>jill</STRONG> may run any commands in the directory /usr/bin/ except for those commands
+belonging to the <EM>SU</EM> and <EM>SHELLS</EM>  <CODE>Cmnd_Aliases</CODE>.
+
+<P>
+<PRE> steve          CSNETS = (operator) /usr/local/op_commands/
+</PRE>
+<P>
+The user <STRONG>steve</STRONG> may run any command in the directory /usr/local/op_commands/ but only as
+user operator.
+
+<P>
+<PRE> matt           valkyrie = KILL
+</PRE>
+<P>
+On his personal workstation, valkyrie, <STRONG>matt</STRONG> needs to be able to kill hung processes.
+
+<P>
+<PRE> WEBMASTERS     www = (www) ALL, (root) /usr/bin/su www
+</PRE>
+<P>
+On the host www, any user in the <EM>WEBMASTERS</EM>  <CODE>User_Alias</CODE> (will, wendy, and wim), may run any command as user www (which owns the web
+pages) or simply <CODE>su(1)</CODE> to www.
+
+<P>
+<PRE> ALL            CDROM = NOPASSWD: /sbin/umount /CDROM,\
+                /sbin/mount -o nosuid\,nodev /dev/cd0a /CDROM
+</PRE>
+<P>
+Any user may mount or unmount a CD-ROM on the machines in the CDROM
+<CODE>Host_Alias</CODE> (orion, perseus, hercules) without entering a password. This is a bit
+tedious for users to type, so it is a prime candiate for encapsulating in a
+shell script.
 
 <P>
 <HR>
-<H2><A NAME="User_Alias_specifications_">User Alias specifications:</A></H2>
+<H1><A NAME="SECURITY_NOTES">SECURITY NOTES</A></H1>
 <P>
-The two <EM>user aliases</EM> simply groups the <A HREF="#item_FULLTIME">FULLTIME</A> and
-<A HREF="#item_PARTTIME">PARTTIME</A> folks into two separate aliases.
+It is generally not effective to ``subtract'' commands from <CODE>ALL</CODE>
+using the '!' operator. A user can trivially circumvent this by copying the
+desired command to a different name and then executing that. For example:
 
 <P>
-<HR>
-<H2><A NAME="Command_alias_specifications_">Command alias specifications:</A></H2>
+<PRE>    bill        ALL = ALL, !SU, !SHELLS
+</PRE>
 <P>
-Command aliases are lists of commands with or without associated command
-line arguments. The entries above should be self-explanatory.
+Doesn't really prevent <STRONG>bill</STRONG> from running the commands listed in
+<EM>SU</EM> or <EM>SHELLS</EM> since he can simply copy those commands to a different name, or use a shell
+escape from an editor or other program. Therefore, these kind of
+restrictions should be considered advisory at best (and reinforced by
+policy).
 
-<P>
-<HR>
-<H2><A NAME="User_specifications_">User specifications:</A></H2>
-<DL>
-<DT><STRONG><A NAME="item_FULLTIME">FULLTIME</A></STRONG><DD>
-<P>
-Full-time sysadmins in the <A HREF="#item_FULLTIME">FULLTIME</A> alias may run any command on any host as any user without a password.
-
-<DT><STRONG><A NAME="item__wheel">%wheel</A></STRONG><DD>
-<P>
-Any user in the UN*X group <CODE>wheel</CODE> may run any command on any host.
-
-<DT><STRONG><A NAME="item_PARTTIME">PARTTIME</A></STRONG><DD>
-<P>
-Part-time sysadmins in the <A HREF="#item_PARTTIME">PARTTIME</A> alias may run any command except those in the <CODE>SHELLS</CODE> and <CODE>SU</CODE> aliases on any host.
-
-<DT><STRONG><A NAME="item__interns">+interns</A></STRONG><DD>
-<P>
-Any user in the netgroup <CODE>interns</CODE> may run any command except those in the <CODE>SHELLS</CODE> and <CODE>SU</CODE> aliases on any host that is in the <CODE>openlabs</CODE> netgroup.
-
-<DT><STRONG><A NAME="item_britt">britt</A></STRONG><DD>
-<P>
-The user <A HREF="#item_britt">britt</A> may run commands in the <CODE>SHUTDOWN</CODE> alias on the <CODE>REMOTE</CODE> machines and commands in the <CODE>LPCS</CODE> alias on any machine.
-
-<DT><STRONG><A NAME="item_jimbo">jimbo</A></STRONG><DD>
-<P>
-The user <A HREF="#item_jimbo">jimbo</A> may <CODE>su</CODE> to any user save root on the machines on <CODE>CUNETS</CODE> (which is explicitly listed as a class B network).
-
-<DT><STRONG><A NAME="item_nieusma">nieusma</A></STRONG><DD>
-<P>
-The user <A HREF="#item_nieusma">nieusma</A> may run commands in the <CODE>SHUTDOWN</CODE> alias as well as <EM>/sbin/reboot</EM> on the <CODE>SERVER</CODE> machines and any command except those in the <CODE>SHELLS</CODE> alias on the <CODE>HUB</CODE>
-machines.
-
-<DT><STRONG><A NAME="item_jill">jill</A></STRONG><DD>
-<P>
-The user <A HREF="#item_jill">jill</A> may run <CODE>/sbin/shutdown -h now</CODE> or
-<CODE>/sbin/shutdown -r now</CODE> as well as the commands in the
-<CODE>MISC</CODE> alias on houdini.
-
-<DT><STRONG><A NAME="item_markm">markm</A></STRONG><DD>
-<P>
-The user <A HREF="#item_markm">markm</A> may run any command on the <CODE>HUB</CODE> machines except <EM>/sbin/shutdown</EM>, <EM>/sbin/halt</EM>, and commands listed in the <CODE>MISC</CODE> alias.
-
-<DT><STRONG><A NAME="item_davehieb">davehieb</A></STRONG><DD>
-<P>
-The user <A HREF="#item_davehieb">davehieb</A> may run any command on <CODE>merlin</CODE> as any user in the Runas_Alias OP (ie: root or operator). He may also run <EM>/sbin/halt</EM> on the <CODE>SERVERS</CODE> and any command on <CODE>kodiakthorn</CODE> (no password required on <CODE>kodiakthorn</CODE>).
-
-<DT><STRONG><A NAME="item_steve">steve</A></STRONG><DD>
-<P>
-The user <A HREF="#item_steve">steve</A> may run any command in the <EM>/usr/op_commands/</EM>
-directory as user <CODE>operator</CODE> on the machines on <CODE>CSNETS</CODE>.
-
-</DL>
 <P>
 <HR>
 <H1><A NAME="CAVEATS">CAVEATS</A></H1>
 <P>
 The <EM>sudoers</EM> file should <STRONG>always</STRONG> be edited by the <STRONG>visudo</STRONG>
 command which locks the file and does grammatical checking. It is
-imperative that the <EM>sudoers</EM> be free of syntax errors since sudo will not run with a syntactically
-incorrect <EM>sudoers</EM> file.
+imperative that <EM>sudoers</EM> be free of syntax errors since <STRONG>sudo</STRONG>
+will not run with a syntactically incorrect <EM>sudoers</EM> file.
 
 <P>
 <HR>
 <H1><A NAME="FILES">FILES</A></H1>
 <P>
-<PRE> /etc/sudoers           file of authorized users.
- /etc/netgroup          list of network groups.
+<PRE> /etc/sudoers           List of who can run what
+ /etc/group             Local groups file
+ /etc/netgroup          List of network groups
 </PRE>
 <P>
 <HR>
diff --git a/sudoers.man b/sudoers.man
index 18aa96893..64374408f 100644
--- a/sudoers.man
+++ b/sudoers.man
@@ -2,8 +2,8 @@
 ''' $RCSfile$$Revision$$Date$
 '''
 ''' $Log$
-''' Revision 1.10  1999/06/22 10:38:38  millert
-''' typos
+''' Revision 1.11  1999/08/26 09:00:58  millert
+''' new sudoers(8) man page
 '''
 '''
 .de Sh
@@ -96,7 +96,7 @@
 .nr % 0
 .rr F
 .\}
-.TH sudoers 5 "1.6" "22/Jun/1999" "FILE FORMATS"
+.TH SUDOERS 5 "1.6" "25/Aug/1999" "FILE FORMATS"
 .UC
 .if n .hy 0
 .if n .na
@@ -191,123 +191,230 @@
 .\}
 .rm #[ #] #H #V #F C
 .SH "NAME"
-sudoers \- list of which users may execute what as root
+sudoers \- list of which users may execute what
 .SH "DESCRIPTION"
-The \fIsudoers\fR file is composed of an optional host alias section,
-an optional command alias section and the user specification section.
-All command or host aliases need to start with their respective keywords
-(ie: Host_Alias, User_Alias, Runas_Alias or Cmnd_Alias).
-If there are multiple occurrences of a user, the logical union of the
-entries will be used.  Note that if there is an entry that denies access
-to a command that is followed by an entry that grants access the user
-will be allowed to run the command.
-.Sh "user specification format:"
+The \fIsudoers\fR file is composed two types of entries:
+aliases (basically variables) and user specifications
+(which specify who may run what).  The grammar of \fIsudoers\fR
+will be described below in Extended Backus-Naur Form (EBNF).
+Don't despair if you don't know what EBNF is, it is fairly
+simple and the definitions below are annotated.
+.Sh "Quick guide to \s-1EBNF\s0"
+\s-1EBNF\s0 is a concise and exact way of describing the grammar of a language.
+Each \s-1EBNF\s0 definition is made up of \fIproduction rules\fR.  Eg.
 .PP
 .Vb 1
-\&  user access_group [: access_group] ...
+\& symbol ::= definition | alternate1 | alternate2 ...
 .Ve
+Each \fIproduction rule\fR references others and thus makes up a
+grammar for the language.  \s-1EBNF\s0 also contains the following
+operators, which many readers will recognize from regular
+expressions.  Do not, however, confuse them with \*(L"wildcard\*(R"
+characters, which have different meanings.
+.Ip "\f(CW?\fR" 8
+Means that the preceding symbol (or group of symbols) is optional.
+That is, it may appear once or not at all.
+.Ip "\f(CW*\fR" 8
+Means that the preceding symbol (or group of symbols) may appear
+zero or more times.
+.Ip "\f(CW+\fR" 8
+Means that the preceding symbol (or group of symbols) may appear
+one or more times.
+.PP
+Parentheses may be used to group symbols together.  For clarity,
+we will use single quotes ('') to designate what is a verbatim character
+string (as opposed to a symbol name).
+.Sh "Aliases"
+There are four kinds of aliases: the \f(CWUser_Alias\fR, \f(CWRunas_Alias\fR,
+\f(CWHost_Alias\fR and \f(CWCmnd_Alias\fR.
+.PP
 .Vb 4
-\&    access_group ::= host-list = [(runas-list)] [NOPASSWD:] [op]cmnd_type
-\&                     [,[(user-list)] [NOPASSWD|PASSWD:] [op]cmnd_type] ... 
-\&       cmnd_type ::= a command OR a command alias.
-\&              op ::= the logical "!" NOT operator.
+\& Alias ::= User_Alias = User_Alias (':' User_Alias)* |
+\&           Runas_Alias (':' Runas_Alias)* |
+\&           Host_Alias (':' Host_Alias)* |
+\&           Cmnd_Alias (':' Cmnd_Alias)*
 .Ve
-.Sh "host alias section format:"
+.Vb 1
+\& User_Alias ::= NAME '=' User_List
+.Ve
+.Vb 1
+\& Runas_Alias ::= NAME '=' Runas_User_List
+.Ve
+.Vb 1
+\& Host_Alias ::= NAME '=' Host_List
+.Ve
+.Vb 1
+\& Cmnd_Alias ::= NAME '=' Cmnd_List
+.Ve
+.Vb 1
+\& NAME ::= [A-Z]([A-Z][0-9]_)*
+.Ve
+Each \fIalias\fR definition is of the form
 .PP
 .Vb 1
-\&  Host_Alias HOSTALIAS = host-list
+\& Alias_Type NAME = item1, item2, ...
 .Ve
-.Vb 5
-\&      Host_Alias ::= a keyword.
-\&       HOSTALIAS ::= an upper-case alias name.
-\&       host-list ::= a comma separated list of hosts, netgroups,
-\&                     ip addresses, networks.  A logical "!"
-\&                     NOT operator may be prefixed to any of these.
-.Ve
-.Sh "user alias section format:"
+where \fIAlias_Type\fR is one of \f(CWUser_Alias\fR, \f(CWRunas_Alias\fR, \f(CWHost_Alias\fR,
+or \f(CWCmnd_Alias\fR.  A \f(CWNAME\fR is a string of upper case letters, numbers,
+and the underscore characters ('_').  A \f(CWNAME\fR \fBmust\fR start with an
+upper case letter.  It is possible to put several alias definitions
+of the same type on a single line, joined by a semicolon (':').  Eg.
 .PP
 .Vb 1
-\&  User_Alias USERALIAS = user-list
+\& Alias_Type NAME = item1, item2, item3 : NAME = item4, item5
 .Ve
-.Vb 5
-\&      User_Alias ::= a keyword.
-\&       USERALIAS ::= an upper-case alias name.
-\&       user-list ::= a comma separated list of users, groups, netgroups.
-\&                     A logical "!" NOT operator may be prefixed to any
-\&                     of these.
-.Ve
-.Sh "runas alias section format:"
-.PP
-.Vb 1
-\&  Runas_Alias RUNASALIAS = runas-list
-.Ve
-.Vb 5
-\&      Runas_Alias ::= a keyword.
-\&       RUNASALIAS ::= an upper-case alias name.
-\&       runas-list ::= a comma separated list of users, groups, netgroups.
-\&                      A logical "!" NOT operator may be prefixed to any
-\&                      of these.
-.Ve
-.Sh "command alias section format:"
-.PP
-.Vb 1
-\&  Cmnd_Alias CMNDALIAS = cmnd-list
-.Ve
-.Vb 5
-\&      Cmnd_Alias ::= a keyword.
-\&       CMNDALIAS ::= an upper-case alias name.
-\&       cmnd-list ::= a comma separated list commands.
-\&                     A logical "!" NOT operator may be prefixed to any
-\&                     of these.
-.Ve
-.Sh "command specification:"
-.PP
-.Vb 1
-\&  path arg1 arg2 .. argn = command
-.Ve
-.Vb 2
-\&            path ::= a fully qualified pathname.
-\&       arg[1..n] ::= optional command line arguments.
-.Ve
-.Sh "persistence of modifiers"
-When a \fIrunas-list\fR is specified for an \fIaccess_group\fR, it
-affects all commands in the \fIaccess_group\fR.  For example, given:
-.PP
-.Vb 1
-\&    oper bigserver = (root, sysadm) /usr/bin/kill, /bin/rm
-.Ve
-User \f(CWoper\fR will be able to run \f(CW/usr/bin/kill\fR and \f(CW/bin/rm\fR
-as \fBroot\fR or \fBsysadm\fR on the machine, \f(CWbigserver\fR.  The
-\fIrunas-list\fR is \*(L"sticky\*(R" across entries in the comma-separated
-\fIaccess_group\fR.  You can override the \fIrunas-list\fR with another
-one, at which point the new \fIrunas-list\fR becomes the default for
-that \fIaccess_group\fR.  For example, given:
+The definitions of what constitutes a valid \fIalias\fR member follow.
 .PP
 .Vb 2
-\&    oper bigserver = (root, sysadm) /usr/bin/kill, (root) /bin/rm, \e
-\&        /bin/rmdir
+\& User_List ::= User |
+\&               User ',' User_List
 .Ve
-User \f(CWoper\fR can still run \f(CW/usr/bin/kill\fR as \fBroot\fR or \fBsysadm\fR but
-can only run \f(CW/bin/rm\fR and \f(CW/bin/rmdir\fR as \fBroot\fR.
+.Vb 5
+\& User ::= '!'* username |
+\&          '!'* '#'uid |
+\&          '!'* '%'group |
+\&          '!'* '+'netgroup |
+\&          '!'* User_Alias
+.Ve
+A \f(CWUser_List\fR is made up of one or more usernames, uids
+(prefixed with \*(L'#'), System groups (prefixed with \*(L'%'),
+netgroups (prefixed with \*(L'+') and other aliases.  Each list
+item may be prefixed with one or more \*(L'!\*(R' operators.  An odd number
+of \*(L'!\*(R' operators negates the value of the item; an even number
+just cancel each other out.
 .PP
-Similarly, the \fB\s-1NOPASSWD\s0\fR modifier is also persistent across an
-\fIaccess_group\fR. For example given:
+.Vb 2
+\& Runas_List ::= Runas_User |
+\&                Runas_User ',' Runas_List
+.Ve
+.Vb 5
+\& Runas_User ::= '!'* username |
+\&                '!'* '#'uid |
+\&                '!'* '%'group |
+\&                '!'* +netgroup |
+\&                '!'* Runas_Alias
+.Ve
+Likewise, a \f(CWRunas_List\fR has the same possible elements
+as a \f(CWUser_List\fR, except that it can include a \f(CWRunas_Alias\fR,
+instead of a \f(CWUser_Alias\fR.
+.PP
+.Vb 2
+\& Host_List ::= Host |
+\&               Host ',' Host_List
+.Ve
+.Vb 5
+\& Host ::= '!'* hostname |
+\&          '!'* ip_addr |
+\&          '!'* network(/netmask)? |
+\&          '!'* '+'netgroup |
+\&          '!'* Host_Alias
+.Ve
+A \f(CWHost_List\fR is made up of one or more hostnames, \s-1IP\s0 addresses,
+network numbers, netgroups (prefixed with \*(L'+') and other aliases.
+Again, the value of an item may be negated with the \*(L'!\*(R' operator.
+If you do not specify a netmask with a network number, the netmask
+of the host's ethernet \fIinterface\fR\|(s) will be used when matching.
+The netmask may be specified either in dotted quad notation (eg.
+255.255.255.0) or \s-1CIDR\s0 notation (number of bits, eg. 24).
+.PP
+.Vb 2
+\& Cmnd_List ::= Cmnd |
+\&               Cmnd ',' Cmnd_List
+.Ve
+.Vb 3
+\& commandname ::= filename |
+\&                 filename args |
+\&                 filename '""'
+.Ve
+.Vb 3
+\& Cmnd ::= '!'* commandname |
+\&          '!'* directory |
+\&          '!'* Cmnd_Alias
+.Ve
+A \f(CWCmnd_List\fR is a list of one or more commandnames, directories, and other
+aliases.  A commandname is a fully-qualified filename which may include
+shell-style wildcards (see `Wildcards\*(R' section below).  A simple
+filename allows the user to run the command with any arguments he/she
+wishes.  However, you may also command line arguments (including wildcards).
+Alternately, you can specify \f(CW""\fR to indicate that the command
+may only be run \fBwithout\fR command line arguments.  A directory is a
+fully qualified pathname ending in a \*(L'/\*(R'.  When you specify a directory
+in a \f(CWCmnd_List\fR, the user will be able to run any file within that directory
+(but not in any subdirectories therein).
+.PP
+If a \f(CWCmnd\fR has associated command line arguments, then the arguments
+in the \f(CWCmnd\fR must match exactly those given by the user on the command line
+(or match the wildcards if there are any).  Note that the following
+characters must be escaped with a \*(L'\e\*(R' if they are used in command
+arguments: \*(L',\*(R', \*(L':\*(R', \*(L'=\*(R', \*(L'\e\e\*(R'.
+.Sh "User Specification"
 .PP
 .Vb 1
-\&    oper bigserver = NOPASSWD: /usr/bin/kill, /bin/rm, /bin/rmdir
+\& Runas_Spec ::= '(' Runas_List ')'
 .Ve
-User \f(CWoper\fR will be able to run \f(CW/usr/bin/kill\fR, \f(CW/bin/rm\fR, and
-\f(CW/bin/rmdir\fR as \fBroot\fR without a password.  If we change that to:
+.Vb 1
+\& Cmnd_Spec ::= Runas_Spec? ('NOPASSWD:' | 'PASSWD:')? Cmnd
+.Ve
+.Vb 2
+\& Cmnd_Spec_List ::= Cmnd_Spec |
+\&                    Cmnd_Spec ',' Cmnd_Spec_List
+.Ve
+.Vb 1
+\& User_Spec ::= User_list Cmnd_Spec_List (':' User_Spec)*
+.Ve
+A \fBuser specification\fR determines which commands a user may run
+(and as what user) on specified hosts.  By default, commands are
+run as \fBroot\fR but this can be changed on a per-command basis.
+.PP
+Let's break that down into its constituent parts:
+.Sh "Runas_Spec"
+A \f(CWRunas_Spec\fR is simply a \f(CWRunas_List\fR (as defined above)
+enclosed in a set of parentheses.  If you do not specify a
+\f(CWRunas_Spec\fR in the user specification, a default \f(CWRunas_Spec\fR
+of \fBroot\fR will be used.  A \f(CWRunas_Spec\fR sets the default for
+commands that follow it.  What this means is that for the entry:
 .PP
 .Vb 1
-\&    oper bigserver = NOPASSWD: /usr/bin/kill, PASSWD: /bin/rm, /bin/rmdir
+\& dgb    boulder = (operator) /bin/ls, /bin/kill, /usr/bin/who
 .Ve
-User \f(CWoper\fR can still run \f(CW/usr/bin/kill\fR without a password but
-must give a password to run \f(CW/bin/rm\fR and \f(CW/bin/rmdir\fR.
-.Sh "wildcards (aka meta characters):"
-\fBsudo\fR allows shell-style \fIwildcards\fR along with command arguments
-in the \fIsudoers\fR file.  Wildcard matching is done via the \fB\s-1POSIX\s0\fR
-\f(CWfnmatch(3)\fR routine.
+The user \fBdgb\fR may run \fI/bin/ls\fR, \fI/bin/kill\fR, and
+\fI/usr/bin/lprm\fR -- but only as \fBoperator\fR.  Eg.
+.PP
+.Vb 1
+\&    sudo -u operator /bin/ls.
+.Ve
+It is also possible to override a \f(CWRunas_Spec\fR later on in an
+entry.  If we modify the entry like so:
+.PP
+.Vb 1
+\& dgb    boulder = (operator) /bin/ls, (root) /bin/kill, /usr/bin/lprm
+.Ve
+Then user \fBdgb\fR is now allowed to run \fI/bin/ls\fR as \fBoperator\fR,
+but  \fI/bin/kill\fR and \fI/usr/bin/lprm\fR as \fBroot\fR.
+.Sh "\s-1NOPASSWD\s0 and \s-1PASSWD\s0"
+By default, \fBsudo\fR requires that a user authenticate him or herself
+before running a command.  This behavior can be modified via the
+\f(CWNOPASSWD\fR tag.  Like a \f(CWRunas_Spec\fR, the \f(CWNOPASSWD\fR tag sets
+a default for the commands that follow it in the \f(CWCmnd_Spec_List\fR.
+Conversely, the \f(CWPASSWD\fR tag can be used to reverse things.
+For example:
+.PP
+.Vb 1
+\& ray    rushmore = NOPASSWD: /bin/kill, /bin/ls, /usr/bin/lprm
+.Ve
+would allow the user \fBray\fR to run \fI/bin/kill\fR, \fI/bin/ls\fR, and
+\fI/usr/bin/lprm\fR as root on the machine rushmore as \fBroot\fR without
+authenticating himself.  If we only want \fBray\fR to be able to
+run \fI/bin/kill\fR without a password the entry would be:
+.PP
+.Vb 1
+\& ray    rushmore = NOPASSWD: /bin/kill, PASSWD: /bin/ls, /usr/bin/lprm
+.Ve
+.Sh "Wildcards (aka meta characters):"
+\fBsudo\fR allows shell-style \fIwildcards\fR to be used in pathnames
+as well as command line arguments in the \fIsudoers\fR file.  Wildcard
+matching is done via the \fB\s-1POSIX\s0\fR \f(CWfnmatch(3)\fR routine.  Note that
+these are \fInot\fR regular expressions.
 .Ip "\f(CW*\fR" 8
 Matches any set of zero or more characters.
 .Ip "\f(CW?\fR" 8
@@ -319,180 +426,272 @@ Matches any character \fBnot\fR in the specified range.
 .Ip "\f(CW\ex\fR" 8
 For any character \*(L"x\*(R", evaluates to \*(L"x\*(R".  This is used to
 escape special characters such as: \*(L"*\*(R", \*(L"?\*(R", \*(L"[\*(R", and \*(L"}\*(R".
-.Sh "exceptions to wildcard rules:"
-The following exceptions apply to the above rules:
-.Ip "\f(CW""\fR" 8
-If the empty string \f(CW""\fR is the only command line argument in the
-\fIsudoers\fR entry it means that command may take \fBno\fR arguments.
-.Sh "other special characters and reserved words:"
-Text after a pound sign (\fB#\fR) is considered a comment.
-Words that begin with a percent sign (\fB%\fR) are assumed to
-be \s-1UN\s0*X groups (%staff refers to users in the group \fIstaff\fR).
-Words that begin with a plus sign (\fB+\fR) are assumed to
-be netgroups (\fB+cshosts\fR refers to the netgroup \fIcshosts\fR).
-Long lines can be newline escaped with the backslash \fB\e\fR character.
 .PP
-The reserved word \fB\s-1NOPASSWD\s0\fR indicates that a user need not
-enter a password for the command listed in that entry.  The
-\fB\s-1NOPASSWD\s0\fR modifier is persistent across entries in a \fIuser-list\fR
-and can be reversed with the \fB\s-1PASSWD\s0\fR modifier.
-.PP
-The reserved alias \fI\s-1ALL\s0\fR can be used for both {Host,User,Cmnd}_Alias.
-\fB\s-1DO\s0 \s-1NOT\s0\fR define an alias of \fI\s-1ALL\s0\fR, it will \fB\s-1NOT\s0\fR be used.
-Note that \fI\s-1ALL\s0\fR implies the entire universe of hosts/users/commands.
-You can subtract elements from the universe by using the syntax:
+Note that a forward slash ('/') will \fBnot\fR be matched by
+wildcards used in the pathname.  When matching the command
+line arguments, however, as slash \fBdoes\fR get matched by
+wildcards.  This is to make a path like:
 .PP
 .Vb 1
-\&   user  host=ALL,!ALIAS1,!/sbin/halt...
+\&    /usr/bin/*
 .Ve
-Commands may have optional command line arguments.  If they do,
-then the arguments in the \fIsudoers\fR file must exactly match those
-on the command line.  It is also possible to have a command's
-arguments span multiple lines as long as the line continuance
-character \*(L"\e\*(R" is used.  The following characters must be escaped
-with a \*(L"\e\*(R" if used in command arguments: \*(L",\*(R", \*(L":\*(R", \*(L"=\*(R", \*(L"\e\*(R".
-.SH "EXAMPLES"
+match \f(CW/usr/bin/who\fR but not \f(CW/usr/bin/X11/xterm\fR.
+.Sh "Exceptions to wildcard rules:"
+The following exceptions apply to the above rules:
+.Ip \f(CW""\fR 8
+If the empty string \f(CW""\fR is the only command line argument in the
+\fIsudoers\fR entry it means that command is not allowed to be run
+with \fBany\fR arguments.
+.Sh "Other special characters and reserved words:"
+The pound sign ('#') is used to indicate a comment (unless it
+occurs in the context of a user name and is followed by one or
+more digits, in which case it is treated as a uid).  Both the
+comment character and any text after it, up to the end of the line,
+are ignored.
 .PP
-.Vb 7
-\&    # Host alias specification
-\&    Host_Alias  HUB=houdini:\e
-\&                REMOTE=merlin,kodiakthorn,spirit
-\&    Host_Alias  SERVERS=houdini,merlin,kodiakthorn,spirit
-\&    Host_Alias  CUNETS=128.138.0.0/255.255.0.0
-\&    Host_Alias  CSNETS=128.138.243.0,128.138.204.0,\e
-\&                       128.138.205.192
+The reserved word \fB\s-1ALL\s0\fR is a a built in \fIalias\fR that always causes
+a match to succeed.  It can be used wherever one might otherwise
+use a \f(CWCmnd_Alias\fR, \f(CWUser_Alias\fR, \f(CWRunas_Alias\fR, or \f(CWHost_Alias\fR.
+You should not try to define your own \fIalias\fR called \fB\s-1ALL\s0\fR as the
+built in alias will be used in preference to your own.
+.PP
+An exclamation point (\*(R'!') can be used as a logical \fInot\fR operator
+both in an \fIalias\fR and in front of a \f(CWCmnd\fR.  This allows one to
+exclude certain values.  Note, however, that using a \f(CW!\fR in
+conjunction with the built in \f(CWALL\fR alias to allow a user to
+run \*(L"all but a few\*(R" commands rarely works as intended (see \s-1SECURITY\s0
+\s-1NOTES\s0 below).
+.PP
+Long lines can be continued with a backslash (\*(R'\e\e') as the last
+character on the line.
+.PP
+Whitespace between elements in a list as well as specicial syntactic
+characters in a \fIUser Specification\fR ('=\*(R', \*(L':\*(R', \*(L'(\*(R', \*(L')') is optional.
+.SH "EXAMPLES"
+Below are example \fIsudoers\fR entries.  Admittedly, some of
+these are a bit contrived.  First, we define our \fIaliases\fR:
+.PP
+.Vb 4
+\& # User alias specification
+\& User_Alias     FULLTIMERS = millert, mikef, dowdy
+\& User_Alias     PARTTIMERS = bostley, jwfox, crawl
+\& User_Alias     WEBMASTERS = will, wendy, wim
 .Ve
 .Vb 3
-\&    # User alias specification
-\&    User_Alias  FULLTIME=millert,dowdy,mikef
-\&    User_Alias  PARTTIME=juola,mccreary,tor
+\& # Runas alias specification
+\& Runas_Alias    OP = root, operator
+\& Runas_Alias    DB = oracle, sybase
 .Ve
+.Vb 9
+\& # Host alias specification
+\& Host_Alias     SPARC = bigtime, eclipse, moet, anchor :\e
+\&                SGI = grolsch, dandelion, black :\e
+\&                ALPHA = widget, thalamus, foobar :\e
+\&                HPPA = boa, nag, python
+\& Host_Alias     CUNETS = 128.138.0.0/255.255.0.0
+\& Host_Alias     CSNETS = 128.138.243.0, 128.138.204.0/24, 128.138.242.0
+\& Host_Alias     SERVERS = master, mail, www, ns
+\& Host_Alias     CDROM = orion, perseus, hercules
+.Ve
+.Vb 12
+\& # Cmnd alias specification
+\& Cmnd_Alias     DUMPS = /usr/bin/mt, /usr/sbin/dump, /usr/sbin/rdump,\e
+\&                        /usr/sbin/restore, /usr/sbin/rrestore
+\& Cmnd_Alias     KILL = /usr/bin/kill
+\& Cmnd_Alias     PRINTING = /usr/sbin/lpc, /usr/bin/lprm
+\& Cmnd_Alias     SHUTDOWN = /usr/sbin/shutdown
+\& Cmnd_Alias     HALT = /usr/sbin/halt, /usr/sbin/fasthalt
+\& Cmnd_Alias     REBOOT = /usr/sbin/reboot, /usr/sbin/fastboot
+\& Cmnd_Alias     SHELLS = /usr/bin/sh, /usr/bin/csh, /usr/bin/ksh, \e
+\&                         /usr/local/bin/tcsh, /usr/bin/rsh, \e
+\&                         /usr/local/bin/zsh
+\& Cmnd_Alias     SU = /usr/bin/su
+.Ve
+The \fIUser specification\fR is the part that actually determines who may
+run what.
+.PP
 .Vb 2
-\&    # Runas alias specification
-\&    Runas_Alias OP=root,operator
+\& root           ALL = (ALL) ALL
+\& %wheel         ALL = (ALL) ALL
 .Ve
-.Vb 6
-\&    # Command alias specification
-\&    Cmnd_Alias  LPCS=/usr/sbin/lpc,/usr/bin/lprm
-\&    Cmnd_Alias  SHELLS=/bin/sh,/bin/csh,/bin/tcsh,/bin/ksh
-\&    Cmnd_Alias  SU=/usr/bin/su
-\&    Cmnd_Alias  MISC=/bin/rm,/bin/cat:\e
-\&                SHUTDOWN=/sbin/halt,/sbin/shutdown
+We let \fBroot\fR and any user in group \fBwheel\fR run any command on any
+host as any user.
+.PP
+.Vb 1
+\& FULLTIMERS     ALL = NOPASSWD: ALL
 .Ve
-.Vb 14
-\&    # User specification
-\&    FULLTIME    ALL=(ALL) NOPASSWD: ALL
-\&    %wheel      ALL=ALL
-\&    PARTTIME    ALL=ALL,!SHELLS,!SU
-\&    +interns    +openlabs=ALL,!SHELLS,!SU
-\&    britt       REMOTE=SHUTDOWN:ALL=LPCS
-\&    jimbo       CUNETS=/usr/bin/su [!-]*,!/usr/bin/su *root*
-\&    nieusma     SERVERS=SHUTDOWN,/sbin/reboot:\e
-\&                HUB=ALL,!SHELLS
-\&    jill        houdini=/sbin/shutdown -[hr] now,MISC
-\&    markm       HUB=ALL,!MISC,!/sbin/shutdown,!/sbin/halt
-\&    davehieb    merlin=(OP) ALL:SERVERS=/sbin/halt:\e
-\&                kodiakthorn=NOPASSWD: ALL
-\&    steve       CSNETS=(operator) /usr/op_commands/
+Full time sysadmins (\fBmillert\fR, \fBmikef\fR, and \fBdowdy\fR) may run any
+command on any host without authenticating themselves.
+.PP
+.Vb 1
+\& PARTTIMERS     ALL = ALL
 .Ve
-.Sh "Host Alias specifications:"
-The are four \fIhost aliases\fR.  The first actually contains
-two \fIaliases\fR.  It sets \f(CWHUB\fR to be \f(CWhoudini\fR and \f(CWREMOTE\fR
-to the three machines \f(CWmerlin\fR, \f(CWkodiakthorn\fR and \f(CWspirit\fR.
-Similarly, \f(CWSERVERS\fR is set to the machines \f(CWhoudini\fR, \f(CWmerlin\fR,
-\f(CWkodiakthorn\fR and \f(CWspirit\fR.  The \f(CWCSNETS\fR alias will match
-any host on the 128.138.243.0, 128.138.204.0, or 128.138.205.192
-nets.  The \f(CWCUNETS\fR alias will match any host on the 128.138.0.0
-(class B) network.  Note that these are \fBnetwork\fR addresses, not ip
-addresses.  Unless an explicit netmask is given, the local \fInetmask\fR
-is used to determine whether or not the current host belongs to a network.
-.Sh "User Alias specifications:"
-The two \fIuser aliases\fR simply groups the \f(CWFULLTIME\fR and
-\f(CWPARTTIME\fR folks into two separate aliases.
-.Sh "Command alias specifications:"
-Command aliases are lists of commands with or without associated
-command line arguments.  The entries above should be self-explanatory.
-.Sh "User specifications:"
-.Ip "\s-1FULLTIME\s0" 16
-Full-time sysadmins in the \f(CWFULLTIME\fR alias may run any
-command on any host as any user without a password.
-.Ip "%wheel" 16
-Any user in the \s-1UN\s0*X group \f(CWwheel\fR may run any
-command on any host.
-.Ip "\s-1PARTTIME\s0" 16
-Part-time sysadmins in the \f(CWPARTTIME\fR alias may run any
-command except those in the \f(CWSHELLS\fR and \f(CWSU\fR aliases
-on any host.
-.Ip "+interns" 16
-Any user in the netgroup \f(CWinterns\fR may run any
-command except those in the \f(CWSHELLS\fR and \f(CWSU\fR aliases
-on any host that is in the \f(CWopenlabs\fR netgroup.
-.Ip "britt" 16
-The user \f(CWbritt\fR may run commands in the \f(CWSHUTDOWN\fR alias
-on the \f(CWREMOTE\fR machines and commands in the \f(CWLPCS\fR alias
-on any machine.
-.Ip "jimbo" 16
-The user \f(CWjimbo\fR may \f(CWsu\fR to any user save root on the
-machines on \f(CWCUNETS\fR (which is explicitly listed as a class
-B network).
-.Ip "nieusma" 16
-The user \f(CWnieusma\fR may run commands in the \f(CWSHUTDOWN\fR alias
-as well as \fI/sbin/reboot\fR on the \f(CWSERVER\fR machines and
-any command except those in the \f(CWSHELLS\fR alias on the \f(CWHUB\fR
-machines.
-.Ip "jill" 16
-The user \f(CWjill\fR may run \f(CW/sbin/shutdown -h now\fR or
-\f(CW/sbin/shutdown -r now\fR as well as the commands in the
-\f(CWMISC\fR alias on houdini.
-.Ip "markm" 16
-The user \f(CWmarkm\fR may run any command on the \f(CWHUB\fR machines
-except \fI/sbin/shutdown\fR, \fI/sbin/halt\fR, and commands listed
-in the \f(CWMISC\fR alias.
-.Ip "davehieb" 16
-The user \f(CWdavehieb\fR may run any command on \f(CWmerlin\fR as any
-user in the Runas_Alias \s-1OP\s0 (ie: root or operator).  He may
-also run \fI/sbin/halt\fR on the \f(CWSERVERS\fR and any command
-on \f(CWkodiakthorn\fR (no password required on \f(CWkodiakthorn\fR).
-.Ip "steve" 16
-The user \f(CWsteve\fR may run any command in the \fI/usr/op_commands/\fR
-directory as user \f(CWoperator\fR on the machines on \f(CWCSNETS\fR.
+Part time sysadmins (\fBbostley\fR, \fBjwfox\fR, and \fBcrawl\fR) may run any
+command on any host but they must authenticate themselves first
+(since the entry lacks the \f(CWNOPASSWD\fR tag).
+.PP
+.Vb 1
+\& jack           CSNETS = ALL
+.Ve
+The user \fBjack\fR may run any command on the machines in the \fICSNETS\fR alias
+(the networks \f(CW128.138.243.0\fR, \f(CW128.138.204.0\fR, and \f(CW128.138.242.0\fR).
+Of those networks, only <128.138.204.0> has an explicit netmask (in
+CIDR notation) indicating it is a class C network.  For the other
+networks in \fICSNETS\fR, the local machine's netmask will be used
+during matching.
+.PP
+.Vb 1
+\& lisa           CUNETS = ALL
+.Ve
+The user \fBlisa\fR may run any command on any host in the \fICUNETS\fR alias
+(the class B network \f(CW128.138.0.0\fR).
+.PP
+.Vb 2
+\& operator       ALL = DUMPS, KILL, PRINTING, SHUTDOWN, HALT, REBOOT,\e
+\&                /usr/oper/bin/
+.Ve
+The \fBoperator\fR user may run commands limited to simple maintenance.
+Here, those are commands related to backups, killing processes, the
+printing system, shutting down the system, and any commands in the
+directory \fI/usr/oper/bin/\fR.
+.PP
+.Vb 1
+\& joe            ALL = /usr/bin/su operator
+.Ve
+The user \fBjoe\fR may only \fIsu\fR\|(1) to operator.
+.PP
+.Vb 1
+\& pete           HPPA = /usr/bin/passwd [A-z]*, !/usr/bin/passwd root
+.Ve
+The user \fBpete\fR is allowed to change anyone's password except for
+root on the \fIHPPA\fR machines.  Note that this assumes \fIpasswd\fR\|(1)
+does not take multiple usernames on the command line.
+.PP
+.Vb 1
+\& bob            SPARC = (OP) ALL : SGI = (OP) ALL
+.Ve
+The user \fBbob\fR may run anything on the \fISPARC\fR and \fISGI\fR machines
+as any user listed in the \fIOP\fR \f(CWRunas_Alias\fR (\fBroot\fR and \fBoperator\fR).
+.PP
+.Vb 1
+\& jim            +biglab = ALL
+.Ve
+The user \fBjim\fR may run any command on machines in the \fIbiglab\fR netgroup.
+\fBSudo\fR knows that \*(L"biglab\*(R" is a netgroup due to the \*(L'+\*(R' prefix.
+.PP
+.Vb 1
+\& +secretaries   ALL = PRINTING, /usr/bin/adduser, /usr/bin/rmuser
+.Ve
+Users in the \fBsecretaries\fR netgroup need to help manage the printers
+as well as add and remove users, so they are allowed to run those
+commands on all machines.
+.PP
+.Vb 1
+\& fred           ALL = (DB) NOPASSWD: ALL
+.Ve
+The user \fBfred\fR can run commands as any user in the \fIDB\fR \f(CWRunas_Alias\fR
+(\fBoracle\fR or \fBsybase\fR) without giving a password.
+.PP
+.Vb 1
+\& john           ALPHA = /usr/bin/su [!-]*, !/usr/bin/su *root*
+.Ve
+On the \fIALPHA\fR machines, user \fBjohn\fR may su to anyone except root
+but he is not allowed to give \fIsu\fR\|(1) any flags.
+.PP
+.Vb 1
+\& jen            ALL, !SERVERS = ALL
+.Ve
+The user \fBjen\fR may run any command on any machine except for those
+in the \fISERVERS\fR \f(CWHost_Alias\fR (master, mail, www and ns).
+.PP
+.Vb 1
+\& jill           SERVERS = /usr/bin/, !SU, !SHELLS
+.Ve
+For any machine in the \fISERVERS\fR \f(CWHost_Alias\fR, \fBjill\fR may run
+any commands in the directory /usr/bin/ except for those commands
+belonging to the \fISU\fR and \fISHELLS\fR \f(CWCmnd_Aliases\fR.
+.PP
+.Vb 1
+\& steve          CSNETS = (operator) /usr/local/op_commands/
+.Ve
+The user \fBsteve\fR may run any command in the directory /usr/local/op_commands/
+but only as user operator.
+.PP
+.Vb 1
+\& matt           valkyrie = KILL
+.Ve
+On his personal workstation, valkyrie, \fBmatt\fR needs to be able to
+kill hung processes.
+.PP
+.Vb 1
+\& WEBMASTERS     www = (www) ALL, (root) /usr/bin/su www
+.Ve
+On the host www, any user in the \fIWEBMASTERS\fR \f(CWUser_Alias\fR (will,
+wendy, and wim), may run any command as user www (which owns the
+web pages) or simply \fIsu\fR\|(1) to www.
+.PP
+.Vb 2
+\& ALL            CDROM = NOPASSWD: /sbin/umount /CDROM,\e
+\&                /sbin/mount -o nosuid\e,nodev /dev/cd0a /CDROM
+.Ve
+Any user may mount or unmount a CD\-ROM on the machines in the CDROM
+\f(CWHost_Alias\fR (orion, perseus, hercules) without entering a password.
+This is a bit tedious for users to type, so it is a prime candiate
+for encapsulating in a shell script.
+.SH "SECURITY NOTES"
+It is generally not effective to \*(L"subtract\*(R" commands from \f(CWALL\fR
+using the \*(L'!\*(R' operator.  A user can trivially circumvent this
+by copying the desired command to a different name and then
+executing that.  For example:
+.PP
+.Vb 1
+\&    bill        ALL = ALL, !SU, !SHELLS
+.Ve
+Doesn't really prevent \fBbill\fR from running the commands listed in
+\fISU\fR or \fISHELLS\fR since he can simply copy those commands to a
+different name, or use a shell escape from an editor or other
+program.  Therefore, these kind of restrictions should be considered
+advisory at best (and reinforced by policy).
 .SH "CAVEATS"
 The \fIsudoers\fR file should \fBalways\fR be edited by the \fBvisudo\fR
 command which locks the file and does grammatical checking. It is
-imperative that the \fIsudoers\fR be free of syntax errors since sudo
+imperative that \fIsudoers\fR be free of syntax errors since \fBsudo\fR
 will not run with a syntactically incorrect \fIsudoers\fR file.
 .SH "FILES"
 .PP
-.Vb 2
-\& /etc/sudoers           file of authorized users.
-\& /etc/netgroup          list of network groups.
+.Vb 3
+\& /etc/sudoers           List of who can run what
+\& /etc/group             Local groups file
+\& /etc/netgroup          List of network groups
 .Ve
 .SH "SEE ALSO"
 \fIsudo\fR\|(8), \fIvisudo\fR\|(8), \fIsu\fR\|(1), \fIfnmatch\fR\|(3).
 
 .rn }` ''
-.IX Title "sudoers 5"
-.IX Name "sudoers - list of which users may execute what as root"
+.IX Title "SUDOERS 5"
+.IX Name "sudoers - list of which users may execute what"
 
 .IX Header "NAME"
 
 .IX Header "DESCRIPTION"
 
-.IX Subsection "user specification format:"
+.IX Subsection "Quick guide to \s-1EBNF\s0"
 
-.IX Subsection "host alias section format:"
+.IX Item "\f(CW?\fR"
 
-.IX Subsection "user alias section format:"
+.IX Item "\f(CW*\fR"
 
-.IX Subsection "runas alias section format:"
+.IX Item "\f(CW+\fR"
 
-.IX Subsection "command alias section format:"
+.IX Subsection "Aliases"
 
-.IX Subsection "command specification:"
+.IX Subsection "User Specification"
 
-.IX Subsection "persistence of modifiers"
+.IX Subsection "Runas_Spec"
 
-.IX Subsection "wildcards (aka meta characters):"
+.IX Subsection "\s-1NOPASSWD\s0 and \s-1PASSWD\s0"
+
+.IX Subsection "Wildcards (aka meta characters):"
 
 .IX Item "\f(CW*\fR"
 
@@ -504,43 +703,15 @@ will not run with a syntactically incorrect \fIsudoers\fR file.
 
 .IX Item "\f(CW\ex\fR"
 
-.IX Subsection "exceptions to wildcard rules:"
+.IX Subsection "Exceptions to wildcard rules:"
 
 .IX Item "\f(CW""\fR"
 
-.IX Subsection "other special characters and reserved words:"
+.IX Subsection "Other special characters and reserved words:"
 
 .IX Header "EXAMPLES"
 
-.IX Subsection "Host Alias specifications:"
-
-.IX Subsection "User Alias specifications:"
-
-.IX Subsection "Command alias specifications:"
-
-.IX Subsection "User specifications:"
-
-.IX Item "\s-1FULLTIME\s0"
-
-.IX Item "%wheel"
-
-.IX Item "\s-1PARTTIME\s0"
-
-.IX Item "+interns"
-
-.IX Item "britt"
-
-.IX Item "jimbo"
-
-.IX Item "nieusma"
-
-.IX Item "jill"
-
-.IX Item "markm"
-
-.IX Item "davehieb"
-
-.IX Item "steve"
+.IX Header "SECURITY NOTES"
 
 .IX Header "CAVEATS"
 
diff --git a/sudoers.pod b/sudoers.pod
index deb901c55..654d89b0c 100644
--- a/sudoers.pod
+++ b/sudoers.pod
@@ -1,116 +1,261 @@
 =cut
+Copyright (c) 1994-1996,1998-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
+   from the author.
+
+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.
+
 $Sudo$
 =pod
 
 =head1 NAME
 
-sudoers - list of which users may execute what as root
+sudoers - list of which users may execute what
 
 =head1 DESCRIPTION
 
-The I<sudoers> file is composed of an optional host alias section,
-an optional command alias section and the user specification section.
-All command or host aliases need to start with their respective keywords
-(ie: Host_Alias, User_Alias, Runas_Alias or Cmnd_Alias).
-If there are multiple occurrences of a user, the logical union of the
-entries will be used.  Note that if there is an entry that denies access
-to a command that is followed by an entry that grants access the user
-will be allowed to run the command.
+The I<sudoers> file is composed two types of entries:
+aliases (basically variables) and user specifications
+(which specify who may run what).  The grammar of I<sudoers>
+will be described below in Extended Backus-Naur Form (EBNF).
+Don't despair if you don't know what EBNF is, it is fairly
+simple and the definitions below are annotated.
 
-=head2 user specification format:
+=head2 Quick guide to EBNF
 
-  user access_group [: access_group] ...
+EBNF is a concise and exact way of describing the grammar of a language.
+Each EBNF definition is made up of I<production rules>.  Eg.
 
-    access_group ::= host-list = [(runas-list)] [NOPASSWD:] [op]cmnd_type
-		     [,[(user-list)] [NOPASSWD|PASSWD:] [op]cmnd_type] ... 
-       cmnd_type ::= a command OR a command alias.
-              op ::= the logical "!" NOT operator.
+ symbol ::= definition | alternate1 | alternate2 ...
 
-=head2 host alias section format:
+Each I<production rule> references others and thus makes up a
+grammar for the language.  EBNF also contains the following
+operators, which many readers will recognize from regular
+expressions.  Do not, however, confuse them with "wildcard"
+characters, which have different meanings.
 
-  Host_Alias HOSTALIAS = host-list
+=over 8
 
-      Host_Alias ::= a keyword.
-       HOSTALIAS ::= an upper-case alias name.
-       host-list ::= a comma separated list of hosts, netgroups,
-                     ip addresses, networks.  A logical "!"
-		     NOT operator may be prefixed to any of these.
+=item C<?>
 
-=head2 user alias section format:
+Means that the preceding symbol (or group of symbols) is optional.
+That is, it may appear once or not at all.
 
-  User_Alias USERALIAS = user-list
+=item C<*>
 
-      User_Alias ::= a keyword.
-       USERALIAS ::= an upper-case alias name.
-       user-list ::= a comma separated list of users, groups, netgroups.
-                     A logical "!" NOT operator may be prefixed to any
-		     of these.
+Means that the preceding symbol (or group of symbols) may appear
+zero or more times.
 
-=head2 runas alias section format:
+=item C<+>
 
-  Runas_Alias RUNASALIAS = runas-list
+Means that the preceding symbol (or group of symbols) may appear
+one or more times.
 
-      Runas_Alias ::= a keyword.
-       RUNASALIAS ::= an upper-case alias name.
-       runas-list ::= a comma separated list of users, groups, netgroups.
-                      A logical "!" NOT operator may be prefixed to any
-		      of these.
+=back
 
-=head2 command alias section format:
+Parentheses may be used to group symbols together.  For clarity,
+we will use single quotes ('') to designate what is a verbatim character
+string (as opposed to a symbol name).
 
-  Cmnd_Alias CMNDALIAS = cmnd-list
+=head2 Aliases
 
-      Cmnd_Alias ::= a keyword.
-       CMNDALIAS ::= an upper-case alias name.
-       cmnd-list ::= a comma separated list commands.
-                     A logical "!" NOT operator may be prefixed to any
-		     of these.
+There are four kinds of aliases: the C<User_Alias>, C<Runas_Alias>,
+C<Host_Alias> and C<Cmnd_Alias>.
 
-=head2 command specification:
+ Alias ::= User_Alias = User_Alias (':' User_Alias)* |
+	   Runas_Alias (':' Runas_Alias)* |
+	   Host_Alias (':' Host_Alias)* |
+	   Cmnd_Alias (':' Cmnd_Alias)*
 
-  path arg1 arg2 .. argn = command
+ User_Alias ::= NAME '=' User_List
 
-            path ::= a fully qualified pathname.
-       arg[1..n] ::= optional command line arguments.
+ Runas_Alias ::= NAME '=' Runas_User_List
 
-=head2 persistence of modifiers
+ Host_Alias ::= NAME '=' Host_List
 
-When a I<runas-list> is specified for an I<access_group>, it
-affects all commands in the I<access_group>.  For example, given:
+ Cmnd_Alias ::= NAME '=' Cmnd_List
 
-    oper bigserver = (root, sysadm) /usr/bin/kill, /bin/rm
+ NAME ::= [A-Z]([A-Z][0-9]_)*
 
-User C<oper> will be able to run C</usr/bin/kill> and C</bin/rm>
-as B<root> or B<sysadm> on the machine, C<bigserver>.  The
-I<runas-list> is "sticky" across entries in the comma-separated
-I<access_group>.  You can override the I<runas-list> with another
-one, at which point the new I<runas-list> becomes the default for
-that I<access_group>.  For example, given:
+Each I<alias> definition is of the form
 
-    oper bigserver = (root, sysadm) /usr/bin/kill, (root) /bin/rm, \
-	/bin/rmdir
+ Alias_Type NAME = item1, item2, ...
 
-User C<oper> can still run C</usr/bin/kill> as B<root> or B<sysadm> but
-can only run C</bin/rm> and C</bin/rmdir> as B<root>.
+where I<Alias_Type> is one of C<User_Alias>, C<Runas_Alias>, C<Host_Alias>,
+or C<Cmnd_Alias>.  A C<NAME> is a string of upper case letters, numbers,
+and the underscore characters ('_').  A C<NAME> B<must> start with an
+upper case letter.  It is possible to put several alias definitions
+of the same type on a single line, joined by a semicolon (':').  Eg.
 
-Similarly, the B<NOPASSWD> modifier is also persistent across an
-I<access_group>. For example given:
+ Alias_Type NAME = item1, item2, item3 : NAME = item4, item5
 
-    oper bigserver = NOPASSWD: /usr/bin/kill, /bin/rm, /bin/rmdir
+The definitions of what constitutes a valid I<alias> member follow.
 
-User C<oper> will be able to run C</usr/bin/kill>, C</bin/rm>, and
-C</bin/rmdir> as B<root> without a password.  If we change that to:
+ User_List ::= User |
+	       User ',' User_List
 
-    oper bigserver = NOPASSWD: /usr/bin/kill, PASSWD: /bin/rm, /bin/rmdir
+ User ::= '!'* username |
+	  '!'* '#'uid |
+	  '!'* '%'group |
+	  '!'* '+'netgroup |
+	  '!'* User_Alias
 
-User C<oper> can still run C</usr/bin/kill> without a password but
-must give a password to run C</bin/rm> and C</bin/rmdir>.
+A C<User_List> is made up of one or more usernames, uids
+(prefixed with '#'), System groups (prefixed with '%'),
+netgroups (prefixed with '+') and other aliases.  Each list
+item may be prefixed with one or more '!' operators.  An odd number
+of '!' operators negates the value of the item; an even number
+just cancel each other out.
 
-=head2 wildcards (aka meta characters):
+ Runas_List ::= Runas_User |
+		Runas_User ',' Runas_List
 
-B<sudo> allows shell-style I<wildcards> along with command arguments
-in the I<sudoers> file.  Wildcard matching is done via the B<POSIX>
-C<fnmatch(3)> routine.
+ Runas_User ::= '!'* username |
+	        '!'* '#'uid |
+	        '!'* '%'group |
+	        '!'* +netgroup |
+	        '!'* Runas_Alias
+
+Likewise, a C<Runas_List> has the same possible elements
+as a C<User_List>, except that it can include a C<Runas_Alias>,
+instead of a C<User_Alias>.
+
+ Host_List ::= Host |
+	       Host ',' Host_List
+
+ Host ::= '!'* hostname |
+	  '!'* ip_addr |
+	  '!'* network(/netmask)? |
+	  '!'* '+'netgroup |
+	  '!'* Host_Alias
+
+A C<Host_List> is made up of one or more hostnames, IP addresses,
+network numbers, netgroups (prefixed with '+') and other aliases.
+Again, the value of an item may be negated with the '!' operator.
+If you do not specify a netmask with a network number, the netmask
+of the host's ethernet interface(s) will be used when matching.
+The netmask may be specified either in dotted quad notation (eg.
+255.255.255.0) or CIDR notation (number of bits, eg. 24).
+
+ Cmnd_List ::= Cmnd |
+	       Cmnd ',' Cmnd_List
+
+ commandname ::= filename |
+	         filename args |
+	         filename '""'
+
+ Cmnd ::= '!'* commandname |
+	  '!'* directory |
+	  '!'* Cmnd_Alias
+
+A C<Cmnd_List> is a list of one or more commandnames, directories, and other
+aliases.  A commandname is a fully-qualified filename which may include
+shell-style wildcards (see `Wildcards' section below).  A simple
+filename allows the user to run the command with any arguments he/she
+wishes.  However, you may also command line arguments (including wildcards).
+Alternately, you can specify C<""> to indicate that the command
+may only be run B<without> command line arguments.  A directory is a
+fully qualified pathname ending in a '/'.  When you specify a directory
+in a C<Cmnd_List>, the user will be able to run any file within that directory
+(but not in any subdirectories therein).
+
+If a C<Cmnd> has associated command line arguments, then the arguments
+in the C<Cmnd> must match exactly those given by the user on the command line
+(or match the wildcards if there are any).  Note that the following
+characters must be escaped with a '\' if they are used in command
+arguments: ',', ':', '=', '\\'.
+
+=head2 User Specification
+
+ Runas_Spec ::= '(' Runas_List ')'
+
+ Cmnd_Spec ::= Runas_Spec? ('NOPASSWD:' | 'PASSWD:')? Cmnd
+
+ Cmnd_Spec_List ::= Cmnd_Spec |
+		    Cmnd_Spec ',' Cmnd_Spec_List
+
+ User_Spec ::= User_list Cmnd_Spec_List (':' User_Spec)*
+
+A B<user specification> determines which commands a user may run
+(and as what user) on specified hosts.  By default, commands are
+run as B<root> but this can be changed on a per-command basis.
+
+Let's break that down into its constituent parts:
+
+=head2 Runas_Spec
+
+A C<Runas_Spec> is simply a C<Runas_List> (as defined above)
+enclosed in a set of parentheses.  If you do not specify a
+C<Runas_Spec> in the user specification, a default C<Runas_Spec>
+of B<root> will be used.  A C<Runas_Spec> sets the default for
+commands that follow it.  What this means is that for the entry:
+
+ dgb	boulder = (operator) /bin/ls, /bin/kill, /usr/bin/who
+
+The user B<dgb> may run F</bin/ls>, F</bin/kill>, and
+F</usr/bin/lprm> -- but only as B<operator>.  Eg.
+
+    sudo -u operator /bin/ls.
+
+It is also possible to override a C<Runas_Spec> later on in an
+entry.  If we modify the entry like so:
+
+ dgb	boulder = (operator) /bin/ls, (root) /bin/kill, /usr/bin/lprm
+
+Then user B<dgb> is now allowed to run F</bin/ls> as B<operator>,
+but  F</bin/kill> and F</usr/bin/lprm> as B<root>.
+
+=head2 NOPASSWD and PASSWD
+
+By default, B<sudo> requires that a user authenticate him or herself
+before running a command.  This behavior can be modified via the
+C<NOPASSWD> tag.  Like a C<Runas_Spec>, the C<NOPASSWD> tag sets
+a default for the commands that follow it in the C<Cmnd_Spec_List>.
+Conversely, the C<PASSWD> tag can be used to reverse things.
+For example:
+
+ ray	rushmore = NOPASSWD: /bin/kill, /bin/ls, /usr/bin/lprm
+
+would allow the user B<ray> to run F</bin/kill>, F</bin/ls>, and
+F</usr/bin/lprm> as root on the machine rushmore as B<root> without
+authenticating himself.  If we only want B<ray> to be able to
+run F</bin/kill> without a password the entry would be:
+
+ ray	rushmore = NOPASSWD: /bin/kill, PASSWD: /bin/ls, /usr/bin/lprm
+
+=head2 Wildcards (aka meta characters):
+
+B<sudo> allows shell-style I<wildcards> to be used in pathnames
+as well as command line arguments in the I<sudoers> file.  Wildcard
+matching is done via the B<POSIX> C<fnmatch(3)> routine.  Note that
+these are I<not> regular expressions.
 
 =over 8
 
@@ -137,7 +282,16 @@ escape special characters such as: "*", "?", "[", and "}".
 
 =back
 
-=head2 exceptions to wildcard rules:
+Note that a forward slash ('/') will B<not> be matched by
+wildcards used in the pathname.  When matching the command
+line arguments, however, as slash B<does> get matched by
+wildcards.  This is to make a path like:
+
+    /usr/bin/*
+
+match C</usr/bin/who> but not C</usr/bin/X11/xterm>.
+
+=head2 Exceptions to wildcard rules:
 
 The following exceptions apply to the above rules:
 
@@ -146,182 +300,215 @@ The following exceptions apply to the above rules:
 =item C<"">
 
 If the empty string C<""> is the only command line argument in the
-I<sudoers> entry it means that command may take B<no> arguments.
+I<sudoers> entry it means that command is not allowed to be run
+with B<any> arguments.
 
 =back
 
-=head2 other special characters and reserved words:
+=head2 Other special characters and reserved words:
 
-Text after a pound sign (B<#>) is considered a comment.
-Words that begin with a percent sign (B<%>) are assumed to
-be UN*X groups (%staff refers to users in the group I<staff>).
-Words that begin with a plus sign (B<+>) are assumed to
-be netgroups (B<+cshosts> refers to the netgroup I<cshosts>).
-Long lines can be newline escaped with the backslash B<\> character.
+The pound sign ('#') is used to indicate a comment (unless it
+occurs in the context of a user name and is followed by one or
+more digits, in which case it is treated as a uid).  Both the
+comment character and any text after it, up to the end of the line,
+are ignored.
 
-The reserved word B<NOPASSWD> indicates that a user need not
-enter a password for the command listed in that entry.  The
-B<NOPASSWD> modifier is persistent across entries in a I<user-list>
-and can be reversed with the B<PASSWD> modifier.
+The reserved word B<ALL> is a a built in I<alias> that always causes
+a match to succeed.  It can be used wherever one might otherwise
+use a C<Cmnd_Alias>, C<User_Alias>, C<Runas_Alias>, or C<Host_Alias>.
+You should not try to define your own I<alias> called B<ALL> as the
+built in alias will be used in preference to your own.
 
-The reserved alias I<ALL> can be used for both {Host,User,Cmnd}_Alias.
-B<DO NOT> define an alias of I<ALL>, it will B<NOT> be used.
-Note that I<ALL> implies the entire universe of hosts/users/commands.
-You can subtract elements from the universe by using the syntax:
+An exclamation point ('!') can be used as a logical I<not> operator
+both in an I<alias> and in front of a C<Cmnd>.  This allows one to
+exclude certain values.  Note, however, that using a C<!> in
+conjunction with the built in C<ALL> alias to allow a user to
+run "all but a few" commands rarely works as intended (see SECURITY
+NOTES below).
 
-   user  host=ALL,!ALIAS1,!/sbin/halt...
+Long lines can be continued with a backslash ('\\') as the last
+character on the line.
 
-Commands may have optional command line arguments.  If they do,
-then the arguments in the I<sudoers> file must exactly match those
-on the command line.  It is also possible to have a command's
-arguments span multiple lines as long as the line continuance
-character "\" is used.  The following characters must be escaped
-with a "\" if used in command arguments: ",", ":", "=", "\".
+Whitespace between elements in a list as well as specicial syntactic
+characters in a I<User Specification> ('=', ':', '(', ')') is optional.
 
 =head1 EXAMPLES
 
-    # Host alias specification
-    Host_Alias  HUB=houdini:\
-                REMOTE=merlin,kodiakthorn,spirit
-    Host_Alias  SERVERS=houdini,merlin,kodiakthorn,spirit
-    Host_Alias  CUNETS=128.138.0.0/255.255.0.0
-    Host_Alias  CSNETS=128.138.243.0,128.138.204.0,\
-                       128.138.205.192
+Below are example I<sudoers> entries.  Admittedly, some of
+these are a bit contrived.  First, we define our I<aliases>:
 
-    # User alias specification
-    User_Alias  FULLTIME=millert,dowdy,mikef
-    User_Alias  PARTTIME=juola,mccreary,tor
+ # User alias specification
+ User_Alias	FULLTIMERS = millert, mikef, dowdy
+ User_Alias	PARTTIMERS = bostley, jwfox, crawl
+ User_Alias	WEBMASTERS = will, wendy, wim
 
-    # Runas alias specification
-    Runas_Alias	OP=root,operator
+ # Runas alias specification
+ Runas_Alias	OP = root, operator
+ Runas_Alias	DB = oracle, sybase
 
-    # Command alias specification
-    Cmnd_Alias  LPCS=/usr/sbin/lpc,/usr/bin/lprm
-    Cmnd_Alias  SHELLS=/bin/sh,/bin/csh,/bin/tcsh,/bin/ksh
-    Cmnd_Alias  SU=/usr/bin/su
-    Cmnd_Alias  MISC=/bin/rm,/bin/cat:\
-                SHUTDOWN=/sbin/halt,/sbin/shutdown
+ # Host alias specification
+ Host_Alias	SPARC = bigtime, eclipse, moet, anchor :\
+		SGI = grolsch, dandelion, black :\
+		ALPHA = widget, thalamus, foobar :\
+		HPPA = boa, nag, python
+ Host_Alias	CUNETS = 128.138.0.0/255.255.0.0
+ Host_Alias	CSNETS = 128.138.243.0, 128.138.204.0/24, 128.138.242.0
+ Host_Alias	SERVERS = master, mail, www, ns
+ Host_Alias	CDROM = orion, perseus, hercules
 
-    # User specification
-    FULLTIME    ALL=(ALL) NOPASSWD: ALL
-    %wheel	ALL=ALL
-    PARTTIME    ALL=ALL,!SHELLS,!SU
-    +interns    +openlabs=ALL,!SHELLS,!SU
-    britt       REMOTE=SHUTDOWN:ALL=LPCS
-    jimbo	CUNETS=/usr/bin/su [!-]*,!/usr/bin/su *root*
-    nieusma     SERVERS=SHUTDOWN,/sbin/reboot:\
-                HUB=ALL,!SHELLS
-    jill        houdini=/sbin/shutdown -[hr] now,MISC
-    markm       HUB=ALL,!MISC,!/sbin/shutdown,!/sbin/halt
-    davehieb    merlin=(OP) ALL:SERVERS=/sbin/halt:\
-                kodiakthorn=NOPASSWD: ALL
-    steve       CSNETS=(operator) /usr/op_commands/
+ # Cmnd alias specification
+ Cmnd_Alias	DUMPS = /usr/bin/mt, /usr/sbin/dump, /usr/sbin/rdump,\
+			/usr/sbin/restore, /usr/sbin/rrestore
+ Cmnd_Alias	KILL = /usr/bin/kill
+ Cmnd_Alias	PRINTING = /usr/sbin/lpc, /usr/bin/lprm
+ Cmnd_Alias	SHUTDOWN = /usr/sbin/shutdown
+ Cmnd_Alias	HALT = /usr/sbin/halt, /usr/sbin/fasthalt
+ Cmnd_Alias	REBOOT = /usr/sbin/reboot, /usr/sbin/fastboot
+ Cmnd_Alias	SHELLS = /usr/bin/sh, /usr/bin/csh, /usr/bin/ksh, \
+			 /usr/local/bin/tcsh, /usr/bin/rsh, \
+			 /usr/local/bin/zsh
+ Cmnd_Alias	SU = /usr/bin/su
 
-=head2 Host Alias specifications:
+The I<User specification> is the part that actually determines who may
+run what.
 
-The are four I<host aliases>.  The first actually contains
-two I<aliases>.  It sets C<HUB> to be C<houdini> and C<REMOTE>
-to the three machines C<merlin>, C<kodiakthorn> and C<spirit>.
-Similarly, C<SERVERS> is set to the machines C<houdini>, C<merlin>,
-C<kodiakthorn> and C<spirit>.  The C<CSNETS> alias will match
-any host on the 128.138.243.0, 128.138.204.0, or 128.138.205.192
-nets.  The C<CUNETS> alias will match any host on the 128.138.0.0
-(class B) network.  Note that these are B<network> addresses, not ip
-addresses.  Unless an explicit netmask is given, the local I<netmask>
-is used to determine whether or not the current host belongs to a network.
+ root		ALL = (ALL) ALL
+ %wheel		ALL = (ALL) ALL
 
-=head2 User Alias specifications:
+We let B<root> and any user in group B<wheel> run any command on any
+host as any user.
 
-The two I<user aliases> simply groups the C<FULLTIME> and
-C<PARTTIME> folks into two separate aliases.
+ FULLTIMERS	ALL = NOPASSWD: ALL
 
-=head2 Command alias specifications:
+Full time sysadmins (B<millert>, B<mikef>, and B<dowdy>) may run any
+command on any host without authenticating themselves.
 
-Command aliases are lists of commands with or without associated
-command line arguments.  The entries above should be self-explanatory.
+ PARTTIMERS	ALL = ALL
 
-=head2 User specifications:
+Part time sysadmins (B<bostley>, B<jwfox>, and B<crawl>) may run any
+command on any host but they must authenticate themselves first
+(since the entry lacks the C<NOPASSWD> tag).
 
-=over 16
+ jack		CSNETS = ALL
 
-=item FULLTIME
+The user B<jack> may run any command on the machines in the I<CSNETS> alias
+(the networks C<128.138.243.0>, C<128.138.204.0>, and C<128.138.242.0>).
+Of those networks, only <128.138.204.0> has an explicit netmask (in
+CIDR notation) indicating it is a class C network.  For the other
+networks in I<CSNETS>, the local machine's netmask will be used
+during matching.
 
-Full-time sysadmins in the C<FULLTIME> alias may run any
-command on any host as any user without a password.
+ lisa		CUNETS = ALL
 
-=item %wheel
+The user B<lisa> may run any command on any host in the I<CUNETS> alias
+(the class B network C<128.138.0.0>).
 
-Any user in the UN*X group C<wheel> may run any
-command on any host.
+ operator	ALL = DUMPS, KILL, PRINTING, SHUTDOWN, HALT, REBOOT,\
+		/usr/oper/bin/
 
-=item PARTTIME
+The B<operator> user may run commands limited to simple maintenance.
+Here, those are commands related to backups, killing processes, the
+printing system, shutting down the system, and any commands in the
+directory F</usr/oper/bin/>.
 
-Part-time sysadmins in the C<PARTTIME> alias may run any
-command except those in the C<SHELLS> and C<SU> aliases
-on any host.
+ joe		ALL = /usr/bin/su operator
 
-=item +interns
+The user B<joe> may only su(1) to operator.
 
-Any user in the netgroup C<interns> may run any
-command except those in the C<SHELLS> and C<SU> aliases
-on any host that is in the C<openlabs> netgroup.
+ pete		HPPA = /usr/bin/passwd [A-z]*, !/usr/bin/passwd root
 
-=item britt
+The user B<pete> is allowed to change anyone's password except for
+root on the I<HPPA> machines.  Note that this assumes passwd(1)
+does not take multiple usernames on the command line.
 
-The user C<britt> may run commands in the C<SHUTDOWN> alias
-on the C<REMOTE> machines and commands in the C<LPCS> alias
-on any machine.
+ bob		SPARC = (OP) ALL : SGI = (OP) ALL
 
-=item jimbo
+The user B<bob> may run anything on the I<SPARC> and I<SGI> machines
+as any user listed in the I<OP> C<Runas_Alias> (B<root> and B<operator>).
 
-The user C<jimbo> may C<su> to any user save root on the
-machines on C<CUNETS> (which is explicitly listed as a class
-B network).
+ jim		+biglab = ALL
 
-=item nieusma
+The user B<jim> may run any command on machines in the I<biglab> netgroup.
+B<Sudo> knows that "biglab" is a netgroup due to the '+' prefix.
 
-The user C<nieusma> may run commands in the C<SHUTDOWN> alias
-as well as F</sbin/reboot> on the C<SERVER> machines and
-any command except those in the C<SHELLS> alias on the C<HUB>
-machines.
+ +secretaries	ALL = PRINTING, /usr/bin/adduser, /usr/bin/rmuser
 
-=item jill
+Users in the B<secretaries> netgroup need to help manage the printers
+as well as add and remove users, so they are allowed to run those
+commands on all machines.
 
-The user C<jill> may run C</sbin/shutdown -h now> or
-C</sbin/shutdown -r now> as well as the commands in the
-C<MISC> alias on houdini.
+ fred		ALL = (DB) NOPASSWD: ALL
 
-=item markm
+The user B<fred> can run commands as any user in the I<DB> C<Runas_Alias>
+(B<oracle> or B<sybase>) without giving a password.
 
-The user C<markm> may run any command on the C<HUB> machines
-except F</sbin/shutdown>, F</sbin/halt>, and commands listed
-in the C<MISC> alias.
+ john		ALPHA = /usr/bin/su [!-]*, !/usr/bin/su *root*
 
-=item davehieb
+On the I<ALPHA> machines, user B<john> may su to anyone except root
+but he is not allowed to give su(1) any flags.
 
-The user C<davehieb> may run any command on C<merlin> as any
-user in the Runas_Alias OP (ie: root or operator).  He may
-also run F</sbin/halt> on the C<SERVERS> and any command
-on C<kodiakthorn> (no password required on C<kodiakthorn>).
+ jen		ALL, !SERVERS = ALL
 
-=item steve
+The user B<jen> may run any command on any machine except for those
+in the I<SERVERS> C<Host_Alias> (master, mail, www and ns).
 
-The user C<steve> may run any command in the F</usr/op_commands/>
-directory as user C<operator> on the machines on C<CSNETS>.
+ jill		SERVERS = /usr/bin/, !SU, !SHELLS
 
-=back
+For any machine in the I<SERVERS> C<Host_Alias>, B<jill> may run
+any commands in the directory /usr/bin/ except for those commands
+belonging to the I<SU> and I<SHELLS> C<Cmnd_Aliases>.
+
+ steve		CSNETS = (operator) /usr/local/op_commands/
+
+The user B<steve> may run any command in the directory /usr/local/op_commands/
+but only as user operator.
+
+ matt		valkyrie = KILL
+
+On his personal workstation, valkyrie, B<matt> needs to be able to
+kill hung processes.
+
+ WEBMASTERS	www = (www) ALL, (root) /usr/bin/su www
+
+On the host www, any user in the I<WEBMASTERS> C<User_Alias> (will,
+wendy, and wim), may run any command as user www (which owns the
+web pages) or simply su(1) to www.
+
+ ALL		CDROM = NOPASSWD: /sbin/umount /CDROM,\
+		/sbin/mount -o nosuid\,nodev /dev/cd0a /CDROM
+
+Any user may mount or unmount a CD-ROM on the machines in the CDROM
+C<Host_Alias> (orion, perseus, hercules) without entering a password.
+This is a bit tedious for users to type, so it is a prime candiate
+for encapsulating in a shell script.
+
+=head1 SECURITY NOTES
+
+It is generally not effective to "subtract" commands from C<ALL>
+using the '!' operator.  A user can trivially circumvent this
+by copying the desired command to a different name and then
+executing that.  For example:
+
+    bill	ALL = ALL, !SU, !SHELLS
+
+Doesn't really prevent B<bill> from running the commands listed in
+I<SU> or I<SHELLS> since he can simply copy those commands to a
+different name, or use a shell escape from an editor or other
+program.  Therefore, these kind of restrictions should be considered
+advisory at best (and reinforced by policy).
 
 =head1 CAVEATS
 
 The I<sudoers> file should B<always> be edited by the B<visudo>
 command which locks the file and does grammatical checking. It is
-imperative that the I<sudoers> be free of syntax errors since sudo
+imperative that I<sudoers> be free of syntax errors since B<sudo>
 will not run with a syntactically incorrect I<sudoers> file.
 
 =head1 FILES
 
- /etc/sudoers		file of authorized users.
- /etc/netgroup		list of network groups.
+ /etc/sudoers		List of who can run what
+ /etc/group		Local groups file
+ /etc/netgroup		List of network groups
 
 =head1 SEE ALSO
 
