mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 09:17:31 +00:00 
			
		
		
		
	Change command format.
This commit is contained in:
		
							
								
								
									
										29
									
								
								NOTES
									
									
									
									
									
								
							
							
						
						
									
										29
									
								
								NOTES
									
									
									
									
									
								
							@@ -11,10 +11,31 @@ Commands: d detach
 | 
			
		||||
There is one default server process per user which puts its socket in
 | 
			
		||||
/tmp/tmux-UID. It is created the first time tmux is run and subsequent
 | 
			
		||||
invocations will connect to the same server. The server holds multiple
 | 
			
		||||
sessions, call tmux with "-n <session name>" to create a session or attach to
 | 
			
		||||
an existing session. All the sessions may be listed with -l, or the windows of
 | 
			
		||||
a single session with "-ln <session name>". Sessions are destroyed when no
 | 
			
		||||
windows remain attached to them.
 | 
			
		||||
sessions.
 | 
			
		||||
 | 
			
		||||
Syntax is: tmux [-v] [-n name] [-s path] command
 | 
			
		||||
 | 
			
		||||
The command is either list, new or attach. Create a new session with:
 | 
			
		||||
 | 
			
		||||
	tmux new
 | 
			
		||||
 | 
			
		||||
Optionally giving it a name with:
 | 
			
		||||
 | 
			
		||||
	tmux -n <session name> new
 | 
			
		||||
 | 
			
		||||
Attach to a previous session with:
 | 
			
		||||
 | 
			
		||||
	tmux -n <session name> attach
 | 
			
		||||
 | 
			
		||||
List all sessions with:
 | 
			
		||||
 | 
			
		||||
	tmux list
 | 
			
		||||
 | 
			
		||||
Or the windows of a single session with:
 | 
			
		||||
 | 
			
		||||
	tmux -n <session name> list
 | 
			
		||||
 | 
			
		||||
Sessions are destroyed when no windows remain attached to them.
 | 
			
		||||
 | 
			
		||||
Another server process can be used by specifying an alternative socket path with
 | 
			
		||||
"-s <path>" but it shouldn't normally be required.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										14
									
								
								command.c
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								command.c
									
									
									
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
/* $Id: command.c,v 1.2 2007-08-27 10:30:28 nicm Exp $ */
 | 
			
		||||
/* $Id: command.c,v 1.3 2007-08-27 13:45:26 nicm Exp $ */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
			
		||||
@@ -83,7 +83,7 @@ cmd_fn_select(struct buffer *srv_out, int arg)
 | 
			
		||||
 	struct hdr		hdr;
 | 
			
		||||
	struct select_data	data;
 | 
			
		||||
 | 
			
		||||
	hdr.code = MSG_SELECT;
 | 
			
		||||
	hdr.type = MSG_SELECT;
 | 
			
		||||
	hdr.size = sizeof data;
 | 
			
		||||
	buffer_write(srv_out, &hdr, sizeof hdr);
 | 
			
		||||
	data.idx = arg;
 | 
			
		||||
