mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-03 16:46:18 +00:00 
			
		
		
		
	Start the first client with a special socketpair so it is already known to the
server rather than playing silly games to get them synchronised before doing anything. Change attach-session to start the server.
This commit is contained in:
		
							
								
								
									
										8
									
								
								CHANGES
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								CHANGES
									
									
									
									
									
								
							@@ -1,3 +1,9 @@
 | 
			
		||||
19 January 2009
 | 
			
		||||
 | 
			
		||||
* attach-session now tries to start the server if it isn't already started - if
 | 
			
		||||
  no sessions are created in .tmux.conf this will cause an error.
 | 
			
		||||
* Clean up starting server by making initial client get a special socketpair.
 | 
			
		||||
 | 
			
		||||
18 January 2009
 | 
			
		||||
 | 
			
		||||
* Unbreak UTF-8.
 | 
			
		||||
@@ -958,7 +964,7 @@
 | 
			
		||||
  (including mutt, emacs). No status bar yet and no key remapping or other
 | 
			
		||||
  customisation.
 | 
			
		||||
 | 
			
		||||
$Id: CHANGES,v 1.220 2009-01-18 21:46:30 nicm Exp $
 | 
			
		||||
$Id: CHANGES,v 1.221 2009-01-19 17:16:09 nicm Exp $
 | 
			
		||||
 | 
			
		||||
 LocalWords:  showw utf UTF fulvio ciriaco joshe OSC APC gettime abc DEF OA clr
 | 
			
		||||
 LocalWords:  rivo nurges lscm Erdely eol smysession mysession ek dstname RB ms
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										36
									
								
								client.c
									
									
									
									
									
								
							
							
						
						
									
										36
									
								
								client.c
									
									
									
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
/* $Id: client.c,v 1.40 2009-01-18 12:09:42 nicm Exp $ */
 | 
			
		||||
/* $Id: client.c,v 1.41 2009-01-19 17:16:09 nicm Exp $ */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
			
		||||
