Fix the -s and -i flags and add support for the "implied_shell"
option. If the user does not specify a command, sudo will now pass in the path to the user's shell and set impied_shell=true. The plugin can them either check the command normally or return -2 to cause sudo to print a usage message and exit.
This commit is contained in:
@@ -61,7 +61,7 @@ SSuuddoo PPlluuggiinn AAPPII
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
1.8.0a1 March 19, 2010 1
|
1.8.0a1 March 21, 2010 1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -127,7 +127,7 @@ SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
1.8.0a1 March 19, 2010 2
|
1.8.0a1 March 21, 2010 2
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -172,6 +172,15 @@ SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
|
|||||||
Set to true if the user specified the -i flag, indicating
|
Set to true if the user specified the -i flag, indicating
|
||||||
that the user wishes to run a login shell.
|
that the user wishes to run a login shell.
|
||||||
|
|
||||||
|
implied_shell=bool
|
||||||
|
If the user does not specify a program on the command line,
|
||||||
|
ssuuddoo will pass the plugin the path to the user's shell and
|
||||||
|
set _i_m_p_l_i_e_d___s_h_e_l_l to true. This allows ssuuddoo with no
|
||||||
|
arguments to be used similarly to _s_u(1). If the plugin
|
||||||
|
does not to support this usage, it may return a value of -2
|
||||||
|
from the check_policy function, which will cause ssuuddoo to
|
||||||
|
print a usage message and exit.
|
||||||
|
|
||||||
preserve_groups=bool
|
preserve_groups=bool
|
||||||
Set to true if the user specified the -P flag, indicating
|
Set to true if the user specified the -P flag, indicating
|
||||||
that the user wishes to preserve the group vector instead
|
that the user wishes to preserve the group vector instead
|
||||||
@@ -182,18 +191,9 @@ SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
|
|||||||
command, indicating that the user wishes to ignore any
|
command, indicating that the user wishes to ignore any
|
||||||
cached authentication credentials.
|
cached authentication credentials.
|
||||||
|
|
||||||
login_class=string
|
|
||||||
BSD login class to use when setting resource limits and
|
|
||||||
nice value, if specified by the -c flag.
|
|
||||||
|
|
||||||
selinux_role=string
|
|
||||||
SELinux role to use when executing the command, if
|
|
||||||
specified by the -r flag.
|
|
||||||
|
|
||||||
|
|
||||||
|
1.8.0a1 March 21, 2010 3
|
||||||
|
|
||||||
1.8.0a1 March 19, 2010 3
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -202,6 +202,14 @@ SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
|
|||||||
SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
|
SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
|
||||||
|
|
||||||
|
|
||||||
|
login_class=string
|
||||||
|
BSD login class to use when setting resource limits and
|
||||||
|
nice value, if specified by the -c flag.
|
||||||
|
|
||||||
|
selinux_role=string
|
||||||
|
SELinux role to use when executing the command, if
|
||||||
|
specified by the -r flag.
|
||||||
|
|
||||||
selinux_type=string
|
selinux_type=string
|
||||||
SELinux type to use when executing the command, if
|
SELinux type to use when executing the command, if
|
||||||
specified by the -t flag.
|
specified by the -t flag.
|
||||||
@@ -247,6 +255,19 @@ SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
|
|||||||
terminal device associated with the session, the value will
|
terminal device associated with the session, the value will
|
||||||
be empty, as in tty=.
|
be empty, as in tty=.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
1.8.0a1 March 21, 2010 4
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
|
||||||
|
|
||||||
|
|
||||||
host=string
|
host=string
|
||||||
The local machine's hostname as returned by the
|
The local machine's hostname as returned by the
|
||||||
gethostname() system call.
|
gethostname() system call.
|
||||||
@@ -256,18 +277,6 @@ SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
|
|||||||
is no terminal device available, a default value of 24 is
|
is no terminal device available, a default value of 24 is
|
||||||
used.
|
used.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
1.8.0a1 March 19, 2010 4
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
|
|
||||||
|
|
||||||
|
|
||||||
cols=int
|
cols=int
|
||||||
The number of columns the user's terminal supports. If
|
The number of columns the user's terminal supports. If
|
||||||
there is no terminal device available, a default value of
|
there is no terminal device available, a default value of
|
||||||
@@ -311,6 +320,20 @@ SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
|
|||||||
will be set.
|
will be set.
|
||||||
|
|
||||||
check_policy
|
check_policy
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
1.8.0a1 March 21, 2010 5
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
|
||||||
|
|
||||||
|
|
||||||
int (*check_policy)(int argc, char * const argv[]
|
int (*check_policy)(int argc, char * const argv[]
|
||||||
char *env_add[], char **command_info[],
|
char *env_add[], char **command_info[],
|
||||||
char **argv_out[], char **user_env_out[]);
|
char **argv_out[], char **user_env_out[]);
|
||||||
@@ -322,18 +345,6 @@ SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
|
|||||||
SUDO_CONF_ERROR_MSG to present additional error information to the
|
SUDO_CONF_ERROR_MSG to present additional error information to the
|
||||||
user.
|
user.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
1.8.0a1 March 19, 2010 5
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
|
|
||||||
|
|
||||||
|
|
||||||
The function arguments are as follows:
|
The function arguments are as follows:
|
||||||
|
|
||||||
argc
|
argc
|
||||||
@@ -377,6 +388,18 @@ SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
|
|||||||
runas_gid=gid
|
runas_gid=gid
|
||||||
Group ID to run the command as.
|
Group ID to run the command as.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
1.8.0a1 March 21, 2010 6
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
|
||||||
|
|
||||||
|
|
||||||
runas_egid=gid
|
runas_egid=gid
|
||||||
Effective group ID to run the command as. If not
|
Effective group ID to run the command as. If not
|
||||||
specified, the value of _r_u_n_a_s___g_i_d is used.
|
specified, the value of _r_u_n_a_s___g_i_d is used.
|
||||||
@@ -388,18 +411,6 @@ SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
|
|||||||
|
|
||||||
login_class=login_class
|
login_class=login_class
|
||||||
BSD login class to use when setting resource limits and
|
BSD login class to use when setting resource limits and
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
1.8.0a1 March 19, 2010 6
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
|
|
||||||
|
|
||||||
|
|
||||||
nice value (optional). This option is only set on systems
|
nice value (optional). This option is only set on systems
|
||||||
that support login classes.
|
that support login classes.
|
||||||
|
|
||||||
@@ -442,6 +453,19 @@ SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
|
|||||||
system call when executing the command. The plugin is
|
system call when executing the command. The plugin is
|
||||||
responsible for allocating and populating the vector.
|
responsible for allocating and populating the vector.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
1.8.0a1 March 21, 2010 7
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
|
||||||
|
|
||||||
|
|
||||||
user_env_out
|
user_env_out
|
||||||
The NULL-terminated environment vector to use when executing
|
The NULL-terminated environment vector to use when executing
|
||||||
the command. The plugin is responsible for allocating and
|
the command. The plugin is responsible for allocating and
|
||||||
@@ -454,18 +478,6 @@ SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
|
|||||||
List available privileges for the invoking user. Returns 1 on
|
List available privileges for the invoking user. Returns 1 on
|
||||||
success, 0 on failure and -1 on error. On error, the plugin may
|
success, 0 on failure and -1 on error. On error, the plugin may
|
||||||
optionally call the conversation function with SUDO_CONF_ERROR_MSG
|
optionally call the conversation function with SUDO_CONF_ERROR_MSG
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
1.8.0a1 March 19, 2010 7
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
|
|
||||||
|
|
||||||
|
|
||||||
to present additional error information to the user.
|
to present additional error information to the user.
|
||||||
|
|
||||||
Privileges should be output via the conversation function using
|
Privileges should be output via the conversation function using
|
||||||
@@ -509,6 +521,17 @@ SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
|
|||||||
invalidate
|
invalidate
|
||||||
void (*invalidate)(int remove);
|
void (*invalidate)(int remove);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
1.8.0a1 March 21, 2010 8
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
|
||||||
|
|
||||||
|
|
||||||
The invalidate function is called when ssuuddoo is called with the -k
|
The invalidate function is called when ssuuddoo is called with the -k
|
||||||
or -K flag. For policy plugins such as _s_u_d_o_e_r_s that cache
|
or -K flag. For policy plugins such as _s_u_d_o_e_r_s that cache
|
||||||
authentication credentials, this function will invalidate the
|
authentication credentials, this function will invalidate the
|
||||||
@@ -520,18 +543,6 @@ SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
|
|||||||
|
|
||||||
_C_o_n_v_e_r_s_a_t_i_o_n _A_P_I
|
_C_o_n_v_e_r_s_a_t_i_o_n _A_P_I
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
1.8.0a1 March 19, 2010 8
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
|
|
||||||
|
|
||||||
|
|
||||||
If the plugin needs to interact with the user or display informational
|
If the plugin needs to interact with the user or display informational
|
||||||
or error messages, it may do so via the conversation function. A
|
or error messages, it may do so via the conversation function. A
|
||||||
plugin should not attempt to read directly from the standard input or
|
plugin should not attempt to read directly from the standard input or
|
||||||
@@ -566,6 +577,27 @@ SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
|
|||||||
usage.
|
usage.
|
||||||
|
|
||||||
II//OO PPlluuggiinn AAPPII
|
II//OO PPlluuggiinn AAPPII
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
1.8.0a1 March 21, 2010 9
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
|
||||||
|
|
||||||
|
|
||||||
struct io_plugin {
|
struct io_plugin {
|
||||||
#define SUDO_IO_PLUGIN 2
|
#define SUDO_IO_PLUGIN 2
|
||||||
unsigned int type; /* always SUDO_IO_PLUGIN */
|
unsigned int type; /* always SUDO_IO_PLUGIN */
|
||||||
@@ -586,18 +618,6 @@ SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
|
|||||||
disabled, such as passwords). The log_output function receives output
|
disabled, such as passwords). The log_output function receives output
|
||||||
from the pseudo-tty that is suitable for replaying the user's session
|
from the pseudo-tty that is suitable for replaying the user's session
|
||||||
at a later time. Either log_input or log_output may be NULL. If the
|
at a later time. Either log_input or log_output may be NULL. If the
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
1.8.0a1 March 19, 2010 9
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
|
|
||||||
|
|
||||||
|
|
||||||
open function returns 0, no I/O will be sent to the plugin.
|
open function returns 0, no I/O will be sent to the plugin.
|
||||||
|
|
||||||
The io_plugin struct has the following fields:
|
The io_plugin struct has the following fields:
|
||||||
@@ -632,6 +652,18 @@ SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
|
|||||||
A pointer to the conversation function that may be used by the
|
A pointer to the conversation function that may be used by the
|
||||||
_s_h_o_w___v_e_r_s_i_o_n function to display version information (see
|
_s_h_o_w___v_e_r_s_i_o_n function to display version information (see
|
||||||
show_version below). The conversation function may also be
|
show_version below). The conversation function may also be
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
1.8.0a1 March 21, 2010 10
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
|
||||||
|
|
||||||
|
|
||||||
used to display additional error message to the user.
|
used to display additional error message to the user.
|
||||||
|
|
||||||
settings
|
settings
|
||||||
@@ -653,17 +685,6 @@ SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
|
|||||||
the form of "name=value" strings. The vector is terminated by
|
the form of "name=value" strings. The vector is terminated by
|
||||||
a NULL pointer.
|
a NULL pointer.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
1.8.0a1 March 19, 2010 10
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
|
|
||||||
|
|
||||||
|
|
||||||
When parsing _u_s_e_r___i_n_f_o, the plugin should split on the ffiirrsstt
|
When parsing _u_s_e_r___i_n_f_o, the plugin should split on the ffiirrsstt
|
||||||
equal sign ('=') since the _n_a_m_e field will never include one
|
equal sign ('=') since the _n_a_m_e field will never include one
|
||||||
itself but the _v_a_l_u_e might.
|
itself but the _v_a_l_u_e might.
|
||||||
@@ -697,6 +718,18 @@ SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
|
|||||||
of errno set by the _e_x_e_c_v_e(2) system call. If the command was
|
of errno set by the _e_x_e_c_v_e(2) system call. If the command was
|
||||||
successfully executed, the value of error is 0.
|
successfully executed, the value of error is 0.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
1.8.0a1 March 21, 2010 11
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
|
||||||
|
|
||||||
|
|
||||||
show_version
|
show_version
|
||||||
int (*show_version)(int verbose);
|
int (*show_version)(int verbose);
|
||||||
|
|
||||||
@@ -718,18 +751,6 @@ SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
|
|||||||
|
|
||||||
The function arguments are as follows:
|
The function arguments are as follows:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
1.8.0a1 March 19, 2010 11
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
|
|
||||||
|
|
||||||
|
|
||||||
buf The buffer containing user input.
|
buf The buffer containing user input.
|
||||||
|
|
||||||
len The length of _b_u_f in bytes.
|
len The length of _b_u_f in bytes.
|
||||||
@@ -757,6 +778,24 @@ SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
|
|||||||
SSuuddoo iimmpplleemmeennttaattiioonn ddeettaaiillss
|
SSuuddoo iimmpplleemmeennttaattiioonn ddeettaaiillss
|
||||||
Version macros:
|
Version macros:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
1.8.0a1 March 21, 2010 12
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
|
||||||
|
|
||||||
|
|
||||||
#define SUDO_API_VERSION_GET_MAJOR(v) ((v) >> 16)
|
#define SUDO_API_VERSION_GET_MAJOR(v) ((v) >> 16)
|
||||||
#define SUDO_API_VERSION_GET_MINOR(v) ((v) & 0xffff)
|
#define SUDO_API_VERSION_GET_MINOR(v) ((v) & 0xffff)
|
||||||
#define SUDO_API_VERSION_SET_MAJOR(vp, n) do { \
|
#define SUDO_API_VERSION_SET_MAJOR(vp, n) do { \
|
||||||
@@ -787,6 +826,33 @@ SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
1.8.0a1 March 19, 2010 12
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
1.8.0a1 March 21, 2010 13
|
||||||
|
|
||||||
|
|
||||||
|
@@ -139,7 +139,7 @@
|
|||||||
.\" ========================================================================
|
.\" ========================================================================
|
||||||
.\"
|
.\"
|
||||||
.IX Title "SUDO_PLUGIN @mansectsu@"
|
.IX Title "SUDO_PLUGIN @mansectsu@"
|
||||||
.TH SUDO_PLUGIN @mansectsu@ "March 19, 2010" "1.8.0a1" "MAINTENANCE COMMANDS"
|
.TH SUDO_PLUGIN @mansectsu@ "March 21, 2010" "1.8.0a1" "MAINTENANCE COMMANDS"
|
||||||
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
|
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
|
||||||
.\" way too many mistakes in technical documents.
|
.\" way too many mistakes in technical documents.
|
||||||
.if n .ad l
|
.if n .ad l
|
||||||
@@ -295,6 +295,15 @@ the user wishes to preserve the environment.
|
|||||||
.IX Item "login_shell=bool"
|
.IX Item "login_shell=bool"
|
||||||
Set to true if the user specified the \f(CW\*(C`\-i\*(C'\fR flag, indicating that
|
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.
|
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
|
.IP "preserve_groups=bool" 4
|
||||||
.IX Item "preserve_groups=bool"
|
.IX Item "preserve_groups=bool"
|
||||||
Set to true if the user specified the \f(CW\*(C`\-P\*(C'\fR flag, indicating that
|
Set to true if the user specified the \f(CW\*(C`\-P\*(C'\fR flag, indicating that
|
||||||
|
@@ -180,6 +180,16 @@ the user wishes to preserve the environment.
|
|||||||
Set to true if the user specified the C<-i> flag, indicating that
|
Set to true if the user specified the C<-i> flag, indicating that
|
||||||
the user wishes to run a login shell.
|
the user wishes to run a login shell.
|
||||||
|
|
||||||
|
=item implied_shell=bool
|
||||||
|
|
||||||
|
If the user does not specify a program on the command line, B<sudo>
|
||||||
|
will pass the plugin the path to the user's shell and set
|
||||||
|
I<implied_shell> to true. This allows B<sudo> with no arguments
|
||||||
|
to be used similarly to L<su(1)>. If the plugin does not to support
|
||||||
|
this usage, it may return a value of -2 from the C<check_policy>
|
||||||
|
function, which will cause B<sudo> to print a usage message and
|
||||||
|
exit.
|
||||||
|
|
||||||
=item preserve_groups=bool
|
=item preserve_groups=bool
|
||||||
|
|
||||||
Set to true if the user specified the C<-P> flag, indicating that
|
Set to true if the user specified the C<-P> flag, indicating that
|
||||||
|
@@ -262,12 +262,6 @@ sudoers_policy_open(unsigned int version, sudo_conv_t conversation,
|
|||||||
/* Set login class if applicable. */
|
/* Set login class if applicable. */
|
||||||
set_loginclass(sudo_user.pw);
|
set_loginclass(sudo_user.pw);
|
||||||
|
|
||||||
#if 0 /* XXX - later */
|
|
||||||
/* Update initial shell now that runas is set. */
|
|
||||||
if (ISSET(sudo_mode, MODE_LOGIN_SHELL))
|
|
||||||
NewArgv[0] = runas_pw->pw_shell;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* XXX */
|
/* XXX */
|
||||||
user_env = envp; /* stash for later */
|
user_env = envp; /* stash for later */
|
||||||
|
|
||||||
@@ -305,11 +299,17 @@ sudoers_policy_main(int argc, char * const argv[], char *env_add[],
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Local copy of argv */
|
/*
|
||||||
|
* Make a local copy of argc/argv, with special handling
|
||||||
|
* for the '-e', '-i' or '-s' options.
|
||||||
|
* XXX - handle sudoedit
|
||||||
|
*/
|
||||||
NewArgv = emalloc2(argc + 1, sizeof(char *));
|
NewArgv = emalloc2(argc + 1, sizeof(char *));
|
||||||
memcpy(NewArgv, argv, argc * sizeof(char *));
|
memcpy(NewArgv, argv, argc * sizeof(char *));
|
||||||
NewArgv[argc] = NULL;
|
NewArgv[argc] = NULL;
|
||||||
NewArgc = argc;
|
NewArgc = argc;
|
||||||
|
if (ISSET(sudo_mode, MODE_LOGIN_SHELL))
|
||||||
|
NewArgv[0] = runas_pw->pw_shell;
|
||||||
|
|
||||||
/* Set environ to contents of user_env. */
|
/* Set environ to contents of user_env. */
|
||||||
env_init(user_env);
|
env_init(user_env);
|
||||||
@@ -387,9 +387,9 @@ sudoers_policy_main(int argc, char * const argv[], char *env_add[],
|
|||||||
if (ISSET(sudo_mode, MODE_PRESERVE_GROUPS))
|
if (ISSET(sudo_mode, MODE_PRESERVE_GROUPS))
|
||||||
def_preserve_groups = TRUE;
|
def_preserve_groups = TRUE;
|
||||||
|
|
||||||
/* If no command line args and "set_home" is not set, error out. */
|
/* If no command line args and "shell_noargs" is not set, error out. */
|
||||||
if (ISSET(sudo_mode, MODE_IMPLIED_SHELL) && !def_shell_noargs) {
|
if (ISSET(sudo_mode, MODE_IMPLIED_SHELL) && !def_shell_noargs) {
|
||||||
/* XXX - error message */
|
rval = -2; /* usage error */
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -447,7 +447,7 @@ sudoers_policy_main(int argc, char * const argv[], char *env_add[],
|
|||||||
goto done;
|
goto done;
|
||||||
} else if (cmnd_status == NOT_FOUND) {
|
} else if (cmnd_status == NOT_FOUND) {
|
||||||
//audit_failure(NewArgv, "%s: command not found", user_cmnd);
|
//audit_failure(NewArgv, "%s: command not found", user_cmnd);
|
||||||
warningx("command not found", user_cmnd);
|
warningx("%s: command not found", user_cmnd);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -622,12 +622,6 @@ init_vars(char * const envp[])
|
|||||||
(void) tzset(); /* set the timezone if applicable */
|
(void) tzset(); /* set the timezone if applicable */
|
||||||
#endif /* HAVE_TZSET */
|
#endif /* HAVE_TZSET */
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* Default value for cmnd and cwd, overridden later. */
|
|
||||||
if (user_cmnd == NULL)
|
|
||||||
user_cmnd = NewArgv[0];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (ep = envp; *ep; ep++) {
|
for (ep = envp; *ep; ep++) {
|
||||||
/* XXX - don't fill in if empty string */
|
/* XXX - don't fill in if empty string */
|
||||||
switch (**ep) {
|
switch (**ep) {
|
||||||
@@ -644,9 +638,7 @@ init_vars(char * const envp[])
|
|||||||
user_path = *ep + 5;
|
user_path = *ep + 5;
|
||||||
break;
|
break;
|
||||||
case 'S':
|
case 'S':
|
||||||
if (strncmp("SHELL=", *ep, 6) == 0)
|
if (!user_prompt && strncmp("SUDO_PROMPT=", *ep, 12) == 0)
|
||||||
user_shell = *ep + 6;
|
|
||||||
else if (!user_prompt && strncmp("SUDO_PROMPT=", *ep, 12) == 0)
|
|
||||||
user_prompt = *ep + 12;
|
user_prompt = *ep + 12;
|
||||||
else if (strncmp("SUDO_USER=", *ep, 10) == 0)
|
else if (strncmp("SUDO_USER=", *ep, 10) == 0)
|
||||||
prev_user = *ep + 10;
|
prev_user = *ep + 10;
|
||||||
@@ -683,8 +675,6 @@ init_vars(char * const envp[])
|
|||||||
#ifdef HAVE_MBR_CHECK_MEMBERSHIP
|
#ifdef HAVE_MBR_CHECK_MEMBERSHIP
|
||||||
mbr_uid_to_uuid(user_uid, user_uuid);
|
mbr_uid_to_uuid(user_uid, user_uuid);
|
||||||
#endif
|
#endif
|
||||||
if (user_shell == NULL || *user_shell == '\0')
|
|
||||||
user_shell = estrdup(sudo_user.pw->pw_shell);
|
|
||||||
|
|
||||||
/* It is now safe to use log_error() and set_perms() */
|
/* It is now safe to use log_error() and set_perms() */
|
||||||
|
|
||||||
@@ -692,43 +682,6 @@ init_vars(char * const envp[])
|
|||||||
/* may call log_error() */
|
/* may call log_error() */
|
||||||
set_fqdn();
|
set_fqdn();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0 /* XXX need to adapt this in sudo.c */
|
|
||||||
/*
|
|
||||||
* If we were given the '-e', '-i' or '-s' options we need to redo
|
|
||||||
* NewArgv and NewArgc.
|
|
||||||
*/
|
|
||||||
if (ISSET(sudo_mode, MODE_EDIT)) {
|
|
||||||
NewArgv--;
|
|
||||||
NewArgc++;
|
|
||||||
NewArgv[0] = "sudoedit";
|
|
||||||
} else if (ISSET(sudo_mode, MODE_SHELL)) {
|
|
||||||
char **av;
|
|
||||||
|
|
||||||
/* Allocate an extra slot for execve() failure (ENOEXEC). */
|
|
||||||
av = (char **) emalloc2(5, sizeof(char *));
|
|
||||||
av++;
|
|
||||||
|
|
||||||
av[0] = user_shell; /* may be updated later */
|
|
||||||
if (NewArgc > 0) {
|
|
||||||
size_t size;
|
|
||||||
char *cmnd, *src, *dst, *end;
|
|
||||||
size = (size_t) (NewArgv[NewArgc - 1] - NewArgv[0]) +
|
|
||||||
strlen(NewArgv[NewArgc - 1]) + 1;
|
|
||||||
cmnd = emalloc(size);
|
|
||||||
src = NewArgv[0];
|
|
||||||
dst = cmnd;
|
|
||||||
for (end = src + size - 1; src < end; src++, dst++)
|
|
||||||
*dst = *src == 0 ? ' ' : *src;
|
|
||||||
*dst = '\0';
|
|
||||||
av[1] = "-c";
|
|
||||||
av[2] = cmnd;
|
|
||||||
NewArgc = 2;
|
|
||||||
}
|
|
||||||
av[++NewArgc] = NULL;
|
|
||||||
NewArgv = av;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -748,6 +701,10 @@ set_cmnd(sudo_mode)
|
|||||||
rval = FOUND;
|
rval = FOUND;
|
||||||
user_stat = emalloc(sizeof(struct stat));
|
user_stat = emalloc(sizeof(struct stat));
|
||||||
|
|
||||||
|
/* Default value for cmnd, overridden below. */
|
||||||
|
if (user_cmnd == NULL)
|
||||||
|
user_cmnd = NewArgv[0];
|
||||||
|
|
||||||
if (sudo_mode & (MODE_RUN | MODE_EDIT | MODE_CHECK)) {
|
if (sudo_mode & (MODE_RUN | MODE_EDIT | MODE_CHECK)) {
|
||||||
if (ISSET(sudo_mode, MODE_RUN | MODE_CHECK)) {
|
if (ISSET(sudo_mode, MODE_RUN | MODE_CHECK)) {
|
||||||
set_perms(PERM_RUNAS);
|
set_perms(PERM_RUNAS);
|
||||||
@@ -766,16 +723,9 @@ set_cmnd(sudo_mode)
|
|||||||
char *to, **from;
|
char *to, **from;
|
||||||
size_t size, n;
|
size_t size, n;
|
||||||
|
|
||||||
/* If we didn't realloc NewArgv it is contiguous so just count. */
|
|
||||||
if (!ISSET(sudo_mode, MODE_SHELL)) {
|
|
||||||
size = (size_t) (NewArgv[NewArgc-1] - NewArgv[1]) +
|
|
||||||
strlen(NewArgv[NewArgc-1]) + 1;
|
|
||||||
} else {
|
|
||||||
for (size = 0, from = NewArgv + 1; *from; from++)
|
|
||||||
size += strlen(*from) + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Alloc and build up user_args. */
|
/* Alloc and build up user_args. */
|
||||||
|
for (size = 0, from = NewArgv + 1; *from; from++)
|
||||||
|
size += strlen(*from) + 1;
|
||||||
user_args = emalloc(size);
|
user_args = emalloc(size);
|
||||||
for (to = user_args, from = NewArgv + 1; *from; from++) {
|
for (to = user_args, from = NewArgv + 1; *from; from++) {
|
||||||
n = strlcpy(to, *from, size - (to - user_args));
|
n = strlcpy(to, *from, size - (to - user_args));
|
||||||
@@ -1197,6 +1147,11 @@ deserialize_info(char * const settings[], char * const user_info[])
|
|||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (MATCHES(*cur, "implied_shell=")) {
|
||||||
|
if (atobool(*cur + sizeof("implied_shell=") - 1) == TRUE)
|
||||||
|
SET(flags, MODE_IMPLIED_SHELL);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (MATCHES(*cur, "preserve_groups=")) {
|
if (MATCHES(*cur, "preserve_groups=")) {
|
||||||
SET(flags, MODE_PRESERVE_GROUPS);
|
SET(flags, MODE_PRESERVE_GROUPS);
|
||||||
continue;
|
continue;
|
||||||
|
@@ -48,7 +48,6 @@ struct sudo_user {
|
|||||||
struct stat *cmnd_stat;
|
struct stat *cmnd_stat;
|
||||||
char *name;
|
char *name;
|
||||||
char *path;
|
char *path;
|
||||||
char *shell;
|
|
||||||
char *tty;
|
char *tty;
|
||||||
char *ttypath;
|
char *ttypath;
|
||||||
char *host;
|
char *host;
|
||||||
@@ -156,7 +155,6 @@ struct sudo_user {
|
|||||||
#define user_passwd (sudo_user.pw->pw_passwd)
|
#define user_passwd (sudo_user.pw->pw_passwd)
|
||||||
#define user_uuid (sudo_user.uuid)
|
#define user_uuid (sudo_user.uuid)
|
||||||
#define user_dir (sudo_user.pw->pw_dir)
|
#define user_dir (sudo_user.pw->pw_dir)
|
||||||
#define user_shell (sudo_user.shell)
|
|
||||||
#define user_ngroups (sudo_user.ngroups)
|
#define user_ngroups (sudo_user.ngroups)
|
||||||
#define user_groups (sudo_user.groups)
|
#define user_groups (sudo_user.groups)
|
||||||
#define user_tty (sudo_user.tty)
|
#define user_tty (sudo_user.tty)
|
||||||
|
@@ -66,7 +66,6 @@ const char *list_user, *runas_user, *runas_group;
|
|||||||
/*
|
/*
|
||||||
* Local functions.
|
* Local functions.
|
||||||
*/
|
*/
|
||||||
static void usage(int) __attribute__((__noreturn__));
|
|
||||||
static void usage_excl(int) __attribute__((__noreturn__));
|
static void usage_excl(int) __attribute__((__noreturn__));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -102,7 +101,9 @@ static struct sudo_settings {
|
|||||||
{ "runas_user" },
|
{ "runas_user" },
|
||||||
#define ARG_PROGNAME 12
|
#define ARG_PROGNAME 12
|
||||||
{ "progname" },
|
{ "progname" },
|
||||||
#define NUM_SETTINGS 13
|
#define ARG_IMPLIED_SHELL 13
|
||||||
|
{ "implied_shell" },
|
||||||
|
#define NUM_SETTINGS 14
|
||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -295,13 +296,13 @@ parse_args(int argc, char **argv, int *nargc, char ***nargv, char ***settingsp,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*nargc = argc - optind;
|
argc -= optind;
|
||||||
*nargv = argv + optind;
|
argv += optind;
|
||||||
|
|
||||||
if (!mode) {
|
if (!mode) {
|
||||||
/* Defer -k mode setting until we know whether it is a flag or not */
|
/* Defer -k mode setting until we know whether it is a flag or not */
|
||||||
if (sudo_settings[ARG_IGNORE_TICKET].value != NULL) {
|
if (sudo_settings[ARG_IGNORE_TICKET].value != NULL) {
|
||||||
if (*nargc == 0) {
|
if (argc == 0) {
|
||||||
mode = MODE_INVALIDATE; /* -k by itself */
|
mode = MODE_INVALIDATE; /* -k by itself */
|
||||||
sudo_settings[ARG_IGNORE_TICKET].value = NULL;
|
sudo_settings[ARG_IGNORE_TICKET].value = NULL;
|
||||||
valid_flags = 0;
|
valid_flags = 0;
|
||||||
@@ -311,7 +312,7 @@ parse_args(int argc, char **argv, int *nargc, char ***nargv, char ***settingsp,
|
|||||||
mode = MODE_RUN; /* running a command */
|
mode = MODE_RUN; /* running a command */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*nargc > 0 && mode == MODE_LIST)
|
if (argc > 0 && mode == MODE_LIST)
|
||||||
mode = MODE_CHECK;
|
mode = MODE_CHECK;
|
||||||
|
|
||||||
if (ISSET(flags, MODE_LOGIN_SHELL)) {
|
if (ISSET(flags, MODE_LOGIN_SHELL)) {
|
||||||
@@ -347,15 +348,55 @@ parse_args(int argc, char **argv, int *nargc, char ***nargv, char ***settingsp,
|
|||||||
warningx("the `-A' and `-S' options may not be used together");
|
warningx("the `-A' and `-S' options may not be used together");
|
||||||
usage(1);
|
usage(1);
|
||||||
}
|
}
|
||||||
if ((*nargc == 0 && mode == MODE_EDIT) ||
|
if ((argc == 0 && mode == MODE_EDIT) ||
|
||||||
(*nargc > 0 && !ISSET(mode, MODE_RUN | MODE_EDIT | MODE_CHECK)))
|
(argc > 0 && !ISSET(mode, MODE_RUN | MODE_EDIT | MODE_CHECK)))
|
||||||
usage(1);
|
usage(1);
|
||||||
if (*nargc == 0 && mode == MODE_RUN && !ISSET(flags, MODE_SHELL))
|
if (argc == 0 && mode == MODE_RUN && !ISSET(flags, MODE_SHELL)) {
|
||||||
SET(flags, (MODE_IMPLIED_SHELL | MODE_SHELL));
|
SET(flags, (MODE_IMPLIED_SHELL | MODE_SHELL));
|
||||||
|
sudo_settings[ARG_IMPLIED_SHELL].value = "true";
|
||||||
|
}
|
||||||
|
|
||||||
if (mode == MODE_HELP)
|
if (mode == MODE_HELP)
|
||||||
usage(0);
|
usage(0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For shell mode we need to rewrite argv
|
||||||
|
*/
|
||||||
|
if (ISSET(mode, MODE_RUN) && ISSET(flags, MODE_SHELL)) {
|
||||||
|
char **av;
|
||||||
|
int ac;
|
||||||
|
|
||||||
|
if (argc == 0) {
|
||||||
|
/* just the shell */
|
||||||
|
ac = argc + 1;
|
||||||
|
av = emalloc2(ac + 1, sizeof(char *));
|
||||||
|
memcpy(av + 1, argv, argc * sizeof(char *));
|
||||||
|
} else {
|
||||||
|
/* shell -c "command" */
|
||||||
|
size_t size;
|
||||||
|
char *src, *dst, *end;
|
||||||
|
|
||||||
|
/* length of the command + NUL terminator */
|
||||||
|
size = (size_t)(argv[argc - 1] - argv[0]) +
|
||||||
|
strlen(argv[argc - 1]) + 1;
|
||||||
|
|
||||||
|
ac = 3;
|
||||||
|
av = emalloc2(ac + 1, sizeof(char *));
|
||||||
|
av[1] = "-c";
|
||||||
|
av[2] = dst = emalloc(size);
|
||||||
|
|
||||||
|
src = argv[0];
|
||||||
|
for (end = src + size - 1; src < end; src++, dst++)
|
||||||
|
*dst = *src == 0 ? ' ' : *src;
|
||||||
|
*dst = '\0';
|
||||||
|
}
|
||||||
|
av[0] = (char *)user_details.shell; /* plugin may override shell */
|
||||||
|
av[ac] = NULL;
|
||||||
|
|
||||||
|
argv = av;
|
||||||
|
argc = ac;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Format setting_pairs into settings array.
|
* Format setting_pairs into settings array.
|
||||||
*/
|
*/
|
||||||
@@ -375,6 +416,8 @@ parse_args(int argc, char **argv, int *nargc, char ***nargv, char ***settingsp,
|
|||||||
|
|
||||||
*settingsp = settings;
|
*settingsp = settings;
|
||||||
*env_addp = env_add;
|
*env_addp = env_add;
|
||||||
|
*nargc = argc;
|
||||||
|
*nargv = argv;
|
||||||
return(mode | flags);
|
return(mode | flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -388,7 +431,7 @@ usage_out(const char *buf)
|
|||||||
* Give usage message and exit.
|
* Give usage message and exit.
|
||||||
* The actual usage strings are in sudo_usage.h for configure substitution.
|
* The actual usage strings are in sudo_usage.h for configure substitution.
|
||||||
*/
|
*/
|
||||||
static void
|
void
|
||||||
usage(int exit_val)
|
usage(int exit_val)
|
||||||
{
|
{
|
||||||
struct lbuf lbuf;
|
struct lbuf lbuf;
|
||||||
|
13
src/sudo.c
13
src/sudo.c
@@ -224,8 +224,11 @@ main(int argc, char *argv[], char *envp[])
|
|||||||
ok = policy_plugin.u.policy->check_policy(nargc, nargv, env_add,
|
ok = policy_plugin.u.policy->check_policy(nargc, nargv, env_add,
|
||||||
&command_info, &argv_out, &user_env_out);
|
&command_info, &argv_out, &user_env_out);
|
||||||
sudo_debug(8, "policy plugin returns %d", ok);
|
sudo_debug(8, "policy plugin returns %d", ok);
|
||||||
if (ok != TRUE)
|
if (ok != TRUE) {
|
||||||
exit(ok); /* plugin printed error message */
|
if (ok == -2)
|
||||||
|
usage(1);
|
||||||
|
exit(1); /* plugin printed error message */
|
||||||
|
}
|
||||||
command_info_to_details(command_info, &command_details);
|
command_info_to_details(command_info, &command_details);
|
||||||
/* Restore coredumpsize resource limit before running. */
|
/* Restore coredumpsize resource limit before running. */
|
||||||
#if defined(RLIMIT_CORE) && !defined(SUDO_DEVEL)
|
#if defined(RLIMIT_CORE) && !defined(SUDO_DEVEL)
|
||||||
@@ -330,6 +333,12 @@ get_user_info(struct user_details *ud)
|
|||||||
errorx(1, "unable to allocate memory");
|
errorx(1, "unable to allocate memory");
|
||||||
ud->username = user_info[i] + sizeof("user=") - 1;
|
ud->username = user_info[i] + sizeof("user=") - 1;
|
||||||
|
|
||||||
|
/* Stash user's shell for use with the -s flag; don't pass to plugin. */
|
||||||
|
if ((ud->shell = getenv("SHELL")) == NULL || ud->shell[0] == '\0') {
|
||||||
|
ud->shell = pw->pw_shell[0] ? pw->pw_shell : _PATH_BSHELL;
|
||||||
|
}
|
||||||
|
ud->shell = estrdup(ud->shell);
|
||||||
|
|
||||||
easprintf(&user_info[++i], "uid=%lu", (unsigned long)ud->uid);
|
easprintf(&user_info[++i], "uid=%lu", (unsigned long)ud->uid);
|
||||||
easprintf(&user_info[++i], "euid=%lu", (unsigned long)ud->euid);
|
easprintf(&user_info[++i], "euid=%lu", (unsigned long)ud->euid);
|
||||||
easprintf(&user_info[++i], "gid=%lu", (unsigned long)ud->gid);
|
easprintf(&user_info[++i], "gid=%lu", (unsigned long)ud->gid);
|
||||||
|
@@ -117,6 +117,7 @@ struct user_details {
|
|||||||
const char *cwd;
|
const char *cwd;
|
||||||
const char *tty;
|
const char *tty;
|
||||||
const char *host;
|
const char *host;
|
||||||
|
const char *shell;
|
||||||
GETGROUPS_T *groups;
|
GETGROUPS_T *groups;
|
||||||
int ngroups;
|
int ngroups;
|
||||||
int ts_cols;
|
int ts_cols;
|
||||||
@@ -210,6 +211,9 @@ int exec_setup(struct command_details *details);
|
|||||||
extern int debug_level;
|
extern int debug_level;
|
||||||
extern struct plugin_container_list io_plugins;
|
extern struct plugin_container_list io_plugins;
|
||||||
|
|
||||||
|
/* parse_args.c */
|
||||||
|
void usage(int) __attribute__((__noreturn__));
|
||||||
|
|
||||||
#ifndef errno
|
#ifndef errno
|
||||||
extern int errno;
|
extern int errno;
|
||||||
#endif
|
#endif
|
||||||
|
Reference in New Issue
Block a user