Merge tag 'debian/1.8.5p2-1' into squeeze
[debian/sudo] / doc / sudo_plugin.man.in
diff --git a/doc/sudo_plugin.man.in b/doc/sudo_plugin.man.in
new file mode 100644 (file)
index 0000000..ca9589f
--- /dev/null
@@ -0,0 +1,1637 @@
+.\" Copyright (c) 2009-2012 Todd C. Miller <Todd.Miller@courtesan.com>
+.\" 
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\" 
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\" 
+.\" Automatically generated by Pod::Man 2.23 (Pod::Simple 3.14)
+.\"
+.\" Standard preamble:
+.\" ========================================================================
+.de Sp \" Vertical space (when we can't use .PP)
+.if t .sp .5v
+.if n .sp
+..
+.de Vb \" Begin verbatim text
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve \" End verbatim text
+.ft R
+.fi
+..
+.\" Set up some character translations and predefined strings.  \*(-- will
+.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
+.\" double quote, and \*(R" will give a right double quote.  \*(C+ will
+.\" give a nicer C++.  Capital omega is used to do unbreakable dashes and
+.\" therefore won't be available.  \*(C` and \*(C' expand to `' in nroff,
+.\" nothing in troff, for use with C<>.
+.tr \(*W-
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.ie n \{\
+.    ds -- \(*W-
+.    ds PI pi
+.    if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.    if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\"  diablo 12 pitch
+.    ds L" ""
+.    ds R" ""
+.    ds C` 
+.    ds C' 
+'br\}
+.el\{\
+.    ds -- \|\(em\|
+.    ds PI \(*p
+.    ds L" ``
+.    ds R" ''
+'br\}
+.\"
+.\" Escape single quotes in literal strings from groff's Unicode transform.
+.ie \n(.g .ds Aq \(aq
+.el       .ds Aq '
+.\"
+.\" If the F register is turned on, we'll generate index entries on stderr for
+.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
+.\" entries marked with X<> in POD.  Of course, you'll have to process the
+.\" output yourself in some meaningful fashion.
+.ie \nF \{\
+.    de IX
+.    tm Index:\\$1\t\\n%\t"\\$2"
+..
+.    nr % 0
+.    rr F
+.\}
+.el \{\
+.    de IX
+..
+.\}
+.\"
+.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
+.\" Fear.  Run.  Save yourself.  No user-serviceable parts.
+.    \" fudge factors for nroff and troff
+.if n \{\
+.    ds #H 0
+.    ds #V .8m
+.    ds #F .3m
+.    ds #[ \f1
+.    ds #] \fP
+.\}
+.if t \{\
+.    ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+.    ds #V .6m
+.    ds #F 0
+.    ds #[ \&
+.    ds #] \&
+.\}
+.    \" simple accents for nroff and troff
+.if n \{\
+.    ds ' \&
+.    ds ` \&
+.    ds ^ \&
+.    ds , \&
+.    ds ~ ~
+.    ds /
+.\}
+.if t \{\
+.    ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+.    ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+.    ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+.    ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+.    ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+.    ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.\}
+.    \" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.    \" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+.    \" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+.    ds : e
+.    ds 8 ss
+.    ds o a
+.    ds d- d\h'-1'\(ga
+.    ds D- D\h'-1'\(hy
+.    ds th \o'bp'
+.    ds Th \o'LP'
+.    ds ae ae
+.    ds Ae AE
+.\}
+.rm #[ #] #H #V #F C
+.\" ========================================================================
+.\"
+.IX Title "SUDO_PLUGIN @mansectsu@"
+.TH SUDO_PLUGIN @mansectsu@ "April 23, 2012" "1.8.5" "MAINTENANCE COMMANDS"
+.\" For nroff, turn off justification.  Always turn off hyphenation; it makes
+.\" way too many mistakes in technical documents.
+.if n .ad l
+.nh
+.SH "NAME"
+sudo_plugin \- Sudo Plugin API
+.SH "DESCRIPTION"
+.IX Header "DESCRIPTION"
+Starting with version 1.8, \fBsudo\fR supports a plugin \s-1API\s0
+for policy and session logging.  By default, the \fIsudoers\fR policy
+plugin and an associated I/O logging plugin are used.  Via the plugin
+\&\s-1API\s0, \fBsudo\fR can be configured to use alternate policy and/or I/O
+logging plugins provided by third parties.  The plugins to be used
+are specified via the \fI@sysconfdir@/sudo.conf\fR file.
+.PP
+The \s-1API\s0 is versioned with a major and minor number.  The minor
+version number is incremented when additions are made.  The major
+number is incremented when incompatible changes are made.  A plugin
+should be check the version passed to it and make sure that the
+major version matches.
+.PP
+The plugin \s-1API\s0 is defined by the \f(CW\*(C`sudo_plugin.h\*(C'\fR header file.
+.SS "The sudo.conf File"
+.IX Subsection "The sudo.conf File"
+The \fI@sysconfdir@/sudo.conf\fR file contains plugin configuration directives.
+Currently, the only supported keyword is the \f(CW\*(C`Plugin\*(C'\fR directive,
+which causes a plugin plugin to be loaded.
+.PP
+A \f(CW\*(C`Plugin\*(C'\fR line consists of the \f(CW\*(C`Plugin\*(C'\fR keyword, followed by the
+\&\fIsymbol_name\fR and the \fIpath\fR to the shared object containing the
+plugin.  The \fIsymbol_name\fR is the name of the \f(CW\*(C`struct policy_plugin\*(C'\fR
+or \f(CW\*(C`struct io_plugin\*(C'\fR in the plugin shared object.  The \fIpath\fR
+may be fully qualified or relative.  If not fully qualified it is
+relative to the \fI@prefix@/libexec\fR directory.  Any additional
+parameters after the \fIpath\fR are passed as options to the plugin's
+\&\fIopen\fR function.  Lines that don't begin with \f(CW\*(C`Plugin\*(C'\fR, \f(CW\*(C`Path\*(C'\fR,
+\&\f(CW\*(C`Debug\*(C'\fR or \f(CW\*(C`Set\*(C'\fR are silently ignored.
+.PP
+The same shared object may contain multiple plugins, each with a
+different symbol name.  The shared object file must be owned by uid
+0 and only writable by its owner.  Because of ambiguities that arise
+from composite policies, only a single policy plugin may be specified.
+This limitation does not apply to I/O plugins.
+.PP
+.Vb 10
+\& #
+\& # Default @sysconfdir@/sudo.conf file
+\& #
+\& # Format:
+\& #   Plugin plugin_name plugin_path plugin_options ...
+\& #   Path askpass /path/to/askpass
+\& #   Path noexec /path/to/sudo_noexec.so
+\& #   Debug sudo /var/log/sudo_debug all@warn
+\& #   Set disable_coredump true
+\& #
+\& # The plugin_path is relative to @prefix@/libexec unless
+\& #   fully qualified.
+\& # The plugin_name corresponds to a global symbol in the plugin
+\& #   that contains the plugin interface structure.
+\& # The plugin_options are optional.
+\& #
+\& Plugin sudoers_policy sudoers.so
+\& Plugin sudoers_io sudoers.so
+.Ve
+.SS "Policy Plugin \s-1API\s0"
+.IX Subsection "Policy Plugin API"
+A policy plugin must declare and populate a \f(CW\*(C`policy_plugin\*(C'\fR struct
+in the global scope.  This structure contains pointers to the functions
+that implement the \fBsudo\fR policy checks.  The name of the symbol should
+be specified in \fI@sysconfdir@/sudo.conf\fR along with a path to the plugin
+so that \fBsudo\fR can load it.
+.PP
+.Vb 10
+\& struct policy_plugin {
+\& #define SUDO_POLICY_PLUGIN     1
+\&     unsigned int type; /* always SUDO_POLICY_PLUGIN */
+\&     unsigned int version; /* always SUDO_API_VERSION */
+\&     int (*open)(unsigned int version, sudo_conv_t conversation,
+\&                 sudo_printf_t plugin_printf, char * const settings[],
+\&                 char * const user_info[], char * const user_env[],
+\&                 char * const plugin_options[]);
+\&     void (*close)(int exit_status, int error);
+\&     int (*show_version)(int verbose);
+\&     int (*check_policy)(int argc, char * const argv[],
+\&                         char *env_add[], char **command_info[],
+\&                         char **argv_out[], char **user_env_out[]);
+\&     int (*list)(int argc, char * const argv[], int verbose,
+\&                 const char *list_user);
+\&     int (*validate)(void);
+\&     void (*invalidate)(int remove);
+\&     int (*init_session)(struct passwd *pwd, char **user_env[]);
+\&     void (*register_hooks)(int version,
+\&        int (*register_hook)(struct sudo_hook *hook));
+\&     void (*deregister_hooks)(int version,
+\&        int (*deregister_hook)(struct sudo_hook *hook));
+\& };
+.Ve
+.PP
+The policy_plugin struct has the following fields:
+.IP "type" 4
+.IX Item "type"
+The \f(CW\*(C`type\*(C'\fR field should always be set to \s-1SUDO_POLICY_PLUGIN\s0.
+.IP "version" 4
+.IX Item "version"
+The \f(CW\*(C`version\*(C'\fR field should be set to \s-1SUDO_API_VERSION\s0.
+.Sp
+This allows \fBsudo\fR to determine the \s-1API\s0 version the plugin was
+built against.
+.IP "open" 4
+.IX Item "open"
+.Vb 4
+\& int (*open)(unsigned int version, sudo_conv_t conversation,
+\&             sudo_printf_t plugin_printf, char * const settings[],
+\&             char * const user_info[], char * const user_env[],
+\&             char * const plugin_options[]);
+.Ve
+.Sp
+Returns 1 on success, 0 on failure, \-1 if a general error occurred,
+or \-2 if there was a usage error.  In the latter case, \fBsudo\fR will
+print a usage message before it exits.  If an error occurs, the
+plugin may optionally call the conversation or plugin_printf function
+with \f(CW\*(C`SUDO_CONF_ERROR_MSG\*(C'\fR to present additional error information
+to the user.
+.Sp
+The function arguments are as follows:
+.RS 4
+.IP "version" 4
+.IX Item "version"
+The version passed in by \fBsudo\fR allows the plugin to determine the
+major and minor version number of the plugin \s-1API\s0 supported by
+\&\fBsudo\fR.
+.IP "conversation" 4
+.IX Item "conversation"
+A pointer to the conversation function that can be used by the
+plugin to interact with the user (see below).
+Returns 0 on success and \-1 on failure.
+.IP "plugin_printf" 4
+.IX Item "plugin_printf"
+A pointer to a printf-style function that may be used to display
+informational or error messages (see below).
+Returns the number of characters printed on success and \-1 on failure.
+.IP "settings" 4
+.IX Item "settings"
+A vector of user-supplied \fBsudo\fR settings in the form of \*(L"name=value\*(R"
+strings.  The vector is terminated by a \f(CW\*(C`NULL\*(C'\fR pointer.  These
+settings correspond to flags the user specified when running \fBsudo\fR.
+As such, they will only be present when the corresponding flag has
+been specified on the command line.
+.Sp
+When parsing \fIsettings\fR, the plugin should split on the \fBfirst\fR
+equal sign ('=') since the \fIname\fR field will never include one
+itself but the \fIvalue\fR might.
+.RS 4
+.IP "debug_flags=string" 4
+.IX Item "debug_flags=string"
+A comma-separated list of debug flags that correspond to \fBsudo\fR's
+\&\f(CW\*(C`Debug\*(C'\fR entry in \fI@sysconfdir@/sudo.conf\fR, if there is one.  The
+flags are passed to the plugin as they appear in \fI@sysconfdir@/sudo.conf\fR.
+The syntax used by \fBsudo\fR and the \fIsudoers\fR plugin is
+\&\fIsubsystem\fR@\fIpriority\fR but the plugin is free to use a different
+format so long as it does not include a command \f(CW\*(C`,\*(C'\fR.
+.Sp
+For reference, the priorities supported by the \fBsudo\fR front end and
+\&\fIsudoers\fR are: \fIcrit\fR, \fIerr\fR, \fIwarn\fR, \fInotice\fR, \fIdiag\fR,
+\&\fIinfo\fR, \fItrace\fR and \fIdebug\fR.
+.Sp
+The following subsystems are defined: \fImain\fR, \fImemory\fR, \fIargs\fR,
+\&\fIexec\fR, \fIpty\fR, \fIutmp\fR, \fIconv\fR, \fIpcomm\fR, \fIutil\fR, \fIlist\fR,
+\&\fInetif\fR, \fIaudit\fR, \fIedit\fR, \fIselinux\fR, \fIldap\fR, \fImatch\fR, \fIparser\fR,
+\&\fIalias\fR, \fIdefaults\fR, \fIauth\fR, \fIenv\fR, \fIlogging\fR, \fInss\fR, \fIrbtree\fR,
+\&\fIperms\fR, \fIplugin\fR.  The subsystem \fIall\fR includes every subsystem.
+.Sp
+There is not currently a way to specify a set of debug flags specific
+to the plugin\*(--the flags are shared by \fBsudo\fR and the plugin.
+.IP "debug_level=number" 4
+.IX Item "debug_level=number"
+This setting has been deprecated in favor of \fIdebug_flags\fR.
+.IP "runas_user=string" 4
+.IX Item "runas_user=string"
+The user name or uid to to run the command as, if specified via the
+\&\f(CW\*(C`\-u\*(C'\fR flag.
+.IP "runas_group=string" 4
+.IX Item "runas_group=string"
+The group name or gid to to run the command as, if specified via
+the \f(CW\*(C`\-g\*(C'\fR flag.
+.IP "prompt=string" 4
+.IX Item "prompt=string"
+The prompt to use when requesting a password, if specified via
+the \f(CW\*(C`\-p\*(C'\fR flag.
+.IP "set_home=bool" 4
+.IX Item "set_home=bool"
+Set to true if the user specified the \f(CW\*(C`\-H\*(C'\fR flag.  If true, set the
+\&\f(CW\*(C`HOME\*(C'\fR environment variable to the target user's home directory.
+.IP "preserve_environment=bool" 4
+.IX Item "preserve_environment=bool"
+Set to true if the user specified the \f(CW\*(C`\-E\*(C'\fR flag, indicating that
+the user wishes to preserve the environment.
+.IP "run_shell=bool" 4
+.IX Item "run_shell=bool"
+Set to true if the user specified the \f(CW\*(C`\-s\*(C'\fR flag, indicating that
+the user wishes to run a shell.
+.IP "login_shell=bool" 4
+.IX Item "login_shell=bool"
+Set to true if the user specified the \f(CW\*(C`\-i\*(C'\fR flag, indicating that
+the user wishes to run a login shell.
+.IP "implied_shell=bool" 4
+.IX Item "implied_shell=bool"
+If the user does not specify a program on the command line, \fBsudo\fR
+will pass the plugin the path to the user's shell and set
+\&\fIimplied_shell\fR to true.  This allows \fBsudo\fR with no arguments
+to be used similarly to \fIsu\fR\|(1).  If the plugin does not to support
+this usage, it may return a value of \-2 from the \f(CW\*(C`check_policy\*(C'\fR
+function, which will cause \fBsudo\fR to print a usage message and
+exit.
+.IP "preserve_groups=bool" 4
+.IX Item "preserve_groups=bool"
+Set to true if the user specified the \f(CW\*(C`\-P\*(C'\fR flag, indicating that
+the user wishes to preserve the group vector instead of setting it
+based on the runas user.
+.IP "ignore_ticket=bool" 4
+.IX Item "ignore_ticket=bool"
+Set to true if the user specified the \f(CW\*(C`\-k\*(C'\fR flag along with a
+command, indicating that the user wishes to ignore any cached
+authentication credentials.
+.IP "noninteractive=bool" 4
+.IX Item "noninteractive=bool"
+Set to true if the user specified the \f(CW\*(C`\-n\*(C'\fR flag, indicating that
+\&\fBsudo\fR should operate in non-interactive mode.  The plugin may
+reject a command run in non-interactive mode if user interaction
+is required.
+.IP "login_class=string" 4
+.IX Item "login_class=string"
+\&\s-1BSD\s0 login class to use when setting resource limits and nice value,
+if specified by the \f(CW\*(C`\-c\*(C'\fR flag.
+.IP "selinux_role=string" 4
+.IX Item "selinux_role=string"
+SELinux role to use when executing the command, if specified by
+the \f(CW\*(C`\-r\*(C'\fR flag.
+.IP "selinux_type=string" 4
+.IX Item "selinux_type=string"
+SELinux type to use when executing the command, if specified by
+the \f(CW\*(C`\-t\*(C'\fR flag.
+.IP "bsdauth_type=string" 4
+.IX Item "bsdauth_type=string"
+Authentication type, if specified by the \f(CW\*(C`\-a\*(C'\fR flag, to use on
+systems where \s-1BSD\s0 authentication is supported.
+.IP "network_addrs=list" 4
+.IX Item "network_addrs=list"
+A space-separated list of \s-1IP\s0 network addresses and netmasks in the
+form \*(L"addr/netmask\*(R", e.g. \*(L"192.168.1.2/255.255.255.0\*(R".  The address
+and netmask pairs may be either IPv4 or IPv6, depending on what the
+operating system supports.  If the address contains a colon (':'),
+it is an IPv6 address, else it is IPv4.
+.IP "progname=string" 4
+.IX Item "progname=string"
+The command name that sudo was run as, typically \*(L"sudo\*(R" or \*(L"sudoedit\*(R".
+.IP "sudoedit=bool" 4
+.IX Item "sudoedit=bool"
+Set to true when the \f(CW\*(C`\-e\*(C'\fR flag is is specified or if invoked as
+\&\fBsudoedit\fR.  The plugin shall substitute an editor into \fIargv\fR
+in the \fIcheck_policy\fR function or return \f(CW\*(C`\-2\*(C'\fR with a usage error
+if the plugin does not support \fIsudoedit\fR.  For more information,
+see the \fIcheck_policy\fR section.
+.IP "closefrom=number" 4
+.IX Item "closefrom=number"
+If specified, the user has requested via the \f(CW\*(C`\-C\*(C'\fR flag that \fBsudo\fR
+close all files descriptors with a value of \fInumber\fR or higher.
+The plugin may optionally pass this, or another value, back in the
+\&\fIcommand_info\fR list.
+.RE
+.RS 4
+.Sp
+Additional settings may be added in the future so the plugin should
+silently ignore settings that it does not recognize.
+.RE
+.IP "user_info" 4
+.IX Item "user_info"
+A vector of information about the user running the command in the form of
+\&\*(L"name=value\*(R" strings.  The vector is terminated by a \f(CW\*(C`NULL\*(C'\fR pointer.
+.Sp
+When parsing \fIuser_info\fR, the plugin should split on the \fBfirst\fR
+equal sign ('=') since the \fIname\fR field will never include one
+itself but the \fIvalue\fR might.
+.RS 4
+.IP "pid=int" 4
+.IX Item "pid=int"
+The process \s-1ID\s0 of the running \fBsudo\fR process.
+Only available starting with \s-1API\s0 version 1.2
+.IP "ppid=int" 4
+.IX Item "ppid=int"
+The parent process \s-1ID\s0 of the running \fBsudo\fR process.
+Only available starting with \s-1API\s0 version 1.2
+.IP "sid=int" 4
+.IX Item "sid=int"
+The session \s-1ID\s0 of the running \fBsudo\fR process or 0 if \fBsudo\fR is
+not part of a \s-1POSIX\s0 job control session.
+Only available starting with \s-1API\s0 version 1.2
+.IP "pgid=int" 4
+.IX Item "pgid=int"
+The \s-1ID\s0 of the process group that the running \fBsudo\fR process belongs
+to.
+Only available starting with \s-1API\s0 version 1.2
+.IP "tcpgid=int" 4
+.IX Item "tcpgid=int"
+The \s-1ID\s0 of the forground process group associated with the terminal
+device associcated with the \fBsudo\fR process or \-1 if there is no
+terminal present.
+Only available starting with \s-1API\s0 version 1.2
+.IP "user=string" 4
+.IX Item "user=string"
+The name of the user invoking \fBsudo\fR.
+.IP "euid=uid_t" 4
+.IX Item "euid=uid_t"
+The effective user \s-1ID\s0 of the user invoking \fBsudo\fR.
+.IP "uid=uid_t" 4
+.IX Item "uid=uid_t"
+The real user \s-1ID\s0 of the user invoking \fBsudo\fR.
+.IP "egid=gid_t" 4
+.IX Item "egid=gid_t"
+The effective group \s-1ID\s0 of the user invoking \fBsudo\fR.
+.IP "gid=gid_t" 4
+.IX Item "gid=gid_t"
+The real group \s-1ID\s0 of the user invoking \fBsudo\fR.
+.IP "groups=list" 4
+.IX Item "groups=list"
+The user's supplementary group list formatted as a string of
+comma-separated group IDs.
+.IP "cwd=string" 4
+.IX Item "cwd=string"
+The user's current working directory.
+.IP "tty=string" 4
+.IX Item "tty=string"
+The path to the user's terminal device.  If the user has no terminal
+device associated with the session, the value will be empty, as in
+\&\f(CW\*(C`tty=\*(C'\fR.
+.IP "host=string" 4
+.IX Item "host=string"
+The local machine's hostname as returned by the \f(CW\*(C`gethostname()\*(C'\fR
+system call.
+.IP "lines=int" 4
+.IX Item "lines=int"
+The number of lines the user's terminal supports.  If there is
+no terminal device available, a default value of 24 is used.
+.IP "cols=int" 4
+.IX Item "cols=int"
+The number of columns the user's terminal supports.  If there is
+no terminal device available, a default value of 80 is used.
+.RE
+.RS 4
+.RE
+.IP "user_env" 4
+.IX Item "user_env"
+The user's environment in the form of a \f(CW\*(C`NULL\*(C'\fR\-terminated vector of
+\&\*(L"name=value\*(R" strings.
+.Sp
+When parsing \fIuser_env\fR, the plugin should split on the \fBfirst\fR
+equal sign ('=') since the \fIname\fR field will never include one
+itself but the \fIvalue\fR might.
+.IP "plugin_options" 4
+.IX Item "plugin_options"
+Any (non-comment) strings immediately after the plugin path are
+treated as arguments to the plugin.  These arguments are split on
+a white space boundary and are passed to the plugin in the form of
+a \f(CW\*(C`NULL\*(C'\fR\-terminated array of strings.  If no arguments were
+specified, \fIplugin_options\fR will be the \s-1NULL\s0 pointer.
+.Sp
+\&\s-1NOTE:\s0 the \fIplugin_options\fR parameter is only available starting with
+\&\s-1API\s0 version 1.2.  A plugin \fBmust\fR check the \s-1API\s0 version specified
+by the \fBsudo\fR front end before using \fIplugin_options\fR.  Failure to
+do so may result in a crash.
+.RE
+.RS 4
+.RE
+.IP "close" 4
+.IX Item "close"
+.Vb 1
+\& void (*close)(int exit_status, int error);
+.Ve
+.Sp
+The \f(CW\*(C`close\*(C'\fR function is called when the command being run by \fBsudo\fR
+finishes.
+.Sp
+The function arguments are as follows:
+.RS 4
+.IP "exit_status" 4
+.IX Item "exit_status"
+The command's exit status, as returned by the \fIwait\fR\|(2) system call.
+The value of \f(CW\*(C`exit_status\*(C'\fR is undefined if \f(CW\*(C`error\*(C'\fR is non-zero.
+.IP "error" 4
+.IX Item "error"
+If the command could not be executed, this is set to the value of
+\&\f(CW\*(C`errno\*(C'\fR set by the \fIexecve\fR\|(2) system call.  The plugin is responsible
+for displaying error information via the conversation or plugin_printf
+function.  If the command was successfully executed, the value of
+\&\f(CW\*(C`error\*(C'\fR is 0.
+.RE
+.RS 4
+.RE
+.IP "show_version" 4
+.IX Item "show_version"
+.Vb 1
+\& int (*show_version)(int verbose);
+.Ve
+.Sp
+The \f(CW\*(C`show_version\*(C'\fR function is called by \fBsudo\fR when the user specifies
+the \f(CW\*(C`\-V\*(C'\fR option.  The plugin may display its version information
+to the user via the conversation or plugin_printf function using
+\&\f(CW\*(C`SUDO_CONV_INFO_MSG\*(C'\fR.  If the user requests detailed version
+information, the verbose flag will be set.
+.IP "check_policy" 4
+.IX Item "check_policy"
+.Vb 3
+\& int (*check_policy)(int argc, char * const argv[]
+\&                     char *env_add[], char **command_info[],
+\&                     char **argv_out[], char **user_env_out[]);
+.Ve
+.Sp
+The \fIcheck_policy\fR function is called by \fBsudo\fR to determine
+whether the user is allowed to run the specified commands.
+.Sp
+If the \fIsudoedit\fR option was enabled in the \fIsettings\fR array
+passed to the \fIopen\fR function, the user has requested \fIsudoedit\fR
+mode.  \fIsudoedit\fR is a mechanism for editing one or more files
+where an editor is run with the user's credentials instead of with
+elevated privileges.  \fBsudo\fR achieves this by creating user-writable
+temporary copies of the files to be edited and then overwriting the
+originals with the temporary copies after editing is complete.  If
+the plugin supports \fBsudoedit\fR, it should choose the editor to be
+used, potentially from a variable in the user's environment, such
+as \f(CW\*(C`EDITOR\*(C'\fR, and include it in \fIargv_out\fR (note that environment
+variables may include command line flags).  The files to be edited
+should be copied from \fIargv\fR into \fIargv_out\fR, separated from the
+editor and its arguments by a \f(CW"\-\-"\fR element.  The \f(CW"\-\-"\fR will
+be removed by \fBsudo\fR before the editor is executed.  The plugin
+should also set \fIsudoedit=true\fR in the \fIcommand_info\fR list.
+.Sp
+The \fIcheck_policy\fR function returns 1 if the command is allowed,
+0 if not allowed, \-1 for a general error, or \-2 for a usage error
+or if \fBsudoedit\fR was specified but is unsupported by the plugin.
+In the latter case, \fBsudo\fR will print a usage message before it
+exits.  If an error occurs, the plugin may optionally call the
+conversation or plugin_printf function with \f(CW\*(C`SUDO_CONF_ERROR_MSG\*(C'\fR
+to present additional error information to the user.
+.Sp
+The function arguments are as follows:
+.RS 4
+.IP "argc" 4
+.IX Item "argc"
+The number of elements in \fIargv\fR, not counting the final \f(CW\*(C`NULL\*(C'\fR
+pointer.
+.IP "argv" 4
+.IX Item "argv"
+The argument vector describing the command the user wishes to run,
+in the same form as what would be passed to the \fIexecve()\fR system
+call.  The vector is terminated by a \f(CW\*(C`NULL\*(C'\fR pointer.
+.IP "env_add" 4
+.IX Item "env_add"
+Additional environment variables specified by the user on the command
+line in the form of a \f(CW\*(C`NULL\*(C'\fR\-terminated vector of \*(L"name=value\*(R"
+strings.  The plugin may reject the command if one or more variables
+are not allowed to be set, or it may silently ignore such variables.
+.Sp
+When parsing \fIenv_add\fR, the plugin should split on the \fBfirst\fR
+equal sign ('=') since the \fIname\fR field will never include one
+itself but the \fIvalue\fR might.
+.IP "command_info" 4
+.IX Item "command_info"
+Information about the command being run in the form of \*(L"name=value\*(R"
+strings.  These values are used by \fBsudo\fR to set the execution
+environment when running a command.  The plugin is responsible for
+creating and populating the vector, which must be terminated with
+a \f(CW\*(C`NULL\*(C'\fR pointer.  The following values are recognized by \fBsudo\fR:
+.RS 4
+.IP "command=string" 4
+.IX Item "command=string"
+Fully qualified path to the command to be executed.
+.IP "runas_uid=uid" 4
+.IX Item "runas_uid=uid"
+User \s-1ID\s0 to run the command as.
+.IP "runas_euid=uid" 4
+.IX Item "runas_euid=uid"
+Effective user \s-1ID\s0 to run the command as.
+If not specified, the value of \fIrunas_uid\fR is used.
+.IP "runas_gid=gid" 4
+.IX Item "runas_gid=gid"
+Group \s-1ID\s0 to run the command as.
+.IP "runas_egid=gid" 4
+.IX Item "runas_egid=gid"
+Effective group \s-1ID\s0 to run the command as.
+If not specified, the value of \fIrunas_gid\fR is used.
+.IP "runas_groups=list" 4
+.IX Item "runas_groups=list"
+The supplementary group vector to use for the command in the form
+of a comma-separated list of group IDs.  If \fIpreserve_groups\fR
+is set, this option is ignored.
+.IP "login_class=string" 4
+.IX Item "login_class=string"
+\&\s-1BSD\s0 login class to use when setting resource limits and nice value
+(optional).  This option is only set on systems that support login
+classes.
+.IP "preserve_groups=bool" 4
+.IX Item "preserve_groups=bool"
+If set, \fBsudo\fR will preserve the user's group vector instead of
+initializing the group vector based on \f(CW\*(C`runas_user\*(C'\fR.
+.IP "cwd=string" 4
+.IX Item "cwd=string"
+The current working directory to change to when executing the command.
+.IP "noexec=bool" 4
+.IX Item "noexec=bool"
+If set, prevent the command from executing other programs.
+.IP "chroot=string" 4
+.IX Item "chroot=string"
+The root directory to use when running the command.
+.IP "nice=int" 4
+.IX Item "nice=int"
+Nice value (priority) to use when executing the command.  The nice
+value, if specified, overrides the priority associated with the
+\&\fIlogin_class\fR on \s-1BSD\s0 systems.
+.IP "umask=octal" 4
+.IX Item "umask=octal"
+The file creation mask to use when executing the command.
+.IP "selinux_role=string" 4
+.IX Item "selinux_role=string"
+SELinux role to use when executing the command.
+.IP "selinux_type=string" 4
+.IX Item "selinux_type=string"
+SELinux type to use when executing the command.
+.IP "timeout=int" 4
+.IX Item "timeout=int"
+Command timeout.  If non-zero then when the timeout expires the
+command will be killed.
+.IP "sudoedit=bool" 4
+.IX Item "sudoedit=bool"
+Set to true when in \fIsudoedit\fR mode.  The plugin may enable
+\&\fIsudoedit\fR mode even if \fBsudo\fR was not invoked as \fBsudoedit\fR.
+This allows the plugin to perform command substitution and transparently
+enable \fIsudoedit\fR when the user attempts to run an editor.
+.IP "closefrom=number" 4
+.IX Item "closefrom=number"
+If specified, \fBsudo\fR will close all files descriptors with a value
+of \fInumber\fR or higher.
+.IP "iolog_compress=bool" 4
+.IX Item "iolog_compress=bool"
+Set to true if the I/O logging plugins, if any, should compress the
+log data.  This is a hint to the I/O logging plugin which may choose
+to ignore it.
+.IP "iolog_path=string" 4
+.IX Item "iolog_path=string"
+Fully qualified path to the file or directory in which I/O log is
+to be stored.  This is a hint to the I/O logging plugin which may
+choose to ignore it.  If no I/O logging plugin is loaded, this
+setting has no effect.
+.IP "iolog_stdin=bool" 4
+.IX Item "iolog_stdin=bool"
+Set to true if the I/O logging plugins, if any, should log the
+standard input if it is not connected to a terminal device.  This
+is a hint to the I/O logging plugin which may choose to ignore it.
+.IP "iolog_stdout=bool" 4
+.IX Item "iolog_stdout=bool"
+Set to true if the I/O logging plugins, if any, should log the
+standard output if it is not connected to a terminal device.  This
+is a hint to the I/O logging plugin which may choose to ignore it.
+.IP "iolog_stderr=bool" 4
+.IX Item "iolog_stderr=bool"
+Set to true if the I/O logging plugins, if any, should log the
+standard error if it is not connected to a terminal device.  This
+is a hint to the I/O logging plugin which may choose to ignore it.
+.IP "iolog_ttyin=bool" 4
+.IX Item "iolog_ttyin=bool"
+Set to true if the I/O logging plugins, if any, should log all
+terminal input.  This only includes input typed by the user and not
+from a pipe or redirected from a file.  This is a hint to the I/O
+logging plugin which may choose to ignore it.
+.IP "iolog_ttyout=bool" 4
+.IX Item "iolog_ttyout=bool"
+Set to true if the I/O logging plugins, if any, should log all
+terminal output.  This only includes output to the screen, not
+output to a pipe or file.  This is a hint to the I/O logging plugin
+which may choose to ignore it.
+.IP "use_pty=bool" 4
+.IX Item "use_pty=bool"
+Allocate a pseudo-tty to run the command in, regardless of whether
+or not I/O logging is in use.  By default, \fBsudo\fR will only run
+the command in a pty when an I/O log plugin is loaded.
+.IP "set_utmp=bool" 4
+.IX Item "set_utmp=bool"
+Create a utmp (or utmpx) entry when a pseudo-tty is allocated.  By
+default, the new entry will be a copy of the user's existing utmp
+entry (if any), with the tty, time, type and pid fields updated.
+.IP "utmp_user=string" 4
+.IX Item "utmp_user=string"
+User name to use when constructing a new utmp (or utmpx) entry when
+\&\fIset_utmp\fR is enabled.  This option can be used to set the user
+field in the utmp entry to the user the command runs as rather than
+the invoking user.  If not set, \fBsudo\fR will base the new entry on
+the invoking user's existing entry.
+.RE
+.RS 4
+.Sp
+Unsupported values will be ignored.
+.RE
+.IP "argv_out" 4
+.IX Item "argv_out"
+The \f(CW\*(C`NULL\*(C'\fR\-terminated argument vector to pass to the \fIexecve()\fR
+system call when executing the command.  The plugin is responsible
+for allocating and populating the vector.
+.IP "user_env_out" 4
+.IX Item "user_env_out"
+The \f(CW\*(C`NULL\*(C'\fR\-terminated environment vector to use when executing the
+command.  The plugin is responsible for allocating and populating
+the vector.
+.RE
+.RS 4
+.RE
+.IP "list" 4
+.IX Item "list"
+.Vb 2
+\& int (*list)(int verbose, const char *list_user,
+\&             int argc, char * const argv[]);
+.Ve
+.Sp
+List available privileges for the invoking user.  Returns 1 on
+success, 0 on failure and \-1 on error.  On error, the plugin may
+optionally call the conversation or plugin_printf function with
+\&\f(CW\*(C`SUDO_CONF_ERROR_MSG\*(C'\fR to present additional error information to
+the user.
+.Sp
+Privileges should be output via the conversation or plugin_printf
+function using \f(CW\*(C`SUDO_CONV_INFO_MSG\*(C'\fR.
+.RS 4
+.IP "verbose" 4
+.IX Item "verbose"
+Flag indicating whether to list in verbose mode or not.
+.IP "list_user" 4
+.IX Item "list_user"
+The name of a different user to list privileges for if the policy
+allows it.  If \f(CW\*(C`NULL\*(C'\fR, the plugin should list the privileges of
+the invoking user.
+.IP "argc" 4
+.IX Item "argc"
+The number of elements in \fIargv\fR, not counting the final \f(CW\*(C`NULL\*(C'\fR
+pointer.
+.IP "argv" 4
+.IX Item "argv"
+If non\-\f(CW\*(C`NULL\*(C'\fR, an argument vector describing a command the user
+wishes to check against the policy in the same form as what would
+be passed to the \fIexecve()\fR system call.  If the command is permitted
+by the policy, the fully-qualified path to the command should be
+displayed along with any command line arguments.
+.RE
+.RS 4
+.RE
+.IP "validate" 4
+.IX Item "validate"
+.Vb 1
+\& int (*validate)(void);
+.Ve
+.Sp
+The \f(CW\*(C`validate\*(C'\fR function is called when \fBsudo\fR is run with the
+\&\f(CW\*(C`\-v\*(C'\fR flag.  For policy plugins such as \fIsudoers\fR that cache
+authentication credentials, this function will validate and cache
+the credentials.
+.Sp
+The \f(CW\*(C`validate\*(C'\fR function should be \f(CW\*(C`NULL\*(C'\fR if the plugin does not
+support credential caching.
+.Sp
+Returns 1 on success, 0 on failure and \-1 on error.
+On error, the plugin may optionally call the conversation or plugin_printf
+function with \f(CW\*(C`SUDO_CONF_ERROR_MSG\*(C'\fR to present additional
+error information to the user.
+.IP "invalidate" 4
+.IX Item "invalidate"
+.Vb 1
+\& void (*invalidate)(int remove);
+.Ve
+.Sp
+The \f(CW\*(C`invalidate\*(C'\fR function is called when \fBsudo\fR is called with
+the \f(CW\*(C`\-k\*(C'\fR or \f(CW\*(C`\-K\*(C'\fR flag.  For policy plugins such as \fIsudoers\fR that
+cache authentication credentials, this function will invalidate the
+credentials.  If the \fIremove\fR flag is set, the plugin may remove
+the credentials instead of simply invalidating them.
+.Sp
+The \f(CW\*(C`invalidate\*(C'\fR function should be \f(CW\*(C`NULL\*(C'\fR if the plugin does not
+support credential caching.
+.IP "init_session" 4
+.IX Item "init_session"
+.Vb 1
+\& int (*init_session)(struct passwd *pwd, char **user_envp[);
+.Ve
+.Sp
+The \f(CW\*(C`init_session\*(C'\fR function is called before \fBsudo\fR sets up the
+execution environment for the command.  It is run in the parent
+\&\fBsudo\fR process and before any uid or gid changes.  This can be used
+to perform session setup that is not supported by \fIcommand_info\fR,
+such as opening the \s-1PAM\s0 session.  The \f(CW\*(C`close\*(C'\fR function can be
+used to tear down the session that was opened by \f(CW\*(C`init_session\*(C'\fR.
+.Sp
+The \fIpwd\fR argument points to a passwd struct for the user the
+command will be run as if the uid the command will run as was found
+in the password database, otherwise it will be \s-1NULL\s0.
+.Sp
+The \fIuser_env\fR argument points to the environment the command will
+run in, in the form of a \f(CW\*(C`NULL\*(C'\fR\-terminated vector of \*(L"name=value\*(R"
+strings.  This is the same string passed back to the front end via
+the Policy Plugin's \fIuser_env_out\fR parameter.  If the \f(CW\*(C`init_session\*(C'\fR
+function needs to modify the user environment, it should update the
+pointer stored in \fIuser_env\fR.  The expected use case is to merge
+the contents of the \s-1PAM\s0 environment (if any) with the contents of
+\&\fIuser_env\fR.  \s-1NOTE:\s0 the \fIuser_env\fR parameter is only available
+starting with \s-1API\s0 version 1.2.  A plugin \fBmust\fR check the \s-1API\s0
+version specified by the \fBsudo\fR front end before using \fIuser_env\fR.
+Failure to do so may result in a crash.
+.Sp
+Returns 1 on success, 0 on failure and \-1 on error.
+On error, the plugin may optionally call the conversation or plugin_printf
+function with \f(CW\*(C`SUDO_CONF_ERROR_MSG\*(C'\fR to present additional
+error information to the user.
+.IP "register_hooks" 4
+.IX Item "register_hooks"
+.Vb 2
+\& void (*register_hooks)(int version,
+\&    int (*register_hook)(struct sudo_hook *hook));
+.Ve
+.Sp
+The \f(CW\*(C`register_hooks\*(C'\fR function is called by the sudo front end to
+register any hooks the plugin needs.  If the plugin does not support
+hooks, \f(CW\*(C`register_hooks\*(C'\fR should be set to the \s-1NULL\s0 pointer.
+.Sp
+The \fIversion\fR argument describes the version of the hooks \s-1API\s0
+supported by the \fBsudo\fR front end.
+.Sp
+The \f(CW\*(C`register_hook\*(C'\fR function should be used to register any supported
+hooks the plugin needs.  It returns 0 on success, 1 if the hook
+type is not supported and \-1 if the major version in \f(CW\*(C`struct hook\*(C'\fR
+does not match the front end's major hook \s-1API\s0 version.
+.Sp
+See the \*(L"Hook Function \s-1API\s0\*(R" section below for more information
+about hooks.
+.Sp
+\&\s-1NOTE:\s0 the \f(CW\*(C`register_hooks\*(C'\fR function is only available starting
+with \s-1API\s0 version 1.2.  If the \fBsudo\fR front end doesn't support \s-1API\s0
+version 1.2 or higher, \f(CW\*(C`register_hooks\*(C'\fR will not be called.
+.IP "deregister_hooks" 4
+.IX Item "deregister_hooks"
+.Vb 2
+\& void (*deregister_hooks)(int version,
+\&    int (*deregister_hook)(struct sudo_hook *hook));
+.Ve
+.Sp
+The \f(CW\*(C`deregister_hooks\*(C'\fR function is called by the sudo front end
+to deregister any hooks the plugin has registered.  If the plugin
+does not support hooks, \f(CW\*(C`deregister_hooks\*(C'\fR should be set to the
+\&\s-1NULL\s0 pointer.
+.Sp
+The \fIversion\fR argument describes the version of the hooks \s-1API\s0
+supported by the \fBsudo\fR front end.
+.Sp
+The \f(CW\*(C`deregister_hook\*(C'\fR function should be used to deregister any
+hooks that were put in place by the \f(CW\*(C`register_hook\*(C'\fR function.  If
+the plugin tries to deregister a hook that the front end does not
+support, \f(CW\*(C`deregister_hook\*(C'\fR will return an error.
+.Sp
+See the \*(L"Hook Function \s-1API\s0\*(R" section below for more information
+about hooks.
+.Sp
+\&\s-1NOTE:\s0 the \f(CW\*(C`deregister_hooks\*(C'\fR function is only available starting
+with \s-1API\s0 version 1.2.  If the \fBsudo\fR front end doesn't support \s-1API\s0
+version 1.2 or higher, \f(CW\*(C`deregister_hooks\*(C'\fR will not be called.
+.PP
+\fIPolicy Plugin Version Macros\fR
+.IX Subsection "Policy Plugin Version Macros"
+.PP
+.Vb 6
+\& /* Plugin API version major/minor. */
+\& #define SUDO_API_VERSION_MAJOR 1
+\& #define SUDO_API_VERSION_MINOR 2
+\& #define SUDO_API_MKVERSION(x, y) ((x << 16) | y)
+\& #define SUDO_API_VERSION SUDO_API_MKVERSION(SUDO_API_VERSION_MAJOR,\e
+\&                                             SUDO_API_VERSION_MINOR)
+\&
+\& /* Getters and setters for API version */
+\& #define SUDO_API_VERSION_GET_MAJOR(v) ((v) >> 16)
+\& #define SUDO_API_VERSION_GET_MINOR(v) ((v) & 0xffff)
+\& #define SUDO_API_VERSION_SET_MAJOR(vp, n) do { \e
+\&     *(vp) = (*(vp) & 0x0000ffff) | ((n) << 16); \e
+\& } while(0)
+\& #define SUDO_VERSION_SET_MINOR(vp, n) do { \e
+\&     *(vp) = (*(vp) & 0xffff0000) | (n); \e
+\& } while(0)
+.Ve
+.SS "I/O Plugin \s-1API\s0"
+.IX Subsection "I/O Plugin API"
+.Vb 10
+\& struct io_plugin {
+\& #define SUDO_IO_PLUGIN         2
+\&     unsigned int type; /* always SUDO_IO_PLUGIN */
+\&     unsigned int version; /* always SUDO_API_VERSION */
+\&     int (*open)(unsigned int version, sudo_conv_t conversation
+\&                 sudo_printf_t plugin_printf, char * const settings[],
+\&                 char * const user_info[], int argc, char * const argv[],
+\&                 char * const user_env[], char * const plugin_options[]);
+\&     void (*close)(int exit_status, int error); /* wait status or error */
+\&     int (*show_version)(int verbose);
+\&     int (*log_ttyin)(const char *buf, unsigned int len);
+\&     int (*log_ttyout)(const char *buf, unsigned int len);
+\&     int (*log_stdin)(const char *buf, unsigned int len);
+\&     int (*log_stdout)(const char *buf, unsigned int len);
+\&     int (*log_stderr)(const char *buf, unsigned int len);
+\&     void (*register_hooks)(int version,
+\&        int (*register_hook)(struct sudo_hook *hook));
+\&     void (*deregister_hooks)(int version,
+\&        int (*deregister_hook)(struct sudo_hook *hook));
+\& };
+.Ve
+.PP
+When an I/O plugin is loaded, \fBsudo\fR runs the command in a pseudo-tty.
+This makes it possible to log the input and output from the user's
+session.  If any of the standard input, standard output or standard
+error do not correspond to a tty, \fBsudo\fR will open a pipe to capture
+the I/O for logging before passing it on.
+.PP
+The log_ttyin function receives the raw user input from the terminal
+device (note that this will include input even when echo is disabled,
+such as when a password is read). The log_ttyout function receives
+output from the pseudo-tty that is suitable for replaying the user's
+session at a later time.  The log_stdin, log_stdout and log_stderr
+functions are only called if the standard input, standard output
+or standard error respectively correspond to something other than
+a tty.
+.PP
+Any of the logging functions may be set to the \s-1NULL\s0
+pointer if no logging is to be performed.  If the open function
+returns \f(CW0\fR, no I/O will be sent to the plugin.
+.PP
+The io_plugin struct has the following fields:
+.IP "type" 4
+.IX Item "type"
+The \f(CW\*(C`type\*(C'\fR field should always be set to \s-1SUDO_IO_PLUGIN\s0
+.IP "version" 4
+.IX Item "version"
+The \f(CW\*(C`version\*(C'\fR field should be set to \s-1SUDO_API_VERSION\s0.
+.Sp
+This allows \fBsudo\fR to determine the \s-1API\s0 version the plugin was
+built against.
+.IP "open" 4
+.IX Item "open"
+.Vb 4
+\& int (*open)(unsigned int version, sudo_conv_t conversation
+\&             sudo_printf_t plugin_printf, char * const settings[],
+\&             char * const user_info[], int argc, char * const argv[],
+\&             char * const user_env[], char * const plugin_options[]);
+.Ve
+.Sp
+The \fIopen\fR function is run before the \fIlog_input\fR, \fIlog_output\fR
+or \fIshow_version\fR functions are called.  It is only called if the
+version is being requested or the \fIcheck_policy\fR function has
+returned successfully.  It returns 1 on success, 0 on failure, \-1
+if a general error occurred, or \-2 if there was a usage error.  In
+the latter case, \fBsudo\fR will print a usage message before it exits.
+If an error occurs, the plugin may optionally call the conversation
+or plugin_printf function with \f(CW\*(C`SUDO_CONF_ERROR_MSG\*(C'\fR to present
+additional error information to the user.
+.Sp
+The function arguments are as follows:
+.RS 4
+.IP "version" 4
+.IX Item "version"
+The version passed in by \fBsudo\fR allows the plugin to determine the
+major and minor version number of the plugin \s-1API\s0 supported by
+\&\fBsudo\fR.
+.IP "conversation" 4
+.IX Item "conversation"
+A pointer to the conversation function that may be used by the
+\&\fIshow_version\fR function to display version information (see
+show_version below).  The conversation function may also be used
+to display additional error message to the user.
+The conversation function returns 0 on success and \-1 on failure.
+.IP "plugin_printf" 4
+.IX Item "plugin_printf"
+A pointer to a printf-style function that may be used by the
+\&\fIshow_version\fR function to display version information (see
+show_version below).  The plugin_printf function may also be used
+to display additional error message to the user.
+The plugin_printf function returns number of characters printed on
+success and \-1 on failure.
+.IP "settings" 4
+.IX Item "settings"
+A vector of user-supplied \fBsudo\fR settings in the form of \*(L"name=value\*(R"
+strings.  The vector is terminated by a \f(CW\*(C`NULL\*(C'\fR pointer.  These
+settings correspond to flags the user specified when running \fBsudo\fR.
+As such, they will only be present when the corresponding flag has
+been specified on the command line.
+.Sp
+When parsing \fIsettings\fR, the plugin should split on the \fBfirst\fR
+equal sign ('=') since the \fIname\fR field will never include one
+itself but the \fIvalue\fR might.
+.Sp
+See the \*(L"Policy Plugin \s-1API\s0\*(R" section for a list of all possible settings.
+.IP "user_info" 4
+.IX Item "user_info"
+A vector of information about the user running the command in the form of
+\&\*(L"name=value\*(R" strings.  The vector is terminated by a \f(CW\*(C`NULL\*(C'\fR pointer.
+.Sp
+When parsing \fIuser_info\fR, the plugin should split on the \fBfirst\fR
+equal sign ('=') since the \fIname\fR field will never include one
+itself but the \fIvalue\fR might.
+.Sp
+See the \*(L"Policy Plugin \s-1API\s0\*(R" section for a list of all possible strings.
+.IP "argc" 4
+.IX Item "argc"
+The number of elements in \fIargv\fR, not counting the final \f(CW\*(C`NULL\*(C'\fR
+pointer.
+.IP "argv" 4
+.IX Item "argv"
+If non\-\f(CW\*(C`NULL\*(C'\fR, an argument vector describing a command the user
+wishes to run in the same form as what would be passed to the
+\&\fIexecve()\fR system call.
+.IP "user_env" 4
+.IX Item "user_env"
+The user's environment in the form of a \f(CW\*(C`NULL\*(C'\fR\-terminated vector of
+\&\*(L"name=value\*(R" strings.
+.Sp
+When parsing \fIuser_env\fR, the plugin should split on the \fBfirst\fR
+equal sign ('=') since the \fIname\fR field will never include one
+itself but the \fIvalue\fR might.
+.IP "plugin_options" 4
+.IX Item "plugin_options"
+Any (non-comment) strings immediately after the plugin path are
+treated as arguments to the plugin.  These arguments are split on
+a white space boundary and are passed to the plugin in the form of
+a \f(CW\*(C`NULL\*(C'\fR\-terminated array of strings.  If no arguments were
+specified, \fIplugin_options\fR will be the \s-1NULL\s0 pointer.
+.Sp
+\&\s-1NOTE:\s0 the \fIplugin_options\fR parameter is only available starting with
+\&\s-1API\s0 version 1.2.  A plugin \fBmust\fR check the \s-1API\s0 version specified
+by the \fBsudo\fR front end before using \fIplugin_options\fR.  Failure to
+do so may result in a crash.
+.RE
+.RS 4
+.RE
+.IP "close" 4
+.IX Item "close"
+.Vb 1
+\& void (*close)(int exit_status, int error);
+.Ve
+.Sp
+The \f(CW\*(C`close\*(C'\fR function is called when the command being run by \fBsudo\fR
+finishes.
+.Sp
+The function arguments are as follows:
+.RS 4
+.IP "exit_status" 4
+.IX Item "exit_status"
+The command's exit status, as returned by the \fIwait\fR\|(2) system call.
+The value of \f(CW\*(C`exit_status\*(C'\fR is undefined if \f(CW\*(C`error\*(C'\fR is non-zero.
+.IP "error" 4
+.IX Item "error"
+If the command could not be executed, this is set to the value of
+\&\f(CW\*(C`errno\*(C'\fR set by the \fIexecve\fR\|(2) system call.  If the command was
+successfully executed, the value of \f(CW\*(C`error\*(C'\fR is 0.
+.RE
+.RS 4
+.RE
+.IP "show_version" 4
+.IX Item "show_version"
+.Vb 1
+\& int (*show_version)(int verbose);
+.Ve
+.Sp
+The \f(CW\*(C`show_version\*(C'\fR function is called by \fBsudo\fR when the user specifies
+the \f(CW\*(C`\-V\*(C'\fR option.  The plugin may display its version information
+to the user via the conversation or plugin_printf function using
+\&\f(CW\*(C`SUDO_CONV_INFO_MSG\*(C'\fR.  If the user requests detailed version
+information, the verbose flag will be set.
+.IP "log_ttyin" 4
+.IX Item "log_ttyin"
+.Vb 1
+\& int (*log_ttyin)(const char *buf, unsigned int len);
+.Ve
+.Sp
+The \fIlog_ttyin\fR function is called whenever data can be read from
+the user but before it is passed to the running command.  This
+allows the plugin to reject data if it chooses to (for instance
+if the input contains banned content).  Returns \f(CW1\fR if the data
+should be passed to the command, \f(CW0\fR if the data is rejected
+(which will terminate the command) or \f(CW\*(C`\-1\*(C'\fR if an error occurred.
+.Sp
+The function arguments are as follows:
+.RS 4
+.IP "buf" 4
+.IX Item "buf"
+The buffer containing user input.
+.IP "len" 4
+.IX Item "len"
+The length of \fIbuf\fR in bytes.
+.RE
+.RS 4
+.RE
+.IP "log_ttyout" 4
+.IX Item "log_ttyout"
+.Vb 1
+\& int (*log_ttyout)(const char *buf, unsigned int len);
+.Ve
+.Sp
+The \fIlog_ttyout\fR function is called whenever data can be read from
+the command but before it is written to the user's terminal.  This
+allows the plugin to reject data if it chooses to (for instance
+if the output contains banned content).  Returns \f(CW1\fR if the data
+should be passed to the user, \f(CW0\fR if the data is rejected
+(which will terminate the command) or \f(CW\*(C`\-1\*(C'\fR if an error occurred.
+.Sp
+The function arguments are as follows:
+.RS 4
+.IP "buf" 4
+.IX Item "buf"
+The buffer containing command output.
+.IP "len" 4
+.IX Item "len"
+The length of \fIbuf\fR in bytes.
+.RE
+.RS 4
+.RE
+.IP "log_stdin" 4
+.IX Item "log_stdin"
+.Vb 1
+\& int (*log_stdin)(const char *buf, unsigned int len);
+.Ve
+.Sp
+The \fIlog_stdin\fR function is only used if the standard input does
+not correspond to a tty device.  It is called whenever data can be
+read from the standard input but before it is passed to the running
+command.  This allows the plugin to reject data if it chooses to
+(for instance if the input contains banned content).  Returns \f(CW1\fR
+if the data should be passed to the command, \f(CW0\fR if the data is
+rejected (which will terminate the command) or \f(CW\*(C`\-1\*(C'\fR if an error
+occurred.
+.Sp
+The function arguments are as follows:
+.RS 4
+.IP "buf" 4
+.IX Item "buf"
+The buffer containing user input.
+.IP "len" 4
+.IX Item "len"
+The length of \fIbuf\fR in bytes.
+.RE
+.RS 4
+.RE
+.IP "log_stdout" 4
+.IX Item "log_stdout"
+.Vb 1
+\& int (*log_stdout)(const char *buf, unsigned int len);
+.Ve
+.Sp
+The \fIlog_stdout\fR function is only used if the standard output does
+not correspond to a tty device.  It is called whenever data can be
+read from the command but before it is written to the standard
+output.  This allows the plugin to reject data if it chooses to
+(for instance if the output contains banned content).  Returns \f(CW1\fR
+if the data should be passed to the user, \f(CW0\fR if the data is
+rejected (which will terminate the command) or \f(CW\*(C`\-1\*(C'\fR if an error
+occurred.
+.Sp
+The function arguments are as follows:
+.RS 4
+.IP "buf" 4
+.IX Item "buf"
+The buffer containing command output.
+.IP "len" 4
+.IX Item "len"
+The length of \fIbuf\fR in bytes.
+.RE
+.RS 4
+.RE
+.IP "log_stderr" 4
+.IX Item "log_stderr"
+.Vb 1
+\& int (*log_stderr)(const char *buf, unsigned int len);
+.Ve
+.Sp
+The \fIlog_stderr\fR function is only used if the standard error does
+not correspond to a tty device.  It is called whenever data can be
+read from the command but before it is written to the standard
+error.  This allows the plugin to reject data if it chooses to
+(for instance if the output contains banned content).  Returns \f(CW1\fR
+if the data should be passed to the user, \f(CW0\fR if the data is
+rejected (which will terminate the command) or \f(CW\*(C`\-1\*(C'\fR if an error
+occurred.
+.Sp
+The function arguments are as follows:
+.RS 4
+.IP "buf" 4
+.IX Item "buf"
+The buffer containing command output.
+.IP "len" 4
+.IX Item "len"
+The length of \fIbuf\fR in bytes.
+.RE
+.RS 4
+.RE
+.IP "register_hooks" 4
+.IX Item "register_hooks"
+See the \*(L"Policy Plugin \s-1API\s0\*(R" section for a description of
+\&\f(CW\*(C`register_hooks\*(C'\fR.
+.IP "deregister_hooks" 4
+.IX Item "deregister_hooks"
+See the \*(L"Policy Plugin \s-1API\s0\*(R" section for a description of
+\&\f(CW\*(C`deregister_hooks\*(C'\fR.
+.PP
+\fII/O Plugin Version Macros\fR
+.IX Subsection "I/O Plugin Version Macros"
+.PP
+Same as for the \*(L"Policy Plugin \s-1API\s0\*(R".
+.SS "Hook Function \s-1API\s0"
+.IX Subsection "Hook Function API"
+Beginning with plugin \s-1API\s0 version 1.2, it is possible to install
+hooks for certain functions called by the \fBsudo\fR front end.
+.PP
+Currently, the only supported hooks relate to the handling of
+environment variables.  Hooks can be used to intercept attempts to
+get, set, or remove environment variables so that these changes can
+be reflected in the version of the environment that is used to
+execute a command.  A future version of the \s-1API\s0 will support
+hooking internal \fBsudo\fR front end functions as well.
+.PP
+\fIHook structure\fR
+.IX Subsection "Hook structure"
+.PP
+Hooks in \fBsudo\fR are described by the following structure:
+.PP
+.Vb 1
+\& typedef int (*sudo_hook_fn_t)();
+\&
+\& struct sudo_hook {
+\&     int hook_version;
+\&     int hook_type;
+\&     sudo_hook_fn_t hook_fn;
+\&     void *closure;
+\& };
+.Ve
+.PP
+The \f(CW\*(C`sudo_hook\*(C'\fR structure has the following fields:
+.IP "hook_version" 4
+.IX Item "hook_version"
+The \f(CW\*(C`hook_version\*(C'\fR field should be set to \s-1SUDO_HOOK_VERSION\s0.
+.IP "hook_type" 4
+.IX Item "hook_type"
+The \f(CW\*(C`hook_type\*(C'\fR field may be one of the following supported hook types:
+.RS 4
+.IP "\s-1SUDO_HOOK_SETENV\s0" 4
+.IX Item "SUDO_HOOK_SETENV"
+The C library \f(CW\*(C`setenv()\*(C'\fR function.  Any registered hooks will run
+before the C library implementation.  The \f(CW\*(C`hook_fn\*(C'\fR field should
+be a function that matches the following typedef:
+.Sp
+.Vb 2
+\& typedef int (*sudo_hook_fn_setenv_t)(const char *name,
+\&    const char *value, int overwrite, void *closure);
+.Ve
+.Sp
+If the registered hook does not match the typedef the results are
+unspecified.
+.IP "\s-1SUDO_HOOK_UNSETENV\s0" 4
+.IX Item "SUDO_HOOK_UNSETENV"
+The C library \f(CW\*(C`unsetenv()\*(C'\fR function.  Any registered hooks will run
+before the C library implementation.  The \f(CW\*(C`hook_fn\*(C'\fR field should
+be a function that matches the following typedef:
+.Sp
+.Vb 2
+\& typedef int (*sudo_hook_fn_unsetenv_t)(const char *name,
+\&    void *closure);
+.Ve
+.IP "\s-1SUDO_HOOK_GETENV\s0" 4
+.IX Item "SUDO_HOOK_GETENV"
+The C library \f(CW\*(C`getenv()\*(C'\fR function.  Any registered hooks will run
+before the C library implementation.  The \f(CW\*(C`hook_fn\*(C'\fR field should
+be a function that matches the following typedef:
+.Sp
+.Vb 2
+\& typedef int (*sudo_hook_fn_getenv_t)(const char *name,
+\&    char **value, void *closure);
+.Ve
+.Sp
+If the registered hook does not match the typedef the results are
+unspecified.
+.IP "\s-1SUDO_HOOK_PUTENV\s0" 4
+.IX Item "SUDO_HOOK_PUTENV"
+The C library \f(CW\*(C`putenv()\*(C'\fR function.  Any registered hooks will run
+before the C library implementation.  The \f(CW\*(C`hook_fn\*(C'\fR field should
+be a function that matches the following typedef:
+.Sp
+.Vb 2
+\& typedef int (*sudo_hook_fn_putenv_t)(char *string,
+\&    void *closure);
+.Ve
+.Sp
+If the registered hook does not match the typedef the results are
+unspecified.
+.RE
+.RS 4
+.RE
+.IP "hook_fn" 4
+.IX Item "hook_fn"
+.Vb 1
+\& sudo_hook_fn_t hook_fn;
+.Ve
+.Sp
+The \f(CW\*(C`hook_fn\*(C'\fR field should be set to the plugin's hook implementation.
+The actual function arguments will vary depending on the \f(CW\*(C`hook_type\*(C'\fR
+(see \f(CW\*(C`hook_type\*(C'\fR above).  In all cases, the \f(CW\*(C`closure\*(C'\fR field of
+\&\f(CW\*(C`struct sudo_hook\*(C'\fR is passed as the last function parameter.  This
+can be used to pass arbitrary data to the plugin's hook implementation.
+.Sp
+The function return value may be one of the following:
+.RS 4
+.IP "\s-1SUDO_HOOK_RET_ERROR\s0" 4
+.IX Item "SUDO_HOOK_RET_ERROR"
+The hook function encountered an error.
+.IP "\s-1SUDO_HOOK_RET_NEXT\s0" 4
+.IX Item "SUDO_HOOK_RET_NEXT"
+The hook completed without error, go on to the next hook (including
+the native implementation if applicable).  For example, a \f(CW\*(C`getenv\*(C'\fR
+hook might return \f(CW\*(C`SUDO_HOOK_RET_NEXT\*(C'\fR if the specified variable
+was not found in the private copy of the environment.
+.IP "\s-1SUDO_HOOK_RET_STOP\s0" 4
+.IX Item "SUDO_HOOK_RET_STOP"
+The hook completed without error, stop processing hooks for this
+invocation.  This can be used to replace the native implementation.
+For example, a \f(CW\*(C`setenv\*(C'\fR hook that operates on a private copy of
+the environment but leaves \f(CW\*(C`environ\*(C'\fR unchanged.
+.RE
+.RS 4
+.RE
+.PP
+Note that it is very easy to create an infinite loop when hooking
+C library functions.  For example, a \f(CW\*(C`getenv\*(C'\fR hook that calls the
+\&\f(CW\*(C`snprintf\*(C'\fR function may create a loop if the \f(CW\*(C`snprintf\*(C'\fR implementation
+calls \f(CW\*(C`getenv\*(C'\fR to check the locale.  To prevent this, you may wish
+to use a static variable in the hook function to guard against
+nested calls.  E.g.
+.PP
+.Vb 7
+\& static int in_progress = 0; /* avoid recursion */
+\& if (in_progress)
+\&     return SUDO_HOOK_RET_NEXT;
+\& in_progress = 1;
+\& ...
+\& in_progress = 0;
+\& return SUDO_HOOK_RET_STOP;
+.Ve
+.PP
+\fIHook \s-1API\s0 Version Macros\fR
+.IX Subsection "Hook API Version Macros"
+.PP
+.Vb 6
+\& /* Hook API version major/minor */
+\& #define SUDO_HOOK_VERSION_MAJOR 1
+\& #define SUDO_HOOK_VERSION_MINOR 0
+\& #define SUDO_HOOK_MKVERSION(x, y) ((x << 16) | y)
+\& #define SUDO_HOOK_VERSION SUDO_HOOK_MKVERSION(SUDO_HOOK_VERSION_MAJOR,\e
+\&                                               SUDO_HOOK_VERSION_MINOR)
+\&
+\& /* Getters and setters for hook API version */
+\& #define SUDO_HOOK_VERSION_GET_MAJOR(v) ((v) >> 16)
+\& #define SUDO_HOOK_VERSION_GET_MINOR(v) ((v) & 0xffff)
+\& #define SUDO_HOOK_VERSION_SET_MAJOR(vp, n) do { \e
+\&     *(vp) = (*(vp) & 0x0000ffff) | ((n) << 16); \e
+\& } while(0)
+\& #define SUDO_HOOK_VERSION_SET_MINOR(vp, n) do { \e
+\&     *(vp) = (*(vp) & 0xffff0000) | (n); \e
+\& } while(0)
+.Ve
+.SS "Conversation \s-1API\s0"
+.IX Subsection "Conversation API"
+If the plugin needs to interact with the user, it may do so via the
+conversation function.  A plugin should not attempt to read directly
+from the standard input or the user's tty (neither of which are
+guaranteed to exist).  The caller must include a trailing newline
+in \f(CW\*(C`msg\*(C'\fR if one is to be printed.
+.PP
+A printf-style function is also available that can be used to display
+informational or error messages to the user, which is usually more
+convenient for simple messages where no use input is required.
+.PP
+.Vb 12
+\& struct sudo_conv_message {
+\& #define SUDO_CONV_PROMPT_ECHO_OFF  0x0001 /* do not echo user input */
+\& #define SUDO_CONV_PROMPT_ECHO_ON   0x0002 /* echo user input */
+\& #define SUDO_CONV_ERROR_MSG        0x0003 /* error message */
+\& #define SUDO_CONV_INFO_MSG         0x0004 /* informational message */
+\& #define SUDO_CONV_PROMPT_MASK      0x0005 /* mask user input */
+\& #define SUDO_CONV_DEBUG_MSG        0x0006 /* debugging message */
+\& #define SUDO_CONV_PROMPT_ECHO_OK   0x1000 /* flag: allow echo if no tty */
+\&     int msg_type;
+\&     int timeout;
+\&     const char *msg;
+\& };
+\&
+\& struct sudo_conv_reply {
+\&     char *reply;
+\& };
+\&
+\& typedef int (*sudo_conv_t)(int num_msgs,
+\&              const struct sudo_conv_message msgs[],
+\&              struct sudo_conv_reply replies[]);
+\&
+\& typedef int (*sudo_printf_t)(int msg_type, const char *fmt, ...);
+.Ve
+.PP
+Pointers to the conversation and printf-style functions are passed
+in to the plugin's \f(CW\*(C`open\*(C'\fR function when the plugin is initialized.
+.PP
+To use the conversation function, the plugin must pass an array of
+\&\f(CW\*(C`sudo_conv_message\*(C'\fR and \f(CW\*(C`sudo_conv_reply\*(C'\fR structures.  There must
+be a \f(CW\*(C`struct sudo_conv_message\*(C'\fR and \f(CW\*(C`struct sudo_conv_reply\*(C'\fR for
+each message in the conversation.  The plugin is responsible for
+freeing the reply buffer filled in to the \f(CW\*(C`struct sudo_conv_reply\*(C'\fR,
+if any.
+.PP
+The printf-style function uses the same underlying mechanism as the
+conversation function but only supports \f(CW\*(C`SUDO_CONV_INFO_MSG\*(C'\fR,
+\&\f(CW\*(C`SUDO_CONV_ERROR_MSG\*(C'\fR and \f(CW\*(C`SUDO_CONV_DEBUG_MSG\*(C'\fR for the \fImsg_type\fR
+parameter.  It can be more convenient than using the conversation
+function if no user reply is needed and supports standard \fIprintf()\fR
+escape sequences.
+.PP
+Unlike, \f(CW\*(C`SUDO_CONV_INFO_MSG\*(C'\fR and \f(CW\*(C`SUDO_CONV_ERROR_MSG\*(C'\fR, messages
+sent with the <\s-1SUDO_CONV_DEBUG_MSG\s0> \fImsg_type\fR are not directly
+user-visible.  Instead, they are logged to the file specified in
+the \f(CW\*(C`Debug\*(C'\fR statement (if any) in the \fI@sysconfdir@/sudo.conf\fR
+file.  This allows a plugin to log debugging information and is
+intended to be used in conjunction with the \fIdebug_flags\fR setting.
+.PP
+See the sample plugin for an example of the conversation function usage.
+.SS "Sudoers Group Plugin \s-1API\s0"
+.IX Subsection "Sudoers Group Plugin API"
+The \fIsudoers\fR module supports a plugin interface to allow non-Unix
+group lookups.  This can be used to query a group source other than
+the standard Unix group database.  A sample group plugin is bundled
+with \fBsudo\fR that implements file-based lookups.  Third party group
+plugins include a \s-1QAS\s0 \s-1AD\s0 plugin available from Quest Software.
+.PP
+A group plugin must declare and populate a \f(CW\*(C`sudoers_group_plugin\*(C'\fR
+struct in the global scope.  This structure contains pointers to
+the functions that implement plugin initialization, cleanup and
+group lookup.
+.PP
+.Vb 8
+\& struct sudoers_group_plugin {
+\&    unsigned int version;
+\&    int (*init)(int version, sudo_printf_t sudo_printf,
+\&                char *const argv[]);
+\&    void (*cleanup)(void);
+\&    int (*query)(const char *user, const char *group,
+\&                 const struct passwd *pwd);
+\&};
+.Ve
+.PP
+The \f(CW\*(C`sudoers_group_plugin\*(C'\fR struct has the following fields:
+.IP "version" 4
+.IX Item "version"
+The \f(CW\*(C`version\*(C'\fR field should be set to \s-1GROUP_API_VERSION\s0.
+.Sp
+This allows \fIsudoers\fR to determine the \s-1API\s0 version the group plugin
+was built against.
+.IP "init" 4
+.IX Item "init"
+.Vb 2
+\& int (*init)(int version, sudo_printf_t plugin_printf,
+\&             char *const argv[]);
+.Ve
+.Sp
+The \fIinit\fR function is called after \fIsudoers\fR has been parsed but
+before any policy checks.  It returns 1 on success, 0 on failure
+(or if the plugin is not configured), and \-1 if a error occurred.
+If an error occurs, the plugin may call the plugin_printf function
+with \f(CW\*(C`SUDO_CONF_ERROR_MSG\*(C'\fR to present additional error information
+to the user.
+.Sp
+The function arguments are as follows:
+.RS 4
+.IP "version" 4
+.IX Item "version"
+The version passed in by \fIsudoers\fR allows the plugin to determine the
+major and minor version number of the group plugin \s-1API\s0 supported by
+\&\fIsudoers\fR.
+.IP "plugin_printf" 4
+.IX Item "plugin_printf"
+A pointer to a printf-style function that may be used to display
+informational or error message to the user.
+Returns the number of characters printed on success and \-1 on failure.
+.IP "argv" 4
+.IX Item "argv"
+A NULL-terminated array of arguments generated from the \fIgroup_plugin\fR
+option in \fIsudoers\fR.  If no arguments were given, \fIargv\fR will be
+\&\s-1NULL\s0.
+.RE
+.RS 4
+.RE
+.IP "cleanup" 4
+.IX Item "cleanup"
+.Vb 1
+\& void (*cleanup)();
+.Ve
+.Sp
+The \fIcleanup\fR function is called when \fIsudoers\fR has finished its
+group checks.  The plugin should free any memory it has allocated
+and close open file handles.
+.IP "query" 4
+.IX Item "query"
+.Vb 2
+\& int (*query)(const char *user, const char *group,
+\&              const struct passwd *pwd);
+.Ve
+.Sp
+The \fIquery\fR function is used to ask the group plugin whether \fIuser\fR
+is a member of \fIgroup\fR.
+.Sp
+The function arguments are as follows:
+.RS 4
+.IP "user" 4
+.IX Item "user"
+The name of the user being looked up in the external group database.
+.IP "group" 4
+.IX Item "group"
+The name of the group being queried.
+.IP "pwd" 4
+.IX Item "pwd"
+The password database entry for \fIuser\fR, if any.  If \fIuser\fR is not
+present in the password database, \fIpwd\fR will be \f(CW\*(C`NULL\*(C'\fR.
+.RE
+.RS 4
+.RE
+.PP
+\fIGroup \s-1API\s0 Version Macros\fR
+.IX Subsection "Group API Version Macros"
+.PP
+.Vb 5
+\& /* Sudoers group plugin version major/minor */
+\& #define GROUP_API_VERSION_MAJOR 1
+\& #define GROUP_API_VERSION_MINOR 0
+\& #define GROUP_API_VERSION ((GROUP_API_VERSION_MAJOR << 16) | \e
+\&                            GROUP_API_VERSION_MINOR)
+\&
+\& /* Getters and setters for group version */
+\& #define GROUP_API_VERSION_GET_MAJOR(v) ((v) >> 16)
+\& #define GROUP_API_VERSION_GET_MINOR(v) ((v) & 0xffff)
+\& #define GROUP_API_VERSION_SET_MAJOR(vp, n) do { \e
+\&     *(vp) = (*(vp) & 0x0000ffff) | ((n) << 16); \e
+\& } while(0)
+\& #define GROUP_API_VERSION_SET_MINOR(vp, n) do { \e
+\&     *(vp) = (*(vp) & 0xffff0000) | (n); \e
+\& } while(0)
+.Ve
+.SH "PLUGIN API CHANGELOG"
+.IX Header "PLUGIN API CHANGELOG"
+The following revisions have been made to the Sudo Plugin \s-1API\s0.
+.IP "Version 1.0" 4
+.IX Item "Version 1.0"
+Initial \s-1API\s0 version.
+.IP "Version 1.1" 4
+.IX Item "Version 1.1"
+The I/O logging plugin's \f(CW\*(C`open\*(C'\fR function was modified to take the
+\&\f(CW\*(C`command_info\*(C'\fR list as an argument.
+.IP "Version 1.2" 4
+.IX Item "Version 1.2"
+The Policy and I/O logging plugins' \f(CW\*(C`open\*(C'\fR functions are now passed
+a list of plugin options if any are specified in \fI@sysconfdir@/sudo.conf\fR.
+.Sp
+A simple hooks \s-1API\s0 has been introduced to allow plugins to hook in to the
+system's environment handling functions.
+.Sp
+The \f(CW\*(C`init_session\*(C'\fR Policy plugin function is now passed a pointer
+to the user environment which can be updated as needed.  This can
+be used to merge in environment variables stored in the \s-1PAM\s0 handle
+before a command is run.
+.SH "SEE ALSO"
+.IX Header "SEE ALSO"
+\&\fIsudoers\fR\|(@mansectform@), \fIsudo\fR\|(@mansectsu@)
+.SH "BUGS"
+.IX Header "BUGS"
+If you feel you have found a bug in \fBsudo\fR, please submit a bug report
+at http://www.sudo.ws/sudo/bugs/
+.SH "SUPPORT"
+.IX Header "SUPPORT"
+Limited free support is available via the sudo-workers mailing list,
+see http://www.sudo.ws/mailman/listinfo/sudo\-workers to subscribe or
+search the archives.
+.SH "DISCLAIMER"
+.IX Header "DISCLAIMER"
+\&\fBsudo\fR is provided ``\s-1AS\s0 \s-1IS\s0'' and any express or implied warranties,
+including, but not limited to, the implied warranties of merchantability
+and fitness for a particular purpose are disclaimed.  See the \s-1LICENSE\s0
+file distributed with \fBsudo\fR or http://www.sudo.ws/sudo/license.html
+for complete details.