mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 09:26:05 +00:00 
			
		
		
		
	Rewrite command handling to be more generic. Not finished!
This commit is contained in:
		
							
								
								
									
										6
									
								
								CHANGES
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								CHANGES
									
									
									
									
									
								
							@@ -1,5 +1,9 @@
 | 
				
			|||||||
03 October 2007
 | 
					03 October 2007
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* (nicm) Rewrite command handling so commands are much more generic and the
 | 
				
			||||||
 | 
					  same commands are used for command line and keys (although most will probably
 | 
				
			||||||
 | 
					  need to check how they are called). Currently incomplete (only new/detach/ls
 | 
				
			||||||
 | 
					  implemented).
 | 
				
			||||||
* (nicm) String number arguments. So you can do: tmux bind ^Q create "blah".
 | 
					* (nicm) String number arguments. So you can do: tmux bind ^Q create "blah".
 | 
				
			||||||
* (nicm) Key binding. tmux bind key command [argument] and tmux unbind key.
 | 
					* (nicm) Key binding. tmux bind key command [argument] and tmux unbind key.
 | 
				
			||||||
  Key names are in a table in key-string.c, plus A is A, ^A is ctrl-A.
 | 
					  Key names are in a table in key-string.c, plus A is A, ^A is ctrl-A.
 | 
				
			||||||
@@ -99,5 +103,5 @@
 | 
				
			|||||||
  (including mutt, emacs). No status bar yet and no key remapping or other
 | 
					  (including mutt, emacs). No status bar yet and no key remapping or other
 | 
				
			||||||
  customisation.
 | 
					  customisation.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$Id: CHANGES,v 1.25 2007-10-03 12:34:16 nicm Exp $
 | 
					$Id: CHANGES,v 1.26 2007-10-03 21:31:06 nicm Exp $
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										9
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										9
									
								
								Makefile
									
									
									
									
									
								
							@@ -1,4 +1,4 @@
 | 
				
			|||||||
# $Id: Makefile,v 1.12 2007-10-03 11:26:34 nicm Exp $
 | 
					# $Id: Makefile,v 1.13 2007-10-03 21:31:07 nicm Exp $
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.SUFFIXES: .c .o .y .h
 | 
					.SUFFIXES: .c .o .y .h
 | 
				
			||||||
.PHONY: clean
 | 
					.PHONY: clean
 | 
				
			||||||
@@ -17,9 +17,10 @@ DEBUG=
 | 
				
			|||||||
META?= \002 # C-b
 | 
					META?= \002 # C-b
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SRCS= tmux.c server.c server-msg.c server-fn.c buffer.c buffer-poll.c status.c \
 | 
					SRCS= tmux.c server.c server-msg.c server-fn.c buffer.c buffer-poll.c status.c \
 | 
				
			||||||
      xmalloc.c xmalloc-debug.c cmd.c input.c input-keys.c screen.c window.c \
 | 
					      xmalloc.c xmalloc-debug.c input.c input-keys.c screen.c window.c \
 | 
				
			||||||
      session.c local.c log.c client.c client-msg.c client-fn.c op.c op-list.c \
 | 
					      session.c local.c log.c client.c client-msg.c client-fn.c key-string.c \
 | 
				
			||||||
      key-string.c
 | 
					      key-bindings.c \
 | 
				
			||||||
 | 
					      cmd.c cmd-new-session.c cmd-detach-session.c cmd-list-sessions.c 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
YACC= yacc -d
 | 
					YACC= yacc -d
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										5
									
								
								TODO
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								TODO
									
									
									
									
									
								
							@@ -33,8 +33,11 @@
 | 
				
			|||||||
	IPC is arse-about-face: too much overhead. 8-byte header for each
 | 
						IPC is arse-about-face: too much overhead. 8-byte header for each
 | 
				
			||||||
	packet... hrm. already scanning output for \e, could add an extra
 | 
						packet... hrm. already scanning output for \e, could add an extra
 | 
				
			||||||
	byte to it for message
 | 
						byte to it for message
 | 
				
			||||||
- could use bsearch all over the place
 | 
					- could use bsearch all over the place or get rid of smaller tables (clientmsg)
 | 
				
			||||||
- better errors when creating new windows/sessions (how?)
 | 
					- better errors when creating new windows/sessions (how?)
 | 
				
			||||||
 | 
					- commands should have to care less about CMD_KEY
 | 
				
			||||||
 | 
					- CLIENT_HOLD sucks
 | 
				
			||||||
 | 
					- session with CMD_NOSESSION should be an error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- For 0.1 --------------------------------------------------------------------
 | 
					-- For 0.1 --------------------------------------------------------------------
 | 
				
			||||||
- man page
 | 
					- man page
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										17
									
								
								client-msg.c
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								client-msg.c
									
									
									
									
									
								
							@@ -1,4 +1,4 @@
 | 
				
			|||||||
/* $Id: client-msg.c,v 1.5 2007-10-03 10:18:31 nicm Exp $ */
 | 
					/* $Id: client-msg.c,v 1.6 2007-10-03 21:31:07 nicm Exp $ */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
					 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
				
			||||||
