Add a struct sudo_conv_callback that contains on_suspend and on_resume
function pointer args plus a closure pointer and at it to the conversation function.
This commit is contained in:
@@ -1297,9 +1297,26 @@ DDEESSCCRRIIPPTTIIOONN
|
||||
char *reply;
|
||||
};
|
||||
|
||||
/* Conversation callback API version major/minor */
|
||||
#define SUDO_CONV_CALLBACK_VERSION_MAJOR 1
|
||||
#define SUDO_CONV_CALLBACK_VERSION_MINOR 0
|
||||
#define SUDO_CONV_CALLBACK_MKVERSION(x, y) ((x << 16) | y)
|
||||
#define SUDO_CONV_CALLBACK_VERSION \
|
||||
SUDO_CONV_CALLBACK_MKVERSION(SUDO_CONV_CALLBACK_VERSION_MAJOR, \
|
||||
SUDO_CONV_CALLBACK_VERSION_MINOR)
|
||||
|
||||
typedef int (*sudo_conv_callback_fn_t)(int signo, void *closure);
|
||||
struct sudo_conv_callback {
|
||||
unsigned int version;
|
||||
void *closure;
|
||||
sudo_conv_callback_fn_t on_suspend;
|
||||
sudo_conv_callback_fn_t on_resume;
|
||||
};
|
||||
|
||||
typedef int (*sudo_conv_t)(int num_msgs,
|
||||
const struct sudo_conv_message msgs[],
|
||||
struct sudo_conv_reply replies[]);
|
||||
struct sudo_conv_reply replies[],
|
||||
struct sudo_conv_callback *callback);
|
||||
|
||||
typedef int (*sudo_printf_t)(int msg_type, const char *fmt, ...);
|
||||
|
||||
@@ -1309,13 +1326,21 @@ DDEESSCCRRIIPPTTIIOONN
|
||||
To use the ccoonnvveerrssaattiioonn() function, the plugin must pass an array of
|
||||
sudo_conv_message and sudo_conv_reply structures. There must be a struct
|
||||
sudo_conv_message and struct sudo_conv_reply for each message in the
|
||||
conversation. The plugin is responsible for freeing the reply buffer
|
||||
located in each struct sudo_conv_reply, if it is not NULL.
|
||||
SUDO_CONV_REPL_MAX represents the maximum length of the reply buffer (not
|
||||
including the trailing NUL character). In practical terms, this is the
|
||||
longest password ssuuddoo will support. It is also useful as a maximum value
|
||||
for the mmeemmsseett__ss() function when clearing passwords filled in by the
|
||||
conversation function.
|
||||
conversation. The struct sudo_conv_callback pointer, if not NULL,
|
||||
contains function pointers that are called when the ssuuddoo process is
|
||||
suspended and/or resumed during conversation input. The functions are
|
||||
passed the signal that caused ssuuddoo to be suspended and the _c_l_o_s_u_r_e
|
||||
pointer. This allows the plugin to release resources such as locks that
|
||||
should not be held indefinitely on suspend and reacquire them on resume.
|
||||
Note that the functions are not actually invoked from within a signal
|
||||
handler.
|
||||
|
||||
The plugin is responsible for freeing the reply buffer located in each
|
||||
struct sudo_conv_reply, if it is not NULL. SUDO_CONV_REPL_MAX represents
|
||||
the maximum length of the reply buffer (not including the trailing NUL
|
||||
character). In practical terms, this is the longest password ssuuddoo will
|
||||
support. It is also useful as a maximum value for the mmeemmsseett__ss()
|
||||
function when clearing passwords filled in by the conversation function.
|
||||
|
||||
The pprriinnttff()-style function uses the same underlying mechanism as the
|
||||
ccoonnvveerrssaattiioonn() function but only supports SUDO_CONV_INFO_MSG and
|
||||
@@ -1490,6 +1515,12 @@ PPLLUUGGIINN AAPPII CCHHAANNGGEELLOOGG
|
||||
Version 1.8 (sudo 1.8.15)
|
||||
The _s_u_d_o_e_d_i_t___f_o_l_l_o_w entry was added to the command_info list.
|
||||
|
||||
The sudo _c_o_n_v_e_r_s_a_t_i_o_n function now takes a pointer to a struct
|
||||
sudo_conv_callback as its fourth argument. The sudo_conv_t
|
||||
definition has been updated to match. The plugin must specify that
|
||||
it supports plugin API version 1.8 or higher to receive a
|
||||
conversation function pointer that supports this argument.
|
||||
|
||||
SSEEEE AALLSSOO
|
||||
sudo.conf(4), sudoers(4), sudo(1m)
|
||||
|
||||
@@ -1519,4 +1550,4 @@ DDIISSCCLLAAIIMMEERR
|
||||
file distributed with ssuuddoo or http://www.sudo.ws/license.html for
|
||||
complete details.
|
||||
|
||||
Sudo 1.8.15 August 6, 2015 Sudo 1.8.15
|
||||
Sudo 1.8.15 September 2, 2015 Sudo 1.8.15
|
||||
|
@@ -16,7 +16,7 @@
|
||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
.\"
|
||||
.TH "SUDO_PLUGIN" "5" "August 6, 2015" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
|
||||
.TH "SUDO_PLUGIN" "5" "September 2, 2015" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
|
||||
.nh
|
||||
.if n .ad l
|
||||
.SH "NAME"
|
||||
@@ -2293,9 +2293,26 @@ struct sudo_conv_reply {
|
||||
char *reply;
|
||||
};
|
||||
|
||||
/* Conversation callback API version major/minor */
|
||||
#define SUDO_CONV_CALLBACK_VERSION_MAJOR 1
|
||||
#define SUDO_CONV_CALLBACK_VERSION_MINOR 0
|
||||
#define SUDO_CONV_CALLBACK_MKVERSION(x, y) ((x << 16) | y)
|
||||
#define SUDO_CONV_CALLBACK_VERSION \e
|
||||
SUDO_CONV_CALLBACK_MKVERSION(SUDO_CONV_CALLBACK_VERSION_MAJOR, \e
|
||||
SUDO_CONV_CALLBACK_VERSION_MINOR)
|
||||
|
||||
typedef int (*sudo_conv_callback_fn_t)(int signo, void *closure);
|
||||
struct sudo_conv_callback {
|
||||
unsigned int version;
|
||||
void *closure;
|
||||
sudo_conv_callback_fn_t on_suspend;
|
||||
sudo_conv_callback_fn_t on_resume;
|
||||
};
|
||||
|
||||
typedef int (*sudo_conv_t)(int num_msgs,
|
||||
const struct sudo_conv_message msgs[],
|
||||
struct sudo_conv_reply replies[]);
|
||||
struct sudo_conv_reply replies[],
|
||||
struct sudo_conv_callback *callback);
|
||||
|
||||
typedef int (*sudo_printf_t)(int msg_type, const char *fmt, ...);
|
||||
.RE
|
||||
@@ -2323,6 +2340,23 @@ and
|
||||
\fRstruct sudo_conv_reply\fR
|
||||
for
|
||||
each message in the conversation.
|
||||
The
|
||||
\fRstruct sudo_conv_callback\fR
|
||||
pointer, if not
|
||||
\fRNULL\fR,
|
||||
contains function pointers that are called when the
|
||||
\fBsudo\fR
|
||||
process is suspended and/or resumed during conversation input.
|
||||
The functions are passed the signal that caused
|
||||
\fBsudo\fR
|
||||
to be suspended and the
|
||||
\fIclosure\fR
|
||||
pointer.
|
||||
This allows the plugin to release resources such as locks that
|
||||
should not be held indefinitely on suspend and reacquire them
|
||||
on resume.
|
||||
Note that the functions are not actually invoked from within a signal handler.
|
||||
.PP
|
||||
The plugin is responsible for freeing the reply buffer located in each
|
||||
\fRstruct sudo_conv_reply\fR,
|
||||
if it is not
|
||||
@@ -2662,6 +2696,17 @@ The
|
||||
entry was added to the
|
||||
\fRcommand_info\fR
|
||||
list.
|
||||
.sp
|
||||
The sudo
|
||||
\fIconversation\fR
|
||||
function now takes a pointer to a
|
||||
\fRstruct sudo_conv_callback\fR
|
||||
as its fourth argument.
|
||||
The
|
||||
\fRsudo_conv_t\fR
|
||||
definition has been updated to match.
|
||||
The plugin must specify that it supports plugin API version 1.8 or higher
|
||||
to receive a conversation function pointer that supports this argument.
|
||||
.SH "SEE ALSO"
|
||||
sudo.conf(@mansectform@),
|
||||
sudoers(@mansectform@),
|
||||
|
@@ -14,7 +14,7 @@
|
||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd August 6, 2015
|
||||
.Dd September 2, 2015
|
||||
.Dt SUDO_PLUGIN @mansectform@
|
||||
.Os Sudo @PACKAGE_VERSION@
|
||||
.Sh NAME
|
||||
@@ -1999,9 +1999,26 @@ struct sudo_conv_reply {
|
||||
char *reply;
|
||||
};
|
||||
|
||||
/* Conversation callback API version major/minor */
|
||||
#define SUDO_CONV_CALLBACK_VERSION_MAJOR 1
|
||||
#define SUDO_CONV_CALLBACK_VERSION_MINOR 0
|
||||
#define SUDO_CONV_CALLBACK_MKVERSION(x, y) ((x << 16) | y)
|
||||
#define SUDO_CONV_CALLBACK_VERSION \e
|
||||
SUDO_CONV_CALLBACK_MKVERSION(SUDO_CONV_CALLBACK_VERSION_MAJOR, \e
|
||||
SUDO_CONV_CALLBACK_VERSION_MINOR)
|
||||
|
||||
typedef int (*sudo_conv_callback_fn_t)(int signo, void *closure);
|
||||
struct sudo_conv_callback {
|
||||
unsigned int version;
|
||||
void *closure;
|
||||
sudo_conv_callback_fn_t on_suspend;
|
||||
sudo_conv_callback_fn_t on_resume;
|
||||
};
|
||||
|
||||
typedef int (*sudo_conv_t)(int num_msgs,
|
||||
const struct sudo_conv_message msgs[],
|
||||
struct sudo_conv_reply replies[]);
|
||||
struct sudo_conv_reply replies[],
|
||||
struct sudo_conv_callback *callback);
|
||||
|
||||
typedef int (*sudo_printf_t)(int msg_type, const char *fmt, ...);
|
||||
.Ed
|
||||
@@ -2028,6 +2045,23 @@ and
|
||||
.Li struct sudo_conv_reply
|
||||
for
|
||||
each message in the conversation.
|
||||
The
|
||||
.Li struct sudo_conv_callback
|
||||
pointer, if not
|
||||
.Dv NULL ,
|
||||
contains function pointers that are called when the
|
||||
.Nm sudo
|
||||
process is suspended and/or resumed during conversation input.
|
||||
The functions are passed the signal that caused
|
||||
.Nm sudo
|
||||
to be suspended and the
|
||||
.Fa closure
|
||||
pointer.
|
||||
This allows the plugin to release resources such as locks that
|
||||
should not be held indefinitely on suspend and reacquire them
|
||||
on resume.
|
||||
Note that the functions are not actually invoked from within a signal handler.
|
||||
.Pp
|
||||
The plugin is responsible for freeing the reply buffer located in each
|
||||
.Li struct sudo_conv_reply ,
|
||||
if it is not
|
||||
@@ -2329,6 +2363,17 @@ The
|
||||
entry was added to the
|
||||
.Li command_info
|
||||
list.
|
||||
.Pp
|
||||
The sudo
|
||||
.Em conversation
|
||||
function now takes a pointer to a
|
||||
.Li struct sudo_conv_callback
|
||||
as its fourth argument.
|
||||
The
|
||||
.Li sudo_conv_t
|
||||
definition has been updated to match.
|
||||
The plugin must specify that it supports plugin API version 1.8 or higher
|
||||
to receive a conversation function pointer that supports this argument.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr sudo.conf @mansectform@ ,
|
||||
|
@@ -121,6 +121,7 @@ typedef void (*sudo_fatal_callback_t)(void);
|
||||
|
||||
struct sudo_conv_message;
|
||||
struct sudo_conv_reply;
|
||||
struct sudo_conv_callback;
|
||||
|
||||
__dso_public int sudo_fatal_callback_deregister_v1(sudo_fatal_callback_t func);
|
||||
__dso_public int sudo_fatal_callback_register_v1(sudo_fatal_callback_t func);
|
||||
@@ -134,7 +135,7 @@ __dso_public void sudo_warn_nodebug_v1(const char *fmt, ...) __printf0like(1, 2)
|
||||
__dso_public void sudo_warnx_nodebug_v1(const char *fmt, ...) __printflike(1, 2);
|
||||
__dso_public void sudo_vwarn_nodebug_v1(const char *fmt, va_list ap) __printf0like(1, 0);
|
||||
__dso_public void sudo_vwarnx_nodebug_v1(const char *fmt, va_list ap) __printflike(1, 0);
|
||||
__dso_public void sudo_warn_set_conversation_v1(int (*conv)(int num_msgs, const struct sudo_conv_message *msgs, struct sudo_conv_reply *replies));
|
||||
__dso_public void sudo_warn_set_conversation_v1(int (*conv)(int num_msgs, const struct sudo_conv_message *msgs, struct sudo_conv_reply *replies, struct sudo_conv_callback *callback));
|
||||
|
||||
#define sudo_fatal_callback_deregister(_a) sudo_fatal_callback_deregister_v1((_a))
|
||||
#define sudo_fatal_callback_register(_a) sudo_fatal_callback_register_v1((_a))
|
||||
@@ -148,7 +149,6 @@ __dso_public void sudo_warn_set_conversation_v1(int (*conv)(int num_msgs, const
|
||||
#define sudo_vwarn_nodebug(_a, _b) sudo_vwarn_nodebug_v1((_a), (_b))
|
||||
#define sudo_vwarnx_nodebug(_a, _b) sudo_vwarnx_nodebug_v1((_a), (_b))
|
||||
#define sudo_warn_set_conversation(_a) sudo_warn_set_conversation_v1(_a)
|
||||
#define sudo_warn_set_conversation(_a) sudo_warn_set_conversation_v1(_a)
|
||||
|
||||
#ifdef DEFAULT_TEXT_DOMAIN
|
||||
# define sudo_warn_gettext(_a) sudo_warn_gettext_v1(DEFAULT_TEXT_DOMAIN, (_a))
|
||||
|
@@ -61,8 +61,27 @@ struct sudo_conv_reply {
|
||||
char *reply;
|
||||
};
|
||||
|
||||
/* Conversation callback API version major/minor */
|
||||
#define SUDO_CONV_CALLBACK_VERSION_MAJOR 1
|
||||
#define SUDO_CONV_CALLBACK_VERSION_MINOR 0
|
||||
#define SUDO_CONV_CALLBACK_MKVERSION(x, y) ((x << 16) | y)
|
||||
#define SUDO_CONV_CALLBACK_VERSION SUDO_CONV_CALLBACK_MKVERSION(SUDO_CONV_CALLBACK_VERSION_MAJOR, SUDO_CONV_CALLBACK_VERSION_MINOR)
|
||||
|
||||
/*
|
||||
* Callback struct to be passed to the conversation function.
|
||||
* Can be used to perform operations on suspend/resume such
|
||||
* as dropping/acquiring locks.
|
||||
*/
|
||||
typedef int (*sudo_conv_callback_fn_t)(int signo, void *closure);
|
||||
struct sudo_conv_callback {
|
||||
unsigned int version;
|
||||
void *closure;
|
||||
sudo_conv_callback_fn_t on_suspend;
|
||||
sudo_conv_callback_fn_t on_resume;
|
||||
};
|
||||
|
||||
typedef int (*sudo_conv_t)(int num_msgs, const struct sudo_conv_message msgs[],
|
||||
struct sudo_conv_reply replies[]);
|
||||
struct sudo_conv_reply replies[], struct sudo_conv_callback *callback);
|
||||
typedef int (*sudo_printf_t)(int msg_type, const char *fmt, ...);
|
||||
|
||||
/*
|
||||
|
@@ -179,7 +179,7 @@ warning(int errnum, const char *fmt, va_list ap)
|
||||
}
|
||||
msgs[nmsgs].msg_type = SUDO_CONV_ERROR_MSG;
|
||||
msgs[nmsgs++].msg = "\n";
|
||||
sudo_warn_conversation(nmsgs, msgs, NULL);
|
||||
sudo_warn_conversation(nmsgs, msgs, NULL, NULL);
|
||||
if (buf != static_buf)
|
||||
free(buf);
|
||||
} else {
|
||||
|
@@ -42,7 +42,7 @@
|
||||
#include "sudo_auth.h"
|
||||
|
||||
int
|
||||
sudo_afs_verify(struct passwd *pw, char *pass, sudo_auth *auth)
|
||||
sudo_afs_verify(struct passwd *pw, char *pass, sudo_auth *auth, struct sudo_conv_callback *callback)
|
||||
{
|
||||
struct ktc_encryptionKey afs_key;
|
||||
struct ktc_token afs_token;
|
||||
|
@@ -128,7 +128,7 @@ sudo_aix_init(struct passwd *pw, sudo_auth *auth)
|
||||
}
|
||||
|
||||
int
|
||||
sudo_aix_verify(struct passwd *pw, char *prompt, sudo_auth *auth)
|
||||
sudo_aix_verify(struct passwd *pw, char *prompt, sudo_auth *auth, struct sudo_conv_callback *callback)
|
||||
{
|
||||
char *pass, *message = NULL;
|
||||
int result = 1, reenter = 0;
|
||||
@@ -137,7 +137,7 @@ sudo_aix_verify(struct passwd *pw, char *prompt, sudo_auth *auth)
|
||||
|
||||
do {
|
||||
pass = auth_getpass(prompt, def_passwd_timeout * 60,
|
||||
SUDO_CONV_PROMPT_ECHO_OFF);
|
||||
SUDO_CONV_PROMPT_ECHO_OFF, callback);
|
||||
if (pass == NULL)
|
||||
break;
|
||||
free(message);
|
||||
@@ -157,7 +157,7 @@ sudo_aix_verify(struct passwd *pw, char *prompt, sudo_auth *auth)
|
||||
msg.msg_type = SUDO_CONV_ERROR_MSG;
|
||||
msg.msg = message;
|
||||
memset(&repl, 0, sizeof(repl));
|
||||
sudo_conv(1, &msg, &repl);
|
||||
sudo_conv(1, &msg, &repl, NULL);
|
||||
}
|
||||
rval = pass ? AUTH_FAILURE : AUTH_INTR;
|
||||
}
|
||||
|
@@ -98,7 +98,7 @@ bsdauth_init(struct passwd *pw, sudo_auth *auth)
|
||||
}
|
||||
|
||||
int
|
||||
bsdauth_verify(struct passwd *pw, char *prompt, sudo_auth *auth)
|
||||
bsdauth_verify(struct passwd *pw, char *prompt, sudo_auth *auth, struct sudo_conv_callback *callback)
|
||||
{
|
||||
char *pass;
|
||||
char *s;
|
||||
@@ -121,9 +121,9 @@ bsdauth_verify(struct passwd *pw, char *prompt, sudo_auth *auth)
|
||||
* S/Key.
|
||||
*/
|
||||
if ((s = auth_challenge(as)) == NULL) {
|
||||
pass = auth_getpass(prompt, def_passwd_timeout * 60, SUDO_CONV_PROMPT_ECHO_OFF);
|
||||
pass = auth_getpass(prompt, def_passwd_timeout * 60, SUDO_CONV_PROMPT_ECHO_OFF, callback);
|
||||
} else {
|
||||
pass = auth_getpass(prompt, def_passwd_timeout * 60, SUDO_CONV_PROMPT_ECHO_OFF);
|
||||
pass = auth_getpass(prompt, def_passwd_timeout * 60, SUDO_CONV_PROMPT_ECHO_OFF, callback);
|
||||
if (pass && *pass == '\0') {
|
||||
if ((prompt = strrchr(s, '\n')))
|
||||
prompt++;
|
||||
@@ -142,7 +142,7 @@ bsdauth_verify(struct passwd *pw, char *prompt, sudo_auth *auth)
|
||||
debug_return_int(AUTH_FATAL);
|
||||
}
|
||||
pass = auth_getpass(prompt, def_passwd_timeout * 60,
|
||||
SUDO_CONV_PROMPT_ECHO_ON);
|
||||
SUDO_CONV_PROMPT_ECHO_ON, callback);
|
||||
free(s);
|
||||
}
|
||||
}
|
||||
|
@@ -59,7 +59,7 @@
|
||||
static int check_dce_status(error_status_t, char *);
|
||||
|
||||
int
|
||||
sudo_dce_verify(struct passwd *pw, char *plain_pw, sudo_auth *auth)
|
||||
sudo_dce_verify(struct passwd *pw, char *plain_pw, sudo_auth *auth, struct sudo_conv_callback *callback)
|
||||
{
|
||||
struct passwd temp_pw;
|
||||
sec_passwd_rec_t password_rec;
|
||||
|
@@ -72,7 +72,7 @@ sudo_fwtk_init(struct passwd *pw, sudo_auth *auth)
|
||||
}
|
||||
|
||||
int
|
||||
sudo_fwtk_verify(struct passwd *pw, char *prompt, sudo_auth *auth)
|
||||
sudo_fwtk_verify(struct passwd *pw, char *prompt, sudo_auth *auth, struct sudo_conv_callback *callback)
|
||||
{
|
||||
char *pass; /* Password from the user */
|
||||
char buf[SUDO_CONV_REPL_MAX + 12]; /* General prupose buffer */
|
||||
@@ -91,17 +91,17 @@ restart:
|
||||
/* Get the password/response from the user. */
|
||||
if (strncmp(resp, "challenge ", 10) == 0) {
|
||||
(void) snprintf(buf, sizeof(buf), "%s\nResponse: ", &resp[10]);
|
||||
pass = auth_getpass(buf, def_passwd_timeout * 60, SUDO_CONV_PROMPT_ECHO_OFF);
|
||||
pass = auth_getpass(buf, def_passwd_timeout * 60, SUDO_CONV_PROMPT_ECHO_OFF, callback);
|
||||
if (pass && *pass == '\0') {
|
||||
pass = auth_getpass("Response [echo on]: ",
|
||||
def_passwd_timeout * 60, SUDO_CONV_PROMPT_ECHO_ON);
|
||||
def_passwd_timeout * 60, SUDO_CONV_PROMPT_ECHO_ON, callback);
|
||||
}
|
||||
} else if (strncmp(resp, "chalnecho ", 10) == 0) {
|
||||
pass = auth_getpass(&resp[10], def_passwd_timeout * 60,
|
||||
SUDO_CONV_PROMPT_ECHO_OFF);
|
||||
SUDO_CONV_PROMPT_ECHO_OFF, callback);
|
||||
} else if (strncmp(resp, "password", 8) == 0) {
|
||||
pass = auth_getpass(prompt, def_passwd_timeout * 60,
|
||||
SUDO_CONV_PROMPT_ECHO_OFF);
|
||||
SUDO_CONV_PROMPT_ECHO_OFF, callback);
|
||||
} else if (strncmp(resp, "display ", 8) == 0) {
|
||||
fprintf(stderr, "%s\n", &resp[8]);
|
||||
strlcpy(buf, "response dummy", sizeof(buf));
|
||||
|
@@ -180,7 +180,7 @@ done:
|
||||
|
||||
#ifdef HAVE_KRB5_VERIFY_USER
|
||||
int
|
||||
sudo_krb5_verify(struct passwd *pw, char *pass, sudo_auth *auth)
|
||||
sudo_krb5_verify(struct passwd *pw, char *pass, sudo_auth *auth, struct sudo_conv_callback *callback)
|
||||
{
|
||||
krb5_context sudo_context;
|
||||
krb5_principal princ;
|
||||
|
@@ -71,7 +71,8 @@
|
||||
|
||||
static int converse(int, PAM_CONST struct pam_message **,
|
||||
struct pam_response **, void *);
|
||||
static struct pam_conv pam_conv = { converse, NULL };
|
||||
static struct sudo_conv_callback *conv_callback;
|
||||
static struct pam_conv pam_conv = { converse, &conv_callback };
|
||||
static char *def_prompt = PASSPROMPT;
|
||||
static bool getpass_error;
|
||||
static pam_handle_t *pamh;
|
||||
@@ -137,7 +138,7 @@ sudo_pam_init(struct passwd *pw, sudo_auth *auth)
|
||||
}
|
||||
|
||||
int
|
||||
sudo_pam_verify(struct passwd *pw, char *prompt, sudo_auth *auth)
|
||||
sudo_pam_verify(struct passwd *pw, char *prompt, sudo_auth *auth, struct sudo_conv_callback *callback)
|
||||
{
|
||||
const char *s;
|
||||
int *pam_status = (int *) auth->data;
|
||||
@@ -145,6 +146,7 @@ sudo_pam_verify(struct passwd *pw, char *prompt, sudo_auth *auth)
|
||||
|
||||
def_prompt = prompt; /* for converse */
|
||||
getpass_error = false; /* set by converse if user presses ^C */
|
||||
conv_callback = callback; /* passed to conversation function */
|
||||
|
||||
/* PAM_SILENT prevents the authentication service from generating output. */
|
||||
*pam_status = pam_authenticate(pamh, PAM_SILENT);
|
||||
@@ -375,7 +377,7 @@ sudo_pam_end_session(struct passwd *pw, sudo_auth *auth)
|
||||
*/
|
||||
static int
|
||||
converse(int num_msg, PAM_CONST struct pam_message **msg,
|
||||
struct pam_response **response, void *appdata_ptr)
|
||||
struct pam_response **response, void *callback)
|
||||
{
|
||||
struct pam_response *pr;
|
||||
PAM_CONST struct pam_message *pm;
|
||||
@@ -427,7 +429,7 @@ converse(int num_msg, PAM_CONST struct pam_message **msg,
|
||||
prompt = pm->msg;
|
||||
}
|
||||
/* Read the password unless interrupted. */
|
||||
pass = auth_getpass(prompt, def_passwd_timeout * 60, type);
|
||||
pass = auth_getpass(prompt, def_passwd_timeout * 60, type, callback);
|
||||
if (pass == NULL) {
|
||||
/* Error (or ^C) reading password, don't try again. */
|
||||
getpass_error = true;
|
||||
|
@@ -54,7 +54,7 @@ sudo_passwd_init(struct passwd *pw, sudo_auth *auth)
|
||||
}
|
||||
|
||||
int
|
||||
sudo_passwd_verify(struct passwd *pw, char *pass, sudo_auth *auth)
|
||||
sudo_passwd_verify(struct passwd *pw, char *pass, sudo_auth *auth, struct sudo_conv_callback *callback)
|
||||
{
|
||||
char sav, *epass;
|
||||
char *pw_epasswd = auth->data;
|
||||
|
@@ -124,7 +124,7 @@ sudo_rfc1938_setup(struct passwd *pw, char **promptp, sudo_auth *auth)
|
||||
}
|
||||
|
||||
int
|
||||
sudo_rfc1938_verify(struct passwd *pw, char *pass, sudo_auth *auth)
|
||||
sudo_rfc1938_verify(struct passwd *pw, char *pass, sudo_auth *auth, struct sudo_conv_callback *callback)
|
||||
{
|
||||
debug_decl(sudo_rfc1938_verify, SUDOERS_DEBUG_AUTH)
|
||||
|
||||
|
@@ -65,7 +65,7 @@ sudo_secureware_init(struct passwd *pw, sudo_auth *auth)
|
||||
}
|
||||
|
||||
int
|
||||
sudo_secureware_verify(struct passwd *pw, char *pass, sudo_auth *auth)
|
||||
sudo_secureware_verify(struct passwd *pw, char *pass, sudo_auth *auth, struct sudo_conv_callback *callback)
|
||||
{
|
||||
char *pw_epasswd = auth->data;
|
||||
char *epass = NULL;
|
||||
|
@@ -139,14 +139,14 @@ sudo_securid_setup(struct passwd *pw, char **promptp, sudo_auth *auth)
|
||||
* incorrect authentication, fatal on errors
|
||||
*/
|
||||
int
|
||||
sudo_securid_verify(struct passwd *pw, char *pass, sudo_auth *auth)
|
||||
sudo_securid_verify(struct passwd *pw, char *pass, sudo_auth *auth, struct sudo_conv_callback *callback)
|
||||
{
|
||||
SDI_HANDLE *sd = (SDI_HANDLE *) auth->data;
|
||||
int rval;
|
||||
debug_decl(sudo_securid_verify, SUDOERS_DEBUG_AUTH)
|
||||
|
||||
pass = auth_getpass("Enter your PASSCODE: ",
|
||||
def_passwd_timeout * 60, SUDO_CONV_PROMPT_ECHO_OFF);
|
||||
def_passwd_timeout * 60, SUDO_CONV_PROMPT_ECHO_OFF, callback);
|
||||
|
||||
/* Have ACE verify password */
|
||||
switch (SD_Check(*sd, pass, pw->pw_name)) {
|
||||
@@ -181,7 +181,7 @@ sudo_securid_verify(struct passwd *pw, char *pass, sudo_auth *auth)
|
||||
!!! ATTENTION !!!\n\
|
||||
Wait for the token code to change, \n\
|
||||
then enter the new token code.\n", \
|
||||
def_passwd_timeout * 60, SUDO_CONV_PROMPT_ECHO_OFF);
|
||||
def_passwd_timeout * 60, SUDO_CONV_PROMPT_ECHO_OFF, callback);
|
||||
|
||||
if (SD_Next(*sd, pass) == ACM_OK) {
|
||||
rval = AUTH_SUCCESS;
|
||||
|
@@ -126,7 +126,7 @@ sudo_sia_setup(struct passwd *pw, char **promptp, sudo_auth *auth)
|
||||
}
|
||||
|
||||
int
|
||||
sudo_sia_verify(struct passwd *pw, char *prompt, sudo_auth *auth)
|
||||
sudo_sia_verify(struct passwd *pw, char *prompt, sudo_auth *auth, struct sudo_conv_callback *callback)
|
||||
{
|
||||
SIAENTITY *siah = (SIAENTITY *) auth->data;
|
||||
debug_decl(sudo_sia_verify, SUDOERS_DEBUG_AUTH)
|
||||
|
@@ -209,7 +209,8 @@ user_interrupted(void)
|
||||
* Returns true if verified, false if not or -1 on error.
|
||||
*/
|
||||
int
|
||||
verify_user(struct passwd *pw, char *prompt, int validated)
|
||||
verify_user(struct passwd *pw, char *prompt, int validated,
|
||||
struct sudo_conv_callback *callback)
|
||||
{
|
||||
unsigned int ntries;
|
||||
int rval, status, success = AUTH_FAILURE;
|
||||
@@ -281,7 +282,7 @@ verify_user(struct passwd *pw, char *prompt, int validated)
|
||||
p = prompt;
|
||||
} else {
|
||||
p = auth_getpass(prompt, def_passwd_timeout * 60,
|
||||
SUDO_CONV_PROMPT_ECHO_OFF);
|
||||
SUDO_CONV_PROMPT_ECHO_OFF, callback);
|
||||
if (p == NULL)
|
||||
break;
|
||||
}
|
||||
@@ -291,7 +292,7 @@ verify_user(struct passwd *pw, char *prompt, int validated)
|
||||
if (IS_DISABLED(auth))
|
||||
continue;
|
||||
|
||||
success = auth->status = (auth->verify)(pw, p, auth);
|
||||
success = auth->status = (auth->verify)(pw, p, auth, callback);
|
||||
if (success != AUTH_FAILURE)
|
||||
break;
|
||||
}
|
||||
@@ -387,7 +388,8 @@ sudo_auth_end_session(struct passwd *pw)
|
||||
}
|
||||
|
||||
char *
|
||||
auth_getpass(const char *prompt, int timeout, int type)
|
||||
auth_getpass(const char *prompt, int timeout, int type,
|
||||
struct sudo_conv_callback *callback)
|
||||
{
|
||||
struct sudo_conv_message msg;
|
||||
struct sudo_conv_reply repl;
|
||||
@@ -415,7 +417,7 @@ auth_getpass(const char *prompt, int timeout, int type)
|
||||
msg.timeout = def_passwd_timeout * 60;
|
||||
msg.msg = prompt;
|
||||
memset(&repl, 0, sizeof(repl));
|
||||
sudo_conv(1, &msg, &repl);
|
||||
sudo_conv(1, &msg, &repl, callback);
|
||||
/* XXX - check for ENOTTY? */
|
||||
|
||||
/* Restore previous signal mask. */
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2005, 2007-2012 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
* Copyright (c) 1999-2005, 2007-2015 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
|
||||
@@ -30,7 +30,7 @@ typedef struct sudo_auth {
|
||||
void *data; /* method-specific data pointer */
|
||||
int (*init)(struct passwd *pw, struct sudo_auth *auth);
|
||||
int (*setup)(struct passwd *pw, char **prompt, struct sudo_auth *auth);
|
||||
int (*verify)(struct passwd *pw, char *p, struct sudo_auth *auth);
|
||||
int (*verify)(struct passwd *pw, char *p, struct sudo_auth *auth, struct sudo_conv_callback *callback);
|
||||
int (*cleanup)(struct passwd *pw, struct sudo_auth *auth);
|
||||
int (*begin_session)(struct passwd *pw, char **user_env[], struct sudo_auth *auth);
|
||||
int (*end_session)(struct passwd *pw, struct sudo_auth *auth);
|
||||
@@ -47,47 +47,48 @@ typedef struct sudo_auth {
|
||||
#define IS_ONEANDONLY(x) ((x)->flags & FLAG_ONEANDONLY)
|
||||
|
||||
/* Like tgetpass() but uses conversation function */
|
||||
char *auth_getpass(const char *prompt, int timeout, int type);
|
||||
char *auth_getpass(const char *prompt, int timeout, int type,
|
||||
struct sudo_conv_callback *callback);
|
||||
|
||||
/* Pointer to conversation function to use with auth_getpass(). */
|
||||
extern sudo_conv_t sudo_conv;
|
||||
|
||||
/* Prototypes for standalone methods */
|
||||
int bsdauth_init(struct passwd *pw, sudo_auth *auth);
|
||||
int bsdauth_verify(struct passwd *pw, char *prompt, sudo_auth *auth);
|
||||
int bsdauth_verify(struct passwd *pw, char *prompt, sudo_auth *auth, struct sudo_conv_callback *callback);
|
||||
int bsdauth_cleanup(struct passwd *pw, sudo_auth *auth);
|
||||
int sudo_aix_init(struct passwd *pw, sudo_auth *auth);
|
||||
int sudo_aix_verify(struct passwd *pw, char *pass, sudo_auth *auth);
|
||||
int sudo_aix_verify(struct passwd *pw, char *pass, sudo_auth *auth, struct sudo_conv_callback *callback);
|
||||
int sudo_aix_cleanup(struct passwd *pw, sudo_auth *auth);
|
||||
int sudo_fwtk_init(struct passwd *pw, sudo_auth *auth);
|
||||
int sudo_fwtk_verify(struct passwd *pw, char *prompt, sudo_auth *auth);
|
||||
int sudo_fwtk_verify(struct passwd *pw, char *prompt, sudo_auth *auth, struct sudo_conv_callback *callback);
|
||||
int sudo_fwtk_cleanup(struct passwd *pw, sudo_auth *auth);
|
||||
int sudo_pam_init(struct passwd *pw, sudo_auth *auth);
|
||||
int sudo_pam_verify(struct passwd *pw, char *prompt, sudo_auth *auth);
|
||||
int sudo_pam_verify(struct passwd *pw, char *prompt, sudo_auth *auth, struct sudo_conv_callback *callback);
|
||||
int sudo_pam_cleanup(struct passwd *pw, sudo_auth *auth);
|
||||
int sudo_pam_begin_session(struct passwd *pw, char **user_env[], sudo_auth *auth);
|
||||
int sudo_pam_end_session(struct passwd *pw, sudo_auth *auth);
|
||||
int sudo_securid_init(struct passwd *pw, sudo_auth *auth);
|
||||
int sudo_securid_setup(struct passwd *pw, char **prompt, sudo_auth *auth);
|
||||
int sudo_securid_verify(struct passwd *pw, char *pass, sudo_auth *auth);
|
||||
int sudo_securid_verify(struct passwd *pw, char *pass, sudo_auth *auth, struct sudo_conv_callback *callback);
|
||||
int sudo_sia_setup(struct passwd *pw, char **prompt, sudo_auth *auth);
|
||||
int sudo_sia_verify(struct passwd *pw, char *prompt, sudo_auth *auth);
|
||||
int sudo_sia_verify(struct passwd *pw, char *prompt, sudo_auth *auth, struct sudo_conv_callback *callback);
|
||||
int sudo_sia_cleanup(struct passwd *pw, sudo_auth *auth);
|
||||
|
||||
/* Prototypes for normal methods */
|
||||
int sudo_afs_verify(struct passwd *pw, char *pass, sudo_auth *auth);
|
||||
int sudo_dce_verify(struct passwd *pw, char *pass, sudo_auth *auth);
|
||||
int sudo_afs_verify(struct passwd *pw, char *pass, sudo_auth *auth, struct sudo_conv_callback *callback);
|
||||
int sudo_dce_verify(struct passwd *pw, char *pass, sudo_auth *auth, struct sudo_conv_callback *callback);
|
||||
int sudo_krb5_init(struct passwd *pw, sudo_auth *auth);
|
||||
int sudo_krb5_setup(struct passwd *pw, char **prompt, sudo_auth *auth);
|
||||
int sudo_krb5_verify(struct passwd *pw, char *pass, sudo_auth *auth);
|
||||
int sudo_krb5_verify(struct passwd *pw, char *pass, sudo_auth *auth, struct sudo_conv_callback *callback);
|
||||
int sudo_krb5_cleanup(struct passwd *pw, sudo_auth *auth);
|
||||
int sudo_passwd_init(struct passwd *pw, sudo_auth *auth);
|
||||
int sudo_passwd_verify(struct passwd *pw, char *pass, sudo_auth *auth);
|
||||
int sudo_passwd_verify(struct passwd *pw, char *pass, sudo_auth *auth, struct sudo_conv_callback *callback);
|
||||
int sudo_passwd_cleanup(struct passwd *pw, sudo_auth *auth);
|
||||
int sudo_rfc1938_setup(struct passwd *pw, char **prompt, sudo_auth *auth);
|
||||
int sudo_rfc1938_verify(struct passwd *pw, char *pass, sudo_auth *auth);
|
||||
int sudo_rfc1938_verify(struct passwd *pw, char *pass, sudo_auth *auth, struct sudo_conv_callback *callback);
|
||||
int sudo_secureware_init(struct passwd *pw, sudo_auth *auth);
|
||||
int sudo_secureware_verify(struct passwd *pw, char *pass, sudo_auth *auth);
|
||||
int sudo_secureware_verify(struct passwd *pw, char *pass, sudo_auth *auth, struct sudo_conv_callback *callback);
|
||||
int sudo_secureware_cleanup(struct passwd *pw, sudo_auth *auth);
|
||||
|
||||
/* Fields: name, flags, init, setup, verify, cleanup, begin_sess, end_sess */
|
||||
|
@@ -96,7 +96,7 @@ check_user_interactive(int validated, int mode, struct passwd *auth_pw)
|
||||
if (prompt == NULL)
|
||||
goto done;
|
||||
|
||||
rval = verify_user(auth_pw, prompt, validated);
|
||||
rval = verify_user(auth_pw, prompt, validated, NULL); /* XXX */
|
||||
if (rval == true && lectured) {
|
||||
if (set_lectured() == -1)
|
||||
rval = -1;
|
||||
@@ -192,7 +192,7 @@ display_lecture(int status)
|
||||
buf[nread] = '\0';
|
||||
msg.msg_type = SUDO_CONV_ERROR_MSG;
|
||||
msg.msg = buf;
|
||||
sudo_conv(1, &msg, &repl);
|
||||
sudo_conv(1, &msg, &repl, NULL);
|
||||
}
|
||||
fclose(fp);
|
||||
} else {
|
||||
@@ -203,7 +203,7 @@ display_lecture(int status)
|
||||
" #1) Respect the privacy of others.\n"
|
||||
" #2) Think before you type.\n"
|
||||
" #3) With great power comes great responsibility.\n\n");
|
||||
sudo_conv(1, &msg, &repl);
|
||||
sudo_conv(1, &msg, &repl, NULL);
|
||||
}
|
||||
debug_return_bool(true);
|
||||
}
|
||||
|
@@ -261,7 +261,7 @@ output(const char *buf)
|
||||
msg.msg_type = SUDO_CONV_INFO_MSG;
|
||||
msg.msg = buf;
|
||||
memset(&repl, 0, sizeof(repl));
|
||||
if (sudo_conv(1, &msg, &repl) == -1)
|
||||
if (sudo_conv(1, &msg, &repl, NULL) == -1)
|
||||
debug_return_int(0);
|
||||
debug_return_int(strlen(buf));
|
||||
}
|
||||
|
@@ -243,7 +243,7 @@ int set_lectured(void);
|
||||
|
||||
/* sudo_auth.c */
|
||||
bool sudo_auth_needs_end_session(void);
|
||||
int verify_user(struct passwd *pw, char *prompt, int validated);
|
||||
int verify_user(struct passwd *pw, char *prompt, int validated, struct sudo_conv_callback *callback);
|
||||
int sudo_auth_begin_session(struct passwd *pw, char **user_env[]);
|
||||
int sudo_auth_end_session(struct passwd *pw);
|
||||
int sudo_auth_init(struct passwd *pw);
|
||||
|
@@ -43,7 +43,7 @@ extern int tgetpass_flags; /* XXX */
|
||||
*/
|
||||
int
|
||||
sudo_conversation(int num_msgs, const struct sudo_conv_message msgs[],
|
||||
struct sudo_conv_reply replies[])
|
||||
struct sudo_conv_reply replies[], struct sudo_conv_callback *callback)
|
||||
{
|
||||
struct sudo_conv_reply *repl;
|
||||
const struct sudo_conv_message *msg;
|
||||
@@ -65,7 +65,7 @@ sudo_conversation(int num_msgs, const struct sudo_conv_message msgs[],
|
||||
if (ISSET(msg->msg_type, SUDO_CONV_PROMPT_ECHO_OK))
|
||||
SET(flags, TGP_NOECHO_TRY);
|
||||
/* Read the password unless interrupted. */
|
||||
pass = tgetpass(msg->msg, msg->timeout, flags);
|
||||
pass = tgetpass(msg->msg, msg->timeout, flags, callback);
|
||||
if (pass == NULL)
|
||||
goto err;
|
||||
if ((repl->reply = strdup(pass)) == NULL) {
|
||||
@@ -103,6 +103,13 @@ err:
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
sudo_conversation_1_7(int num_msgs, const struct sudo_conv_message msgs[],
|
||||
struct sudo_conv_reply replies[])
|
||||
{
|
||||
return sudo_conversation(num_msgs, msgs, replies, NULL);
|
||||
}
|
||||
|
||||
int
|
||||
sudo_conversation_printf(int msg_type, const char *fmt, ...)
|
||||
{
|
||||
|
@@ -1187,7 +1187,7 @@ policy_open(struct plugin_container *plugin, struct sudo_settings *settings,
|
||||
case SUDO_API_MKVERSION(1, 0):
|
||||
case SUDO_API_MKVERSION(1, 1):
|
||||
rval = plugin->u.policy_1_0->open(plugin->u.io_1_0->version,
|
||||
sudo_conversation, sudo_conversation_printf, plugin_settings,
|
||||
sudo_conversation_1_7, sudo_conversation_printf, plugin_settings,
|
||||
user_info, user_env);
|
||||
break;
|
||||
default:
|
||||
@@ -1346,12 +1346,12 @@ iolog_open(struct plugin_container *plugin, struct sudo_settings *settings,
|
||||
switch (plugin->u.generic->version) {
|
||||
case SUDO_API_MKVERSION(1, 0):
|
||||
rval = plugin->u.io_1_0->open(plugin->u.io_1_0->version,
|
||||
sudo_conversation, sudo_conversation_printf, plugin_settings,
|
||||
sudo_conversation_1_7, sudo_conversation_printf, plugin_settings,
|
||||
user_info, argc, argv, user_env);
|
||||
break;
|
||||
case SUDO_API_MKVERSION(1, 1):
|
||||
rval = plugin->u.io_1_1->open(plugin->u.io_1_1->version,
|
||||
sudo_conversation, sudo_conversation_printf, plugin_settings,
|
||||
sudo_conversation_1_7, sudo_conversation_printf, plugin_settings,
|
||||
user_info, command_info, argc, argv, user_env);
|
||||
break;
|
||||
default:
|
||||
|
@@ -183,7 +183,8 @@ struct timeval;
|
||||
void cleanup(int);
|
||||
|
||||
/* tgetpass.c */
|
||||
char *tgetpass(const char *, int, int);
|
||||
char *tgetpass(const char *prompt, int timeout, int flags,
|
||||
struct sudo_conv_callback *callback);
|
||||
|
||||
/* exec.c */
|
||||
int pipe_nonblock(int fds[2]);
|
||||
|
@@ -26,13 +26,16 @@ struct generic_plugin {
|
||||
/* the rest depends on the type... */
|
||||
};
|
||||
|
||||
typedef int (*sudo_conv_1_7_t)(int num_msgs,
|
||||
const struct sudo_conv_message msgs[], struct sudo_conv_reply replies[]);
|
||||
|
||||
/*
|
||||
* Backwards-compatible structures for API bumps.
|
||||
*/
|
||||
struct policy_plugin_1_0 {
|
||||
unsigned int type;
|
||||
unsigned int version;
|
||||
int (*open)(unsigned int version, sudo_conv_t conversation,
|
||||
int (*open)(unsigned int version, sudo_conv_1_7_t conversation,
|
||||
sudo_printf_t sudo_printf, char * const settings[],
|
||||
char * const user_info[], char * const user_env[]);
|
||||
void (*close)(int exit_status, int error); /* wait status or error */
|
||||
@@ -49,7 +52,7 @@ struct policy_plugin_1_0 {
|
||||
struct io_plugin_1_0 {
|
||||
unsigned int type;
|
||||
unsigned int version;
|
||||
int (*open)(unsigned int version, sudo_conv_t conversation,
|
||||
int (*open)(unsigned int version, sudo_conv_1_7_t conversation,
|
||||
sudo_printf_t sudo_printf, char * const settings[],
|
||||
char * const user_info[], int argc, char * const argv[],
|
||||
char * const user_env[]);
|
||||
@@ -64,7 +67,7 @@ struct io_plugin_1_0 {
|
||||
struct io_plugin_1_1 {
|
||||
unsigned int type;
|
||||
unsigned int version;
|
||||
int (*open)(unsigned int version, sudo_conv_t conversation,
|
||||
int (*open)(unsigned int version, sudo_conv_1_7_t conversation,
|
||||
sudo_printf_t sudo_printf, char * const settings[],
|
||||
char * const user_info[], char * const command_info[],
|
||||
int argc, char * const argv[], char * const user_env[]);
|
||||
@@ -103,6 +106,8 @@ extern struct plugin_container policy_plugin;
|
||||
extern struct plugin_container_list io_plugins;
|
||||
|
||||
int sudo_conversation(int num_msgs, const struct sudo_conv_message msgs[],
|
||||
struct sudo_conv_reply replies[], struct sudo_conv_callback *callback);
|
||||
int sudo_conversation_1_7(int num_msgs, const struct sudo_conv_message msgs[],
|
||||
struct sudo_conv_reply replies[]);
|
||||
int sudo_conversation_printf(int msg_type, const char *fmt, ...);
|
||||
|
||||
|
@@ -55,7 +55,8 @@ static char *sudo_askpass(const char *, const char *);
|
||||
* Like getpass(3) but with timeout and echo flags.
|
||||
*/
|
||||
char *
|
||||
tgetpass(const char *prompt, int timeout, int flags)
|
||||
tgetpass(const char *prompt, int timeout, int flags,
|
||||
struct sudo_conv_callback *callback)
|
||||
{
|
||||
sigaction_t sa, savealrm, saveint, savehup, savequit, saveterm;
|
||||
sigaction_t savetstp, savettin, savettou, savepipe;
|
||||
@@ -173,11 +174,21 @@ restore:
|
||||
*/
|
||||
for (i = 0; i < NSIG; i++) {
|
||||
if (signo[i]) {
|
||||
switch (i) {
|
||||
case SIGTSTP:
|
||||
case SIGTTIN:
|
||||
case SIGTTOU:
|
||||
if (callback != NULL && callback->on_suspend != NULL)
|
||||
callback->on_suspend(i, callback->closure);
|
||||
break;
|
||||
}
|
||||
kill(getpid(), i);
|
||||
switch (i) {
|
||||
case SIGTSTP:
|
||||
case SIGTTIN:
|
||||
case SIGTTOU:
|
||||
if (callback != NULL && callback->on_resume != NULL)
|
||||
callback->on_resume(i, callback->closure);
|
||||
need_restart = 1;
|
||||
break;
|
||||
}
|
||||
|
Reference in New Issue
Block a user