fall back on exec_nopty() even if the policy plugin requested a pty.
We never allocate a pty when sudo is not run from a terminal anyway.
}
/*
- * If we have an I/O plugin or the policy plugin has requested one, we
- * need to allocate a pty.
+ * Run the command in a new pty if there is an I/O plugin or the policy
+ * has requested a pty. If /dev/tty is unavailable and no I/O plugin
+ * is configured, this returns false and we run the command without a pty.
*/
if (!TAILQ_EMPTY(&io_plugins) || ISSET(details->flags, CD_USE_PTY)) {
- /*
- * Run the command in a new pty, wait for it to finish and
- * send the plugin the exit status.
- */
- exec_pty(details, cstat);
- } else if (!ISSET(details->flags, CD_SET_TIMEOUT|CD_SUDOEDIT) &&
+ if (exec_pty(details, cstat))
+ goto done;
+ }
+
+ /*
+ * If we are not running the command in a pty, we were not invoked
+ * as sudoedit, there is no command timeout and there is no close
+ * function, just exec directly. Only returns on error.
+ */
+ if (!ISSET(details->flags, CD_SET_TIMEOUT|CD_SUDOEDIT) &&
policy_plugin.u.policy->close == NULL) {
- /*
- * If we are not running the command in a pty, we were not invoked
- * as sudoedit, there is no command timeout and there is no close
- * function, just exec directly. Only returns on error.
- */
if (!sudo_terminated(cstat)) {
exec_cmnd(details, -1);
cstat->type = CMD_ERRNO;
cstat->val = errno;
}
- } else {
- /*
- * No pty but we need to wait for the command to finish to
- * send the plugin the exit status.
- */
- exec_nopty(details, cstat);
+ goto done;
}
+
+ /*
+ * Run the command in the existing tty (if any) and wait for it to finish.
+ */
+ exec_nopty(details, cstat);
+
+done:
+ /* The caller will run any plugin close functions. */
debug_return_int(cstat->type == CMD_ERRNO ? -1 : 0);
}
/*
* Execute a command and wait for it to finish.
*/
-int
+void
exec_nopty(struct command_details *details, struct command_status *cstat)
{
struct exec_closure_nopty ec = { 0 };
/* Check for early termination or suspend signals before we fork. */
if (sudo_terminated(cstat)) {
sigprocmask(SIG_SETMASK, &oset, NULL);
- debug_return_int(0);
+ debug_return;
}
ec.cmnd_pid = sudo_debug_fork();
/* Free things up. */
free_exec_closure_nopty(&ec);
- debug_return_int(cstat->type == CMD_ERRNO ? -1 : 0);
+ debug_return;
}
/*
* This is a little bit tricky due to how POSIX job control works and
* we fact that we have two different controlling terminals to deal with.
*/
-int
+bool
exec_pty(struct command_details *details, struct command_status *cstat)
{
int io_pipe[3][2] = { { -1, -1 }, { -1, -1 }, { -1, -1 } };
if (pty_setup(details->euid, user_details.tty)) {
if (ISSET(details->flags, CD_SET_UTMP))
utmp_user = details->utmp_user ? details->utmp_user : user_details.username;
+ } else if (TAILQ_EMPTY(&io_plugins)) {
+ /* Not logging I/O and didn't allocate a pty. */
+ debug_return_bool(false);
}
/*
/* Check for early termination or suspend signals before we fork. */
if (sudo_terminated(cstat)) {
sigprocmask(SIG_SETMASK, &oset, NULL);
- debug_return_int(0);
+ debug_return_int(true);
}
ec.monitor_pid = sudo_debug_fork();
TAILQ_FOREACH_SAFE(sigfwd, &ec.sigfwd_list, entries, sigfwd_next) {
free(sigfwd);
}
- debug_return_int(cstat->type == CMD_ERRNO ? -1 : 0);
+ debug_return_bool(true);
}
/*
char **disable_execute(char *envp[], const char *dso);
/* exec_nopty.c */
-int exec_nopty(struct command_details *details, struct command_status *cstat);
+void exec_nopty(struct command_details *details, struct command_status *cstat);
/* exec_pty.c */
-int exec_pty(struct command_details *details, struct command_status *cstat);
+bool exec_pty(struct command_details *details, struct command_status *cstat);
void pty_cleanup(void);
int pty_make_controlling(void);
extern int io_fds[6];