summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--cli-chansession.c11
-rw-r--r--common-channel.c5
-rw-r--r--svr-chansession.c22
3 files changed, 23 insertions, 15 deletions
diff --git a/cli-chansession.c b/cli-chansession.c
index fee8a22..0f0d07a 100644
--- a/cli-chansession.c
+++ b/cli-chansession.c
@@ -64,16 +64,17 @@ static void cli_chansessreq(struct Channel *channel) {
type = buf_getstring(ses.payload, NULL);
wantreply = buf_getbool(ses.payload);
- if (strcmp(type, "exit-status") != 0) {
+ if (strcmp(type, "exit-status") == 0) {
+ cli_ses.retval = buf_getint(ses.payload);
+ TRACE(("got exit-status of '%d'", cli_ses.retval))
+ } else if (strcmp(type, "exit-signal") == 0) {
+ TRACE(("got exit-signal, ignoring it"))
+ } else {
TRACE(("unknown request '%s'", type))
send_msg_channel_failure(channel);
goto out;
}
- /* We'll just trust what they tell us */
- cli_ses.retval = buf_getint(ses.payload);
- TRACE(("got exit-status of '%d'", cli_ses.retval))
-
out:
m_free(type);
}
diff --git a/common-channel.c b/common-channel.c
index d87ea7d..fdaeb24 100644
--- a/common-channel.c
+++ b/common-channel.c
@@ -313,6 +313,7 @@ static void check_close(struct Channel *channel) {
/* And if we can't receive any more data from them either, close up */
if (!channel->sent_close
&& channel->readfd == FD_CLOSED
+ && (ERRFD_IS_WRITE(channel) || channel->errfd == FD_CLOSED)
&& !write_pending(channel)) {
TRACE(("sending close, readfd is closed"))
send_msg_channel_close(channel);
@@ -624,8 +625,8 @@ static void send_msg_channel_data(struct Channel *channel, int isextended) {
close_chan_fd(channel, fd, SHUT_RD);
}
ses.writepayload->len = ses.writepayload->pos = 0;
- TRACE(("leave send_msg_channel_data: len %d read err or EOF for fd %d",
- len, channel->index));
+ TRACE(("leave send_msg_channel_data: len %d read err %d or EOF for fd %d",
+ len, errno, fd))
return;
}
buf_incrwritepos(ses.writepayload, len);
diff --git a/svr-chansession.c b/svr-chansession.c
index 23cac85..ae5cb3f 100644
--- a/svr-chansession.c
+++ b/svr-chansession.c
@@ -67,6 +67,7 @@ extern char** environ;
static int sesscheckclose(struct Channel *channel) {
struct ChanSess *chansess = (struct ChanSess*)channel->typedata;
+ TRACE(("sesscheckclose, pid is %d", chansess->exit.exitpid))
return chansess->exit.exitpid != -1;
}
@@ -88,12 +89,13 @@ static void sesssigchild_handler(int UNUSED(dummy)) {
TRACE(("enter sigchld handler"))
while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
+ TRACE(("sigchld handler: pid %d", pid))
exit = NULL;
/* find the corresponding chansess */
for (i = 0; i < svr_ses.childpidsize; i++) {
if (svr_ses.childpids[i].pid == pid) {
-
+ TRACE(("found match session"));
exit = &svr_ses.childpids[i].chansess->exit;
break;
}
@@ -102,6 +104,7 @@ static void sesssigchild_handler(int UNUSED(dummy)) {
/* If the pid wasn't matched, then we might have hit the race mentioned
* above. So we just store the info for the parent to deal with */
if (exit == NULL) {
+ TRACE(("using lastexit"));
exit = &svr_ses.lastexit;
}
@@ -125,7 +128,8 @@ static void sesssigchild_handler(int UNUSED(dummy)) {
while (1) {
/* EAGAIN means the pipe's full, so don't need to write anything */
/* isserver is just a random byte to write */
- if (write(ses.signal_pipe[1], &ses.isserver, 1) == 1 || errno == EAGAIN) {
+ if (write(ses.signal_pipe[1], &ses.isserver, 1) == 1
+ || errno == EAGAIN) {
break;
}
if (errno == EINTR) {
@@ -142,7 +146,6 @@ static void sesssigchild_handler(int UNUSED(dummy)) {
}
/* send the exit status or the signal causing termination for a session */
-/* XXX server */
static void send_exitsignalstatus(struct Channel *channel) {
struct ChanSess *chansess = (struct ChanSess*)channel->typedata;
@@ -181,10 +184,11 @@ static void send_msg_chansess_exitsignal(struct Channel * channel,
int i;
char* signame = NULL;
-
dropbear_assert(chansess->exit.exitpid != -1);
dropbear_assert(chansess->exit.exitsignal > 0);
+ TRACE(("send_msg_chansess_exitsignal %d", chansess->exit.exitsignal))
+
CHECKCLEARTOWRITE();
/* we check that we can match a signal name, otherwise
@@ -294,7 +298,7 @@ static void closechansess(struct Channel *channel) {
if (svr_ses.childpids[i].chansess == chansess) {
dropbear_assert(svr_ses.childpids[i].pid > 0);
TRACE(("closing pid %d", svr_ses.childpids[i].pid))
- TRACE(("exitpid = %d", chansess->exit.exitpid))
+ TRACE(("exitpid is %d", chansess->exit.exitpid))
svr_ses.childpids[i].pid = -1;
svr_ses.childpids[i].chansess = NULL;
}
@@ -682,22 +686,24 @@ static int noptycommand(struct Channel *channel, struct ChanSess *chansess) {
/* parent */
TRACE(("continue noptycommand: parent"))
chansess->pid = pid;
+ TRACE(("child pid is %d", pid))
addchildpid(chansess, pid);
if (svr_ses.lastexit.exitpid != -1) {
+ TRACE(("parent side: lastexitpid is %d", svr_ses.lastexit.exitpid))
/* The child probably exited and the signal handler triggered
* possibly before we got around to adding the childpid. So we fill
- * out it's data manually */
+ * out its data manually */
for (i = 0; i < svr_ses.childpidsize; i++) {
- if (svr_ses.childpids[i].pid == pid) {
+ if (svr_ses.childpids[i].pid == svr_ses.lastexit.exitpid) {
+ TRACE(("found match for lastexitpid"))
svr_ses.childpids[i].chansess->exit = svr_ses.lastexit;
svr_ses.lastexit.exitpid = -1;
}
}
}
-
close(infds[FDIN]);
close(outfds[FDOUT]);
close(errfds[FDOUT]);