diff --git a/auth.h b/auth.h
index 7ebf9ae7e4b962bbe6cf42ed33646db98e867dad..0fd9c73e18d28d7c9c279dcbca5316b109ef8b55 100644
--- a/auth.h
+++ b/auth.h
@@ -133,7 +133,6 @@ struct PubKeyOptions {
 	int no_pty_flag;
 	/* "command=" option. */
 	unsigned char * forced_command;
-	unsigned char * original_command;
 };
 #endif
 
diff --git a/channel.h b/channel.h
index 5c63226b2549772992ac83e6be12aad4db8b445c..d9e289461e87a68d127980f3be4dedc5739eb831 100644
--- a/channel.h
+++ b/channel.h
@@ -69,6 +69,10 @@ struct Channel {
 	int sent_close, recv_close;
 	int recv_eof, sent_eof;
 
+	/* Set after running the ChanType-specific close hander
+	 * to ensure we don't run it twice (nor type->checkclose()). */
+	int close_handler_done;
+
 	int initconn; /* used for TCP forwarding, whether the channel has been
 					 fully initialised */
 
diff --git a/chansession.h b/chansession.h
index 924518b8eab57712702b4513d8e933129c1a6848..ef252eaf7eb6b9b29e61365f3bc8f9fc1577a01d 100644
--- a/chansession.h
+++ b/chansession.h
@@ -69,6 +69,10 @@ struct ChanSess {
 	char * agentfile;
 	char * agentdir;
 #endif
+
+#ifdef ENABLE_SVR_PUBKEY_OPTIONS
+	char *original_command;
+#endif
 };
 
 struct ChildPid {
diff --git a/cli-agentfwd.c b/cli-agentfwd.c
index c9ce8334c6a8bf96949d846cd635059d2ecfbb3e..a8213056313b7ea7b65851085774fc124ce6b4f1 100644
--- a/cli-agentfwd.c
+++ b/cli-agentfwd.c
@@ -260,7 +260,7 @@ void agent_buf_sign(buffer *sigblob, sign_key *key,
 		const unsigned char *data, unsigned int len) {
 	buffer *request_data = NULL;
 	buffer *response = NULL;
-	unsigned int keylen, siglen;
+	unsigned int siglen;
 	int packet_type;
 	
 	/* Request format
@@ -271,7 +271,6 @@ void agent_buf_sign(buffer *sigblob, sign_key *key,
 	*/
 	request_data = buf_new(MAX_PUBKEY_SIZE + len + 12);
 	buf_put_pub_key(request_data, key, key->type);
-	keylen = request_data->len - 4;
 	
 	buf_putstring(request_data, data, len);
 	buf_putint(request_data, 0);
diff --git a/common-channel.c b/common-channel.c
index 5821b085355c2e8bd67021e1ae7eb68d8e25d1fa..9eaba5090779cd63c40e80bf5f69f67e55b525b9 100644
--- a/common-channel.c
+++ b/common-channel.c
@@ -138,6 +138,7 @@ struct Channel* newchannel(unsigned int remotechan,
 	newchan->index = i;
 	newchan->sent_close = newchan->recv_close = 0;
 	newchan->sent_eof = newchan->recv_eof = 0;
+	newchan->close_handler_done = 0;
 
 	newchan->remotechan = remotechan;
 	newchan->transwindow = transwindow;
@@ -270,7 +271,9 @@ static void check_close(struct Channel *channel) {
 				cbuf_getused(channel->writebuf),
 				channel->extrabuf ? cbuf_getused(channel->extrabuf) : 0))
 
-	if (!channel->flushing && channel->type->check_close
+	if (!channel->flushing 
+		&& !channel->close_handler_done
+		&& channel->type->check_close
 		&& channel->type->check_close(channel))
 	{
 		channel->flushing = 1;
@@ -281,7 +284,8 @@ static void check_close(struct Channel *channel) {
 	   channel, to ensure that the shell has exited (and the exit status 
 	   retrieved) before we close things up. */
 	if (!channel->type->check_close	
-			|| channel->type->check_close(channel)) {
+		|| channel->close_handler_done
+		|| channel->type->check_close(channel)) {
 		close_allowed = 1;
 	}
 
@@ -363,9 +367,11 @@ static void check_in_progress(struct Channel *channel) {
 /* Send the close message and set the channel as closed */
 static void send_msg_channel_close(struct Channel *channel) {
 
-	TRACE(("enter send_msg_channel_close"))
-	if (channel->type->closehandler) {
+	TRACE(("enter send_msg_channel_close %p", channel))
+	if (channel->type->closehandler 
+			&& !channel->close_handler_done) {
 		channel->type->closehandler(channel);
+		channel->close_handler_done = 1;
 	}
 	
 	CHECKCLEARTOWRITE();
@@ -568,16 +574,17 @@ void recv_msg_channel_request() {
 
 	struct Channel *channel;
 
-	TRACE(("enter recv_msg_channel_request"))
-	
 	channel = getchannel();
 
+	TRACE(("enter recv_msg_channel_request %p", channel))
+
 	if (channel->sent_close) {
 		TRACE(("leave recv_msg_channel_request: already closed channel"))
 		return;
 	}
 
-	if (channel->type->reqhandler) {
+	if (channel->type->reqhandler 
+			&& !channel->close_handler_done) {
 		channel->type->reqhandler(channel);
 	} else {
 		send_msg_channel_failure(channel);
diff --git a/dbutil.c b/dbutil.c
index b9d7f474e3de79764197fd1981457d38f479242b..9a6d846a22d50b19bc3344649849a6cc355e97c5 100644
--- a/dbutil.c
+++ b/dbutil.c
@@ -800,12 +800,6 @@ void * m_strdup(const char * str) {
 	return ret;
 }
 
-void __m_free(void* ptr) {
-	if (ptr != NULL) {
-		free(ptr);
-	}
-}
-
 void * m_realloc(void* ptr, size_t size) {
 
 	void *ret;
diff --git a/dbutil.h b/dbutil.h
index 14c4c28033dc54d27a9b048a3987355b6968f9f0..0f16bf3c162d4c3a6b1164f2bfa29291866ba9be 100644
--- a/dbutil.h
+++ b/dbutil.h
@@ -83,8 +83,7 @@ void m_close(int fd);
 void * m_malloc(size_t size);
 void * m_strdup(const char * str);
 void * m_realloc(void* ptr, size_t size);
-#define m_free(X) __m_free(X); (X) = NULL;
-void __m_free(void* ptr);
+#define m_free(X) free(X); (X) = NULL;
 void m_burn(void* data, unsigned int len);
 void setnonblocking(int fd);
 void disallow_core();
diff --git a/signkey.c b/signkey.c
index c53805a1c2a97ff4ffb96d062bb714bf34b45492..1d908f4b8a88b2ddf9d6f9595b7b16c462a20f6b 100644
--- a/signkey.c
+++ b/signkey.c
@@ -105,11 +105,11 @@ int buf_get_pub_key(buffer *buf, sign_key *key, int *type) {
 	m_free(ident);
 
 	if (*type != DROPBEAR_SIGNKEY_ANY && *type != keytype) {
-		TRACE(("buf_get_pub_key bad type - got %d, expected %d", keytype, type))
+		TRACE(("buf_get_pub_key bad type - got %d, expected %d", keytype, *type))
 		return DROPBEAR_FAILURE;
 	}
 	
-	TRACE(("buf_get_pub_key keytype is %d"))
+	TRACE(("buf_get_pub_key keytype is %d", keytype))
 
 	*type = keytype;
 
diff --git a/svr-authpubkeyoptions.c b/svr-authpubkeyoptions.c
index fd87703848c9d296ebcfb63d1f5ee6cb885cb179..4490b5849c9db48c166ae65e19b629d6c57a742d 100644
--- a/svr-authpubkeyoptions.c
+++ b/svr-authpubkeyoptions.c
@@ -92,14 +92,15 @@ int svr_pubkey_allows_pty() {
  * by any 'command' public key option. */
 void svr_pubkey_set_forced_command(struct ChanSess *chansess) {
 	if (ses.authstate.pubkey_options) {
-		ses.authstate.pubkey_options->original_command = chansess->cmd;
-		if (!chansess->cmd)
-		{
-			ses.authstate.pubkey_options->original_command = m_strdup("");
+		if (chansess->cmd) {
+			/* original_command takes ownership */
+			chansess->original_command = chansess->cmd;
+		} else {
+			chansess->original_command = m_strdup("");
 		}
-		chansess->cmd = ses.authstate.pubkey_options->forced_command;
+		chansess->cmd = m_strdup(ses.authstate.pubkey_options->forced_command);
 #ifdef LOG_COMMANDS
-		dropbear_log(LOG_INFO, "Command forced to '%s'", ses.authstate.pubkey_options->original_command);
+		dropbear_log(LOG_INFO, "Command forced to '%s'", chansess->original_command);
 #endif
 	}
 }
diff --git a/svr-chansession.c b/svr-chansession.c
index e6ad713cf7df03d9c38e8725a6ef8402d4588742..4d6d4fe0b3288a0a7b04b678680b4a050bf9fccf 100644
--- a/svr-chansession.c
+++ b/svr-chansession.c
@@ -218,6 +218,8 @@ static int newchansess(struct Channel *channel) {
 
 	struct ChanSess *chansess;
 
+	TRACE(("new chansess %p", channel))
+
 	dropbear_assert(channel->typedata == NULL);
 
 	chansess = (struct ChanSess*)m_malloc(sizeof(struct ChanSess));
@@ -280,6 +282,10 @@ static void closechansess(struct Channel *channel) {
 	m_free(chansess->cmd);
 	m_free(chansess->term);
 
+#ifdef ENABLE_SVR_PUBKEY_OPTIONS
+	m_free(chansess->original_command);
+#endif
+
 	if (chansess->tty) {
 		/* write the utmp/wtmp login record */
 		li = chansess_login_alloc(chansess);
@@ -925,10 +931,8 @@ static void execchild(void *user_data) {
 	}
 	
 #ifdef ENABLE_SVR_PUBKEY_OPTIONS
-	if (ses.authstate.pubkey_options &&
-			ses.authstate.pubkey_options->original_command) {
-		addnewvar("SSH_ORIGINAL_COMMAND", 
-			ses.authstate.pubkey_options->original_command);
+	if (chansess->original_command) {
+		addnewvar("SSH_ORIGINAL_COMMAND", chansess->original_command);
 	}
 #endif
 
diff --git a/svr-x11fwd.c b/svr-x11fwd.c
index 1af027bdf7caa7c2670b7a33c424619f1e3b95df..92dadd5c54aa502f3f3e08a82d089adeb5c1264b 100644
--- a/svr-x11fwd.c
+++ b/svr-x11fwd.c
@@ -175,7 +175,7 @@ void x11cleanup(struct ChanSess *chansess) {
 	m_free(chansess->x11authprot);
 	m_free(chansess->x11authcookie);
 
-	TRACE(("chansess %s", chansess))
+	TRACE(("chansess %x", chansess))
 	if (chansess->x11listener != NULL) {
 		remove_listener(chansess->x11listener);
 		chansess->x11listener = NULL;