@@ -44,23 +44,20 @@ client_init(
 | 
			
		||||
	struct winsize			ws;
 | 
			
		||||
	size_t				size;
 | 
			
		||||
	int				mode;
 | 
			
		||||
	u_int				retries;
 | 
			
		||||
	struct buffer		       *b;
 | 
			
		||||
	char			       *name;
 | 
			
		||||
 | 
			
		||||
	retries = 0;
 | 
			
		||||
retry:
 | 
			
		||||
	if (stat(path, &sb) != 0) {
 | 
			
		||||
		if (start_server && errno == ENOENT) {
 | 
			
		||||
			if (server_start(path) != 0)
 | 
			
		||||
				goto no_start;
 | 
			
		||||
			goto retry;
 | 
			
		||||
			if ((cctx->srv_fd = server_start(path)) == -1)
 | 
			
		||||
				goto start_failed;
 | 
			
		||||
			goto server_started;
 | 
			
		||||
		}
 | 
			
		||||
		goto fail;
 | 
			
		||||
		goto not_found;
 | 
			
		||||
	}
 | 
			
		||||
	if (!S_ISSOCK(sb.st_mode)) {
 | 
			
		||||
		errno = ENOTSOCK;
 | 
			
		||||
		goto fail;
 | 
			
		||||
		goto not_found;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	memset(&sa, 0, sizeof sa);
 | 
			
		||||
@@ -68,7 +65,7 @@ retry:
 | 
			
		||||
	size = strlcpy(sa.sun_path, path, sizeof sa.sun_path);
 | 
			
		||||
	if (size >= sizeof sa.sun_path) {
 | 
			
		||||
		errno = ENAMETOOLONG;
 | 
			
		||||
		goto fail;
 | 
			
		||||
		goto not_found;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ((cctx->srv_fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
 | 
			
		||||
@@ -76,16 +73,17 @@ retry:
 | 
			
		||||
 | 
			
		||||
	if (connect(
 | 
			
		||||
	    cctx->srv_fd, (struct sockaddr *) &sa, SUN_LEN(&sa)) == -1) {
 | 
			
		||||
		if (start_server && errno == ECONNREFUSED && retries < 10) {
 | 
			
		||||
			if (unlink(path) != 0)
 | 
			
		||||
				goto fail;
 | 
			
		||||
			if (server_start(path) != 0)
 | 
			
		||||
				goto no_start;
 | 
			
		||||
		if (errno == ECONNREFUSED) {
 | 
			
		||||
			if (unlink(path) != 0 || !start_server)
 | 
			
		||||
				goto not_found;
 | 
			
		||||
			if ((cctx->srv_fd = server_start(path)) == -1)
 | 
			
		||||
				goto start_failed;
 | 
			
		||||
			goto server_started;
 | 
			
		||||
		}
 | 
			
		||||
		retries++;
 | 
			
		||||
		goto retry;
 | 
			
		||||
		goto not_found;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
server_started:
 | 
			
		||||
	if ((mode = fcntl(cctx->srv_fd, F_GETFL)) == -1)
 | 
			
		||||
		fatal("fcntl");
 | 
			
		||||
	if (fcntl(cctx->srv_fd, F_SETFL, mode|O_NONBLOCK) == -1)
 | 
			
		||||
@@ -118,11 +116,11 @@ retry:
 | 
			
		||||
 | 
			
		||||
	return (0);
 | 
			
		||||
 | 
			
		||||
no_start:
 | 
			
		||||
start_failed:
 | 
			
		||||
	log_warnx("server failed to start");
 | 
			
		||||
	return (1);
 | 
			
		||||
 | 
			
		||||
fail:
 | 
			
		||||
not_found:
 | 
			
		||||
	log_warn("server not found");
 | 
			
		||||
	return (1);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
/* $Id: cmd-attach-session.c,v 1.21 2008-12-10 20:25:41 nicm Exp $ */
 | 
			
		||||
/* $Id: cmd-attach-session.c,v 1.22 2009-01-19 17:16:09 nicm Exp $ */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
			
		||||
@@ -29,7 +29,7 @@ void	cmd_attach_session_exec(struct cmd *, struct cmd_ctx *);
 | 
			
		||||
const struct cmd_entry cmd_attach_session_entry = {
 | 
			
		||||
	"attach-session", "attach",
 | 
			
		||||
	"[-d] " CMD_TARGET_SESSION_USAGE,
 | 
			
		||||
	CMD_DFLAG|CMD_CANTNEST,
 | 
			
		||||
       	CMD_DFLAG|CMD_CANTNEST|CMD_STARTSERVER,
 | 
			
		||||
	cmd_target_init,
 | 
			
		||||
	cmd_target_parse,
 | 
			
		||||
	cmd_attach_session_exec,
 | 
			
		||||
@@ -45,10 +45,14 @@ cmd_attach_session_exec(struct cmd *self, struct cmd_ctx *ctx)
 | 
			
		||||
	struct cmd_target_data	*data = self->data;
 | 
			
		||||
	struct session		*s;
 | 
			
		||||
	char			*cause;
 | 
			
		||||
 | 
			
		||||
	
 | 
			
		||||
	if (ctx->curclient != NULL)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	if (ARRAY_LENGTH(&sessions) == 0) {
 | 
			
		||||
		ctx->error(ctx, "no sessions");
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	if ((s = cmd_find_session(ctx, data->target)) == NULL)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										111
									
								
								server.c
									
									
									
									
									
								
							
							
						
						
									
										111
									
								
								server.c
									
									
									
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
/* $Id: server.c,v 1.108 2009-01-18 14:40:48 nicm Exp $ */
 | 
			
		||||
/* $Id: server.c,v 1.109 2009-01-19 17:16:09 nicm Exp $ */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
			
		||||
@@ -58,6 +58,51 @@ void		 server_check_timers(struct client *);
 | 
			
		||||
void		 server_second_timers(void);
 | 
			
		||||
int		 server_update_socket(const char *);
 | 
			
		||||
 | 
			
		||||
/* Create a new client. */
 | 
			
		||||
struct client *
 | 
			
		||||
server_create_client(int fd)
 | 
			
		||||
{
 | 
			
		||||
	struct client	*c;
 | 
			
		||||
	int		 mode;
 | 
			
		||||
	u_int		 i;
 | 
			
		||||
 | 
			
		||||
	if ((mode = fcntl(fd, F_GETFL)) == -1)
 | 
			
		||||
		fatal("fcntl failed");
 | 
			
		||||
	if (fcntl(fd, F_SETFL, mode|O_NONBLOCK) == -1)
 | 
			
		||||
		fatal("fcntl failed");
 | 
			
		||||
 | 
			
		||||
	c = xcalloc(1, sizeof *c);
 | 
			
		||||
	c->fd = fd;
 | 
			
		||||
	c->in = buffer_create(BUFSIZ);
 | 
			
		||||
	c->out = buffer_create(BUFSIZ);
 | 
			
		||||
 | 
			
		||||
	ARRAY_INIT(&c->prompt_hdata);
 | 
			
		||||
 | 
			
		||||
	c->tty.fd = -1;
 | 
			
		||||
	c->title = NULL;
 | 
			
		||||
 | 
			
		||||
	c->session = NULL;
 | 
			
		||||
	c->sx = 80;
 | 
			
		||||
	c->sy = 25;
 | 
			
		||||
	screen_init(&c->status, c->sx, 1, 0);
 | 
			
		||||
 | 
			
		||||
	c->message_string = NULL;
 | 
			
		||||
 | 
			
		||||
	c->prompt_string = NULL;
 | 
			
		||||
	c->prompt_buffer = NULL;
 | 
			
		||||
	c->prompt_index = 0;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
 | 
			
		||||
		if (ARRAY_ITEM(&clients, i) == NULL) {
 | 
			
		||||
			ARRAY_SET(&clients, i, c);
 | 
			
		||||
			return (c);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	ARRAY_ADD(&clients, c);
 | 
			
		||||
	return (c);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Find client index. */
 | 
			
		||||
int
 | 
			
		||||
server_client_index(struct client *c)
 | 
			
		||||
{
 | 
			
		||||
@@ -79,9 +124,8 @@ server_start(const char *path)
 | 
			
		||||
	mode_t			mask;
 | 
			
		||||
	int		   	n, fd, pair[2], mode;
 | 
			
		||||
	char		       *cause;
 | 
			
		||||
	u_char			ch;
 | 
			
		||||
 | 
			
		||||
	/* Make a little socketpair to wait for the server to be ready. */
 | 
			
		||||
	/* The first client is special and gets a socketpair; create it. */
 | 
			
		||||
	if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pair) != 0)
 | 
			
		||||
		fatal("socketpair failed");
 | 
			
		||||
 | 
			
		||||
@@ -92,17 +136,7 @@ server_start(const char *path)
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		close(pair[1]);
 | 
			
		||||
 | 
			
		||||
		ch = 0x00;
 | 
			
		||||
		if (read(pair[0], &ch, 1) == 1 && ch == 0xff) {
 | 
			
		||||
			close(pair[0]);
 | 
			
		||||
			return (0);
 | 
			
		||||
		}
 | 
			
		||||
		ch = 0x00;
 | 
			
		||||
		if (write(pair[1], &ch, 1) != 1)
 | 
			
		||||
			fatal("write failed");
 | 
			
		||||
		close(pair[0]);
 | 
			
		||||
		return (1);
 | 
			
		||||
		return (pair[0]);
 | 
			
		||||
	}
 | 
			
		||||
	close(pair[0]);
 | 
			
		||||
 | 
			
		||||
@@ -166,11 +200,7 @@ server_start(const char *path)
 | 
			
		||||
	if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
 | 
			
		||||
		fatal("fcntl failed");
 | 
			
		||||
 | 
			
		||||
	ch = 0xff;
 | 
			
		||||
	if (write(pair[1], &ch, 1) != 1)
 | 
			
		||||
		fatal("write failed");
 | 
			
		||||
	read(pair[1], &ch, 1); /* Ignore errors; just to wait before closing. */
 | 
			
		||||
	close(pair[1]);
 | 
			
		||||
	server_create_client(pair[1]);
 | 
			
		||||
 | 
			
		||||
	n = server_main(path, fd);
 | 
			
		||||
#ifdef DEBUG
 | 
			
		||||
@@ -532,52 +562,17 @@ server_handle_clients(struct pollfd **pfd)
 | 
			
		||||
struct client *
 | 
			
		||||
server_accept_client(int srv_fd)
 | 
			
		||||
{
 | 
			
		||||
	struct client	       *c;
 | 
			
		||||
	struct sockaddr_storage	sa;
 | 
			
		||||
	socklen_t		slen = sizeof sa;
 | 
			
		||||
	int		 	client_fd, mode;
 | 
			
		||||
	u_int			i;
 | 
			
		||||
	int			fd;
 | 
			
		||||
 | 
			
		||||
	client_fd = accept(srv_fd, (struct sockaddr *) &sa, &slen);
 | 
			
		||||
	if (client_fd == -1) {
 | 
			
		||||
	fd = accept(srv_fd, (struct sockaddr *) &sa, &slen);
 | 
			
		||||
	if (fd == -1) {
 | 
			
		||||
		if (errno == EAGAIN || errno == EINTR || errno == ECONNABORTED)
 | 
			
		||||
			return (NULL);
 | 
			
		||||
		fatal("accept failed");
 | 
			
		||||
	}
 | 
			
		||||
	if ((mode = fcntl(client_fd, F_GETFL)) == -1)
 | 
			
		||||
		fatal("fcntl failed");
 | 
			
		||||
	if (fcntl(client_fd, F_SETFL, mode|O_NONBLOCK) == -1)
 | 
			
		||||
		fatal("fcntl failed");
 | 
			
		||||
 | 
			
		||||
	c = xcalloc(1, sizeof *c);
 | 
			
		||||
	c->fd = client_fd;
 | 
			
		||||
	c->in = buffer_create(BUFSIZ);
 | 
			
		||||
	c->out = buffer_create(BUFSIZ);
 | 
			
		||||
 | 
			
		||||
	ARRAY_INIT(&c->prompt_hdata);
 | 
			
		||||
 | 
			
		||||
	c->tty.fd = -1;
 | 
			
		||||
	c->title = NULL;
 | 
			
		||||
 | 
			
		||||
	c->session = NULL;
 | 
			
		||||
	c->sx = 80;
 | 
			
		||||
	c->sy = 25;
 | 
			
		||||
	screen_init(&c->status, c->sx, 1, 0);
 | 
			
		||||
 | 
			
		||||
	c->message_string = NULL;
 | 
			
		||||
 | 
			
		||||
	c->prompt_string = NULL;
 | 
			
		||||
	c->prompt_buffer = NULL;
 | 
			
		||||
	c->prompt_index = 0;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
 | 
			
		||||
		if (ARRAY_ITEM(&clients, i) == NULL) {
 | 
			
		||||
			ARRAY_SET(&clients, i, c);
 | 
			
		||||
			return (c);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	ARRAY_ADD(&clients, c);
 | 
			
		||||
	return (c);
 | 
			
		||||
	return (server_create_client(fd));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Input data from client. */
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										7
									
								
								tmux.1
									
									
									
									
									
								
							
							
						
						
									
										7
									
								
								tmux.1
									
									
									
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
.\" $Id: tmux.1,v 1.66 2009-01-17 17:16:31 nicm Exp $
 | 
			
		||||
.\" $Id: tmux.1,v 1.67 2009-01-19 17:16:09 nicm Exp $
 | 
			
		||||
.\"
 | 
			
		||||
.\" Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
			
		||||
.\"
 | 
			
		||||
@@ -345,6 +345,11 @@ Create a new client in the current terminal and attach it to a session.
 | 
			
		||||
If
 | 
			
		||||
.Fl d
 | 
			
		||||
is specified, any other clients attached to the session are detached.
 | 
			
		||||
.Pp
 | 
			
		||||
If no server is started,
 | 
			
		||||
.It attach-session
 | 
			
		||||
will attempt to start it; this will fail unless sessions are created in the
 | 
			
		||||
configuration file.
 | 
			
		||||
.It Xo Ic bind-key
 | 
			
		||||
.Ar key Ar command Op Ar arguments
 | 
			
		||||
.Xc
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										3
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								tmux.h
									
									
									
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
/* $Id: tmux.h,v 1.241 2009-01-18 21:46:30 nicm Exp $ */
 | 
			
		||||
/* $Id: tmux.h,v 1.242 2009-01-19 17:16:09 nicm Exp $ */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
			
		||||
@@ -1253,6 +1253,7 @@ const char *key_string_lookup_key(int);
 | 
			
		||||
 | 
			
		||||
/* server.c */
 | 
			
		||||
extern struct clients clients;
 | 
			
		||||
struct client *server_create_client(int);
 | 
			
		||||
int	 server_client_index(struct client *);
 | 
			
		||||
int	 server_start(const char *);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user