@@ -98,7 +98,7 @@ cmd_fn_create(struct buffer *srv_out, unused int arg)
 | 
			
		||||
{
 | 
			
		||||
 	struct hdr	hdr;
 | 
			
		||||
 | 
			
		||||
	hdr.code = MSG_CREATE;
 | 
			
		||||
	hdr.type = MSG_CREATE;
 | 
			
		||||
	hdr.size = 0;
 | 
			
		||||
	buffer_write(srv_out, &hdr, sizeof hdr);
 | 
			
		||||
 | 
			
		||||
@@ -118,7 +118,7 @@ cmd_fn_next(struct buffer *srv_out, unused int arg)
 | 
			
		||||
{
 | 
			
		||||
 	struct hdr	hdr;
 | 
			
		||||
 | 
			
		||||
	hdr.code = MSG_NEXT;
 | 
			
		||||
	hdr.type = MSG_NEXT;
 | 
			
		||||
	hdr.size = 0;
 | 
			
		||||
	buffer_write(srv_out, &hdr, sizeof hdr);
 | 
			
		||||
 | 
			
		||||
@@ -131,7 +131,7 @@ cmd_fn_previous(struct buffer *srv_out, unused int arg)
 | 
			
		||||
{
 | 
			
		||||
 	struct hdr	hdr;
 | 
			
		||||
 | 
			
		||||
	hdr.code = MSG_PREVIOUS;
 | 
			
		||||
	hdr.type = MSG_PREVIOUS;
 | 
			
		||||
	hdr.size = 0;
 | 
			
		||||
	buffer_write(srv_out, &hdr, sizeof hdr);
 | 
			
		||||
 | 
			
		||||
@@ -144,7 +144,7 @@ cmd_fn_refresh(struct buffer *srv_out, unused int arg)
 | 
			
		||||
{
 | 
			
		||||
 	struct hdr	hdr;
 | 
			
		||||
 | 
			
		||||
	hdr.code = MSG_REFRESH;
 | 
			
		||||
	hdr.type = MSG_REFRESH;
 | 
			
		||||
	hdr.size = 0;
 | 
			
		||||
	buffer_write(srv_out, &hdr, sizeof hdr);
 | 
			
		||||
 | 
			
		||||
@@ -157,7 +157,7 @@ cmd_fn_rename(struct buffer *srv_out, unused int arg)
 | 
			
		||||
{
 | 
			
		||||
 	struct hdr	hdr;
 | 
			
		||||
 | 
			
		||||
	hdr.code = MSG_RENAME;
 | 
			
		||||
	hdr.type = MSG_RENAME;
 | 
			
		||||
	hdr.size = 0;
 | 
			
		||||
	buffer_write(srv_out, &hdr, sizeof hdr);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										122
									
								
								server.c
									
									
									
									
									
								
							
							
						
						
									
										122
									
								
								server.c
									
									
									
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
/* $Id: server.c,v 1.5 2007-08-27 12:05:15 nicm Exp $ */
 | 
			
		||||
/* $Id: server.c,v 1.6 2007-08-27 13:45:26 nicm Exp $ */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
			
		||||
@@ -63,7 +63,8 @@ void		 lost_window(struct window *);
 | 
			
		||||
void		 changed_window(struct client *);
 | 
			
		||||
void		 draw_client(struct client *, u_int, u_int);
 | 
			
		||||
void	 	 process_client(struct client *);
 | 
			
		||||
void		 process_identify_msg(struct client *, struct hdr *);
 | 
			
		||||
void		 process_new_msg(struct client *, struct hdr *);
 | 
			
		||||
void		 process_attach_msg(struct client *, struct hdr *);
 | 
			
		||||
void		 process_create_msg(struct client *, struct hdr *);
 | 
			
		||||
void		 process_next_msg(struct client *, struct hdr *);
 | 
			
		||||
void		 process_previous_msg(struct client *, struct hdr *);
 | 
			
		||||
@@ -388,11 +389,11 @@ write_message(struct client *c, const char *fmt, ...)
 | 
			
		||||
		input_store8(c->out, ' ');
 | 
			
		||||
 | 
			
		||||
	size = BUFFER_USED(c->out) - size;
 | 
			
		||||
	hdr.code = MSG_OUTPUT;
 | 
			
		||||
	hdr.type = MSG_OUTPUT;
 | 
			
		||||
	hdr.size = size;
 | 
			
		||||
	memcpy(BUFFER_IN(c->out) - size - sizeof hdr, &hdr, sizeof hdr);
 | 
			
		||||
 | 
			
		||||
	hdr.code = MSG_PAUSE;
 | 
			
		||||
	hdr.type = MSG_PAUSE;
 | 
			
		||||
	hdr.size = 0;
 | 
			
		||||
	buffer_write(c->out, &hdr, sizeof hdr);
 | 
			
		||||
 | 
			
		||||
@@ -403,7 +404,7 @@ write_message(struct client *c, const char *fmt, ...)
 | 
			
		||||
	screen_draw(&c->session->window->screen, c->out, c->sy - 1, c->sy - 1);
 | 
			
		||||
 | 
			
		||||
	size = BUFFER_USED(c->out) - size;
 | 
			
		||||
	hdr.code = MSG_OUTPUT;
 | 
			
		||||
	hdr.type = MSG_OUTPUT;
 | 
			
		||||
	hdr.size = size;
 | 
			
		||||
	memcpy(BUFFER_IN(c->out) - size - sizeof hdr, &hdr, sizeof hdr);
 | 
			
		||||
}
 | 
			
		||||
@@ -452,7 +453,7 @@ user_start(struct client *c, const char *prompt, const char *now,
 | 
			
		||||
	input_store_zero(c->out, CODE_CURSORON);
 | 
			
		||||
 | 
			
		||||
	size = BUFFER_USED(c->out) - size;
 | 
			
		||||
	hdr.code = MSG_OUTPUT;
 | 
			
		||||
	hdr.type = MSG_OUTPUT;
 | 
			
		||||
	hdr.size = size;
 | 
			
		||||
	memcpy(BUFFER_IN(c->out) - size - sizeof hdr, &hdr, sizeof hdr);
 | 
			
		||||
}
 | 
			
		||||
@@ -589,7 +590,7 @@ user_input(struct client *c, size_t in)
 | 
			
		||||
 | 
			
		||||
	size = BUFFER_USED(c->out) - size;
 | 
			
		||||
	if (size != 0) {
 | 
			
		||||
		hdr.code = MSG_OUTPUT;
 | 
			
		||||
		hdr.type = MSG_OUTPUT;
 | 
			
		||||
		hdr.size = size;
 | 
			
		||||
		memcpy(BUFFER_IN(c->out) - size - sizeof hdr, &hdr, sizeof hdr);
 | 
			
		||||
	} else
 | 
			
		||||
@@ -602,7 +603,7 @@ write_client(struct client *c, u_int cmd, void *buf, size_t len)
 | 
			
		||||
{
 | 
			
		||||
	struct hdr	 hdr;
 | 
			
		||||
 | 
			
		||||
	hdr.code = cmd;
 | 
			
		||||
	hdr.type = cmd;
 | 
			
		||||
	hdr.size = len;
 | 
			
		||||
 | 
			
		||||
	buffer_write(c->out, &hdr, sizeof hdr);
 | 
			
		||||
@@ -617,7 +618,7 @@ write_client2(struct client *c,
 | 
			
		||||
{
 | 
			
		||||
	struct hdr	 hdr;
 | 
			
		||||
 | 
			
		||||
	hdr.code = cmd;
 | 
			
		||||
	hdr.type = cmd;
 | 
			
		||||
	hdr.size = len1 + len2;
 | 
			
		||||
 | 
			
		||||
	buffer_write(c->out, &hdr, sizeof hdr);
 | 
			
		||||
@@ -635,7 +636,7 @@ write_clients(struct window *w, u_int cmd, void *buf, size_t len)
 | 
			
		||||
 	struct hdr	 hdr;
 | 
			
		||||
	u_int		 i;
 | 
			
		||||
 | 
			
		||||
	hdr.code = cmd;
 | 
			
		||||
	hdr.type = cmd;
 | 
			
		||||
	hdr.size = len;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
 | 
			
		||||
@@ -714,7 +715,7 @@ draw_client(struct client *c, u_int py_upper, u_int py_lower)
 | 
			
		||||
	size = BUFFER_USED(c->out) - size;
 | 
			
		||||
	log_debug("redrawing screen, %zu bytes", size);
 | 
			
		||||
	if (size != 0) {
 | 
			
		||||
		hdr.code = MSG_OUTPUT;
 | 
			
		||||
		hdr.type = MSG_OUTPUT;
 | 
			
		||||
		hdr.size = size;
 | 
			
		||||
		memcpy(
 | 
			
		||||
		    BUFFER_IN(c->out) - size - sizeof hdr, &hdr, sizeof hdr);
 | 
			
		||||
@@ -735,9 +736,12 @@ process_client(struct client *c)
 | 
			
		||||
		return;
 | 
			
		||||
	buffer_remove(c->in, sizeof hdr);
 | 
			
		||||
 | 
			
		||||
	switch (hdr.code) {
 | 
			
		||||
	case MSG_IDENTIFY:
 | 
			
		||||
		process_identify_msg(c, &hdr);
 | 
			
		||||
	switch (hdr.type) {
 | 
			
		||||
	case MSG_NEW:
 | 
			
		||||
		process_new_msg(c, &hdr);
 | 
			
		||||
		break;
 | 
			
		||||
	case MSG_ATTACH:
 | 
			
		||||
		process_attach_msg(c, &hdr);
 | 
			
		||||
		break;
 | 
			
		||||
	case MSG_CREATE:
 | 
			
		||||
		process_create_msg(c, &hdr);
 | 
			
		||||
@@ -769,19 +773,23 @@ process_client(struct client *c)
 | 
			
		||||
	case MSG_RENAME:
 | 
			
		||||
		process_rename_msg(c, &hdr);
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		fatalx("unexpected message");
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Identify message from client. */
 | 
			
		||||
/* New message from client. */
 | 
			
		||||
void
 | 
			
		||||
process_identify_msg(struct client *c, struct hdr *hdr)
 | 
			
		||||
process_new_msg(struct client *c, struct hdr *hdr)
 | 
			
		||||
{
 | 
			
		||||
	struct identify_data	 data;
 | 
			
		||||
	const char		*shell;
 | 
			
		||||
	char			*cmd;
 | 
			
		||||
	struct new_data	 data;
 | 
			
		||||
	const char      *shell;
 | 
			
		||||
	char		*cmd, *msg;
 | 
			
		||||
	
 | 
			
		||||
	if (c->session != NULL)
 | 
			
		||||
		return;
 | 
			
		||||
	if (hdr->size != sizeof data)
 | 
			
		||||
		fatalx("bad MSG_IDENTIFY size");
 | 
			
		||||
		fatalx("bad MSG_NEW size");
 | 
			
		||||
	buffer_read(c->in, &data, hdr->size);
 | 
			
		||||
 | 
			
		||||
	c->sx = data.sx;
 | 
			
		||||
@@ -790,21 +798,57 @@ process_identify_msg(struct client *c, struct hdr *hdr)
 | 
			
		||||
	c->sy = data.sy;
 | 
			
		||||
	if (c->sy == 0)
 | 
			
		||||
		c->sy = 25;
 | 
			
		||||
	
 | 
			
		||||
	/* Try and find session or create if not found. */
 | 
			
		||||
	c->session = session_find(data.name);
 | 
			
		||||
	if (c->session == NULL) {
 | 
			
		||||
		shell = getenv("SHELL");
 | 
			
		||||
		if (shell == NULL)
 | 
			
		||||
			shell = "/bin/ksh";
 | 
			
		||||
		xasprintf(&cmd, "%s -l", shell);
 | 
			
		||||
		c->session =
 | 
			
		||||
		    session_create(data.name, cmd, c->sx, c->sy);
 | 
			
		||||
		xfree(cmd);
 | 
			
		||||
 | 
			
		||||
	if (*data.name != '\0' && session_find(data.name) != NULL) {
 | 
			
		||||
		xasprintf(&msg, "duplicate session: %s", data.name);
 | 
			
		||||
		write_client(c, MSG_READY, msg, strlen(msg));
 | 
			
		||||
		xfree(msg);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	shell = getenv("SHELL");
 | 
			
		||||
	if (shell == NULL)
 | 
			
		||||
		shell = "/bin/ksh";
 | 
			
		||||
	xasprintf(&cmd, "%s -l", shell);
 | 
			
		||||
	c->session = session_create(data.name, cmd, c->sx, c->sy);
 | 
			
		||||
	if (c->session == NULL)
 | 
			
		||||
		fatalx("session_create failed");
 | 
			
		||||
	xfree(cmd);
 | 
			
		||||
	
 | 
			
		||||
	write_client(c, MSG_READY, NULL, 0);
 | 
			
		||||
	draw_client(c, 0, c->sy - 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Attach message from client. */
 | 
			
		||||
void
 | 
			
		||||
process_attach_msg(struct client *c, struct hdr *hdr)
 | 
			
		||||
{
 | 
			
		||||
	struct attach_data	 data;
 | 
			
		||||
	char			*msg;
 | 
			
		||||
	
 | 
			
		||||
	if (c->session != NULL)
 | 
			
		||||
		return;
 | 
			
		||||
	if (hdr->size != sizeof data)
 | 
			
		||||
		fatalx("bad MSG_ATTACH size");
 | 
			
		||||
	buffer_read(c->in, &data, hdr->size);
 | 
			
		||||
 | 
			
		||||
	c->sx = data.sx;
 | 
			
		||||
	if (c->sx == 0)
 | 
			
		||||
		c->sx = 80;
 | 
			
		||||
	c->sy = data.sy;
 | 
			
		||||
	if (c->sy == 0)
 | 
			
		||||
		c->sy = 25;
 | 
			
		||||
 | 
			
		||||
	if (*data.name != '\0')
 | 
			
		||||
		c->session = session_find(data.name);
 | 
			
		||||
	if (c->session == NULL) {
 | 
			
		||||
		xasprintf(&msg, "session not found: %s", data.name);
 | 
			
		||||
		write_client(c, MSG_READY, msg, strlen(msg));
 | 
			
		||||
		xfree(msg);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	write_client(c, MSG_READY, NULL, 0);
 | 
			
		||||
	draw_client(c, 0, c->sy - 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -816,7 +860,7 @@ process_create_msg(struct client *c, struct hdr *hdr)
 | 
			
		||||
	char		*cmd;
 | 
			
		||||
 | 
			
		||||
	if (c->session == NULL)
 | 
			
		||||
		fatalx("MSG_CREATE before identified");
 | 
			
		||||
		return;
 | 
			
		||||
	if (hdr->size != 0)
 | 
			
		||||
		fatalx("bad MSG_CREATE size");
 | 
			
		||||
 | 
			
		||||
@@ -836,7 +880,7 @@ void
 | 
			
		||||
process_next_msg(struct client *c, struct hdr *hdr)
 | 
			
		||||
{
 | 
			
		||||
	if (c->session == NULL)
 | 
			
		||||
		fatalx("MSG_NEXT before identified");
 | 
			
		||||
		return;
 | 
			
		||||
	if (hdr->size != 0)
 | 
			
		||||
		fatalx("bad MSG_NEXT size");
 | 
			
		||||
 | 
			
		||||
@@ -851,7 +895,7 @@ void
 | 
			
		||||
process_previous_msg(struct client *c, struct hdr *hdr)
 | 
			
		||||
{
 | 
			
		||||
	if (c->session == NULL)
 | 
			
		||||
		fatalx("MSG_PREVIOUS before identified");
 | 
			
		||||
		return;
 | 
			
		||||
	if (hdr->size != 0)
 | 
			
		||||
		fatalx("bad MSG_PREVIOUS size");
 | 
			
		||||
 | 
			
		||||
@@ -868,7 +912,7 @@ process_size_msg(struct client *c, struct hdr *hdr)
 | 
			
		||||
	struct size_data	data;
 | 
			
		||||
 | 
			
		||||
	if (c->session == NULL)
 | 
			
		||||
		fatalx("MSG_SIZE before identified");
 | 
			
		||||
		return;
 | 
			
		||||
	if (hdr->size != sizeof data)
 | 
			
		||||
		fatalx("bad MSG_SIZE size");
 | 
			
		||||
	buffer_read(c->in, &data, hdr->size);
 | 
			
		||||
@@ -889,7 +933,7 @@ void
 | 
			
		||||
process_input_msg(struct client *c, struct hdr *hdr)
 | 
			
		||||
{
 | 
			
		||||
	if (c->session == NULL)
 | 
			
		||||
		fatalx("MSG_INPUT before identified");
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	if (c->prompt == NULL)
 | 
			
		||||
		window_input(c->session->window, c->in, hdr->size);
 | 
			
		||||
@@ -904,7 +948,7 @@ process_refresh_msg(struct client *c, struct hdr *hdr)
 | 
			
		||||
	struct refresh_data	data;
 | 
			
		||||
 | 
			
		||||
	if (c->session == NULL)
 | 
			
		||||
		fatalx("MSG_REFRESH before identified");
 | 
			
		||||
		return;
 | 
			
		||||
	if (hdr->size != 0 && hdr->size != sizeof data)
 | 
			
		||||
		fatalx("bad MSG_REFRESH size");
 | 
			
		||||
 | 
			
		||||
@@ -918,7 +962,7 @@ process_select_msg(struct client *c, struct hdr *hdr)
 | 
			
		||||
	struct select_data	data;
 | 
			
		||||
 | 
			
		||||
	if (c->session == NULL)
 | 
			
		||||
		fatalx("MSG_SELECT before identified");
 | 
			
		||||
		return;
 | 
			
		||||
	if (hdr->size != sizeof data)
 | 
			
		||||
		fatalx("bad MSG_SELECT size");
 | 
			
		||||
	buffer_read(c->in, &data, hdr->size);
 | 
			
		||||
@@ -1014,7 +1058,7 @@ void
 | 
			
		||||
process_rename_msg(struct client *c, struct hdr *hdr)
 | 
			
		||||
{
 | 
			
		||||
	if (c->session == NULL)
 | 
			
		||||
		fatalx("MSG_RENAME before identified");
 | 
			
		||||
		return;
 | 
			
		||||
	if (hdr->size != 0)
 | 
			
		||||
		fatalx("bad MSG_RENAME size");
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										20
									
								
								session.c
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								session.c
									
									
									
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
/* $Id: session.c,v 1.4 2007-08-27 12:05:15 nicm Exp $ */
 | 
			
		||||
/* $Id: session.c,v 1.5 2007-08-27 13:45:26 nicm Exp $ */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
			
		||||
@@ -50,8 +50,7 @@ session_create(const char *name, const char *cmd, u_int sx, u_int sy)
 | 
			
		||||
	u_int		 i;
 | 
			
		||||
 | 
			
		||||
	s = xmalloc(sizeof *s);
 | 
			
		||||
	s->tim = time(NULL); 
 | 
			
		||||
	strlcpy(s->name, name, sizeof s->name);
 | 
			
		||||
	s->tim = time(NULL);
 | 
			
		||||
	ARRAY_INIT(&s->windows);
 | 
			
		||||
 | 
			
		||||
	if (session_new(s, cmd, sx, sy) != 0) {
 | 
			
		||||
@@ -60,13 +59,19 @@ session_create(const char *name, const char *cmd, u_int sx, u_int sy)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
 | 
			
		||||
		s = ARRAY_ITEM(&sessions, i);
 | 
			
		||||
		if (s == NULL) {
 | 
			
		||||
		if (ARRAY_ITEM(&sessions, i) == NULL) {
 | 
			
		||||
			ARRAY_SET(&sessions, i, s);
 | 
			
		||||
			return (s);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	ARRAY_ADD(&sessions, s);
 | 
			
		||||
	if (i == ARRAY_LENGTH(&sessions))
 | 
			
		||||
		ARRAY_ADD(&sessions, s);
 | 
			
		||||
 | 
			
		||||
	if (*name != '\0')
 | 
			
		||||
		strlcpy(s->name, name, sizeof s->name);
 | 
			
		||||
	else
 | 
			
		||||
		xsnprintf(s->name, sizeof s->name, "session-%u", i);
 | 
			
		||||
 | 
			
		||||
	return (s);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -128,7 +133,6 @@ session_detach(struct session *s, struct window *w)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	window_remove(&s->windows, w);
 | 
			
		||||
	return (0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Flush session if it is empty. */
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										292
									
								
								tmux.c
									
									
									
									
									
								
							
							
						
						
									
										292
									
								
								tmux.c
									
									
									
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
/* $Id: tmux.c,v 1.2 2007-07-25 23:13:18 nicm Exp $ */
 | 
			
		||||
/* $Id: tmux.c,v 1.3 2007-08-27 13:45:26 nicm Exp $ */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
			
		||||
@@ -40,13 +40,15 @@
 | 
			
		||||
const char	*malloc_options = "AFGJPX";
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
void		 op_new(char *, struct winsize *);
 | 
			
		||||
void		 op_attach(char *, struct winsize *);
 | 
			
		||||
int	 	 connect_server(void);
 | 
			
		||||
int		 process_server(struct buffer *);
 | 
			
		||||
int		 process_local(struct buffer *, struct buffer *);
 | 
			
		||||
int		 process_server(char **);
 | 
			
		||||
int		 process_local(void);
 | 
			
		||||
void		 sighandler(int);
 | 
			
		||||
__dead void	 usage(void);
 | 
			
		||||
__dead void	 main_list(char *);
 | 
			
		||||
void		 process_list(struct buffer *, const char *);
 | 
			
		||||
void		 process_list(const char *);
 | 
			
		||||
 | 
			
		||||
/* SIGWINCH received flag. */
 | 
			
		||||
volatile sig_atomic_t sigwinch;
 | 
			
		||||
@@ -60,11 +62,21 @@ int		 debug_level;
 | 
			
		||||
/* Path to server socket. */
 | 
			
		||||
char		 socket_path[MAXPATHLEN];
 | 
			
		||||
 | 
			
		||||
/* Server socket and buffers. */
 | 
			
		||||
int		 server_fd = -1;
 | 
			
		||||
struct buffer	*server_in;
 | 
			
		||||
struct buffer	*server_out;
 | 
			
		||||
 | 
			
		||||
/* Local socket and buffers. */
 | 
			
		||||
int		 local_fd = -1;
 | 
			
		||||
struct buffer	*local_in;
 | 
			
		||||
struct buffer	*local_out;
 | 
			
		||||
 | 
			
		||||
__dead void
 | 
			
		||||
usage(void)
 | 
			
		||||
{
 | 
			
		||||
	fprintf(stderr,
 | 
			
		||||
	    "usage: %s [-v] [-n name] [-s path]\n", __progname);
 | 
			
		||||
	    "usage: %s [-v] [-n name] [-s path] command\n", __progname);
 | 
			
		||||
        exit(1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -87,13 +99,12 @@ sighandler(int sig)
 | 
			
		||||
int
 | 
			
		||||
main(int argc, char **argv)
 | 
			
		||||
{
 | 
			
		||||
	int	 		 opt, srv_fd, loc_fd, mode, listf, n;
 | 
			
		||||
	char			*path, name[MAXNAMELEN];
 | 
			
		||||
	int	 		 opt, mode, n;
 | 
			
		||||
	char			*path, *error, name[MAXNAMELEN];
 | 
			
		||||
	FILE			*f;
 | 
			
		||||
	struct buffer		*srv_in, *srv_out, *loc_in, *loc_out;
 | 
			
		||||
	enum op			 op;
 | 
			
		||||
	struct pollfd		 pfds[2];
 | 
			
		||||
	struct hdr		 hdr;
 | 
			
		||||
	struct identify_data	 id;
 | 
			
		||||
	struct size_data	 sd;
 | 
			
		||||
	struct winsize	 	 ws;
 | 
			
		||||
	struct sigaction	 act;
 | 
			
		||||
@@ -101,13 +112,9 @@ main(int argc, char **argv)
 | 
			
		||||
 | 
			
		||||
	*name = '\0';
 | 
			
		||||
	path = NULL;
 | 
			
		||||
	listf = 0;
 | 
			
		||||
 | 
			
		||||
        while ((opt = getopt(argc, argv, "ln:s:v?")) != EOF) {
 | 
			
		||||
        while ((opt = getopt(argc, argv, "n:s:v?")) != EOF) {
 | 
			
		||||
                switch (opt) {
 | 
			
		||||
		case 'l':
 | 
			
		||||
			listf = 1;
 | 
			
		||||
			break;
 | 
			
		||||
		case 'n':
 | 
			
		||||
			if (strlcpy(name, optarg, sizeof name) >= sizeof name)
 | 
			
		||||
				errx(1, "name too long");
 | 
			
		||||
@@ -125,7 +132,17 @@ main(int argc, char **argv)
 | 
			
		||||
        }
 | 
			
		||||
	argc -= optind;
 | 
			
		||||
	argv += optind;
 | 
			
		||||
	if (argc != 0)
 | 
			
		||||
	if (argc != 1)
 | 
			
		||||
		usage();
 | 
			
		||||
 | 
			
		||||
	/* Determine command. */
 | 
			
		||||
	if (strncmp(argv[0], "list", strlen(argv[0])) == 0)
 | 
			
		||||
		op = OP_LIST;
 | 
			
		||||
	else if (strncmp(argv[0], "new", strlen(argv[0])) == 0)
 | 
			
		||||
		op = OP_NEW;
 | 
			
		||||
	else if (strncmp(argv[0], "attach", strlen(argv[0])) == 0)
 | 
			
		||||
		op = OP_ATTACH;
 | 
			
		||||
	else
 | 
			
		||||
		usage();
 | 
			
		||||
 | 
			
		||||
	/* Sort out socket path. */
 | 
			
		||||
@@ -137,18 +154,33 @@ main(int argc, char **argv)
 | 
			
		||||
		err(1, "realpath");
 | 
			
		||||
	xfree(path);
 | 
			
		||||
 | 
			
		||||
	/* Skip to list function if listing. */
 | 
			
		||||
	if (listf) {
 | 
			
		||||
		if (*name == '\0')
 | 
			
		||||
			main_list(NULL);
 | 
			
		||||
		else
 | 
			
		||||
			main_list(name);
 | 
			
		||||
	/* Start server if necessary. */
 | 
			
		||||
	if (stat(socket_path, &sb) != 0) {
 | 
			
		||||
		if (errno != ENOENT)
 | 
			
		||||
			err(1, "%s", socket_path);
 | 
			
		||||
		else if (op != OP_LIST) {
 | 
			
		||||
			if (server_start() != 0)
 | 
			
		||||
				errx(1, "couldn't start server");	
 | 
			
		||||
			sleep(1);
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		if (!S_ISSOCK(sb.st_mode))
 | 
			
		||||
			errx(1, "%s: not a socket", socket_path);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* And fill name. */
 | 
			
		||||
	if (*name == '\0') 
 | 
			
		||||
		xsnprintf(name, sizeof name, "s-%lu", (u_long) getpid());
 | 
			
		||||
	
 | 
			
		||||
	/* Connect to server. */
 | 
			
		||||
	if ((server_fd = connect_server()) == -1)
 | 
			
		||||
		errx(1, "couldn't find server");
 | 
			
		||||
	if ((mode = fcntl(server_fd, F_GETFL)) == -1)
 | 
			
		||||
		err(1, "fcntl");
 | 
			
		||||
	if (fcntl(server_fd, F_SETFL, mode|O_NONBLOCK) == -1)
 | 
			
		||||
		err(1, "fcntl");
 | 
			
		||||
	server_in = buffer_create(BUFSIZ);
 | 
			
		||||
	server_out = buffer_create(BUFSIZ);
 | 
			
		||||
 | 
			
		||||
	if (op == OP_LIST)
 | 
			
		||||
		main_list(name);
 | 
			
		||||
 | 
			
		||||
	/* Check stdin/stdout. */
 | 
			
		||||
	if (!isatty(STDIN_FILENO))
 | 
			
		||||
		errx(1, "stdin is not a tty");
 | 
			
		||||
@@ -181,42 +213,21 @@ main(int argc, char **argv)
 | 
			
		||||
	if (sigaction(SIGCHLD, &act, NULL) != 0)
 | 
			
		||||
		err(1, "sigaction");
 | 
			
		||||
 | 
			
		||||
	/* Start server if necessary. */
 | 
			
		||||
	if (stat(socket_path, &sb) != 0) {
 | 
			
		||||
		if (errno != ENOENT)
 | 
			
		||||
			err(1, "%s", socket_path);
 | 
			
		||||
		else {
 | 
			
		||||
			if (server_start() != 0)
 | 
			
		||||
				errx(1, "couldn't start server");	
 | 
			
		||||
			sleep(1);
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		if (!S_ISSOCK(sb.st_mode))
 | 
			
		||||
			errx(1, "%s: not a socket", socket_path);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Connect to server. */
 | 
			
		||||
	if ((srv_fd = connect_server()) == -1)
 | 
			
		||||
		errx(1, "couldn't find server");
 | 
			
		||||
	if ((mode = fcntl(srv_fd, F_GETFL)) == -1)
 | 
			
		||||
		err(1, "fcntl");
 | 
			
		||||
	if (fcntl(srv_fd, F_SETFL, mode|O_NONBLOCK) == -1)
 | 
			
		||||
		err(1, "fcntl");
 | 
			
		||||
	srv_in = buffer_create(BUFSIZ);
 | 
			
		||||
	srv_out = buffer_create(BUFSIZ);
 | 
			
		||||
 | 
			
		||||
	/* Find window size. */
 | 
			
		||||
	if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1)
 | 
			
		||||
		err(1, "ioctl(TIOCGWINSZ)");
 | 
			
		||||
 | 
			
		||||
	/* Send initial data. */
 | 
			
		||||
	hdr.code = MSG_IDENTIFY;
 | 
			
		||||
	hdr.size = sizeof id;
 | 
			
		||||
	buffer_write(srv_out, &hdr, sizeof hdr);
 | 
			
		||||
	strlcpy(id.name, name, sizeof id.name);
 | 
			
		||||
	id.sx = ws.ws_col;
 | 
			
		||||
	id.sy = ws.ws_row;
 | 
			
		||||
	buffer_write(srv_out, &id, hdr.size);
 | 
			
		||||
	switch (op) {
 | 
			
		||||
	case OP_NEW:
 | 
			
		||||
		op_new(name, &ws);
 | 
			
		||||
		break;
 | 
			
		||||
	case OP_ATTACH:
 | 
			
		||||
		op_attach(name, &ws);
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		fatalx("unknown op");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Start logging to file. */
 | 
			
		||||
	if (debug_level > 0) {
 | 
			
		||||
@@ -226,39 +237,36 @@ main(int argc, char **argv)
 | 
			
		||||
		log_open(f, LOG_USER, debug_level);
 | 
			
		||||
		xfree(path);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Initialise terminal. */
 | 
			
		||||
	loc_fd = local_init(&loc_in, &loc_out);
 | 
			
		||||
	setproctitle("client (%s)", name);
 | 
			
		||||
 | 
			
		||||
	/* Main loop. */
 | 
			
		||||
	n = 0;
 | 
			
		||||
	while (!sigterm) {
 | 
			
		||||
		/* Handle SIGWINCH if necessary. */
 | 
			
		||||
		if (sigwinch) {
 | 
			
		||||
		if (local_fd != -1 && sigwinch) {
 | 
			
		||||
			if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1)
 | 
			
		||||
				fatal("ioctl failed");
 | 
			
		||||
 | 
			
		||||
			hdr.code = MSG_SIZE;
 | 
			
		||||
			hdr.type = MSG_SIZE;
 | 
			
		||||
			hdr.size = sizeof sd;
 | 
			
		||||
			buffer_write(srv_out, &hdr, sizeof hdr);
 | 
			
		||||
			buffer_write(server_out, &hdr, sizeof hdr);
 | 
			
		||||
			sd.sx = ws.ws_col;
 | 
			
		||||
			sd.sy = ws.ws_row;
 | 
			
		||||
			buffer_write(srv_out, &sd, hdr.size);
 | 
			
		||||
			buffer_write(server_out, &sd, hdr.size);
 | 
			
		||||
 | 
			
		||||
			sigwinch = 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* Set up pollfds. */
 | 
			
		||||
		pfds[0].fd = srv_fd;
 | 
			
		||||
		pfds[0].fd = server_fd;
 | 
			
		||||
		pfds[0].events = POLLIN;
 | 
			
		||||
		if (BUFFER_USED(srv_out) > 0)
 | 
			
		||||
		if (BUFFER_USED(server_out) > 0)
 | 
			
		||||
			pfds[0].events |= POLLOUT;
 | 
			
		||||
		pfds[1].fd = loc_fd;
 | 
			
		||||
		pfds[1].fd = local_fd;
 | 
			
		||||
		pfds[1].events = POLLIN;
 | 
			
		||||
		if (BUFFER_USED(loc_out) > 0)
 | 
			
		||||
		if (local_fd != -1 && BUFFER_USED(local_out) > 0)
 | 
			
		||||
			pfds[1].events |= POLLOUT;
 | 
			
		||||
 | 
			
		||||
	
 | 
			
		||||
		/* Do the poll. */
 | 
			
		||||
		if (poll(pfds, 2, INFTIM) == -1) {
 | 
			
		||||
			if (errno == EAGAIN || errno == EINTR)
 | 
			
		||||
@@ -267,9 +275,10 @@ main(int argc, char **argv)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* Read/write from sockets. */
 | 
			
		||||
		if (buffer_poll(&pfds[0], srv_in, srv_out) != 0)
 | 
			
		||||
		if (buffer_poll(&pfds[0], server_in, server_out) != 0)
 | 
			
		||||
			goto server_dead;
 | 
			
		||||
		if (buffer_poll(&pfds[1], loc_in, loc_out) != 0)
 | 
			
		||||
		if (local_fd != -1 && 
 | 
			
		||||
		    buffer_poll(&pfds[1], local_in, local_out) != 0)
 | 
			
		||||
			fatalx("lost local socket");
 | 
			
		||||
 | 
			
		||||
		/* Output flushed; pause if requested. */
 | 
			
		||||
@@ -277,13 +286,17 @@ main(int argc, char **argv)
 | 
			
		||||
			usleep(750000);
 | 
			
		||||
 | 
			
		||||
		/* Process any data. */
 | 
			
		||||
		if ((n = process_server(srv_in)) == -1)
 | 
			
		||||
		if ((n = process_server(&error)) == -1)
 | 
			
		||||
			break;
 | 
			
		||||
		if (process_local(loc_in, srv_out) == -1)
 | 
			
		||||
		if (process_local() == -1)
 | 
			
		||||
			break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	local_done();
 | 
			
		||||
	if (local_fd != -1)
 | 
			
		||||
		local_done();
 | 
			
		||||
 | 
			
		||||
	if (error != NULL)
 | 
			
		||||
		errx(1, "%s", error);
 | 
			
		||||
 | 
			
		||||
	if (!sigterm)
 | 
			
		||||
		printf("[detached]\n");
 | 
			
		||||
@@ -292,12 +305,47 @@ main(int argc, char **argv)
 | 
			
		||||
	exit(0);
 | 
			
		||||
 | 
			
		||||
server_dead:
 | 
			
		||||
	local_done();
 | 
			
		||||
	if (local_fd != -1)
 | 
			
		||||
		local_done();
 | 
			
		||||
 | 
			
		||||
	printf("[lost server]\n");
 | 
			
		||||
	exit(1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* New command. */
 | 
			
		||||
void
 | 
			
		||||
op_new(char *name, struct winsize *ws)
 | 
			
		||||
{
 | 
			
		||||
	struct new_data	data;
 | 
			
		||||
	struct hdr	hdr;
 | 
			
		||||
 | 
			
		||||
	hdr.type = MSG_NEW;
 | 
			
		||||
	hdr.size = sizeof data;
 | 
			
		||||
	buffer_write(server_out, &hdr, sizeof hdr);
 | 
			
		||||
 | 
			
		||||
	strlcpy(data.name, name, sizeof data.name);
 | 
			
		||||
	data.sx = ws->ws_col;
 | 
			
		||||
	data.sy = ws->ws_row;
 | 
			
		||||
	buffer_write(server_out, &data, hdr.size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Attach command. */
 | 
			
		||||
void
 | 
			
		||||
op_attach(char *name, struct winsize *ws)
 | 
			
		||||
{
 | 
			
		||||
	struct attach_data	data;
 | 
			
		||||
	struct hdr		hdr;
 | 
			
		||||
 | 
			
		||||
	hdr.type = MSG_ATTACH;
 | 
			
		||||
	hdr.size = sizeof data;
 | 
			
		||||
	buffer_write(server_out, &hdr, sizeof hdr);
 | 
			
		||||
 | 
			
		||||
	strlcpy(data.name, name, sizeof data.name);
 | 
			
		||||
	data.sx = ws->ws_col;
 | 
			
		||||
	data.sy = ws->ws_row;
 | 
			
		||||
	buffer_write(server_out, &data, hdr.size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Connect to server socket from PID. */
 | 
			
		||||
int
 | 
			
		||||
connect_server(void)
 | 
			
		||||
@@ -323,21 +371,30 @@ connect_server(void)
 | 
			
		||||
 | 
			
		||||
/* Handle data from server. */
 | 
			
		||||
int
 | 
			
		||||
process_server(struct buffer *srv_in)
 | 
			
		||||
process_server(char **error)
 | 
			
		||||
{
 | 
			
		||||
	struct hdr	hdr;
 | 
			
		||||
 | 
			
		||||
	*error = NULL;
 | 
			
		||||
	for (;;) {
 | 
			
		||||
		if (BUFFER_USED(srv_in) < sizeof hdr)
 | 
			
		||||
		if (BUFFER_USED(server_in) < sizeof hdr)
 | 
			
		||||
			break;
 | 
			
		||||
		memcpy(&hdr, BUFFER_OUT(srv_in), sizeof hdr);
 | 
			
		||||
		if (BUFFER_USED(srv_in) < (sizeof hdr) + hdr.size)
 | 
			
		||||
		memcpy(&hdr, BUFFER_OUT(server_in), sizeof hdr);
 | 
			
		||||
		if (BUFFER_USED(server_in) < (sizeof hdr) + hdr.size)
 | 
			
		||||
			break;
 | 
			
		||||
		buffer_remove(srv_in, sizeof hdr);
 | 
			
		||||
		buffer_remove(server_in, sizeof hdr);
 | 
			
		||||
 | 
			
		||||
		switch (hdr.code) {
 | 
			
		||||
		switch (hdr.type) {
 | 
			
		||||
		case MSG_READY:
 | 
			
		||||
			if (hdr.size != 0) {
 | 
			
		||||
				xasprintf(error, "%.*s",
 | 
			
		||||
				    (int) hdr.size, BUFFER_OUT(server_in));
 | 
			
		||||
				return (-1);
 | 
			
		||||
			}
 | 
			
		||||
			local_fd = local_init(&local_in, &local_out);
 | 
			
		||||
			break;
 | 
			
		||||
		case MSG_OUTPUT:
 | 
			
		||||
			local_output(srv_in, hdr.size);
 | 
			
		||||
			local_output(server_in, hdr.size);
 | 
			
		||||
			break;
 | 
			
		||||
		case MSG_PAUSE:
 | 
			
		||||
			if (hdr.size != 0)
 | 
			
		||||
@@ -345,6 +402,8 @@ process_server(struct buffer *srv_in)
 | 
			
		||||
			return (1);
 | 
			
		||||
		case MSG_EXIT:
 | 
			
		||||
			return (-1);
 | 
			
		||||
		default:
 | 
			
		||||
			fatalx("unexpected message");
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -353,13 +412,16 @@ process_server(struct buffer *srv_in)
 | 
			
		||||
 | 
			
		||||
/* Handle data from local terminal. */
 | 
			
		||||
int
 | 
			
		||||
process_local(struct buffer *loc_in, struct buffer *srv_out)
 | 
			
		||||
process_local(void)
 | 
			
		||||
{
 | 
			
		||||
	struct buffer	*b;
 | 
			
		||||
	struct hdr	 hdr;
 | 
			
		||||
	size_t		 size;
 | 
			
		||||
	int		 n, key;
 | 
			
		||||
 | 
			
		||||
	if (local_fd == -1)
 | 
			
		||||
		return (0);
 | 
			
		||||
 | 
			
		||||
	n = 0;
 | 
			
		||||
	b = buffer_create(BUFSIZ);
 | 
			
		||||
 | 
			
		||||
@@ -368,10 +430,10 @@ process_local(struct buffer *loc_in, struct buffer *srv_out)
 | 
			
		||||
 | 
			
		||||
		if (key == cmd_prefix) {
 | 
			
		||||
			if ((key = local_key(NULL)) == KEYC_NONE) {
 | 
			
		||||
				buffer_reverse_remove(loc_in, size);
 | 
			
		||||
				buffer_reverse_remove(local_in, size);
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
			n = cmd_execute(key, srv_out);
 | 
			
		||||
			n = cmd_execute(key, server_out);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@@ -385,10 +447,10 @@ process_local(struct buffer *loc_in, struct buffer *srv_out)
 | 
			
		||||
	}
 | 
			
		||||
	log_debug("transmitting %zu bytes of input", BUFFER_USED(b));
 | 
			
		||||
 | 
			
		||||
	hdr.code = MSG_INPUT;
 | 
			
		||||
	hdr.type = MSG_INPUT;
 | 
			
		||||
	hdr.size = BUFFER_USED(b);
 | 
			
		||||
	buffer_write(srv_out, &hdr, sizeof hdr);
 | 
			
		||||
	buffer_write(srv_out, BUFFER_OUT(b), BUFFER_USED(b));
 | 
			
		||||
	buffer_write(server_out, &hdr, sizeof hdr);
 | 
			
		||||
	buffer_write(server_out, BUFFER_OUT(b), BUFFER_USED(b));
 | 
			
		||||
 | 
			
		||||
	buffer_destroy(b);
 | 
			
		||||
	return (n);
 | 
			
		||||
@@ -400,41 +462,29 @@ main_list(char *name)
 | 
			
		||||
{
 | 
			
		||||
	struct sessions_data	 sd;
 | 
			
		||||
	struct windows_data	 wd;
 | 
			
		||||
	int			 srv_fd, mode;
 | 
			
		||||
	struct buffer		*srv_in, *srv_out;
 | 
			
		||||
	struct pollfd	 	 pfd;
 | 
			
		||||
	struct hdr		 hdr;
 | 
			
		||||
 | 
			
		||||
	/* Connect to server. */
 | 
			
		||||
	if ((srv_fd = connect_server()) == -1)
 | 
			
		||||
		errx(1, "couldn't find server");
 | 
			
		||||
	if ((mode = fcntl(srv_fd, F_GETFL)) == -1)
 | 
			
		||||
		err(1, "fcntl");
 | 
			
		||||
	if (fcntl(srv_fd, F_SETFL, mode|O_NONBLOCK) == -1)
 | 
			
		||||
		err(1, "fcntl");
 | 
			
		||||
	srv_in = buffer_create(BUFSIZ);
 | 
			
		||||
	srv_out = buffer_create(BUFSIZ);
 | 
			
		||||
 | 
			
		||||
	/* Send query data. */
 | 
			
		||||
	if (name == NULL) {
 | 
			
		||||
		hdr.code = MSG_SESSIONS;
 | 
			
		||||
	if (*name == '\0') {
 | 
			
		||||
		hdr.type = MSG_SESSIONS;
 | 
			
		||||
		hdr.size = sizeof sd;
 | 
			
		||||
		buffer_write(srv_out, &hdr, sizeof hdr);
 | 
			
		||||
		buffer_write(srv_out, &sd, hdr.size);
 | 
			
		||||
		buffer_write(server_out, &hdr, sizeof hdr);
 | 
			
		||||
		buffer_write(server_out, &sd, hdr.size);
 | 
			
		||||
	} else {
 | 
			
		||||
		hdr.code = MSG_WINDOWS;
 | 
			
		||||
		hdr.type = MSG_WINDOWS;
 | 
			
		||||
		hdr.size = sizeof wd;
 | 
			
		||||
		buffer_write(srv_out, &hdr, sizeof hdr);
 | 
			
		||||
		buffer_write(server_out, &hdr, sizeof hdr);
 | 
			
		||||
		strlcpy(wd.name, name, sizeof wd.name);
 | 
			
		||||
		buffer_write(srv_out, &wd, hdr.size);
 | 
			
		||||
		buffer_write(server_out, &wd, hdr.size);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Main loop. */
 | 
			
		||||
	for (;;) {
 | 
			
		||||
		/* Set up pollfd. */
 | 
			
		||||
		pfd.fd = srv_fd;
 | 
			
		||||
		pfd.fd = server_fd;
 | 
			
		||||
		pfd.events = POLLIN;
 | 
			
		||||
		if (BUFFER_USED(srv_out) > 0)
 | 
			
		||||
		if (BUFFER_USED(server_out) > 0)
 | 
			
		||||
			pfd.events |= POLLOUT;
 | 
			
		||||
 | 
			
		||||
		/* Do the poll. */
 | 
			
		||||
@@ -445,16 +495,16 @@ main_list(char *name)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* Read/write from sockets. */
 | 
			
		||||
		if (buffer_poll(&pfd, srv_in, srv_out) != 0)
 | 
			
		||||
		if (buffer_poll(&pfd, server_in, server_out) != 0)
 | 
			
		||||
			errx(1, "lost server"); 
 | 
			
		||||
 | 
			
		||||
		/* Process data. */
 | 
			
		||||
		process_list(srv_in, name);
 | 
			
		||||
		process_list(name);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
process_list(struct buffer *srv_in, const char *name)
 | 
			
		||||
process_list(const char *name)
 | 
			
		||||
{
 | 
			
		||||
	struct sessions_data	 sd;
 | 
			
		||||
	struct sessions_entry	 se;
 | 
			
		||||
@@ -464,25 +514,25 @@ process_list(struct buffer *srv_in, const char *name)
 | 
			
		||||
	char		        *tim;
 | 
			
		||||
	
 | 
			
		||||
	for (;;) {
 | 
			
		||||
		if (BUFFER_USED(srv_in) < sizeof hdr)
 | 
			
		||||
		if (BUFFER_USED(server_in) < sizeof hdr)
 | 
			
		||||
			break;
 | 
			
		||||
		memcpy(&hdr, BUFFER_OUT(srv_in), sizeof hdr);
 | 
			
		||||
		if (BUFFER_USED(srv_in) < (sizeof hdr) + hdr.size)
 | 
			
		||||
		memcpy(&hdr, BUFFER_OUT(server_in), sizeof hdr);
 | 
			
		||||
		if (BUFFER_USED(server_in) < (sizeof hdr) + hdr.size)
 | 
			
		||||
			break;
 | 
			
		||||
		buffer_remove(srv_in, sizeof hdr);
 | 
			
		||||
		buffer_remove(server_in, sizeof hdr);
 | 
			
		||||
		
 | 
			
		||||
		switch (hdr.code) {
 | 
			
		||||
		switch (hdr.type) {
 | 
			
		||||
		case MSG_SESSIONS:
 | 
			
		||||
			if (hdr.size < sizeof sd)
 | 
			
		||||
				errx(1, "bad MSG_SESSIONS size");
 | 
			
		||||
			buffer_read(srv_in, &sd, sizeof sd);
 | 
			
		||||
			buffer_read(server_in, &sd, sizeof sd);
 | 
			
		||||
			hdr.size -= sizeof sd; 
 | 
			
		||||
			if (sd.sessions == 0 && hdr.size == 0)
 | 
			
		||||
				exit(0);
 | 
			
		||||
			if (hdr.size < sd.sessions * sizeof se)
 | 
			
		||||
				errx(1, "bad MSG_SESSIONS size");
 | 
			
		||||
			while (sd.sessions-- > 0) {
 | 
			
		||||
				buffer_read(srv_in, &se, sizeof se);
 | 
			
		||||
				buffer_read(server_in, &se, sizeof se);
 | 
			
		||||
				tim = ctime(&se.tim);
 | 
			
		||||
				*strchr(tim, '\n') = '\0';
 | 
			
		||||
				printf("%s: %u windows (created %s)\n",
 | 
			
		||||
@@ -492,14 +542,14 @@ process_list(struct buffer *srv_in, const char *name)
 | 
			
		||||
		case MSG_WINDOWS:
 | 
			
		||||
			if (hdr.size < sizeof wd)
 | 
			
		||||
				errx(1, "bad MSG_WINDOWS size");
 | 
			
		||||
			buffer_read(srv_in, &wd, sizeof wd);
 | 
			
		||||
			buffer_read(server_in, &wd, sizeof wd);
 | 
			
		||||
			hdr.size -= sizeof wd; 
 | 
			
		||||
			if (wd.windows == 0 && hdr.size == 0)
 | 
			
		||||
				errx(1, "session \"%s\" not found", name);
 | 
			
		||||
			if (hdr.size < wd.windows * sizeof we)
 | 
			
		||||
				errx(1, "bad MSG_WINDOWS size");
 | 
			
		||||
			while (wd.windows-- > 0) {
 | 
			
		||||
				buffer_read(srv_in, &we, sizeof we);
 | 
			
		||||
				buffer_read(server_in, &we, sizeof we);
 | 
			
		||||
				if (*we.title != '\0') {
 | 
			
		||||
					printf("%u: %s \"%s\" (%s)\n",
 | 
			
		||||
					    we.idx, we.name, we.title, we.tty); 
 | 
			
		||||
@@ -509,6 +559,8 @@ process_list(struct buffer *srv_in, const char *name)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			exit(0);
 | 
			
		||||
		default:
 | 
			
		||||
			fatalx("unexpected message");
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										122
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										122
									
								
								tmux.h
									
									
									
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
/* $Id: tmux.h,v 1.4 2007-08-27 12:05:15 nicm Exp $ */
 | 
			
		||||
/* $Id: tmux.h,v 1.5 2007-08-27 13:45:26 nicm Exp $ */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
			
		||||
@@ -226,68 +226,6 @@ struct buffer {
 | 
			
		||||
#define KEYC_UP -149
 | 
			
		||||
#define KEYC_MOUSE -150
 | 
			
		||||
 | 
			
		||||
/* Escape codes. */
 | 
			
		||||
/*
 | 
			
		||||
	AL=\E[%dL	parm_insert_line
 | 
			
		||||
	DC=\E[%dP	parm_dch
 | 
			
		||||
	DL=\E[%dM	parm_delete_line
 | 
			
		||||
	DO=\E[%dB	parm_down_cursor
 | 
			
		||||
	IC=\E[%d@	parm_ich
 | 
			
		||||
	Km=\E[M		key_mouse
 | 
			
		||||
	LE=\E[%dD	parm_left_cursor
 | 
			
		||||
	RI=\E[%dC	parm_right_cursor
 | 
			
		||||
	UP=\E[%dA	parm_up_cursor
 | 
			
		||||
	ac=++,,--..00``aaffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~
 | 
			
		||||
			acs_chars
 | 
			
		||||
	ae=^O		exit_alt_charset_mode
 | 
			
		||||
	al=\E[L		insert_line
 | 
			
		||||
	as=^N		enter_alt_charset_mode
 | 
			
		||||
	bl=^G		bell
 | 
			
		||||
	bt=\E[Z		back_tab
 | 
			
		||||
	cb=\E[1K	clear_bol
 | 
			
		||||
	cd=\E[J		clear_eos
 | 
			
		||||
	ce=\E[K		clear_eol
 | 
			
		||||
	cl=\E[H\E[J	clear_screen
 | 
			
		||||
	cm=\E[%i%d;%dH	cursor_address
 | 
			
		||||
	cr=^M		carriage_return
 | 
			
		||||
	cs=\E[%i%d;%dr	change_scroll_region
 | 
			
		||||
	ct=\E[3g	clear_all_tabs
 | 
			
		||||
	dc=\E[P		delete_character
 | 
			
		||||
	dl=\E[M		delete_line
 | 
			
		||||
	do=^J		cursor_down
 | 
			
		||||
	eA=\E(B\E)0	ena_acs
 | 
			
		||||
	ei=\E[4l	exit_insert_mode
 | 
			
		||||
	ho=\E[H		cursor_home
 | 
			
		||||
	im=\E[4h	enter_insert_mode
 | 
			
		||||
	is=\E)0		init_2string
 | 
			
		||||
	le=^H		cursor_left
 | 
			
		||||
	mb=\E[5m	enter_blink_mode
 | 
			
		||||
	md=\E[1m	enter_bold_mode
 | 
			
		||||
	me=\E[m		exit_attrbute_mode
 | 
			
		||||
	mr=\E[7m	enter_reverse_mode
 | 
			
		||||
	nd=\E[C		cursor_right
 | 
			
		||||
	nw=\EE		newline
 | 
			
		||||
	rc=\E8		restore_cursor
 | 
			
		||||
	rs=\Ec		reset_string
 | 
			
		||||
	sc=\E7		save_cursor
 | 
			
		||||
	se=\E[23m	exit_standout_mode
 | 
			
		||||
	sf=^J		scroll_forward
 | 
			
		||||
	so=\E[3m	enter_standout_mode
 | 
			
		||||
	sr=\EM		scroll_reverse
 | 
			
		||||
	st=\EH		set_tab
 | 
			
		||||
	ta=^I		tab
 | 
			
		||||
	ue=\E[24m	exit_underline_mode
 | 
			
		||||
	up=\EM		cursor_up
 | 
			
		||||
	s=\E[4m
 | 
			
		||||
	vb=\Eg		flash_screen
 | 
			
		||||
	ve=\E[34h\E[?25h
 | 
			
		||||
			cursor_normal
 | 
			
		||||
	vi=\E[?25l	cursor_invisible
 | 
			
		||||
	vs=\E[34l	cursor_visible
 | 
			
		||||
	E0=\E(B
 | 
			
		||||
	S0=\E(%p1%c
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Translated escape codes. */
 | 
			
		||||
#define CODE_CURSORUP 0
 | 
			
		||||
#define CODE_CURSORDOWN 1
 | 
			
		||||
@@ -317,25 +255,47 @@ struct buffer {
 | 
			
		||||
#define CODE_KKEYPADON 25
 | 
			
		||||
#define CODE_TITLE 26
 | 
			
		||||
 | 
			
		||||
/* Command-line commands. */
 | 
			
		||||
enum op {
 | 
			
		||||
	OP_LIST = 0,
 | 
			
		||||
	OP_NEW,
 | 
			
		||||
	OP_ATTACH
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Message codes. */
 | 
			
		||||
#define MSG_IDENTIFY 0
 | 
			
		||||
#define MSG_CREATE 1
 | 
			
		||||
#define MSG_EXIT 2
 | 
			
		||||
#define MSG_SIZE 3
 | 
			
		||||
#define MSG_NEXT 4
 | 
			
		||||
#define MSG_PREVIOUS 5
 | 
			
		||||
#define MSG_INPUT 6	/* input from client to server */
 | 
			
		||||
#define MSG_OUTPUT 7	/* output from server to client */
 | 
			
		||||
#define MSG_REFRESH 8
 | 
			
		||||
#define MSG_SELECT 9
 | 
			
		||||
#define MSG_SESSIONS 10
 | 
			
		||||
#define MSG_WINDOWS 11
 | 
			
		||||
#define MSG_PAUSE 12
 | 
			
		||||
#define MSG_RENAME 13
 | 
			
		||||
enum hdrtype {
 | 
			
		||||
	MSG_NEW = 0,
 | 
			
		||||
	MSG_ATTACH,
 | 
			
		||||
	MSG_READY,
 | 
			
		||||
	MSG_CREATE,
 | 
			
		||||
	MSG_EXIT,
 | 
			
		||||
	MSG_SIZE,
 | 
			
		||||
	MSG_NEXT,
 | 
			
		||||
	MSG_PREVIOUS,
 | 
			
		||||
	MSG_INPUT,
 | 
			
		||||
	MSG_OUTPUT,
 | 
			
		||||
	MSG_REFRESH,
 | 
			
		||||
	MSG_SELECT,
 | 
			
		||||
	MSG_SESSIONS,
 | 
			
		||||
	MSG_WINDOWS,
 | 
			
		||||
	MSG_PAUSE,
 | 
			
		||||
	MSG_RENAME
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct identify_data {
 | 
			
		||||
/* Message header structure. */
 | 
			
		||||
struct hdr {
 | 
			
		||||
	enum hdrtype	type;
 | 
			
		||||
	size_t		size;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct new_data {
 | 
			
		||||
	char	name[MAXNAMELEN];
 | 
			
		||||
	u_int	sx;
 | 
			
		||||
	u_int	sy;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct attach_data {
 | 
			
		||||
	char	name[MAXNAMELEN];
 | 
			
		||||
	u_int	sx;
 | 
			
		||||
	u_int	sy;
 | 
			
		||||
};
 | 
			
		||||
@@ -377,12 +337,6 @@ struct refresh_data {
 | 
			
		||||
	u_int	py_lower;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Message header structure. */
 | 
			
		||||
struct hdr {
 | 
			
		||||
	u_int	code;
 | 
			
		||||
	size_t	size;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Attributes. */
 | 
			
		||||
#define ATTR_BRIGHT 0x1
 | 
			
		||||
#define ATTR_DIM 0x2
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user