- Big OpenBSD CVS update (mainly beginnings of SSH2 infrastructure)
   - [auth.c session.c sshd.c auth.h]
     split sshd.c -> auth.c session.c sshd.c plus cleanup and goto-removal
   - [bufaux.c bufaux.h]
     support ssh2 bignums
   - [channels.c channels.h clientloop.c sshd.c nchan.c nchan.h packet.c]
     [readconf.c ssh.c ssh.h serverloop.c]
     replace big switch() with function tables (prepare for ssh2)
   - [ssh2.h]
     ssh2 message type codes
   - [sshd.8]
     reorder Xr to avoid cutting
   - [serverloop.c]
     close(fdin) if fdin != fdout, shutdown otherwise, ok theo@
   - [channels.c]
     missing close
     allow bigger packets
   - [cipher.c cipher.h]
     support ssh2 ciphers
   - [compress.c]
     cleanup, less code
   - [dispatch.c dispatch.h]
     function tables for different message types
   - [log-server.c]
     do not log() if debuggin to stderr
     rename a cpp symbol, to avoid param.h collision
   - [mpaux.c]
     KNF
   - [nchan.c]
     sync w/ channels.c
diff --git a/serverloop.c b/serverloop.c
index 2afca76..8bf448c 100644
--- a/serverloop.c
+++ b/serverloop.c
@@ -13,6 +13,10 @@
 #include "buffer.h"
 #include "servconf.h"
 #include "pty.h"
+#include "channels.h"
+
+#include "compat.h"
+#include "dispatch.h"
 
 static Buffer stdin_buffer;	/* Buffer for stdin data. */
 static Buffer stdout_buffer;	/* Buffer for stdout data. */
@@ -47,6 +51,8 @@
 static volatile int child_has_selected; /* Child has had chance to drain. */
 static volatile int child_wait_status;	/* Status from wait(). */
 
+void	server_init_dispatch(void);
+
 void 
 sigchld_handler(int sig)
 {
@@ -68,104 +74,6 @@
 }
 
 /*
- * Process any buffered packets that have been received from the client.
- */
-void 
-process_buffered_input_packets()
-{
-	int type;
-	char *data;
-	unsigned int data_len;
-	int row, col, xpixel, ypixel;
-	int payload_len;
-
-	/* Process buffered packets from the client. */
-	while ((type = packet_read_poll(&payload_len)) != SSH_MSG_NONE) {
-		switch (type) {
-		case SSH_CMSG_STDIN_DATA:
-			/* Stdin data from the client.  Append it to the buffer. */
-			/* Ignore any data if the client has closed stdin. */
-			if (fdin == -1)
-				break;
-			data = packet_get_string(&data_len);
-			packet_integrity_check(payload_len, (4 + data_len), type);
-			buffer_append(&stdin_buffer, data, data_len);
-			memset(data, 0, data_len);
-			xfree(data);
-			break;
-
-		case SSH_CMSG_EOF:
-			/*
-			 * Eof from the client.  The stdin descriptor to the
-			 * program will be closed when all buffered data has
-			 * drained.
-			 */
-			debug("EOF received for stdin.");
-			packet_integrity_check(payload_len, 0, type);
-			stdin_eof = 1;
-			break;
-
-		case SSH_CMSG_WINDOW_SIZE:
-			debug("Window change received.");
-			packet_integrity_check(payload_len, 4 * 4, type);
-			row = packet_get_int();
-			col = packet_get_int();
-			xpixel = packet_get_int();
-			ypixel = packet_get_int();
-			if (fdin != -1)
-				pty_change_window_size(fdin, row, col, xpixel, ypixel);
-			break;
-
-		case SSH_MSG_PORT_OPEN:
-			debug("Received port open request.");
-			channel_input_port_open(payload_len);
-			break;
-
-		case SSH_MSG_CHANNEL_OPEN_CONFIRMATION:
-			debug("Received channel open confirmation.");
-			packet_integrity_check(payload_len, 4 + 4, type);
-			channel_input_open_confirmation();
-			break;
-
-		case SSH_MSG_CHANNEL_OPEN_FAILURE:
-			debug("Received channel open failure.");
-			packet_integrity_check(payload_len, 4, type);
-			channel_input_open_failure();
-			break;
-
-		case SSH_MSG_CHANNEL_DATA:
-			channel_input_data(payload_len);
-			break;
-
-		case SSH_MSG_CHANNEL_CLOSE:
-			debug("Received channel close.");
-			packet_integrity_check(payload_len, 4, type);
-			channel_input_close();
-			break;
-
-		case SSH_MSG_CHANNEL_CLOSE_CONFIRMATION:
-			debug("Received channel close confirmation.");
-			packet_integrity_check(payload_len, 4, type);
-			channel_input_close_confirmation();
-			break;
-
-		default:
-			/*
-			 * In this phase, any unexpected messages cause a
-			 * protocol error.  This is to ease debugging; also,
-			 * since no confirmations are sent messages,
-			 * unprocessed unknown messages could cause strange
-			 * problems.  Any compatible protocol extensions must
-			 * be negotiated before entering the interactive
-			 * session.
-			 */
-			packet_disconnect("Protocol error during session: type %d",
-					  type);
-		}
-	}
-}
-
-/*
  * Make packets from buffered stderr data, and buffer it for sending
  * to the client.
  */
