diff --git a/ChangeLog b/ChangeLog
index 0200c3954a9248e9df72e5fed2fdcb373652278a..3fdb1b9d576162fc3e48de23468c31d878a9f1a7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+Fri Dec  4 02:30:28 1998    <nisse@puck>
+
+	* (practically every file): Adapted to new gc and object system.
+
+	* xalloc.c (lsh_object_check_subtype): Allow NULL pointers. They
+	are occasionally permissible (for instance, the NULL crypto
+	algorithm), and when they aren't the error will be detected early
+	anyway. 
+	(lsh_object_check): -"-
+
+	* keyexchange.c (do_handle_kexinit): Use an object_list for
+ 	passing around the selected algorithms. The void ** that was used
+ 	earlier was unfriendly to the gc.
+
 Sun Nov 22 00:57:16 1998    <nisse@puck>
 
 	* lsh.c (main): Bug fix (pass *address* of crypto_rc4_algorithm).
diff --git a/doc/TODO b/doc/TODO
index aa1825b7c56af7a76f01e0036beab723b8da4698..a21bad004e3387f6bcc59e44a73c3f384bfe6480 100644
--- a/doc/TODO
+++ b/doc/TODO
@@ -61,6 +61,8 @@ lssh_space_alloc.
 Make lists of integers (usually atoms) its own type. Can this be done
 in such a way that they can also be allocated statically? 
 
+Have the allocator initialize all objects automatically.
+
 
 CHANNELS
 
diff --git a/src/Makefile.am.in b/src/Makefile.am.in
index 4d7a31f8a57261804a363142a2d40a423ebbfd30..4a2027e0b4548c8c066b4a9e067c35a26b48d4ee 100644
--- a/src/Makefile.am.in
+++ b/src/Makefile.am.in
@@ -31,13 +31,13 @@ bin_PROGRAMS = lsh lshd
 
 generated_sources = atoms_defines.h atoms_gperf.c atoms_table.c
 
-common_sources = abstract_io.c alist.c atoms.c bignum.c channel.c \
-	charset.c connection.c crypto.c \
-	debug.c disconnect.c encrypt.c format.c getopt.c io.c keyexchange.c \
-	packet_ignore.c pad.c parse.c publickey_crypto.c \
+common_sources = abstract_io.c abstract_crypto.c alist.c atoms.c \
+	bignum.c channel.c charset.c connection.c crypto.c \
+	debug.c disconnect.c encrypt.c format.c gc.c getopt.c io.c keyexchange.c \
+	list.c packet_ignore.c pad.c parse.c password.c publickey_crypto.c \
 	randomness.c \
 	read_data.c read_line.c read_packet.c service.c \
-	translate_signal.c unpad.c \
+	translate_signal.c unpad.c userauth.c \
 	werror.c write_buffer.c xalloc.c 
 
 lsh_SOURCES = $(common_sources) lsh.c client.c client_keyexchange.c \
diff --git a/src/abstract_crypto.h b/src/abstract_crypto.h
index 7fc80ff4b2f0b40e476deccbe72b59223bc47f89..27ec3ddc76f8f6fc0e94176e923291cfb51f7314 100644
--- a/src/abstract_crypto.h
+++ b/src/abstract_crypto.h
@@ -28,6 +28,12 @@
 
 #include "lsh_types.h"
 
+/* Use the same instance struct for both hash functions and macs. This
+ * is a little ugly. */
+#define mac_instance_class hash_instance_class
+#define mac_instance hash_instance
+#define mac_size hash_size
+
 #define CLASS_DECLARE
 #include "abstract_crypto.h.x"
 #undef CLASS_DECLARE
@@ -65,7 +71,7 @@ struct crypto_instance
        (block_size simple UINT32)
        (key_size simple UINT32)
        (make_crypt method (object crypto_instance)
-                   "int mode" "UIINT8 *key")))
+                   "int mode" "UINT8 *key")))
 */
      
 #if 0
@@ -87,6 +93,8 @@ struct crypto_algorithm
 #define MAKE_DECRYPT(crypto, key) \
 ((crypto)->make_crypt((crypto), CRYPTO_DECRYPT, (key)))
 
+/* FIXME: Hashes could use non-virtual methods. */
+     
 /* CLASS:
    (class
      (name hash_instance)
@@ -120,10 +128,6 @@ struct hash_instance
 
 #define HASH_COPY(instance) ((instance)->copy((instance)))
 
-/* Used for both hash functions ad macs */
-#define mac_instance hash_instance
-#define mac_size hash_size
-
 /* CLASS:
    (class
      (name hash_algorithm)
diff --git a/src/abstract_io.h b/src/abstract_io.h
index f70b281f645d679784e134356cd312d64f8e2a88..ce8301459d2d0a429b4de87a5ebc20957e76a6cd 100644
--- a/src/abstract_io.h
+++ b/src/abstract_io.h
@@ -46,7 +46,7 @@
    (class
      (name abstract_read)
      (vars
-       (read method int
+       (read indirect-method int
              "UINT32 length" "UINT8 *buffer")))
 */
 #if 0
@@ -67,7 +67,7 @@ struct abstract_read
    (class
      (name read_handler)
      (vars
-       (handler method int "struct abstract_read *read")))
+       (handler indirect-method int "struct abstract_read *read")))
 */
 
 #if 0
diff --git a/src/alist.c b/src/alist.c
index 637c3954e6fb2769e65a6a8a8c33403b2a1e0e3b..8e87af6d30afcac12632d97b55deed8b295b1508 100644
--- a/src/alist.c
+++ b/src/alist.c
@@ -33,6 +33,10 @@
 #include "werror.h"
 #include "xalloc.h"
 
