From 642c0b00ab43079cd251ec9616963b8a806b3464 Mon Sep 17 00:00:00 2001
From: Nicholas Marriott <nicholas.marriott@gmail.com>
Date: Thu, 5 Jun 2008 16:35:32 +0000
Subject: [PATCH] Easy bits of arg printing for list-keys.

---
 CHANGES                 |   7 ++-
 cmd-attach-session.c    |  36 ++++++------
 cmd-bind-key.c          |  36 ++++++------
 cmd-copy-mode.c         |   9 +--
 cmd-detach-client.c     |  11 ++--
 cmd-generic.c           | 120 +++++++++++++++++++++++++++-------------
 cmd-has-session.c       |  11 ++--
 cmd-kill-server.c       |   7 ++-
 cmd-kill-session.c      |  11 ++--
 cmd-kill-window.c       |   9 +--
 cmd-last-window.c       |  11 ++--
 cmd-link-window.c       |  36 ++++++------
 cmd-list-clients.c      |   7 ++-
 cmd-list-keys.c         |  17 ++++--
 cmd-list-sessions.c     |   7 ++-
 cmd-list-windows.c      |  11 ++--
 cmd-new-session.c       |  46 +++++++--------
 cmd-new-window.c        |  46 +++++++--------
 cmd-next-window.c       |  11 ++--
 cmd-paste-buffer.c      |   9 +--
 cmd-previous-window.c   |  11 ++--
 cmd-refresh-client.c    |  11 ++--
 cmd-rename-session.c    |  36 ++++++------
 cmd-rename-window.c     |  36 ++++++------
 cmd-scroll-mode.c       |   9 +--
 cmd-select-window.c     |  17 +++---
 cmd-send-keys.c         |  36 ++++++------
 cmd-send-prefix.c       |   9 +--
 cmd-set-option.c        |  36 ++++++------
 cmd-set-window-option.c |  36 ++++++------
 cmd-start-server.c      |   7 ++-
 cmd-swap-window.c       |  36 ++++++------
 cmd-switch-client.c     |  36 ++++++------
 cmd-unbind-key.c        |  34 ++++++------
 cmd-unlink-window.c     |   9 +--
 cmd.c                   |  12 ++--
 key-bindings.c          |   4 +-
 tmux.c                  |   4 +-
 tmux.h                  |  55 +++++++++---------
 39 files changed, 485 insertions(+), 407 deletions(-)

diff --git a/CHANGES b/CHANGES
index 91e89982..49947563 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,8 @@
+05 June 2008
+
+* Infrastructure for printing arguments in list-keys output. Easy ones only for
+  now.
+
 04 June 2008
 
 * Add some vi(1) key bindings in copy mode, and support binding ^[, ^\, ^]
@@ -403,4 +408,4 @@
   (including mutt, emacs). No status bar yet and no key remapping or other
   customisation.
 
-$Id: CHANGES,v 1.109 2008-06-04 20:01:35 nicm Exp $
+$Id: CHANGES,v 1.110 2008-06-05 16:35:31 nicm Exp $
diff --git a/cmd-attach-session.c b/cmd-attach-session.c
index 3a456a24..d4d3367e 100644
--- a/cmd-attach-session.c
+++ b/cmd-attach-session.c
@@ -1,4 +1,4 @@
-/* $Id: cmd-attach-session.c,v 1.15 2008-06-03 16:55:09 nicm Exp $ */
+/* $Id: cmd-attach-session.c,v 1.16 2008-06-05 16:35:31 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -26,11 +26,11 @@
  * Attach existing session to the current terminal.
  */
 