@@ -378,7 +286,7 @@
 #ifdef USE_PIPES
 			close(fdin);
 #else
-			if (fdout == -1)
+			if (fdin != fdout)
 				close(fdin);
 			else
 				shutdown(fdin, SHUT_WR); /* We will no longer send. */
@@ -425,6 +333,12 @@
 	packet_write_wait();
 }
 
+void 
+process_buffered_input_packets()
+{
+	dispatch_run(DISPATCH_NONBLOCK, NULL);
+}
+
 /*
  * Performs the interactive session.  This handles data transmission between
  * the client and the program.  Note that the notion of stdin, stdout, and
@@ -490,6 +404,8 @@
 	if (fderr == -1)
 		fderr_eof = 1;
 
+	server_init_dispatch();
+
 	/* Main loop of the server for the interactive session mode. */
 	for (;;) {
 		fd_set readset, writeset;
@@ -505,7 +421,7 @@
 #ifdef USE_PIPES
 			close(fdin);
 #else
-			if (fdout == -1)
+			if (fdin != fdout)
 				close(fdin);
 			else
 				shutdown(fdin, SHUT_WR); /* We will no longer send. */
@@ -549,7 +465,7 @@
 		    (buffer_len(&stdout_buffer) == 0) && 
 			 (buffer_len(&stderr_buffer) == 0)) {
 			if (!channel_still_open())
-				goto quit;
+				break;
 			if (!waiting_termination) {
 				const char *s = "Waiting for forwarded connections to terminate...\r\n";
 				char *cp;
@@ -576,7 +492,6 @@
 		process_output(&writeset);
 	}
 
-quit:
 	/* Cleanup and termination code. */
 
 	/* Wait until all output has been sent to the client. */
@@ -662,3 +577,79 @@
 	packet_disconnect("wait returned status %04x.", wait_status);
 	/* NOTREACHED */
 }
+
+void
+server_input_stdin_data(int type, int plen)
+{
+	char *data;
+	unsigned int data_len;
+
+	/* Stdin data from the client.  Append it to the buffer. */
+	/* Ignore any data if the client has closed stdin. */
+	if (fdin == -1)
+		return;
+	data = packet_get_string(&data_len);
+	packet_integrity_check(plen, (4 + data_len), type);
+	buffer_append(&stdin_buffer, data, data_len);
+	memset(data, 0, data_len);
+	xfree(data);
+}
+
+void
+server_input_eof(int type, int plen)
+{
+	/*
+	 * Eof from the client.  The stdin descriptor to the
+	 * program will be closed when all buffered data has
+	 * drained.
+	 */
+	debug("EOF received for stdin.");
+	packet_integrity_check(plen, 0, type);
+	stdin_eof = 1;
+}
+
+void
+server_input_window_size(int type, int plen)
+{
+	int row = packet_get_int();
+	int col = packet_get_int();
+	int xpixel = packet_get_int();
+	int ypixel = packet_get_int();
+
+	debug("Window change received.");
+	packet_integrity_check(plen, 4 * 4, type);
+	if (fdin != -1)
+		pty_change_window_size(fdin, row, col, xpixel, ypixel);
+}
+
+void 
+server_init_dispatch_13()
+{
+	debug("server_init_dispatch_13");
+	dispatch_init(NULL);
+	dispatch_set(SSH_CMSG_EOF, &server_input_eof);
+	dispatch_set(SSH_CMSG_STDIN_DATA, &server_input_stdin_data);
+	dispatch_set(SSH_CMSG_WINDOW_SIZE, &server_input_window_size);
+	dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_close);
+	dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, &channel_input_close_confirmation);
+	dispatch_set(SSH_MSG_CHANNEL_DATA, &channel_input_data);
+	dispatch_set(SSH_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation);
+	dispatch_set(SSH_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
+	dispatch_set(SSH_MSG_PORT_OPEN, &channel_input_port_open);
+}
+void 
+server_init_dispatch_15()
+{
+	server_init_dispatch_13();
+	debug("server_init_dispatch_15");
+	dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_ieof);
+	dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, &channel_input_oclose);
+}
+void 
+server_init_dispatch()
+{
+	if (compat13)
+		server_init_dispatch_13();
+	else
+		server_init_dispatch_15();
+}