+#define CLASS_DEFINE
+#include "alist.h.x"
+#undef CLASS_DEFINE
+
 struct alist_node
 {
   struct alist_node *next;
diff --git a/src/alist.h b/src/alist.h
index 46f3b2b2ffc9c17f2efb906b9a19c742797f41cc..443c41753beb1111885af62c556c1aec734631df 100644
--- a/src/alist.h
+++ b/src/alist.h
@@ -28,6 +28,13 @@
 
 #include "lsh_types.h"
 
+/* Forward declaration */
+struct alist;
+
+#define CLASS_DECLARE
+#include "alist.h.x"
+#undef CLASS_DECLARE
+
 /* Not supported anymore */
 /* #define ALIST_USE_SIZE 0 */
 
@@ -88,6 +95,4 @@ struct alist *make_linked_alist(int n, ...);
 
 #define make_alist make_linear_alist
 
-#include "alist.h.x"
-
 #endif /* LSH_ALIST_H_INCLUDED */
diff --git a/src/blocking_write.c b/src/blocking_write.c
index fdc8b40d662ac79b2d6ae2870fae7622dffa2c2b..5f35a5f0106d1e1c0bf956f4203496bc2156fbc9 100644
--- a/src/blocking_write.c
+++ b/src/blocking_write.c
@@ -11,13 +11,11 @@
 static int do_write(struct abstract_write *w,
 		    struct lsh_string *packet)
 {
-  struct packet_blocking_write *closure
-    = (struct packet_blocking_write *) w;
+  CAST(packet_blocking_write, closure, w);
   
   UINT32 left = packet->length;
   UINT8 *p = packet->data;
 
-  MDEBUG(closure);
   while(left)
     {
       int written = write(closure->fd, p, left);
diff --git a/src/channel.c b/src/channel.c
index 6fddbff90fa98ecdfba28efc6c1f2cbe9300ef9c..0f2ba6b5503bc67bdf43607a1d6fc1af144a2662 100644
--- a/src/channel.c
+++ b/src/channel.c
@@ -38,6 +38,25 @@
 #include "channel.h.x"
 #undef CLASS_DEFINE
 
+#include "channel.c.x"
+
+/* CLASS:
+   (class
+     (name connection_service)
+     (super ssh_service)
+     (vars
+       ; Supported global requests 
+       (global_requests object alist)
+
+       (channel_types object alist)
+
+       ; Initialize connection (for instance, request channels to be 
+       ; opened or services to be forwarded).
+
+       (start object connection_startup)))
+*/
+
+#if 0
 struct connection_service
 {
   struct ssh_service super;
@@ -50,35 +69,57 @@ struct connection_service
    * or services to be forwarded. */
   struct connection_startup *start;
 };
+#endif
 
+/* CLASS:
+   (class
+     (name channel_handler)
+     (super packet_handler)
+     (vars
+       (table object channel_table)))
+*/
+
+#if 0
 struct channel_handler
 {
   struct packet_handler super;
   
   struct channel_table *table;
 };
+#endif
 
+/* CLASS:
+   (class
+     (name global_request_handler)
+     (super channel_handler super)
+     (vars
+       (global_requests object alist)))
+*/
+
+#if 0
 struct global_request_handler
 {
   struct channel_handler super;
   
   struct alist *global_requests;
 };
+#endif
 
+/* CLASS:
+   (class
+     (name channel_open_handler)
+     (super channel_handler)
+     (vars
+       (channel_types object alist)))
+*/
+
+#if 0
 struct channel_open_handler
 {
   struct channel_handler super;
 
   struct alist *channel_types;
 };
-
-#if 0
-struct channel_request_handler
-{
-  struct channel_handler *super;
-
-  struct alist *request_types;
-};
 #endif
 
 struct lsh_string *format_global_failure(void)
@@ -152,9 +193,8 @@ struct lsh_string *prepare_window_adjust(struct ssh_channel *channel,
 
 struct channel_table *make_channel_table(void)
 {
-  struct channel_table *table;
+  NEW(channel_table, table);
 
-  NEW(table);
   table->channels = lsh_space_alloc(sizeof(struct ssh_channel *)
 				      * INITIAL_CHANNELS);
   table->allocated_channels = INITIAL_CHANNELS;
@@ -256,15 +296,13 @@ static int do_global_request(struct packet_handler *c,
 			     struct ssh_connection *connection,
 			     struct lsh_string *packet)
 {
-  struct global_request_handler *closure = (struct global_request_handler *) c;
+  CAST(global_request_handler, closure, c);
 
   struct simple_buffer buffer;
   int msg_number;
   int name;
   int want_reply;
   
-  MDEBUG(closure);
-
   simple_buffer_init(&buffer, packet->length, packet->data);
 
   if (parse_uint8(&buffer, &msg_number)
@@ -291,7 +329,7 @@ static int do_channel_open(struct packet_handler *c,
 			   struct ssh_connection *connection,
 			   struct lsh_string *packet)
 {
-  struct channel_open_handler *closure = (struct channel_open_handler *) c;
+  CAST(channel_open_handler, closure, c);
 
   struct simple_buffer buffer;
   int msg_number;
@@ -300,8 +338,6 @@ static int do_channel_open(struct packet_handler *c,
   UINT32 window_size;
   UINT32 max_packet;
   
-  MDEBUG(closure);
-
   simple_buffer_init(&buffer, packet->length, packet->data);
 
   if (parse_uint8(&buffer, &msg_number)
@@ -379,7 +415,7 @@ static int do_channel_request(struct packet_handler *c,
 			      struct ssh_connection *connection,
 			      struct lsh_string *packet)
 {
-  struct channel_handler *closure = (struct channel_handler *) c;
+  CAST(channel_handler, closure, c);
 
   struct simple_buffer buffer;
   int msg_number;
@@ -387,8 +423,6 @@ static int do_channel_request(struct packet_handler *c,
   int type;
   int want_reply;
 
-  MDEBUG(closure);
-
   simple_buffer_init(&buffer, packet->length, packet->data);
 
   if (parse_uint8(&buffer, &msg_number)
@@ -431,15 +465,13 @@ static int do_window_adjust(struct packet_handler *c,
 			    struct ssh_connection *connection,
 			    struct lsh_string *packet)
 {
-  struct channel_handler *closure = (struct channel_handler *) c;
+  CAST(channel_handler, closure, c);
 
   struct simple_buffer buffer;
   int msg_number;
   UINT32 channel_number;
   UINT32 size;
 
-  MDEBUG(closure);
-
   simple_buffer_init(&buffer, packet->length, packet->data);
 
   if (parse_uint8(&buffer, &msg_number)
@@ -481,15 +513,13 @@ static int do_channel_data(struct packet_handler *c,
 			   struct ssh_connection *connection,
 			   struct lsh_string *packet)
 {
-  struct channel_handler *closure = (struct channel_handler *) c;
+  CAST(channel_handler, closure, c);
 
   struct simple_buffer buffer;
   int msg_number;
   UINT32 channel_number;
   struct lsh_string *data;
   
-  MDEBUG(closure);
-
   simple_buffer_init(&buffer, packet->length, packet->data);
 
   if (parse_uint8(&buffer, &msg_number)
@@ -554,7 +584,7 @@ static int do_channel_extended_data(struct packet_handler *c,
 				    struct ssh_connection *connection,
 				    struct lsh_string *packet)
 {
-  struct channel_handler *closure = (struct channel_handler *) c;
+  CAST(channel_handler, closure, c);
 
   struct simple_buffer buffer;
   int msg_number;
@@ -562,8 +592,6 @@ static int do_channel_extended_data(struct packet_handler *c,
   UINT32 type;
   struct lsh_string *data;
   
-  MDEBUG(closure);
-
   simple_buffer_init(&buffer, packet->length, packet->data);
 
   if (parse_uint8(&buffer, &msg_number)
@@ -638,14 +666,12 @@ static int do_channel_eof(struct packet_handler *c,
 			  struct ssh_connection *connection,
 			  struct lsh_string *packet)
 {
-  struct channel_handler *closure = (struct channel_handler *) c;
+  CAST(channel_handler, closure, c);
 
   struct simple_buffer buffer;
   int msg_number;
   UINT32 channel_number;
   
-  MDEBUG(closure);
-
   simple_buffer_init(&buffer, packet->length, packet->data);
 
   if (parse_uint8(&buffer, &msg_number)
@@ -700,14 +726,12 @@ static int do_channel_close(struct packet_handler *c,
 			    struct ssh_connection *connection,
 			    struct lsh_string *packet)
 {
-  struct channel_handler *closure = (struct channel_handler *) c;
+  CAST(channel_handler, closure, c);
 
   struct simple_buffer buffer;
   int msg_number;
   UINT32 channel_number;
   
-  MDEBUG(closure);
-
   simple_buffer_init(&buffer, packet->length, packet->data);
 
   if (parse_uint8(&buffer, &msg_number)
@@ -758,7 +782,7 @@ static int do_channel_open_confirm(struct packet_handler *c,
 			      struct ssh_connection *connection,
 			      struct lsh_string *packet)
 {
-  struct channel_handler *closure = (struct channel_handler *) c;
+  CAST(channel_handler, closure, c);
 
   struct simple_buffer buffer;
   int msg_number;
@@ -767,8 +791,6 @@ static int do_channel_open_confirm(struct packet_handler *c,
   UINT32 window_size;
   UINT32 max_packet;
   
-  MDEBUG(closure);
-
   simple_buffer_init(&buffer, packet->length, packet->data);
 
   if (parse_uint8(&buffer, &msg_number)
@@ -805,7 +827,7 @@ static int do_channel_open_failure(struct packet_handler *c,
 			      struct ssh_connection *connection,
 			      struct lsh_string *packet)
 {
-  struct channel_handler *closure = (struct channel_handler *) c;
+  CAST(channel_handler, closure, c);
 
   struct simple_buffer buffer;
   int msg_number;
@@ -818,8 +840,6 @@ static int do_channel_open_failure(struct packet_handler *c,
   UINT8 *language;
   UINT32 language_length;
   
-  MDEBUG(closure);
-
   simple_buffer_init(&buffer, packet->length, packet->data);
 
   if (parse_uint8(&buffer, &msg_number)
@@ -858,14 +878,12 @@ static int do_channel_success(struct packet_handler *c,
 			      struct ssh_connection *connection,
 			      struct lsh_string *packet)
 {
-  struct channel_handler *closure = (struct channel_handler *) c;
+  CAST(channel_handler, closure, c);
 
   struct simple_buffer buffer;
   int msg_number;
   UINT32 channel_number;
   
-  MDEBUG(closure);
-
   simple_buffer_init(&buffer, packet->length, packet->data);
 
   if (parse_uint8(&buffer, &msg_number)
@@ -890,14 +908,12 @@ static int do_channel_failure(struct packet_handler *c,
 			      struct ssh_connection *connection,
 			      struct lsh_string *packet)
 {
-  struct channel_handler *closure = (struct channel_handler *) c;
+  CAST(channel_handler, closure, c);
 
   struct simple_buffer buffer;
   int msg_number;
   UINT32 channel_number;
   
-  MDEBUG(closure);
-
   simple_buffer_init(&buffer, packet->length, packet->data);
 
   if (parse_uint8(&buffer, &msg_number)
@@ -921,88 +937,75 @@ static int do_channel_failure(struct packet_handler *c,
 static int init_connection_service(struct ssh_service *s,
 				   struct ssh_connection *connection)
 {
-  struct connection_service *self = (struct connection_service *) s;
+  CAST(connection_service, self, s);
+
   struct channel_table *table;
   
-  struct global_request_handler *globals;
-  struct channel_open_handler *open;
-  struct channel_handler *request;
-
-  struct channel_handler *adjust;
-  struct channel_handler *data;
-  struct channel_handler *extended;
+  NEW(global_request_handler, globals);
+  NEW(channel_open_handler, open);
+  NEW(channel_handler, request);
 
-  struct channel_handler *eof;
-  struct channel_handler *close;
+  NEW(channel_handler, adjust);
+  NEW(channel_handler, data);
+  NEW(channel_handler, extended);
 
-  struct channel_handler *open_confirm;
-  struct channel_handler *open_failure;
+  NEW(channel_handler, eof);
+  NEW(channel_handler, close);
 
-  struct channel_handler *channel_success;
-  struct channel_handler *channel_failure;
+  NEW(channel_handler, open_confirm);
+  NEW(channel_handler, open_failure);
 
-  MDEBUG(self);
+  NEW(channel_handler, channel_success);
+  NEW(channel_handler, channel_failure);
 
   table = make_channel_table();
   
-  NEW(globals);
   globals->super.super.handler = do_global_request;
   globals->super.table = table;
   globals->global_requests = self->global_requests;
   connection->dispatch[SSH_MSG_GLOBAL_REQUEST] = &globals->super.super;
     
-  NEW(open);
   open->super.super.handler = do_channel_open;
   open->super.table = table;
   open->channel_types = self->channel_types;
   connection->dispatch[SSH_MSG_CHANNEL_OPEN] = &open->super.super;
 
-  NEW(request);
   request->super.handler = do_channel_request;
   request->table = table;
   connection->dispatch[SSH_MSG_CHANNEL_REQUEST] = &request->super;
   
-  NEW(adjust);
   adjust->super.handler = do_window_adjust;
   adjust->table = table;
   connection->dispatch[SSH_MSG_CHANNEL_WINDOW_ADJUST] = &adjust->super;
 
-  NEW(data);
   data->super.handler = do_channel_data;
   data->table = table;
   connection->dispatch[SSH_MSG_CHANNEL_DATA] = &data->super;
 
-  NEW(extended);
   extended->super.handler = do_channel_extended_data;
   extended->table = table;
   connection->dispatch[SSH_MSG_CHANNEL_WINDOW_ADJUST] = &extended->super;
 
-  NEW(eof);
   eof->super.handler = do_channel_eof;
   eof->table = table;
   connection->dispatch[SSH_MSG_CHANNEL_EOF] = &eof->super;
 
-  NEW(close);
   close->super.handler = do_channel_close;
   close->table = table;
   connection->dispatch[SSH_MSG_CHANNEL_CLOSE] = &close->super;
 
-  NEW(open_confirm);
   open_confirm->super.handler = do_channel_open_confirm;
   open_confirm->table = table;
   connection->dispatch[SSH_MSG_CHANNEL_OPEN_CONFIRMATION] = &open_confirm->super;
 
-  NEW(open_failure);
   open_failure->super.handler = do_channel_open_failure;
   open_failure->table = table;
   connection->dispatch[SSH_MSG_CHANNEL_OPEN_FAILURE] = &open_failure->super;
   
-  NEW(channel_success);
   channel_success->super.handler = do_channel_success;
   channel_success->table = table;
   connection->dispatch[SSH_MSG_CHANNEL_SUCCESS] = &channel_success->super;
 
-  NEW(channel_failure);
   channel_failure->super.handler = do_channel_failure;
   channel_failure->table = table;
   connection->dispatch[SSH_MSG_CHANNEL_FAILURE] = &channel_failure->super;
@@ -1016,9 +1019,7 @@ struct ssh_service *make_connection_service(struct alist *global_requests,
 					    struct alist *channel_types,
 					    struct connection_startup *start)
 {
-  struct connection_service *self;
-
-  NEW(self);
+  NEW(connection_service, self);
 
   self->super.init = init_connection_service;
   self->global_requests = global_requests;
@@ -1118,17 +1119,37 @@ struct lsh_string *channel_transmit_extended(struct ssh_channel *channel,
 }
 
 /* Writing data to a channel */
+/* CLASS:
+   (class
+     (name channel_write)
+     (super abstract_write)
+     (vars
+       (channel object ssh_channel)))
+*/
+
+#if 0
 struct channel_write
 {
   struct abstract_write super;
   struct ssh_channel *channel;
 };
+#endif
+
+/* CLASS:
+   (class
+     (name channel_write_extended)
+     (super channel_write)
+     (vars
+       (type simple UINT32)))
+*/
 
+#if 0
 struct channel_write_extended
 {
   struct channel_write super;
   UINT32 type;
 };
+#endif
 
 static int do_channel_write(struct abstract_write *w,
 			    struct lsh_string *packet)
@@ -1142,7 +1163,7 @@ static int do_channel_write(struct abstract_write *w,
 static int do_channel_write_extended(struct abstract_write *w,
 				     struct lsh_string *packet)
 {
-  struct channel_write_extended *closure = (struct channel_write_extended *) w;
+  CAST(channel_write_extended, closure, w);
 
   return A_WRITE(closure->super.channel->write,
 		 channel_transmit_extended(closure->super.channel,
@@ -1152,9 +1173,7 @@ static int do_channel_write_extended(struct abstract_write *w,
 
 struct abstract_write *make_channel_write(struct ssh_channel *channel)
 {
-  struct channel_write *closure;
-
-  NEW(closure);
+  NEW(channel_write, closure);
 
   closure->super.write = do_channel_write;
   closure->channel = channel;
@@ -1165,9 +1184,7 @@ struct abstract_write *make_channel_write(struct ssh_channel *channel)
 struct abstract_write *make_channel_write_extended(struct ssh_channel *channel,
 						   UINT32 type)
 {
-  struct channel_write_extended *closure;
-
-  NEW(closure);
+  NEW(channel_write_extended, closure);
 
   closure->super.super.write = do_channel_write_extended;
   closure->super.channel = channel;
@@ -1188,17 +1205,25 @@ struct read_handler *make_channel_read_stderr(struct ssh_channel *channel)
 						    SSH_EXTENDED_DATA_STDERR));
 }    
 
+/* CLASS:
+   (class
+     (name channel_close_callback)
+     (super close_callback)
+     (vars
+       (channel object ssh_channel)))
+*/
+
+#if 0
 struct channel_close_callback
 {
   struct close_callback super;
   struct ssh_channel *channel;
 };
+#endif
 
 static int channel_close_callback(struct close_callback *c, int reason)
 {
-  struct channel_close_callback *closure = (struct channel_close_callback *)c;
-
-  MDEBUG(closure);
+  CAST(channel_close_callback, closure, c);
 
   channel_close(closure->channel);
 
@@ -1208,9 +1233,8 @@ static int channel_close_callback(struct close_callback *c, int reason)
   
 struct close_callback *make_channel_close(struct ssh_channel *channel)
 {
-  struct channel_close_callback *closure;
-
-  NEW(closure);
+  NEW(channel_close_callback, closure);
+  
   closure->super.f = channel_close_callback;
   closure->channel = channel;
 
diff --git a/src/channel.h b/src/channel.h
index 88dc0811b45b0e5dfe75be1cec2bb840916e9455..46db8e7717419554eff1d2f7c01e7509c9e3e012 100644
--- a/src/channel.h
+++ b/src/channel.h
@@ -93,6 +93,7 @@
        ; Reply from SSH_MSG_CHANNEL_REQUEST 
        (channel_success method int)
        (channel_failure method int)))
+*/
 
 #if 0
 struct ssh_channel
diff --git a/src/client.c b/src/client.c
index bfaae72d4008c74a8d5831fdf229071a6907ca44..8fa1193005caf191177603a2f23d0faf848ad1f8 100644
--- a/src/client.c
+++ b/src/client.c
@@ -50,7 +50,23 @@
 #include <string.h>
 #include <assert.h>
 
+#include "client.c.x"
+
 /* Handle connection and initial handshaking. */
+/* CLASS:
+   (class
+     (name client_callback)
+     (super fd_callback)
+     (vars
+       (backend object io_backend)
+       (block_size simple UINT32)
+       (id_comment simple "char *")
+       (random object randomness)
+       (init object make_kexinit)
+       (kexinit_handler object packet_handler)))
+*/
+
+#if 0     
 struct client_callback
 {
   struct fd_callback super;
@@ -62,6 +78,7 @@ struct client_callback
   struct make_kexinit *init;
   struct packet_handler *kexinit_handler;
 };
+#endif
 
 static int client_initiate(struct fd_callback **c,
 			   int fd)
@@ -71,7 +88,6 @@ static int client_initiate(struct fd_callback **c,
 
   int res;
   
-
   struct ssh_connection *connection
     = make_ssh_connection(closure->kexinit_handler);
 
@@ -98,21 +114,28 @@ static int client_initiate(struct fd_callback **c,
 				    NULL);
 }
 
+/* CLASS:
+   (class
+     (name client_line_handler)
+     (super line_handler)
+     (vars
+       (connection object ssh_connection)))
+*/
+
+#if 0
 struct client_line_handler
 {
   struct line_handler super;
   struct ssh_connection *connection;
 };
+#endif
 
 static struct read_handler *do_line(struct line_handler **h,
 				    UINT32 length,
 				    UINT8 *line)
 {
-  struct client_line_handler *closure
-    = (struct client_line_handler *) *h;
+  CAST(client_line_handler, closure, *h);
 
-  MDEBUG(closure);
-  
   if ( (length >= 4) && !memcmp(line, "SSH-", 4))
     {
       /* Parse and remember format string */
@@ -138,7 +161,7 @@ static struct read_handler *do_line(struct line_handler **h,
 	  verbose("\n");
 	  
 	  /* FIXME: Cleanup properly. */
-	  lsh_object_free(closure);
+	  KILL(closure);
 
 	  return new;
 	}
@@ -149,7 +172,7 @@ static struct read_handler *do_line(struct line_handler **h,
 	  werror("\n");
 
 	  /* FIXME: Clean up properly */
-	  lsh_object_free(closure);
+	  KILL(closure);
 	  *h = NULL;
 		  
 	  return 0;
@@ -167,9 +190,7 @@ static struct read_handler *do_line(struct line_handler **h,
 
 struct read_handler *make_client_read_line(struct ssh_connection *c)
 {
-  struct client_line_handler *closure;
-
-  NEW(closure);
+  NEW(client_line_handler, closure);
 
   closure->super.handler = do_line;
   closure->connection = c;
@@ -186,9 +207,7 @@ make_client_callback(struct io_backend *b,
 		     struct packet_handler *kexinit_handler)
   
 {
-  struct client_callback *connected;
-
-  NEW(connected);
+  NEW(client_callback, connected);
 
   connected->super.f = client_initiate;
   connected->backend = b;
@@ -214,9 +233,7 @@ static int client_close_die(struct close_callback *closure, int reason)
 
 struct close_callback *make_client_close_handler(void)
 {
-  struct close_callback *c;
-
-  NEW(c);
+  NEW(close_callback, c);
 
   c->f = client_close_die;
 
@@ -224,6 +241,16 @@ struct close_callback *make_client_close_handler(void)
 }
 
 /* Start a service that the server has accepted (for instance ssh-userauth). */
+/* CLASS:
+   (class
+     (name accept_service_handler)
+     (super packet_handler)
+     (vars
+       (service_name simple int)
+       (service object ssh_service)))
+*/
+
+#if 0
 struct accept_service_handler
 {
   struct packet_handler super;
@@ -231,19 +258,18 @@ struct accept_service_handler
   int service_name;
   struct ssh_service *service;
 };
+#endif
 
 static int do_accept_service(struct packet_handler *c,
 			     struct ssh_connection *connection,
 			     struct lsh_string *packet)
 {
-  struct accept_service_handler *closure = (struct accept_service_handler *) c;
+  CAST(accept_service_handler, closure, c);
 
   struct simple_buffer buffer;
   int msg_number;
   int name;
 
-  MDEBUG(closure);
-
   simple_buffer_init(&buffer, packet->length, packet->data);
   
   if (parse_uint8(&buffer, &msg_number)
@@ -265,9 +291,8 @@ static int do_accept_service(struct packet_handler *c,
 struct packet_handler *make_accept_service_handler(int service_name,
 						   struct ssh_service *service)
 {
-  struct accept_service_handler *closure;
+  NEW(accept_service_handler, closure);
 
-  NEW(closure);
   closure->super.handler = do_accept_service;
   closure->service_name = service_name;
   closure->service = service;
@@ -275,6 +300,16 @@ struct packet_handler *make_accept_service_handler(int service_name,
   return &closure->super;
 }
 
+/* CLASS:
+   (class
+     (name service_request)
+     (super ssh_service)
+     (vars
+       (service_name simple int)
+       (service object ssh_service)))
+*/
+
+#if 0
 struct service_request
 {
   struct ssh_service super;
@@ -282,14 +317,13 @@ struct service_request
   int service_name;
   struct ssh_service *service;
 };
+#endif
 
 static int do_request_service(struct ssh_service *c,
 			      struct ssh_connection *connection)
 {
-  struct service_request *closure = (struct service_request *) c;
+  CAST(service_request, closure, c);
   
-  MDEBUG(closure);
-
   connection->dispatch[SSH_MSG_SERVICE_ACCEPT]
     = make_accept_service_handler(closure->service_name,
 				  closure->service);
@@ -300,9 +334,8 @@ static int do_request_service(struct ssh_service *c,
 struct ssh_service *request_service(int service_name,
 				    struct ssh_service *service)
 {
-  struct service_request *closure;
+  NEW(service_request, closure);
 
-  NEW(closure);
   closure->super.init = do_request_service;
   closure->service_name = service_name;
   closure->service = service;
@@ -311,6 +344,25 @@ struct ssh_service *request_service(int service_name,
 }
 
 /* Initiate and manage a session */
+/* CLASS:
+   (class
+     (name client_session)
+     (super ssh_channel)
+     (vars
+       ; Exec or shell request. 
+       (final_request simple int)
+       (args string)
+  
+       ; To access stdio
+       (in object io_fd)
+       (out object io_fd)
+       (err object io_fd)
+
+       ; Where to save the exit code.
+       (exit_status simple "int *")))
+*/
+
+#if 0
 struct client_session
 {
   struct ssh_channel super;
@@ -327,13 +379,12 @@ struct client_session
   /* Where to save the exit code. */
   int *exit_status;
 };
+#endif
 
 static int close_client_session(struct ssh_channel *c)
 {
-  struct client_session *session = (struct client_session *) c;
+  CAST(client_session, session, c);
   
-  MDEBUG(session);
-
   close_fd(&session->in->super, 0);
 #if 0
   close_fd(&session->out->super, 0);
@@ -345,10 +396,8 @@ static int close_client_session(struct ssh_channel *c)
 
 static int client_session_die(struct ssh_channel *c)
 {
-  struct client_session *closure = (struct client_session *) c;
+  CAST(client_session, closure, c);
   
-  MDEBUG(closure);
-
   /* FIXME: Don't die this hard. */
   if ( (closure->super.flags & (CHANNEL_SENT_CLOSE | CHANNEL_RECIEVED_CLOSE))
        ==  (CHANNEL_SENT_CLOSE | CHANNEL_RECIEVED_CLOSE))
@@ -357,23 +406,31 @@ static int client_session_die(struct ssh_channel *c)
   exit(EXIT_FAILURE);
 }
 
+/* CLASS:
+   (class
+     (name exit_handler)
+     (super channel_request)
+     (vars
+       (exit_status simple "int *")))
+*/
+
+#if 0
 struct exit_handler
 {
   struct channel_request super;
 
   int *exit_status;
 };
+#endif
 
 static int do_exit_status(struct channel_request *c,
 			  struct ssh_channel *channel,
 			  int want_reply,
 			  struct simple_buffer *args)
 {
-  struct exit_handler *closure = (struct exit_handler *) c;
+  CAST(exit_handler, closure, c);
   int status;
 
-  MDEBUG(closure);
-  
   if (!want_reply
       && parse_uint32(args, &status)
       && parse_eod(args))
@@ -395,6 +452,8 @@ static int do_exit_signal(struct channel_request *c,
 			  int want_reply,
 			  struct simple_buffer *args)
 {
+  CAST(exit_handler, closure, c);
+
   int signal;
   int core;
 
@@ -404,10 +463,6 @@ static int do_exit_signal(struct channel_request *c,
   UINT8 *language;
   UINT32 language_length;
   
-  struct exit_handler *closure = (struct exit_handler *) c;
-
-  MDEBUG(closure);
-  
   if (!want_reply
       && parse_uint32(args, &signal)
       && parse_boolean(args, &core)
@@ -440,9 +495,8 @@ static int do_exit_signal(struct channel_request *c,
 
 struct channel_request *make_handle_exit_status(int *exit_status)
 {
-  struct exit_handler *self;
+  NEW(exit_handler, self);
 
-  NEW(self);
   self->super.handler = do_exit_status;
 
   self->exit_status = exit_status;
@@ -452,9 +506,8 @@ struct channel_request *make_handle_exit_status(int *exit_status)
 
 struct channel_request *make_handle_exit_signal(int *exit_status)
 {
-  struct exit_handler *self;
+  NEW(exit_handler, self);
 
-  NEW(self);
   self->super.handler = do_exit_signal;
 
   self->exit_status = exit_status;
@@ -466,10 +519,8 @@ struct channel_request *make_handle_exit_signal(int *exit_status)
 static int do_recieve(struct ssh_channel *c,
 		      int type, struct lsh_string *data)
 {
-  struct client_session *closure = (struct client_session *) c;
+  CAST(client_session, closure, c);
   
-  MDEBUG(closure);
-
   switch(type)
     {
     case CHANNEL_DATA:
@@ -484,9 +535,7 @@ static int do_recieve(struct ssh_channel *c,
 /* We may send more data */
 static int do_send(struct ssh_channel *c)
 {
-  struct client_session *closure = (struct client_session *) c;
-
-  MDEBUG(closure);
+  CAST(client_session, closure, c);
 
   assert(closure->in->super.read);
   assert(closure->in->handler);
@@ -498,10 +547,8 @@ static int do_send(struct ssh_channel *c)
 /* We have a remote shell */
 static int do_io(struct ssh_channel *channel)
 {
-  struct client_session *closure = (struct client_session *) channel;
+  CAST(client_session, closure, channel);
   
-  MDEBUG(closure);
-
   channel->recieve = do_recieve;
   
   closure->out->super.close_callback
@@ -523,11 +570,9 @@ static int do_io(struct ssh_channel *channel)
 /* We have opened a channel of type "session" */
 static int do_open_confirm(struct ssh_channel *c)
 {
-  struct client_session *closure = (struct client_session *) c;
+  CAST(client_session, closure, c);
   struct lsh_string *args;
   
-  MDEBUG(closure);
-
   closure->super.open_confirm = NULL;
   closure->super.open_failure = NULL;
 
@@ -550,9 +595,7 @@ static struct ssh_channel *make_client_session(struct io_fd *in,
 					       struct lsh_string *args,
 					       int *exit_status)
 {
-  struct client_session *self;
-
-  NEW(self);
+  NEW(client_session, self);
 
   init_channel(&self->super);
 
@@ -577,6 +620,25 @@ static struct ssh_channel *make_client_session(struct io_fd *in,
   return &self->super;
 }
 
+/* CLASS:
+   (class
+     (name client_startup)
+     (super connection_startup)
+     (vars
+       (session object ssh_channel)
+       
+       ; Exec or shell request. 
+       ;; (final_request simple int)
+       ;; (args string)
+  
+       ; To access stdio 
+       ;; (in object io_fd)
+       ;; (out object io_fd)
+       ;; (err object io_fd)
+       ))
+*/
+
+#if 0
 struct client_startup
 {
   struct connection_startup super;
@@ -593,16 +655,15 @@ struct client_startup
   struct io_fd *err;
 #endif
 };
+#endif
 
 static int do_client_startup(struct connection_startup *c,
 			     struct channel_table *table,
 			     struct abstract_write *write)
 {
-  struct client_startup *closure = (struct client_startup *) c;
+  CAST(client_startup, closure, c);
   struct lsh_string *s;
   
-  MDEBUG(closure);
-
   closure->session->write = write;
   
   closure->session->open_confirm = do_open_confirm;
@@ -626,9 +687,8 @@ struct connection_startup *make_client_startup(struct io_fd *in,
 					       struct lsh_string *args,
 					       int *exit_status)
 {
-  struct client_startup *closure;
+  NEW(client_startup, closure);
   
-  NEW(closure);
   closure->super.start = do_client_startup;
   closure->session = make_client_session(in, out, err,
 					 WINDOW_SIZE,
diff --git a/src/client_keyexchange.c b/src/client_keyexchange.c
index 1d09099809604ad963703227055668a650e8ba57..59017c8aa79530344c13324aa91f68669454ff58 100644
--- a/src/client_keyexchange.c
+++ b/src/client_keyexchange.c
@@ -30,14 +30,43 @@
 #include "werror.h"
 #include "xalloc.h"
 
+#define CLASS_DEFINE
+#include "client_keyexchange.h.x"
+#undef CLASS_DEFINE
+
+#include "client_keyexchange.c.x"
+
+/* CLASS:
+   (class
+     (name dh_client_exchange)
+     (super keyexchange_algorithm)
+     (vars
+       (dh object diffie_hellman_method)
+       (verifier object lookup_verifier)))
+*/
+
+#if 0     
 struct dh_client_exchange
 {
   struct keyexchange_algorithm super;
   struct diffie_hellman_method *dh;
   struct lookup_verifier *verifier;
 };
+#endif
 
 /* Handler for the kex_dh_reply message */
+/* CLASS:
+   (class
+     (name dh_client)
+     (super packet_handler)
+     (vars
+       (dh struct diffie_hellman_instance)
+       (verifier object lookup_verifier)
+       (install object install_keys)
+       (finished object ssh_service)))
+*/
+
+#if 0
 struct dh_client
 {
   struct packet_handler super;
@@ -47,19 +76,18 @@ struct dh_client
   
   struct ssh_service *finished;
 };
-
+#endif
+    
 static int do_handle_dh_reply(struct packet_handler *c,
 			      struct ssh_connection *connection,
 			      struct lsh_string *packet)
 {
-  struct dh_client *closure = (struct dh_client *) c;
+  CAST(dh_client, closure, c);
   struct verifier *v;
   struct hash_instance *hash;
   struct lsh_string *s;
   int res;
 
-  MDEBUG(closure);
-  
   verbose("handle_dh_reply()\n");
   
   if (!dh_process_server_msg(&closure->dh, packet))
@@ -105,7 +133,7 @@ static int do_handle_dh_reply(struct packet_handler *c,
   /* FIXME: Return value is ignored */
   (void) INSTALL_KEYS(closure->install, connection, hash);
 
-  lsh_object_free(hash);
+  KILL(hash);
 
   connection->dispatch[SSH_MSG_KEXDH_REPLY] = connection->fail;
   connection->kex_state = KEX_STATE_NEWKEYS;
@@ -122,18 +150,15 @@ static int do_init_dh(struct keyexchange_algorithm *c,
 		      struct ssh_service *finished,
 		      int hostkey_algorithm_atom,
 		      struct signature_algorithm *ignored,
-		      void **algorithms)
+		      struct object_list *algorithms)
 {
-  struct dh_client_exchange *closure = (struct dh_client_exchange *) c;
-  struct dh_client *dh;
+  CAST(dh_client_exchange, closure, c);
+  NEW(dh_client, dh);
 
   int res;
 
-  MDEBUG(closure);
-  MDEBUG_SUBTYPE(connection);
-  MDEBUG_SUBTYPE(ignored);
-
-  NEW(dh);
+  CHECK_SUBTYPE(ssh_connection, connection);
+  CHECK_SUBTYPE(signature_algorithm, ignored);
 
   /* FIXME: Use this value to choose a verifier function */
   if (hostkey_algorithm_atom != ATOM_SSH_DSS)
@@ -171,11 +196,9 @@ struct keyexchange_algorithm *
 make_dh_client(struct diffie_hellman_method *dh,
 	       struct lookup_verifier *verifier)
 {
-  struct dh_client_exchange *self;
-
-  NEW(self);
+  NEW(dh_client_exchange, self);
 
-  MDEBUG(dh);
+  CHECK_TYPE(diffie_hellman_method, dh);
   
   self->super.init = do_init_dh;
   self->dh = dh;
@@ -184,11 +207,24 @@ make_dh_client(struct diffie_hellman_method *dh,
   return &self->super;
 }
 
+/* FIXME: This is identical to the server_install_keys structure in
+ * server_keyexchange.c. It should probably be moved somewhere else. */
+
+/* CLASS:
+   (class
+     (name client_install_keys)
+     (super install_keys)
+     (vars
+       (algorithms object object_list)))
+*/
+
+#if 0
 struct client_install_keys
 {
   struct install_keys super;
-  void **algorithms;
+  struct object_list *algorithms;
 };
+#endif
 
 static int do_install(struct install_keys *c,
 		      struct ssh_connection *connection,
@@ -198,9 +234,7 @@ static int do_install(struct install_keys *c,
    * happens to be weak. */
   /* FIXME: No IV:s */
 
-  struct client_install_keys *closure = (struct client_install_keys *) c;
-
-  MDEBUG(closure);
+  CAST(client_install_keys, closure, c);
 
   /* Keys for recieving */
   connection->dispatch[SSH_MSG_NEWKEYS] = make_newkeys_handler
@@ -223,11 +257,9 @@ static int do_install(struct install_keys *c,
   return 1;
 }
 
-struct install_keys *make_client_install_keys(void **algorithms)
+struct install_keys *make_client_install_keys(struct object_list *algorithms)
 {
-  struct client_install_keys *self;
-
-  NEW(self);
+  NEW(client_install_keys, self);
 
   self->super.install = do_install;
   self->algorithms = algorithms;
diff --git a/src/client_keyexchange.h b/src/client_keyexchange.h
index caf954d5fabfbc0923f63065387bc0ac63f00138..f4bb505deb10d43234b2a86dd902b606dc3527c7 100644
--- a/src/client_keyexchange.h
+++ b/src/client_keyexchange.h
@@ -29,6 +29,10 @@
 #include "keyexchange.h"
 #include "publickey_crypto.h"
 
+#define CLASS_DECLARE
+#include "client_keyexchange.h.x"
+#undef CLASS_DECLARE
+
 /* Maps a key blob to a signature verifier, using some signature
  * algorithm and some method to determine the authenticity of the key.
  * Returns NULL If the key is invalid or not trusted. */
@@ -57,6 +61,6 @@ struct keyexchange_algorithm *
 make_dh_client(struct diffie_hellman_method *dh,
 	       struct lookup_verifier *verifier);
 
-struct install_keys *make_client_install_keys(void **algorithms);
+struct install_keys *make_client_install_keys(struct object_list *algorithms);
 
 #endif /* LSH_CLIENT_KEYEXCHANGE_H_INCLUDED */
diff --git a/src/client_userauth.c b/src/client_userauth.c
index 24e4c586d6679b288cb4fd422007d28e22e72142..ab7abc4ab1493e19d2cb0b6e11f7fd545d65d389 100644
--- a/src/client_userauth.c
+++ b/src/client_userauth.c
@@ -46,9 +46,26 @@
  * the lock and turning it around).
  *
  * If none of the keys were recognized, or if no keys were available
- *from the start, we ask the user for a password and attempts to log
- *in using that. */
+ * from the start, we ask the user for a password and attempts to log
+ * in using that. */
 
+#include "client_userauth.c.x"
+
+/* CLASS:
+   (class
+     (name client_userauth)
+     (super ssh_service)
+     (vars
+       (username string)            ; Remote user name to authenticate as.
+
+       (service_name simple int)    ; Service we want to access .
+       (service object ssh_service)
+  
+       ; FIXME: Keys to try
+       ))
+*/
+
+#if 0
 struct client_userauth
 {
   struct ssh_service super;
@@ -59,20 +76,41 @@ struct client_userauth
   
   /* FIXME: Keys to try */
 };
+#endif
+
+/* CLASS:
+   (class
+     (name success_handler)
+     (super packet_handler)
+     (vars
+       (service object ssh_service)))
+*/
 
+#if 0
 struct success_handler
 {
   struct packet_handler super;
 
   struct ssh_service *service;
 };
+#endif
+
+/* CLASS:
+   (class
+     (name failure_handler)
+     (super packet_handler)
+     (vars
+       (userauth object client_userauth)))
+*/
 
+#if 0
 struct failure_handler
 {
   struct packet_handler super;
 
   struct client_userauth *userauth;
 };
+#endif
 
 static struct lsh_string *format_userauth_password(struct lsh_string *name,
 						   int service,
@@ -112,13 +150,11 @@ static int do_userauth_success(struct packet_handler *c,
 				struct ssh_connection *connection,
 				struct lsh_string *packet)
 {
-  struct success_handler *closure = (struct success_handler *) c;
+  CAST(success_handler, closure, c);
   struct simple_buffer buffer;
 
   int msg_number;
     
-  MDEBUG(closure);
-
   simple_buffer_init(&buffer, packet->length, packet->data);
 
   if (parse_uint8(&buffer, &msg_number)
@@ -144,15 +180,13 @@ static int do_userauth_failure(struct packet_handler *c,
 			       struct ssh_connection *connection,
 			       struct lsh_string *packet)
 {
-  struct failure_handler *closure = (struct failure_handler *) c;
+  CAST(failure_handler, closure, c);
   struct simple_buffer buffer;
 
   int msg_number;
-  int *methods = NULL;
+  struct int_list *methods = NULL;
   int partial_success;
     
-  MDEBUG(closure);
-
   simple_buffer_init(&buffer, packet->length, packet->data);
 
   if (parse_uint8(&buffer, &msg_number)
@@ -169,24 +203,24 @@ static int do_userauth_failure(struct packet_handler *c,
 	{ /* Doesn't help us */
 	  werror("Recieved SSH_MSH_USERAUTH_FAILURE "
 		 "indicating partial success.\n");
-	  lsh_space_free(methods);
+	  KILL(methods);
 
 	  return LSH_FAIL | LSH_DIE;
 	}
-      for(i = 0; methods[i] >= 0; i++)
-	if (methods[i] == ATOM_PASSWORD)
+
+      for(i = 0; i < LIST_LENGTH(methods); i++)
+	if (LIST(methods)[i] == ATOM_PASSWORD)
 	  {
 	    /* Try again */
-	    lsh_space_free(methods);
+	    KILL(methods);
 	    return send_passwd(closure->userauth, connection);
 	  }
       /* No methods that we can use */
-      lsh_space_free(methods);
+      KILL(methods);
       return LSH_FAIL | LSH_DIE;
     }
 
-  if (methods)
-    lsh_space_free(methods);
+  KILL(methods);
   
   lsh_string_free(packet);
   return LSH_FAIL | LSH_DIE;
@@ -205,7 +239,7 @@ static int do_userauth_banner(struct packet_handler *closure,
   UINT32 language_length;
   UINT8 *language;
   
-  MDEBUG(closure);
+  CHECK_TYPE(packet_handler, closure);
 
   simple_buffer_init(&buffer, packet->length, packet->data);
 
@@ -227,9 +261,8 @@ static int do_userauth_banner(struct packet_handler *closure,
 
 static struct packet_handler *make_success_handler(struct ssh_service *service)
 {
-  struct success_handler *self;
+  NEW(success_handler, self);
 
-  NEW(self);
   self->super.handler = do_userauth_success;
   self->service = service;
 
@@ -239,9 +272,8 @@ static struct packet_handler *make_success_handler(struct ssh_service *service)
 static struct packet_handler *
 make_failure_handler(struct client_userauth *userauth)
 {
-  struct failure_handler *self;
+  NEW(failure_handler, self);
 
-  NEW(self);
   self->super.handler = do_userauth_failure;
   self->userauth = userauth;
 
@@ -250,9 +282,8 @@ make_failure_handler(struct client_userauth *userauth)
 
 static struct packet_handler *make_banner_handler()
 {
-  struct packet_handler *self;
+  NEW(packet_handler, self);
 
-  NEW(self);
   self->handler = do_userauth_banner;
   
   return self;
@@ -261,9 +292,7 @@ static struct packet_handler *make_banner_handler()
 static int init_client_userauth(struct ssh_service *c,
 				struct ssh_connection *connection)
 {
-  struct client_userauth *closure = (struct client_userauth *) c;
-
-  MDEBUG(closure);
+  CAST(client_userauth, closure, c);
 
   connection->dispatch[SSH_MSG_USERAUTH_SUCCESS]
     = make_success_handler(closure->service);
@@ -279,9 +308,7 @@ struct ssh_service *make_client_userauth(struct lsh_string *username,
 					 int service_name,
 					 struct ssh_service *service)
 {
-  struct client_userauth *closure;
-
-  NEW(closure);
+  NEW(client_userauth, closure);
 
   closure->super.init = init_client_userauth;
   closure->username = username;
diff --git a/src/connection.c b/src/connection.c
index 65881c5d89ba126bc5828bd3841959e3f9356148..818a921fc0fd54a33c70bf3435ab9f84fa42931d 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -41,7 +41,7 @@
 static int handle_connection(struct abstract_write *w,
 			     struct lsh_string *packet)
 {
-  CAST(closure, ssh_connection, w);
+  CAST(ssh_connection, closure, w);
   UINT8 msg;
 
   if (!packet->length)
diff --git a/src/crypto.c b/src/crypto.c
index f5638f502e83f278a9bb3cd1e83ed8af154310a4..fc715782ee682f0dfd103f0728634e0bf4289299 100644
--- a/src/crypto.c
+++ b/src/crypto.c
@@ -33,6 +33,9 @@
 #include "werror.h"
 #include "xalloc.h"
 
+#include "crypto.c.x"
+
+#if 0
 /* No crypto */
 static void do_crypt_none(struct crypto_instance *ignored,
 			  UINT32 length, UINT8 *dst, UINT8 *src)
@@ -49,20 +52,29 @@ struct crypto_instance crypto_none_instance =
   8,
   do_crypt_none
 };
-
+#endif
+
+/* CLASS:
+   (class
+     (name rc4_instance)
+     (super crypto_instance)
+     (vars
+       (ctx simple "struct rc4_ctx")))
+*/
+   
+#if 0
 struct rc4_instance
 {
   struct crypto_instance super;
   struct rc4_ctx ctx;
 };
+#endif
 
 static void do_crypt_rc4(struct crypto_instance *s,
 			 UINT32 length, UINT8 *src, UINT8 *dst)
 {
-  struct rc4_instance *self = (struct rc4_instance *) s;
+  CAST(rc4_instance, self, s);
 
-  MDEBUG(self);
-  
   if (length % 8)
     fatal("Internal error\n");
 
@@ -72,9 +84,7 @@ static void do_crypt_rc4(struct crypto_instance *s,
 static struct crypto_instance *
 make_rc4_instance(struct crypto_algorithm *ignored, int mode, UINT8 *key)
 {
-  struct rc4_instance *self;
-
-  NEW(self);
+  NEW(rc4_instance, self);
 
   self->super.block_size = 8;
   self->super.crypt = do_crypt_rc4;
@@ -89,29 +99,35 @@ struct crypto_algorithm crypto_rc4_algorithm =
   8, 16, make_rc4_instance };
 
 /* SHA1 hash */
+/* CLASS:
+   (class
+     (name sha_instance)
+     (super hash_instance)
+     (vars
+       (ctx simple "struct sha_ctx")))
+*/
+
+#if 0
 struct sha_instance
 {
   struct hash_instance super;
   struct sha_ctx ctx;
 };
+#endif
 
 static void do_sha_update(struct hash_instance *s,
 			  UINT32 length, UINT8 *data)
 {
-  struct sha_instance *self = (struct sha_instance *) s;
+  CAST(sha_instance, self, s);
 
-  MDEBUG(self);
-  
   sha_update(&self->ctx, data, length);
 }
 
 static void do_sha_digest(struct hash_instance *s,
 			  UINT8 *dst)
 {
-  struct sha_instance *self = (struct sha_instance *) s;
+  CAST(sha_instance, self, s);
 
-  MDEBUG(self);
-  
   sha_final(&self->ctx);
   sha_digest(&self->ctx, dst);
   sha_init(&self->ctx);
@@ -119,12 +135,8 @@ static void do_sha_digest(struct hash_instance *s,
 
 static struct hash_instance *do_sha_copy(struct hash_instance *s)
 {
-  struct sha_instance *self = (struct sha_instance *) s;
-  struct sha_instance *new;
-
-  MDEBUG(self);
-
-  NEW(new);
+  CAST(sha_instance, self, s);
+  NEW(sha_instance, new);
 
   memcpy(new, self, sizeof(*self));
   return &new->super;
@@ -132,9 +144,7 @@ static struct hash_instance *do_sha_copy(struct hash_instance *s)
 
 static struct hash_instance *make_sha_instance(struct hash_algorithm *ignored)
 {
-  struct sha_instance *res;
-
-  NEW(res);
+  NEW(sha_instance, res);
 
   res->super.hash_size = 20;
   res->super.update = do_sha_update;
@@ -151,13 +161,36 @@ struct hash_algorithm sha_algorithm =
   SHA_DATASIZE, SHA_DIGESTSIZE, make_sha_instance };
 
 /* HMAC (rfc-2104) */
-
+/* CLASS:
+   (class
+     (name hmac_algorithm)
+     (super mac_algorithm)
+     (vars
+       (hash object hash_algorithm)))
+*/
+
+#if 0
 struct hmac_algorithm
 {
   struct mac_algorithm super;
   struct hash_algorithm *hash;
 };
-
+#endif
+
+/* CLASS:
+   (class
+     (name hmac_instance)
+     (super mac_instance)
+     (vars
+       ; Initialized hash objects 
+       (hinner object hash_instance)
+       (houter object hash_instance)
+
+       ; Modified by update 
+       (state object hash_instance)))
+*/
+
+#if 0
 struct hmac_instance
 {
   struct mac_instance super;
@@ -168,13 +201,12 @@ struct hmac_instance
   /* Modified by update */
   struct hash_instance *state;
 };
+#endif
 
 static void do_hmac_update(struct mac_instance *s,
 			   UINT32 length, UINT8 *data)
 {
-  struct hmac_instance *self = (struct hmac_instance *) s;
-
-  MDEBUG(self);
+  CAST(hmac_instance, self, s);
 
   HASH_UPDATE(self->state, length, data);
 }
@@ -182,30 +214,24 @@ static void do_hmac_update(struct mac_instance *s,
 static void do_hmac_digest(struct mac_instance *s,
 			   UINT8 *data)
 {
-  struct hmac_instance *self = (struct hmac_instance *) s;
+  CAST(hmac_instance, self, s);
   struct hash_instance *h = self->state;
 
-  MDEBUG(self);
-  
   HASH_DIGEST(h, data);   /* Inner hash */
-  lsh_object_free(h);
+  KILL(h);
   h = HASH_COPY(self->houter);
   HASH_UPDATE(h, self->super.mac_size, data);
   HASH_DIGEST(h, data);
-  lsh_object_free(h);
+  KILL(h);
 
   self->state = HASH_COPY(self->hinner);
 }
 
 static struct mac_instance *do_hmac_copy(struct mac_instance *s)
 {
-  struct hmac_instance *self = (struct hmac_instance *) s;
-  struct hmac_instance *new;
-
-  MDEBUG(self);
+  CAST(hmac_instance, self, s);
+  NEW(hmac_instance, new);
 
-  NEW(new);
-  
   memcpy(&new->super, &self->super, sizeof(self->super));
 
   /* FIXME: Sharing hinner and houter objects makes gc more difficult */
@@ -222,15 +248,11 @@ static struct mac_instance *do_hmac_copy(struct mac_instance *s)
 static struct mac_instance *make_hmac_instance(struct mac_algorithm *s,
 					       UINT8 *key)
 {
-  struct hmac_algorithm *self = (struct hmac_algorithm *) s;
-  struct hmac_instance *instance;
+  CAST(hmac_algorithm, self, s);
+  NEW(hmac_instance, instance);
   UINT8 *pad = alloca(self->hash->block_size);
   int i;
 
-  MDEBUG(self);
-
-  NEW(instance);
-  
   instance->super.hash_size = self->super.hash_size;
   instance->super.update = do_hmac_update;
   instance->super.digest = do_hmac_digest;
@@ -259,9 +281,7 @@ static struct mac_instance *make_hmac_instance(struct mac_algorithm *s,
   
 struct mac_algorithm *make_hmac_algorithm(struct hash_algorithm *h)
 {
-  struct hmac_algorithm *self;
-
-  NEW(self);
+  NEW(hmac_algorithm, self);
 
   self->super.hash_size = h->hash_size;
   /* Recommended in RFC-2104 */
diff --git a/src/debug.c b/src/debug.c
index 4610c38d57556a92997677340855043ef9594bbd..ecdf9e20b8ea6c8e98cbf65613547f3ae61b24f5 100644
--- a/src/debug.c
+++ b/src/debug.c
@@ -32,20 +32,29 @@
 #include "xalloc.h"
 #include "werror.h"
 
+#include "debug.c.x"
+
+/* CLASS:
+   (class
+     (name packet_debug)
+     (super abstract_write_pipe)
+     (vars
+       (prefix simple "char *")))
+*/
+
+#if 0
 struct packet_debug
 {
   struct abstract_write_pipe super;
   char *prefix;
 };
+#endif
 
 static int do_debug(struct abstract_write *w,
 		    struct lsh_string *packet)
 {
-  struct packet_debug *closure
-    = (struct packet_debug *) w;
+  CAST(packet_debug, closure, w);
   
-  MDEBUG(closure);
-
   debug("DEBUG: recieved packet");
   debug_hex(packet->length, packet->data);
   debug("\n");
@@ -56,9 +65,7 @@ static int do_debug(struct abstract_write *w,
 struct abstract_write *
 make_packet_debug(struct abstract_write *continuation, char *prefix)
 {
-  struct packet_debug *closure;
-
-  NEW(closure);
+  NEW(packet_debug, closure);
 
   closure->super.super.write = do_debug;
   closure->super.next = continuation;
@@ -135,9 +142,7 @@ static int do_rec_debug(struct packet_handler *self,
 
 struct packet_handler *make_rec_debug_handler(void)
 {
-  struct packet_handler *self;
-
-  NEW(self);
+  NEW(packet_handler, self);
 
   self->handler = do_rec_debug;
 
diff --git a/src/disconnect.c b/src/disconnect.c
index ac9745a26f55113958c5ec341ff1d2cb8c5be0ff..82fb9988a3f58329db4061a20697ef0383d70b1e 100644
--- a/src/disconnect.c
+++ b/src/disconnect.c
@@ -72,9 +72,7 @@ static int do_disconnect(struct packet_handler *closure,
 
 struct packet_handler *make_disconnect_handler(void)
 {
-  struct packet_handler *res;
-
-  NEW(res);
+  NEW(packet_handler, res);
 
   res->handler = do_disconnect;
   return res;
diff --git a/src/encrypt.c b/src/encrypt.c
index d9dc942b9c7043b3882a909e9391315c46f63f24..665e7676f79b4b96e46b67d5f8de7a364e5e351f 100644
--- a/src/encrypt.c
+++ b/src/encrypt.c
@@ -28,6 +28,18 @@
 #include "format.h"
 #include "xalloc.h"
 
+#include "encrypt.c.x"
+
+/* CLASS:
+   (class
+     (name packet_encrypt)
+     (super abstract_write_pipe)
+     (vars
+       (sequence_number simple UINT32)
+       (connection object ssh_connection)))
+*/
+
+#if 0
 struct packet_encrypt
 {
   struct abstract_write_pipe super;
@@ -35,17 +47,16 @@ struct packet_encrypt
 
   struct ssh_connection *connection;
 };
+#endif
 
 static int do_encrypt(struct abstract_write *w,
 		      struct lsh_string *packet)
 {
-  struct packet_encrypt *closure = (struct packet_encrypt *) w;
+  CAST(packet_encrypt, closure, w);
   struct ssh_connection *connection = closure->connection;
   struct lsh_string *new;
   UINT8 *mac;
 
-  MDEBUG(closure);
-  
   new = ssh_format("%lr%lr", packet->length, NULL,
 		   connection->send_mac ? connection->send_mac->mac_size : 0,
 		   &mac);
@@ -75,9 +86,7 @@ struct abstract_write *
 make_packet_encrypt(struct abstract_write *continuation,
 		    struct ssh_connection *connection)
 {
-  struct packet_encrypt *closure;
-
-  NEW(closure);
+  NEW(packet_encrypt, closure);
 
   closure->super.super.write = do_encrypt;
   closure->super.next = continuation;
diff --git a/src/format.c b/src/format.c
index 29ff42622062ffa5ad49cf6c9f4cff5619ad9389..0f00a2b8cfdbfbd4ccbd26f10578fa7e8f8bb999 100644
--- a/src/format.c
+++ b/src/format.c
@@ -23,13 +23,15 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <assert.h>
-#include <string.h>
-
 #include "format.h"
+
+#include "list.h"
 #include "werror.h"
 #include "xalloc.h"
 
+#include <assert.h>
+#include <string.h>
+
 struct lsh_string *ssh_format(char *format, ...)
 {
   va_list args;
@@ -167,15 +169,15 @@ UINT32 ssh_vformat_length(char *f, va_list args)
 	      }
 	    case 'A':
 	      {
-		int *atom = va_arg(args, int *);
-		int n;
+		struct int_list *l = va_arg(args, struct int_list *);
+		int n, i;
 
-		for(n = 0; *atom >= 0; atom++)
+		for(n = i =0; i < LIST_LENGTH(l); i++)
 		  {
-		    if (*atom)
+		    if (LIST(l)[i])
 		      {
 			n++;
-			length += get_atom_length(*atom);
+			length += get_atom_length(LIST(l)[i]);
 		      }
 		  }
 		if (n)
@@ -355,24 +357,24 @@ void ssh_vformat_write(char *f, UINT32 size, UINT8 *buffer, va_list args)
 	      }
 	    case 'A':
 	      {
-		int *atom = va_arg(args, int *);
+		struct int_list *l = va_arg(args, struct int_list *);
 		UINT8 *start = buffer; /* Where to store the length */
-		int n;
+		int n, i;
 		
 		if (!literal)
 		  buffer += 4;
 		
-		for(n = 0; *atom >= 0; atom++)
+		for(n = i = 0; i < LIST_LENGTH(l); i++)
 		  {
-		    if (*atom)
+		    if (LIST(l)[i])
 		      {
-			UINT32 length = get_atom_length(*atom);
+			UINT32 length = get_atom_length(LIST(l)[i]);
 			
 			if (n)
 			  /* Not the first atom */
 			  *buffer++ = ',';
 
-			memcpy(buffer, get_atom_name(atom[0]), length);
+			memcpy(buffer, get_atom_name(LIST(l)[i]), length);
 			buffer += length;
 
 			n++;
diff --git a/src/format.h b/src/format.h
index ef68620a180db4361bfe78dfde05ba38c2f61da7..b3da261497e51dbd680f0b1db0a13e7d477927b5 100644
--- a/src/format.h
+++ b/src/format.h
@@ -50,9 +50,8 @@
  *
  * %a  Insert a string containing one atom.
  *
- * %A  Insert a string containing a list of atoms. The corresponding
- *     argument sublist should be a int* pointing to a list of atoms,
- *     terminated with -1. Zero elements are allowed and ignored.
+ * %A  Insert a string containing a list of atoms. The input is an
+ *     int_list object. Zero elements are allowed and ignored.
  *
  * %X  Insert a string containing a list of atoms. The corresponding
  *     argument sublist should be terminated with a zero. (Not used)
diff --git a/src/gc.c b/src/gc.c
index c52475867b788f648286307040cae211102a1f78..762bfb61afa73b5d15c04fc9dd15c42a521c6fe1 100644
--- a/src/gc.c
+++ b/src/gc.c
@@ -31,50 +31,46 @@
 #include <assert.h>
 
 /* Global variables */
-static struct lsh_object *all_objects;
-unsigned number_of_objects;
-unsigned live_objects;
-
+static struct lsh_object *all_objects = NULL;
+unsigned number_of_objects = 0;
+unsigned live_objects = 0;
+
+/* FIXME: This function recurses heavily. One could use some trickery
+ * to emulate tail recursion, which would help marking linked list. Or
+ * one could use some more efficient datastructures than the C stack
+ * for keeping track of the marked but not yet traced objects. */
 static void gc_mark(struct lsh_object *o)
 {
-  while(o)
-    switch(o->alloc_method)
+  if (!o)
+    return;
+  
+  switch(o->alloc_method)
+    {
+    case LSH_ALLOC_STACK:
+      fatal("gc_mark: Unexpected stack object!\n");
+
+    case LSH_ALLOC_HEAP:
+      if (o->marked)
+	return;
+      o->marked = 1;
+      /* Fall through */
+    case LSH_ALLOC_STATIC:
+      /* Can't use mark bit on static objects, as there's no way to
+       * reset all the bits */
+      assert(!o->dead);
       {
-      case LSH_ALLOC_STACK:
-	fatal("gc_mark: Unexpected stack object!\n");
-
-      case LSH_ALLOC_HEAP:
-	if (o->marked)
-	  return;
-	o->marked = 1;
-	/* Fall through */
-      case LSH_ALLOC_STATIC:
-	/* Can't use mark bit on static objects, as there's no way to
-	 * reset all the bits */
-	assert(!o->dead);
-	{
-	  struct lsh_object *instance = o;
-	  struct lsh_class *class;
+	struct lsh_class *class;
 	
-	  for (class = o->isa, o = NULL; class; class = class->super_class)
-	    {
-	      if (class->mark_instance)
-		{
-		  struct lsh_object *p = MARK_INSTANCE(class, instance, gc_mark);
-		  if (o)
-		    {
-		      if (p)
-			gc_mark(p);
-		    }
-		  else
-		    o = p;
-		}
-	    }
-	}
-	break;
-      default:
-	fatal("gc_mark: Memory corrupted!\n");
+	for (class = o->isa, o = NULL; class; class = class->super_class)
+	  {
+	    if (class->mark_instance)
+	      MARK_INSTANCE(class, o, gc_mark);
+	  }
       }
+      break;
+    default:
+      fatal("gc_mark: Memory corrupted!\n");
+    }
 }
 
 static void gc_sweep(void)
@@ -125,6 +121,9 @@ void gc_register(struct lsh_object *o)
  * references to killed objects. */
 void gc_kill(struct lsh_object *o)
 {
+  if (!o)
+    return;
+  
   assert(!o->dead);
 
   o->dead = 1;
diff --git a/src/io.c b/src/io.c
index f0b46a3eddceb681b2d6ea64c3a845adac9d82a5..5c99a29575ee720579f86b8925f40b4743d372bf 100644
--- a/src/io.c
+++ b/src/io.c
@@ -46,6 +46,12 @@
 #include "write_buffer.h"
 #include "xalloc.h"
 
+#define CLASS_DEFINE
+#include "io.h.x"
+#undef CLASS_DEFINE
+
+#include "io.c.x"
+
 /* If there's nothing to do for this amount of time (ms), do
  * spontaneous gc. */
 
@@ -197,19 +203,26 @@ int io_iter(struct io_backend *b)
   return 1;
 }
 
+/* CLASS:
+   (class
+     (name fd_read)
+     (super abstract_read)
+       (vars
+         (fd simple int)))
+*/
+
+#if 0
 struct fd_read
 {
   struct abstract_read super;
   int fd;
 };
+#endif
 
 static int do_read(struct abstract_read **r, UINT32 length, UINT8 *buffer)
 {
-  struct fd_read *closure
-    = (struct fd_read *) *r;
+  CAST(fd_read, closure, *r);
 
-  MDEBUG(closure);
-  
   while(1)
     {
       int res = read(closure->fd, buffer, length);
@@ -240,14 +253,12 @@ static int do_read(struct abstract_read **r, UINT32 length, UINT8 *buffer)
 
 static void read_callback(struct lsh_fd *fd)
 {
-  struct io_fd *self = (struct io_fd *) fd;
+  CAST(io_fd, self, fd);
   int res;
 
   struct fd_read r =
   { { STACK_HEADER, do_read }, fd->fd };
 
-  MDEBUG(self);
-  
   /* The handler function may install a new handler */
   res = READ_HANDLER(self->handler,
 		     &r.super);
@@ -299,12 +310,10 @@ static void read_callback(struct lsh_fd *fd)
 
 static void write_callback(struct lsh_fd *fd)
 {
-  struct io_fd *self = (struct io_fd *) fd;
+  CAST(io_fd, self, fd);
   UINT32 size;
   int res;
   
-  MDEBUG(self);
-
   size = MIN(self->buffer->end - self->buffer->start,
 	     self->buffer->block_size);
   assert(size);
@@ -339,14 +348,12 @@ static void write_callback(struct lsh_fd *fd)
 
 static void listen_callback(struct lsh_fd *fd)
 {
-  struct listen_fd *self = (struct listen_fd *) fd;
+  CAST(listen_fd, self, fd);
   struct sockaddr_in peer;
   size_t addr_len = sizeof(peer);
   int res;
   int conn;
 
-  MDEBUG(self);
-  
   /* FIXME: Do something with the peer address? */
 
   conn = accept(fd->fd,
@@ -369,11 +376,9 @@ static void listen_callback(struct lsh_fd *fd)
 
 static void connect_callback(struct lsh_fd *fd)
 {
-  struct connect_fd *self = (struct connect_fd *) fd;
+  CAST(connect_fd, self, fd);
   int res;
   
-  MDEBUG(self);
-
   res = FD_CALLBACK(self->callback, fd->fd);
 
   if (LSH_ACTIONP(res))
@@ -536,7 +541,6 @@ struct connect_fd *io_connect(struct io_backend *b,
 			      struct sockaddr_in *local,
 			      struct fd_callback *f)
 {
-  struct connect_fd *fd;
   int s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
   
   if (s<0)
@@ -562,22 +566,24 @@ struct connect_fd *io_connect(struct io_backend *b,
       errno = saved_errno;
       return NULL;
     }
-  
-  NEW(fd);
-  init_file(b, &fd->super, s);
 
-  fd->super.want_write = 1;
-  fd->super.write = connect_callback;
-  fd->callback = f;
+  {
+    NEW(connect_fd, fd);
+
+    init_file(b, &fd->super, s);
 
-  return fd;
+    fd->super.want_write = 1;
+    fd->super.write = connect_callback;
+    fd->callback = f;
+    
+    return fd;
+  }
 }
 
 struct listen_fd *io_listen(struct io_backend *b,
 			    struct sockaddr_in *local,
 			    struct fd_callback *callback)
 {
-  struct listen_fd *fd;
   int s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
   
   if (s<0)
@@ -604,22 +610,22 @@ struct listen_fd *io_listen(struct io_backend *b,
       return NULL;
     }
 
-  NEW(fd);
-
-  init_file(b, &fd->super, s);
-
-  fd->super.want_read = 1;
-  fd->super.read = listen_callback;
-  fd->callback = callback;
+  {
+    NEW(listen_fd, fd);
 
-  return fd;
+    init_file(b, &fd->super, s);
+    
+    fd->super.want_read = 1;
+    fd->super.read = listen_callback;
+    fd->callback = callback;
+    
+    return fd;
+  }
 }
 
 static void really_close(struct lsh_fd *fd)
 {
-  struct io_fd *self = (struct io_fd *) fd;
-
-  MDEBUG(self);
+  CAST(io_fd, self, fd);
 
   assert(self->buffer);
 
@@ -628,9 +634,7 @@ static void really_close(struct lsh_fd *fd)
 
 static void prepare_write(struct lsh_fd *fd)
 {
-  struct io_fd *self = (struct io_fd *) fd;
-
-  MDEBUG(self);
+  CAST(io_fd, self, fd);
 
   assert(self->buffer);
 
@@ -645,14 +649,13 @@ struct abstract_write *io_read_write(struct io_backend *b,
 				     UINT32 block_size,
 				     struct close_callback *close_callback)
 {
-  struct io_fd *f;
+  NEW(io_fd, f);
   struct write_buffer *buffer = write_buffer_alloc(block_size);
 
   debug("io.c: Preparing fd %d for reading and writing\n", fd);
   
   io_init_fd(fd);
   
-  NEW(f);
   init_file(b, &f->super, fd);
   
   /* Reading */
@@ -677,14 +680,12 @@ struct io_fd *io_read(struct io_backend *b,
 		      struct read_handler *handler,
 		      struct close_callback *close_callback)
 {
-  struct io_fd *f;
+  NEW(io_fd, f);
 
   debug("io.c: Preparing fd %d for reading\n", fd);
   
   io_init_fd(fd);
 
-  NEW(f);
-
   init_file(b, &f->super, fd);
 
   /* Reading */
@@ -702,14 +703,13 @@ struct io_fd *io_write(struct io_backend *b,
 		       UINT32 block_size,
 		       struct close_callback *close_callback)
 {
-  struct io_fd *f;
+  NEW(io_fd, f);
   struct write_buffer *buffer = write_buffer_alloc(block_size);
 
   debug("io.c: Preparing fd %d for writing\n", fd);
   
   io_init_fd(fd);
   
-  NEW(f);
   init_file(b, &f->super, fd);
 
   /* Writing */
diff --git a/src/io.h b/src/io.h
index 4dcf2fba11dcedab0d9f6620278c98e68ef1d346..7b41166073b87c23e6d1b19f25b613281d0b1e6f 100644
--- a/src/io.h
+++ b/src/io.h
@@ -33,12 +33,16 @@
 #include <netdb.h>
 #include <netinet/in.h>
 
+#define CLASS_DECLARE
+#include "io.h.x"
+#undef CLASS_DECLARE
+
 /* A closed function with a file descriptor as argument */
 /* CLASS:
    (class
      (name fd_callback)
      (vars
-       (f method int "int fd")))
+       (f indirect-method int "int fd")))
 */
 
 #if 0
@@ -95,24 +99,24 @@ struct close_callback
      (name lsh_fd)
      (vars
        (next object lsh_fd)
-       (fd int)
+       (fd simple int)
 
        ; User's close callback
-       (close_reason int)
+       (close_reason simple int)
        (close_callback object close_callback)
 
        ; Called before poll
        (prepare method void)
 
-       (want_read int)
+       (want_read simple int)
        ; Called if poll indicates that data can be read. 
        (read method void)
 
-       (want_write int)
+       (want_write simple int)
        ; Called if poll indicates that data can be written.
        (write method void)
 
-       (close_now int)
+       (close_now simple int)
        (really_close method void)))
 */
 
@@ -175,7 +179,7 @@ struct io_fd
 
 /* CLASS:
    (class
-     (name io_fd)
+     (name listen_fd)
      (super lsh_fd)
      (vars
        (callback object fd_callback)))
@@ -210,7 +214,8 @@ struct callout
        ; Linked list of fds. 
        (files object lsh_fd)
        ; Callouts
-       ;; (callouts object callout)))
+       ;; (callouts object callout)
+       ))
 */
 
 #if 0
diff --git a/src/keyexchange.c b/src/keyexchange.c
index bd810cb708d493e2c6338b2d836c185609238e4f..dccd43d23f101f403372711f835e47994e5dcd47 100644
--- a/src/keyexchange.c
+++ b/src/keyexchange.c
@@ -36,6 +36,32 @@
 #include "werror.h"
 #include "xalloc.h"
 
+#include <assert.h>
+
+#define CLASS_DEFINE
+#include "keyexchange.h.x"
+#undef CLASS_DEFINE
+
+#include "keyexchange.c.x"
+
+/* CLASS:
+   (class
+     (name kexinit_handler)
+     (super packet_handler)
+     (vars
+       (type simple int)
+       (init object make_kexinit)
+
+       ; Maps names to algorithms. It's dangerous to lookup random atoms
+       ; in this table, as not all objects have the same type. This
+       ; mapping is used only on atoms that have appeared in *both* the
+       ; client's and the server's list of algorithms (of a certain
+       ; type), and therefore the remote side can't screw things up.
+       (algorithms object alist)
+
+       (finished object ssh_service)))
+*/
+#if 0
 struct kexinit_handler
 {
   struct packet_handler super;
@@ -53,31 +79,34 @@ struct kexinit_handler
 
   struct ssh_service *finished;
 };
+#endif
 
 #define NLISTS 10
 
 static struct kexinit *parse_kexinit(struct lsh_string *packet)
 {
-  struct kexinit *res;
+  NEW(kexinit, res);
   struct simple_buffer buffer;
   struct simple_buffer sub_buffer;
   int msg_number;
   UINT32 reserved;
   
-  int *lists[NLISTS];
+  struct int_list *lists[NLISTS];
   int i;
   
   simple_buffer_init(&buffer, packet->length, packet->data);
 
   if (!parse_uint8(&buffer, &msg_number)
       || (msg_number != SSH_MSG_KEXINIT) )
-    return 0;
+    {
+      KILL(res);
+      return 0;
+    }
 
-  NEW(res);
 
   if (!parse_octets(&buffer, 16, res->cookie))
     {
-      lsh_object_free(res);
+      KILL(res);
       return NULL;
     }
   
@@ -96,8 +125,8 @@ static struct kexinit *parse_kexinit(struct lsh_string *packet)
       /* Bad format */
       int j;
       for (j = 0; j<i; j++)
-	lsh_space_free(lists[i]);
-      lsh_object_free(res);
+	KILL(lists[i]);
+      KILL(res);
       return NULL;
     }
   
@@ -156,20 +185,22 @@ int initiate_keyexchange(struct ssh_connection *connection,
     return res;
 }
 
-static int select_algorithm(int *server_list, int *client_list)
+static int select_algorithm(struct int_list *server_list,
+			    struct int_list *client_list)
 {
   /* FIXME: This quadratic complexity algorithm should do as long as
    * the lists are short. */
   int i, j;
 
-  for(i = 0; client_list[i] >= 0; i++)
+  for(i = 0; i < LIST_LENGTH(client_list) >= 0; i++)
     {
-      if (!client_list[i])
+      int a = LIST(client_list)[i];
+      if (!a)
 	/* Unknown algorithm */
 	continue;
-      for(j = 0; server_list[j] > 0; j++)
-	if (client_list[i] == server_list[j])
-	  return client_list[i];
+      for(j = 0; j < LIST_LENGTH(server_list); j++)
+	if (a == LIST(server_list)[j])
+	  return a;
     }
 
   return 0;
@@ -186,21 +217,18 @@ static int do_handle_kexinit(struct packet_handler *c,
 			     struct ssh_connection *connection,
 			     struct lsh_string *packet)
 {
-  struct kexinit_handler *closure = (struct kexinit_handler *) c;
+  CAST(kexinit_handler, closure, c);
   struct kexinit *msg = parse_kexinit(packet);
 
   int kex_algorithm;
   int hostkey_algorithm;
 
   int parameters[KEX_PARAMETERS];
-  void **algorithms;
+  struct object_list *algorithms;
 
   int i;
   int res = 0;
 
-  MDEBUG(closure);
-  MDEBUG(msg);
-  
   if (!msg)
     return LSH_FAIL | LSH_DIE;
 
@@ -225,11 +253,11 @@ static int do_handle_kexinit(struct packet_handler *c,
 
   /* Select key exchange algorithms */
 
-  if (connection->kexinits[0]->kex_algorithms[0]
-      == connection->kexinits[1]->kex_algorithms[0])
+  if (LIST(connection->kexinits[0]->kex_algorithms)[0]
+      == LIST(connection->kexinits[1]->kex_algorithms)[0])
     {
       /* Use this algorithm */
-      kex_algorithm = connection->kexinits[0]->kex_algorithms[0];
+      kex_algorithm = LIST(connection->kexinits[0]->kex_algorithms)[0];
     }
   else
     {
@@ -238,7 +266,8 @@ static int do_handle_kexinit(struct packet_handler *c,
 	  /* Wrong guess */
 	  connection->kex_state = KEX_STATE_IGNORE;
 	}
-      /* FIXME: Ignores that some keyechange algorithms require
+
+      /* FIXME: Ignores that some keyexchange algorithms require
        * certain features of the host key algorithms. */
       
       kex_algorithm
@@ -256,7 +285,7 @@ static int do_handle_kexinit(struct packet_handler *c,
   hostkey_algorithm
     = select_algorithm(connection->kexinits[0]->server_hostkey_algorithms,
 		       connection->kexinits[1]->server_hostkey_algorithms);
-  
+
   for(i = 0; i<KEX_PARAMETERS; i++)
     {
       parameters[i]
@@ -270,10 +299,10 @@ static int do_handle_kexinit(struct packet_handler *c,
 	}
     }
   
-  algorithms = lsh_space_alloc(KEX_PARAMETERS*sizeof(void *));
+  algorithms = alloc_object_list(KEX_PARAMETERS);
   
   for (i = 0; i<KEX_PARAMETERS; i++)
-    algorithms[i] = ALIST_GET(closure->algorithms, parameters[i]);
+    LIST(algorithms)[i] = ALIST_GET(closure->algorithms, parameters[i]);
       
   return res
     | KEYEXCHANGE_INIT( (struct keyexchange_algorithm *)
@@ -290,9 +319,7 @@ struct packet_handler *make_kexinit_handler(int type,
 					    struct alist *algorithms,
 					    struct ssh_service *finished)
 {
-  struct kexinit_handler *self;
-
-  NEW(self);
+  NEW(kexinit_handler, self);
 
   self->super.handler = do_handle_kexinit;
 
@@ -335,21 +362,24 @@ static struct lsh_string *kex_make_key(struct hash_instance *secret,
     fatal("Not implemented\n");
 
   memcpy(key->data, digest, key_length);
-  lsh_object_free(hash);
+  KILL(hash);
 
   debug_hex(key->length, key->data);
   return key;
 }
   
 struct crypto_instance *kex_make_encrypt(struct hash_instance *secret,
-					 void **algorithms,
+					 struct object_list *algorithms,
 					 int type,
 					 struct ssh_connection *connection)
 {
-  struct crypto_algorithm *algorithm = algorithms[type];
+  CAST_SUBTYPE(crypto_algorithm, algorithm, LIST(algorithms)[type]);
+    
   struct lsh_string *key;
   struct crypto_instance *crypto;
-  
+
+  assert(LIST_LENGTH(algorithms) == KEX_PARAMETERS);
+
   if (!algorithm)
     return NULL;
 
@@ -365,14 +395,17 @@ struct crypto_instance *kex_make_encrypt(struct hash_instance *secret,
 }
 
 struct crypto_instance *kex_make_decrypt(struct hash_instance *secret,
-					 void **algorithms,
+					 struct object_list *algorithms,
 					 int type,
 					 struct ssh_connection *connection)
 {
-  struct crypto_algorithm *algorithm = algorithms[type];
+  CAST_SUBTYPE(crypto_algorithm, algorithm, LIST(algorithms)[type]);
+
   struct lsh_string *key;
   struct crypto_instance *crypto;
-  
+
+  assert(LIST_LENGTH(algorithms) == KEX_PARAMETERS);
+
   if (!algorithm)
     return NULL;
   
@@ -388,14 +421,17 @@ struct crypto_instance *kex_make_decrypt(struct hash_instance *secret,
 }
 
 struct mac_instance *kex_make_mac(struct hash_instance *secret,
-				  void **algorithms,
+				  struct object_list *algorithms,
 				  int type,
 				  struct ssh_connection *connection)
 {
-  struct mac_algorithm *algorithm = algorithms[type];
+  CAST(mac_algorithm, algorithm, LIST(algorithms)[type]);
+
   struct mac_instance *mac;
   struct lsh_string *key;
 
+  assert(LIST_LENGTH(algorithms) == KEX_PARAMETERS);
+  
   if (!algorithm)
     return NULL;
 
@@ -408,23 +444,32 @@ struct mac_instance *kex_make_mac(struct hash_instance *secret,
   return mac;
 }
 
+/* CLASS:
+   (class
+     (name newkeys_handler)
+     (super packet_handler)
+     (vars
+       (crypto object crypto_instance)
+       (mac object mac_instance)))
+*/
+
+#if 0
 struct newkeys_handler
 {
   struct packet_handler super;
   struct crypto_instance *crypto;
   struct mac_instance *mac;
 };
+#endif
 
 static int do_handle_newkeys(struct packet_handler *c,
 			     struct ssh_connection *connection,
 			     struct lsh_string *packet)
 {
-  struct newkeys_handler *closure = (struct newkeys_handler *) c;
+  CAST(newkeys_handler, closure, c);
   struct simple_buffer buffer;
   int msg_number;
 
-  MDEBUG(closure);
-  
   simple_buffer_init(&buffer, packet->length, packet->data);
 
   if (parse_uint8(&buffer, &msg_number)
@@ -438,7 +483,7 @@ static int do_handle_newkeys(struct packet_handler *c,
 
       connection->dispatch[SSH_MSG_NEWKEYS] = NULL;
 
-      lsh_object_free(closure);
+      KILL(closure);
       return LSH_OK | LSH_GOON;
     }
   else
@@ -449,9 +494,7 @@ struct packet_handler *
 make_newkeys_handler(struct crypto_instance *crypto,
 		     struct mac_instance *mac)
 {
-  struct newkeys_handler *self;
-
-  NEW(self);
+  NEW(newkeys_handler,self);
 
   self->super.handler = do_handle_newkeys;
   self->crypto = crypto;
@@ -460,6 +503,80 @@ make_newkeys_handler(struct crypto_instance *crypto,
   return &self->super;
 }
 
+/* Uses the same algorithms for both directions */
+/* CLASS:
+   (class
+     (name simple_kexinit)
+     (super make_kexinit)
+     (vars
+       (r object randomness)
+       (kex_algorithms object int_list)
+       (hostkey_algorithms object int_list)
+       (crypto_algorithms object int_list)
+       (mac_algorithms object int_list)
+       (compression_algorithms object int_list)
+       (languages object int_list)))
+*/
+
+static struct kexinit *do_make_simple_kexinit(struct make_kexinit *c)
+{
+  CAST(simple_kexinit, closure, c);
+  NEW(kexinit, res);
+
+  RANDOM(closure->r, 16, res->cookie);
+
+  res->kex_algorithms = closure->kex_algorithms;
+  res->server_hostkey_algorithms = closure->hostkey_algorithms;
+  res->parameters[KEX_ENCRYPTION_CLIENT_TO_SERVER] = closure->crypto_algorithms;
+  res->parameters[KEX_ENCRYPTION_SERVER_TO_CLIENT] = closure->crypto_algorithms;
+  res->parameters[KEX_MAC_CLIENT_TO_SERVER] = closure->mac_algorithms;
+  res->parameters[KEX_MAC_SERVER_TO_CLIENT] = closure->mac_algorithms;
+  res->parameters[KEX_COMPRESSION_CLIENT_TO_SERVER]
+    = closure->compression_algorithms;
+  res->parameters[KEX_COMPRESSION_SERVER_TO_CLIENT]
+    = closure->compression_algorithms;
+  res->languages_client_to_server = closure->languages;
+  res->languages_server_to_client = closure->languages;
+  res->first_kex_packet_follows = 0;
+
+  return res;
+}
+
+struct make_kexinit *make_simple_kexinit(struct randomness *r,
+					 struct int_list *kex_algorithms,
+					 struct int_list *hostkey_algorithms,
+					 struct int_list *crypto_algorithms,
+					 struct int_list *mac_algorithms,
+					 struct int_list *compression_algorithms,
+					 struct int_list *languages)
+{
+  NEW(simple_kexinit, res);
+
+  res->super.make = do_make_simple_kexinit;
+  res->r = r;
+  res->kex_algorithms = kex_algorithms;
+  res->hostkey_algorithms = hostkey_algorithms;
+  res->crypto_algorithms = crypto_algorithms;
+  res->mac_algorithms = mac_algorithms;
+  res->compression_algorithms = compression_algorithms;
+  res->languages = languages;
+
+  return &res->super;
+}
+
+struct make_kexinit *make_test_kexinit(struct randomness *r)
+{
+  return make_simple_kexinit
+    (r,
+     make_int_list(1, ATOM_DIFFIE_HELLMAN_GROUP1_SHA1, -1),
+     make_int_list(1, ATOM_SSH_DSS, -1),
+     make_int_list(2, ATOM_ARCFOUR, ATOM_NONE, -1),
+     make_int_list(1, ATOM_HMAC_SHA1, -1),
+     make_int_list(1, ATOM_NONE, -1),
+     make_int_list(0, -1));
+}
+
+#if 0
 struct test_kexinit
 {
   struct make_kexinit super;
@@ -468,8 +585,8 @@ struct test_kexinit
 
 static struct kexinit *do_make_kexinit(struct make_kexinit *c)
 {
-  struct test_kexinit *closure = (struct test_kexinit *) c;
-  struct kexinit *res;
+  CAST(test_kexinit, closure, c);
+  NEW(kexinit, res);
 
   static int kex_algorithms[] = { ATOM_DIFFIE_HELLMAN_GROUP1_SHA1, -1 };
   static int server_hostkey_algorithms[] = { ATOM_SSH_DSS, -1 };
@@ -478,10 +595,6 @@ static struct kexinit *do_make_kexinit(struct make_kexinit *c)
   static int compression_algorithms[] = { ATOM_NONE, -1 };
   static int languages[] = { -1 };
 
-  MDEBUG(closure);
-
-  NEW(res);
-  
   RANDOM(closure->r, 16, res->cookie);
   res->kex_algorithms = kex_algorithms;
   res->server_hostkey_algorithms = server_hostkey_algorithms;
@@ -500,12 +613,13 @@ static struct kexinit *do_make_kexinit(struct make_kexinit *c)
 
 struct make_kexinit *make_test_kexinit(struct randomness *r)
 {
-  struct test_kexinit *res;
-
-  NEW(res);
+  NEW(test_kexinit, res);
 
   res->super.make = do_make_kexinit;
   res->r = r;
 
   return &res->super;
 }
+
+#endif
+
diff --git a/src/keyexchange.h b/src/keyexchange.h
index 006a071931a2870970ec46a341a1fa9c4edce6c8..3325b7b56bdd83ee735ca1193564ed45b4eb6778 100644
--- a/src/keyexchange.h
+++ b/src/keyexchange.h
@@ -29,6 +29,7 @@
 #include "abstract_crypto.h"
 #include "abstract_io.h"
 #include "alist.h"
+#include "list.h"
 #include "connection.h"
 #include "service.h"
 
@@ -55,6 +56,10 @@
  * nothing else. */
 #define KEX_STATE_NEWKEYS 3
 
+#define CLASS_DECLARE
+#include "keyexchange.h.x"
+#undef CLASS_DECLARE
+
 #if 0
 /* Use the service struct instead */
 struct keyexchange_finished
@@ -73,12 +78,12 @@ struct keyexchange_finished
      (name keyexchange_algorithm)
      (vars
        ; Algorithms is an array indexed by the KEX_* values above
-       (init method void
+       (init method int
 	     "struct ssh_connection *connection"
 	     "struct ssh_service *finished"
 	     "int hostkey_algorithm_atom"
 	     "struct signature_algorithm *hostkey_algorithm"
-	     "void **algorithms")))
+	     "struct object_list *algorithms")))
 */
 #if 0
 struct keyexchange_algorithm
@@ -90,7 +95,7 @@ struct keyexchange_algorithm
 	      struct ssh_service *finished,
 	      int hostkey_algorithm_atom,
 	      struct signature_algorithm *hostkey_algorithm,
-	      void **algorithms);
+	      struct object_list *algorithms);
 };
 #endif
 
@@ -103,11 +108,11 @@ struct keyexchange_algorithm
      (vars
        (cookie array UINT8 16);
        ; Lists of atoms
-       (kex_algorithms object lsh_list)
-       (server_hostkey_algorithms object lsh_list)
-       (parameters array (object lsh_list) KEX_PARAMETERS)
-       (languages_client_to_server object lsh_list)
-       (languages_server_to_client object lsh_list)
+       (kex_algorithms object int_list)
+       (server_hostkey_algorithms object int_list)
+       (parameters array (object int_list) KEX_PARAMETERS)
+       (languages_client_to_server object int_list)
+       (languages_server_to_client object int_list)
        (first_kex_packet_follows simple int)))
 */
      
@@ -207,20 +212,28 @@ struct lsh_string *format_kex(struct kexinit *kex);
 int disconnect_kex_failed(struct ssh_connection *connection, char *msg);
 
 struct crypto_instance *kex_make_encrypt(struct hash_instance *secret,
-					 void **algorithms,
+					 struct object_list *algorithms,
 					 int type,
 					 struct ssh_connection *connection);
 
 struct crypto_instance *kex_make_decrypt(struct hash_instance *secret,
-					 void **algorithms,
+					 struct object_list *algorithms,
 					 int type,
 					 struct ssh_connection *connection);
 
 struct mac_instance *kex_make_mac(struct hash_instance *secret,
-				  void **algorithms,
+				  struct object_list *algorithms,
 				  int type,
 				  struct ssh_connection *connection);
 
+struct make_kexinit *make_simple_kexinit(struct randomness *r,
+					 struct int_list *kex_algorithms,
+					 struct int_list *hostkey_algorithms,
+					 struct int_list *crypto_algorithms,
+					 struct int_list *mac_algorithms,
+					 struct int_list *compression_algorithms,
+					 struct int_list *languages);
+
 struct make_kexinit *make_test_kexinit(struct randomness *r);
 
 int initiate_keyexchange(struct ssh_connection *connection,
diff --git a/src/list.c b/src/list.c
index ebeec27e99a785c7d59d333b5a021da7c801d1dc..43a3c36fff5ba006693ae1f59d27c4239474c1c5 100644
--- a/src/list.c
+++ b/src/list.c
@@ -25,18 +25,21 @@
 
 #include "list.h"
 
+#include <assert.h>
+#include <stdarg.h>
+
 #define CLASS_DEFINE
 #include "list.h.x"
 #undef CLASS_DEFINE
 
 #include "xalloc.h"
 
-struct lsh_list *make_list(unsigned n, ...);
+struct int_list *make_int_list(unsigned n, ...)
 {
   int i;
   va_list args;
   
-  struct lsh_list *l = lsh_list_alloc(n);
+  struct int_list *l = alloc_int_list(n);
 
   va_start(args, n);
   
@@ -51,3 +54,21 @@ struct lsh_list *make_list(unsigned n, ...);
 
   return l;
 }
+
+struct object_list *make_object_list(unsigned n, ...)
+{
+  int i;
+  va_list args;
+  
+  struct object_list *l = alloc_object_list(n);
+
+  va_start(args, n);
+  
+  for (i=0; i<n; i++)
+    LIST(l)[i] = va_arg(args, struct lsh_object *);
+
+  assert(va_arg(args, int) == -1);
+
+  return l;
+}
+
diff --git a/src/list.h b/src/list.h
index eba440d2cc4ca190648152ceedf739347ab074a3..2a81e539c07251fd4a13d316493c8c73d87fb2cf 100644
--- a/src/list.h
+++ b/src/list.h
@@ -34,14 +34,44 @@
 
 /* CLASS:
    (class
-     (name lsh_list)
+     (name list_header)
+     (vars
+       (length simple unsigned)))
+*/
+
+/* CLASS:
+   (class
+     (name int_list)
+     (super list_header)
      (vars
-       (length simple unsigned)
        ; This is really of variable size
-       (elements array int 1)))
+       (elements var-array int "super.length")))
+*/
+
+/* CLASS:
+   (class
+     (name object_list)
+     (super list_header)
+     (vars
+       ; This is really of variable size
+       (elements var-array (object lsh_object) "super.length")))
 */
 
 #define LIST(x) ((x)->elements)
-struct lsh_list *make_list(unsigned length, ...);
+#define LIST_LENGTH(x) (((struct list_header *) (x))->length)
+
+struct list_header *lsh_list_alloc(struct lsh_class *class,
+				   unsigned length, size_t element_size);
+
+#define alloc_int_list(n) \
+  ((struct int_list *) lsh_list_alloc(&CLASS(int_list), (n), sizeof(int)))
+     
+struct int_list *make_int_list(unsigned length, ...);
+
+#define alloc_object_list(n) \
+  ((struct object_list *) \
+   lsh_list_alloc(&CLASS(object_list), (n), sizeof(struct lsh_object *)))
+
+struct object_list *make_object_list(unsigned length, ...);
 
 #endif /* LSH_LIST_H_INCLUDED */
diff --git a/src/lsh.c b/src/lsh.c
index 4b534461607dea851ab8af5eb50f8082864d41a3..ee93f771ce202c85dd4f8bf347eabbedbad1a259 100644
--- a/src/lsh.c
+++ b/src/lsh.c
@@ -50,6 +50,8 @@
 #include "werror.h"
 #include "xalloc.h"
 
+#include "lsh.c.x"
+
 /* Block size for stdout and stderr buffers */
 #define BLOCK_SIZE 32768
 
@@ -60,28 +62,34 @@ void usage(void)
   exit(1);
 }
 
+/* CLASS:
+   (class
+     (name fake_host_db)
+     (super lookup_verifier)
+     (vars
+       (algorithm object signature_algorithm)))
+*/
+
+#if 0
 struct fake_host_db
 {
   struct lookup_verifier super;
 
   struct signature_algorithm *algorithm;
 };
+#endif
 
 static struct verifier *do_host_lookup(struct lookup_verifier *c,
 				       struct lsh_string *key)
 {
-  struct fake_host_db *closure = (struct fake_host_db *) c;
+  CAST(fake_host_db, closure, c);
 
-  MDEBUG(closure);
-  
   return MAKE_VERIFIER(closure->algorithm, key->length, key->data);
 }
 
 static struct lookup_verifier *make_fake_host_db(struct signature_algorithm *a)
 {
-  struct fake_host_db *res;
-
-  NEW(res);
+  NEW(fake_host_db, res);
 
   res->super.lookup = do_host_lookup;
   res->algorithm = a;
diff --git a/src/lshd.c b/src/lshd.c
index b76f3ad0afe46d278350a5f4190eda81ec24b75b..e7fe716ba012d0c8628fc2a60975eb6418b30153 100644
--- a/src/lshd.c
+++ b/src/lshd.c
@@ -139,8 +139,6 @@ int main(int argc, char **argv)
   struct make_kexinit *make_kexinit;
   struct packet_handler *kexinit_handler;
   
-  int advertised_methods[] = { ATOM_PASSWORD, -1 };
-  
   /* For filtering messages. Could perhaps also be used when converting
    * strings to and from UTF8. */
   setlocale(LC_CTYPE, "");
@@ -200,7 +198,7 @@ int main(int argc, char **argv)
      (make_alist
       (1, ATOM_SSH_USERAUTH,
        make_userauth_service
-       (advertised_methods,
+       (make_int_list(1, ATOM_PASSWORD, -1),
 	make_alist(1, ATOM_PASSWORD,
 		   make_unix_userauth
 		   (make_alist(1,
diff --git a/src/make_class b/src/make_class
index 8e72feb9270cbe764e3c949ea544bd087e27a1bf..f89d714bbd0a4ec0c78c13b4d9f917a750b7acff 100755
--- a/src/make_class
+++ b/src/make_class
@@ -67,7 +67,11 @@
 ;; (simple c-type)   c-type
 ;; (special c-type mark-fn free-fn)
 ;;
+;; (struct tag)
+;;
 ;; (array type size) type name[size]
+;; Variable size array (must be last) */
+;; (var-array type size-field)  type name[1]
 ;;
 ;; (pointer type)    type *name
 ;; (space type)      Like pointer, but should be freed
@@ -87,8 +91,8 @@
       (type->category `(simple ,type))
       (let ((tag (car type)))
 	(case tag
-	  ((string object simple special space bignum) tag)
-	  ((array pointer) (type->category (cadr type)))
+	  ((string object simple special space bignum struct) tag)
+	  ((array var-array pointer) (type->category (cadr type)))
 	  
 	  (else (error "make_class: type->category: Invalid type" type))))))
 
@@ -98,12 +102,15 @@
       (case (car type)
 	((string) (list "struct lsh_string *" expr))
 	((object) (list "struct " (cadr type) " *" expr))
+	((struct) (list "struct " (cadr type) " " expr)) 
 	((bignum) (list "mpz_t " expr))
 	((simple special) (list (cadr type) " " expr))
 	((pointer space) (type->declaration (cadr type)
 					    (list "(*(" expr "))")))
 	((array)  (type->declaration (cadr type)
 				     (list "((" expr ")[" (caddr type) "])")))
+	((var-array)  (type->declaration (cadr type)
+				     (list "((" expr ")[1])")))
 	((function) (type->declaration (cadr type)
 				       (list expr
 					     "(" (implode (cddr type) ", ")
@@ -116,6 +123,7 @@
       (case (car type)
 	((string simple function space bignum) #f)
 	((object) (list "mark((struct lsh_object *) " expr ");\n"))
+	((struct) (list (cadr type) "_mark(&" expr ", mark);\n"))
 	((pointer) (if (null? (cddr type))
 		       (type->mark (cadr type) (list "*(" expr ")"))
 
@@ -142,7 +150,14 @@
 		      "  for (k=0; k<" (caddr type) "; k++)\n"
 		      "    " mark-k
 		      "}\n"))))
-	
+	((var-array)
+	 (let ((mark-k (type->mark (cadr type) (list "(" expr ")[k]"))))
+	   (and mark-k
+		(list "{\n  unsigned k;\n"
+		      "  for (k=0; k<i->" (caddr type) "; k++)\n"
+		      "    " mark-k
+		      "}\n"))))
+	 
 	(else (error "make_class: type->mark: Invalid type" type)))))
 
 (define (type->free type expr)
@@ -153,6 +168,7 @@
       (type->free `(simple ,type) expr)
       (case (car type)
 	((object simple function pointer) #f)
+	((struct) (list (cadr type) "_free(&" expr ");\n"))
 	((string) (free/f "lsh_string_free"))
 	((bignum) (free/f "mpz_clear"))
 	((space) (free/f "lsh_space_free"))
@@ -165,9 +181,17 @@
 		      "  for (k=0; k<" (caddr type) "; k++)\n"
 		      "    " free-k
 		      "}\n"))))
+	((var-array)
+	 (let ((free-k (type->free (cadr type) (list "(" expr ")[k]"))))
+	   (and free-k
+		(list "{\n  unsigned k;\n"
+		      "  for (k=0; k<i->" (caddr type) "; k++)\n"
+		      "    " free-k
+		      "}\n"))))
     
 	(else (error "make_class: type->free: Invalid type" type)))))
 
+#!
 (define (type->init type expr)
   (if (atom? type)
       (type->init `(simple ,type) expr)
@@ -183,7 +207,7 @@
 		      "}\n"))))
 
 	(else (error "make_class: type->init: Invalid type" type)))))
-    
+!#  
   
 #!
 (define var-category car)
@@ -218,16 +242,30 @@
 ;; (method (function int "struct this_type *self struct foo *arg") name)
 
 (define (fix-method name var)
-  (if (eq? 'method (cadr var))
-      `(,(car var) pointer (function ,(caddr var) ("struct " ,name " *self")
-				     ,@(cdddr var)))
-      var))
+  (case (cadr var)
+    ((method)
+     `(,(car var) pointer (function ,(caddr var) ("struct " ,name " *self")
+				     ,@(cdddr var))))
+    ((indirect-method)
+     `(,(car var) pointer (function ,(caddr var) ("struct " ,name " **self")
+				     ,@(cdddr var))))
+    (else var)))
+
+(define (do-instance-struct name super vars)
+  ; (werror "do-instance-struct\n")
+  (list "struct " name 
+	"\n{\n"
+	"  struct " (or super "lsh_object") " super;\n"
+	(map (lambda (var)
+	       (list "  " (type->declaration (var-type var)
+					     (var-name var)) ";\n"))
+	     vars)
+	"};\n"))
 
 (define (do-struct name super vars)
-  (werror "do-struct\n")
+  ; (werror "do-struct\n")
   (list "struct " name 
 	"\n{\n"
-	"  struct " (or super "lsh_object") " super;\n"
 	(map (lambda (var)
 	       (list "  " (type->declaration (var-type var)
 					     (var-name var)) ";\n"))
@@ -235,13 +273,13 @@
 	"};\n"))
 
 (define (do-mark-function name vars)
-  (werror "do-mark-function\n")
+  ; (werror "do-mark-function\n")
   (let ((markers (filter identity
 			 (map (lambda (var)
 				(type->mark (var-type var)
 					    (list "i->" (var-name var))))
 			      vars))))
-    (werror "gazonk\n")
+    ; (werror "gazonk\n")
     (and (not (null? markers))
 	 (list "static void do_"
 	       name "_mark(struct lsh_object *o, \n"
@@ -253,14 +291,14 @@
 	       "}\n\n"))))
 
 (define (do-free-function name vars)
-  (werror "do-free-function\n")
+  ; (werror "do-free-function\n")
   (let ((freers (filter identity
 			(map (lambda (var)
 			       (type->free (var-type var) 
 					   (list "i->" (var-name var))))
 			     
 			     vars))))
-    (werror "gazonk\n")
+    ; (werror "gazonk\n")
 
     (and (not (null? freers))
 	 (list "static void do_"
@@ -271,6 +309,43 @@
 		    freers)
 	       "}\n\n"))))
 
+(define (declare-struct-mark-function name)
+  (list "void "	name "_mark(struct " name " *i, \n"
+	"    void (*mark)(struct lsh_object *o))"))
+
+(define (do-struct-mark-function name vars)
+  ; (werror "do-struct-mark-function\n")
+  (let ((markers (filter identity
+			 (map (lambda (var)
+				(type->mark (var-type var)
+					    (list "i->" (var-name var))))
+			      vars))))
+    ; (werror "gazonk\n")
+    (list (declare-struct-mark-function name)
+	  "\n{\n"
+	  (map (lambda (x) (list "  " x))
+	       markers)
+	  "}\n\n")))
+
+(define (declare-struct-free-function name)
+  (list "void " name "_free(struct " name " *i)"))
+
+(define (do-struct-free-function name vars)
+  ; (werror "do-struct-free-function\n")
+  (let ((freers (filter identity
+			(map (lambda (var)
+			       (type->free (var-type var) 
+					   (list "i->" (var-name var))))
+			     
+			     vars))))
+    ; (werror "gazonk\n")
+
+    (list (declare-struct-free-function name)
+	  "\n{\n"
+	  (map (lambda (x) (list "  " x))
+	       freers)
+	  "}\n\n")))
+
 (define (do-class name super mark-function free-function meta methods)
   (define initializer
     (list "{ STATIC_HEADER,\n  "
@@ -286,7 +361,7 @@
 	  (if mark-function (list "do_" name "_mark") "NULL") ",\n  "
 	  (if free-function (list "do_" name "_free") "NULL") "\n"
 	  "}"))
-  (werror "do-class\n")
+  ; (werror "do-class\n")
   (if meta
       (list "struct " meta "_meta " name "_class_extended =\n"
 	    "{ " initializer 
@@ -301,7 +376,7 @@
 (define (process-class exp)
   (let ((type (car exp))
 	(attributes (cdr exp)))
-    (werror "process-class: type = ~S\n" type)
+    ; (werror "process-class: type = ~S\n" type)
     (case type
       ((class)
        (let ((name (get 'name attributes cadr))
@@ -309,14 +384,15 @@
 	     (raw-vars (get 'vars attributes cdr))
 	     (meta (get 'meta attributes cadr))
 	     (methods (get 'methods attributes cdr)))
-	 (werror "foo\n")
+	 (werror "Processing class ~S\n" name)
+	 ; (werror "foo\n")
 	 (let ((vars (map (lambda (var) (fix-method name var))
 			  raw-vars)))
 	   (let ((mark-function (do-mark-function name vars))
 		 (free-function (do-free-function name vars)))
-	     (werror "baar\n")
+	     ; (werror "baar\n")
 	     (list "#ifndef CLASS_DEFINE\n"	
-		   (do-struct name super vars)
+		   (do-instance-struct name super vars)
 		   (if meta
 		       (list "extern struct " meta "_meta "
 			     name "_class_extended;\n")
@@ -331,6 +407,7 @@
       ((meta)
        (let ((name (get 'name attributes cadr))
 	     (methods (get 'methods attributes cdr)))
+	 (werror "Processing meta ~S\n" name)
 	 (list "#ifndef CLASS_DEFINE\n"
 	       "struct " name "_meta\n"
 	       "{\n"
@@ -339,9 +416,29 @@
 		    methods)
 	       "};\n"
 	       "#endif /* !CLASS_DEFINE */\n\n")))
-      (else (list "#error Unknown expression type " type "\n")))))
-
+      ((struct)
+       (let ((name (get 'name attributes cadr))
+	     (super (get 'super attributes cadr))
+	     (raw-vars (get 'vars attributes cdr))
+	     (meta (get 'meta attributes cadr))
+	     (methods (get 'methods attributes cdr)))
+	 (werror "Processing struct ~S\n" name)
+	 ; (werror "foo\n")
+	 ;; FIXME: Is this really needed?
+	 (let ((vars (map (lambda (var) (fix-method name var))
+			  raw-vars)))
+	   ; (werror "baar\n")
+	   (list "#ifndef CLASS_DEFINE\n"	
+		 (do-struct name super vars)
+		 "extern " (declare-struct-mark-function name) ";\n"
+		 "extern " (declare-struct-free-function name) ";\n"
+		 "#endif /* !CLASS_DEFINE */\n\n"
+		 "#ifndef CLASS_DECLARE\n"
+		 (do-struct-mark-function name vars)
+		 (do-struct-free-function name vars)
+		 "#endif /* !CLASS_DECLARE */\n\n"))))
 
+      (else (list "#error Unknown expression type " type "\n")))))
 
 (define main
   (let ((test (lambda (s) (string-prefix? "/* CLASS:" s))))
diff --git a/src/packet_ignore.c b/src/packet_ignore.c
index 071f401dbd4bd4f8565cac7b0dad99a1da0b267c..2af9d6c25f724c479eeb0c1b8616408f5bf6a22f 100644
--- a/src/packet_ignore.c
+++ b/src/packet_ignore.c
@@ -37,9 +37,7 @@ static int do_ignore(struct packet_handler *closure,
 
 struct packet_handler *make_ignore_handler(void)
 {
-  struct packet_handler *res;
-
-  NEW(res);
+  NEW(packet_handler, res);
 
   res->handler = do_ignore;
   return res;
diff --git a/src/pad.c b/src/pad.c
index a2baf1aeff90f5eec89b6a62ca16cc7d5d0c4179..1a4f4367591a24b7cbd6478ec3662d30e5e038d4 100644
--- a/src/pad.c
+++ b/src/pad.c
@@ -30,6 +30,18 @@
 #include "format.h"
 #include "xalloc.h"
 
+#include "pad.c.x"
+
+/* CLASS:
+   (class
+     (name packet_pad)
+     (super abstract_write_pipe)
+     (vars
+       (connection object ssh_connection)
+       (random object randomness)))
+*/
+
+#if 0
 struct packet_pad
 {
   struct abstract_write_pipe super;
@@ -38,12 +50,12 @@ struct packet_pad
 
   struct randomness *random;
 };
+#endif
 
 static int do_pad(struct abstract_write *w,
 		  struct lsh_string *packet)
 {
-  struct packet_pad *closure
-    = (struct packet_pad *) w;
+  CAST(packet_pad, closure, w);
   struct ssh_connection *connection = closure->connection;
 
   struct lsh_string *new;
@@ -54,8 +66,6 @@ static int do_pad(struct abstract_write *w,
   UINT8 *data;
   UINT32 block_size;
 
-  MDEBUG(closure);
-
   block_size = connection->send_crypto
     ? connection->send_crypto->block_size : 8;
   
@@ -85,9 +95,7 @@ make_packet_pad(struct abstract_write *continuation,
 		struct ssh_connection *connection,
 		struct randomness *random)
 {
-  struct packet_pad *closure;
-
-  NEW(closure);
+  NEW(packet_pad, closure);
 
   closure->super.super.write = do_pad;
   closure->super.next = continuation;
diff --git a/src/parse.c b/src/parse.c
index d1adbbf06814e5bcdd46808414887a29e3521791..11877dc4f1b35735cce95851d65e97fcfa01baf9 100644
--- a/src/parse.c
+++ b/src/parse.c
@@ -23,8 +23,10 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include "format.h"
 #include "parse.h"
+
+#include "format.h"
+#include "list.h"
 #include "werror.h"
 #include "xalloc.h"
 
@@ -239,33 +241,33 @@ int parse_next_atom(struct simple_buffer *buffer, int *result)
   return 1;
 }
 
-int *parse_atom_list(struct simple_buffer *buffer)
+struct int_list *parse_atom_list(struct simple_buffer *buffer)
 {
   int count;
   int i;
-  int *res;
+  struct int_list *res;
   
   /* Count commas (no commas means one atom) */
   for (i = buffer->pos, count = 1; i < buffer->capacity; i++)
     if (buffer->data[i] == ',')
       count++;
 
-  res = lsh_space_alloc(sizeof(int) * (count+1));
+  res = alloc_int_list(count);
 
   for (i = 0; i < count; i++)
     {
-      switch(parse_next_atom(buffer, res+i))
+      switch(parse_next_atom(buffer, LIST(res)+i))
 	{
 	case 1:
 	  continue;
 	case 0:
-	  lsh_space_free(res);
+	  KILL(res);
 	  return NULL;
 	default:
 	  fatal("Internal error\n");
 	}
     }
-  res[i] = -1;
+
   return res;
 }
 
diff --git a/src/parse.h b/src/parse.h
index 7a51144712010ff0ee566e7180a5d5ede6646e61..6b1945bbf64ae4bef755baeef031b750af198070 100644
--- a/src/parse.h
+++ b/src/parse.h
@@ -77,10 +77,9 @@ int parse_atom(struct simple_buffer *buffer, int *result);
  * Unknown atoms sets result to zero. */
 int parse_next_atom(struct simple_buffer *buffer, int *result);
 
-/* Allocates an array of integers. The 0 atom means an unknown atom
- * was read. The list is terminated with -1. Returns a NULL pointer on
- * error. */
-int *parse_atom_list(struct simple_buffer *buffer);
+/* Creates a list of integers. The 0 atom means an unknown atom was
+ * read. Returns a NULL pointer on error. */
+struct int_list *parse_atom_list(struct simple_buffer *buffer);
 
 /* Returns success (i.e. 1) iff there is no data left */
 int parse_eod(struct simple_buffer *buffer);
diff --git a/src/password.c b/src/password.c
new file mode 100644
index 0000000000000000000000000000000000000000..15b8b1c05fdf3839a49ee4c7003f56f09346dafb
--- /dev/null
+++ b/src/password.c
@@ -0,0 +1,35 @@
+/* password.c
+ *
+ * System dependant password related functions.
+ *
+ * $Id$
+ */
+
+/* lsh, an implementation of the ssh protocol
+ *
+ * Copyright (C) 1998 Niels M�ller
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "password.h"
+
+#include "xalloc.h"
+
+#define CLASS_DEFINE
+#include "password.h.x"
+#undef CLASS_DEFINE
+
+
diff --git a/src/password.h b/src/password.h
index 2e337e26215a276e7c786286cc917c256219acba..4a68481ef6b7a78d8a968b6b8172edde2cecc13c 100644
--- a/src/password.h
+++ b/src/password.h
@@ -34,6 +34,10 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#define CLASS_DECLARE
+#include "password.h.x"
+#undef CLASS_DECLARE
+
 struct lsh_string *
 read_password(int max_length, struct lsh_string *prompt, int free);
 
diff --git a/src/publickey_crypto.c b/src/publickey_crypto.c
index 3a69a1be76f2ab0a84aa58058e61411ba69304bd..0312f481f939f9a4a6e80cf7fa4949a4e613d7bb 100644
--- a/src/publickey_crypto.c
+++ b/src/publickey_crypto.c
@@ -36,8 +36,23 @@
 #include "werror.h"
 #include "xalloc.h"
 
-/* DSS signatures */
+#define CLASS_DEFINE
+#include "publickey_crypto.h.x"
+#undef CLASS_DEFINE
+
+#include "publickey_crypto.c.x"
 
+/* DSS signatures */
+/* CLASS:
+   (class
+     (name dss_signer)
+     (super signer)
+     (vars
+       (random object randomness)
+       (public struct dss_public)
+       (a bignum)))
+*/
+#if 0
 struct dss_signer
 {
   struct signer super;
@@ -45,18 +60,38 @@ struct dss_signer
   struct dss_public public;
   mpz_t a; 		/* Private key */
 };
+#endif
+
+/* CLASS:
+   (class
+     (name dss_verifier)
+     (super verifier)
+     (vars
+       (public struct dss_public)))
+*/
 
+#if 0
 struct dss_verifier
 {
   struct verifier super;
   struct dss_public public;
 };
-  
+#endif
+
+/* CLASS:
+   (class
+     (name dss_algorithm)
+     (super signature_algorithm)
+     (vars
+       (random object randomness)))
+*/
+#if 0
 struct dss_algorithm
 {
   struct signature_algorithm super;
   struct randomness *random;
 };
+#endif
 
 static void dss_hash(mpz_t h, UINT32 length, UINT8 *msg)
 {
@@ -72,19 +107,17 @@ static void dss_hash(mpz_t h, UINT32 length, UINT8 *msg)
   debug_mpz(h);
   debug("\n");
   
-  lsh_object_free(hash);
+  KILL(hash);
 }
 
 static struct lsh_string *do_dss_sign(struct signer *c,
 				      UINT32 length,
 				      UINT8 *msg)
 {
-  struct dss_signer *closure = (struct dss_signer *) c;
+  CAST(dss_signer, closure, c);
   mpz_t k, r, s, tmp;
   struct lsh_string *signature;
 
-  MDEBUG(closure);
-  
   /* Select k, 0<k<q, randomly */
   mpz_init_set(tmp, closure->public.q);
   mpz_sub_ui(tmp, tmp, 1);
@@ -161,7 +194,7 @@ static int do_dss_verify(struct verifier *c,
 			 UINT32 signature_length,
 			 UINT8 * signature_data)
 {
-  struct dss_verifier *closure = (struct dss_verifier *) c;
+  CAST(dss_verifier, closure, c);
   struct simple_buffer buffer;
 
   int res;
@@ -171,8 +204,6 @@ static int do_dss_verify(struct verifier *c,
 
   mpz_t w, tmp, v;
 
-  MDEBUG(closure);
-  
   simple_buffer_init(&buffer, signature_length, signature_data);
   if (!parse_atom(&buffer, &atom)
       || (atom != ATOM_SSH_DSS) )
@@ -270,7 +301,8 @@ static int do_dss_verify(struct verifier *c,
   return !res;
 }
 
-static int parse_dss_public(struct simple_buffer *buffer, struct dss_public *public)
+static int parse_dss_public(struct simple_buffer *buffer,
+			    struct dss_public *public)
 {
   return (parse_bignum(buffer, public->p)
 	  && (mpz_sgn(public->p) == 1)
@@ -293,42 +325,37 @@ static struct signer *make_dss_signer(struct signature_algorithm *c,
 				      UINT32 private_length,
 				      UINT8 *private)
 {
-  struct dss_algorithm *closure = (struct dss_algorithm *) c;
+  CAST(dss_algorithm, closure, c);
+  NEW(dss_signer, res);
   
-  struct dss_signer *res;
   struct simple_buffer public_buffer;
   struct simple_buffer private_buffer;  
   int atom;
 
-  MDEBUG(closure);
-  
-  simple_buffer_init(&public_buffer, public_length, public);
-  if (!parse_atom(&public_buffer, &atom)
-      || (atom != ATOM_SSH_DSS) )
-    return 0;
-  
-  simple_buffer_init(&private_buffer, private_length, private);
-
-  NEW(res);
-
+  /* FIXME: The allocator could do this kind of initialization
+   * automatically. */
   mpz_init(res->public.p);
   mpz_init(res->public.q);
   mpz_init(res->public.g);
   mpz_init(res->public.y);
   mpz_init(res->a);
   
+  simple_buffer_init(&public_buffer, public_length, public);
+  if (!parse_atom(&public_buffer, &atom)
+      || (atom != ATOM_SSH_DSS) )
+    {
+      KILL(res);
+      return 0;
+    }
+  simple_buffer_init(&private_buffer, private_length, private);
+
   if (! (parse_dss_public(&public_buffer, &res->public)
   	 && parse_bignum(&private_buffer, res->a)
 	 /* FIXME: Perhaps do some more sanity checks? */
 	 && (mpz_sgn(res->a) == 1)
 	 && parse_eod(&private_buffer) ))
     {
-      mpz_clear(res->public.p);
-      mpz_clear(res->public.q);
-      mpz_clear(res->public.g);
-      mpz_clear(res->public.y);
-      mpz_clear(res->a);
-      lsh_object_free(res);
+      KILL(res);
       return NULL;
     }
   
@@ -342,30 +369,29 @@ static struct verifier *make_dss_verifier(struct signature_algorithm *closure,
 					  UINT32 public_length,
 					  UINT8 *public)
 {
-  struct dss_verifier *res;
+  NEW(dss_verifier, res);
   struct simple_buffer buffer;
   int atom;
 
-  simple_buffer_init(&buffer, public_length, public);
-  if (!parse_atom(&buffer, &atom)
-      || (atom != ATOM_SSH_DSS) )
-    return 0;
-
-  NEW(res);
-
+  /* FIXME: The allocator could do this kind of initialization
+   * automatically. */
   mpz_init(res->public.p);
   mpz_init(res->public.q);
   mpz_init(res->public.g);
   mpz_init(res->public.y);
   
+  simple_buffer_init(&buffer, public_length, public);
+  if (!parse_atom(&buffer, &atom)
+      || (atom != ATOM_SSH_DSS) )
+    {
+      KILL(res);
+      return 0;
+    }
+  
   if (!parse_dss_public(&buffer, &res->public))
     /* FIXME: Perhaps do some more sanity checks? */
     {
-      mpz_clear(res->public.p);
-      mpz_clear(res->public.q);
-      mpz_clear(res->public.g);
-      mpz_clear(res->public.y);
-      lsh_object_free(res);
+      KILL(res);
       return NULL;
     }
 
@@ -375,9 +401,7 @@ static struct verifier *make_dss_verifier(struct signature_algorithm *closure,
 
 struct signature_algorithm *make_dss_algorithm(struct randomness *random)
 {
-  struct dss_algorithm *dss;
-
-  NEW(dss);
+  NEW(dss_algorithm, dss);
 
   dss->super.make_signer = make_dss_signer;
   dss->super.make_verifier = make_dss_verifier;
@@ -387,23 +411,31 @@ struct signature_algorithm *make_dss_algorithm(struct randomness *random)
 }
     
 /* Groups */
-
+/* CLASS:
+   (class
+     (name group_zn)
+     (super group)
+     (vars
+       (modulo bignum)))
+*/
+#if 0
 struct group_zn  /* Z_n^* */
 {
   struct group super;
   mpz_t modulo;
 };
+#endif
 
 static int zn_member(struct group *c, mpz_t x)
 {
-  struct group_zn *closure = (struct group_zn *) c;
+  CAST(group_zn, closure, c);
 
   return ( (mpz_sgn(x) == 1) && (mpz_cmp(x, closure->modulo) < 0) );
 }
 
 static void zn_invert(struct group *c, mpz_t res, mpz_t x)
 {
-  struct group_zn *closure = (struct group_zn *) c;
+  CAST(group_zn, closure, c);
 
   if (!mpz_invert(res, x, closure->modulo))
     fatal("zn_invert: element is non-invertible\n");
@@ -413,7 +445,7 @@ static void zn_invert(struct group *c, mpz_t res, mpz_t x)
 
 static void zn_combine(struct group *c, mpz_t res, mpz_t a, mpz_t b)
 {
-  struct group_zn *closure = (struct group_zn *) c;
+  CAST(group_zn, closure, c);
 
   mpz_mul(res, a, b);
   mpz_fdiv_r(res, res, closure->modulo);
@@ -421,7 +453,7 @@ static void zn_combine(struct group *c, mpz_t res, mpz_t a, mpz_t b)
 
 static void zn_power(struct group *c, mpz_t res, mpz_t g, mpz_t e)
 {
-  struct group_zn *closure = (struct group_zn *) c;
+  CAST(group_zn, closure, c);
 
   mpz_powm(res, g, e, closure->modulo);
 }
@@ -429,9 +461,7 @@ static void zn_power(struct group *c, mpz_t res, mpz_t g, mpz_t e)
 /* Assumes p is a prime number */
 struct group *make_zn(mpz_t p)
 {
-  struct group_zn *res;
-
-  NEW(res);
+  NEW(group_zn, res);
 
   res->super.member = zn_member;
   res->super.invert = zn_invert;
@@ -450,6 +480,8 @@ void init_diffie_hellman_instance(struct diffie_hellman_method *m,
 				  struct diffie_hellman_instance *self,
 				  struct ssh_connection *c)
 {
+  /* FIXME: The allocator could do this kind of initialization
+   * automatically. */
   mpz_init(self->e);
   mpz_init(self->f);
   mpz_init(self->secret);
@@ -495,11 +527,9 @@ void init_diffie_hellman_instance(struct diffie_hellman_method *m,
 
 struct diffie_hellman_method *make_dh1(struct randomness *r)
 {
-  struct diffie_hellman_method *res;
+  NEW(diffie_hellman_method, res);
   mpz_t p;
   
-  NEW(res);
-  
   mpz_init_set_str(p,
 		   "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
 		   "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
diff --git a/src/publickey_crypto.h b/src/publickey_crypto.h
index 9a23854d2e25f5ed521e516990a45e8ac4e8361a..90252c54f9633b0282e7d99d403ffb2861cf2dfd 100644
--- a/src/publickey_crypto.h
+++ b/src/publickey_crypto.h
@@ -30,8 +30,14 @@
 #include "bignum.h"
 #include "connection.h"
 
+#define CLASS_DECLARE
+#include "publickey_crypto.h.x"
+#undef CLASS_DECLARE
+
 struct signature_algorithm *make_dss_algorithm(struct randomness *random);
 
+/* FIXME: Groups could use "non-virtual" methods */
+
 /* Groups. For now, assume that all group elements are represented by
  * bignums. */
 /* CLASS:
diff --git a/src/randomness.c b/src/randomness.c
index be45a947827dbdaace188d3a1b29c751082c9536..8b9097926e9cfab618797aee81af4d5ea77c2bc0 100644
--- a/src/randomness.c
+++ b/src/randomness.c
@@ -30,7 +30,24 @@
 
 #include "xalloc.h"
 
+#define CLASS_DEFINE
+#include "randomness.h.x"
+#undef CLASS_DEFINE
+
+#include "randomness.c.x"
+
 /* Random */
+/* CLASS:
+   (class
+     (name poor_random)
+     (super randomness)
+     (vars
+       (hash object hash_instance)
+       (pos simple UINT32)
+       (buffer space UINT8)))
+*/
+
+#if 0
 struct poor_random
 {
   struct randomness super;
@@ -38,13 +55,12 @@ struct poor_random
   UINT32 pos;
   UINT8 *buffer;
 };
+#endif
 
-static void do_poor_random(struct randomness **r, UINT32 length, UINT8 *dst)
+static void do_poor_random(struct randomness *r, UINT32 length, UINT8 *dst)
 {
-  struct poor_random *self = (struct poor_random *) *r;
+  CAST(poor_random, self, r);
 
-  MDEBUG(self);
-  
   while(length)
     {
       UINT32 available = self->hash->hash_size - self->pos;
@@ -73,11 +89,9 @@ static void do_poor_random(struct randomness **r, UINT32 length, UINT8 *dst)
 struct randomness *make_poor_random(struct hash_algorithm *hash,
 				    struct lsh_string *init)
 {
-  struct poor_random *self;
+  NEW(poor_random, self);
   time_t now = time(NULL); /* To avoid cycles */
 
-  NEW(self);
-  
   self->super.random = do_poor_random;
   self->hash = MAKE_HASH(hash);
   self->buffer = lsh_space_alloc(hash->hash_size);
diff --git a/src/randomness.h b/src/randomness.h
index 53d79add47bc7a6107723d8942cf6b948263f658..1e954346ab2c32f026d9601e0567c9ec11fc8a56 100644
--- a/src/randomness.h
+++ b/src/randomness.h
@@ -28,14 +28,27 @@
 
 #include "abstract_crypto.h"
 
+#define CLASS_DECLARE
+#include "randomness.h.x"
+#undef CLASS_DECLARE
+
+/* CLASS:
+   (class
+     (name randomness)
+     (vars
+       (random method void "UINT32 length" "UINT8 *dst")))
+*/
+
+#if 0
 struct randomness
 {
   struct lsh_object header;
   
   void (*random)(struct randomness **closure, UINT32 length, UINT8 *dst);
 };
+#endif
 
-#define RANDOM(r, length, dst) ((r)->random(&(r), length, dst))
+#define RANDOM(r, length, dst) ((r)->random((r), length, dst))
 
 struct randomness *make_poor_random(struct hash_algorithm *hash,
 				    struct lsh_string *init);
diff --git a/src/read_data.c b/src/read_data.c
index 01d8c2ce24190f3e7d0b76c0c3e7d93de3ed3b35..43e312f45c31d8474f6334cb4c9d353b1e834a34 100644
--- a/src/read_data.c
+++ b/src/read_data.c
@@ -30,6 +30,25 @@
 
 #include <assert.h>
 
+#include "read_data.c.x"
+
+/* CLASS:
+   (class
+     (name read_data)
+     (super read_handler)
+     (vars
+       ; Where to send the data 
+       (write object abstract_write)
+
+       ; For flow control. 
+   
+       ; FIXME: Perhaps the information that is needed for flow
+       ; control should be abstracted out from the channel struct? 
+
+       (channel object ssh_channel)))
+*/
+
+#if 0
 struct read_data
 {
   struct read_handler super; /* Super type */
@@ -44,17 +63,16 @@ struct read_data
 
   struct ssh_channel *channel;
 };
+#endif
 
 static int do_read_data(struct read_handler **h,
 			struct abstract_read *read)
 {
-  struct read_data *closure = (struct read_data *) *h;
+  CAST(read_data, closure, *h);
   int to_read;
   int n;
   struct lsh_string *packet;
   
-  MDEBUG_SUBTYPE(closure);
-
   assert(closure->channel->sources);
   
   if (closure->channel->flags &
@@ -100,9 +118,7 @@ static int do_read_data(struct read_handler **h,
 struct read_handler *make_read_data(struct ssh_channel *channel,
 				    struct abstract_write *write)
 {
-  struct read_data *closure;
-
-  NEW(closure);
+  NEW(read_data, closure);
 
   closure->super.handler = do_read_data;
   closure->channel = channel;
diff --git a/src/read_line.c b/src/read_line.c
index 2ab0113f884bbe0e806052e81267defd789c4ed7..060ce06505ec1fac623ca2db6d1de87f75407948 100644
--- a/src/read_line.c
+++ b/src/read_line.c
@@ -26,9 +26,29 @@
 #include <string.h>
 
 #include "read_line.h"
+
 #include "werror.h"
 #include "xalloc.h"
 
+#define CLASS_DEFINE
+#include "read_line.h.x"
+#undef CLASS_DEFINE
+
+#include "read_line.c.x"
+
+/* CLASS:
+   (class
+     (name read_line)
+     (super read_handler)
+     (vars
+       (handler object line_handler)
+
+       ; Line buffer       
+       (pos simple UINT32)
+       (buffer array UINT8 MAX_LINE)))
+*/
+
+#if 0
 struct read_line
 {
   struct read_handler super; /* Super type */
@@ -37,25 +57,34 @@ struct read_line
   UINT32 pos;   /* Line buffer */
   UINT8 buffer[MAX_LINE];
 };
-
+#endif
+
+/* CLASS:
+   (class
+     (name string_read)
+     (super abstract_read)
+     (vars
+       (line object read_line)
+       (index simple UINT32)))
+*/
+
+#if 0
 struct string_read
 {
   struct abstract_read super;
   struct read_line *line;
   UINT32 index;
 };
+#endif
 
 static int do_string_read(struct abstract_read **r,
 			  UINT32 length, UINT8 *buffer)
 {
-  struct string_read *closure
-    = (struct string_read *) *r;
+  CAST(string_read, closure, *r);
   
   UINT32 left = closure->line->pos - closure->index;
   UINT32 to_read = MIN(length, left);
 
-  MDEBUG(closure);
-  
   memcpy(buffer, closure->line->buffer + closure->index, to_read);
   closure->index += to_read;
 
@@ -65,15 +94,13 @@ static int do_string_read(struct abstract_read **r,
 static int do_read_line(struct read_handler **h,
 			struct abstract_read *read)
 {
-  struct read_line *closure = (struct read_line *) *h;
+  CAST(read_line, closure, *h);
   
   UINT8 *eol;
   UINT32 length;
   struct read_handler *next;
   int n;
 
-  MDEBUG(closure);
-  
   n = A_READ(read, MAX_LINE - closure->pos, closure->buffer);
 
   switch(n)
@@ -136,7 +163,7 @@ static int do_read_line(struct read_handler **h,
 		}
 	    }
 	  /* No data left */
-	  lsh_object_free(closure);
+	  KILL(closure);
 	  *h = next;
 	  return LSH_OK | LSH_GOON;
 	}
@@ -159,9 +186,7 @@ static int do_read_line(struct read_handler **h,
 
 struct read_handler *make_read_line(struct line_handler *handler)
 {
-  struct read_line *closure;
-
-  NEW(closure);
+  NEW(read_line, closure);
 
   closure->super.handler = do_read_line;
   closure->pos = 0;
diff --git a/src/read_line.h b/src/read_line.h
index f32b8287ee25fc5b312186cda8d9bfff7c5ee584..d7c7917903544c8b963baa51de82c97f63b2f5fe 100644
--- a/src/read_line.h
+++ b/src/read_line.h
@@ -28,10 +28,23 @@
 
 #include "abstract_io.h"
 
+#define CLASS_DECLARE
+#include "read_line.h.x"
+#undef CLASS_DECLARE
+
 /* This limit follows the ssh specification */
 #define MAX_LINE 255
 
 /* May store a new handler into *h. */
+/* CLASS:
+   (class
+     (name line_handler)
+     (vars
+       (handler indirect-method "struct read_handler *"
+		"UINT32 length" "UINT8 *line")))
+*/
+
+#if 0
 struct line_handler
 {
   struct lsh_object header;
@@ -40,6 +53,7 @@ struct line_handler
 				   UINT32 length,
 				   UINT8 *line);
 };
+#endif
 
 #define PROCESS_LINE(h, length, line) \
 ((h)->handler(&(h), (length), (line)))
diff --git a/src/read_packet.c b/src/read_packet.c
index 41076dea5eede6b2fc4e84a3b0fea8a48eecf9eb..c178d12797fe9908b7060141e1eee0c927cf2e01 100644
--- a/src/read_packet.c
+++ b/src/read_packet.c
@@ -40,6 +40,34 @@
 #define WAIT_CONTENTS 2
 #define WAIT_MAC 3
 
+#include "read_packet.c.x"
+
+/* CLASS:
+   (class
+     (name read_packet)
+     (super read_handler)
+     (vars
+       (state simple int)
+  
+       ; Attached to read packets
+       (sequence_number simple UINT32)
+  
+       ; Buffer partial headers and packets.
+       (pos simple UINT32)
+
+       ; NOTE: This buffer should hold one block, and must be
+       ; reallocated when the crypto algorithms is changed. 
+       (buffer string)
+       (crypt_pos simple "UINT8 *")
+
+       ; Must point to an area large enough to hold a mac 
+       (recieved_mac string) 
+  
+       (handler object abstract_write)
+       (connection object ssh_connection)))
+*/
+     
+#if 0
 struct read_packet
 {
   struct read_handler super; /* Super type */
@@ -62,6 +90,7 @@ struct read_packet
   struct abstract_write *handler;
   struct ssh_connection *connection;
 };
+#endif
 
 static struct lsh_string *
 lsh_string_realloc(struct lsh_string *s, UINT32 length)
@@ -86,11 +115,9 @@ lsh_string_realloc(struct lsh_string *s, UINT32 length)
 static int do_read_packet(struct read_handler **h,
 			  struct abstract_read *read)
 {
-  struct read_packet *closure = (struct read_packet *) *h;
+  CAST(read_packet, closure, *h);
   int total = 0;
   
-  MDEBUG(closure);
-
   while (total < QUANTUM)
     switch(closure->state)
       {
@@ -303,9 +330,7 @@ static int do_read_packet(struct read_handler **h,
 struct read_handler *make_read_packet(struct abstract_write *handler,
 				      struct ssh_connection *connection)
 {
-  struct read_packet *closure;
-
-  NEW(closure);
+  NEW(read_packet, closure);
 
   closure->super.handler = do_read_packet;
 
diff --git a/src/reaper.c b/src/reaper.c
index 3ea7d8af0634c792c06e370529affd1d1a6e0287..231aa88da4f563ff20fd606c767e4a1a8ac60824 100644
--- a/src/reaper.c
+++ b/src/reaper.c
@@ -38,6 +38,12 @@
 #include <sys/types.h>
 #include <sys/wait.h>
 
+#define CLASS_DEFINE
+#include "reaper.h.x"
+#undef CLASS_DEFINE
+
+#include "reaper.c.x"
+
 static sig_atomic_t halloween;
 
 static void child_handler(int signum)
@@ -47,6 +53,17 @@ static void child_handler(int signum)
   halloween = 1;
 }
 
+/* CLASS:
+   (class
+     (name reaper)
+     (super reap)
+     (vars
+       ; Mapping of from pids to exit-callbacks. 
+       ; NOTE: This assumes that a pid_t fits in an int. 
+       (children object alist)))
+*/
+
+#if 0
 struct reaper
 {
   struct reap super;
@@ -55,13 +72,12 @@ struct reaper
   /* NOTE: This assumes that a pid_t fits in an int. */
   struct alist *children;
 };
+#endif
 
 static void do_reap(struct reap *c,
 		    pid_t pid, struct exit_callback *callback)
 {
-  struct reaper *closure = (struct reaper *) c;
-
-  MDEBUG(closure);
+  CAST(reaper, closure, c);
 
   assert(!ALIST_GET(closure->children, pid));
 
@@ -138,9 +154,8 @@ static void reap(struct reaper *r)
 
 struct reap *make_reaper(void)
 {
-  struct reaper *closure;
+  NEW(reaper, closure);
 
-  NEW(closure);
   closure->super.reap = do_reap;
   closure->children = make_linked_alist(0, -1);
 
@@ -150,13 +165,11 @@ struct reap *make_reaper(void)
 /* FIXME: Prehaps this function should return a suitable exit code? */
 void reaper_run(struct reap *r, struct io_backend *b)
 {
-  struct reaper *self  = (struct reaper *) r;
+  CAST(reaper, self, r);
   
   struct sigaction pipe;
   struct sigaction chld;
 
-  MDEBUG(self);
-  
   pipe.sa_handler = SIG_IGN;
   sigemptyset(&pipe.sa_mask);
   pipe.sa_flags = 0;
diff --git a/src/reaper.h b/src/reaper.h
index dac5d8db9cbb97d40b4d18c25a5e688d2da0d5e4..1b71115feea91b6b2ef2b4d2fffeed04982df85d 100644
--- a/src/reaper.h
+++ b/src/reaper.h
@@ -29,6 +29,18 @@
 
 #include "io.h"
 
+#define CLASS_DECLARE
+#include "reaper.h.x"
+#undef CLASS_DECLARE
+
+/* CLASS:
+   (class
+     (name exit_callback)
+     (vars
+       (exit method void "int signaled" "int core" "int value")))
+*/
+
+#if 0
 struct exit_callback
 {
   struct lsh_object header;
@@ -36,15 +48,25 @@ struct exit_callback
   void (*exit)(struct exit_callback *closure,
 	       int signaled, int core, int value);
 };
+#endif
 
 #define EXIT_CALLBACK(e, s, c, v) ((e)->exit((e), (s), (c), (v)))
 
+/* CLASS:
+   (class
+     (name reap)
+     (vars
+       (reap method void "pid_t pid" "struct exit_callback *callback")))
+*/
+
+#if 0
 struct reap
 {
   struct lsh_object header;
 
   void (*reap)(struct reap *closure, pid_t pid, struct exit_callback *callback);
 };
+#endif
 
 #define REAP(r, p, c) ((r)->reap((r), (p), (c)))
 
diff --git a/src/server.c b/src/server.c
index 27478811aa7564d41cca2440145229b26c6f4017..318c7127ad50d007b7d36d2798c00219f8b8b5c4 100644
--- a/src/server.c
+++ b/src/server.c
@@ -70,6 +70,31 @@
 #include <signal.h>
 #include <unistd.h>
 
+#define CLASS_DEFINE
+#include "server.h.x"
+#undef CLASS_DEFINE
+
+#include "server.c.x"
+
+/* CLASS:
+   (class
+     (name server_callback)
+     (super fd_callback)
+     (vars
+       (backend object io_backend)
+
+        (secret object signer) ; Secret key
+	(host_key string)      ; Public key 
+
+	(block_size simple UINT32)
+	(id_comment simple "char *")
+
+	(random object randomness)
+	(init object make_kexinit)
+	(kexinit_handler object packet_handler)))
+*/
+     
+#if 0
 struct server_callback
 {
   struct fd_callback super;
@@ -84,6 +109,7 @@ struct server_callback
   struct make_kexinit *init;
   struct packet_handler *kexinit_handler;
 };
+#endif
 
 static int server_initiate(struct fd_callback **c,
 			   int fd)
@@ -121,19 +147,27 @@ static int server_initiate(struct fd_callback **c,
 				    NULL);
 }
 
+/* CLASS:
+   (class
+     (name server_line_handler)
+     (super line_handler)
+     (vars
+       (connection object ssh_connection)))
+*/
+
+#if 0
 struct server_line_handler
 {
   struct line_handler super;
   struct ssh_connection *connection;
 };
+#endif
 
 static struct read_handler *do_line(struct line_handler **h,
 				    UINT32 length,
 				    UINT8 *line)
 {
-  struct server_line_handler *closure = (struct server_line_handler *) *h;
-  
-  MDEBUG(closure);
+  CAST(server_line_handler, closure, *h);
   
   if ( (length >= 4) && !memcmp(line, "SSH-", 4))
     {
@@ -155,7 +189,7 @@ static struct read_handler *do_line(struct line_handler **h,
 	  verbose("\n");
 	  
 	  /* FIXME: Cleanup properly. */
-	  lsh_object_free(closure);
+	  KILL(closure);
 
 	  return new;
 	}
@@ -166,7 +200,7 @@ static struct read_handler *do_line(struct line_handler **h,
 	  werror("\n");
 
 	  /* FIXME: Clean up properly */
-	  lsh_object_free(closure);
+	  KILL(closure);
 	  *h = 0;
 		  
 	  return 0;
@@ -184,10 +218,8 @@ static struct read_handler *do_line(struct line_handler **h,
 
 struct read_handler *make_server_read_line(struct ssh_connection *c)
 {
-  struct server_line_handler *closure;
+  NEW(server_line_handler, closure);
 
-  NEW(closure);
-  
   closure->super.handler = do_line;
   closure->connection = c;
   
@@ -202,9 +234,7 @@ make_server_callback(struct io_backend *b,
 		     struct make_kexinit *init,
 		     struct packet_handler *kexinit_handler)
 {
-  struct server_callback *connected;
-
-  NEW(connected);
+  NEW(server_callback, connected);
 
   connected->super.f = server_initiate;
   connected->backend = b;
@@ -229,9 +259,7 @@ static int server_die(struct close_callback *closure, int reason)
 
 struct close_callback *make_server_close_handler(void)
 {
-  struct close_callback *c;
-
-  NEW(c);
+  NEW(close_callback, c);
 
   c->f = server_die;
 
@@ -239,6 +267,24 @@ struct close_callback *make_server_close_handler(void)
 }
 
 /* Session */
+/* CLASS:
+   (class
+     (name server_session)
+     (super ssh_channel)
+     (vars
+       ; User information
+       (user object unix_user)
+
+       ; Non-zero if a shell or command has been started. 
+       (running simple int)
+
+       ; Child process's stdio 
+       (in object io_fd)
+       (out object io_fd)
+       (err object io_fd)))
+*/
+
+#if 0
 struct server_session
 {
   struct ssh_channel super;
@@ -254,15 +300,14 @@ struct server_session
   struct io_fd *out;
   struct io_fd *err;
 };
+#endif
 
 /* Recieve channel data */
 static int do_recieve(struct ssh_channel *c,
 		      int type, struct lsh_string *data)
 {
-  struct server_session *closure = (struct server_session *) c;
+  CAST(server_session, closure, c);
   
-  MDEBUG(closure);
-
   switch(type)
     {
     case CHANNEL_DATA:
@@ -279,9 +324,7 @@ static int do_recieve(struct ssh_channel *c,
 /* We may send more data */
 static int do_send(struct ssh_channel *c)
 {
-  struct server_session *closure = (struct server_session *) c;
-
-  MDEBUG(closure);
+  CAST(server_session, closure, c);
 
   assert(closure->out->super.read);
   assert(closure->out->handler);
@@ -298,9 +341,7 @@ struct ssh_channel *make_server_session(struct unix_user *user,
 					UINT32 max_window,
 					struct alist *request_types)
 {
-  struct server_session *self;
-
-  NEW(self);
+  NEW(server_session, self);
 
   init_channel(&self->super);
 
@@ -322,6 +363,16 @@ struct ssh_channel *make_server_session(struct unix_user *user,
   return &self->super;
 }
 
+/* CLASS:
+   (class
+     (name open_session)
+     (super channel_open)
+     (vars
+       (user object unix_user)
+       (session_requests object alist)))
+*/
+
+#if 0
 struct open_session
 {
   struct channel_open super;
@@ -329,6 +380,7 @@ struct open_session
   struct unix_user *user;
   struct alist *session_requests;
 };
+#endif
 
 #define WINDOW_SIZE (SSH_MAX_PACKET << 3)
 
@@ -338,10 +390,8 @@ static struct ssh_channel *do_open_session(struct channel_open *c,
 					   char **error_msg,
 					   struct lsh_string **data)
 {
-  struct open_session *closure = (struct open_session *) c;
+  CAST(open_session, closure, c);
   
-  MDEBUG(closure);
-
   debug("server.c: do_open_session()\n");
   
   if (!parse_eod(args))
@@ -354,9 +404,7 @@ static struct ssh_channel *do_open_session(struct channel_open *c,
 struct channel_open *make_open_session(struct unix_user *user,
 				       struct alist *session_requests)
 {
-  struct open_session *closure;
-
-  NEW(closure);
+  NEW(open_session, closure);
 
   closure->super.handler = do_open_session;
   closure->user = user;
@@ -365,6 +413,22 @@ struct channel_open *make_open_session(struct unix_user *user,
   return &closure->super;
 }
 
+/* CLASS:
+   (class
+     (name server_connection_service)
+     (super unix_service)
+     (vars
+       (global_requests object alist)
+
+       ; Requests specific to session channels 
+       (session_requests object alist)
+
+       ; FIXME: Doesn't support any channel types but "session". This
+       ; must be fixed to support for "direct-tcpip" channels.
+       ))
+*/
+
+#if 0
 struct server_connection_service
 {
   struct unix_service super;
@@ -377,15 +441,13 @@ struct server_connection_service
   /* FIXME: Doesn't support any channel types but "session".
    * This must be fixed to support for "direct-tcpip" channels. */
 };
+#endif
 
 /* Start an authenticated ssh-connection service */
 static struct ssh_service *do_login(struct unix_service *c,
 				    struct unix_user *user)
 {
-  struct server_connection_service *closure
-    = (struct server_connection_service *) c;
-
-  MDEBUG(closure);
+  CAST(server_connection_service, closure, c);
 
   debug("server.c: do_login()\n");
   
@@ -401,9 +463,7 @@ static struct ssh_service *do_login(struct unix_service *c,
 struct unix_service *make_server_session_service(struct alist *global_requests,
 						 struct alist *session_requests)
 {
-  struct server_connection_service *closure;
-
-  NEW(closure);
+  NEW(server_connection_service, closure);
 
   closure->super.login = do_login;
   closure->global_requests = global_requests;
@@ -433,23 +493,32 @@ struct lsh_string *format_exit(struct ssh_channel *channel, int value)
 				0,
 				"%i", value);
 }
-      
+
+/* CLASS:
+   (class
+     (name exit_shell)
+     (super exit_callback)
+     (vars
+       (session object server_session)))
+*/
+
+#if 0
 struct exit_shell
 {
   struct exit_callback super;
 
   struct server_session *session;
 };
+#endif
 
 static void do_exit_shell(struct exit_callback *c, int signaled,
 			  int core, int value)
 {
-  struct exit_shell *closure = (struct exit_shell *) c;
+  CAST(exit_shell, closure, c);
   struct server_session *session = closure->session;
   struct ssh_channel *channel = &session->super;
   
-  MDEBUG(closure);
-  MDEBUG(session);
+  CHECK_TYPE(server_session, session);
 
   /* FIXME: Should we explicitly mark these files for closing?
    * The io-backend should notice EOF anyway. */
@@ -494,9 +563,7 @@ static void do_exit_shell(struct exit_callback *c, int signaled,
 
 static struct exit_callback *make_exit_shell(struct server_session *session)
 {
-  struct exit_shell *self;
-
-  NEW(self);
+  NEW(exit_shell, self);
 
   self->super.exit = do_exit_shell;
   self->session = session;
@@ -504,6 +571,16 @@ static struct exit_callback *make_exit_shell(struct server_session *session)
   return &self->super;
 }
 
+/* CLASS:
+   (class
+     (name shell_request)
+     (super channel_request)
+     (vars
+       (backend object io_backend)
+       (reap object reap)))
+*/
+
+#if 0
 struct shell_request
 {
   struct channel_request super;
@@ -511,6 +588,7 @@ struct shell_request
   struct io_backend *backend;
   struct reap *reap;
 };
+#endif
 
 /* Creates a one-way socket connection. Returns 1 on successm 0 on
  * failure. fds[0] is for reading, fds[1] for writing (like for the
@@ -553,15 +631,14 @@ static int do_spawn_shell(struct channel_request *c,
 			  int want_reply,
 			  struct simple_buffer *args)
 {
-  struct shell_request *closure = (struct shell_request *) c;
+  CAST(shell_request, closure, c);
   struct server_session *session = (struct server_session *) channel;
 
   int in[2];
   int out[2];
   int err[2];
 
-  MDEBUG(closure);
-  MDEBUG(session);
+  CHECK_TYPE(server_session, session);
 
   if (!parse_eod(args))
     return LSH_FAIL | LSH_DIE;
@@ -761,9 +838,8 @@ static int do_spawn_shell(struct channel_request *c,
 struct channel_request *make_shell_handler(struct io_backend *backend,
 					   struct reap *reap)
 {
-  struct shell_request *closure;
+  NEW(shell_request, closure);
 
-  NEW(closure);
   closure->super.handler = do_spawn_shell;
   closure->backend = backend;
   closure->reap = reap;
diff --git a/src/server_keyexchange.c b/src/server_keyexchange.c
index bef6b31e0a258305af400672fdfad9c4428c5fa2..9c7d1844aea6485e9f37fc3a0262b132f8510366 100644
--- a/src/server_keyexchange.c
+++ b/src/server_keyexchange.c
@@ -30,6 +30,19 @@
 #include "werror.h"
 #include "xalloc.h"
 
+#include "server_keyexchange.c.x"
+
+/* CLASS:
+   (class
+     (name dh_server_exchange)
+     (super keyexchange_algorithm)
+     (vars
+       (dh object diffie_hellman_method)
+       (server_key string)
+       (signer object signer)))
+*/
+
+#if 0
 struct dh_server_exchange
 {
   struct keyexchange_algorithm super;
@@ -37,8 +50,22 @@ struct dh_server_exchange
   struct lsh_string *server_key;
   struct signer *signer;
 };
+#endif
 
 /* Handler for the kex_dh_reply message */
+/* CLASS:
+   (class
+     (name dh_server)
+     (super packet_handler)
+     (vars
+       (dh struct diffie_hellman_instance)
+       ;; (server_key string)
+       (signer object signer)
+       (install object install_keys)
+       (finished object ssh_service)))
+*/
+
+#if 0
 struct dh_server
 {
   struct packet_handler super;
@@ -49,18 +76,17 @@ struct dh_server
   
   struct ssh_service *finished;
 };
+#endif
 
 static int do_handle_dh_init(struct packet_handler *c,
 			     struct ssh_connection *connection,
 			     struct lsh_string *packet)
 {
-  struct dh_server *closure = (struct dh_server *) c;
+  CAST(dh_server, closure, c);
   struct hash_instance *hash;
   struct lsh_string *s;
   int res;
 
-  MDEBUG(closure);
-  
   verbose("handle_dh_init()\n");
   
   if (!dh_process_client_msg(&closure->dh, packet))
@@ -100,7 +126,7 @@ static int do_handle_dh_init(struct packet_handler *c,
   /* FIXME: Return value is ignored */
   (void) INSTALL_KEYS(closure->install, connection, hash);
 
-  lsh_object_free(hash);
+  KILL(hash);
 
   connection->kex_state = KEX_STATE_NEWKEYS;
   connection->dispatch[SSH_MSG_KEXDH_INIT] = connection->fail;
@@ -117,17 +143,14 @@ static int do_init_dh(struct keyexchange_algorithm *c,
 		      struct ssh_service *finished,
 		      int hostkey_algorithm_atom,
 		      struct signature_algorithm *ignored,
-		      void **algorithms)
+		      struct object_list *algorithms)
 {
-  struct dh_server_exchange *closure = (struct dh_server_exchange *) c;
-  struct dh_server *dh;
+  CAST(dh_server_exchange, closure, c);
+  NEW(dh_server, dh);
 
-  MDEBUG(closure);
-  MDEBUG(connection);
-  MDEBUG_SUBTYPE(finished);
-  MDEBUG_SUBTYPE(ignored);
-  
-  NEW(dh);
+  CHECK_TYPE(ssh_connection, connection);
+  CHECK_SUBTYPE(ssh_service, finished);
+  CHECK_SUBTYPE(signature_algorithm, ignored);
   
   /* FIXME: Use this value to choose a signer function */
   if (hostkey_algorithm_atom != ATOM_SSH_DSS)
@@ -164,9 +187,7 @@ make_dh_server(struct diffie_hellman_method *dh,
 	       struct lsh_string *server_key,
 	       struct signer *signer)
 {
-  struct dh_server_exchange *self;
-
-  NEW(self);
+  NEW(dh_server_exchange, self);
 
   self->super.init = do_init_dh;
   self->dh = dh;
@@ -176,11 +197,24 @@ make_dh_server(struct diffie_hellman_method *dh,
   return &self->super;
 }
 
+/* FIXME: This is identical to the client_install_keys structure in
+ * client_keyexchange.c. It should probably be moved somewhere else. */
+
+/* CLASS:
+   (class
+     (name server_install_keys)
+     (super install_keys)
+     (vars
+       (algorithms object object_list)))
+*/
+
+#if 0
 struct server_install_keys
 {
   struct install_keys super;
-  void **algorithms;
+  struct object_list *algorithms;
 };
+#endif
 
 static int do_install(struct install_keys *c,
 		      struct ssh_connection *connection,
@@ -190,10 +224,8 @@ static int do_install(struct install_keys *c,
    * happens to be weak. */
   /* FIXME: No IV:s */
 
-  struct server_install_keys *closure = (struct server_install_keys *) c;
+  CAST(server_install_keys, closure, c);
   
-  MDEBUG(closure);
-
   /* Keys for recieving */
   connection->dispatch[SSH_MSG_NEWKEYS] = make_newkeys_handler
     (kex_make_encrypt(secret, closure->algorithms,
@@ -215,11 +247,9 @@ static int do_install(struct install_keys *c,
   return 1;
 }
 
-struct install_keys *make_server_install_keys(void **algorithms)
+struct install_keys *make_server_install_keys(struct object_list *algorithms)
 {
-  struct server_install_keys *self;
-
-  NEW(self);
+  NEW(server_install_keys, self);
 
   self->super.install = do_install;
   self->algorithms = algorithms;
diff --git a/src/server_keyexchange.h b/src/server_keyexchange.h
index 5e06473d56b89b3383ea4e2766672ab52330847b..792112308e04364af823f504bfe567236553aa84 100644
--- a/src/server_keyexchange.h
+++ b/src/server_keyexchange.h
@@ -34,6 +34,6 @@ make_dh_server(struct diffie_hellman_method *dh,
 	       struct lsh_string *server_key,
 	       struct signer *signer);
 
-struct install_keys *make_server_install_keys(void **algorithms);
+struct install_keys *make_server_install_keys(struct object_list *algorithms);
 
 #endif /* LSH_SERVER_KEYEXCHANGE_H_INCLUDED */
diff --git a/src/server_password.c b/src/server_password.c
index d7e948ad2e78eba16ad969faf75aa400018a9398..4a2898104a946af1aff708d4c2680b12e58db722 100644
--- a/src/server_password.c
+++ b/src/server_password.c
@@ -36,25 +36,31 @@
 
 #include <pwd.h>
 #include <grp.h>
-    
+
+#include "server_password.c.x"
+
 /* NOTE: Calls functions using the *disgusting* convention of returning
  * pointers to static buffers. */
 struct unix_user *lookup_user(struct lsh_string *name, int free)
 {
   struct passwd *passwd;
-  struct unix_user *res;
+  NEW(unix_user, res);
 
   name = make_cstring(name, free);
 
   if (!name)
-    return 0;
+    {
+      KILL(res);
+      return 0;
+    }
   
   if (!(passwd = getpwnam(name->data)))
     {
       lsh_string_free(name);
+      KILL(res);
       return 0;
     }
-  NEW(res);
+
   res->uid = passwd->pw_uid;
   res->gid = passwd->pw_gid;
   res->name = name;
@@ -98,6 +104,17 @@ int verify_password(struct unix_user *user,
   return 1;
 }
 
+/* CLASS:
+   (class
+     (name unix_authentication)
+     (super userauth)
+     (vars
+       ;; (login object login_method)
+       ; Services allowed. Maps names to struct unix_service.
+       (services object alist)))
+*/
+     
+#if 0
 struct unix_authentication
 {
   struct userauth super;
@@ -108,6 +125,7 @@ struct unix_authentication
   /* Services allowed. Maps names to struct unix_service */
   struct alist *services; 
 };
+#endif
 
 static int do_authenticate(struct userauth *c,
 			   struct lsh_string *username,
@@ -115,13 +133,11 @@ static int do_authenticate(struct userauth *c,
 			   struct simple_buffer *args,
 			   struct ssh_service **result)
 {
-  struct unix_authentication *closure = (struct unix_authentication *) c;
+  CAST(unix_authentication, closure, c);
   struct lsh_string *password = NULL;
   struct unix_service *service;
   int change_passwd;
   
-  MDEBUG(closure);
-
   if (!( (service = ALIST_GET(closure->services, requested_service))))
     {
       lsh_string_free(username);
@@ -187,9 +203,8 @@ static int do_authenticate(struct userauth *c,
   
 struct userauth *make_unix_userauth(struct alist *services)
 {
-  struct unix_authentication *closure;
+  NEW(unix_authentication, closure);
 
-  NEW(closure);
   closure->super.authenticate = do_authenticate;
 #if 0
   closure->login = login;
@@ -250,6 +265,8 @@ int change_dir(struct unix_user *user)
   return 1;  
 }
 
+#if 0
+
 struct setuid_service
 {
   struct ssh_service super;
@@ -259,19 +276,15 @@ struct setuid_service
   struct ssh_service *service;
 };
 
-#if 0
-
 /* NOTE: This is used only if early forking (i.e., for directly after
  * user autentication) is enabled. */
 static int do_setuid(struct ssh_service *c,
 		     struct ssh_connection *connection)
 {
-  struct setuid_service *closure  = (struct setuid_service *) c;  
+  CAST(setuid_service, closure, c);  
   uid_t server_uid = getuid();
   int res = 0;
 
-  MDEBUG(closure);
-  
   if (server_uid != closure->user->uid)
     {
       if (server_uid)
diff --git a/src/server_userauth.c b/src/server_userauth.c
index 66e05f136151811f38b0f10ed3ce917a7ec024a6..92e3b4cf092f0df996ff3bd2632199da721f0cc1 100644
--- a/src/server_userauth.c
+++ b/src/server_userauth.c
@@ -11,9 +11,21 @@
 
 #include <assert.h>
 
+#include "server_userauth.c.x"
+
 /* FIXME: Supports only password authentication so far. There should
  * be some abstraction for handling several authentication methods. */
 
+/* CLASS:
+   (class
+     (name userauth_service)
+     (super ssh_service)
+     (vars
+       (advertised_methods object int_list)
+       (methods object alist)))
+*/
+
+#if 0
 struct userauth_service
 {
   struct ssh_service super;
@@ -23,6 +35,7 @@ struct userauth_service
 
   struct alist *methods; /* Maps authentication method names to methods */
 };
+#endif
 
 /* Max number of attempts */
 #define AUTH_ATTEMPTS 20
@@ -31,11 +44,26 @@ struct userauth_service
  * io.c could be used for timeouts, but it's not clear how the timeout
  * handler can close the right connection. */
 
+/* CLASS:
+   (class
+     (name userauth_handler)
+     (super packet_handler)
+     (vars
+       ; Attempts left 
+       (attempts simple int)
+
+       ; Methods advertised in failure messages
+       (advertised_methods object int_list)
+
+       (methods object alist)))
+*/
+
+#if 0
 struct userauth_handler
 {
   struct packet_handler super;
 
-  /* Attempts left */  
+  /* Attempts left */
   int attempts;
 
   /* Methods advertised in failure messages */
@@ -43,8 +71,10 @@ struct userauth_handler
   
   struct alist *methods;
 };
+#endif
 
-struct lsh_string *format_userauth_failure(int *methods, int partial)
+struct lsh_string *format_userauth_failure(struct int_list *methods,
+					   int partial)
 {
   return ssh_format("%c%A%c", SSH_MSG_USERAUTH_FAILURE, methods, partial);
 }
@@ -64,7 +94,7 @@ static int do_handle_userauth(struct packet_handler *c,
 			      struct ssh_connection *connection,
 			      struct lsh_string *packet)
 {
-  struct userauth_handler * closure = (struct userauth_handler *) c;
+  CAST(userauth_handler,  closure, c);
   struct simple_buffer buffer;
 
   int msg_number;
@@ -73,8 +103,6 @@ static int do_handle_userauth(struct packet_handler *c,
   int method;
   int res;
   
-  MDEBUG(closure);
-
   simple_buffer_init(&buffer, packet->length, packet->data);
 
   if (parse_uint8(&buffer, &msg_number)
@@ -133,12 +161,9 @@ static int do_handle_userauth(struct packet_handler *c,
 static int init_userauth(struct ssh_service *s, /* int name, */
 			 struct ssh_connection *c)
 {
-  struct userauth_service *self = (struct userauth_service *) s;
-  struct userauth_handler *auth;
+  CAST(userauth_service, self, s);
+  NEW(userauth_handler, auth);
   
-  MDEBUG(self);
-
-  NEW(auth);
   auth->super.handler = do_handle_userauth;
   auth->advertised_methods = self->advertised_methods;
   auth->methods = self->methods;
@@ -149,12 +174,10 @@ static int init_userauth(struct ssh_service *s, /* int name, */
   return 1;
 }
 
-struct ssh_service *make_userauth_service(int *advertised_methods,
+struct ssh_service *make_userauth_service(struct int_list *advertised_methods,
 					  struct alist *methods)
 {
-  struct userauth_service *self;
-
-  NEW(self);
+  NEW(userauth_service, self);
 
   self->super.init = init_userauth;
   self->advertised_methods = advertised_methods;
diff --git a/src/session.h b/src/session.h
index 1b97add53924e1e013dcee5e814c61ceebfae31f..0ac3a2a8f74ce0ef4cd0775f1bfca7cad2aa6f81 100644
--- a/src/session.h
+++ b/src/session.h
@@ -37,8 +37,6 @@
 struct ssh_session
 {
   struct channel super;
-
-  
 };
 
 struct lsh_string *format_session_open(UINT32 channel,
diff --git a/src/unpad.c b/src/unpad.c
index 0f770f904c1dcd989fe42a82e5a3bf15685e073c..ba46ecbcd05662b5df0dd788b8c48437d0c76d5b 100644
--- a/src/unpad.c
+++ b/src/unpad.c
@@ -31,14 +31,12 @@
 static int do_unpad(struct abstract_write *w,
 		    struct lsh_string *packet)
 {
-  struct abstract_write_pipe *closure = (struct abstract_write_pipe *) w;
+  CAST(abstract_write_pipe, closure, w);
   
   UINT8 padding_length;
   UINT32 payload_length;
   struct lsh_string *new;
   
-  MDEBUG(closure);
-
   if (packet->length < 1)
     return 0;
   
@@ -63,9 +61,7 @@ static int do_unpad(struct abstract_write *w,
 struct abstract_write *
 make_packet_unpad(struct abstract_write *continuation)
 {
-  struct abstract_write_pipe *closure;
-
-  NEW(closure);
+  NEW(abstract_write_pipe, closure);
 
   closure->super.write = do_unpad;
   closure->next = continuation;
diff --git a/src/userauth.c b/src/userauth.c
new file mode 100644
index 0000000000000000000000000000000000000000..f9632ea1e56b3b259a666daf121a4be0c73d79bd
--- /dev/null
+++ b/src/userauth.c
@@ -0,0 +1,29 @@
+/* userauth.h
+ *
+ */
+
+/* lsh, an implementation of the ssh protocol
+ *
+ * Copyright (C) 1998 Niels M�ller
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "userauth.h"
+
+#define CLASS_DEFINE
+#include "userauth.h.x"
+#undef CLASS_DEFINE
+
diff --git a/src/userauth.h b/src/userauth.h
index a9a0a1fa0c19fdaf15f424575d847e10f3614e78..43f76f1545f6ce6bd33cacf09ec106e64bf68304 100644
--- a/src/userauth.h
+++ b/src/userauth.h
@@ -24,14 +24,33 @@
 #ifndef LSH_USERAUTH_H_INCLUDED
 #define LSH_USERAUTH_H_INCLUDED
 
+#include "list.h"
 #include "parse.h"
 #include "service.h"
 
+#define CLASS_DECLARE
+#include "userauth.h.x"
+#undef CLASS_DECLARE
+
 /* Returns 0 if the request is somehow invalid. Otheerwise, returns 1,
  * and sets SERVICE non-NULL iff access is granted. */
 
 /* FIXME: Something more general is needed for authentication methods
  * which send additional messages. */
+
+/* CLASS:
+   (class
+     (name userauth)
+     (vars
+       (authenticate method int
+		     ; The name is consumed by this function
+		     "struct lsh_string *username"
+		     "int requested_service"
+		     "struct simple_buffer *args"
+		     "struct ssh_service **service")))
+*/
+       
+#if 0
 struct userauth
 {
   struct lsh_object header;
@@ -43,15 +62,17 @@ struct userauth
 		      struct simple_buffer *args,
 		      struct ssh_service **service);
 };
+#endif
 
 #define AUTHENTICATE(s, u, r, a, g) \
 ((s)->authenticate((s), (u), (r), (a), (g)))
 
-struct lsh_string *format_userauth_failure(int *methods, int partial);
+struct lsh_string *format_userauth_failure(struct int_list *methods,
+					   int partial);
 struct lsh_string *format_userauth_success(void);
 
 /* Server functions */     
-struct ssh_service *make_userauth_service(int *advertised_methods,
+struct ssh_service *make_userauth_service(struct int_list *advertised_methods,
 					  struct alist *methods);
 
 /* Client functions */
diff --git a/src/write_buffer.c b/src/write_buffer.c
index 7b2b89e01c81f7621b774054bc71bc7bbf5a10eb..78b5f2346b001d7e6cecdca436a738c962314bc2 100644
--- a/src/write_buffer.c
+++ b/src/write_buffer.c
@@ -29,14 +29,30 @@
 
 #include <assert.h>
 
+/* Prototype */
+static void do_free_buffer(struct buffer_node *n);
+
+#define CLASS_DEFINE
+#include "write_buffer.h.x"
+#undef CLASS_DEFINE
+
+static void do_free_buffer(struct buffer_node *n)
+{
+  while(n)
+    {
+      struct buffer_node *old = n;
+      lsh_string_free(n->packet);
+      n = n->next;
+      lsh_space_free(old);
+    }
+}
+
 static int do_write(struct abstract_write *w,
 		    struct lsh_string *packet)
 {
-  struct write_buffer *closure = (struct write_buffer *) w;
+  CAST(write_buffer, closure, w);
   struct buffer_node *new;
   
-  MDEBUG(closure);
-
   if (!packet->length)
     {
       lsh_string_free(packet);
@@ -163,9 +179,7 @@ void write_buffer_close(struct write_buffer *buffer)
 
 struct write_buffer *write_buffer_alloc(UINT32 size)
 {
-  struct write_buffer *res;
-
-  NEW(res);
+  NEW(write_buffer, res);
   
   res->super.write = do_write;
   
diff --git a/src/write_buffer.h b/src/write_buffer.h
index b73fe839ea85c9db32709e72390f7cfc96594ea4..8cd303c090ad94b91a169143da0ac407d1df6f4c 100644
--- a/src/write_buffer.h
+++ b/src/write_buffer.h
@@ -28,6 +28,10 @@
 
 #include "abstract_io.h"
 
+#define CLASS_DECLARE
+#include "write_buffer.h.x"
+#undef CLASS_DECLARE
+
 /* For the packet queue */
 /* NOTE: No object header */
 struct buffer_node
@@ -37,6 +41,33 @@ struct buffer_node
   struct lsh_string *packet;
 };
 
+/* CLASS:
+   (class
+     (name write_buffer)
+     (super abstract_write)
+     (vars
+       (block_size simple UINT32)
+       (buffer space UINT8)        ; Size is twice the blocksize 
+       (empty simple int)
+
+       ; If non-zero, don't accept any more data. The i/o-channel
+       ; should be closed once the current buffers are flushed. 
+       (closed simple int)
+
+       ;; (try_write simple int)
+
+       (head special "struct buffer_node *"
+                     #f do_free_buffer)
+       (tail simple "struct buffer_node *")
+
+       (pos simple UINT32)        ; Partial packet
+       (partial string)
+
+       (start simple UINT32)
+       (end simple UINT32)))
+*/
+
+#if 0
 struct write_buffer
 {
   struct abstract_write super;
@@ -62,6 +93,7 @@ struct write_buffer
   UINT32 start;
   UINT32 end;
 };
+#endif
 
 struct write_buffer *write_buffer_alloc(UINT32 size);
 int write_buffer_pre_write(struct write_buffer *buffer);
diff --git a/src/xalloc.c b/src/xalloc.c
index 34263ec48ada7d71604e59037ee8fcb4323e06f7..f7bf2cfa6ec6a88c60b89f1873d0df446202f386 100644
--- a/src/xalloc.c
+++ b/src/xalloc.c
@@ -25,9 +25,11 @@
 
 #include "xalloc.h"
 
+#include "list.h"
 #include "werror.h"
 
 #include <stdlib.h>
+#include <string.h>
 
 #ifdef DEBUG_ALLOC
 
@@ -93,6 +95,15 @@ static void *xalloc(size_t size)
   void *res = lsh_malloc(size);
   if (!res)
     fatal("Virtual memory exhausted");
+
+  /* FIXME: The gc can't handle uninitialized pointers. The simple way
+   * is to zero-fill all memory as it is allocated. But initialization
+   * is only necessary for objects, strings need no initialization. By
+   * moving initializing to some higher level, we could avoid
+   * unnecessary clearing, and also initialize mpz objects
+   * automatically. */
+  memset(res, 0, size);
+
   return res;
 }
 
@@ -128,11 +139,11 @@ struct lsh_object *lsh_object_alloc(struct lsh_class *class)
   return instance;
 }
 
-struct lsh_list *lsh_list_alloc(unsigned length)
+struct list_header *lsh_list_alloc(struct lsh_class *class,
+				   unsigned length, size_t element_size)
 {
-  struct lsh_class *class = &CLASS(lsh_list);
-  struct lsh_list *list = xalloc(class->size
-				 + sizeof(int) * (length - 1));
+  struct list_header *list = xalloc(class->size
+				    + element_size * (length - 1));
   list->super.isa = class;
   list->super.alloc_method = LSH_ALLOC_HEAP;
 
@@ -146,6 +157,9 @@ struct lsh_list *lsh_list_alloc(unsigned length)
 /* Should be called *only* by the gc */
 void lsh_object_free(struct lsh_object *o)
 {
+  if (!o)
+    return;
+  
   if (o->alloc_method != LSH_ALLOC_HEAP)
     fatal("lsh_object_free: Object not allocated on the heap!\n");
 
@@ -179,6 +193,9 @@ void lsh_object_free(void *p)
 struct lsh_object *lsh_object_check(struct lsh_class *class,
 				    struct lsh_object *instance)
 {
+  if (!instance)
+    return instance;
+  
   if (instance->marked)
     fatal("lsh_object_check: Unexpected marked object!\n");
 
@@ -196,6 +213,9 @@ struct lsh_object *lsh_object_check_subtype(struct lsh_class *class,
 {
   struct lsh_class *type;
   
+  if (!instance)
+    return instance;
+
   if (instance->marked)
     fatal("lsh_object_check: Unexpected marked object!\n");
 
@@ -222,7 +242,12 @@ void *lsh_space_alloc(size_t size)
 
 void lsh_space_free(void *p)
 {
-  int *m = ((int *) p) - 1;
+  int *m;
+  
+  if (!p)
+    return;
+  
+  m = ((int *) p) - 1;
 
   if (*m != -1919)
     fatal("lsh_free_space: Type error!\n");
diff --git a/src/xalloc.h b/src/xalloc.h
index 79dd89e07ae552d72e02a6c6919bb1e018d00582..90ec40078a70e0c3ad48b5a8d7e21c6641121b66 100644
--- a/src/xalloc.h
+++ b/src/xalloc.h
@@ -26,7 +26,7 @@
 #ifndef LSH_XALLOC_H_INCLUDED
 #define LSH_XALLOC_H_INCLUDED
 
-#include "list.h"
+#include "gc.h"
 
 #include <stdlib.h>
 
@@ -54,8 +54,6 @@ void lsh_object_free(struct lsh_object *o);
 void *lsh_space_alloc(size_t size);
 void lsh_space_free(void *p);
 
-struct lsh_list *lsh_list_alloc(unsigned length);
-
 #ifdef DEBUG_ALLOC
 
 struct lsh_object *lsh_object_check(struct lsh_class *class,
@@ -103,6 +101,6 @@ struct lsh_object *lsh_object_check_subtype(struct lsh_class *class,
 #define NEW_SPACE(x) ((x) = lsh_space_alloc(sizeof(*(x))))
 
 #include "gc.h"
-#define KILL(x) gc_kill((x))
+#define KILL(x) gc_kill((struct lsh_object *) (x))
 
 #endif /* LSH_XALLOC_H_INCLUDED */
diff --git a/src/zlib.c b/src/zlib.c
index 95bcb1f771b23647f2e77bd5321b83328254acf6..7c6389d0d5602e06429d8e076ec5feff4fee3298 100644
--- a/src/zlib.c
+++ b/src/zlib.c
@@ -27,15 +27,13 @@
 
 #error zlib.c not working at all
 
-static int do_deflate(struct abstract_write **c,
+static int do_deflate(struct abstract_write *w,
 		      struct lsh_string *packet)
 {
-  struct zlib_processor *closure = (struct zlib_processor *) *c;
+  CAST(zlib_processor, closure, w);
   
   struct lsh_string *new;
 
-  MDEBUG(closure);
-
   /* call deflate, copy into new packet */
 
   new = lsh_string_alloc(...);