-int	cmd_attach_session_parse(struct cmd *, void **, int, char **, char **);
-void	cmd_attach_session_exec(void *, struct cmd_ctx *);
-void	cmd_attach_session_send(void *, struct buffer *);
-void	cmd_attach_session_recv(void **, struct buffer *);
-void	cmd_attach_session_free(void *);
+int	cmd_attach_session_parse(struct cmd *, int, char **, char **);
+void	cmd_attach_session_exec(struct cmd *, struct cmd_ctx *);
+void	cmd_attach_session_send(struct cmd *, struct buffer *);
+void	cmd_attach_session_recv(struct cmd *, struct buffer *);
+void	cmd_attach_session_free(struct cmd *);
 
 struct cmd_attach_session_data {
 	char	*cname;
@@ -47,17 +47,17 @@ const struct cmd_entry cmd_attach_session_entry = {
 	cmd_attach_session_send,
 	cmd_attach_session_recv,
 	cmd_attach_session_free,
+	NULL,
 	NULL
 };
 
 int
-cmd_attach_session_parse(
-    struct cmd *self, void **ptr, int argc, char **argv, char **cause)
+cmd_attach_session_parse(struct cmd *self, int argc, char **argv, char **cause)
 {
 	struct cmd_attach_session_data	*data;
 	int				 opt;
 
-	*ptr = data = xmalloc(sizeof *data);
+	self->data = data = xmalloc(sizeof *data);
 	data->cname = NULL;
 	data->sname = NULL;
 	data->flag_detach = 0;
@@ -93,14 +93,14 @@ cmd_attach_session_parse(
 usage:
 	xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
 
-	cmd_attach_session_free(data);
+	self->entry->free(self);
 	return (-1);
 }
 
 void
-cmd_attach_session_exec(void *ptr, struct cmd_ctx *ctx)
+cmd_attach_session_exec(struct cmd *self, struct cmd_ctx *ctx)
 {
-	struct cmd_attach_session_data	*data = ptr;
+	struct cmd_attach_session_data	*data = self->data;
 	struct session			*s;
 	char				*cause;
 
@@ -131,9 +131,9 @@ cmd_attach_session_exec(void *ptr, struct cmd_ctx *ctx)
 }
 
 void
-cmd_attach_session_send(void *ptr, struct buffer *b)
+cmd_attach_session_send(struct cmd *self, struct buffer *b)
 {
-	struct cmd_attach_session_data	*data = ptr;
+	struct cmd_attach_session_data	*data = self->data;
 
 	buffer_write(b, data, sizeof *data);
 	cmd_send_string(b, data->cname);
@@ -141,20 +141,20 @@ cmd_attach_session_send(void *ptr, struct buffer *b)
 }
 
 void
-cmd_attach_session_recv(void **ptr, struct buffer *b)
+cmd_attach_session_recv(struct cmd *self, struct buffer *b)
 {
 	struct cmd_attach_session_data	*data;
 
-	*ptr = data = xmalloc(sizeof *data);
+	self->data = data = xmalloc(sizeof *data);
 	buffer_read(b, data, sizeof *data);
 	data->cname = cmd_recv_string(b);
 	data->sname = cmd_recv_string(b);
 }
 
 void
-cmd_attach_session_free(void *ptr)
+cmd_attach_session_free(struct cmd *self)
 {
-	struct cmd_attach_session_data	*data = ptr;
+	struct cmd_attach_session_data	*data = self->data;
 
 	if (data->cname != NULL)
 		xfree(data->cname);
diff --git a/cmd-bind-key.c b/cmd-bind-key.c
index f02c440b..03d38744 100644
--- a/cmd-bind-key.c
+++ b/cmd-bind-key.c
@@ -1,4 +1,4 @@
-/* $Id: cmd-bind-key.c,v 1.12 2008-06-03 05:35:50 nicm Exp $ */
+/* $Id: cmd-bind-key.c,v 1.13 2008-06-05 16:35:31 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -26,11 +26,11 @@
  * Bind a key to a command, this recurses through cmd_*.
  */
 
-int	cmd_bind_key_parse(struct cmd *, void **, int, char **, char **);
-void	cmd_bind_key_exec(void *, struct cmd_ctx *);
-void	cmd_bind_key_send(void *, struct buffer *);
-void	cmd_bind_key_recv(void **, struct buffer *);
-void	cmd_bind_key_free(void *);
+int	cmd_bind_key_parse(struct cmd *, int, char **, char **);
+void	cmd_bind_key_exec(struct cmd *, struct cmd_ctx *);
+void	cmd_bind_key_send(struct cmd *, struct buffer *);
+void	cmd_bind_key_recv(struct cmd *, struct buffer *);
+void	cmd_bind_key_free(struct cmd *);
 
 struct cmd_bind_key_data {
 	int		 key;
@@ -46,17 +46,17 @@ const struct cmd_entry cmd_bind_key_entry = {
 	cmd_bind_key_send,
 	cmd_bind_key_recv,
 	cmd_bind_key_free,
+	NULL,
 	NULL
 };
 
 int
-cmd_bind_key_parse(
-    struct cmd *self, void **ptr, int argc, char **argv, char **cause)
+cmd_bind_key_parse(struct cmd *self, int argc, char **argv, char **cause)
 {
 	struct cmd_bind_key_data	*data;
 	int				 opt;
 
-	*ptr = data = xmalloc(sizeof *data);
+	self->data = data = xmalloc(sizeof *data);
 	data->cmd = NULL;
 
 	while ((opt = getopt(argc, argv, "")) != EOF) {
@@ -86,14 +86,14 @@ usage:
 	xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
 
 error:
-	cmd_bind_key_free(data);
+	self->entry->free(self);
 	return (-1);
 }
 
 void
-cmd_bind_key_exec(void *ptr, struct cmd_ctx *ctx)
+cmd_bind_key_exec(struct cmd *self, struct cmd_ctx *ctx)
 {
-	struct cmd_bind_key_data	*data = ptr;
+	struct cmd_bind_key_data	*data = self->data;
 
 	if (data == NULL)
 		return;
@@ -106,28 +106,28 @@ cmd_bind_key_exec(void *ptr, struct cmd_ctx *ctx)
 }
 
 void
-cmd_bind_key_send(void *ptr, struct buffer *b)
+cmd_bind_key_send(struct cmd *self, struct buffer *b)
 {
-	struct cmd_bind_key_data	*data = ptr;
+	struct cmd_bind_key_data	*data = self->data;
 
 	buffer_write(b, data, sizeof *data);
 	cmd_send(data->cmd, b);
 }
 
 void
-cmd_bind_key_recv(void **ptr, struct buffer *b)
+cmd_bind_key_recv(struct cmd *self, struct buffer *b)
 {
 	struct cmd_bind_key_data	*data;
 
-	*ptr = data = xmalloc(sizeof *data);
+	self->data = data = xmalloc(sizeof *data);
 	buffer_read(b, data, sizeof *data);
 	data->cmd = cmd_recv(b);
 }
 
 void
-cmd_bind_key_free(void *ptr)
+cmd_bind_key_free(struct cmd *self)
 {
-	struct cmd_bind_key_data	*data = ptr;
+	struct cmd_bind_key_data	*data = self->data;
 
 	if (data->cmd != NULL)
 		cmd_free(data->cmd);
diff --git a/cmd-copy-mode.c b/cmd-copy-mode.c
index 88123043..37bb4a2f 100644
--- a/cmd-copy-mode.c
+++ b/cmd-copy-mode.c
@@ -1,4 +1,4 @@
-/* $Id: cmd-copy-mode.c,v 1.8 2008-06-03 05:35:50 nicm Exp $ */
+/* $Id: cmd-copy-mode.c,v 1.9 2008-06-05 16:35:31 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -24,7 +24,7 @@
  * Enter copy mode. Only valid when bound to a key.
  */
 
-void	cmd_copy_mode_exec(void *, struct cmd_ctx *);
+void	cmd_copy_mode_exec(struct cmd *, struct cmd_ctx *);
 
 const struct cmd_entry cmd_copy_mode_entry = {
 	"copy-mode", NULL, 
@@ -35,15 +35,16 @@ const struct cmd_entry cmd_copy_mode_entry = {
 	cmd_windowonly_send,
 	cmd_windowonly_recv,
 	cmd_windowonly_free,
+	NULL,
 	NULL
 };
 
 void
-cmd_copy_mode_exec(void *ptr, struct cmd_ctx *ctx)
+cmd_copy_mode_exec(struct cmd *self, struct cmd_ctx *ctx)
 {
 	struct winlink	*wl;
 
-	if ((wl = cmd_windowonly_get(ptr, ctx, NULL)) == NULL)
+	if ((wl = cmd_windowonly_get(self, ctx, NULL)) == NULL)
 		return;
 
 	window_set_mode(wl->window, &window_copy_mode);
diff --git a/cmd-detach-client.c b/cmd-detach-client.c
index 934f948d..04ee1831 100644
--- a/cmd-detach-client.c
+++ b/cmd-detach-client.c
@@ -1,4 +1,4 @@
-/* $Id: cmd-detach-client.c,v 1.4 2008-06-03 05:35:50 nicm Exp $ */
+/* $Id: cmd-detach-client.c,v 1.5 2008-06-05 16:35:31 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -24,7 +24,7 @@
  * Detach a client.
  */
 
-void	cmd_detach_client_exec(void *, struct cmd_ctx *);
+void	cmd_detach_client_exec(struct cmd *, struct cmd_ctx *);
 
 const struct cmd_entry cmd_detach_client_entry = {
 	"detach-client", "detach",
@@ -35,15 +35,16 @@ const struct cmd_entry cmd_detach_client_entry = {
 	cmd_clientonly_send,
 	cmd_clientonly_recv,
 	cmd_clientonly_free,
-	NULL
+	NULL,
+	cmd_clientonly_print
 };
 
 void
-cmd_detach_client_exec(void *ptr, struct cmd_ctx *ctx)
+cmd_detach_client_exec(struct cmd *self, struct cmd_ctx *ctx)
 {
 	struct client	*c;
 
-	if ((c = cmd_clientonly_get(ptr, ctx)) == NULL)
+	if ((c = cmd_clientonly_get(self, ctx)) == NULL)
 		return;
 
 	server_write_client(c, MSG_DETACH, NULL, 0);
diff --git a/cmd-generic.c b/cmd-generic.c
index a5dad562..b045a7ee 100644
--- a/cmd-generic.c
+++ b/cmd-generic.c
@@ -1,4 +1,4 @@
-/* $Id: cmd-generic.c,v 1.5 2008-06-04 16:11:52 nicm Exp $ */
+/* $Id: cmd-generic.c,v 1.6 2008-06-05 16:35:31 nicm Exp $ */
 
 /*
  * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -24,13 +24,12 @@
 #include "tmux.h"
 
 int
-cmd_clientonly_parse(
-    struct cmd *self, void **ptr, int argc, char **argv, char **cause)
+cmd_clientonly_parse(struct cmd *self, int argc, char **argv, char **cause)
 {
 	struct cmd_clientonly_data	*data;
 	int				 opt;
 
-	*ptr = data = xmalloc(sizeof *data);
+	self->data = data = xmalloc(sizeof *data);
 	data->cname = NULL;
 
 	while ((opt = getopt(argc, argv, "c:")) != EOF) {
@@ -53,33 +52,33 @@ cmd_clientonly_parse(
 usage:
 	xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
 
-	self->entry->free(data);
+	self->entry->free(self);
 	return (-1);
 }
 
 void
-cmd_clientonly_send(void *ptr, struct buffer *b)
+cmd_clientonly_send(struct cmd *self, struct buffer *b)
 {
-	struct cmd_clientonly_data	*data = ptr;
+	struct cmd_clientonly_data	*data = self->data;
 
 	buffer_write(b, data, sizeof *data);
 	cmd_send_string(b, data->cname);
 }
 
 void
-cmd_clientonly_recv(void **ptr, struct buffer *b)
+cmd_clientonly_recv(struct cmd *self, struct buffer *b)
 {
 	struct cmd_clientonly_data	*data;
 
-	*ptr = data = xmalloc(sizeof *data);
+	self->data = data = xmalloc(sizeof *data);
 	buffer_read(b, data, sizeof *data);
 	data->cname = cmd_recv_string(b);
 }
 
 void
-cmd_clientonly_free(void *ptr)
+cmd_clientonly_free(struct cmd *self)
 {
-	struct cmd_clientonly_data	*data = ptr;
+	struct cmd_clientonly_data	*data = self->data;
 
 	if (data->cname != NULL)
 		xfree(data->cname);
@@ -87,23 +86,35 @@ cmd_clientonly_free(void *ptr)
 }
 
 struct client *
-cmd_clientonly_get(void *ptr, struct cmd_ctx *ctx)
+cmd_clientonly_get(struct cmd *self, struct cmd_ctx *ctx)
 {
-	struct cmd_clientonly_data	*data = ptr;
+	struct cmd_clientonly_data	*data = self->data;
 
   	if (data != NULL)
 		return (cmd_find_client(ctx, data->cname));
 	return (cmd_find_client(ctx, NULL));
 }
 
+void
+cmd_clientonly_print(struct cmd *self, char *buf, size_t len)
+{
+	struct cmd_clientonly_data	*data = self->data;
+	size_t				 off = 0;
+	
+	off += xsnprintf(buf, len, "%s ", self->entry->name);
+	if (data == NULL)
+		return;
+	if (off < len && data->cname != NULL)
+		off += xsnprintf(buf + off, len - off, "-c %s ", data->cname);
+}
+
 int
-cmd_sessiononly_parse(
-    struct cmd *self, void **ptr, int argc, char **argv, char **cause)
+cmd_sessiononly_parse(struct cmd *self, int argc, char **argv, char **cause)
 {
 	struct cmd_sessiononly_data	*data;
 	int				 opt;
-
-	*ptr = data = xmalloc(sizeof *data);
+	
+	self->data = data = xmalloc(sizeof *data);
 	data->cname = NULL;
 	data->sname = NULL;
 
@@ -135,14 +146,14 @@ cmd_sessiononly_parse(
 usage:
 	xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
 
-	self->entry->free(data);
+	self->entry->free(self);
 	return (-1);
 }
 
 void
-cmd_sessiononly_send(void *ptr, struct buffer *b)
+cmd_sessiononly_send(struct cmd *self, struct buffer *b)
 {
-	struct cmd_sessiononly_data	*data = ptr;
+	struct cmd_sessiononly_data	*data = self->data;
 
 	buffer_write(b, data, sizeof *data);
 	cmd_send_string(b, data->cname);
@@ -150,20 +161,20 @@ cmd_sessiononly_send(void *ptr, struct buffer *b)
 }
 
 void
-cmd_sessiononly_recv(void **ptr, struct buffer *b)
+cmd_sessiononly_recv(struct cmd *self, struct buffer *b)
 {
 	struct cmd_sessiononly_data	*data;
 
-	*ptr = data = xmalloc(sizeof *data);
+	self->data = data = xmalloc(sizeof *data);
 	buffer_read(b, data, sizeof *data);
 	data->cname = cmd_recv_string(b);
 	data->sname = cmd_recv_string(b);
 }
 
 void
-cmd_sessiononly_free(void *ptr)
+cmd_sessiononly_free(struct cmd *self)
 {
-	struct cmd_sessiononly_data	*data = ptr;
+	struct cmd_sessiononly_data	*data = self->data;
 
 	if (data->cname != NULL)
 		xfree(data->cname);
@@ -173,24 +184,38 @@ cmd_sessiononly_free(void *ptr)
 }
 
 struct session *
-cmd_sessiononly_get(void *ptr, struct cmd_ctx *ctx)
+cmd_sessiononly_get(struct cmd *self, struct cmd_ctx *ctx)
 {
-	struct cmd_sessiononly_data	*data = ptr;
+	struct cmd_sessiononly_data	*data = self->data;
 
   	if (data != NULL)
 		return (cmd_find_session(ctx, data->cname, data->sname));
 	return (cmd_find_session(ctx, NULL, NULL));
 }
 
+void
+cmd_sessiononly_print(struct cmd *self, char *buf, size_t len)
+{
+	struct cmd_sessiononly_data	*data = self->data;
+	size_t				 off = 0;
+	
+	off += xsnprintf(buf, len, "%s ", self->entry->name);
+	if (data == NULL)
+		return;
+	if (off < len && data->cname != NULL)
+		off += xsnprintf(buf + off, len - off, "-c %s ", data->cname);
+	if (off < len && data->sname != NULL)
+		off += xsnprintf(buf + off, len - off, "-s %s ", data->sname);
+}
+
 int
-cmd_windowonly_parse(
-    struct cmd *self, void **ptr, int argc, char **argv, char **cause)
+cmd_windowonly_parse(struct cmd *self, int argc, char **argv, char **cause)
 {
 	struct cmd_windowonly_data	*data;
 	int				 opt;
 	const char			*errstr;
 
-	*ptr = data = xmalloc(sizeof *data);
+	self->data = data = xmalloc(sizeof *data);
 	data->cname = NULL;
 	data->sname = NULL;
 	data->idx = -1;
@@ -231,14 +256,14 @@ usage:
 	xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
 
 error:
-	self->entry->free(data);
+	self->entry->free(self);
 	return (-1);
 }
 
 void
-cmd_windowonly_send(void *ptr, struct buffer *b)
+cmd_windowonly_send(struct cmd *self, struct buffer *b)
 {
-	struct cmd_windowonly_data	*data = ptr;
+	struct cmd_windowonly_data	*data = self->data;
 
 	buffer_write(b, data, sizeof *data);
 	cmd_send_string(b, data->cname);
@@ -246,20 +271,20 @@ cmd_windowonly_send(void *ptr, struct buffer *b)
 }
 
 void
-cmd_windowonly_recv(void **ptr, struct buffer *b)
+cmd_windowonly_recv(struct cmd *self, struct buffer *b)
 {
 	struct cmd_windowonly_data	*data;
 
-	*ptr = data = xmalloc(sizeof *data);
+	self->data = data = xmalloc(sizeof *data);
 	buffer_read(b, data, sizeof *data);
 	data->cname = cmd_recv_string(b);
 	data->sname = cmd_recv_string(b);
 }
 
 void
-cmd_windowonly_free(void *ptr)
+cmd_windowonly_free(struct cmd *self)
 {
-	struct cmd_windowonly_data	*data = ptr;
+	struct cmd_windowonly_data	*data = self->data;
 
 	if (data->cname != NULL)
 		xfree(data->cname);
@@ -269,15 +294,32 @@ cmd_windowonly_free(void *ptr)
 }
 
 struct winlink *
-cmd_windowonly_get(void *ptr, struct cmd_ctx *ctx, struct session **sp)
+cmd_windowonly_get(struct cmd *self, struct cmd_ctx *ctx, struct session **sp)
 {
-	struct cmd_windowonly_data	*data = ptr;
+	struct cmd_windowonly_data	*data = self->data;
 	struct winlink			*wl;
 
   	if (data == NULL) {
 		wl = cmd_find_window(ctx, NULL, NULL, -1, sp);
 		return (wl);
 	}
-		
+	
 	return (cmd_find_window(ctx, data->cname, data->sname, data->idx, sp));
 }
+
+void
+cmd_windowonly_print(struct cmd *self, char *buf, size_t len)
+{
+	struct cmd_windowonly_data	*data = self->data;
+	size_t				 off = 0;
+	
+	off += xsnprintf(buf, len, "%s ", self->entry->name);
+	if (data == NULL)
+		return;
+	if (off < len && data->cname != NULL)
+		off += xsnprintf(buf + off, len - off, "-c %s ", data->cname);
+	if (off < len && data->sname != NULL)
+		off += xsnprintf(buf + off, len - off, "-s %s ", data->sname);
+	if (off < len && data->idx != -1)
+		off += xsnprintf(buf + off, len - off, "-i %d ", data->idx);
+}
diff --git a/cmd-has-session.c b/cmd-has-session.c
index fade7de7..df4951b4 100644
--- a/cmd-has-session.c
+++ b/cmd-has-session.c
@@ -1,4 +1,4 @@
-/* $Id: cmd-has-session.c,v 1.7 2008-06-03 05:35:50 nicm Exp $ */
+/* $Id: cmd-has-session.c,v 1.8 2008-06-05 16:35:31 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -24,7 +24,7 @@
  * Cause client to report an error and exit with 1 if session doesn't exist.
  */
 
-void	cmd_has_session_exec(void *, struct cmd_ctx *);
+void	cmd_has_session_exec(struct cmd *, struct cmd_ctx *);
 
 const struct cmd_entry cmd_has_session_entry = {
 	"has-session", "has",
@@ -35,15 +35,16 @@ const struct cmd_entry cmd_has_session_entry = {
 	cmd_sessiononly_send,
 	cmd_sessiononly_recv,
 	cmd_sessiononly_free,
-	NULL
+	NULL,
+	cmd_sessiononly_print
 };
 
 void
-cmd_has_session_exec(void *ptr, struct cmd_ctx *ctx)
+cmd_has_session_exec(struct cmd *self, struct cmd_ctx *ctx)
 {
 	struct session	*s;
 
-	if ((s = cmd_sessiononly_get(ptr, ctx)) == NULL)
+	if ((s = cmd_sessiononly_get(self, ctx)) == NULL)
 		return;
 
 	if (ctx->cmdclient != NULL)
diff --git a/cmd-kill-server.c b/cmd-kill-server.c
index c4b3f7a6..a4d7c27c 100644
--- a/cmd-kill-server.c
+++ b/cmd-kill-server.c
@@ -1,4 +1,4 @@
-/* $Id: cmd-kill-server.c,v 1.3 2008-06-03 18:13:54 nicm Exp $ */
+/* $Id: cmd-kill-server.c,v 1.4 2008-06-05 16:35:31 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -27,7 +27,7 @@
  * Kill the server and do nothing else.
  */
 
-void	cmd_kill_server_exec(void *, struct cmd_ctx *);
+void	cmd_kill_server_exec(struct cmd *, struct cmd_ctx *);
 
 const struct cmd_entry cmd_kill_server_entry = {
 	"kill-server", NULL,
@@ -38,11 +38,12 @@ const struct cmd_entry cmd_kill_server_entry = {
 	NULL,
 	NULL,
 	NULL,
+	NULL,
 	NULL
 };
 
 void
-cmd_kill_server_exec(unused void *ptr, struct cmd_ctx *ctx)
+cmd_kill_server_exec(unused struct cmd *self, struct cmd_ctx *ctx)
 {
 	sigterm = 1;
 
diff --git a/cmd-kill-session.c b/cmd-kill-session.c
index abca8ca1..1a4fbaa0 100644
--- a/cmd-kill-session.c
+++ b/cmd-kill-session.c
@@ -1,4 +1,4 @@
-/* $Id: cmd-kill-session.c,v 1.8 2008-06-03 05:35:51 nicm Exp $ */
+/* $Id: cmd-kill-session.c,v 1.9 2008-06-05 16:35:31 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -27,7 +27,7 @@
  * Note this deliberately has no alias to make it hard to hit by accident.
  */
 
-void	cmd_kill_session_exec(void *, struct cmd_ctx *);
+void	cmd_kill_session_exec(struct cmd *, struct cmd_ctx *);
 
 const struct cmd_entry cmd_kill_session_entry = {
 	"kill-session", NULL,
@@ -38,17 +38,18 @@ const struct cmd_entry cmd_kill_session_entry = {
 	cmd_sessiononly_send,
 	cmd_sessiononly_recv,
 	cmd_sessiononly_free,
-	NULL
+	NULL,
+	cmd_sessiononly_print
 };
 
 void
-cmd_kill_session_exec(void *ptr, struct cmd_ctx *ctx)
+cmd_kill_session_exec(struct cmd *self, struct cmd_ctx *ctx)
 {
 	struct session	*s;
 	struct client	*c;
 	u_int		 i;
 
-	if ((s = cmd_sessiononly_get(ptr, ctx)) == NULL)
+	if ((s = cmd_sessiononly_get(self, ctx)) == NULL)
 		return;
 
 	for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
diff --git a/cmd-kill-window.c b/cmd-kill-window.c
index 6fd3de3a..2d34217d 100644
--- a/cmd-kill-window.c
+++ b/cmd-kill-window.c
@@ -1,4 +1,4 @@
-/* $Id: cmd-kill-window.c,v 1.11 2008-06-03 05:35:51 nicm Exp $ */
+/* $Id: cmd-kill-window.c,v 1.12 2008-06-05 16:35:31 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -24,7 +24,7 @@
  * Destroy window.
  */
 
-void	cmd_kill_window_exec(void *, struct cmd_ctx *);
+void	cmd_kill_window_exec(struct cmd *, struct cmd_ctx *);
 
 const struct cmd_entry cmd_kill_window_entry = {
 	"kill-window", "killw",
@@ -35,11 +35,12 @@ const struct cmd_entry cmd_kill_window_entry = {
 	cmd_windowonly_send,
 	cmd_windowonly_recv,
 	cmd_windowonly_free,
+	NULL,
 	NULL
 };
 
 void
-cmd_kill_window_exec(void *ptr, struct cmd_ctx *ctx)
+cmd_kill_window_exec(struct cmd *self, struct cmd_ctx *ctx)
 {
 	struct winlink	*wl;
 	struct session	*s;
@@ -47,7 +48,7 @@ cmd_kill_window_exec(void *ptr, struct cmd_ctx *ctx)
 	u_int		 i;
 	int		 destroyed;
 
-	if ((wl = cmd_windowonly_get(ptr, ctx, &s)) == NULL)
+	if ((wl = cmd_windowonly_get(self, ctx, &s)) == NULL)
 		return;
 
  	destroyed = session_detach(s, wl);
diff --git a/cmd-last-window.c b/cmd-last-window.c
index 8d55a23c..a9deef03 100644
--- a/cmd-last-window.c
+++ b/cmd-last-window.c
@@ -1,4 +1,4 @@
-/* $Id: cmd-last-window.c,v 1.9 2008-06-03 05:35:51 nicm Exp $ */
+/* $Id: cmd-last-window.c,v 1.10 2008-06-05 16:35:31 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -24,7 +24,7 @@
  * Move to last window.
  */
 
-void	cmd_last_window_exec(void *, struct cmd_ctx *);
+void	cmd_last_window_exec(struct cmd *, struct cmd_ctx *);
 
 const struct cmd_entry cmd_last_window_entry = {
 	"last-window", "last", 
@@ -35,15 +35,16 @@ const struct cmd_entry cmd_last_window_entry = {
 	cmd_sessiononly_send,
 	cmd_sessiononly_recv,
 	cmd_sessiononly_free,
-	NULL
+	NULL,
+	cmd_sessiononly_print
 };
 
 void
-cmd_last_window_exec(void *ptr, struct cmd_ctx *ctx)
+cmd_last_window_exec(struct cmd *self, struct cmd_ctx *ctx)
 {
 	struct session	*s;
 
-	if ((s = cmd_sessiononly_get(ptr, ctx)) == NULL)
+	if ((s = cmd_sessiononly_get(self, ctx)) == NULL)
 		return;
 
 	if (session_last(s) == 0)
diff --git a/cmd-link-window.c b/cmd-link-window.c
index e43c9ad9..9888d389 100644
--- a/cmd-link-window.c
+++ b/cmd-link-window.c
@@ -1,4 +1,4 @@
-/* $Id: cmd-link-window.c,v 1.16 2008-06-04 16:46:23 nicm Exp $ */
+/* $Id: cmd-link-window.c,v 1.17 2008-06-05 16:35:31 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -27,11 +27,11 @@
  * Link a window into another session.
  */
 
-int	cmd_link_window_parse(struct cmd *, void **, int, char **, char **);
-void	cmd_link_window_exec(void *, struct cmd_ctx *);
-void	cmd_link_window_send(void *, struct buffer *);
-void	cmd_link_window_recv(void **, struct buffer *);
-void	cmd_link_window_free(void *);
+int	cmd_link_window_parse(struct cmd *, int, char **, char **);
+void	cmd_link_window_exec(struct cmd *, struct cmd_ctx *);
+void	cmd_link_window_send(struct cmd *, struct buffer *);
+void	cmd_link_window_recv(struct cmd *, struct buffer *);
+void	cmd_link_window_free(struct cmd *);
 
 struct cmd_link_window_data {
 	char	*cname;
@@ -52,18 +52,18 @@ const struct cmd_entry cmd_link_window_entry = {
 	cmd_link_window_send,
 	cmd_link_window_recv,
 	cmd_link_window_free,
+	NULL,
 	NULL
 };
 
 int
-cmd_link_window_parse(
-    struct cmd *self, void **ptr, int argc, char **argv, char **cause)
+cmd_link_window_parse(struct cmd *self, int argc, char **argv, char **cause)
 {
 	struct cmd_link_window_data	*data;
 	const char			*errstr;
 	int				 opt;
 
-	*ptr = data = xmalloc(sizeof *data);
+	self->data = data = xmalloc(sizeof *data);
 	data->cname = NULL;
 	data->sname = NULL;
 	data->flag_detached = 0;
@@ -121,14 +121,14 @@ usage:
 	xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
 
 error:
-	cmd_link_window_free(data);
+	self->entry->free(self);
 	return (-1);
 }
 
 void
-cmd_link_window_exec(void *ptr, struct cmd_ctx *ctx)
+cmd_link_window_exec(struct cmd *self, struct cmd_ctx *ctx)
 {
-	struct cmd_link_window_data	*data = ptr;
+	struct cmd_link_window_data	*data = self->data;
 	struct session			*s, *src;
 	struct winlink			*wl, *wl2;
 
@@ -202,9 +202,9 @@ cmd_link_window_exec(void *ptr, struct cmd_ctx *ctx)
 }
 
 void
-cmd_link_window_send(void *ptr, struct buffer *b)
+cmd_link_window_send(struct cmd *self, struct buffer *b)
 {
-	struct cmd_link_window_data	*data = ptr;
+	struct cmd_link_window_data	*data = self->data;
 
 	buffer_write(b, data, sizeof *data);
 	cmd_send_string(b, data->cname);
@@ -213,11 +213,11 @@ cmd_link_window_send(void *ptr, struct buffer *b)
 }
 
 void
-cmd_link_window_recv(void **ptr, struct buffer *b)
+cmd_link_window_recv(struct cmd *self, struct buffer *b)
 {
 	struct cmd_link_window_data	*data;
 
-	*ptr = data = xmalloc(sizeof *data);
+	self->data = data = xmalloc(sizeof *data);
 	buffer_read(b, data, sizeof *data);
 	data->cname = cmd_recv_string(b);
 	data->sname = cmd_recv_string(b);
@@ -225,9 +225,9 @@ cmd_link_window_recv(void **ptr, struct buffer *b)
 }
 
 void
-cmd_link_window_free(void *ptr)
+cmd_link_window_free(struct cmd *self)
 {
-	struct cmd_link_window_data	*data = ptr;
+	struct cmd_link_window_data	*data = self->data;
 
 	if (data->cname != NULL)
 		xfree(data->cname);
diff --git a/cmd-list-clients.c b/cmd-list-clients.c
index 2abf436e..c25d53e2 100644
--- a/cmd-list-clients.c
+++ b/cmd-list-clients.c
@@ -1,4 +1,4 @@
-/* $Id: cmd-list-clients.c,v 1.6 2008-06-03 05:35:51 nicm Exp $ */
+/* $Id: cmd-list-clients.c,v 1.7 2008-06-05 16:35:31 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -27,7 +27,7 @@
  * List all clients.
  */
 
-void	cmd_list_clients_exec(void *, struct cmd_ctx *);
+void	cmd_list_clients_exec(struct cmd *, struct cmd_ctx *);
 
 const struct cmd_entry cmd_list_clients_entry = {
 	"list-clients", "lsc",
@@ -38,11 +38,12 @@ const struct cmd_entry cmd_list_clients_entry = {
 	NULL,
 	NULL,
 	NULL,
+	NULL,
 	NULL
 };
 
 void
-cmd_list_clients_exec(unused void *ptr, struct cmd_ctx *ctx)
+cmd_list_clients_exec(unused struct cmd *self, struct cmd_ctx *ctx)
 {
 	struct client	*c;
 	u_int		 i;
diff --git a/cmd-list-keys.c b/cmd-list-keys.c
index d31c4ef8..def2fb6f 100644
--- a/cmd-list-keys.c
+++ b/cmd-list-keys.c
@@ -1,4 +1,4 @@
-/* $Id: cmd-list-keys.c,v 1.8 2008-06-03 05:35:51 nicm Exp $ */
+/* $Id: cmd-list-keys.c,v 1.9 2008-06-05 16:35:31 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -24,7 +24,7 @@
  * List key bindings.
  */
 
-void	cmd_list_keys_exec(void *, struct cmd_ctx *);
+void	cmd_list_keys_exec(struct cmd *, struct cmd_ctx *);
 
 const struct cmd_entry cmd_list_keys_entry = {
 	"list-keys", "lsk",
@@ -35,21 +35,28 @@ const struct cmd_entry cmd_list_keys_entry = {
 	NULL,
 	NULL,
 	NULL,
-	NULL
+	NULL,
+	NULL,
 };
 
 void
-cmd_list_keys_exec(unused void *ptr, struct cmd_ctx *ctx)
+cmd_list_keys_exec(unused struct cmd *self, struct cmd_ctx *ctx)
 {
 	struct binding	*bd;
 	const char	*key;
+	char		 s[BUFSIZ];
 	u_int		 i;
 
 	for (i = 0; i < ARRAY_LENGTH(&key_bindings); i++) {
 		bd = ARRAY_ITEM(&key_bindings, i);
 		if ((key = key_string_lookup_key(bd->key)) == NULL)
 			continue;
-		ctx->print(ctx, "%11s: %s", key, bd->cmd->entry->name);
+		if (bd->cmd->entry->print == NULL) {
+			ctx->print(ctx, "%11s: %s", key, bd->cmd->entry->name);
+			continue;
+		}
+		bd->cmd->entry->print(bd->cmd, s, sizeof s);
+		ctx->print(ctx, "%11s: %s", key, s);
 	}
 
 	if (ctx->cmdclient != NULL)
diff --git a/cmd-list-sessions.c b/cmd-list-sessions.c
index 0b112e96..92e64dbb 100644
--- a/cmd-list-sessions.c
+++ b/cmd-list-sessions.c
@@ -1,4 +1,4 @@
-/* $Id: cmd-list-sessions.c,v 1.13 2008-06-03 18:13:54 nicm Exp $ */
+/* $Id: cmd-list-sessions.c,v 1.14 2008-06-05 16:35:31 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -27,7 +27,7 @@
  * List all sessions.
  */
 
-void	cmd_list_sessions_exec(void *, struct cmd_ctx *);
+void	cmd_list_sessions_exec(struct cmd *, struct cmd_ctx *);
 
 const struct cmd_entry cmd_list_sessions_entry = {
 	"list-sessions", "ls", "",
@@ -37,11 +37,12 @@ const struct cmd_entry cmd_list_sessions_entry = {
 	NULL,
 	NULL,
 	NULL,
+	NULL,
 	NULL
 };
 
 void
-cmd_list_sessions_exec(unused void *ptr, struct cmd_ctx *ctx)
+cmd_list_sessions_exec(unused struct cmd *self, struct cmd_ctx *ctx)
 {
 	struct session	*s;
 	struct winlink	*wl;
diff --git a/cmd-list-windows.c b/cmd-list-windows.c
index 990e32cc..8e29d0fc 100644
--- a/cmd-list-windows.c
+++ b/cmd-list-windows.c
@@ -1,4 +1,4 @@
-/* $Id: cmd-list-windows.c,v 1.18 2008-06-03 05:35:51 nicm Exp $ */
+/* $Id: cmd-list-windows.c,v 1.19 2008-06-05 16:35:31 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -26,7 +26,7 @@
  * List windows on given session.
  */
 
-void	cmd_list_windows_exec(void *, struct cmd_ctx *);
+void	cmd_list_windows_exec(struct cmd *, struct cmd_ctx *);
 
 const struct cmd_entry cmd_list_windows_entry = {
 	"list-windows", "lsw",
@@ -37,11 +37,12 @@ const struct cmd_entry cmd_list_windows_entry = {
 	cmd_sessiononly_send,
 	cmd_sessiononly_recv,
 	cmd_sessiononly_free,
-	NULL
+	NULL,
+	cmd_sessiononly_print
 };
 
 void
-cmd_list_windows_exec(void *ptr, struct cmd_ctx *ctx)
+cmd_list_windows_exec(struct cmd *self, struct cmd_ctx *ctx)
 {
 	struct session		*s;
 	struct winlink		*wl;
@@ -49,7 +50,7 @@ cmd_list_windows_exec(void *ptr, struct cmd_ctx *ctx)
 	u_int			 i;
 	unsigned long long	 size;
 
-	if ((s = cmd_sessiononly_get(ptr, ctx)) == NULL)
+	if ((s = cmd_sessiononly_get(self, ctx)) == NULL)
 		return;
 
 	RB_FOREACH(wl, winlinks, &s->windows) {
diff --git a/cmd-new-session.c b/cmd-new-session.c
index 59dcf792..adff55e4 100644
--- a/cmd-new-session.c
+++ b/cmd-new-session.c
@@ -1,4 +1,4 @@
-/* $Id: cmd-new-session.c,v 1.24 2008-06-03 21:42:37 nicm Exp $ */
+/* $Id: cmd-new-session.c,v 1.25 2008-06-05 16:35:31 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -26,12 +26,12 @@
  * Create a new session and attach to the current terminal unless -d is given.
  */
 
-int	cmd_new_session_parse(struct cmd *, void **, int, char **, char **);
-void	cmd_new_session_exec(void *, struct cmd_ctx *);
-void	cmd_new_session_send(void *, struct buffer *);
-void	cmd_new_session_recv(void **, struct buffer *);
-void	cmd_new_session_free(void *);
-void	cmd_new_session_init(void **, int);
+int	cmd_new_session_parse(struct cmd *, int, char **, char **);
+void	cmd_new_session_exec(struct cmd *, struct cmd_ctx *);
+void	cmd_new_session_send(struct cmd *, struct buffer *);
+void	cmd_new_session_recv(struct cmd *, struct buffer *);
+void	cmd_new_session_free(struct cmd *);
+void	cmd_new_session_init(struct cmd *, int);
 
 struct cmd_new_session_data {
 	char	*name;
@@ -49,15 +49,16 @@ const struct cmd_entry cmd_new_session_entry = {
 	cmd_new_session_send,
 	cmd_new_session_recv,
 	cmd_new_session_free,
-	cmd_new_session_init
+	cmd_new_session_init,
+	NULL
 };
 
 void
-cmd_new_session_init(void **ptr, unused int arg)
+cmd_new_session_init(struct cmd *self, unused int arg)
 {
 	struct cmd_new_session_data	 *data;
 
-	*ptr = data = xmalloc(sizeof *data);
+	self->data = data = xmalloc(sizeof *data);
 	data->flag_detached = 0;
 	data->name = NULL;
 	data->winname = NULL;
@@ -65,14 +66,13 @@ cmd_new_session_init(void **ptr, unused int arg)
 }
 
 int
-cmd_new_session_parse(
-    struct cmd *self, void **ptr, int argc, char **argv, char **cause)
+cmd_new_session_parse(struct cmd *self, int argc, char **argv, char **cause)
 {
 	struct cmd_new_session_data	*data;
 	int				 opt;
 
-	self->entry->init(ptr, 0);
-	data = *ptr;
+	self->entry->init(self, 0);
+	data = self->data;
 
 	while ((opt = getopt(argc, argv, "ds:n:")) != EOF) {
 		switch (opt) {
@@ -102,14 +102,14 @@ cmd_new_session_parse(
 usage:
 	xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
 
-	cmd_new_session_free(data);
+	self->entry->free(self);
 	return (-1);
 }
 
 void
-cmd_new_session_exec(void *ptr, struct cmd_ctx *ctx)
+cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx)
 {
-	struct cmd_new_session_data	*data = ptr;
+	struct cmd_new_session_data	*data = self->data;
 	struct client			*c = ctx->cmdclient;
 	struct session			*s;
 	char				*cmd, *cause;
@@ -175,9 +175,9 @@ cmd_new_session_exec(void *ptr, struct cmd_ctx *ctx)
 }
 
 void
-cmd_new_session_send(void *ptr, struct buffer *b)
+cmd_new_session_send(struct cmd *self, struct buffer *b)
 {
-	struct cmd_new_session_data	*data = ptr;
+	struct cmd_new_session_data	*data = self->data;
 
 	buffer_write(b, data, sizeof *data);
 	cmd_send_string(b, data->name);
@@ -186,11 +186,11 @@ cmd_new_session_send(void *ptr, struct buffer *b)
 }
 
 void
-cmd_new_session_recv(void **ptr, struct buffer *b)
+cmd_new_session_recv(struct cmd *self, struct buffer *b)
 {
 	struct cmd_new_session_data	*data;
 
-	*ptr = data = xmalloc(sizeof *data);
+	self->data = data = xmalloc(sizeof *data);
 	buffer_read(b, data, sizeof *data);
 	data->name = cmd_recv_string(b);
 	data->winname = cmd_recv_string(b);
@@ -198,9 +198,9 @@ cmd_new_session_recv(void **ptr, struct buffer *b)
 }
 
 void
-cmd_new_session_free(void *ptr)
+cmd_new_session_free(struct cmd *self)
 {
-	struct cmd_new_session_data	*data = ptr;
+	struct cmd_new_session_data	*data = self->data;
 
 	if (data->name != NULL)
 		xfree(data->name);
diff --git a/cmd-new-window.c b/cmd-new-window.c
index 030847b5..adfea267 100644
--- a/cmd-new-window.c
+++ b/cmd-new-window.c
@@ -1,4 +1,4 @@
-/* $Id: cmd-new-window.c,v 1.20 2008-06-03 21:42:37 nicm Exp $ */
+/* $Id: cmd-new-window.c,v 1.21 2008-06-05 16:35:31 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -27,12 +27,12 @@
  * Create a new window.
  */
 
-int	cmd_new_window_parse(struct cmd *, void **, int, char **, char **);
-void	cmd_new_window_exec(void *, struct cmd_ctx *);
-void	cmd_new_window_send(void *, struct buffer *);
-void	cmd_new_window_recv(void **, struct buffer *);
-void	cmd_new_window_free(void *);
-void	cmd_new_window_init(void **, int);
+int	cmd_new_window_parse(struct cmd *, int, char **, char **);
+void	cmd_new_window_exec(struct cmd *, struct cmd_ctx *);
+void	cmd_new_window_send(struct cmd *, struct buffer *);
+void	cmd_new_window_recv(struct cmd *, struct buffer *);
+void	cmd_new_window_free(struct cmd *);
+void	cmd_new_window_init(struct cmd *, int);
 
 struct cmd_new_window_data {
 	char	*cname;
@@ -52,15 +52,16 @@ const struct cmd_entry cmd_new_window_entry = {
 	cmd_new_window_send,
 	cmd_new_window_recv,
 	cmd_new_window_free,
-	cmd_new_window_init
+	cmd_new_window_init,
+	NULL
 };
 
 void
-cmd_new_window_init(void **ptr, unused int arg)
+cmd_new_window_init(struct cmd *self, unused int arg)
 {
 	struct cmd_new_window_data	 *data;
 
-	*ptr = data = xmalloc(sizeof *data);
+	self->data = data = xmalloc(sizeof *data);
 	data->cname = NULL;
 	data->sname = NULL;
 	data->idx = -1;
@@ -70,15 +71,14 @@ cmd_new_window_init(void **ptr, unused int arg)
 }
 
 int
-cmd_new_window_parse(
-    struct cmd *self, void **ptr, int argc, char **argv, char **cause)
+cmd_new_window_parse(struct cmd *self, int argc, char **argv, char **cause)
 {
 	struct cmd_new_window_data	*data;
 	const char			*errstr;
 	int				 opt;
 
-	self->entry->init(ptr, 0);
-	data = *ptr;
+	self->entry->init(self, 0);
+	data = self->data;
 
 	while ((opt = getopt(argc, argv, "c:di:n:s:")) != EOF) {
 		switch (opt) {
@@ -126,14 +126,14 @@ usage:
 	xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
 
 error:
-	cmd_new_window_free(data);
+	self->entry->free(self);
 	return (-1);
 }
 
 void
-cmd_new_window_exec(void *ptr, struct cmd_ctx *ctx)
+cmd_new_window_exec(struct cmd *self, struct cmd_ctx *ctx)
 {
-	struct cmd_new_window_data	*data = ptr;
+	struct cmd_new_window_data	*data = self->data;
 	struct session			*s;
 	struct winlink			*wl;
 	char				*cmd;
@@ -163,9 +163,9 @@ cmd_new_window_exec(void *ptr, struct cmd_ctx *ctx)
 }
 
 void
-cmd_new_window_send(void *ptr, struct buffer *b)
+cmd_new_window_send(struct cmd *self, struct buffer *b)
 {
-	struct cmd_new_window_data	*data = ptr;
+	struct cmd_new_window_data	*data = self->data;
 
 	buffer_write(b, data, sizeof *data);
 	cmd_send_string(b, data->cname);
@@ -175,11 +175,11 @@ cmd_new_window_send(void *ptr, struct buffer *b)
 }
 
 void
-cmd_new_window_recv(void **ptr, struct buffer *b)
+cmd_new_window_recv(struct cmd *self, struct buffer *b)
 {
 	struct cmd_new_window_data	*data;
 
-	*ptr = data = xmalloc(sizeof *data);
+	self->data = data = xmalloc(sizeof *data);
 	buffer_read(b, data, sizeof *data);
 	data->cname = cmd_recv_string(b);
 	data->sname = cmd_recv_string(b);
@@ -188,9 +188,9 @@ cmd_new_window_recv(void **ptr, struct buffer *b)
 }
 
 void
-cmd_new_window_free(void *ptr)
+cmd_new_window_free(struct cmd *self)
 {
-	struct cmd_new_window_data	*data = ptr;
+	struct cmd_new_window_data	*data = self->data;
 
 	if (data->cname != NULL)
 		xfree(data->cname);
diff --git a/cmd-next-window.c b/cmd-next-window.c
index 5c331643..c15589b7 100644
--- a/cmd-next-window.c
+++ b/cmd-next-window.c
@@ -1,4 +1,4 @@
-/* $Id: cmd-next-window.c,v 1.9 2008-06-03 05:35:51 nicm Exp $ */
+/* $Id: cmd-next-window.c,v 1.10 2008-06-05 16:35:31 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -24,7 +24,7 @@
  * Move to next window.
  */
 
-void	cmd_next_window_exec(void *, struct cmd_ctx *);
+void	cmd_next_window_exec(struct cmd *, struct cmd_ctx *);
 
 const struct cmd_entry cmd_next_window_entry = {
 	"next-window", "next",
@@ -35,15 +35,16 @@ const struct cmd_entry cmd_next_window_entry = {
 	cmd_sessiononly_send,
 	cmd_sessiononly_recv,
 	cmd_sessiononly_free,
-	NULL
+	NULL,
+	cmd_sessiononly_print
 };
 
 void
-cmd_next_window_exec(void *ptr, struct cmd_ctx *ctx)
+cmd_next_window_exec(struct cmd *self, struct cmd_ctx *ctx)
 {
 	struct session	*s;
 
-	if ((s = cmd_sessiononly_get(ptr, ctx)) == NULL)
+	if ((s = cmd_sessiononly_get(self, ctx)) == NULL)
 		return;
 
 	if (session_next(s) == 0)
diff --git a/cmd-paste-buffer.c b/cmd-paste-buffer.c
index 96e0d4f0..a9cd7004 100644
--- a/cmd-paste-buffer.c
+++ b/cmd-paste-buffer.c
@@ -1,4 +1,4 @@
-/* $Id: cmd-paste-buffer.c,v 1.6 2008-06-03 05:35:51 nicm Exp $ */
+/* $Id: cmd-paste-buffer.c,v 1.7 2008-06-05 16:35:32 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -26,7 +26,7 @@
  * Paste paste buffer if present.
  */
 
-void	cmd_paste_buffer_exec(void *, struct cmd_ctx *);
+void	cmd_paste_buffer_exec(struct cmd *, struct cmd_ctx *);
 
 const struct cmd_entry cmd_paste_buffer_entry = {
 	"paste-buffer", "paste",
@@ -37,15 +37,16 @@ const struct cmd_entry cmd_paste_buffer_entry = {
 	cmd_windowonly_send,
 	cmd_windowonly_recv,
 	cmd_windowonly_free,
+	NULL,
 	NULL
 };
 
 void
-cmd_paste_buffer_exec(void *ptr, struct cmd_ctx *ctx)
+cmd_paste_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
 {
 	struct winlink	*wl;
 
-	if ((wl = cmd_windowonly_get(ptr, ctx, NULL)) == NULL)
+	if ((wl = cmd_windowonly_get(self, ctx, NULL)) == NULL)
 		return;
 
 	if (paste_buffer != NULL && *paste_buffer != '\0') {
diff --git a/cmd-previous-window.c b/cmd-previous-window.c
index 2758343f..173333a9 100644
--- a/cmd-previous-window.c
+++ b/cmd-previous-window.c
@@ -1,4 +1,4 @@
-/* $Id: cmd-previous-window.c,v 1.9 2008-06-03 05:35:51 nicm Exp $ */
+/* $Id: cmd-previous-window.c,v 1.10 2008-06-05 16:35:32 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -24,7 +24,7 @@
  * Move to previous window.
  */
 
-void	cmd_previous_window_exec(void *, struct cmd_ctx *);
+void	cmd_previous_window_exec(struct cmd *, struct cmd_ctx *);
 
 const struct cmd_entry cmd_previous_window_entry = {
 	"previous-window", "prev",
@@ -35,15 +35,16 @@ const struct cmd_entry cmd_previous_window_entry = {
 	cmd_sessiononly_send,
 	cmd_sessiononly_recv,
 	cmd_sessiononly_free,
-	NULL
+	NULL,
+	cmd_sessiononly_print
 };
 
 void
-cmd_previous_window_exec(void *ptr, struct cmd_ctx *ctx)
+cmd_previous_window_exec(struct cmd *self, struct cmd_ctx *ctx)
 {
 	struct session	*s;
 
-	if ((s = cmd_sessiononly_get(ptr, ctx)) == NULL)
+	if ((s = cmd_sessiononly_get(self, ctx)) == NULL)
 		return;
 
 	if (session_previous(s) == 0)
diff --git a/cmd-refresh-client.c b/cmd-refresh-client.c
index 90df0ea5..a8cce215 100644
--- a/cmd-refresh-client.c
+++ b/cmd-refresh-client.c
@@ -1,4 +1,4 @@
-/* $Id: cmd-refresh-client.c,v 1.4 2008-06-03 05:35:51 nicm Exp $ */
+/* $Id: cmd-refresh-client.c,v 1.5 2008-06-05 16:35:32 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -24,7 +24,7 @@
  * Refresh client.
  */
 
-void	cmd_refresh_client_exec(void *, struct cmd_ctx *);
+void	cmd_refresh_client_exec(struct cmd *, struct cmd_ctx *);
 
 const struct cmd_entry cmd_refresh_client_entry = {
 	"refresh-client", "refresh",
@@ -35,15 +35,16 @@ const struct cmd_entry cmd_refresh_client_entry = {
 	cmd_clientonly_send,
 	cmd_clientonly_recv,
 	cmd_clientonly_free,
-	NULL
+	NULL,
+	cmd_clientonly_print
 };
 
 void
-cmd_refresh_client_exec(void *ptr, struct cmd_ctx *ctx)
+cmd_refresh_client_exec(struct cmd *self, struct cmd_ctx *ctx)
 {
 	struct client	*c;
 
-	if ((c = cmd_clientonly_get(ptr, ctx)) == NULL)
+	if ((c = cmd_clientonly_get(self, ctx)) == NULL)
 		return;
 
 	server_redraw_client(c);
diff --git a/cmd-rename-session.c b/cmd-rename-session.c
index 48c91193..63314618 100644
--- a/cmd-rename-session.c
+++ b/cmd-rename-session.c
@@ -1,4 +1,4 @@
-/* $Id: cmd-rename-session.c,v 1.8 2008-06-03 16:55:09 nicm Exp $ */
+/* $Id: cmd-rename-session.c,v 1.9 2008-06-05 16:35:32 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -27,11 +27,11 @@
  * Change session name.
  */
 
-int	cmd_rename_session_parse(struct cmd *, void **, int, char **, char **);
-void	cmd_rename_session_exec(void *, struct cmd_ctx *);
-void	cmd_rename_session_send(void *, struct buffer *);
-void	cmd_rename_session_recv(void **, struct buffer *);
-void	cmd_rename_session_free(void *);
+int	cmd_rename_session_parse(struct cmd *, int, char **, char **);
+void	cmd_rename_session_exec(struct cmd *, struct cmd_ctx *);
+void	cmd_rename_session_send(struct cmd *, struct buffer *);
+void	cmd_rename_session_recv(struct cmd *, struct buffer *);
+void	cmd_rename_session_free(struct cmd *);
 
 struct cmd_rename_session_data {
 	char	*cname;
@@ -48,17 +48,17 @@ const struct cmd_entry cmd_rename_session_entry = {
 	cmd_rename_session_send,
 	cmd_rename_session_recv,
 	cmd_rename_session_free,
+	NULL,
 	NULL
 };
 
 int
-cmd_rename_session_parse(
-    struct cmd *self, void **ptr, int argc, char **argv, char **cause)
+cmd_rename_session_parse(struct cmd *self, int argc, char **argv, char **cause)
 {
 	struct cmd_rename_session_data	*data;
 	int				 opt;
 
-	*ptr = data = xmalloc(sizeof *data);
+	self->data = data = xmalloc(sizeof *data);
 	data->cname = NULL;
 	data->sname = NULL;
 	data->newname = NULL;
@@ -93,14 +93,14 @@ cmd_rename_session_parse(
 usage:
 	xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
 
-	cmd_rename_session_free(data);
+	self->entry->free(self);
 	return (-1);
 }
 
 void
-cmd_rename_session_exec(void *ptr, struct cmd_ctx *ctx)
+cmd_rename_session_exec(struct cmd *self, struct cmd_ctx *ctx)
 {
-	struct cmd_rename_session_data	*data = ptr;
+	struct cmd_rename_session_data	*data = self->data;
 	struct session			*s;
 
 	if (data == NULL)
@@ -117,9 +117,9 @@ cmd_rename_session_exec(void *ptr, struct cmd_ctx *ctx)
 }
 
 void
-cmd_rename_session_send(void *ptr, struct buffer *b)
+cmd_rename_session_send(struct cmd *self, struct buffer *b)
 {
-	struct cmd_rename_session_data	*data = ptr;
+	struct cmd_rename_session_data	*data = self->data;
 
 	buffer_write(b, data, sizeof *data);
 	cmd_send_string(b, data->cname);
@@ -128,11 +128,11 @@ cmd_rename_session_send(void *ptr, struct buffer *b)
 }
 
 void
-cmd_rename_session_recv(void **ptr, struct buffer *b)
+cmd_rename_session_recv(struct cmd *self, struct buffer *b)
 {
 	struct cmd_rename_session_data	*data;
 
-	*ptr = data = xmalloc(sizeof *data);
+	self->data = data = xmalloc(sizeof *data);
 	buffer_read(b, data, sizeof *data);
 	data->cname = cmd_recv_string(b);
 	data->sname = cmd_recv_string(b);
@@ -140,9 +140,9 @@ cmd_rename_session_recv(void **ptr, struct buffer *b)
 }
 
 void
-cmd_rename_session_free(void *ptr)
+cmd_rename_session_free(struct cmd *self)
 {
-	struct cmd_rename_session_data	*data = ptr;
+	struct cmd_rename_session_data	*data = self->data;
 
 	if (data->cname != NULL)
 		xfree(data->cname);
diff --git a/cmd-rename-window.c b/cmd-rename-window.c
index 5bb4db5a..7bc26d20 100644
--- a/cmd-rename-window.c
+++ b/cmd-rename-window.c
@@ -1,4 +1,4 @@
-/* $Id: cmd-rename-window.c,v 1.19 2008-06-04 17:54:26 nicm Exp $ */
+/* $Id: cmd-rename-window.c,v 1.20 2008-06-05 16:35:32 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -27,11 +27,11 @@
  * Rename window by index.
  */
 
-int	cmd_rename_window_parse(struct cmd *, void **, int, char **, char **);
-void	cmd_rename_window_exec(void *, struct cmd_ctx *);
-void	cmd_rename_window_send(void *, struct buffer *);
-void	cmd_rename_window_recv(void **, struct buffer *);
-void	cmd_rename_window_free(void *);
+int	cmd_rename_window_parse(struct cmd *, int, char **, char **);
+void	cmd_rename_window_exec(struct cmd *, struct cmd_ctx *);
+void	cmd_rename_window_send(struct cmd *, struct buffer *);
+void	cmd_rename_window_recv(struct cmd *, struct buffer *);
+void	cmd_rename_window_free(struct cmd *);
 
 struct cmd_rename_window_data {
 	char	*cname;
@@ -49,18 +49,18 @@ const struct cmd_entry cmd_rename_window_entry = {
 	cmd_rename_window_send,
 	cmd_rename_window_recv,
 	cmd_rename_window_free,
+	NULL,
 	NULL
 };
 
 int
-cmd_rename_window_parse(
-    struct cmd *self, void **ptr, int argc, char **argv, char **cause)
+cmd_rename_window_parse(struct cmd *self, int argc, char **argv, char **cause)
 {
 	struct cmd_rename_window_data	*data;
 	const char			*errstr;
 	int				 opt;
 
-	*ptr = data = xmalloc(sizeof *data);
+	self->data = data = xmalloc(sizeof *data);
 	data->cname = NULL;
 	data->sname = NULL;
 	data->idx = -1;
@@ -104,14 +104,14 @@ usage:
 	xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
 
 error:
-	cmd_rename_window_free(data);
+	self->entry->free(self);
 	return (-1);
 }
 
 void
-cmd_rename_window_exec(void *ptr, struct cmd_ctx *ctx)
+cmd_rename_window_exec(struct cmd *self, struct cmd_ctx *ctx)
 {
-	struct cmd_rename_window_data	*data = ptr;
+	struct cmd_rename_window_data	*data = self->data;
 	struct session			*s;
 	struct winlink			*wl;
 
@@ -132,9 +132,9 @@ cmd_rename_window_exec(void *ptr, struct cmd_ctx *ctx)
 }
 
 void
-cmd_rename_window_send(void *ptr, struct buffer *b)
+cmd_rename_window_send(struct cmd *self, struct buffer *b)
 {
-	struct cmd_rename_window_data	*data = ptr;
+	struct cmd_rename_window_data	*data = self->data;
 
 	buffer_write(b, data, sizeof *data);
 	cmd_send_string(b, data->cname);
@@ -143,11 +143,11 @@ cmd_rename_window_send(void *ptr, struct buffer *b)
 }
 
 void
-cmd_rename_window_recv(void **ptr, struct buffer *b)
+cmd_rename_window_recv(struct cmd *self, struct buffer *b)
 {
 	struct cmd_rename_window_data	*data;
 
-	*ptr = data = xmalloc(sizeof *data);
+	self->data = data = xmalloc(sizeof *data);
 	buffer_read(b, data, sizeof *data);
 	data->cname = cmd_recv_string(b);
 	data->sname = cmd_recv_string(b);
@@ -155,9 +155,9 @@ cmd_rename_window_recv(void **ptr, struct buffer *b)
 }
 
 void
-cmd_rename_window_free(void *ptr)
+cmd_rename_window_free(struct cmd *self)
 {
-	struct cmd_rename_window_data	*data = ptr;
+	struct cmd_rename_window_data	*data = self->data;
 
 	if (data->cname != NULL)
 		xfree(data->cname);
diff --git a/cmd-scroll-mode.c b/cmd-scroll-mode.c
index dc75de66..16199310 100644
--- a/cmd-scroll-mode.c
+++ b/cmd-scroll-mode.c
@@ -1,4 +1,4 @@
-/* $Id: cmd-scroll-mode.c,v 1.10 2008-06-03 05:35:51 nicm Exp $ */
+/* $Id: cmd-scroll-mode.c,v 1.11 2008-06-05 16:35:32 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -24,7 +24,7 @@
  * Enter scroll mode. Only valid when bound to a key.
  */
 
-void	cmd_scroll_mode_exec(void *, struct cmd_ctx *);
+void	cmd_scroll_mode_exec(struct cmd *, struct cmd_ctx *);
 
 const struct cmd_entry cmd_scroll_mode_entry = {
 	"scroll-mode", NULL,
@@ -35,15 +35,16 @@ const struct cmd_entry cmd_scroll_mode_entry = {
 	cmd_windowonly_send,
 	cmd_windowonly_recv,
 	cmd_windowonly_free,
+	NULL,
 	NULL
 };
 
 void
-cmd_scroll_mode_exec(void *ptr, struct cmd_ctx *ctx)
+cmd_scroll_mode_exec(struct cmd *self, struct cmd_ctx *ctx)
 {
 	struct winlink	*wl;
 
-	if ((wl = cmd_windowonly_get(ptr, ctx, NULL)) == NULL)
+	if ((wl = cmd_windowonly_get(self, ctx, NULL)) == NULL)
 		return;
 
 	window_set_mode(wl->window, &window_scroll_mode);
diff --git a/cmd-select-window.c b/cmd-select-window.c
index 703bed05..23ac48b4 100644
--- a/cmd-select-window.c
+++ b/cmd-select-window.c
@@ -1,4 +1,4 @@
-/* $Id: cmd-select-window.c,v 1.16 2008-06-04 16:11:52 nicm Exp $ */
+/* $Id: cmd-select-window.c,v 1.17 2008-06-05 16:35:32 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -27,8 +27,8 @@
  * Select window by index.
  */
 
-void	cmd_select_window_init(void **, int);
-void	cmd_select_window_exec(void *, struct cmd_ctx *);
+void	cmd_select_window_init(struct cmd *, int);
+void	cmd_select_window_exec(struct cmd *, struct cmd_ctx *);
 
 const struct cmd_entry cmd_select_window_entry = {
 	"select-window", "selectw",
@@ -39,27 +39,28 @@ const struct cmd_entry cmd_select_window_entry = {
 	cmd_windowonly_send,
 	cmd_windowonly_recv,
 	cmd_windowonly_free,
-	cmd_select_window_init
+	cmd_select_window_init,
+	cmd_windowonly_print
 };
 
 void
-cmd_select_window_init(void **ptr, int arg)
+cmd_select_window_init(struct cmd *self, int arg)
 {
 	struct cmd_windowonly_data	*data;
 
-	*ptr = data = xmalloc(sizeof *data);
+	self->data = data = xmalloc(sizeof *data);
 	data->cname = NULL;
 	data->sname = NULL;
 	data->idx = arg - '0';
 }
 
 void
-cmd_select_window_exec(void *ptr, struct cmd_ctx *ctx)
+cmd_select_window_exec(struct cmd *self, struct cmd_ctx *ctx)
 {
 	struct winlink	*wl;
 	struct session	*s;
 
-	if ((wl = cmd_windowonly_get(ptr, ctx, &s)) == NULL)
+	if ((wl = cmd_windowonly_get(self, ctx, &s)) == NULL)
 		return;
 
 	if (session_select(s, wl->idx) == 0)
diff --git a/cmd-send-keys.c b/cmd-send-keys.c
index 6e9f7f43..95ad63cb 100644
--- a/cmd-send-keys.c
+++ b/cmd-send-keys.c
@@ -1,4 +1,4 @@
-/* $Id: cmd-send-keys.c,v 1.7 2008-06-03 16:55:09 nicm Exp $ */
+/* $Id: cmd-send-keys.c,v 1.8 2008-06-05 16:35:32 nicm Exp $ */
 
 /*
  * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -27,11 +27,11 @@
  * Send keys to client.
  */
 
-int	cmd_send_keys_parse(struct cmd *, void **, int, char **, char **);
-void	cmd_send_keys_exec(void *, struct cmd_ctx *);
-void	cmd_send_keys_send(void *, struct buffer *);
-void	cmd_send_keys_recv(void **, struct buffer *);
-void	cmd_send_keys_free(void *);
+int	cmd_send_keys_parse(struct cmd *, int, char **, char **);
+void	cmd_send_keys_exec(struct cmd *, struct cmd_ctx *);
+void	cmd_send_keys_send(struct cmd *, struct buffer *);
+void	cmd_send_keys_recv(struct cmd *, struct buffer *);
+void	cmd_send_keys_free(struct cmd *);
 
 struct cmd_send_keys_data {
 	char	*cname;
@@ -50,19 +50,19 @@ const struct cmd_entry cmd_send_keys_entry = {
 	cmd_send_keys_send,
 	cmd_send_keys_recv,
 	cmd_send_keys_free,
+	NULL,
 	NULL
 };
 
 int
-cmd_send_keys_parse(
-    struct cmd *self, void **ptr, int argc, char **argv, char **cause)
+cmd_send_keys_parse(struct cmd *self, int argc, char **argv, char **cause)
 {
 	struct cmd_send_keys_data	*data;
 	int				 opt, key;
 	const char			*errstr;
 	char				*s;
 
-	*ptr = data = xmalloc(sizeof *data);
+	self->data = data = xmalloc(sizeof *data);
 	data->cname = NULL;
 	data->sname = NULL;
 	data->idx = -1;
@@ -121,14 +121,14 @@ usage:
 	xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
 
 error:
-	cmd_send_keys_free(data);
+	self->entry->free(self);
 	return (-1);
 }
 
 void
-cmd_send_keys_exec(void *ptr, struct cmd_ctx *ctx)
+cmd_send_keys_exec(struct cmd *self, struct cmd_ctx *ctx)
 {
-	struct cmd_send_keys_data	*data = ptr;
+	struct cmd_send_keys_data	*data = self->data;
 	struct winlink			*wl;
 	u_int				 i;
 
@@ -147,9 +147,9 @@ cmd_send_keys_exec(void *ptr, struct cmd_ctx *ctx)
 }
 
 void
-cmd_send_keys_send(void *ptr, struct buffer *b)
+cmd_send_keys_send(struct cmd *self, struct buffer *b)
 {
-	struct cmd_send_keys_data	*data = ptr;
+	struct cmd_send_keys_data	*data = self->data;
 
 	buffer_write(b, data, sizeof *data);
 	cmd_send_string(b, data->cname);
@@ -158,11 +158,11 @@ cmd_send_keys_send(void *ptr, struct buffer *b)
 }
 
 void
-cmd_send_keys_recv(void **ptr, struct buffer *b)
+cmd_send_keys_recv(struct cmd *self, struct buffer *b)
 {
 	struct cmd_send_keys_data	*data;
 
-	*ptr = data = xmalloc(sizeof *data);
+	self->data = data = xmalloc(sizeof *data);
 	buffer_read(b, data, sizeof *data);
 	data->cname = cmd_recv_string(b);
 	data->sname = cmd_recv_string(b);
@@ -171,9 +171,9 @@ cmd_send_keys_recv(void **ptr, struct buffer *b)
 }
 
 void
-cmd_send_keys_free(void *ptr)
+cmd_send_keys_free(struct cmd *self)
 {
-	struct cmd_send_keys_data	*data = ptr;
+	struct cmd_send_keys_data	*data = self->data;
 
 	if (data->cname != NULL)
 		xfree(data->cname);
diff --git a/cmd-send-prefix.c b/cmd-send-prefix.c
index 117ec4c2..c8df7da6 100644
--- a/cmd-send-prefix.c
+++ b/cmd-send-prefix.c
@@ -1,4 +1,4 @@
-/* $Id: cmd-send-prefix.c,v 1.12 2008-06-03 21:42:37 nicm Exp $ */
+/* $Id: cmd-send-prefix.c,v 1.13 2008-06-05 16:35:32 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -24,7 +24,7 @@
  * Send prefix key as a key.
  */
 
-void	cmd_send_prefix_exec(void *, struct cmd_ctx *);
+void	cmd_send_prefix_exec(struct cmd *, struct cmd_ctx *);
 
 const struct cmd_entry cmd_send_prefix_entry = {
 	"send-prefix", NULL,
@@ -35,16 +35,17 @@ const struct cmd_entry cmd_send_prefix_entry = {
 	cmd_windowonly_send,
 	cmd_windowonly_recv,
 	cmd_windowonly_free,
+	NULL,
 	NULL
 };
 
 void
-cmd_send_prefix_exec(void *ptr, struct cmd_ctx *ctx)
+cmd_send_prefix_exec(struct cmd *self, struct cmd_ctx *ctx)
 {
 	struct session	*s;
 	struct winlink	*wl;
 
-	if ((wl = cmd_windowonly_get(ptr, ctx, &s)) == NULL)
+	if ((wl = cmd_windowonly_get(self, ctx, &s)) == NULL)
 		return;
 
 	window_key(wl->window, options_get_number(&s->options, "prefix-key"));
diff --git a/cmd-set-option.c b/cmd-set-option.c
index b2ef320b..1b985103 100644
--- a/cmd-set-option.c
+++ b/cmd-set-option.c
@@ -1,4 +1,4 @@
-/* $Id: cmd-set-option.c,v 1.22 2008-06-04 18:34:56 nicm Exp $ */
+/* $Id: cmd-set-option.c,v 1.23 2008-06-05 16:35:32 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -28,11 +28,11 @@
  * Set an option.
  */
 
-int	cmd_set_option_parse(struct cmd *, void **, int, char **, char **);
-void	cmd_set_option_exec(void *, struct cmd_ctx *);
-void	cmd_set_option_send(void *, struct buffer *);
-void	cmd_set_option_recv(void **, struct buffer *);
-void	cmd_set_option_free(void *);
+int	cmd_set_option_parse(struct cmd *, int, char **, char **);
+void	cmd_set_option_exec(struct cmd *, struct cmd_ctx *);
+void	cmd_set_option_send(struct cmd *, struct buffer *);
+void	cmd_set_option_recv(struct cmd *, struct buffer *);
+void	cmd_set_option_free(struct cmd *);
 
 struct cmd_set_option_data {
 	char	*cname;
@@ -51,17 +51,17 @@ const struct cmd_entry cmd_set_option_entry = {
 	cmd_set_option_send,
 	cmd_set_option_recv,
 	cmd_set_option_free,
+	NULL,
 	NULL
 };
 
 int
-cmd_set_option_parse(
-    struct cmd *self, void **ptr, int argc, char **argv, char **cause)
+cmd_set_option_parse(struct cmd *self, int argc, char **argv, char **cause)
 {
 	struct cmd_set_option_data	*data;
 	int				 opt;
 
-	*ptr = data = xmalloc(sizeof *data);
+	self->data = data = xmalloc(sizeof *data);
 	data->cname = NULL;
 	data->sname = NULL;
 	data->flag_global = 1;
@@ -102,14 +102,14 @@ cmd_set_option_parse(
 usage:
 	xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
 
-	cmd_set_option_free(data);
+	self->entry->free(self);
 	return (-1);
 }
 
 void
-cmd_set_option_exec(void *ptr, unused struct cmd_ctx *ctx)
+cmd_set_option_exec(struct cmd *self, unused struct cmd_ctx *ctx)
 {
-	struct cmd_set_option_data	*data = ptr;
+	struct cmd_set_option_data	*data = self->data;
 	struct client			*c;
 	struct session			*s;
 	struct options			*oo;
@@ -276,9 +276,9 @@ cmd_set_option_exec(void *ptr, unused struct cmd_ctx *ctx)
 }
 
 void
-cmd_set_option_send(void *ptr, struct buffer *b)
+cmd_set_option_send(struct cmd *self, struct buffer *b)
 {
-	struct cmd_set_option_data	*data = ptr;
+	struct cmd_set_option_data	*data = self->data;
 
 	buffer_write(b, data, sizeof *data);
 	cmd_send_string(b, data->cname);
@@ -288,11 +288,11 @@ cmd_set_option_send(void *ptr, struct buffer *b)
 }
 
 void
-cmd_set_option_recv(void **ptr, struct buffer *b)
+cmd_set_option_recv(struct cmd *self, struct buffer *b)
 {
 	struct cmd_set_option_data	*data;
 
-	*ptr = data = xmalloc(sizeof *data);
+	self->data = data = xmalloc(sizeof *data);
 	buffer_read(b, data, sizeof *data);
 	data->cname = cmd_recv_string(b);
 	data->sname = cmd_recv_string(b);
@@ -301,9 +301,9 @@ cmd_set_option_recv(void **ptr, struct buffer *b)
 }
 
 void
-cmd_set_option_free(void *ptr)
+cmd_set_option_free(struct cmd *self)
 {
-	struct cmd_set_option_data	*data = ptr;
+	struct cmd_set_option_data	*data = self->data;
 
 	if (data->cname != NULL)
 		xfree(data->cname);
diff --git a/cmd-set-window-option.c b/cmd-set-window-option.c
index af8d777b..29caa39f 100644
--- a/cmd-set-window-option.c
+++ b/cmd-set-window-option.c
@@ -1,4 +1,4 @@
-/* $Id: cmd-set-window-option.c,v 1.2 2008-06-04 18:32:20 nicm Exp $ */
+/* $Id: cmd-set-window-option.c,v 1.3 2008-06-05 16:35:32 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -28,12 +28,11 @@
  * Set a window option.
  */
 
-int	cmd_set_window_option_parse(
-	    struct cmd *, void **, int, char **, char **);
-void	cmd_set_window_option_exec(void *, struct cmd_ctx *);
-void	cmd_set_window_option_send(void *, struct buffer *);
-void	cmd_set_window_option_recv(void **, struct buffer *);
-void	cmd_set_window_option_free(void *);
+int	cmd_set_window_option_parse(struct cmd *, int, char **, char **);
+void	cmd_set_window_option_exec(struct cmd *, struct cmd_ctx *);
+void	cmd_set_window_option_send(struct cmd *, struct buffer *);
+void	cmd_set_window_option_recv(struct cmd *, struct buffer *);
+void	cmd_set_window_option_free(struct cmd *);
 
 struct cmd_set_window_option_data {
 	char	*cname;
@@ -52,18 +51,19 @@ const struct cmd_entry cmd_set_window_option_entry = {
 	cmd_set_window_option_send,
 	cmd_set_window_option_recv,
 	cmd_set_window_option_free,
+	NULL,
 	NULL
 };
 
 int
 cmd_set_window_option_parse(
-    struct cmd *self, void **ptr, int argc, char **argv, char **cause)
+    struct cmd *self, int argc, char **argv, char **cause)
 {
 	struct cmd_set_window_option_data	*data;
 	int				 	 opt;
 	const char   				*errstr;
 
-	*ptr = data = xmalloc(sizeof *data);
+	self->data = data = xmalloc(sizeof *data);
 	data->cname = NULL;
 	data->sname = NULL;
 	data->idx = -1;
@@ -110,14 +110,14 @@ usage:
 	xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
 
 error:
-	cmd_set_window_option_free(data);
+	self->entry->free(self);
 	return (-1);
 }
 
 void
-cmd_set_window_option_exec(void *ptr, unused struct cmd_ctx *ctx)
+cmd_set_window_option_exec(struct cmd *self, unused struct cmd_ctx *ctx)
 {
-	struct cmd_set_window_option_data	*data = ptr;
+	struct cmd_set_window_option_data	*data = self->data;
 	struct winlink				*wl;
 	struct session				*s;
 	const char				*errstr;
@@ -183,9 +183,9 @@ cmd_set_window_option_exec(void *ptr, unused struct cmd_ctx *ctx)
 }
 
 void
-cmd_set_window_option_send(void *ptr, struct buffer *b)
+cmd_set_window_option_send(struct cmd *self, struct buffer *b)
 {
-	struct cmd_set_window_option_data	*data = ptr;
+	struct cmd_set_window_option_data	*data = self->data;
 
 	buffer_write(b, data, sizeof *data);
 	cmd_send_string(b, data->cname);
@@ -195,11 +195,11 @@ cmd_set_window_option_send(void *ptr, struct buffer *b)
 }
 
 void
-cmd_set_window_option_recv(void **ptr, struct buffer *b)
+cmd_set_window_option_recv(struct cmd *self, struct buffer *b)
 {
 	struct cmd_set_window_option_data	*data;
 
-	*ptr = data = xmalloc(sizeof *data);
+	self->data = data = xmalloc(sizeof *data);
 	buffer_read(b, data, sizeof *data);
 	data->cname = cmd_recv_string(b);
 	data->sname = cmd_recv_string(b);
@@ -208,9 +208,9 @@ cmd_set_window_option_recv(void **ptr, struct buffer *b)
 }
 
 void
-cmd_set_window_option_free(void *ptr)
+cmd_set_window_option_free(struct cmd *self)
 {
-	struct cmd_set_window_option_data	*data = ptr;
+	struct cmd_set_window_option_data	*data = self->data;
 
 	if (data->cname != NULL)
 		xfree(data->cname);
diff --git a/cmd-start-server.c b/cmd-start-server.c
index 7bd89341..08e4bd18 100644
--- a/cmd-start-server.c
+++ b/cmd-start-server.c
@@ -1,4 +1,4 @@
-/* $Id: cmd-start-server.c,v 1.3 2008-06-03 05:35:51 nicm Exp $ */
+/* $Id: cmd-start-server.c,v 1.4 2008-06-05 16:35:32 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -24,7 +24,7 @@
  * Start the server and do nothing else.
  */
 
-void	cmd_start_server_exec(void *, struct cmd_ctx *);
+void	cmd_start_server_exec(struct cmd *, struct cmd_ctx *);
 
 const struct cmd_entry cmd_start_server_entry = {
 	"start-server", "start",
@@ -35,11 +35,12 @@ const struct cmd_entry cmd_start_server_entry = {
 	NULL,
 	NULL,
 	NULL,
+	NULL,
 	NULL
 };
 
 void
-cmd_start_server_exec(unused void *ptr, struct cmd_ctx *ctx)
+cmd_start_server_exec(unused struct cmd *self, struct cmd_ctx *ctx)
 {
 	if (ctx->cmdclient != NULL)
 		server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0);
diff --git a/cmd-swap-window.c b/cmd-swap-window.c
index 968bbc92..1b210278 100644
--- a/cmd-swap-window.c
+++ b/cmd-swap-window.c
@@ -1,4 +1,4 @@
-/* $Id: cmd-swap-window.c,v 1.8 2008-06-03 16:55:09 nicm Exp $ */
+/* $Id: cmd-swap-window.c,v 1.9 2008-06-05 16:35:32 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -27,11 +27,11 @@
  * Swap one window with another.
  */
 
-int	cmd_swap_window_parse(struct cmd *, void **, int, char **, char **);
-void	cmd_swap_window_exec(void *, struct cmd_ctx *);
-void	cmd_swap_window_send(void *, struct buffer *);
-void	cmd_swap_window_recv(void **, struct buffer *);
-void	cmd_swap_window_free(void *);
+int	cmd_swap_window_parse(struct cmd *, int, char **, char **);
+void	cmd_swap_window_exec(struct cmd *, struct cmd_ctx *);
+void	cmd_swap_window_send(struct cmd *, struct buffer *);
+void	cmd_swap_window_recv(struct cmd *, struct buffer *);
+void	cmd_swap_window_free(struct cmd *);
 
 struct cmd_swap_window_data {
 	char	*cname;
@@ -51,18 +51,18 @@ const struct cmd_entry cmd_swap_window_entry = {
 	cmd_swap_window_send,
 	cmd_swap_window_recv,
 	cmd_swap_window_free,
+	NULL,
 	NULL
 };
 
 int
-cmd_swap_window_parse(
-    struct cmd *self, void **ptr, int argc, char **argv, char **cause)
+cmd_swap_window_parse(struct cmd *self, int argc, char **argv, char **cause)
 {
 	struct cmd_swap_window_data	*data;
 	const char			*errstr;
 	int				 opt;
 
-	*ptr = data = xmalloc(sizeof *data);
+	self->data = data = xmalloc(sizeof *data);
 	data->cname = NULL;
 	data->sname = NULL;
 	data->flag_detached = 0;
@@ -116,14 +116,14 @@ usage:
 	xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
 
 error:
-	cmd_swap_window_free(data);
+	self->entry->free(self);
 	return (-1);
 }
 
 void
-cmd_swap_window_exec(void *ptr, struct cmd_ctx *ctx)
+cmd_swap_window_exec(struct cmd *self, struct cmd_ctx *ctx)
 {
-	struct cmd_swap_window_data	*data = ptr;
+	struct cmd_swap_window_data	*data = self->data;
 	struct session			*s, *src;
 	struct winlink			*srcwl, *dstwl;
 	struct window			*w;
@@ -181,9 +181,9 @@ cmd_swap_window_exec(void *ptr, struct cmd_ctx *ctx)
 }
 
 void
-cmd_swap_window_send(void *ptr, struct buffer *b)
+cmd_swap_window_send(struct cmd *self, struct buffer *b)
 {
-	struct cmd_swap_window_data	*data = ptr;
+	struct cmd_swap_window_data	*data = self->data;
 
 	buffer_write(b, data, sizeof *data);
 	cmd_send_string(b, data->cname);
@@ -192,11 +192,11 @@ cmd_swap_window_send(void *ptr, struct buffer *b)
 }
 
 void
-cmd_swap_window_recv(void **ptr, struct buffer *b)
+cmd_swap_window_recv(struct cmd *self, struct buffer *b)
 {
 	struct cmd_swap_window_data	*data;
 
-	*ptr = data = xmalloc(sizeof *data);
+	self->data = data = xmalloc(sizeof *data);
 	buffer_read(b, data, sizeof *data);
 	data->cname = cmd_recv_string(b);
 	data->sname = cmd_recv_string(b);
@@ -204,9 +204,9 @@ cmd_swap_window_recv(void **ptr, struct buffer *b)
 }
 
 void
-cmd_swap_window_free(void *ptr)
+cmd_swap_window_free(struct cmd *self)
 {
-	struct cmd_swap_window_data	*data = ptr;
+	struct cmd_swap_window_data	*data = self->data;
 
 	if (data->cname != NULL)
 		xfree(data->cname);
diff --git a/cmd-switch-client.c b/cmd-switch-client.c
index 63b34487..0b96e364 100644
--- a/cmd-switch-client.c
+++ b/cmd-switch-client.c
@@ -1,4 +1,4 @@
-/* $Id: cmd-switch-client.c,v 1.6 2008-06-03 18:13:54 nicm Exp $ */
+/* $Id: cmd-switch-client.c,v 1.7 2008-06-05 16:35:32 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -28,11 +28,11 @@
  * Switch client to a different session.
  */
 
-int	cmd_switch_client_parse(struct cmd *, void **, int, char **, char **);
-void	cmd_switch_client_exec(void *, struct cmd_ctx *);
-void	cmd_switch_client_send(void *, struct buffer *);
-void	cmd_switch_client_recv(void **, struct buffer *);
-void	cmd_switch_client_free(void *);
+int	cmd_switch_client_parse(struct cmd *, int, char **, char **);
+void	cmd_switch_client_exec(struct cmd *, struct cmd_ctx *);
+void	cmd_switch_client_send(struct cmd *, struct buffer *);
+void	cmd_switch_client_recv(struct cmd *, struct buffer *);
+void	cmd_switch_client_free(struct cmd *);
 
 struct cmd_switch_client_data {
 	char	*cname;
@@ -48,17 +48,17 @@ const struct cmd_entry cmd_switch_client_entry = {
 	cmd_switch_client_send,
 	cmd_switch_client_recv,
 	cmd_switch_client_free,
+	NULL,
 	NULL
 };
 
 int
-cmd_switch_client_parse(
-    struct cmd *self, void **ptr, int argc, char **argv, char **cause)
+cmd_switch_client_parse(struct cmd *self, int argc, char **argv, char **cause)
 {
 	struct cmd_switch_client_data	*data;
 	int				 opt;
 
-	*ptr = data = xmalloc(sizeof *data);
+	self->data = data = xmalloc(sizeof *data);
 	data->cname = NULL;
 	data->name = NULL;
 
@@ -83,14 +83,14 @@ cmd_switch_client_parse(
 usage:
 	xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
 
-	cmd_switch_client_free(data);
+	self->entry->free(self);
 	return (-1);
 }
 
 void
-cmd_switch_client_exec(void *ptr, struct cmd_ctx *ctx)
+cmd_switch_client_exec(struct cmd *self, struct cmd_ctx *ctx)
 {
-	struct cmd_switch_client_data	*data = ptr;
+	struct cmd_switch_client_data	*data = self->data;
 	struct client			*c;
 	struct session			*s;
 
@@ -114,9 +114,9 @@ cmd_switch_client_exec(void *ptr, struct cmd_ctx *ctx)
 }
 
 void
-cmd_switch_client_send(void *ptr, struct buffer *b)
+cmd_switch_client_send(struct cmd *self, struct buffer *b)
 {
-	struct cmd_switch_client_data	*data = ptr;
+	struct cmd_switch_client_data	*data = self->data;
 
 	buffer_write(b, data, sizeof *data);
 	cmd_send_string(b, data->cname);
@@ -124,20 +124,20 @@ cmd_switch_client_send(void *ptr, struct buffer *b)
 }
 
 void
-cmd_switch_client_recv(void **ptr, struct buffer *b)
+cmd_switch_client_recv(struct cmd *self, struct buffer *b)
 {
 	struct cmd_switch_client_data	*data;
 
-	*ptr = data = xmalloc(sizeof *data);
+	self->data = data = xmalloc(sizeof *data);
 	buffer_read(b, data, sizeof *data);
 	data->cname = cmd_recv_string(b);
 	data->name = cmd_recv_string(b);
 }
 
 void
-cmd_switch_client_free(void *ptr)
+cmd_switch_client_free(struct cmd *self)
 {
-	struct cmd_switch_client_data	*data = ptr;
+	struct cmd_switch_client_data	*data = self->data;
 
 	if (data->cname != NULL)
 		xfree(data->cname);
diff --git a/cmd-unbind-key.c b/cmd-unbind-key.c
index 1e660a1d..8dc02d55 100644
--- a/cmd-unbind-key.c
+++ b/cmd-unbind-key.c
@@ -1,4 +1,4 @@
-/* $Id: cmd-unbind-key.c,v 1.11 2008-06-03 05:35:51 nicm Exp $ */
+/* $Id: cmd-unbind-key.c,v 1.12 2008-06-05 16:35:32 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -26,11 +26,11 @@
  * Unbind key from command.
  */
 
-int	cmd_unbind_key_parse(struct cmd *, void **, int, char **, char **);
-void	cmd_unbind_key_exec(void *, struct cmd_ctx *);
-void	cmd_unbind_key_send(void *, struct buffer *);
-void	cmd_unbind_key_recv(void **, struct buffer *);
-void	cmd_unbind_key_free(void *);
+int	cmd_unbind_key_parse(struct cmd *, int, char **, char **);
+void	cmd_unbind_key_exec(struct cmd *, struct cmd_ctx *);
+void	cmd_unbind_key_send(struct cmd *, struct buffer *);
+void	cmd_unbind_key_recv(struct cmd *, struct buffer *);
+void	cmd_unbind_key_free(struct cmd *);
 
 struct cmd_unbind_key_data {
 	int		 key;
@@ -45,17 +45,17 @@ const struct cmd_entry cmd_unbind_key_entry = {
 	cmd_unbind_key_send,
 	cmd_unbind_key_recv,
 	cmd_unbind_key_free,
+	NULL,
 	NULL
 };
 
 int
-cmd_unbind_key_parse(
-    struct cmd *self, void **ptr, int argc, char **argv, char **cause)
+cmd_unbind_key_parse(struct cmd *self, int argc, char **argv, char **cause)
 {
 	struct cmd_unbind_key_data	*data;
 	int				 opt;
 
-	*ptr = data = xmalloc(sizeof *data);
+	self->data = data = xmalloc(sizeof *data);
 
 	while ((opt = getopt(argc, argv, "")) != EOF) {
 		switch (opt) {
@@ -84,9 +84,9 @@ error:
 }
 
 void
-cmd_unbind_key_exec(void *ptr, unused struct cmd_ctx *ctx)
+cmd_unbind_key_exec(struct cmd *self, unused struct cmd_ctx *ctx)
 {
-	struct cmd_unbind_key_data	*data = ptr;
+	struct cmd_unbind_key_data	*data = self->data;
 
 	if (data == NULL)
 		return;
@@ -98,26 +98,26 @@ cmd_unbind_key_exec(void *ptr, unused struct cmd_ctx *ctx)
 }
 
 void
-cmd_unbind_key_send(void *ptr, struct buffer *b)
+cmd_unbind_key_send(struct cmd *self, struct buffer *b)
 {
-	struct cmd_unbind_key_data	*data = ptr;
+	struct cmd_unbind_key_data	*data = self->data;
 
 	buffer_write(b, data, sizeof *data);
 }
 
 void
-cmd_unbind_key_recv(void **ptr, struct buffer *b)
+cmd_unbind_key_recv(struct cmd *self, struct buffer *b)
 {
 	struct cmd_unbind_key_data	*data;
 
-	*ptr = data = xmalloc(sizeof *data);
+	self->data = data = xmalloc(sizeof *data);
 	buffer_read(b, data, sizeof *data);
 }
 
 void
-cmd_unbind_key_free(void *ptr)
+cmd_unbind_key_free(struct cmd *self)
 {
-	struct cmd_unbind_key_data	*data = ptr;
+	struct cmd_unbind_key_data	*data = self->data;
 
 	xfree(data);
 }
diff --git a/cmd-unlink-window.c b/cmd-unlink-window.c
index d06203d3..9b835372 100644
--- a/cmd-unlink-window.c
+++ b/cmd-unlink-window.c
@@ -1,4 +1,4 @@
-/* $Id: cmd-unlink-window.c,v 1.9 2008-06-03 05:35:51 nicm Exp $ */
+/* $Id: cmd-unlink-window.c,v 1.10 2008-06-05 16:35:32 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -24,7 +24,7 @@
  * Unlink a window, unless it would be destroyed by doing so (only one link).
  */
 
-void	cmd_unlink_window_exec(void *, struct cmd_ctx *);
+void	cmd_unlink_window_exec(struct cmd *, struct cmd_ctx *);
 
 const struct cmd_entry cmd_unlink_window_entry = {
 	"unlink-window", "unlinkw",
@@ -35,11 +35,12 @@ const struct cmd_entry cmd_unlink_window_entry = {
 	cmd_windowonly_send,
 	cmd_windowonly_recv,
 	cmd_windowonly_free,
+	NULL,
 	NULL
 };
 
 void
-cmd_unlink_window_exec(void *ptr, struct cmd_ctx *ctx)
+cmd_unlink_window_exec(struct cmd *self, struct cmd_ctx *ctx)
 {
 	struct winlink	*wl;
 	struct session	*s;
@@ -47,7 +48,7 @@ cmd_unlink_window_exec(void *ptr, struct cmd_ctx *ctx)
 	u_int		 i;
 	int		 destroyed;
 
-	if ((wl = cmd_windowonly_get(ptr, ctx, &s)) == NULL)
+	if ((wl = cmd_windowonly_get(self, ctx, &s)) == NULL)
 		return;
 
 	if (wl->window->references == 1) {
diff --git a/cmd.c b/cmd.c
index b88322c3..295f453e 100644
--- a/cmd.c
+++ b/cmd.c
@@ -1,4 +1,4 @@
-/* $Id: cmd.c,v 1.41 2008-06-04 17:54:26 nicm Exp $ */
+/* $Id: cmd.c,v 1.42 2008-06-05 16:35:32 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -114,7 +114,7 @@ cmd_parse(int argc, char **argv, char **cause)
 	cmd = xmalloc(sizeof *cmd);
 	cmd->entry = entry;
 	if (entry->parse != NULL) {
-		if (entry->parse(cmd, &cmd->data, argc, argv, cause) != 0) {
+		if (entry->parse(cmd, argc, argv, cause) != 0) {
 			xfree(cmd);
 			return (NULL);
 		}
@@ -143,7 +143,7 @@ usage:
 void
 cmd_exec(struct cmd *cmd, struct cmd_ctx *ctx)
 {
-	cmd->entry->exec(cmd->data, ctx);
+	cmd->entry->exec(cmd, ctx);
 }
 
 void
@@ -164,7 +164,7 @@ cmd_send(struct cmd *cmd, struct buffer *b)
 	buffer_write(b, &n, sizeof n);
 
 	if (cmd->entry->send != NULL)
-		cmd->entry->send(cmd->data, b);
+		cmd->entry->send(cmd, b);
 }
 
 struct cmd *
@@ -189,7 +189,7 @@ cmd_recv(struct buffer *b)
 	cmd->entry = *entryp;
 
 	if (cmd->entry->recv != NULL)
-		cmd->entry->recv(&cmd->data, b);
+		cmd->entry->recv(cmd, b);
 	return (cmd);
 }
 
@@ -197,7 +197,7 @@ void
 cmd_free(struct cmd *cmd)
 {
 	if (cmd->data != NULL && cmd->entry->free != NULL)
-		cmd->entry->free(cmd->data);
+		cmd->entry->free(cmd);
 	xfree(cmd);
 }
 
diff --git a/key-bindings.c b/key-bindings.c
index f3cb2852..7a0d812e 100644
--- a/key-bindings.c
+++ b/key-bindings.c
@@ -1,4 +1,4 @@
-/* $Id: key-bindings.c,v 1.28 2008-06-03 05:35:51 nicm Exp $ */
+/* $Id: key-bindings.c,v 1.29 2008-06-05 16:35:32 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -122,7 +122,7 @@ key_bindings_init(void)
 		cmd->entry = table[i].entry;
 		cmd->data = NULL;
 		if (cmd->entry->init != NULL)
-			cmd->entry->init(&cmd->data, table[i].key);
+			cmd->entry->init(cmd, table[i].key);
 		key_bindings_add(table[i].key, cmd);
 	}
 }
diff --git a/tmux.c b/tmux.c
index 6efa87cd..6bb55dcc 100644
--- a/tmux.c
+++ b/tmux.c
@@ -1,4 +1,4 @@
-/* $Id: tmux.c,v 1.52 2008-06-04 05:40:35 nicm Exp $ */
+/* $Id: tmux.c,v 1.53 2008-06-05 16:35:32 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -267,7 +267,7 @@ main(int argc, char **argv)
 	if (argc == 0) {
 		cmd = xmalloc(sizeof *cmd);
 		cmd->entry = &cmd_new_session_entry;
-		cmd->entry->init(&cmd->data, 0);
+		cmd->entry->init(cmd, 0);
 	} else if ((cmd = cmd_parse(argc, argv, &cause)) == NULL) {
 		log_warnx("%s", cause);
 		exit(1);
diff --git a/tmux.h b/tmux.h
index c1ab675f..e96e46ed 100644
--- a/tmux.h
+++ b/tmux.h
@@ -1,4 +1,4 @@
-/* $Id: tmux.h,v 1.131 2008-06-04 19:20:10 nicm Exp $ */
+/* $Id: tmux.h,v 1.132 2008-06-05 16:35:32 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -687,12 +687,13 @@ struct cmd_entry {
 #define CMD_CANTNEST 0x2
 	int		 flags;
 
-	int		 (*parse)(struct cmd *, void **, int, char **, char **);
-	void		 (*exec)(void *, struct cmd_ctx *);
-	void		 (*send)(void *, struct buffer *);
-	void	         (*recv)(void **, struct buffer *);
-	void		 (*free)(void *);
-	void		 (*init)(void **, int);
+	int		 (*parse)(struct cmd *, int, char **, char **);
+	void		 (*exec)(struct cmd *, struct cmd_ctx *);
+	void		 (*send)(struct cmd *, struct buffer *);
+	void	         (*recv)(struct cmd *, struct buffer *);
+	void		 (*free)(struct cmd *);
+	void		 (*init)(struct cmd *, int);
+	void 		 (*print)(struct cmd *, char *, size_t);
 };
 
 /* Generic command data. */
@@ -828,26 +829,30 @@ extern const struct cmd_entry cmd_unlink_window_entry;
 
 /* cmd-generic.c */
 #define CMD_CLIENTONLY_USAGE "[-c client-tty]"
-int	cmd_clientonly_parse(struct cmd *, void **, int, char **, char **);
-void	cmd_clientonly_exec(void *, struct cmd_ctx *);
-void	cmd_clientonly_send(void *, struct buffer *);
-void	cmd_clientonly_recv(void **, struct buffer *);
-void	cmd_clientonly_free(void *);
-struct client *cmd_clientonly_get(void *, struct cmd_ctx *);
+int	cmd_clientonly_parse(struct cmd *, int, char **, char **);
+void	cmd_clientonly_exec(struct cmd *, struct cmd_ctx *);
+void	cmd_clientonly_send(struct cmd *, struct buffer *);
+void	cmd_clientonly_recv(struct cmd *, struct buffer *);
+void	cmd_clientonly_free(struct cmd *);
+struct client *cmd_clientonly_get(struct cmd *, struct cmd_ctx *);
+void	cmd_clientonly_print(struct cmd *, char *, size_t);
 #define CMD_SESSIONONLY_USAGE "[-c client-tty|-s session-name]"
-int	cmd_sessiononly_parse(struct cmd *, void **, int, char **, char **);
-void	cmd_sessiononly_exec(void *, struct cmd_ctx *);
-void	cmd_sessiononly_send(void *, struct buffer *);
-void	cmd_sessiononly_recv(void **, struct buffer *);
-void	cmd_sessiononly_free(void *);
-struct session *cmd_sessiononly_get(void *, struct cmd_ctx *);
+int	cmd_sessiononly_parse(struct cmd *, int, char **, char **);
+void	cmd_sessiononly_exec(struct cmd *, struct cmd_ctx *);
+void	cmd_sessiononly_send(struct cmd *, struct buffer *);
+void	cmd_sessiononly_recv(struct cmd *, struct buffer *);
+void	cmd_sessiononly_free(struct cmd *);
+struct session *cmd_sessiononly_get(struct cmd *, struct cmd_ctx *);
+void	cmd_sessiononly_print(struct cmd *, char *, size_t);
 #define CMD_WINDOWONLY_USAGE "[-c client-tty|-s session-name] [-i index]"
-int	cmd_windowonly_parse(struct cmd *, void **, int, char **, char **);
-void	cmd_windowonly_exec(void *, struct cmd_ctx *);
-void	cmd_windowonly_send(void *, struct buffer *);
-void	cmd_windowonly_recv(void **, struct buffer *);
-void	cmd_windowonly_free(void *);
-struct winlink *cmd_windowonly_get(void *, struct cmd_ctx *, struct session **);
+int	cmd_windowonly_parse(struct cmd *, int, char **, char **);
+void	cmd_windowonly_exec(struct cmd *, struct cmd_ctx *);
+void	cmd_windowonly_send(struct cmd *, struct buffer *);
+void	cmd_windowonly_recv(struct cmd *, struct buffer *);
+void	cmd_windowonly_free(struct cmd *);
+struct winlink *cmd_windowonly_get(
+    	    struct cmd *, struct cmd_ctx *, struct session **);
+void	cmd_windowonly_print(struct cmd *, char *, size_t);
 
 /* client.c */
 int	 client_init(const char *, struct client_ctx *, int);