summaryrefslogtreecommitdiffhomepage
path: root/svr-chansession.c
diff options
context:
space:
mode:
Diffstat (limited to 'svr-chansession.c')
-rw-r--r--svr-chansession.c133
1 files changed, 69 insertions, 64 deletions
diff --git a/svr-chansession.c b/svr-chansession.c
index 22fc954..faf62e5 100644
--- a/svr-chansession.c
+++ b/svr-chansession.c
@@ -43,24 +43,24 @@
static int sessioncommand(struct Channel *channel, struct ChanSess *chansess,
int iscmd, int issubsys);
static int sessionpty(struct ChanSess * chansess);
-static int sessionsignal(struct ChanSess *chansess);
+static int sessionsignal(const struct ChanSess *chansess);
static int noptycommand(struct Channel *channel, struct ChanSess *chansess);
static int ptycommand(struct Channel *channel, struct ChanSess *chansess);
-static int sessionwinchange(struct ChanSess *chansess);
-static void execchild(void *user_data_chansess);
+static int sessionwinchange(const struct ChanSess *chansess);
+static void execchild(const void *user_data_chansess);
static void addchildpid(struct ChanSess *chansess, pid_t pid);
static void sesssigchild_handler(int val);
-static void closechansess(struct Channel *channel);
+static void closechansess(const struct Channel *channel);
static int newchansess(struct Channel *channel);
static void chansessionrequest(struct Channel *channel);
-static int sesscheckclose(struct Channel *channel);
+static int sesscheckclose(const struct Channel *channel);
-static void send_exitsignalstatus(struct Channel *channel);
-static void send_msg_chansess_exitstatus(struct Channel * channel,
- struct ChanSess * chansess);
-static void send_msg_chansess_exitsignal(struct Channel * channel,
- struct ChanSess * chansess);
-static void get_termmodes(struct ChanSess *chansess);
+static void send_exitsignalstatus(const struct Channel *channel);
+static void send_msg_chansess_exitstatus(const struct Channel * channel,
+ const struct ChanSess * chansess);
+static void send_msg_chansess_exitsignal(const struct Channel * channel,
+ const struct ChanSess * chansess);
+static void get_termmodes(const struct ChanSess *chansess);
const struct ChanType svrchansess = {
0, /* sepfds */
@@ -74,78 +74,83 @@ const struct ChanType svrchansess = {
/* required to clear environment */
extern char** environ;
-static int sesscheckclose(struct Channel *channel) {
+static int sesscheckclose(const struct Channel *channel) {
struct ChanSess *chansess = (struct ChanSess*)channel->typedata;
TRACE(("sesscheckclose, pid is %d", chansess->exit.exitpid))
return chansess->exit.exitpid != -1;
}
-/* Handler for childs exiting, store the state for return to the client */
-
-/* There's a particular race we have to watch out for: if the forked child
- * executes, exits, and this signal-handler is called, all before the parent
- * gets to run, then the childpids[] array won't have the pid in it. Hence we
- * use the svr_ses.lastexit struct to hold the exit, which is then compared by
- * the parent when it runs. This work correctly at least in the case of a
- * single shell spawned (ie the usual case) */
-static void sesssigchild_handler(int UNUSED(dummy)) {
-
+void svr_chansess_checksignal(void) {
int status;
pid_t pid;
- unsigned int i;
- struct sigaction sa_chld;
- struct exitinfo *exit = NULL;
- const int saved_errno = errno;
-
- /* Make channel handling code look for closed channels */
- ses.channel_signal_pending = 1;
+ if (!ses.channel_signal_pending) {
+ return;
+ }
- TRACE(("enter sigchld handler"))
while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
+ unsigned int i;
+ struct exitinfo *ex = NULL;
TRACE(("sigchld handler: pid %d", pid))
- exit = NULL;
+ ex = 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;
+ ex = &svr_ses.childpids[i].chansess->exit;
break;
}
}
/* 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) {
+ if (ex == NULL) {
TRACE(("using lastexit"));
- exit = &svr_ses.lastexit;
+ ex = &svr_ses.lastexit;
}
- exit->exitpid = pid;
+ ex->exitpid = pid;
if (WIFEXITED(status)) {
- exit->exitstatus = WEXITSTATUS(status);
+ ex->exitstatus = WEXITSTATUS(status);
}
if (WIFSIGNALED(status)) {
- exit->exitsignal = WTERMSIG(status);
+ ex->exitsignal = WTERMSIG(status);
#if !defined(AIX) && defined(WCOREDUMP)
- exit->exitcore = WCOREDUMP(status);
+ ex->exitcore = WCOREDUMP(status);
#else
- exit->exitcore = 0;
+ ex->exitcore = 0;
#endif
} else {
/* we use this to determine how pid exited */
- exit->exitsignal = -1;
+ ex->exitsignal = -1;
}
- /* Make sure that the main select() loop wakes up */
- while (1) {
- /* isserver is just a random byte to write. We can't do anything
- about an error so should just ignore it */
- if (write(ses.signal_pipe[1], &ses.isserver, 1) == 1
- || errno != EINTR) {
- break;
- }
+ }
+}
+
+/* Handler for childs exiting, store the state for return to the client */
+
+/* There's a particular race we have to watch out for: if the forked child
+ * executes, exits, and this signal-handler is called, all before the parent
+ * gets to run, then the childpids[] array won't have the pid in it. Hence we
+ * use the svr_ses.lastexit struct to hold the exit, which is then compared by
+ * the parent when it runs. This work correctly at least in the case of a
+ * single shell spawned (ie the usual case) */
+static void sesssigchild_handler(int UNUSED(dummy)) {
+ struct sigaction sa_chld;
+
+ const int saved_errno = errno;
+
+ TRACE(("enter sigchld handler"))
+
+ /* Make sure that the main select() loop wakes up */
+ while (1) {
+ /* isserver is just a random byte to write. We can't do anything
+ about an error so should just ignore it */
+ if (write(ses.signal_pipe[1], &ses.isserver, 1) == 1
+ || errno != EINTR) {
+ break;
}
}
@@ -159,7 +164,7 @@ static void sesssigchild_handler(int UNUSED(dummy)) {
}
/* send the exit status or the signal causing termination for a session */
-static void send_exitsignalstatus(struct Channel *channel) {
+static void send_exitsignalstatus(const struct Channel *channel) {
struct ChanSess *chansess = (struct ChanSess*)channel->typedata;
@@ -173,8 +178,8 @@ static void send_exitsignalstatus(struct Channel *channel) {
}
/* send the exitstatus to the client */
-static void send_msg_chansess_exitstatus(struct Channel * channel,
- struct ChanSess * chansess) {
+static void send_msg_chansess_exitstatus(const struct Channel * channel,
+ const struct ChanSess * chansess) {
dropbear_assert(chansess->exit.exitpid != -1);
dropbear_assert(chansess->exit.exitsignal == -1);
@@ -192,8 +197,8 @@ static void send_msg_chansess_exitstatus(struct Channel * channel,
}
/* send the signal causing the exit to the client */
-static void send_msg_chansess_exitsignal(struct Channel * channel,
- struct ChanSess * chansess) {
+static void send_msg_chansess_exitsignal(const struct Channel * channel,
+ const struct ChanSess * chansess) {
int i;
char* signame = NULL;
@@ -273,7 +278,7 @@ static int newchansess(struct Channel *channel) {
}
static struct logininfo*
-chansess_login_alloc(struct ChanSess *chansess) {
+chansess_login_alloc(const struct ChanSess *chansess) {
struct logininfo * li;
li = login_alloc_entry(chansess->pid, ses.authstate.username,
svr_ses.remotehost, chansess->tty);
@@ -281,7 +286,7 @@ chansess_login_alloc(struct ChanSess *chansess) {
}
/* clean a session channel */
-static void closechansess(struct Channel *channel) {
+static void closechansess(const struct Channel *channel) {
struct ChanSess *chansess;
unsigned int i;
@@ -403,7 +408,7 @@ out:
/* Send a signal to a session's process as requested by the client*/
-static int sessionsignal(struct ChanSess *chansess) {
+static int sessionsignal(const struct ChanSess *chansess) {
int sig = 0;
char* signame = NULL;
@@ -441,7 +446,7 @@ static int sessionsignal(struct ChanSess *chansess) {
/* Let the process know that the window size has changed, as notified from the
* client. Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
-static int sessionwinchange(struct ChanSess *chansess) {
+static int sessionwinchange(const struct ChanSess *chansess) {
int termc, termr, termw, termh;
@@ -460,7 +465,7 @@ static int sessionwinchange(struct ChanSess *chansess) {
return DROPBEAR_SUCCESS;
}
-static void get_termmodes(struct ChanSess *chansess) {
+static void get_termmodes(const struct ChanSess *chansess) {
struct termios termio;
unsigned char opcode;
@@ -658,7 +663,7 @@ static int sessioncommand(struct Channel *channel, struct ChanSess *chansess,
}
}
if (issubsys) {
-#ifdef SFTPSERVER_PATH
+#if DROPBEAR_SFTPSERVER
if ((cmdlen == 4) && strncmp(chansess->cmd, "sftp", 4) == 0) {
m_free(chansess->cmd);
chansess->cmd = m_strdup(SFTPSERVER_PATH);
@@ -682,7 +687,7 @@ static int sessioncommand(struct Channel *channel, struct ChanSess *chansess,
}
-#ifdef LOG_COMMANDS
+#if LOG_COMMANDS
if (chansess->cmd) {
dropbear_log(LOG_INFO, "User %s executing '%s'",
ses.authstate.pw_name, chansess->cmd);
@@ -769,7 +774,7 @@ static int ptycommand(struct Channel *channel, struct ChanSess *chansess) {
pid_t pid;
struct logininfo *li = NULL;
-#ifdef DO_MOTD
+#if DO_MOTD
buffer * motdbuf = NULL;
int len;
struct stat sb;
@@ -821,7 +826,7 @@ static int ptycommand(struct Channel *channel, struct ChanSess *chansess) {
login_login(li);
login_free_entry(li);
-#ifdef DO_MOTD
+#if DO_MOTD
if (svr_opts.domotd && !chansess->cmd) {
/* don't show the motd if ~/.hushlogin exists */
@@ -898,8 +903,8 @@ static void addchildpid(struct ChanSess *chansess, pid_t pid) {
/* Clean up, drop to user privileges, set up the environment and execute
* the command/shell. This function does not return. */
-static void execchild(void *user_data) {
- struct ChanSess *chansess = user_data;
+static void execchild(const void *user_data) {
+ const struct ChanSess *chansess = user_data;
char *usershell = NULL;
/* with uClinux we'll have vfork()ed, so don't want to overwrite the