@@ -39,7 +39,6 @@ struct client_msg client_msg_table[] = {
 | 
				
			|||||||
	{ MSG_DATA, client_msg_fn_data },
 | 
						{ MSG_DATA, client_msg_fn_data },
 | 
				
			||||||
	{ MSG_DETACH, client_msg_fn_detach },
 | 
						{ MSG_DETACH, client_msg_fn_detach },
 | 
				
			||||||
	{ MSG_ERROR, client_msg_fn_error },
 | 
						{ MSG_ERROR, client_msg_fn_error },
 | 
				
			||||||
	{ MSG_OKAY, client_msg_fn_okay },
 | 
					 | 
				
			||||||
	{ MSG_PAUSE, client_msg_fn_pause },
 | 
						{ MSG_PAUSE, client_msg_fn_pause },
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
#define NCLIENTMSG (sizeof client_msg_table / sizeof client_msg_table[0])
 | 
					#define NCLIENTMSG (sizeof client_msg_table / sizeof client_msg_table[0])
 | 
				
			||||||
@@ -73,7 +72,6 @@ client_msg_dispatch(struct client_ctx *cctx, char **error)
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Data message from server. */
 | 
					 | 
				
			||||||
int
 | 
					int
 | 
				
			||||||
client_msg_fn_data(
 | 
					client_msg_fn_data(
 | 
				
			||||||
    struct hdr *hdr, struct client_ctx *cctx, unused char **error)
 | 
					    struct hdr *hdr, struct client_ctx *cctx, unused char **error)
 | 
				
			||||||
@@ -82,7 +80,6 @@ client_msg_fn_data(
 | 
				
			|||||||
	return (0);
 | 
						return (0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Pause message from server. */
 | 
					 | 
				
			||||||
int
 | 
					int
 | 
				
			||||||
client_msg_fn_pause(
 | 
					client_msg_fn_pause(
 | 
				
			||||||
    struct hdr *hdr, unused struct client_ctx *cctx, unused char **error)
 | 
					    struct hdr *hdr, unused struct client_ctx *cctx, unused char **error)
 | 
				
			||||||
@@ -92,17 +89,6 @@ client_msg_fn_pause(
 | 
				
			|||||||
	return (1);
 | 
						return (1);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Okay message from server. */
 | 
					 | 
				
			||||||
int
 | 
					 | 
				
			||||||
client_msg_fn_okay(
 | 
					 | 
				
			||||||
    struct hdr *hdr, unused struct client_ctx *cctx, unused char **error)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (hdr->size != 0)
 | 
					 | 
				
			||||||
		fatalx("bad MSG_OKAY size");
 | 
					 | 
				
			||||||
	return (0);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Error message from server. */
 | 
					 | 
				
			||||||
int
 | 
					int
 | 
				
			||||||
client_msg_fn_error(struct hdr *hdr, struct client_ctx *cctx, char **error)
 | 
					client_msg_fn_error(struct hdr *hdr, struct client_ctx *cctx, char **error)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -116,7 +102,6 @@ client_msg_fn_error(struct hdr *hdr, struct client_ctx *cctx, char **error)
 | 
				
			|||||||
	return (-1);
 | 
						return (-1);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Detach message from server. */
 | 
					 | 
				
			||||||
int
 | 
					int
 | 
				
			||||||
client_msg_fn_detach(
 | 
					client_msg_fn_detach(
 | 
				
			||||||
    struct hdr *hdr, unused struct client_ctx *cctx, char **error)
 | 
					    struct hdr *hdr, unused struct client_ctx *cctx, char **error)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										93
									
								
								client.c
									
									
									
									
									
								
							
							
						
						
									
										93
									
								
								client.c
									
									
									
									
									
								
							@@ -1,4 +1,4 @@
 | 
				
			|||||||
/* $Id: client.c,v 1.10 2007-10-03 10:18:32 nicm Exp $ */
 | 
					/* $Id: client.c,v 1.11 2007-10-03 21:31:07 nicm Exp $ */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
					 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
				
			||||||
@@ -38,33 +38,19 @@ int	client_process_local(struct client_ctx *, char **);
 | 
				
			|||||||
int
 | 
					int
 | 
				
			||||||
client_init(char *path, struct client_ctx *cctx, int start_server)
 | 
					client_init(char *path, struct client_ctx *cctx, int start_server)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct sockaddr_un	sa;
 | 
						struct sockaddr_un		sa;
 | 
				
			||||||
	struct stat		sb;
 | 
						struct stat			sb;
 | 
				
			||||||
	size_t			sz;
 | 
						struct msg_identify_data	data;
 | 
				
			||||||
	int			mode;
 | 
						struct winsize			ws;
 | 
				
			||||||
	u_int			retries;
 | 
						size_t				sz;
 | 
				
			||||||
 | 
						int				mode;
 | 
				
			||||||
 | 
						u_int				retries;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (path == NULL) {
 | 
						if (path == NULL) {
 | 
				
			||||||
		xasprintf(&path,
 | 
							xasprintf(&path,
 | 
				
			||||||
		    "%s/%s-%lu", _PATH_TMP, __progname, (u_long) getuid());
 | 
							    "%s/%s-%lu", _PATH_TMP, __progname, (u_long) getuid());
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (start_server) {
 | 
					 | 
				
			||||||
		if (!isatty(STDIN_FILENO)) {
 | 
					 | 
				
			||||||
			log_warnx("stdin is not a tty");
 | 
					 | 
				
			||||||
			return (-1);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if (!isatty(STDOUT_FILENO)) {
 | 
					 | 
				
			||||||
			log_warnx("stdout is not a tty");
 | 
					 | 
				
			||||||
			return (-1);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (ioctl(STDIN_FILENO, TIOCGWINSZ, &cctx->ws) == -1) {
 | 
					 | 
				
			||||||
			log_warn("ioctl(TIOCGWINSZ)");
 | 
					 | 
				
			||||||
			return (-1);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	retries = 0;
 | 
						retries = 0;
 | 
				
			||||||
retry:
 | 
					retry:
 | 
				
			||||||
	if (stat(path, &sb) != 0) {
 | 
						if (stat(path, &sb) != 0) {
 | 
				
			||||||
@@ -121,50 +107,18 @@ retry:
 | 
				
			|||||||
	cctx->srv_in = buffer_create(BUFSIZ);
 | 
						cctx->srv_in = buffer_create(BUFSIZ);
 | 
				
			||||||
	cctx->srv_out = buffer_create(BUFSIZ);
 | 
						cctx->srv_out = buffer_create(BUFSIZ);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return (0);
 | 
						if (isatty(STDIN_FILENO) && isatty(STDOUT_FILENO)) {
 | 
				
			||||||
}
 | 
							if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1) {
 | 
				
			||||||
 | 
								log_warn("ioctl(TIOCGWINSZ)");
 | 
				
			||||||
int
 | 
								return (-1);
 | 
				
			||||||
client_flush(struct client_ctx *cctx)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct pollfd	 pfd;
 | 
					 | 
				
			||||||
	struct hdr	 hdr;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for (;;) {
 | 
					 | 
				
			||||||
		pfd.fd = cctx->srv_fd;
 | 
					 | 
				
			||||||
		pfd.events = POLLIN;
 | 
					 | 
				
			||||||
		if (BUFFER_USED(cctx->srv_out) > 0)
 | 
					 | 
				
			||||||
			pfd.events |= POLLOUT;
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
		if (poll(&pfd, 1, INFTIM) == -1) {
 | 
					 | 
				
			||||||
			if (errno == EAGAIN || errno == EINTR)
 | 
					 | 
				
			||||||
				continue;
 | 
					 | 
				
			||||||
			fatal("poll failed");
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (buffer_poll(&pfd, cctx->srv_in, cctx->srv_out) != 0) {
 | 
							data.sx = ws.ws_col;
 | 
				
			||||||
			log_warnx("lost server");
 | 
							data.sy = ws.ws_row;
 | 
				
			||||||
			return (1);
 | 
							client_write_server(cctx, MSG_IDENTIFY, &data, sizeof data);
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (BUFFER_USED(cctx->srv_in) < sizeof hdr)
 | 
					 | 
				
			||||||
			continue;
 | 
					 | 
				
			||||||
		memcpy(&hdr, BUFFER_OUT(cctx->srv_in), sizeof hdr);
 | 
					 | 
				
			||||||
		if (BUFFER_USED(cctx->srv_in) < (sizeof hdr) + hdr.size)
 | 
					 | 
				
			||||||
			continue;
 | 
					 | 
				
			||||||
		buffer_remove(cctx->srv_in, sizeof hdr);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (hdr.type == MSG_OKAY)
 | 
					 | 
				
			||||||
			return (0);
 | 
					 | 
				
			||||||
		if (hdr.type == MSG_ERROR) {
 | 
					 | 
				
			||||||
			if (hdr.size > INT_MAX - 1)
 | 
					 | 
				
			||||||
				fatalx("bad MSG_ERROR size");
 | 
					 | 
				
			||||||
			log_warnx(
 | 
					 | 
				
			||||||
			    "%.*s", (int) hdr.size, BUFFER_OUT(cctx->srv_in));
 | 
					 | 
				
			||||||
			return (1);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		fatalx("unexpected message");
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return (0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int
 | 
					int
 | 
				
			||||||
@@ -244,14 +198,15 @@ local_dead:
 | 
				
			|||||||
void
 | 
					void
 | 
				
			||||||
client_handle_winch(struct client_ctx *cctx)
 | 
					client_handle_winch(struct client_ctx *cctx)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct size_data	data;
 | 
						struct msg_resize_data	data;
 | 
				
			||||||
 | 
						struct winsize		ws;
 | 
				
			||||||
	if (ioctl(STDIN_FILENO, TIOCGWINSZ, &cctx->ws) == -1)
 | 
						
 | 
				
			||||||
 | 
						if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1)
 | 
				
			||||||
		fatal("ioctl failed");
 | 
							fatal("ioctl failed");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	data.sx = cctx->ws.ws_col;
 | 
						data.sx = ws.ws_col;
 | 
				
			||||||
	data.sy = cctx->ws.ws_row;
 | 
						data.sy = ws.ws_row;
 | 
				
			||||||
	client_write_server(cctx, MSG_SIZE, &data, sizeof data);
 | 
						client_write_server(cctx, MSG_RESIZE, &data, sizeof data);
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	sigwinch = 0;
 | 
						sigwinch = 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										137
									
								
								cmd-detach-session.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										137
									
								
								cmd-detach-session.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,137 @@
 | 
				
			|||||||
 | 
					/* $Id: cmd-detach-session.c,v 1.1 2007-10-03 21:31:07 nicm Exp $ */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Permission to use, copy, modify, and distribute this software for any
 | 
				
			||||||
 | 
					 * purpose with or without fee is hereby granted, provided that the above
 | 
				
			||||||
 | 
					 * copyright notice and this permission notice appear in all copies.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 | 
				
			||||||
 | 
					 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 | 
				
			||||||
 | 
					 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 | 
				
			||||||
 | 
					 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
				
			||||||
 | 
					 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
 | 
				
			||||||
 | 
					 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
 | 
				
			||||||
 | 
					 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <sys/types.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <getopt.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "tmux.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Detach session. If called with -a detach all clients attached to specified
 | 
				
			||||||
 | 
					 * session, otherwise detach current session on key press only.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int		 cmd_detach_session_parse(void **, int, char **, char **);
 | 
				
			||||||
 | 
					const char	*cmd_detach_session_usage(void);
 | 
				
			||||||
 | 
					void		 cmd_detach_session_exec(void *, struct cmd_ctx *);
 | 
				
			||||||
 | 
					void		 cmd_detach_session_send(void *, struct buffer *);
 | 
				
			||||||
 | 
					void		 cmd_detach_session_recv(void **, struct buffer *);
 | 
				
			||||||
 | 
					void		 cmd_detach_session_free(void *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct cmd_detach_session_data {
 | 
				
			||||||
 | 
						int	 flag_all;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const struct cmd_entry cmd_detach_session_entry = {
 | 
				
			||||||
 | 
						CMD_DETACHSESSION, "detach-session", "detach", 0,
 | 
				
			||||||
 | 
						cmd_detach_session_parse,
 | 
				
			||||||
 | 
						cmd_detach_session_usage,
 | 
				
			||||||
 | 
						cmd_detach_session_exec,
 | 
				
			||||||
 | 
						cmd_detach_session_send,
 | 
				
			||||||
 | 
						cmd_detach_session_recv,
 | 
				
			||||||
 | 
						cmd_detach_session_free
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					cmd_detach_session_parse(void **ptr, int argc, char **argv, char **cause)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct cmd_detach_session_data	*data;
 | 
				
			||||||
 | 
						int				 opt;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*ptr = data = xmalloc(sizeof *data);
 | 
				
			||||||
 | 
						data->flag_all = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while ((opt = getopt(argc, argv, "a")) != EOF) {
 | 
				
			||||||
 | 
							switch (opt) {
 | 
				
			||||||
 | 
							case 'a':
 | 
				
			||||||
 | 
								data->flag_all = 1;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								goto usage;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}	
 | 
				
			||||||
 | 
						argc -= optind;
 | 
				
			||||||
 | 
						argv -= optind;
 | 
				
			||||||
 | 
						if (argc != 0)
 | 
				
			||||||
 | 
							goto usage;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return (0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					usage:
 | 
				
			||||||
 | 
						usage(cause, "%s", cmd_detach_session_usage());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						xfree(data);
 | 
				
			||||||
 | 
						return (-1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const char *
 | 
				
			||||||
 | 
					cmd_detach_session_usage(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return ("detach-session [-a]");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					cmd_detach_session_exec(void *ptr, struct cmd_ctx *ctx)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct cmd_detach_session_data	*data = ptr, std = { 0 };
 | 
				
			||||||
 | 
						struct client			*c = ctx->client, *cp;
 | 
				
			||||||
 | 
						struct session			*s = ctx->session;
 | 
				
			||||||
 | 
						u_int				 i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (data == NULL)
 | 
				
			||||||
 | 
							data = &std;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (data->flag_all) {
 | 
				
			||||||
 | 
							for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
 | 
				
			||||||
 | 
								cp = ARRAY_ITEM(&clients, i);
 | 
				
			||||||
 | 
								if (cp == NULL || cp->session != s)
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
								server_write_client(cp, MSG_DETACH, NULL, 0);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else if (ctx->flags & CMD_KEY)
 | 
				
			||||||
 | 
							server_write_client(c, MSG_DETACH, NULL, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!(ctx->flags & CMD_KEY))
 | 
				
			||||||
 | 
							server_write_client(c, MSG_EXIT, NULL, 0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					cmd_detach_session_send(void *ptr, struct buffer *b)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct cmd_detach_session_data	*data = ptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						buffer_write(b, data, sizeof *data);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					cmd_detach_session_recv(void **ptr, struct buffer *b)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct cmd_detach_session_data	*data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*ptr = data = xmalloc(sizeof *data);
 | 
				
			||||||
 | 
						buffer_read(b, data, sizeof *data);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					cmd_detach_session_free(void *ptr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct cmd_detach_session_data	*data = ptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						xfree(data);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										70
									
								
								cmd-list-sessions.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								cmd-list-sessions.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,70 @@
 | 
				
			|||||||
 | 
					/* $Id: cmd-list-sessions.c,v 1.1 2007-10-03 21:31:07 nicm Exp $ */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Permission to use, copy, modify, and distribute this software for any
 | 
				
			||||||
 | 
					 * purpose with or without fee is hereby granted, provided that the above
 | 
				
			||||||
 | 
					 * copyright notice and this permission notice appear in all copies.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 | 
				
			||||||
 | 
					 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 | 
				
			||||||
 | 
					 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 | 
				
			||||||
 | 
					 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
				
			||||||
 | 
					 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
 | 
				
			||||||
 | 
					 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
 | 
				
			||||||
 | 
					 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <sys/types.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <getopt.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "tmux.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * List all sessions.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int		 cmd_list_sessions_parse(void **, int, char **, char **);
 | 
				
			||||||
 | 
					const char	*cmd_list_sessions_usage(void);
 | 
				
			||||||
 | 
					void		 cmd_list_sessions_exec(void *, struct cmd_ctx *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const struct cmd_entry cmd_list_sessions_entry = {
 | 
				
			||||||
 | 
						CMD_LISTSESSIONS, "list-sessions", "ls", CMD_NOSESSION,
 | 
				
			||||||
 | 
						NULL,
 | 
				
			||||||
 | 
						NULL,
 | 
				
			||||||
 | 
						cmd_list_sessions_exec,
 | 
				
			||||||
 | 
						NULL,
 | 
				
			||||||
 | 
						NULL,
 | 
				
			||||||
 | 
						NULL
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					cmd_list_sessions_exec(unused void *ptr, struct cmd_ctx *ctx)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct client	*c = ctx->client;
 | 
				
			||||||
 | 
						struct session	*s = ctx->session;
 | 
				
			||||||
 | 
						char		*tim;
 | 
				
			||||||
 | 
						u_int		 i, j, n;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
 | 
				
			||||||
 | 
							s = ARRAY_ITEM(&sessions, i);
 | 
				
			||||||
 | 
							if (s == NULL)
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							n = 0;
 | 
				
			||||||
 | 
							for (j = 0; j < ARRAY_LENGTH(&s->windows); j++) {
 | 
				
			||||||
 | 
								if (ARRAY_ITEM(&s->windows, j) != NULL)
 | 
				
			||||||
 | 
									n++;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							tim = ctime(&s->tim);
 | 
				
			||||||
 | 
							*strchr(tim, '\n') = '\0';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ctx->print(ctx, "%s: %u windows (created %s)", s->name, n, tim);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!(ctx->flags & CMD_KEY))
 | 
				
			||||||
 | 
							server_write_client(c, MSG_EXIT, NULL, 0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										162
									
								
								cmd-new-session.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										162
									
								
								cmd-new-session.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,162 @@
 | 
				
			|||||||
 | 
					/* $Id: cmd-new-session.c,v 1.1 2007-10-03 21:31:07 nicm Exp $ */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Permission to use, copy, modify, and distribute this software for any
 | 
				
			||||||
 | 
					 * purpose with or without fee is hereby granted, provided that the above
 | 
				
			||||||
 | 
					 * copyright notice and this permission notice appear in all copies.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 | 
				
			||||||
 | 
					 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 | 
				
			||||||
 | 
					 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 | 
				
			||||||
 | 
					 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
				
			||||||
 | 
					 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
 | 
				
			||||||
 | 
					 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
 | 
				
			||||||
 | 
					 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <sys/types.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <getopt.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "tmux.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Create a new session and attach to the current terminal unless -d is given.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int		 cmd_new_session_parse(void **, int, char **, char **);
 | 
				
			||||||
 | 
					const char	*cmd_new_session_usage(void);
 | 
				
			||||||
 | 
					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 *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct cmd_new_session_data {
 | 
				
			||||||
 | 
						char	*name;
 | 
				
			||||||
 | 
						int	 flag_detached;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const struct cmd_entry cmd_new_session_entry = {
 | 
				
			||||||
 | 
						CMD_NEWSESSION, "new-session", "new", CMD_STARTSERVER|CMD_NOSESSION,
 | 
				
			||||||
 | 
						cmd_new_session_parse,
 | 
				
			||||||
 | 
						cmd_new_session_usage,
 | 
				
			||||||
 | 
						cmd_new_session_exec, 
 | 
				
			||||||
 | 
						cmd_new_session_send,
 | 
				
			||||||
 | 
						cmd_new_session_recv,
 | 
				
			||||||
 | 
						cmd_new_session_free
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					cmd_new_session_parse(void **ptr, int argc, char **argv, char **cause)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct cmd_new_session_data	*data;
 | 
				
			||||||
 | 
						int				 opt;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*ptr = data = xmalloc(sizeof *data);
 | 
				
			||||||
 | 
						data->flag_detached = 0;
 | 
				
			||||||
 | 
						data->name = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while ((opt = getopt(argc, argv, "ds:")) != EOF) {
 | 
				
			||||||
 | 
							switch (opt) {
 | 
				
			||||||
 | 
							case 'd':
 | 
				
			||||||
 | 
								data->flag_detached = 1;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case 's':
 | 
				
			||||||
 | 
								data->name = xstrdup(optarg);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								goto usage;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}	
 | 
				
			||||||
 | 
						argc -= optind;
 | 
				
			||||||
 | 
						argv -= optind;
 | 
				
			||||||
 | 
						if (argc != 0)
 | 
				
			||||||
 | 
							goto usage;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return (0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					usage:
 | 
				
			||||||
 | 
						usage(cause, "%s", cmd_new_session_usage());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (data->name != NULL)
 | 
				
			||||||
 | 
							xfree(data->name);
 | 
				
			||||||
 | 
						xfree(data);
 | 
				
			||||||
 | 
						return (-1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const char *
 | 
				
			||||||
 | 
					cmd_new_session_usage(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return ("new-session [-d] [-n session name]");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					cmd_new_session_exec(void *ptr, struct cmd_ctx *ctx)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct cmd_new_session_data	*data = ptr, std = { NULL, 0 };
 | 
				
			||||||
 | 
						struct client			*c = ctx->client;
 | 
				
			||||||
 | 
						u_int				 sy;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						if (data == NULL)
 | 
				
			||||||
 | 
							data = &std;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ctx->flags & CMD_KEY)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!data->flag_detached && !(c->flags & CLIENT_TERMINAL)) {
 | 
				
			||||||
 | 
							ctx->error(ctx, "not a terminal");
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (data->name != NULL && session_find(data->name) != NULL) {
 | 
				
			||||||
 | 
							ctx->error(ctx, "duplicate session: %s", data->name);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sy = c->sy;
 | 
				
			||||||
 | 
						if (sy < status_lines)
 | 
				
			||||||
 | 
							sy = status_lines + 1;
 | 
				
			||||||
 | 
						sy -= status_lines;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						c->session = session_create(data->name, default_command, c->sx, sy);
 | 
				
			||||||
 | 
						if (c->session == NULL)
 | 
				
			||||||
 | 
							fatalx("session_create failed");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (data->flag_detached)
 | 
				
			||||||
 | 
							server_write_client(c, MSG_EXIT, NULL, 0);
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
							server_write_client(c, MSG_READY, NULL, 0);
 | 
				
			||||||
 | 
							server_draw_client(c);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					cmd_new_session_send(void *ptr, struct buffer *b)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct cmd_new_session_data	*data = ptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						buffer_write(b, data, sizeof *data);
 | 
				
			||||||
 | 
						cmd_send_string(b, data->name);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					cmd_new_session_recv(void **ptr, struct buffer *b)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct cmd_new_session_data	*data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*ptr = data = xmalloc(sizeof *data);
 | 
				
			||||||
 | 
						buffer_read(b, data, sizeof *data);
 | 
				
			||||||
 | 
						data->name = cmd_recv_string(b);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					cmd_new_session_free(void *ptr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct cmd_new_session_data	*data = ptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (data->name != NULL)
 | 
				
			||||||
 | 
							xfree(data->name);
 | 
				
			||||||
 | 
						xfree(data);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										330
									
								
								cmd.c
									
									
									
									
									
								
							
							
						
						
									
										330
									
								
								cmd.c
									
									
									
									
									
								
							@@ -1,4 +1,4 @@
 | 
				
			|||||||
/* $Id: cmd.c,v 1.4 2007-10-03 12:43:47 nicm Exp $ */
 | 
					/* $Id: cmd.c,v 1.5 2007-10-03 21:31:07 nicm Exp $ */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
					 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
				
			||||||
@@ -18,243 +18,163 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include <sys/types.h>
 | 
					#include <sys/types.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <stdlib.h>
 | 
					#include <getopt.h>
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "tmux.h"
 | 
					#include "tmux.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int	cmd_prefix = META;
 | 
					const struct cmd_entry *cmd_table[] = {
 | 
				
			||||||
 | 
						&cmd_detach_session_entry,
 | 
				
			||||||
void	cmd_fn_detach(struct client *, struct cmd *);
 | 
						&cmd_list_sessions_entry,
 | 
				
			||||||
void	cmd_fn_last(struct client *, struct cmd *);
 | 
						&cmd_new_session_entry,
 | 
				
			||||||
void	cmd_fn_meta(struct client *, struct cmd *);
 | 
						NULL
 | 
				
			||||||
void	cmd_fn_new(struct client *, struct cmd *);
 | 
					 | 
				
			||||||
void	cmd_fn_next(struct client *, struct cmd *);
 | 
					 | 
				
			||||||
void	cmd_fn_previous(struct client *, struct cmd *);
 | 
					 | 
				
			||||||
void	cmd_fn_refresh(struct client *, struct cmd *);
 | 
					 | 
				
			||||||
void	cmd_fn_select(struct client *, struct cmd *);
 | 
					 | 
				
			||||||
void	cmd_fn_info(struct client *, struct cmd *);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const struct cmd cmd_default[] = {
 | 
					 | 
				
			||||||
	{ '0', cmd_fn_select, 0, NULL },
 | 
					 | 
				
			||||||
	{ '1', cmd_fn_select, 1, NULL },
 | 
					 | 
				
			||||||
	{ '2', cmd_fn_select, 2, NULL },
 | 
					 | 
				
			||||||
	{ '3', cmd_fn_select, 3, NULL },
 | 
					 | 
				
			||||||
	{ '4', cmd_fn_select, 4, NULL },
 | 
					 | 
				
			||||||
	{ '5', cmd_fn_select, 5, NULL },
 | 
					 | 
				
			||||||
	{ '6', cmd_fn_select, 6, NULL },
 | 
					 | 
				
			||||||
	{ '7', cmd_fn_select, 7, NULL },
 | 
					 | 
				
			||||||
	{ '8', cmd_fn_select, 8, NULL },
 | 
					 | 
				
			||||||
	{ '9', cmd_fn_select, 9, NULL },
 | 
					 | 
				
			||||||
	{ 'C', cmd_fn_new, 0, NULL },
 | 
					 | 
				
			||||||
	{ 'c', cmd_fn_new, 0, NULL },
 | 
					 | 
				
			||||||
	{ 'D', cmd_fn_detach, 0, NULL },
 | 
					 | 
				
			||||||
	{ 'd', cmd_fn_detach, 0, NULL },
 | 
					 | 
				
			||||||
	{ 'N', cmd_fn_next, 0, NULL },
 | 
					 | 
				
			||||||
	{ 'n', cmd_fn_next, 0, NULL },
 | 
					 | 
				
			||||||
	{ 'P', cmd_fn_previous, 0, NULL },
 | 
					 | 
				
			||||||
	{ 'p', cmd_fn_previous, 0, NULL },
 | 
					 | 
				
			||||||
	{ 'R', cmd_fn_refresh, 0, NULL },
 | 
					 | 
				
			||||||
	{ 'r', cmd_fn_refresh, 0, NULL },
 | 
					 | 
				
			||||||
	{ 'L', cmd_fn_last, 0, NULL },
 | 
					 | 
				
			||||||
	{ 'l', cmd_fn_last, 0, NULL },
 | 
					 | 
				
			||||||
	{ 'I', cmd_fn_info, 0, NULL },
 | 
					 | 
				
			||||||
	{ 'i', cmd_fn_info, 0, NULL },
 | 
					 | 
				
			||||||
	{ META, cmd_fn_meta, 0, NULL },
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
u_int	cmd_count = (sizeof cmd_default / sizeof cmd_default[0]);
 | 
					 | 
				
			||||||
struct cmd *cmd_table;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
const struct bind cmd_bind_table[] = {
 | 
					struct cmd *
 | 
				
			||||||
	{ "detach", 	cmd_fn_detach, 0 },
 | 
					cmd_parse(int argc, char **argv, char **cause)
 | 
				
			||||||
	{ "info",	cmd_fn_info, 0 },
 | 
					 | 
				
			||||||
	{ "last",	cmd_fn_last, 0 },
 | 
					 | 
				
			||||||
	{ "meta",	cmd_fn_meta, 0 },
 | 
					 | 
				
			||||||
	{ "new", 	cmd_fn_new, BIND_STRING|BIND_USER },
 | 
					 | 
				
			||||||
	{ "next",	cmd_fn_next, 0 },
 | 
					 | 
				
			||||||
	{ "previous", 	cmd_fn_previous, 0 },
 | 
					 | 
				
			||||||
	{ "refresh",	cmd_fn_refresh, 0 },
 | 
					 | 
				
			||||||
	{ "select", 	cmd_fn_select, BIND_NUMBER|BIND_USER },
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
#define NCMDBIND (sizeof cmd_bind_table / sizeof cmd_bind_table[0])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const struct bind *
 | 
					 | 
				
			||||||
cmd_lookup_bind(const char *name)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	const struct bind	*bind;
 | 
						const struct cmd_entry **this, *entry;
 | 
				
			||||||
	u_int		         i;
 | 
						struct cmd	        *cmd;
 | 
				
			||||||
 | 
						int			 opt;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (i = 0; i < NCMDBIND; i++) {
 | 
						*cause = NULL;
 | 
				
			||||||
		bind = cmd_bind_table + i;
 | 
						if (argc == 0)
 | 
				
			||||||
		if (strcmp(bind->name, name) == 0)
 | 
							return (NULL);
 | 
				
			||||||
			return (bind);
 | 
					
 | 
				
			||||||
 | 
						entry = NULL;
 | 
				
			||||||
 | 
						for (this = cmd_table; *this != NULL; this++) {
 | 
				
			||||||
 | 
							if (strcmp((*this)->alias, argv[0]) == 0) {
 | 
				
			||||||
 | 
								entry = *this;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (strncmp((*this)->name, argv[0], strlen(argv[0])) != 0)
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
							if (entry != NULL) {
 | 
				
			||||||
 | 
								xasprintf(cause, "ambiguous command: %s", argv[0]);
 | 
				
			||||||
 | 
								return (NULL);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							entry = *this;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if (entry == NULL) {
 | 
				
			||||||
 | 
							xasprintf(cause, "unknown command: %s", argv[0]);
 | 
				
			||||||
 | 
							return (NULL);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						optind = 1;
 | 
				
			||||||
 | 
						if (entry->parse == NULL) {
 | 
				
			||||||
 | 
							while ((opt = getopt(argc, argv, "")) != EOF) {
 | 
				
			||||||
 | 
								switch (opt) {
 | 
				
			||||||
 | 
								default:
 | 
				
			||||||
 | 
									goto usage;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							argc -= optind;
 | 
				
			||||||
 | 
							argv += optind;
 | 
				
			||||||
 | 
							if (argc != 0)
 | 
				
			||||||
 | 
								goto usage;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cmd = xmalloc(sizeof *cmd);
 | 
				
			||||||
 | 
						cmd->entry = entry;
 | 
				
			||||||
 | 
						if (entry->parse != NULL) {
 | 
				
			||||||
 | 
							if (entry->parse(&cmd->data, argc, argv, cause) != 0) {
 | 
				
			||||||
 | 
								xfree(cmd);
 | 
				
			||||||
 | 
								return (NULL);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return (cmd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					usage:
 | 
				
			||||||
 | 
						if (entry->usage == NULL)
 | 
				
			||||||
 | 
							usage(cause, "%s", entry->name);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							usage(cause, "%s", entry->usage());
 | 
				
			||||||
	return (NULL);
 | 
						return (NULL);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
cmd_add_bind(int key, u_int num, char *str, const struct bind *bind)
 | 
					cmd_exec(struct cmd *cmd, struct cmd_ctx *ctx)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct cmd	*cmd = NULL;
 | 
						return (cmd->entry->exec(cmd->data, ctx));
 | 
				
			||||||
	u_int		 i;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for (i = 0; i < cmd_count; i++) {
 | 
					 | 
				
			||||||
		cmd = cmd_table + i;
 | 
					 | 
				
			||||||
		if (cmd->key == key)
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (i == cmd_count) {
 | 
					 | 
				
			||||||
		for (i = 0; i < cmd_count; i++) {
 | 
					 | 
				
			||||||
			cmd = cmd_table + i;
 | 
					 | 
				
			||||||
			if (cmd->key == KEYC_NONE)
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if (i == cmd_count) {
 | 
					 | 
				
			||||||
			cmd_count++;
 | 
					 | 
				
			||||||
			cmd_table = xrealloc(cmd_table,
 | 
					 | 
				
			||||||
			    cmd_count, sizeof cmd_table[0]);
 | 
					 | 
				
			||||||
			cmd = cmd_table + cmd_count - 1;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	cmd->key = key;
 | 
					 | 
				
			||||||
	cmd->fn = bind->fn;
 | 
					 | 
				
			||||||
	if (bind->flags & BIND_USER) {
 | 
					 | 
				
			||||||
		if (bind->flags & BIND_STRING)
 | 
					 | 
				
			||||||
			cmd->str = xstrdup(str);
 | 
					 | 
				
			||||||
		if (bind->flags & BIND_NUMBER)
 | 
					 | 
				
			||||||
			cmd->num = num;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
cmd_remove_bind(int key)
 | 
					cmd_send(struct cmd *cmd, struct buffer *b)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct cmd	*cmd;
 | 
						buffer_write(b, &cmd->entry->type, sizeof cmd->entry->type);
 | 
				
			||||||
	u_int		 i;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (i = 0; i < cmd_count; i++) {
 | 
						if (cmd->entry->send == NULL)
 | 
				
			||||||
		cmd = cmd_table + i;
 | 
							return;
 | 
				
			||||||
		if (cmd->key == key) {
 | 
						return (cmd->entry->send(cmd->data, b));
 | 
				
			||||||
			cmd->key = KEYC_NONE;
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct cmd *
 | 
				
			||||||
 | 
					cmd_recv(struct buffer *b)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const struct cmd_entry **this, *entry;
 | 
				
			||||||
 | 
						struct cmd   	        *cmd;
 | 
				
			||||||
 | 
						enum cmd_type		 type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						buffer_read(b, &type, sizeof type);
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						entry = NULL;
 | 
				
			||||||
 | 
						for (this = cmd_table; *this != NULL; this++) {
 | 
				
			||||||
 | 
							if ((*this)->type == type) {
 | 
				
			||||||
 | 
								entry = *this;
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if (*this == NULL)
 | 
				
			||||||
 | 
							return (NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cmd = xmalloc(sizeof *cmd);
 | 
				
			||||||
 | 
						cmd->entry = entry;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (cmd->entry->recv != NULL)
 | 
				
			||||||
 | 
							cmd->entry->recv(&cmd->data, b);
 | 
				
			||||||
 | 
						return (cmd);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
cmd_init(void)
 | 
					cmd_free(struct cmd *cmd)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	cmd_table = xmalloc(sizeof cmd_default);
 | 
						if (cmd->entry->free != NULL)
 | 
				
			||||||
	memcpy(cmd_table, cmd_default, sizeof cmd_default);
 | 
							cmd->entry->free(cmd->data);
 | 
				
			||||||
 | 
						xfree(cmd);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
cmd_free(void)
 | 
					cmd_send_string(struct buffer *b, const char *s)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	/* XXX free strings */
 | 
						size_t	n;
 | 
				
			||||||
	xfree(cmd_table);
 | 
						
 | 
				
			||||||
}
 | 
						if (s == NULL) {
 | 
				
			||||||
 | 
							n = 0;
 | 
				
			||||||
void
 | 
							buffer_write(b, &n, sizeof n);
 | 
				
			||||||
cmd_dispatch(struct client *c, int key)
 | 
							return;
 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct cmd	*cmd;
 | 
					 | 
				
			||||||
	u_int		 i;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for (i = 0; i < cmd_count; i++) {
 | 
					 | 
				
			||||||
		cmd = cmd_table + i;
 | 
					 | 
				
			||||||
		if (cmd->key != KEYC_NONE && cmd->key == key)
 | 
					 | 
				
			||||||
			cmd->fn(c, cmd);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						n = strlen(s) + 1;
 | 
				
			||||||
 | 
						buffer_write(b, &n, sizeof n);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						buffer_write(b, s, n);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					char *
 | 
				
			||||||
cmd_fn_new(struct client *c, struct cmd *cmd)
 | 
					cmd_recv_string(struct buffer *b)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	char	*s;
 | 
						char   *s;
 | 
				
			||||||
 | 
						size_t	n;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	s = cmd->str;
 | 
						buffer_read(b, &n, sizeof n);
 | 
				
			||||||
	if (s == NULL)
 | 
					
 | 
				
			||||||
		s = default_command;
 | 
						if (n == 0)
 | 
				
			||||||
	if (session_new(c->session, s, c->sx, c->sy) != 0)
 | 
							return (NULL);
 | 
				
			||||||
		server_write_message(c, "%s failed", s); /* XXX */
 | 
						
 | 
				
			||||||
	else
 | 
						s = xmalloc(n);
 | 
				
			||||||
		server_draw_client(c, 0, c->sy - 1);
 | 
						buffer_read(b, s, n);
 | 
				
			||||||
}
 | 
						s[n - 1] = '\0';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
						return (s);
 | 
				
			||||||
cmd_fn_detach(struct client *c, unused struct cmd *cmd)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	server_write_client(c, MSG_DETACH, NULL, 0);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void
 | 
					 | 
				
			||||||
cmd_fn_last(struct client *c, unused struct cmd *cmd)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (session_last(c->session) == 0)
 | 
					 | 
				
			||||||
		server_window_changed(c);
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
		server_write_message(c, "No last window"); 
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void
 | 
					 | 
				
			||||||
cmd_fn_meta(struct client *c, unused struct cmd *cmd)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	window_key(c->session->window, cmd_prefix);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void
 | 
					 | 
				
			||||||
cmd_fn_next(struct client *c, unused struct cmd *cmd)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (session_next(c->session) == 0)
 | 
					 | 
				
			||||||
		server_window_changed(c);
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
		server_write_message(c, "No next window"); 
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void
 | 
					 | 
				
			||||||
cmd_fn_previous(struct client *c, unused struct cmd *cmd)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (session_previous(c->session) == 0)
 | 
					 | 
				
			||||||
		server_window_changed(c);
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
		server_write_message(c, "No previous window"); 
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void
 | 
					 | 
				
			||||||
cmd_fn_refresh(struct client *c, unused struct cmd *cmd)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	server_draw_client(c, 0, c->sy - 1);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void
 | 
					 | 
				
			||||||
cmd_fn_select(struct client *c, struct cmd *cmd)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (session_select(c->session, cmd->num) == 0)
 | 
					 | 
				
			||||||
		server_window_changed(c);
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
		server_write_message(c, "Window %u not present", cmd->num);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void
 | 
					 | 
				
			||||||
cmd_fn_info(struct client *c, unused struct cmd *cmd)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct window	*w;
 | 
					 | 
				
			||||||
	char 		*buf;
 | 
					 | 
				
			||||||
	size_t		 len;
 | 
					 | 
				
			||||||
	u_int		 i;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	len = c->sx + 1;
 | 
					 | 
				
			||||||
	buf = xmalloc(len);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	w = c->session->window;
 | 
					 | 
				
			||||||
	window_index(&c->session->windows, w, &i);
 | 
					 | 
				
			||||||
	xsnprintf(buf, len, "%u:%s \"%s\" (size %u,%u) (cursor %u,%u) "
 | 
					 | 
				
			||||||
	    "(region %u,%u)", i, w->name, w->screen.title, w->screen.sx,
 | 
					 | 
				
			||||||
	    w->screen.sy, w->screen.cx, w->screen.cy, w->screen.ry_upper,
 | 
					 | 
				
			||||||
	    w->screen.ry_lower);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	server_write_message(c, "%s", buf);
 | 
					 | 
				
			||||||
	xfree(buf);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										214
									
								
								key-bindings.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										214
									
								
								key-bindings.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,214 @@
 | 
				
			|||||||
 | 
					/* $Id: key-bindings.c,v 1.1 2007-10-03 21:31:07 nicm Exp $ */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Permission to use, copy, modify, and distribute this software for any
 | 
				
			||||||
 | 
					 * purpose with or without fee is hereby granted, provided that the above
 | 
				
			||||||
 | 
					 * copyright notice and this permission notice appear in all copies.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 | 
				
			||||||
 | 
					 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 | 
				
			||||||
 | 
					 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 | 
				
			||||||
 | 
					 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
				
			||||||
 | 
					 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
 | 
				
			||||||
 | 
					 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
 | 
				
			||||||
 | 
					 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <sys/types.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "tmux.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ARRAY_DECL(, struct binding *) key_bindings;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void	key_bindings_error(struct cmd_ctx *, const char *, ...);
 | 
				
			||||||
 | 
					void	key_bindings_print(struct cmd_ctx *, const char *, ...);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					key_bindings_add(int key, struct cmd *cmd)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct binding	*bd;
 | 
				
			||||||
 | 
						u_int		 i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bd = NULL;
 | 
				
			||||||
 | 
						for (i = 0; i < ARRAY_LENGTH(&key_bindings); i++) {
 | 
				
			||||||
 | 
							bd = ARRAY_ITEM(&key_bindings, i);
 | 
				
			||||||
 | 
							if (bd->key == key)
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (i == ARRAY_LENGTH(&key_bindings)) {
 | 
				
			||||||
 | 
							bd = xmalloc(sizeof *bd);
 | 
				
			||||||
 | 
							ARRAY_ADD(&key_bindings, bd);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bd->key = key;
 | 
				
			||||||
 | 
						bd->cmd = cmd;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					key_bindings_remove(int key)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct binding	*bd;
 | 
				
			||||||
 | 
						u_int		 i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bd = NULL;
 | 
				
			||||||
 | 
						for (i = 0; i < ARRAY_LENGTH(&key_bindings); i++) {
 | 
				
			||||||
 | 
							bd = ARRAY_ITEM(&key_bindings, i);
 | 
				
			||||||
 | 
							if (bd->key == key)
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (i == ARRAY_LENGTH(&key_bindings))
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cmd_free(bd->cmd);
 | 
				
			||||||
 | 
						xfree(bd);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					key_bindings_init(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct {
 | 
				
			||||||
 | 
							int			 key;
 | 
				
			||||||
 | 
							const struct cmd_entry	*entry;
 | 
				
			||||||
 | 
						} table[] = {
 | 
				
			||||||
 | 
							{ 'D', &cmd_detach_session_entry },
 | 
				
			||||||
 | 
							{ 'd', &cmd_detach_session_entry },
 | 
				
			||||||
 | 
							{ 'S', &cmd_list_sessions_entry },
 | 
				
			||||||
 | 
							{ 's', &cmd_list_sessions_entry },
 | 
				
			||||||
 | 
					/*		{ 'C', &cmd_new_window },
 | 
				
			||||||
 | 
							{ 'c', &cmd_new_window },
 | 
				
			||||||
 | 
							{ 'N', &cmd_next_window },
 | 
				
			||||||
 | 
							{ 'n', &cmd_next_window },
 | 
				
			||||||
 | 
							{ 'P', &cmd_previous_window },
 | 
				
			||||||
 | 
							{ 'p', &cmd_previous_window },
 | 
				
			||||||
 | 
							{ 'R', &cmd_refresh_client },
 | 
				
			||||||
 | 
							{ 'r', &cmd_refresh_client },
 | 
				
			||||||
 | 
							{ 'L', &cmd_last_window },
 | 
				
			||||||
 | 
							{ 'l', &cmd_last_window },
 | 
				
			||||||
 | 
							{ 'I', &cmd_windo_info },
 | 
				
			||||||
 | 
							{ 'i', &cmd_window_info },
 | 
				
			||||||
 | 
							{ META, &cmd_meta_entry },
 | 
				
			||||||
 | 
					*//*	{ '0', cmdx_fn_select, 0, NULL },
 | 
				
			||||||
 | 
						{ '1', cmdx_fn_select, 1, NULL },
 | 
				
			||||||
 | 
						{ '2', cmdx_fn_select, 2, NULL },
 | 
				
			||||||
 | 
						{ '3', cmdx_fn_select, 3, NULL },
 | 
				
			||||||
 | 
						{ '4', cmdx_fn_select, 4, NULL },
 | 
				
			||||||
 | 
						{ '5', cmdx_fn_select, 5, NULL },
 | 
				
			||||||
 | 
						{ '6', cmdx_fn_select, 6, NULL },
 | 
				
			||||||
 | 
						{ '7', cmdx_fn_select, 7, NULL },
 | 
				
			||||||
 | 
						{ '8', cmdx_fn_select, 8, NULL },
 | 
				
			||||||
 | 
						{ '9', cmdx_fn_select, 9, NULL },
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						u_int		 i;
 | 
				
			||||||
 | 
						struct cmd	*cmd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < (sizeof table / sizeof table[0]); i++) {
 | 
				
			||||||
 | 
							cmd = xmalloc(sizeof *cmd);
 | 
				
			||||||
 | 
							cmd->entry = table[i].entry;
 | 
				
			||||||
 | 
							cmd->data = NULL;
 | 
				
			||||||
 | 
							key_bindings_add(table[i].key, cmd);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					key_bindings_free(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct binding	*bd;
 | 
				
			||||||
 | 
						u_int		 i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < ARRAY_LENGTH(&key_bindings); i++) {
 | 
				
			||||||
 | 
							bd = ARRAY_ITEM(&key_bindings, i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							cmd_free(bd->cmd);
 | 
				
			||||||
 | 
							xfree(bd);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						ARRAY_FREEALL(&key_bindings);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					key_bindings_error(struct cmd_ctx *ctx, const char *fmt, ...)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						va_list	ap;
 | 
				
			||||||
 | 
						char   *msg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						va_start(ap, fmt);
 | 
				
			||||||
 | 
						xvasprintf(&msg, fmt, ap);
 | 
				
			||||||
 | 
						va_end(ap);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						server_write_message(ctx->client, msg);
 | 
				
			||||||
 | 
						xfree(msg);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					key_bindings_print(struct cmd_ctx *ctx, const char *fmt, ...)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct client	*c = ctx->client;
 | 
				
			||||||
 | 
						struct hdr	 hdr;
 | 
				
			||||||
 | 
						va_list		 ap;
 | 
				
			||||||
 | 
						char		*msg;
 | 
				
			||||||
 | 
						size_t		 size;
 | 
				
			||||||
 | 
						u_int		 i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						buffer_ensure(c->out, sizeof hdr);
 | 
				
			||||||
 | 
						buffer_add(c->out, sizeof hdr);
 | 
				
			||||||
 | 
						size = BUFFER_USED(c->out);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!(c->flags & CLIENT_HOLD)) {
 | 
				
			||||||
 | 
							input_store_zero(c->out, CODE_CURSOROFF);
 | 
				
			||||||
 | 
							for (i = 0; i < c->session->window->screen.sy; i++) {
 | 
				
			||||||
 | 
								input_store_two(c->out, CODE_CURSORMOVE, i + 1, 1);
 | 
				
			||||||
 | 
								input_store_zero(c->out, CODE_CLEARLINE);
 | 
				
			||||||
 | 
							}			
 | 
				
			||||||
 | 
							input_store_two(c->out, CODE_CURSORMOVE, 1, 1);
 | 
				
			||||||
 | 
							input_store_two(c->out, CODE_ATTRIBUTES, 0, 0x88);
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							c->flags |= CLIENT_HOLD;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						va_start(ap, fmt);
 | 
				
			||||||
 | 
						xvasprintf(&msg, fmt, ap);
 | 
				
			||||||
 | 
						va_end(ap);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						buffer_write(c->out, msg, strlen(msg));
 | 
				
			||||||
 | 
						input_store8(c->out, '\r');
 | 
				
			||||||
 | 
						input_store8(c->out, '\n');
 | 
				
			||||||
 | 
						xfree(msg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						size = BUFFER_USED(c->out) - size;
 | 
				
			||||||
 | 
						hdr.type = MSG_DATA;
 | 
				
			||||||
 | 
						hdr.size = size;
 | 
				
			||||||
 | 
						memcpy(BUFFER_IN(c->out) - size - sizeof hdr, &hdr, sizeof hdr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					key_bindings_dispatch(int key, struct client *c)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct cmd_ctx	 ctx;
 | 
				
			||||||
 | 
						struct binding	*bd;
 | 
				
			||||||
 | 
						u_int		 i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bd = NULL;
 | 
				
			||||||
 | 
						for (i = 0; i < ARRAY_LENGTH(&key_bindings); i++) {
 | 
				
			||||||
 | 
							bd = ARRAY_ITEM(&key_bindings, i);
 | 
				
			||||||
 | 
							if (bd->key == key)
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (i == ARRAY_LENGTH(&key_bindings))
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.session = c->session;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.error = key_bindings_error;
 | 
				
			||||||
 | 
						ctx.print = key_bindings_print;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.client = c;
 | 
				
			||||||
 | 
						ctx.flags = CMD_KEY;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cmd_exec(bd->cmd, &ctx);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										199
									
								
								op-list.c
									
									
									
									
									
								
							
							
						
						
									
										199
									
								
								op-list.c
									
									
									
									
									
								
							@@ -1,199 +0,0 @@
 | 
				
			|||||||
/* $Id: op-list.c,v 1.6 2007-09-29 15:06:00 nicm Exp $ */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Permission to use, copy, modify, and distribute this software for any
 | 
					 | 
				
			||||||
 * purpose with or without fee is hereby granted, provided that the above
 | 
					 | 
				
			||||||
 * copyright notice and this permission notice appear in all copies.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 | 
					 | 
				
			||||||
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 | 
					 | 
				
			||||||
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 | 
					 | 
				
			||||||
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
					 | 
				
			||||||
 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
 | 
					 | 
				
			||||||
 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
 | 
					 | 
				
			||||||
 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <sys/types.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <errno.h>
 | 
					 | 
				
			||||||
#include <getopt.h>
 | 
					 | 
				
			||||||
#include <string.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "tmux.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int
 | 
					 | 
				
			||||||
op_list_sessions(char *path, int argc, unused char **argv)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct client_ctx	cctx;
 | 
					 | 
				
			||||||
	char		       *tim;
 | 
					 | 
				
			||||||
	struct sessions_data    data;
 | 
					 | 
				
			||||||
	struct sessions_entry	ent;
 | 
					 | 
				
			||||||
	struct pollfd		pfd;
 | 
					 | 
				
			||||||
	struct hdr		hdr;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (argc != 1)
 | 
					 | 
				
			||||||
		return (usage("list-sessions"));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (client_init(path, &cctx, 0) != 0)
 | 
					 | 
				
			||||||
		return (1);
 | 
					 | 
				
			||||||
	client_write_server(&cctx, MSG_SESSIONS, &data, sizeof data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for (;;) {
 | 
					 | 
				
			||||||
		pfd.fd = cctx.srv_fd;
 | 
					 | 
				
			||||||
		pfd.events = POLLIN;
 | 
					 | 
				
			||||||
		if (BUFFER_USED(cctx.srv_out) > 0)
 | 
					 | 
				
			||||||
			pfd.events |= POLLOUT;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (poll(&pfd, 1, INFTIM) == -1) {
 | 
					 | 
				
			||||||
			if (errno == EAGAIN || errno == EINTR)
 | 
					 | 
				
			||||||
				continue;
 | 
					 | 
				
			||||||
			log_warn("poll");
 | 
					 | 
				
			||||||
			return (-1);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (buffer_poll(&pfd, cctx.srv_in, cctx.srv_out) != 0) {
 | 
					 | 
				
			||||||
			log_warnx("lost server");
 | 
					 | 
				
			||||||
			return (-1);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (BUFFER_USED(cctx.srv_in) < sizeof hdr)
 | 
					 | 
				
			||||||
			continue;
 | 
					 | 
				
			||||||
		memcpy(&hdr, BUFFER_OUT(cctx.srv_in), sizeof hdr);
 | 
					 | 
				
			||||||
		if (BUFFER_USED(cctx.srv_in) < (sizeof hdr) + hdr.size)
 | 
					 | 
				
			||||||
			continue;
 | 
					 | 
				
			||||||
		buffer_remove(cctx.srv_in, sizeof hdr);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (hdr.type == MSG_ERROR) {
 | 
					 | 
				
			||||||
			if (hdr.size > INT_MAX - 1)
 | 
					 | 
				
			||||||
				fatalx("bad MSG_ERROR size");
 | 
					 | 
				
			||||||
			log_warnx(
 | 
					 | 
				
			||||||
			    "%.*s", (int) hdr.size, BUFFER_OUT(cctx.srv_in));
 | 
					 | 
				
			||||||
			return (1);
 | 
					 | 
				
			||||||
		}		
 | 
					 | 
				
			||||||
		if (hdr.type != MSG_SESSIONS)
 | 
					 | 
				
			||||||
			fatalx("unexpected message");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (hdr.size < sizeof data)
 | 
					 | 
				
			||||||
			fatalx("bad MSG_SESSIONS size");
 | 
					 | 
				
			||||||
		buffer_read(cctx.srv_in, &data, sizeof data);
 | 
					 | 
				
			||||||
		hdr.size -= sizeof data; 
 | 
					 | 
				
			||||||
		if (data.sessions == 0 && hdr.size == 0)
 | 
					 | 
				
			||||||
			return (0);
 | 
					 | 
				
			||||||
		if (hdr.size < data.sessions * sizeof ent)
 | 
					 | 
				
			||||||
			fatalx("bad MSG_SESSIONS size");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		while (data.sessions-- > 0) {
 | 
					 | 
				
			||||||
			buffer_read(cctx.srv_in, &ent, sizeof ent);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			tim = ctime(&ent.tim);
 | 
					 | 
				
			||||||
			*strchr(tim, '\n') = '\0';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			printf("%s: %u windows "
 | 
					 | 
				
			||||||
			    "(created %s)\n", ent.name, ent.windows, tim);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		return (0);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int
 | 
					 | 
				
			||||||
op_list_windows(char *path, int argc, char **argv)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct client_ctx	cctx;
 | 
					 | 
				
			||||||
	char			name[MAXNAMELEN];
 | 
					 | 
				
			||||||
	int			opt;
 | 
					 | 
				
			||||||
	struct windows_data	data;
 | 
					 | 
				
			||||||
	struct windows_entry	ent;
 | 
					 | 
				
			||||||
	struct pollfd		pfd;
 | 
					 | 
				
			||||||
	struct hdr		hdr;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	*name = '\0';
 | 
					 | 
				
			||||||
	optind = 1;
 | 
					 | 
				
			||||||
	while ((opt = getopt(argc, argv, "s:?")) != EOF) {
 | 
					 | 
				
			||||||
		switch (opt) {
 | 
					 | 
				
			||||||
		case 's':
 | 
					 | 
				
			||||||
			if (strlcpy(name, optarg, sizeof name) >= sizeof name) {
 | 
					 | 
				
			||||||
				log_warnx("%s: session name too long", optarg);
 | 
					 | 
				
			||||||
				return (1);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		case '?':
 | 
					 | 
				
			||||||
		default:
 | 
					 | 
				
			||||||
			return (usage("list-windows [-s session]"));
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}	
 | 
					 | 
				
			||||||
	argc -= optind;
 | 
					 | 
				
			||||||
	argv += optind;			
 | 
					 | 
				
			||||||
	if (argc != 0)
 | 
					 | 
				
			||||||
		return (usage("list-windows [-s session]"));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (client_init(path, &cctx, 0) != 0)
 | 
					 | 
				
			||||||
		return (1);
 | 
					 | 
				
			||||||
 
 | 
					 | 
				
			||||||
	client_fill_sessid(&data.sid, name);
 | 
					 | 
				
			||||||
	client_write_server(&cctx, MSG_WINDOWS, &data, sizeof data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for (;;) {
 | 
					 | 
				
			||||||
		pfd.fd = cctx.srv_fd;
 | 
					 | 
				
			||||||
		pfd.events = POLLIN;
 | 
					 | 
				
			||||||
		if (BUFFER_USED(cctx.srv_out) > 0)
 | 
					 | 
				
			||||||
			pfd.events |= POLLOUT;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (poll(&pfd, 1, INFTIM) == -1) {
 | 
					 | 
				
			||||||
			if (errno == EAGAIN || errno == EINTR)
 | 
					 | 
				
			||||||
				continue;
 | 
					 | 
				
			||||||
			log_warn("poll");
 | 
					 | 
				
			||||||
			return (-1);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (buffer_poll(&pfd, cctx.srv_in, cctx.srv_out) != 0) {
 | 
					 | 
				
			||||||
			log_warnx("lost server");
 | 
					 | 
				
			||||||
			return (-1);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (BUFFER_USED(cctx.srv_in) < sizeof hdr)
 | 
					 | 
				
			||||||
			continue;
 | 
					 | 
				
			||||||
		memcpy(&hdr, BUFFER_OUT(cctx.srv_in), sizeof hdr);
 | 
					 | 
				
			||||||
		if (BUFFER_USED(cctx.srv_in) < (sizeof hdr) + hdr.size)
 | 
					 | 
				
			||||||
			continue;
 | 
					 | 
				
			||||||
		buffer_remove(cctx.srv_in, sizeof hdr);
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		if (hdr.type == MSG_ERROR) {
 | 
					 | 
				
			||||||
			if (hdr.size > INT_MAX - 1)
 | 
					 | 
				
			||||||
				fatalx("bad MSG_ERROR size");
 | 
					 | 
				
			||||||
			log_warnx(
 | 
					 | 
				
			||||||
			    "%.*s", (int) hdr.size, BUFFER_OUT(cctx.srv_in));
 | 
					 | 
				
			||||||
			return (1);
 | 
					 | 
				
			||||||
		}		
 | 
					 | 
				
			||||||
		if (hdr.type != MSG_WINDOWS)
 | 
					 | 
				
			||||||
			fatalx("unexpected message");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (hdr.size < sizeof data)
 | 
					 | 
				
			||||||
			fatalx("bad MSG_WINDOWS size");
 | 
					 | 
				
			||||||
		buffer_read(cctx.srv_in, &data, sizeof data);
 | 
					 | 
				
			||||||
		hdr.size -= sizeof data; 
 | 
					 | 
				
			||||||
		if (data.windows == 0 && hdr.size == 0) {
 | 
					 | 
				
			||||||
			log_warnx("session not found: %s", name);
 | 
					 | 
				
			||||||
			return (1);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if (hdr.size < data.windows * sizeof ent)
 | 
					 | 
				
			||||||
			fatalx("bad MSG_WINDOWS size");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		while (data.windows-- > 0) {
 | 
					 | 
				
			||||||
			buffer_read(cctx.srv_in, &ent, sizeof ent);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if (*ent.title != '\0') {
 | 
					 | 
				
			||||||
				printf("%u: %s \"%s\" (%s)\n", ent.idx,
 | 
					 | 
				
			||||||
				    ent.name, ent.title, ent.tty);
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				printf("%u: %s (%s)\n",
 | 
					 | 
				
			||||||
				    ent.idx, ent.name, ent.tty);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		return (0);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										271
									
								
								op.c
									
									
									
									
									
								
							
							
						
						
									
										271
									
								
								op.c
									
									
									
									
									
								
							@@ -1,271 +0,0 @@
 | 
				
			|||||||
/* $Id: op.c,v 1.12 2007-10-03 12:43:47 nicm Exp $ */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Permission to use, copy, modify, and distribute this software for any
 | 
					 | 
				
			||||||
 * purpose with or without fee is hereby granted, provided that the above
 | 
					 | 
				
			||||||
 * copyright notice and this permission notice appear in all copies.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 | 
					 | 
				
			||||||
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 | 
					 | 
				
			||||||
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 | 
					 | 
				
			||||||
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
					 | 
				
			||||||
 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
 | 
					 | 
				
			||||||
 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
 | 
					 | 
				
			||||||
 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <sys/types.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <stdlib.h>
 | 
					 | 
				
			||||||
#include <string.h>
 | 
					 | 
				
			||||||
#include <unistd.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "tmux.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int
 | 
					 | 
				
			||||||
op_new_session(char *path, int argc, char **argv)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct new_data	 	data;	
 | 
					 | 
				
			||||||
	struct client_ctx	cctx;
 | 
					 | 
				
			||||||
	char			name[MAXNAMELEN];
 | 
					 | 
				
			||||||
	int			opt, detached;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	*name = '\0';
 | 
					 | 
				
			||||||
	detached = 0;
 | 
					 | 
				
			||||||
	optind = 1;
 | 
					 | 
				
			||||||
	while ((opt = getopt(argc, argv, "s:d?")) != EOF) {
 | 
					 | 
				
			||||||
		switch (opt) {
 | 
					 | 
				
			||||||
		case 's':
 | 
					 | 
				
			||||||
			if (strlcpy(name, optarg, sizeof name) >= sizeof name) {
 | 
					 | 
				
			||||||
				log_warnx("session name too long: %s", optarg);
 | 
					 | 
				
			||||||
				return (1);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		case 'd':
 | 
					 | 
				
			||||||
			detached = 1;
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		case '?':
 | 
					 | 
				
			||||||
		default:
 | 
					 | 
				
			||||||
			return (usage("new-session [-d] [-s session]"));
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}	
 | 
					 | 
				
			||||||
	argc -= optind;
 | 
					 | 
				
			||||||
	argv += optind;			
 | 
					 | 
				
			||||||
	if (argc != 0)
 | 
					 | 
				
			||||||
		return (usage("new-session [-s session]"));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (client_init(path, &cctx, 1) != 0)
 | 
					 | 
				
			||||||
		return (1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	strlcpy(data.name, name, sizeof data.name);
 | 
					 | 
				
			||||||
	data.sx = cctx.ws.ws_col;
 | 
					 | 
				
			||||||
	data.sy = cctx.ws.ws_row;
 | 
					 | 
				
			||||||
	client_write_server(&cctx, MSG_NEW, &data, sizeof data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (detached)
 | 
					 | 
				
			||||||
		return (client_flush(&cctx));
 | 
					 | 
				
			||||||
	return (client_main(&cctx));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int
 | 
					 | 
				
			||||||
op_attach(char *path, int argc, char **argv)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct attach_data	data;
 | 
					 | 
				
			||||||
	struct client_ctx	cctx;
 | 
					 | 
				
			||||||
	char			name[MAXNAMELEN];
 | 
					 | 
				
			||||||
	int			opt;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	*name = '\0';
 | 
					 | 
				
			||||||
	optind = 1;
 | 
					 | 
				
			||||||
	while ((opt = getopt(argc, argv, "s:?")) != EOF) {
 | 
					 | 
				
			||||||
		switch (opt) {
 | 
					 | 
				
			||||||
		case 's':
 | 
					 | 
				
			||||||
			if (strlcpy(name, optarg, sizeof name) >= sizeof name) {
 | 
					 | 
				
			||||||
				log_warnx("session name too long: %s", optarg);
 | 
					 | 
				
			||||||
				return (1);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		case '?':
 | 
					 | 
				
			||||||
		default:
 | 
					 | 
				
			||||||
			return (usage("attach [-s session]"));
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}	
 | 
					 | 
				
			||||||
	argc -= optind;
 | 
					 | 
				
			||||||
	argv += optind;			
 | 
					 | 
				
			||||||
	if (argc != 0)
 | 
					 | 
				
			||||||
		return (usage("attach [-s session]"));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (client_init(path, &cctx, 1) != 0)
 | 
					 | 
				
			||||||
		return (1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	client_fill_sessid(&data.sid, name);
 | 
					 | 
				
			||||||
	data.sx = cctx.ws.ws_col;
 | 
					 | 
				
			||||||
	data.sy = cctx.ws.ws_row;
 | 
					 | 
				
			||||||
	client_write_server(&cctx, MSG_ATTACH, &data, sizeof data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return (client_main(&cctx));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int
 | 
					 | 
				
			||||||
op_rename_window(char *path, int argc, char **argv)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct rename_data	data;	
 | 
					 | 
				
			||||||
	struct client_ctx	cctx;
 | 
					 | 
				
			||||||
	char			sname[MAXNAMELEN];
 | 
					 | 
				
			||||||
	int			opt;  
 | 
					 | 
				
			||||||
	const char	       *errstr;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	*sname = '\0';
 | 
					 | 
				
			||||||
	data.idx = -1;
 | 
					 | 
				
			||||||
	optind = 1;
 | 
					 | 
				
			||||||
	while ((opt = getopt(argc, argv, "i:s:?")) != EOF) {
 | 
					 | 
				
			||||||
		switch (opt) {
 | 
					 | 
				
			||||||
		case 's':
 | 
					 | 
				
			||||||
			if (strlcpy(sname, optarg, sizeof sname) 
 | 
					 | 
				
			||||||
			    >= sizeof sname) {
 | 
					 | 
				
			||||||
				log_warnx("session name too long: %s", optarg);
 | 
					 | 
				
			||||||
				return (1);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		case 'i':
 | 
					 | 
				
			||||||
			data.idx = strtonum(optarg, 0, INT_MAX, &errstr);
 | 
					 | 
				
			||||||
			if (errstr != NULL) {
 | 
					 | 
				
			||||||
				log_warnx(
 | 
					 | 
				
			||||||
				    "window index %s: %s", errstr, optarg); 
 | 
					 | 
				
			||||||
				return (1);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		case '?':
 | 
					 | 
				
			||||||
		default:
 | 
					 | 
				
			||||||
			return (usage(
 | 
					 | 
				
			||||||
			    "rename-window [-s session] [-i index] name"));
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	argc -= optind;
 | 
					 | 
				
			||||||
	argv += optind;
 | 
					 | 
				
			||||||
	if (argc != 1)
 | 
					 | 
				
			||||||
		return (usage("rename-window [-s session] [-i index] name"));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (client_init(path, &cctx, 1) != 0)
 | 
					 | 
				
			||||||
		return (1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	client_fill_sessid(&data.sid, sname);
 | 
					 | 
				
			||||||
	if ((strlcpy(data.newname, argv[0], sizeof data.newname) 
 | 
					 | 
				
			||||||
	    >= sizeof data.newname)) {
 | 
					 | 
				
			||||||
		log_warnx("new window name too long: %s", argv[0]);
 | 
					 | 
				
			||||||
		return (1);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	client_write_server(&cctx, MSG_RENAME, &data, sizeof data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return (client_flush(&cctx));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int
 | 
					 | 
				
			||||||
op_bind_key(char *path, int argc, char **argv)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct bind_data	data;	
 | 
					 | 
				
			||||||
	struct client_ctx	cctx;
 | 
					 | 
				
			||||||
	int			opt;
 | 
					 | 
				
			||||||
	const char	       *errstr;
 | 
					 | 
				
			||||||
	char		       *str;
 | 
					 | 
				
			||||||
	size_t			len;
 | 
					 | 
				
			||||||
 	const struct bind      *bind;
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	optind = 1;
 | 
					 | 
				
			||||||
	while ((opt = getopt(argc, argv, "?")) != EOF) {
 | 
					 | 
				
			||||||
		switch (opt) {
 | 
					 | 
				
			||||||
		default:
 | 
					 | 
				
			||||||
			return (usage("bind-key key command [argument]"));
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	argc -= optind;
 | 
					 | 
				
			||||||
	argv += optind;
 | 
					 | 
				
			||||||
	if (argc != 2 && argc != 3)
 | 
					 | 
				
			||||||
		return (usage("bind-key key command [argument]"));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if ((data.key = key_string_lookup(argv[0])) == KEYC_NONE) {
 | 
					 | 
				
			||||||
		log_warnx("unknown key: %s", argv[0]);
 | 
					 | 
				
			||||||
		return (1);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (strlcpy(data.cmd, argv[1], sizeof data.cmd) >= sizeof data.cmd) {
 | 
					 | 
				
			||||||
		log_warnx("command too long: %s", argv[1]);
 | 
					 | 
				
			||||||
		return (1);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if ((bind = cmd_lookup_bind(data.cmd)) == NULL) {
 | 
					 | 
				
			||||||
		log_warnx("unknown command: %s", data.cmd);
 | 
					 | 
				
			||||||
		return (1);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	str = NULL;
 | 
					 | 
				
			||||||
	len = 0;
 | 
					 | 
				
			||||||
	if (bind->flags & BIND_USER) {
 | 
					 | 
				
			||||||
		if (argc != 3) {
 | 
					 | 
				
			||||||
			log_warnx("%s requires an argument", data.cmd);
 | 
					 | 
				
			||||||
			return (1);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		data.flags |= BIND_USER;
 | 
					 | 
				
			||||||
		if (bind->flags & BIND_STRING) {
 | 
					 | 
				
			||||||
			data.flags |= BIND_STRING;
 | 
					 | 
				
			||||||
			str = argv[2];
 | 
					 | 
				
			||||||
			len = strlen(str);
 | 
					 | 
				
			||||||
		} else if (bind->flags & BIND_NUMBER) {
 | 
					 | 
				
			||||||
			data.flags |= BIND_NUMBER;
 | 
					 | 
				
			||||||
			data.num = strtonum(argv[2], 0, UINT_MAX, &errstr);
 | 
					 | 
				
			||||||
			if (errstr != NULL) {
 | 
					 | 
				
			||||||
				log_warnx("argument %s: %s", errstr, argv[2]); 
 | 
					 | 
				
			||||||
				return (1);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		} else
 | 
					 | 
				
			||||||
			fatalx("no argument type");
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		if (argc != 2) {
 | 
					 | 
				
			||||||
			log_warnx("%s cannot have an argument", data.cmd);
 | 
					 | 
				
			||||||
			return (1);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		data.flags = 0;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (client_init(path, &cctx, 1) != 0)
 | 
					 | 
				
			||||||
		return (1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	client_write_server2(&cctx, MSG_BINDKEY, &data, sizeof data, str, len);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return (client_flush(&cctx));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int
 | 
					 | 
				
			||||||
op_unbind_key(char *path, int argc, char **argv)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct bind_data	data;	
 | 
					 | 
				
			||||||
	struct client_ctx	cctx;
 | 
					 | 
				
			||||||
	int			opt;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	optind = 1;
 | 
					 | 
				
			||||||
	while ((opt = getopt(argc, argv, "?")) != EOF) {
 | 
					 | 
				
			||||||
		switch (opt) {
 | 
					 | 
				
			||||||
		default:
 | 
					 | 
				
			||||||
			return (usage("unbind-key key"));
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	argc -= optind;
 | 
					 | 
				
			||||||
	argv += optind;
 | 
					 | 
				
			||||||
	if (argc != 1)
 | 
					 | 
				
			||||||
		return (usage("unbind-key key"));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if ((data.key = key_string_lookup(argv[0])) == KEYC_NONE) {
 | 
					 | 
				
			||||||
		log_warnx("unknown key: %s", argv[0]);
 | 
					 | 
				
			||||||
		return (1);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (client_init(path, &cctx, 1) != 0)
 | 
					 | 
				
			||||||
		return (1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	client_write_server(&cctx, MSG_UNBINDKEY, &data, sizeof data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return (client_flush(&cctx));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										17
									
								
								server-fn.c
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								server-fn.c
									
									
									
									
									
								
							@@ -1,4 +1,4 @@
 | 
				
			|||||||
/* $Id: server-fn.c,v 1.13 2007-10-03 12:34:16 nicm Exp $ */
 | 
					/* $Id: server-fn.c,v 1.14 2007-10-03 21:31:07 nicm Exp $ */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
					 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
				
			||||||
@@ -64,7 +64,7 @@ server_find_sessid(struct sessid *sid, char **cause)
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (s == NULL) {
 | 
						if (s == NULL) {
 | 
				
			||||||
		xasprintf(cause, "no sessions");
 | 
							xasprintf(cause, "no sessions found");
 | 
				
			||||||
		return (NULL);
 | 
							return (NULL);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (n != 1) {
 | 
						if (n != 1) {
 | 
				
			||||||
@@ -125,6 +125,8 @@ server_write_clients(
 | 
				
			|||||||
	for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
 | 
						for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
 | 
				
			||||||
		c = ARRAY_ITEM(&clients, i);
 | 
							c = ARRAY_ITEM(&clients, i);
 | 
				
			||||||
		if (c != NULL && c->session != NULL) {
 | 
							if (c != NULL && c->session != NULL) {
 | 
				
			||||||
 | 
								if (c->flags & CLIENT_HOLD) /* XXX OUTPUT only */
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
			if (c->session->window == w) {
 | 
								if (c->session->window == w) {
 | 
				
			||||||
				log_debug(
 | 
									log_debug(
 | 
				
			||||||
				    "writing %d to clients: %d", type, c->fd);
 | 
									    "writing %d to clients: %d", type, c->fd);
 | 
				
			||||||
@@ -145,21 +147,22 @@ server_window_changed(struct client *c)
 | 
				
			|||||||
	w = c->session->window;
 | 
						w = c->session->window;
 | 
				
			||||||
	if (c->sx != w->screen.sx || c->sy != w->screen.sy)
 | 
						if (c->sx != w->screen.sx || c->sy != w->screen.sy)
 | 
				
			||||||
		window_resize(w, c->sx, c->sy);
 | 
							window_resize(w, c->sx, c->sy);
 | 
				
			||||||
	server_draw_client(c, 0, c->sy - 1);
 | 
						server_draw_client(c);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Draw window on client. */
 | 
					/* Draw window on client. */
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
server_draw_client(struct client *c, u_int py_upper, u_int py_lower)
 | 
					server_draw_client(struct client *c)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct hdr	hdr;
 | 
						struct hdr	 hdr;
 | 
				
			||||||
	size_t		size;
 | 
						size_t		 size;
 | 
				
			||||||
 | 
						struct screen	*s = &c->session->window->screen;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	buffer_ensure(c->out, sizeof hdr);
 | 
						buffer_ensure(c->out, sizeof hdr);
 | 
				
			||||||
	buffer_add(c->out, sizeof hdr);
 | 
						buffer_add(c->out, sizeof hdr);
 | 
				
			||||||
	size = BUFFER_USED(c->out);
 | 
						size = BUFFER_USED(c->out);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	screen_draw(&c->session->window->screen, c->out, py_upper, py_lower);
 | 
						screen_draw(s, c->out, 0, s->sy - 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	size = BUFFER_USED(c->out) - size;
 | 
						size = BUFFER_USED(c->out) - size;
 | 
				
			||||||
	log_debug("redrawing screen, %zu bytes", size);
 | 
						log_debug("redrawing screen, %zu bytes", size);
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										404
									
								
								server-msg.c
									
									
									
									
									
								
							
							
						
						
									
										404
									
								
								server-msg.c
									
									
									
									
									
								
							@@ -1,4 +1,4 @@
 | 
				
			|||||||
/* $Id: server-msg.c,v 1.19 2007-10-03 13:07:42 nicm Exp $ */
 | 
					/* $Id: server-msg.c,v 1.20 2007-10-03 21:31:07 nicm Exp $ */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
					 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
				
			||||||
@@ -24,16 +24,13 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "tmux.h"
 | 
					#include "tmux.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int	server_msg_fn_attach(struct hdr *, struct client *);
 | 
					int	server_msg_fn_command(struct hdr *, struct client *);
 | 
				
			||||||
int	server_msg_fn_bindkey(struct hdr *, struct client *);
 | 
					int	server_msg_fn_identify(struct hdr *, struct client *);
 | 
				
			||||||
int	server_msg_fn_keys(struct hdr *, struct client *);
 | 
					int	server_msg_fn_keys(struct hdr *, struct client *);
 | 
				
			||||||
int	server_msg_fn_new(struct hdr *, struct client *);
 | 
					int	server_msg_fn_resize(struct hdr *, struct client *);
 | 
				
			||||||
int	server_msg_fn_rename(struct hdr *, struct client *);
 | 
					
 | 
				
			||||||
int	server_msg_fn_sessions(struct hdr *, struct client *);
 | 
					void	server_msg_fn_command_error(struct cmd_ctx *, const char *, ...);
 | 
				
			||||||
int	server_msg_fn_size(struct hdr *, struct client *);
 | 
					void	server_msg_fn_command_print(struct cmd_ctx *, const char *, ...);
 | 
				
			||||||
int	server_msg_fn_unbindkey(struct hdr *, struct client *);
 | 
					 | 
				
			||||||
int	server_msg_fn_windowlist(struct hdr *, struct client *);
 | 
					 | 
				
			||||||
int	server_msg_fn_windows(struct hdr *, struct client *);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct server_msg {
 | 
					struct server_msg {
 | 
				
			||||||
	enum hdrtype	type;
 | 
						enum hdrtype	type;
 | 
				
			||||||
@@ -41,16 +38,10 @@ struct server_msg {
 | 
				
			|||||||
	int	        (*fn)(struct hdr *, struct client *);
 | 
						int	        (*fn)(struct hdr *, struct client *);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
const struct server_msg server_msg_table[] = {
 | 
					const struct server_msg server_msg_table[] = {
 | 
				
			||||||
	{ MSG_ATTACH, server_msg_fn_attach },
 | 
						{ MSG_IDENTIFY, server_msg_fn_identify },
 | 
				
			||||||
	{ MSG_BINDKEY, server_msg_fn_bindkey },
 | 
						{ MSG_COMMAND, server_msg_fn_command },
 | 
				
			||||||
 | 
						{ MSG_RESIZE, server_msg_fn_resize },
 | 
				
			||||||
	{ MSG_KEYS, server_msg_fn_keys },
 | 
						{ MSG_KEYS, server_msg_fn_keys },
 | 
				
			||||||
	{ MSG_NEW, server_msg_fn_new },
 | 
					 | 
				
			||||||
	{ MSG_RENAME, server_msg_fn_rename },
 | 
					 | 
				
			||||||
	{ MSG_SESSIONS, server_msg_fn_sessions },
 | 
					 | 
				
			||||||
	{ MSG_SIZE, server_msg_fn_size },
 | 
					 | 
				
			||||||
	{ MSG_UNBINDKEY, server_msg_fn_unbindkey },
 | 
					 | 
				
			||||||
	{ MSG_WINDOWLIST, server_msg_fn_windowlist },
 | 
					 | 
				
			||||||
	{ MSG_WINDOWS, server_msg_fn_windows },
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
#define NSERVERMSG (sizeof server_msg_table / sizeof server_msg_table[0])
 | 
					#define NSERVERMSG (sizeof server_msg_table / sizeof server_msg_table[0])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -83,89 +74,98 @@ server_msg_dispatch(struct client *c)
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* New message from client. */
 | 
					void
 | 
				
			||||||
int
 | 
					server_msg_fn_command_error(struct cmd_ctx *ctx, const char *fmt, ...)
 | 
				
			||||||
server_msg_fn_new(struct hdr *hdr, struct client *c)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct new_data	 data;
 | 
						va_list	ap;
 | 
				
			||||||
	char	         *msg;
 | 
						char   *msg;
 | 
				
			||||||
	
 | 
					
 | 
				
			||||||
	if (c->session != NULL)
 | 
						va_start(ap, fmt);
 | 
				
			||||||
		return (0);
 | 
						xvasprintf(&msg, fmt, ap);
 | 
				
			||||||
	if (hdr->size != sizeof data)
 | 
						va_end(ap);
 | 
				
			||||||
		fatalx("bad MSG_NEW size");
 | 
					
 | 
				
			||||||
 | 
						server_write_client(ctx->client, MSG_ERROR, msg, strlen(msg));
 | 
				
			||||||
 | 
						xfree(msg);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					server_msg_fn_command_print(struct cmd_ctx *ctx, const char *fmt, ...)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						va_list	ap;
 | 
				
			||||||
 | 
						char   *msg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						va_start(ap, fmt);
 | 
				
			||||||
 | 
						xvasprintf(&msg, fmt, ap);
 | 
				
			||||||
 | 
						va_end(ap);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						server_write_client(ctx->client, MSG_PRINT, msg, strlen(msg));
 | 
				
			||||||
 | 
						xfree(msg);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					server_msg_fn_command(struct hdr *hdr, struct client *c)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct msg_command_data	data;
 | 
				
			||||||
 | 
						struct cmd_ctx	 	ctx;
 | 
				
			||||||
 | 
						struct cmd	       *cmd;
 | 
				
			||||||
 | 
						char	       	       *cause;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (hdr->size < sizeof data)
 | 
				
			||||||
 | 
							fatalx("bad MSG_COMMAND size");
 | 
				
			||||||
	buffer_read(c->in, &data, sizeof data);
 | 
						buffer_read(c->in, &data, sizeof data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	c->sx = data.sx;
 | 
						cmd = cmd_recv(c->in);
 | 
				
			||||||
	if (c->sx == 0)
 | 
						log_debug("got command %u %s from client %d",
 | 
				
			||||||
		c->sx = 80;
 | 
						    cmd->entry->type, cmd->entry->name, c->fd);
 | 
				
			||||||
	c->sy = data.sy;
 | 
					 | 
				
			||||||
	if (c->sy == 0)
 | 
					 | 
				
			||||||
		c->sy = 25;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (c->sy >= status_lines)
 | 
						if (cmd->entry->flags & CMD_NOSESSION)
 | 
				
			||||||
		c->sy -= status_lines;
 | 
							ctx.session = NULL;
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
							ctx.session = server_find_sessid(&data.sid, &cause);
 | 
				
			||||||
 | 
							if (ctx.session == NULL) {
 | 
				
			||||||
 | 
								server_write_error(c, "%s", cause);
 | 
				
			||||||
 | 
								xfree(cause);
 | 
				
			||||||
 | 
								return (0);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}		
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	data.name[(sizeof data.name) - 1] = '\0';
 | 
						ctx.error = server_msg_fn_command_error;
 | 
				
			||||||
	if (*data.name != '\0' && session_find(data.name) != NULL) {
 | 
						ctx.print = server_msg_fn_command_print;
 | 
				
			||||||
		xasprintf(&msg, "duplicate session: %s", data.name);
 | 
					 | 
				
			||||||
		server_write_client(c, MSG_ERROR, msg, strlen(msg));
 | 
					 | 
				
			||||||
		xfree(msg);
 | 
					 | 
				
			||||||
		return (0);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	c->session = session_create(data.name, default_command, c->sx, c->sy);
 | 
						ctx.client = c;
 | 
				
			||||||
	if (c->session == NULL)
 | 
						ctx.flags = 0;
 | 
				
			||||||
		fatalx("session_create failed");
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	server_write_client(c, MSG_OKAY, NULL, 0);
 | 
						cmd_exec(cmd, &ctx);
 | 
				
			||||||
	server_draw_client(c, 0, c->sy - 1);
 | 
						cmd_free(cmd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return (0);
 | 
						return (0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Attach message from client. */
 | 
					 | 
				
			||||||
int
 | 
					int
 | 
				
			||||||
server_msg_fn_attach(struct hdr *hdr, struct client *c)
 | 
					server_msg_fn_identify(struct hdr *hdr, struct client *c)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct attach_data	 data;
 | 
						struct msg_identify_data	data;
 | 
				
			||||||
	char			*cause;
 | 
					
 | 
				
			||||||
	
 | 
						if (hdr->size < sizeof data)
 | 
				
			||||||
	if (c->session != NULL)
 | 
							fatalx("bad MSG_IDENTIFY size");
 | 
				
			||||||
		return (0);
 | 
					 | 
				
			||||||
	if (hdr->size != sizeof data)
 | 
					 | 
				
			||||||
		fatalx("bad MSG_ATTACH size");
 | 
					 | 
				
			||||||
	buffer_read(c->in, &data, sizeof data);
 | 
						buffer_read(c->in, &data, sizeof data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						log_debug("got identify msg from client: %u,%u", data.sx, data.sy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	c->sx = data.sx;
 | 
						c->sx = data.sx;
 | 
				
			||||||
	if (c->sx == 0)
 | 
					 | 
				
			||||||
		c->sx = 80;
 | 
					 | 
				
			||||||
	c->sy = data.sy;
 | 
						c->sy = data.sy;
 | 
				
			||||||
	if (c->sy == 0)
 | 
					 | 
				
			||||||
		c->sy = 25;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (c->sy >= status_lines)
 | 
						c->flags |= CLIENT_TERMINAL;
 | 
				
			||||||
		c->sy -= status_lines;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if ((c->session = server_find_sessid(&data.sid, &cause)) == NULL) {
 | 
					 | 
				
			||||||
		server_write_error(c, "%s", cause);
 | 
					 | 
				
			||||||
		xfree(cause);
 | 
					 | 
				
			||||||
		return (0);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	server_draw_client(c, 0, c->sy - 1);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return (0);
 | 
						return (0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Size message from client. */
 | 
					 | 
				
			||||||
int
 | 
					int
 | 
				
			||||||
server_msg_fn_size(struct hdr *hdr, struct client *c)
 | 
					server_msg_fn_resize(struct hdr *hdr, struct client *c)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct size_data	data;
 | 
						struct msg_resize_data	data;
 | 
				
			||||||
 | 
						u_int			sy;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (c->session == NULL)
 | 
					 | 
				
			||||||
		return (0);
 | 
					 | 
				
			||||||
	if (hdr->size != sizeof data)
 | 
						if (hdr->size != sizeof data)
 | 
				
			||||||
		fatalx("bad MSG_SIZE size");
 | 
							fatalx("bad MSG_SIZE size");
 | 
				
			||||||
	buffer_read(c->in, &data, sizeof data);
 | 
						buffer_read(c->in, &data, sizeof data);
 | 
				
			||||||
@@ -177,265 +177,47 @@ server_msg_fn_size(struct hdr *hdr, struct client *c)
 | 
				
			|||||||
	if (c->sy == 0)
 | 
						if (c->sy == 0)
 | 
				
			||||||
		c->sy = 25;
 | 
							c->sy = 25;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (c->sy >= status_lines)
 | 
						sy = c->sy;
 | 
				
			||||||
		c->sy -= status_lines;
 | 
						if (sy < status_lines)
 | 
				
			||||||
 | 
							sy = status_lines + 1;
 | 
				
			||||||
 | 
						sy -= status_lines;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (window_resize(c->session->window, c->sx, c->sy) != 0)
 | 
						if (window_resize(c->session->window, c->sx, sy) != 0)
 | 
				
			||||||
		server_draw_client(c, 0, c->sy - 1);
 | 
							server_draw_client(c);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return (0);
 | 
						return (0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Keys message from client. */
 | 
					 | 
				
			||||||
int
 | 
					int
 | 
				
			||||||
server_msg_fn_keys(struct hdr *hdr, struct client *c)
 | 
					server_msg_fn_keys(struct hdr *hdr, struct client *c)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int	key;
 | 
						int	key;
 | 
				
			||||||
	size_t	size;
 | 
						size_t	size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (c->session == NULL)
 | 
					 | 
				
			||||||
		return (0);
 | 
					 | 
				
			||||||
	if (hdr->size & 0x1)
 | 
						if (hdr->size & 0x1)
 | 
				
			||||||
		fatalx("bad MSG_KEYS size");
 | 
							fatalx("bad MSG_KEYS size");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (c->flags & CLIENT_HOLD) {
 | 
				
			||||||
 | 
							server_draw_client(c);
 | 
				
			||||||
 | 
							c->flags &= ~CLIENT_HOLD;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	size = hdr->size;
 | 
						size = hdr->size;
 | 
				
			||||||
	while (size != 0) {
 | 
						while (size != 0) {
 | 
				
			||||||
		key = (int16_t) input_extract16(c->in);
 | 
							key = (int16_t) input_extract16(c->in);
 | 
				
			||||||
		size -= 2;
 | 
							size -= 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (c->prefix) {
 | 
							if (c->flags & CLIENT_PREFIX) {
 | 
				
			||||||
			cmd_dispatch(c, key);
 | 
								key_bindings_dispatch(key, c);
 | 
				
			||||||
			c->prefix = 0;
 | 
								c->flags &= ~CLIENT_PREFIX;
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (key == cmd_prefix)
 | 
							if (key == prefix_key)
 | 
				
			||||||
			c->prefix = 1;
 | 
								c->flags |= CLIENT_PREFIX;
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
			window_key(c->session->window, key);
 | 
								window_key(c->session->window, key);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return (0);
 | 
						return (0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Sessions message from client. */
 | 
					 | 
				
			||||||
int
 | 
					 | 
				
			||||||
server_msg_fn_sessions(struct hdr *hdr, struct client *c)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct sessions_data	 data;
 | 
					 | 
				
			||||||
	struct sessions_entry	 entry;
 | 
					 | 
				
			||||||
	struct session		*s;
 | 
					 | 
				
			||||||
	u_int			 i, j;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (hdr->size != sizeof data)
 | 
					 | 
				
			||||||
		fatalx("bad MSG_SESSIONS size");
 | 
					 | 
				
			||||||
	buffer_read(c->in, &data, sizeof data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	data.sessions = 0;
 | 
					 | 
				
			||||||
	for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
 | 
					 | 
				
			||||||
		if (ARRAY_ITEM(&sessions, i) != NULL)
 | 
					 | 
				
			||||||
			data.sessions++;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	server_write_client2(c, MSG_SESSIONS,
 | 
					 | 
				
			||||||
	    &data, sizeof data, NULL, data.sessions * sizeof entry);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
 | 
					 | 
				
			||||||
		s = ARRAY_ITEM(&sessions, i);
 | 
					 | 
				
			||||||
		if (s == NULL)
 | 
					 | 
				
			||||||
			continue;
 | 
					 | 
				
			||||||
		strlcpy(entry.name, s->name, sizeof entry.name);
 | 
					 | 
				
			||||||
		entry.tim = s->tim;
 | 
					 | 
				
			||||||
		entry.windows = 0;
 | 
					 | 
				
			||||||
		for (j = 0; j < ARRAY_LENGTH(&s->windows); j++) {
 | 
					 | 
				
			||||||
			if (ARRAY_ITEM(&s->windows, j) != NULL)
 | 
					 | 
				
			||||||
				entry.windows++;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		buffer_write(c->out, &entry, sizeof entry);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return (0);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Windows message from client. */
 | 
					 | 
				
			||||||
int
 | 
					 | 
				
			||||||
server_msg_fn_windows(struct hdr *hdr, struct client *c)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct windows_data	 data;
 | 
					 | 
				
			||||||
	struct windows_entry	 entry;
 | 
					 | 
				
			||||||
	struct session		*s;
 | 
					 | 
				
			||||||
	struct window		*w;
 | 
					 | 
				
			||||||
	u_int			 i;
 | 
					 | 
				
			||||||
	char		 	*cause;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (hdr->size != sizeof data)
 | 
					 | 
				
			||||||
		fatalx("bad MSG_WINDOWS size");
 | 
					 | 
				
			||||||
	buffer_read(c->in, &data, sizeof data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if ((s = server_find_sessid(&data.sid, &cause)) == NULL) {
 | 
					 | 
				
			||||||
		server_write_error(c, "%s", cause);
 | 
					 | 
				
			||||||
		xfree(cause);
 | 
					 | 
				
			||||||
		return (0);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	data.windows = 0;
 | 
					 | 
				
			||||||
	for (i = 0; i < ARRAY_LENGTH(&s->windows); i++) {
 | 
					 | 
				
			||||||
		if (ARRAY_ITEM(&s->windows, i) != NULL)
 | 
					 | 
				
			||||||
			data.windows++;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	server_write_client2(c, MSG_WINDOWS,
 | 
					 | 
				
			||||||
	    &data, sizeof data, NULL, data.windows * sizeof entry);
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	for (i = 0; i < ARRAY_LENGTH(&s->windows); i++) {
 | 
					 | 
				
			||||||
		w = ARRAY_ITEM(&s->windows, i);
 | 
					 | 
				
			||||||
		if (w == NULL)
 | 
					 | 
				
			||||||
			continue;
 | 
					 | 
				
			||||||
		entry.idx = i;
 | 
					 | 
				
			||||||
		strlcpy(entry.name, w->name, sizeof entry.name);
 | 
					 | 
				
			||||||
		strlcpy(entry.title, w->screen.title, sizeof entry.title);
 | 
					 | 
				
			||||||
		if (ttyname_r(w->fd, entry.tty, sizeof entry.tty) != 0)
 | 
					 | 
				
			||||||
			*entry.tty = '\0';
 | 
					 | 
				
			||||||
		buffer_write(c->out, &entry, sizeof entry);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return (0);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Rename message from client. */
 | 
					 | 
				
			||||||
int
 | 
					 | 
				
			||||||
server_msg_fn_rename(struct hdr *hdr, struct client *c)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct rename_data	data;
 | 
					 | 
				
			||||||
	char                   *cause;
 | 
					 | 
				
			||||||
	struct window	       *w;
 | 
					 | 
				
			||||||
	struct session	       *s;
 | 
					 | 
				
			||||||
	u_int			i;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (hdr->size != sizeof data)
 | 
					 | 
				
			||||||
		fatalx("bad MSG_RENAME size");
 | 
					 | 
				
			||||||
	buffer_read(c->in, &data, sizeof data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 	data.newname[(sizeof data.newname) - 1] = '\0';
 | 
					 | 
				
			||||||
	if ((s = server_find_sessid(&data.sid, &cause)) == NULL) {
 | 
					 | 
				
			||||||
		server_write_error(c, "%s", cause);
 | 
					 | 
				
			||||||
		xfree(cause);
 | 
					 | 
				
			||||||
		return (0);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (data.idx == -1)
 | 
					 | 
				
			||||||
		w = s->window;
 | 
					 | 
				
			||||||
	else {
 | 
					 | 
				
			||||||
		if (data.idx < 0)
 | 
					 | 
				
			||||||
			fatalx("bad window index");
 | 
					 | 
				
			||||||
		w = window_at(&s->windows, data.idx);
 | 
					 | 
				
			||||||
		if (w == NULL) { 
 | 
					 | 
				
			||||||
			server_write_error(c, "window not found: %d", data.idx);
 | 
					 | 
				
			||||||
			return (0);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	strlcpy(w->name, data.newname, sizeof w->name);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	server_write_client(c, MSG_OKAY, NULL, 0);
 | 
					 | 
				
			||||||
	for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
 | 
					 | 
				
			||||||
		c = ARRAY_ITEM(&clients, i);
 | 
					 | 
				
			||||||
		if (c != NULL && c->session != NULL) {
 | 
					 | 
				
			||||||
			if (session_has(c->session, w))
 | 
					 | 
				
			||||||
				server_draw_status(c);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return (0);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Window list message from client */
 | 
					 | 
				
			||||||
int
 | 
					 | 
				
			||||||
server_msg_fn_windowlist(struct hdr *hdr, struct client *c)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct window	*w;
 | 
					 | 
				
			||||||
	char 		*buf;
 | 
					 | 
				
			||||||
	size_t		 len, off;
 | 
					 | 
				
			||||||
	u_int 		 i;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (c->session == NULL)
 | 
					 | 
				
			||||||
		return (0);
 | 
					 | 
				
			||||||
	if (hdr->size != 0)
 | 
					 | 
				
			||||||
		fatalx("bad MSG_WINDOWLIST size");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	len = c->sx + 1;
 | 
					 | 
				
			||||||
	buf = xmalloc(len);
 | 
					 | 
				
			||||||
	off = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	*buf = '\0';
 | 
					 | 
				
			||||||
	for (i = 0; i < ARRAY_LENGTH(&c->session->windows); i++) {
 | 
					 | 
				
			||||||
		w = ARRAY_ITEM(&c->session->windows, i);
 | 
					 | 
				
			||||||
		if (w == NULL)
 | 
					 | 
				
			||||||
			continue;
 | 
					 | 
				
			||||||
		off += xsnprintf(buf + off, len - off, "%u:%s%s ", i, w->name, 
 | 
					 | 
				
			||||||
		    w == c->session->window ? "*" : "");
 | 
					 | 
				
			||||||
		if (off >= len)
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	server_write_message(c, "%s", buf);
 | 
					 | 
				
			||||||
	xfree(buf);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return (0);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Bind key message from client */
 | 
					 | 
				
			||||||
int
 | 
					 | 
				
			||||||
server_msg_fn_bindkey(struct hdr *hdr, struct client *c)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct bind_data	data;
 | 
					 | 
				
			||||||
	const struct bind      *bind;
 | 
					 | 
				
			||||||
	char		       *str;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (hdr->size < sizeof data)
 | 
					 | 
				
			||||||
		fatalx("bad MSG_BINDKEY size");
 | 
					 | 
				
			||||||
	buffer_read(c->in, &data, sizeof data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	str = NULL;
 | 
					 | 
				
			||||||
	if (data.flags & BIND_STRING) {
 | 
					 | 
				
			||||||
		hdr->size -= sizeof data;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		str = xmemstrdup(BUFFER_OUT(c->in), hdr->size);
 | 
					 | 
				
			||||||
		if (hdr->size > 0)
 | 
					 | 
				
			||||||
			buffer_remove(c->in, hdr->size);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 	data.cmd[(sizeof data.cmd) - 1] = '\0';	
 | 
					 | 
				
			||||||
	if ((bind = cmd_lookup_bind(data.cmd)) == NULL)
 | 
					 | 
				
			||||||
		fatalx("unknown command");
 | 
					 | 
				
			||||||
	if (!(bind->flags & BIND_USER) &&
 | 
					 | 
				
			||||||
	    (data.flags & (BIND_NUMBER|BIND_STRING)) != 0)
 | 
					 | 
				
			||||||
		fatalx("argument missing");
 | 
					 | 
				
			||||||
	if ((bind->flags & BIND_USER) &&
 | 
					 | 
				
			||||||
	    (data.flags & (BIND_NUMBER|BIND_STRING)) == 0)
 | 
					 | 
				
			||||||
		fatalx("argument required");
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	cmd_add_bind(data.key, data.num, str, bind);
 | 
					 | 
				
			||||||
	if (str != NULL)
 | 
					 | 
				
			||||||
		xfree(str);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	server_write_client(c, MSG_OKAY, NULL, 0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return (0);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Unbind key message from client */
 | 
					 | 
				
			||||||
int
 | 
					 | 
				
			||||||
server_msg_fn_unbindkey(struct hdr *hdr, struct client *c)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct bind_data	data;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (hdr->size != sizeof data)
 | 
					 | 
				
			||||||
		fatalx("bad MSG_UNBINDKEY size");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	buffer_read(c->in, &data, hdr->size);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	cmd_remove_bind(data.key);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	server_write_client(c, MSG_OKAY, NULL, 0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return (0);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										6
									
								
								server.c
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								server.c
									
									
									
									
									
								
							@@ -1,4 +1,4 @@
 | 
				
			|||||||
/* $Id: server.c,v 1.19 2007-10-03 11:26:34 nicm Exp $ */
 | 
					/* $Id: server.c,v 1.20 2007-10-03 21:31:07 nicm Exp $ */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
					 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
				
			||||||
@@ -127,7 +127,7 @@ server_main(char *srv_path, int srv_fd)
 | 
				
			|||||||
	ARRAY_INIT(&clients);
 | 
						ARRAY_INIT(&clients);
 | 
				
			||||||
	ARRAY_INIT(&sessions);
 | 
						ARRAY_INIT(&sessions);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cmd_init();
 | 
						key_bindings_init();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pfds = NULL;
 | 
						pfds = NULL;
 | 
				
			||||||
	while (!sigterm) {
 | 
						while (!sigterm) {
 | 
				
			||||||
@@ -171,7 +171,7 @@ server_main(char *srv_path, int srv_fd)
 | 
				
			|||||||
		server_handle_clients(&pfd);
 | 
							server_handle_clients(&pfd);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cmd_free();
 | 
						key_bindings_free();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	close(srv_fd);
 | 
						close(srv_fd);
 | 
				
			||||||
	unlink(srv_path);
 | 
						unlink(srv_path);
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										10
									
								
								session.c
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								session.c
									
									
									
									
									
								
							@@ -1,4 +1,4 @@
 | 
				
			|||||||
/* $Id: session.c,v 1.19 2007-09-29 21:02:26 nicm Exp $ */
 | 
					/* $Id: session.c,v 1.20 2007-10-03 21:31:07 nicm Exp $ */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
					 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
				
			||||||
@@ -64,11 +64,10 @@ session_create(const char *name, const char *cmd, u_int sx, u_int sy)
 | 
				
			|||||||
	if (i == ARRAY_LENGTH(&sessions))
 | 
						if (i == ARRAY_LENGTH(&sessions))
 | 
				
			||||||
		ARRAY_ADD(&sessions, s);
 | 
							ARRAY_ADD(&sessions, s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (*name != '\0')
 | 
						if (name != NULL)
 | 
				
			||||||
		strlcpy(s->name, name, sizeof s->name);
 | 
							s->name = xstrdup(name);
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		xsnprintf(s->name, sizeof s->name, "%u", i);
 | 
							xasprintf(&s->name, "%u", i);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (session_new(s, cmd, sx, sy) != 0) {
 | 
						if (session_new(s, cmd, sx, sy) != 0) {
 | 
				
			||||||
		session_destroy(s);
 | 
							session_destroy(s);
 | 
				
			||||||
		return (NULL);
 | 
							return (NULL);
 | 
				
			||||||
@@ -92,6 +91,7 @@ session_destroy(struct session *s)
 | 
				
			|||||||
	while (!ARRAY_EMPTY(&s->windows))
 | 
						while (!ARRAY_EMPTY(&s->windows))
 | 
				
			||||||
		window_remove(&s->windows, ARRAY_FIRST(&s->windows));
 | 
							window_remove(&s->windows, ARRAY_FIRST(&s->windows));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						xfree(s->name);
 | 
				
			||||||
	xfree(s);
 | 
						xfree(s);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										148
									
								
								tmux.c
									
									
									
									
									
								
							
							
						
						
									
										148
									
								
								tmux.c
									
									
									
									
									
								
							@@ -1,4 +1,4 @@
 | 
				
			|||||||
/* $Id: tmux.c,v 1.24 2007-10-03 12:56:02 nicm Exp $ */
 | 
					/* $Id: tmux.c,v 1.25 2007-10-03 21:31:07 nicm Exp $ */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
					 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
				
			||||||
@@ -19,7 +19,10 @@
 | 
				
			|||||||
#include <sys/types.h>
 | 
					#include <sys/types.h>
 | 
				
			||||||
#include <sys/wait.h>
 | 
					#include <sys/wait.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <err.h>
 | 
				
			||||||
 | 
					#include <errno.h>
 | 
				
			||||||
#include <paths.h>
 | 
					#include <paths.h>
 | 
				
			||||||
 | 
					#include <poll.h>
 | 
				
			||||||
#include <signal.h>
 | 
					#include <signal.h>
 | 
				
			||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
@@ -35,45 +38,29 @@ const char	*malloc_options = "AFGJPX";
 | 
				
			|||||||
volatile sig_atomic_t sigwinch;
 | 
					volatile sig_atomic_t sigwinch;
 | 
				
			||||||
volatile sig_atomic_t sigterm;
 | 
					volatile sig_atomic_t sigterm;
 | 
				
			||||||
int		 debug_level;
 | 
					int		 debug_level;
 | 
				
			||||||
 | 
					int		 prefix_key = META;
 | 
				
			||||||
u_int		 status_lines;
 | 
					u_int		 status_lines;
 | 
				
			||||||
char		*default_command;
 | 
					char		*default_command;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void		 sighandler(int);
 | 
					void		 sighandler(int);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct op {
 | 
					void
 | 
				
			||||||
	const char     *cmd;
 | 
					usage(char **ptr, const char *fmt, ...)
 | 
				
			||||||
	const char     *alias;
 | 
					 | 
				
			||||||
	int		(*fn)(char *, int, char **);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
const struct op op_table[] = {
 | 
					 | 
				
			||||||
	{ "attach", NULL, op_attach },
 | 
					 | 
				
			||||||
	{ "bind-key", "bind", op_bind_key },
 | 
					 | 
				
			||||||
	{ "list-sessions", "ls", op_list_sessions },
 | 
					 | 
				
			||||||
	{ "list-windows", "lsw", op_list_windows },
 | 
					 | 
				
			||||||
	{ "new-session", "new", op_new_session },
 | 
					 | 
				
			||||||
	{ "rename-window", "renw", op_rename_window },
 | 
					 | 
				
			||||||
	{ "unbind-key", "unbind", op_unbind_key },
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
#define NOP (sizeof op_table / sizeof op_table[0])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int
 | 
					 | 
				
			||||||
usage(const char *fmt, ...)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	char	*msg;
 | 
						char	*msg;
 | 
				
			||||||
	va_list	 ap;
 | 
						va_list	 ap;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (fmt == NULL) {
 | 
						if (fmt == NULL) {
 | 
				
			||||||
		fprintf(stderr,
 | 
							xasprintf(ptr,
 | 
				
			||||||
		    "usage: %s [-v] [-S path] command [flags]\n", __progname);
 | 
							    "usage: %s [-v] [-S path] command [flags]", __progname);
 | 
				
			||||||
		return (1);
 | 
						} else {
 | 
				
			||||||
	}
 | 
							va_start(ap, fmt);
 | 
				
			||||||
 | 
							xvasprintf(&msg, fmt, ap);
 | 
				
			||||||
 | 
							va_end(ap);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	va_start(ap, fmt);
 | 
							xasprintf(ptr, "usage: %s [-v] [-S path] %s", __progname, msg);
 | 
				
			||||||
	xvasprintf(&msg, fmt, ap);
 | 
							xfree(msg);
 | 
				
			||||||
	va_end(ap);
 | 
						}
 | 
				
			||||||
	fprintf(stderr, "usage: %s [-v] [-S path] %s\n", __progname, msg);
 | 
					 | 
				
			||||||
	xfree(msg);
 | 
					 | 
				
			||||||
	return (1);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
@@ -172,30 +159,39 @@ sigreset(void)
 | 
				
			|||||||
int
 | 
					int
 | 
				
			||||||
main(int argc, char **argv)
 | 
					main(int argc, char **argv)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	const struct op		*op, *found;
 | 
						struct client_ctx	 cctx;
 | 
				
			||||||
 | 
						struct msg_command_data	 data;
 | 
				
			||||||
 | 
						struct buffer		*b;
 | 
				
			||||||
 | 
						struct cmd		*cmd;
 | 
				
			||||||
 | 
						struct pollfd	 	 pfd;
 | 
				
			||||||
 | 
						struct hdr	 	 hdr;
 | 
				
			||||||
	const char		*shell;
 | 
						const char		*shell;
 | 
				
			||||||
	char			*path;
 | 
						char			*path, *cause, name[MAXNAMELEN];
 | 
				
			||||||
	int	 		 opt;
 | 
						int	 		 opt;
 | 
				
			||||||
	u_int			 i;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*name = '\0';
 | 
				
			||||||
	path = NULL;
 | 
						path = NULL;
 | 
				
			||||||
        while ((opt = getopt(argc, argv, "S:v?")) != EOF) {
 | 
					        while ((opt = getopt(argc, argv, "S:s:v?")) != EOF) {
 | 
				
			||||||
                switch (opt) {
 | 
					                switch (opt) {
 | 
				
			||||||
		case 'S':
 | 
							case 'S':
 | 
				
			||||||
			path = xstrdup(optarg);
 | 
								path = xstrdup(optarg);
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
 | 
							case 's':
 | 
				
			||||||
 | 
								if (strlcpy(name, optarg, sizeof name) >= sizeof name)
 | 
				
			||||||
 | 
									errx(1, "session name too long: %s", optarg);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
		case 'v':
 | 
							case 'v':
 | 
				
			||||||
			debug_level++;
 | 
								debug_level++;
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
                case '?':
 | 
					                case '?':
 | 
				
			||||||
                default:
 | 
					                default:
 | 
				
			||||||
                        exit(usage(NULL));
 | 
								goto usage;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
	argc -= optind;
 | 
						argc -= optind;
 | 
				
			||||||
	argv += optind;
 | 
						argv += optind;
 | 
				
			||||||
	if (argc == 0)
 | 
						if (argc == 0)
 | 
				
			||||||
		exit(usage(NULL));
 | 
							goto usage;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	log_open(stderr, LOG_USER, debug_level);
 | 
						log_open(stderr, LOG_USER, debug_level);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -206,21 +202,75 @@ main(int argc, char **argv)
 | 
				
			|||||||
		shell = "/bin/ksh";
 | 
							shell = "/bin/ksh";
 | 
				
			||||||
	xasprintf(&default_command, "exec %s -l", shell);
 | 
						xasprintf(&default_command, "exec %s -l", shell);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	found = NULL;
 | 
						if ((cmd = cmd_parse(argc, argv, &cause)) == NULL) {
 | 
				
			||||||
	for (i = 0; i < NOP; i++) {
 | 
							if (cause == NULL)
 | 
				
			||||||
		op = op_table + i;
 | 
								goto usage;
 | 
				
			||||||
		if (op->alias != NULL && strcmp(argv[0], op->alias) == 0)
 | 
							log_warnx("%s", cause);
 | 
				
			||||||
			exit(op->fn(path, argc, argv));
 | 
							exit(1);
 | 
				
			||||||
		if (strncmp(argv[0], op->cmd, strlen(argv[0])) == 0) {
 | 
						}
 | 
				
			||||||
			if (found != NULL) {
 | 
					
 | 
				
			||||||
				log_warnx("ambiguous command: %s", argv[0]);
 | 
						if (!(cmd->entry->flags & CMD_NOSESSION))
 | 
				
			||||||
				exit(1);
 | 
							client_fill_sessid(&data.sid, name);
 | 
				
			||||||
			}
 | 
						if (client_init(path, &cctx, cmd->entry->flags & CMD_STARTSERVER) != 0)
 | 
				
			||||||
			found = op;
 | 
							exit(1);
 | 
				
			||||||
 | 
						b = buffer_create(BUFSIZ);
 | 
				
			||||||
 | 
						cmd_send(cmd, b);
 | 
				
			||||||
 | 
						cmd_free(cmd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						client_write_server2(&cctx,
 | 
				
			||||||
 | 
						    MSG_COMMAND, &data, sizeof data, BUFFER_OUT(b), BUFFER_USED(b));
 | 
				
			||||||
 | 
						buffer_destroy(b);
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						for (;;) {
 | 
				
			||||||
 | 
							pfd.fd = cctx.srv_fd;
 | 
				
			||||||
 | 
							pfd.events = POLLIN;
 | 
				
			||||||
 | 
							if (BUFFER_USED(cctx.srv_out) > 0)
 | 
				
			||||||
 | 
								pfd.events |= POLLOUT;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
							if (poll(&pfd, 1, INFTIM) == -1) {
 | 
				
			||||||
 | 
								if (errno == EAGAIN || errno == EINTR)
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
								fatal("poll failed");
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (buffer_poll(&pfd, cctx.srv_in, cctx.srv_out) != 0)
 | 
				
			||||||
 | 
								fatalx("lost server");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						restart:
 | 
				
			||||||
 | 
							if (BUFFER_USED(cctx.srv_in) < sizeof hdr)
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
							memcpy(&hdr, BUFFER_OUT(cctx.srv_in), sizeof hdr);
 | 
				
			||||||
 | 
							if (BUFFER_USED(cctx.srv_in) < (sizeof hdr) + hdr.size)
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
							buffer_remove(cctx.srv_in, sizeof hdr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							switch (hdr.type) {
 | 
				
			||||||
 | 
							case MSG_EXIT:
 | 
				
			||||||
 | 
								exit(0);
 | 
				
			||||||
 | 
							case MSG_PRINT:
 | 
				
			||||||
 | 
								if (hdr.size > INT_MAX - 1)
 | 
				
			||||||
 | 
									fatalx("bad MSG_PRINT size");
 | 
				
			||||||
 | 
								log_info(
 | 
				
			||||||
 | 
								    "%.*s", (int) hdr.size, BUFFER_OUT(cctx.srv_in));
 | 
				
			||||||
 | 
								buffer_remove(cctx.srv_in, hdr.size);
 | 
				
			||||||
 | 
								goto restart;
 | 
				
			||||||
 | 
							case MSG_ERROR:
 | 
				
			||||||
 | 
								if (hdr.size > INT_MAX - 1)
 | 
				
			||||||
 | 
									fatalx("bad MSG_ERROR size");
 | 
				
			||||||
 | 
								log_warnx("%s: %.*s", __progname,
 | 
				
			||||||
 | 
								    (int) hdr.size, BUFFER_OUT(cctx.srv_in));	
 | 
				
			||||||
 | 
								buffer_remove(cctx.srv_in, hdr.size);
 | 
				
			||||||
 | 
								exit(1);
 | 
				
			||||||
 | 
							case MSG_READY:
 | 
				
			||||||
 | 
								exit(client_main(&cctx));
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								fatalx("unexpected command");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (found != NULL)
 | 
						/* NOTREACHED */
 | 
				
			||||||
		exit(found->fn(path, argc, argv));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	exit(usage(NULL));
 | 
					usage:
 | 
				
			||||||
 | 
						usage(&cause, NULL);
 | 
				
			||||||
 | 
						fprintf(stderr, "%s\n", cause);
 | 
				
			||||||
 | 
						exit(1);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										194
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										194
									
								
								tmux.h
									
									
									
									
									
								
							@@ -1,4 +1,4 @@
 | 
				
			|||||||
/* $Id: tmux.h,v 1.37 2007-10-03 12:43:47 nicm Exp $ */
 | 
					/* $Id: tmux.h,v 1.38 2007-10-03 21:31:07 nicm Exp $ */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
					 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
				
			||||||
@@ -259,28 +259,17 @@ struct buffer {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/* Message codes. */
 | 
					/* Message codes. */
 | 
				
			||||||
enum hdrtype {
 | 
					enum hdrtype {
 | 
				
			||||||
	MSG_ATTACH,
 | 
						MSG_COMMAND,
 | 
				
			||||||
	MSG_DATA,
 | 
					 | 
				
			||||||
	MSG_DETACH,
 | 
					 | 
				
			||||||
	MSG_ERROR,
 | 
						MSG_ERROR,
 | 
				
			||||||
 | 
						MSG_PRINT,
 | 
				
			||||||
	MSG_EXIT,
 | 
						MSG_EXIT,
 | 
				
			||||||
 | 
						MSG_IDENTIFY,
 | 
				
			||||||
 | 
						MSG_READY,
 | 
				
			||||||
 | 
						MSG_DETACH,
 | 
				
			||||||
 | 
						MSG_RESIZE,
 | 
				
			||||||
 | 
						MSG_DATA,
 | 
				
			||||||
	MSG_KEYS,
 | 
						MSG_KEYS,
 | 
				
			||||||
	MSG_NEW,
 | 
					 | 
				
			||||||
	MSG_OKAY,
 | 
					 | 
				
			||||||
	MSG_PAUSE,
 | 
						MSG_PAUSE,
 | 
				
			||||||
	MSG_RENAME,
 | 
					 | 
				
			||||||
	MSG_SESSIONS,
 | 
					 | 
				
			||||||
	MSG_SIZE,
 | 
					 | 
				
			||||||
	MSG_WINDOWLIST,
 | 
					 | 
				
			||||||
	MSG_WINDOWS,
 | 
					 | 
				
			||||||
	MSG_BINDKEY,
 | 
					 | 
				
			||||||
	MSG_UNBINDKEY,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Message header structure. */
 | 
					 | 
				
			||||||
struct hdr {
 | 
					 | 
				
			||||||
	enum hdrtype	type;
 | 
					 | 
				
			||||||
	size_t		size;
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Session identification. */
 | 
					/* Session identification. */
 | 
				
			||||||
@@ -290,61 +279,26 @@ struct sessid {
 | 
				
			|||||||
	char		name[MAXNAMELEN];	/* empty for current */
 | 
						char		name[MAXNAMELEN];	/* empty for current */
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct new_data {
 | 
					/* Message header structure. */
 | 
				
			||||||
	char		name[MAXNAMELEN];
 | 
					struct hdr {
 | 
				
			||||||
 | 
						enum hdrtype	type;
 | 
				
			||||||
 | 
						size_t		size;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct msg_command_data {
 | 
				
			||||||
 | 
						struct sessid   sid;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct msg_identify_data {
 | 
				
			||||||
	u_int		sx;
 | 
						u_int		sx;
 | 
				
			||||||
	u_int		sy;
 | 
						u_int		sy;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct attach_data {
 | 
					struct msg_resize_data {
 | 
				
			||||||
	struct sessid	sid;
 | 
					 | 
				
			||||||
	u_int		sx;
 | 
						u_int		sx;
 | 
				
			||||||
	u_int		sy;
 | 
						u_int		sy;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct sessions_data {
 | 
					 | 
				
			||||||
	u_int		sessions;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct sessions_entry {
 | 
					 | 
				
			||||||
	char		name[MAXNAMELEN];
 | 
					 | 
				
			||||||
	time_t		tim;
 | 
					 | 
				
			||||||
	u_int		windows;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct windows_data {
 | 
					 | 
				
			||||||
	struct sessid	sid;
 | 
					 | 
				
			||||||
	u_int		windows;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct windows_entry {
 | 
					 | 
				
			||||||
	u_int		idx;
 | 
					 | 
				
			||||||
	char		tty[TTY_NAME_MAX];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	char		name[MAXNAMELEN];
 | 
					 | 
				
			||||||
	char		title[MAXTITLELEN];
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct size_data {
 | 
					 | 
				
			||||||
	u_int		sx;
 | 
					 | 
				
			||||||
	u_int		sy;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct rename_data {
 | 
					 | 
				
			||||||
	int		idx;
 | 
					 | 
				
			||||||
	struct sessid	sid;
 | 
					 | 
				
			||||||
	char		newname[MAXNAMELEN];
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct bind_data {
 | 
					 | 
				
			||||||
	int		key;
 | 
					 | 
				
			||||||
	char		cmd[MAXNAMELEN];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	int		flags;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	u_int		num;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Attributes. */
 | 
					/* Attributes. */
 | 
				
			||||||
#define ATTR_BRIGHT 0x1
 | 
					#define ATTR_BRIGHT 0x1
 | 
				
			||||||
#define ATTR_DIM 0x2
 | 
					#define ATTR_DIM 0x2
 | 
				
			||||||
@@ -460,7 +414,7 @@ ARRAY_DECL(windows, struct window *);
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/* Client session. */
 | 
					/* Client session. */
 | 
				
			||||||
struct session {
 | 
					struct session {
 | 
				
			||||||
	char		 name[MAXNAMELEN];
 | 
						char		*name;
 | 
				
			||||||
	time_t		 tim;
 | 
						time_t		 tim;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct window	*window;
 | 
						struct window	*window;
 | 
				
			||||||
@@ -478,7 +432,10 @@ struct client {
 | 
				
			|||||||
	u_int		 sx;
 | 
						u_int		 sx;
 | 
				
			||||||
	u_int		 sy;
 | 
						u_int		 sy;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	int		 prefix;	/* waiting for command */
 | 
					#define CLIENT_TERMINAL 0x1
 | 
				
			||||||
 | 
					#define CLIENT_PREFIX 0x2
 | 
				
			||||||
 | 
					#define CLIENT_HOLD 0x4
 | 
				
			||||||
 | 
						int		 flags;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct session	*session;
 | 
						struct session	*session;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@@ -493,50 +450,85 @@ struct client_ctx {
 | 
				
			|||||||
	int		 loc_fd;
 | 
						int		 loc_fd;
 | 
				
			||||||
	struct buffer	*loc_in;
 | 
						struct buffer	*loc_in;
 | 
				
			||||||
	struct buffer	*loc_out;
 | 
						struct buffer	*loc_out;
 | 
				
			||||||
 | 
					 | 
				
			||||||
	struct winsize	 ws;
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Key command. */
 | 
					/* Key/command line command. */
 | 
				
			||||||
 | 
					enum cmd_type {
 | 
				
			||||||
 | 
						CMD_NEWSESSION,
 | 
				
			||||||
 | 
						CMD_DETACHSESSION,
 | 
				
			||||||
 | 
						CMD_LISTSESSIONS,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct cmd_ctx {
 | 
				
			||||||
 | 
						struct client  *client;
 | 
				
			||||||
 | 
						struct session *session;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void		(*print)(struct cmd_ctx *, const char *, ...);
 | 
				
			||||||
 | 
						void		(*error)(struct cmd_ctx *, const char *, ...);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define CMD_KEY 0x1
 | 
				
			||||||
 | 
						int		flags;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct cmd_entry {
 | 
				
			||||||
 | 
						enum cmd_type	 type;
 | 
				
			||||||
 | 
						const char	*name;
 | 
				
			||||||
 | 
						const char	*alias;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define CMD_STARTSERVER 0x1
 | 
				
			||||||
 | 
					#define CMD_NOSESSION 0x2
 | 
				
			||||||
 | 
						int		 flags;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int		 (*parse)(void **, int, char **, char **);
 | 
				
			||||||
 | 
						const char 	*(*usage)(void);
 | 
				
			||||||
 | 
						void		 (*exec)(void *, struct cmd_ctx *);
 | 
				
			||||||
 | 
						void		 (*send)(void *, struct buffer *);
 | 
				
			||||||
 | 
						void	         (*recv)(void **, struct buffer *);
 | 
				
			||||||
 | 
						void		 (*free)(void *);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct cmd {
 | 
					struct cmd {
 | 
				
			||||||
	int	key;
 | 
						const struct cmd_entry *entry;
 | 
				
			||||||
	void	(*fn)(struct client *, struct cmd *);
 | 
						void	       	*data;
 | 
				
			||||||
	u_int	num;
 | 
					 | 
				
			||||||
	char   *str;
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Key binding. */
 | 
					/* Key binding. */
 | 
				
			||||||
struct bind {
 | 
					struct binding {
 | 
				
			||||||
	const char	*name;
 | 
						int		 key;
 | 
				
			||||||
	void		 (*fn)(struct client *, struct cmd *);
 | 
						struct cmd	*cmd;
 | 
				
			||||||
	
 | 
					 | 
				
			||||||
#define BIND_USER 0x1
 | 
					 | 
				
			||||||
#define BIND_NUMBER 0x2
 | 
					 | 
				
			||||||
#define BIND_STRING 0x4
 | 
					 | 
				
			||||||
	int		 flags;
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* tmux.c */
 | 
					/* tmux.c */
 | 
				
			||||||
extern volatile sig_atomic_t sigwinch;
 | 
					extern volatile sig_atomic_t sigwinch;
 | 
				
			||||||
extern volatile sig_atomic_t sigterm;
 | 
					extern volatile sig_atomic_t sigterm;
 | 
				
			||||||
 | 
					extern int	prefix_key;
 | 
				
			||||||
extern int	debug_level;
 | 
					extern int	debug_level;
 | 
				
			||||||
extern u_int	status_lines;
 | 
					extern u_int	status_lines;
 | 
				
			||||||
extern char    *default_command;
 | 
					extern char    *default_command;
 | 
				
			||||||
int	 	 usage(const char *, ...);
 | 
					void		 usage(char **, const char *, ...);
 | 
				
			||||||
void		 logfile(const char *);
 | 
					void		 logfile(const char *);
 | 
				
			||||||
void		 siginit(void);
 | 
					void		 siginit(void);
 | 
				
			||||||
void		 sigreset(void);
 | 
					void		 sigreset(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* op.c */
 | 
					/* cmd.c */
 | 
				
			||||||
int	 op_new_session(char *, int, char **);
 | 
					struct cmd	*cmd_parse(int, char **, char **);
 | 
				
			||||||
int	 op_attach(char *, int, char **);
 | 
					void		 cmd_exec(struct cmd *, struct cmd_ctx *);
 | 
				
			||||||
int	 op_rename_window(char *, int, char **);
 | 
					void		 cmd_send(struct cmd *, struct buffer *);
 | 
				
			||||||
int	 op_bind_key(char *, int, char **);
 | 
					struct cmd	*cmd_recv(struct buffer *);
 | 
				
			||||||
int	 op_unbind_key(char *, int, char **);
 | 
					void		 cmd_free(struct cmd *);
 | 
				
			||||||
 | 
					void		 cmd_send_string(struct buffer *, const char *);
 | 
				
			||||||
 | 
					char		*cmd_recv_string(struct buffer *);
 | 
				
			||||||
 | 
					extern const struct cmd_entry  cmd_new_session_entry;
 | 
				
			||||||
 | 
					extern const struct cmd_entry  cmd_detach_session_entry;
 | 
				
			||||||
 | 
					extern const struct cmd_entry  cmd_list_sessions_entry;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* op-list.c */
 | 
					/* bind.c */
 | 
				
			||||||
int	 op_list_sessions(char *, int, char **);
 | 
					const struct bind *cmdx_lookup_bind(const char *);
 | 
				
			||||||
int	 op_list_windows(char *, int, char **);
 | 
					void	 cmdx_add_bind(int, u_int, char *, const struct bind *);
 | 
				
			||||||
 | 
					void	 cmdx_remove_bind(int);
 | 
				
			||||||
 | 
					void     cmdx_init(void);
 | 
				
			||||||
 | 
					void     cmdx_free(void);
 | 
				
			||||||
 | 
					void	 cmdx_dispatch(struct client *, int);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* client.c */
 | 
					/* client.c */
 | 
				
			||||||
int	 client_init(char *, struct client_ctx *, int);
 | 
					int	 client_init(char *, struct client_ctx *, int);
 | 
				
			||||||
@@ -552,14 +544,12 @@ void	 client_write_server2(
 | 
				
			|||||||
    	     struct client_ctx *, enum hdrtype, void *, size_t, void *, size_t);
 | 
					    	     struct client_ctx *, enum hdrtype, void *, size_t, void *, size_t);
 | 
				
			||||||
void	 client_fill_sessid(struct sessid *, char [MAXNAMELEN]);
 | 
					void	 client_fill_sessid(struct sessid *, char [MAXNAMELEN]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* cmd.c */
 | 
					/* key-bindings.c */
 | 
				
			||||||
extern int cmd_prefix;
 | 
					void	 key_bindings_add(int, struct cmd *);
 | 
				
			||||||
const struct bind *cmd_lookup_bind(const char *);
 | 
					void	 key_bindings_remove(int);
 | 
				
			||||||
void	 cmd_add_bind(int, u_int, char *, const struct bind *);
 | 
					void	 key_bindings_init(void);
 | 
				
			||||||
void	 cmd_remove_bind(int);
 | 
					void	 key_bindings_free(void);
 | 
				
			||||||
void     cmd_init(void);
 | 
					void	 key_bindings_dispatch(int, struct client *);
 | 
				
			||||||
void     cmd_free(void);
 | 
					 | 
				
			||||||
void	 cmd_dispatch(struct client *, int);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* key-string.c */
 | 
					/* key-string.c */
 | 
				
			||||||
int	 key_string_lookup(const char *);
 | 
					int	 key_string_lookup(const char *);
 | 
				
			||||||
@@ -582,7 +572,7 @@ void	 server_write_client2(struct client *,
 | 
				
			|||||||
void	 server_write_clients(
 | 
					void	 server_write_clients(
 | 
				
			||||||
    	     struct window *, enum hdrtype, const void *, size_t);
 | 
					    	     struct window *, enum hdrtype, const void *, size_t);
 | 
				
			||||||
void	 server_window_changed(struct client *);
 | 
					void	 server_window_changed(struct client *);
 | 
				
			||||||
void	 server_draw_client(struct client *, u_int, u_int);
 | 
					void	 server_draw_client(struct client *);
 | 
				
			||||||
void	 server_draw_status(struct client *);
 | 
					void	 server_draw_status(struct client *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* status.c */
 | 
					/* status.c */
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user