rewrite errpipe callbacks

This commit is contained in:
Todd C. Miller
2017-04-20 16:12:53 -06:00
parent c2176c32a7
commit c60259bd63
2 changed files with 59 additions and 63 deletions

View File

@@ -301,46 +301,44 @@ static void
mon_errpipe_cb(int fd, int what, void *v) mon_errpipe_cb(int fd, int what, void *v)
{ {
struct monitor_closure *mc = v; struct monitor_closure *mc = v;
ssize_t n; ssize_t nread;
int errval; int errval;
debug_decl(mon_errpipe_cb, SUDO_DEBUG_EXEC); debug_decl(mon_errpipe_cb, SUDO_DEBUG_EXEC);
/* read errno from child or EOF when command is executed. */ /*
n = read(fd, &errval, sizeof(errval)); * Read errno from child or EOF when command is executed.
switch (n) { * Note that the error pipe is *blocking*.
*/
do {
nread = read(fd, &errval, sizeof(errval));
} while (nread == -1 && errno == EINTR);
switch (nread) {
case -1: case -1:
switch (errno) { if (errno != EAGAIN) {
case EINTR: if (mc->cstat->val == CMD_INVALID) {
/* got a signal, restart loop to service it. */ /* XXX - need a way to distinguish non-exec error. */
sudo_ev_loopcontinue(mc->evbase); mc->cstat->type = CMD_ERRNO;
break; mc->cstat->val = errno;
case EAGAIN: }
/* not ready after all... */ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
break; "%s: failed to read error pipe", __func__);
default:
sudo_debug_printf(SUDO_DEBUG_ERROR,
"failed to read error pipe: %s", strerror(errno));
mc->cstat->type = CMD_ERRNO;
mc->cstat->val = errno;
sudo_ev_loopbreak(mc->evbase); sudo_ev_loopbreak(mc->evbase);
break;
} }
break; break;
case 0:
/*
* We get EOF when the command is executed and the other
* end of the error pipe is closed. Just remove the event.
*/
sudo_debug_printf(SUDO_DEBUG_INFO, "EOF on error pipe, removing event");
sudo_ev_del(mc->evbase, mc->errpipe_event);
break;
default: default:
/* Errno value when child is unable to execute command. */ if (nread == 0) {
sudo_debug_printf(SUDO_DEBUG_INFO, "errno from child: %s", /* The error pipe closes when the command is executed. */
strerror(errval)); sudo_debug_printf(SUDO_DEBUG_INFO, "EOF on error pipe");
mc->cstat->type = CMD_ERRNO; } else {
mc->cstat->val = errval; /* Errno value when child is unable to execute command. */
sudo_debug_printf(SUDO_DEBUG_INFO, "errno from child: %s",
strerror(errval));
mc->cstat->type = CMD_ERRNO;
mc->cstat->val = errval;
}
sudo_ev_del(mc->evbase, mc->errpipe_event); sudo_ev_del(mc->evbase, mc->errpipe_event);
close(fd);
break; break;
} }
debug_return; debug_return;

View File

@@ -56,46 +56,44 @@ static void
errpipe_cb(int fd, int what, void *v) errpipe_cb(int fd, int what, void *v)
{ {
struct exec_closure_nopty *ec = v; struct exec_closure_nopty *ec = v;
ssize_t n; ssize_t nread;
int errval; int errval;
debug_decl(errpipe_cb, SUDO_DEBUG_EXEC) debug_decl(errpipe_cb, SUDO_DEBUG_EXEC);
/* read errno from child or EOF when command is executed. */ /*
n = read(fd, &errval, sizeof(errval)); * Read errno from child or EOF when command is executed.
switch (n) { * Note that the error pipe is *blocking*.
*/
do {
nread = read(fd, &errval, sizeof(errval));
} while (nread == -1 && errno == EINTR);
switch (nread) {
case -1: case -1:
switch (errno) { if (errno != EAGAIN) {
case EINTR: if (ec->cstat->val == CMD_INVALID) {
/* got a signal, restart loop to service it. */ /* XXX - need a way to distinguish non-exec error. */
sudo_ev_loopcontinue(ec->evbase); ec->cstat->type = CMD_ERRNO;
break; ec->cstat->val = errno;
case EAGAIN: }
/* not ready after all... */ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
break; "%s: failed to read error pipe", __func__);
default:
sudo_debug_printf(SUDO_DEBUG_ERROR,
"failed to read error pipe: %s", strerror(errno));
ec->cstat->type = CMD_ERRNO;
ec->cstat->val = errno;
sudo_ev_loopbreak(ec->evbase); sudo_ev_loopbreak(ec->evbase);
break;
} }
break; break;
case 0:
/*
* We get EOF when the command is executed and the other
* end of the error pipe is closed. Just remove the event.
*/
sudo_debug_printf(SUDO_DEBUG_INFO, "EOF on error pipe, removing event");
sudo_ev_del(ec->evbase, ec->errpipe_event);
break;
default: default:
/* Errno value when child is unable to execute command. */ if (nread == 0) {
sudo_debug_printf(SUDO_DEBUG_INFO, "errno from child: %s", /* The error pipe closes when the command is executed. */
strerror(errval)); sudo_debug_printf(SUDO_DEBUG_INFO, "EOF on error pipe");
ec->cstat->type = CMD_ERRNO; } else {
ec->cstat->val = errval; /* Errno value when child is unable to execute command. */
sudo_debug_printf(SUDO_DEBUG_INFO, "errno from child: %s",
strerror(errval));
ec->cstat->type = CMD_ERRNO;
ec->cstat->val = errval;
}
sudo_ev_del(ec->evbase, ec->errpipe_event); sudo_ev_del(ec->evbase, ec->errpipe_event);
close(fd);
break; break;
} }
debug_return; debug_return;