mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 00:56:10 +00:00 
			
		
		
		
	Client tidying: get rid of client_ctx struct in favour of two variables in
client.c, and move the functions in client-fn.c into other files.
This commit is contained in:
		
							
								
								
									
										2
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								Makefile
									
									
									
									
									
								
							@@ -1,7 +1,7 @@
 | 
				
			|||||||
# $OpenBSD$
 | 
					# $OpenBSD$
 | 
				
			||||||
 | 
					
 | 
				
			||||||
PROG=	tmux
 | 
					PROG=	tmux
 | 
				
			||||||
SRCS=	attributes.c buffer-poll.c buffer.c cfg.c client-fn.c \
 | 
					SRCS=	attributes.c buffer-poll.c buffer.c cfg.c \
 | 
				
			||||||
	client.c clock.c cmd-attach-session.c cmd-bind-key.c \
 | 
						client.c clock.c cmd-attach-session.c cmd-bind-key.c \
 | 
				
			||||||
	cmd-break-pane.c cmd-choose-session.c cmd-choose-window.c \
 | 
						cmd-break-pane.c cmd-choose-session.c cmd-choose-window.c \
 | 
				
			||||||
	cmd-clear-history.c cmd-clock-mode.c cmd-command-prompt.c \
 | 
						cmd-clear-history.c cmd-clock-mode.c cmd-command-prompt.c \
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										90
									
								
								client-fn.c
									
									
									
									
									
								
							
							
						
						
									
										90
									
								
								client-fn.c
									
									
									
									
									
								
							@@ -1,90 +0,0 @@
 | 
				
			|||||||
/* $OpenBSD$ */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * 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"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void
 | 
					 | 
				
			||||||
client_fill_session(struct msg_command_data *data)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	char		*env, *ptr1, *ptr2, buf[256];
 | 
					 | 
				
			||||||
	size_t		 len;
 | 
					 | 
				
			||||||
	const char	*errstr;
 | 
					 | 
				
			||||||
	long long	 ll;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	data->pid = -1;
 | 
					 | 
				
			||||||
	if ((env = getenv("TMUX")) == NULL)
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if ((ptr2 = strrchr(env, ',')) == NULL || ptr2 == env)
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
	for (ptr1 = ptr2 - 1; ptr1 > env && *ptr1 != ','; ptr1--)
 | 
					 | 
				
			||||||
		;
 | 
					 | 
				
			||||||
	if (*ptr1 != ',')
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
	ptr1++;
 | 
					 | 
				
			||||||
	ptr2++;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	len = ptr2 - ptr1 - 1;
 | 
					 | 
				
			||||||
	if (len > (sizeof buf) - 1)
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
	memcpy(buf, ptr1, len);
 | 
					 | 
				
			||||||
	buf[len] = '\0';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ll = strtonum(buf, 0, LONG_MAX, &errstr);
 | 
					 | 
				
			||||||
	if (errstr != NULL)
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
	data->pid = ll;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ll = strtonum(ptr2, 0, UINT_MAX, &errstr);
 | 
					 | 
				
			||||||
	if (errstr != NULL)
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
	data->idx = ll;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void
 | 
					 | 
				
			||||||
client_write_server(
 | 
					 | 
				
			||||||
    struct client_ctx *cctx, enum msgtype type, void *buf, size_t len)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	imsg_compose(&cctx->ibuf, type, PROTOCOL_VERSION, -1, -1, buf, len);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void
 | 
					 | 
				
			||||||
client_suspend(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct sigaction	 act;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	memset(&act, 0, sizeof act);
 | 
					 | 
				
			||||||
	sigemptyset(&act.sa_mask);
 | 
					 | 
				
			||||||
	act.sa_flags = SA_RESTART;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	act.sa_handler = SIG_DFL;
 | 
					 | 
				
			||||||
	if (sigaction(SIGTSTP, &act, NULL) != 0)
 | 
					 | 
				
			||||||
		fatal("sigaction failed");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	act.sa_handler = sighandler;
 | 
					 | 
				
			||||||
	if (sigaction(SIGCONT, &act, NULL) != 0)
 | 
					 | 
				
			||||||
		fatal("sigaction failed");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	kill(getpid(), SIGTSTP);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										148
									
								
								client.c
									
									
									
									
									
								
							
							
						
						
									
										148
									
								
								client.c
									
									
									
									
									
								
							@@ -33,10 +33,16 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "tmux.h"
 | 
					#include "tmux.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void	client_send_environ(struct client_ctx *);
 | 
					struct imsgbuf	client_ibuf;
 | 
				
			||||||
 | 
					const char     *client_exitmsg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int
 | 
					void	client_send_environ(void);
 | 
				
			||||||
client_init(char *path, struct client_ctx *cctx, int cmdflags, int flags)
 | 
					void	client_write_server(enum msgtype, void *, size_t);
 | 
				
			||||||
 | 
					int	client_dispatch(void);
 | 
				
			||||||
 | 
					void	client_suspend(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct imsgbuf *
 | 
				
			||||||
 | 
					client_init(char *path, int cmdflags, int flags)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct sockaddr_un		sa;
 | 
						struct sockaddr_un		sa;
 | 
				
			||||||
	struct stat			sb;
 | 
						struct stat			sb;
 | 
				
			||||||
@@ -93,10 +99,10 @@ server_started:
 | 
				
			|||||||
		fatal("fcntl failed");
 | 
							fatal("fcntl failed");
 | 
				
			||||||
	if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
 | 
						if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
 | 
				
			||||||
		fatal("fcntl failed");
 | 
							fatal("fcntl failed");
 | 
				
			||||||
	imsg_init(&cctx->ibuf, fd);
 | 
						imsg_init(&client_ibuf, fd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (cmdflags & CMD_SENDENVIRON)
 | 
						if (cmdflags & CMD_SENDENVIRON)
 | 
				
			||||||
		client_send_environ(cctx);
 | 
							client_send_environ();
 | 
				
			||||||
	if (isatty(STDIN_FILENO)) {
 | 
						if (isatty(STDIN_FILENO)) {
 | 
				
			||||||
		if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1)
 | 
							if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1)
 | 
				
			||||||
			fatal("ioctl(TIOCGWINSZ)");
 | 
								fatal("ioctl(TIOCGWINSZ)");
 | 
				
			||||||
@@ -114,23 +120,23 @@ server_started:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		if ((fd2 = dup(STDIN_FILENO)) == -1)
 | 
							if ((fd2 = dup(STDIN_FILENO)) == -1)
 | 
				
			||||||
			fatal("dup failed");
 | 
								fatal("dup failed");
 | 
				
			||||||
		imsg_compose(&cctx->ibuf, MSG_IDENTIFY,
 | 
							imsg_compose(&client_ibuf, MSG_IDENTIFY,
 | 
				
			||||||
		    PROTOCOL_VERSION, -1, fd2, &data, sizeof data);
 | 
							    PROTOCOL_VERSION, -1, fd2, &data, sizeof data);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return (0);
 | 
						return (&client_ibuf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
start_failed:
 | 
					start_failed:
 | 
				
			||||||
	log_warnx("server failed to start");
 | 
						log_warnx("server failed to start");
 | 
				
			||||||
	return (1);
 | 
						return (NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
not_found:
 | 
					not_found:
 | 
				
			||||||
	log_warn("server not found");
 | 
						log_warn("server not found");
 | 
				
			||||||
	return (1);
 | 
						return (NULL);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
client_send_environ(struct client_ctx *cctx)
 | 
					client_send_environ(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	char		      **var;
 | 
						char		      **var;
 | 
				
			||||||
	struct msg_environ_data	data;
 | 
						struct msg_environ_data	data;
 | 
				
			||||||
@@ -138,12 +144,18 @@ client_send_environ(struct client_ctx *cctx)
 | 
				
			|||||||
 	for (var = environ; *var != NULL; var++) {
 | 
					 	for (var = environ; *var != NULL; var++) {
 | 
				
			||||||
		if (strlcpy(data.var, *var, sizeof data.var) >= sizeof data.var)
 | 
							if (strlcpy(data.var, *var, sizeof data.var) >= sizeof data.var)
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		client_write_server(cctx, MSG_ENVIRON, &data, sizeof data);
 | 
							client_write_server(MSG_ENVIRON, &data, sizeof data);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int
 | 
					void
 | 
				
			||||||
client_main(struct client_ctx *cctx)
 | 
					client_write_server(enum msgtype type, void *buf, size_t len)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					 	imsg_compose(&client_ibuf, type, PROTOCOL_VERSION, -1, -1, buf, len);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					__dead void
 | 
				
			||||||
 | 
					client_main(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct pollfd	 pfd;
 | 
						struct pollfd	 pfd;
 | 
				
			||||||
	int		 n, nfds;
 | 
						int		 n, nfds;
 | 
				
			||||||
@@ -158,29 +170,31 @@ client_main(struct client_ctx *cctx)
 | 
				
			|||||||
	 * MSG_READY switched to here. Process anything outstanding now so poll
 | 
						 * MSG_READY switched to here. Process anything outstanding now so poll
 | 
				
			||||||
	 * doesn't hang waiting for messages that have already arrived.
 | 
						 * doesn't hang waiting for messages that have already arrived.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	if (client_msg_dispatch(cctx) != 0)
 | 
						if (client_dispatch() != 0)
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (;;) {
 | 
						for (;;) {
 | 
				
			||||||
		if (sigterm)
 | 
							if (sigterm) {
 | 
				
			||||||
			client_write_server(cctx, MSG_EXITING, NULL, 0);
 | 
								client_exitmsg = "terminated";
 | 
				
			||||||
 | 
								client_write_server(MSG_EXITING, NULL, 0);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		if (sigchld) {
 | 
							if (sigchld) {
 | 
				
			||||||
			waitpid(WAIT_ANY, NULL, WNOHANG);
 | 
								waitpid(WAIT_ANY, NULL, WNOHANG);
 | 
				
			||||||
			sigchld = 0;
 | 
								sigchld = 0;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (sigwinch) {
 | 
							if (sigwinch) {
 | 
				
			||||||
			client_write_server(cctx, MSG_RESIZE, NULL, 0);
 | 
								client_write_server(MSG_RESIZE, NULL, 0);
 | 
				
			||||||
 			sigwinch = 0;
 | 
					 			sigwinch = 0;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (sigcont) {
 | 
							if (sigcont) {
 | 
				
			||||||
			siginit();
 | 
								siginit();
 | 
				
			||||||
			client_write_server(cctx, MSG_WAKEUP, NULL, 0);
 | 
								client_write_server(MSG_WAKEUP, NULL, 0);
 | 
				
			||||||
			sigcont = 0;
 | 
								sigcont = 0;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		pfd.fd = cctx->ibuf.fd;
 | 
							pfd.fd = client_ibuf.fd;
 | 
				
			||||||
		pfd.events = POLLIN;
 | 
							pfd.events = POLLIN;
 | 
				
			||||||
		if (cctx->ibuf.w.queued > 0)
 | 
							if (client_ibuf.w.queued > 0)
 | 
				
			||||||
			pfd.events |= POLLOUT;
 | 
								pfd.events |= POLLOUT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if ((nfds = poll(&pfd, 1, INFTIM)) == -1) {
 | 
							if ((nfds = poll(&pfd, 1, INFTIM)) == -1) {
 | 
				
			||||||
@@ -195,67 +209,41 @@ client_main(struct client_ctx *cctx)
 | 
				
			|||||||
			fatalx("socket error");
 | 
								fatalx("socket error");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (pfd.revents & POLLIN) {
 | 
							if (pfd.revents & POLLIN) {
 | 
				
			||||||
			if ((n = imsg_read(&cctx->ibuf)) == -1 || n == 0) {
 | 
								if ((n = imsg_read(&client_ibuf)) == -1 || n == 0) {
 | 
				
			||||||
				cctx->exittype = CCTX_DIED;
 | 
									client_exitmsg = "lost server";
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if (client_msg_dispatch(cctx) != 0)
 | 
								if (client_dispatch() != 0)
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (pfd.revents & POLLOUT) {
 | 
							if (pfd.revents & POLLOUT) {
 | 
				
			||||||
			if (msgbuf_write(&cctx->ibuf.w) < 0) {
 | 
								if (msgbuf_write(&client_ibuf.w) < 0) {
 | 
				
			||||||
				cctx->exittype = CCTX_DIED;
 | 
									client_exitmsg = "lost server";
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
	/*
 | 
						/* Print the exit message, if any, and exit. */
 | 
				
			||||||
	 * Print exit status message, unless running as a login shell where it
 | 
						if (client_exitmsg != NULL) {
 | 
				
			||||||
	 * would either be pointless or irritating.
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	if (sigterm) {
 | 
					 | 
				
			||||||
		printf("[terminated]\n");
 | 
					 | 
				
			||||||
		return (1);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	switch (cctx->exittype) {
 | 
					 | 
				
			||||||
	case CCTX_DIED:
 | 
					 | 
				
			||||||
		printf("[lost server]\n");
 | 
					 | 
				
			||||||
		return (0);
 | 
					 | 
				
			||||||
	case CCTX_SHUTDOWN:
 | 
					 | 
				
			||||||
 		if (!login_shell)
 | 
					 | 
				
			||||||
			printf("[server exited]\n");
 | 
					 | 
				
			||||||
		return (0);
 | 
					 | 
				
			||||||
	case CCTX_EXIT:
 | 
					 | 
				
			||||||
		if (cctx->errstr != NULL) {
 | 
					 | 
				
			||||||
			printf("[error: %s]\n", cctx->errstr);
 | 
					 | 
				
			||||||
			return (1);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 		if (!login_shell)
 | 
					 | 
				
			||||||
			printf("[exited]\n");
 | 
					 | 
				
			||||||
		return (0);
 | 
					 | 
				
			||||||
	case CCTX_DETACH:
 | 
					 | 
				
			||||||
		if (!login_shell)
 | 
							if (!login_shell)
 | 
				
			||||||
			printf("[detached]\n");
 | 
								printf("[%s]\n", client_exitmsg);
 | 
				
			||||||
		return (0);
 | 
							exit(1);
 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		printf("[unknown error]\n");
 | 
					 | 
				
			||||||
		return (1);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						exit(0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int
 | 
					int
 | 
				
			||||||
client_msg_dispatch(struct client_ctx *cctx)
 | 
					client_dispatch(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct imsg		 imsg;
 | 
						struct imsg		 imsg;
 | 
				
			||||||
	struct msg_print_data	 printdata;
 | 
					 | 
				
			||||||
	struct msg_lock_data	 lockdata;
 | 
						struct msg_lock_data	 lockdata;
 | 
				
			||||||
	ssize_t			 n, datalen;
 | 
						ssize_t			 n, datalen;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (;;) {
 | 
						for (;;) {
 | 
				
			||||||
		if ((n = imsg_get(&cctx->ibuf, &imsg)) == -1)
 | 
							if ((n = imsg_get(&client_ibuf, &imsg)) == -1)
 | 
				
			||||||
			fatalx("imsg_get failed");
 | 
								fatalx("imsg_get failed");
 | 
				
			||||||
		if (n == 0)
 | 
							if (n == 0)
 | 
				
			||||||
			return (0);
 | 
								return (0);
 | 
				
			||||||
@@ -266,25 +254,15 @@ client_msg_dispatch(struct client_ctx *cctx)
 | 
				
			|||||||
			if (datalen != 0)
 | 
								if (datalen != 0)
 | 
				
			||||||
				fatalx("bad MSG_DETACH size");
 | 
									fatalx("bad MSG_DETACH size");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			client_write_server(cctx, MSG_EXITING, NULL, 0);
 | 
								client_write_server(MSG_EXITING, NULL, 0);
 | 
				
			||||||
			cctx->exittype = CCTX_DETACH;
 | 
								client_exitmsg = "detached";
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		case MSG_ERROR:
 | 
					 | 
				
			||||||
			if (datalen != sizeof printdata)
 | 
					 | 
				
			||||||
				fatalx("bad MSG_ERROR size");
 | 
					 | 
				
			||||||
			memcpy(&printdata, imsg.data, sizeof printdata);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			printdata.msg[(sizeof printdata.msg) - 1] = '\0';
 | 
					 | 
				
			||||||
			/* Error string used after exit message from server. */
 | 
					 | 
				
			||||||
			cctx->errstr = xstrdup(printdata.msg);
 | 
					 | 
				
			||||||
			imsg_free(&imsg);
 | 
					 | 
				
			||||||
			return (-1);
 | 
					 | 
				
			||||||
		case MSG_EXIT:
 | 
							case MSG_EXIT:
 | 
				
			||||||
			if (datalen != 0)
 | 
								if (datalen != 0)
 | 
				
			||||||
				fatalx("bad MSG_EXIT size");
 | 
									fatalx("bad MSG_EXIT size");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			client_write_server(cctx, MSG_EXITING, NULL, 0);
 | 
								client_write_server(MSG_EXITING, NULL, 0);
 | 
				
			||||||
			cctx->exittype = CCTX_EXIT;
 | 
								client_exitmsg = "exited";
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		case MSG_EXITED:
 | 
							case MSG_EXITED:
 | 
				
			||||||
			if (datalen != 0)
 | 
								if (datalen != 0)
 | 
				
			||||||
@@ -296,8 +274,8 @@ client_msg_dispatch(struct client_ctx *cctx)
 | 
				
			|||||||
			if (datalen != 0)
 | 
								if (datalen != 0)
 | 
				
			||||||
				fatalx("bad MSG_SHUTDOWN size");
 | 
									fatalx("bad MSG_SHUTDOWN size");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			client_write_server(cctx, MSG_EXITING, NULL, 0);
 | 
								client_write_server(MSG_EXITING, NULL, 0);
 | 
				
			||||||
			cctx->exittype = CCTX_SHUTDOWN;
 | 
								client_exitmsg = "server exited";
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		case MSG_SUSPEND:
 | 
							case MSG_SUSPEND:
 | 
				
			||||||
			if (datalen != 0)
 | 
								if (datalen != 0)
 | 
				
			||||||
@@ -312,7 +290,7 @@ client_msg_dispatch(struct client_ctx *cctx)
 | 
				
			|||||||
			
 | 
								
 | 
				
			||||||
			lockdata.cmd[(sizeof lockdata.cmd) - 1] = '\0';
 | 
								lockdata.cmd[(sizeof lockdata.cmd) - 1] = '\0';
 | 
				
			||||||
			system(lockdata.cmd);
 | 
								system(lockdata.cmd);
 | 
				
			||||||
			client_write_server(cctx, MSG_UNLOCK, NULL, 0);
 | 
								client_write_server(MSG_UNLOCK, NULL, 0);
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
			fatalx("unexpected message");
 | 
								fatalx("unexpected message");
 | 
				
			||||||
@@ -321,3 +299,23 @@ client_msg_dispatch(struct client_ctx *cctx)
 | 
				
			|||||||
		imsg_free(&imsg);
 | 
							imsg_free(&imsg);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					client_suspend(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct sigaction	 act;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memset(&act, 0, sizeof act);
 | 
				
			||||||
 | 
						sigemptyset(&act.sa_mask);
 | 
				
			||||||
 | 
						act.sa_flags = SA_RESTART;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						act.sa_handler = SIG_DFL;
 | 
				
			||||||
 | 
						if (sigaction(SIGTSTP, &act, NULL) != 0)
 | 
				
			||||||
 | 
							fatal("sigaction failed");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						act.sa_handler = sighandler;
 | 
				
			||||||
 | 
						if (sigaction(SIGCONT, &act, NULL) != 0)
 | 
				
			||||||
 | 
							fatal("sigaction failed");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						kill(getpid(), SIGTSTP);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										93
									
								
								tmux.c
									
									
									
									
									
								
							
							
						
						
									
										93
									
								
								tmux.c
									
									
									
									
									
								
							@@ -53,9 +53,10 @@ char		*socket_path;
 | 
				
			|||||||
int		 login_shell;
 | 
					int		 login_shell;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
__dead void	 usage(void);
 | 
					__dead void	 usage(void);
 | 
				
			||||||
 | 
					void	 	 fill_session(struct msg_command_data *);
 | 
				
			||||||
char 		*makesockpath(const char *);
 | 
					char 		*makesockpath(const char *);
 | 
				
			||||||
int		 prepare_cmd(enum msgtype *, void **, size_t *, int, char **);
 | 
					int		 prepare_cmd(enum msgtype *, void **, size_t *, int, char **);
 | 
				
			||||||
int		 dispatch_imsg(struct client_ctx *, const char *, int *);
 | 
					int		 dispatch_imsg(struct imsgbuf *, const char *, int *);
 | 
				
			||||||
__dead void	 shell_exec(const char *, const char *);
 | 
					__dead void	 shell_exec(const char *, const char *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
__dead void
 | 
					__dead void
 | 
				
			||||||
@@ -215,6 +216,44 @@ areshell(const char *shell)
 | 
				
			|||||||
	return (0);
 | 
						return (0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					fill_session(struct msg_command_data *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						char		*env, *ptr1, *ptr2, buf[256];
 | 
				
			||||||
 | 
						size_t		 len;
 | 
				
			||||||
 | 
						const char	*errstr;
 | 
				
			||||||
 | 
						long long	 ll;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						data->pid = -1;
 | 
				
			||||||
 | 
						if ((env = getenv("TMUX")) == NULL)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ((ptr2 = strrchr(env, ',')) == NULL || ptr2 == env)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						for (ptr1 = ptr2 - 1; ptr1 > env && *ptr1 != ','; ptr1--)
 | 
				
			||||||
 | 
							;
 | 
				
			||||||
 | 
						if (*ptr1 != ',')
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						ptr1++;
 | 
				
			||||||
 | 
						ptr2++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						len = ptr2 - ptr1 - 1;
 | 
				
			||||||
 | 
						if (len > (sizeof buf) - 1)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						memcpy(buf, ptr1, len);
 | 
				
			||||||
 | 
						buf[len] = '\0';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ll = strtonum(buf, 0, LONG_MAX, &errstr);
 | 
				
			||||||
 | 
						if (errstr != NULL)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						data->pid = ll;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ll = strtonum(ptr2, 0, UINT_MAX, &errstr);
 | 
				
			||||||
 | 
						if (errstr != NULL)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						data->idx = ll;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
char *
 | 
					char *
 | 
				
			||||||
makesockpath(const char *label)
 | 
					makesockpath(const char *label)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -248,7 +287,7 @@ prepare_cmd(enum msgtype *msg, void **buf, size_t *len, int argc, char **argv)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	static struct msg_command_data	 cmddata;
 | 
						static struct msg_command_data	 cmddata;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	client_fill_session(&cmddata);
 | 
						fill_session(&cmddata);
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	cmddata.argc = argc;
 | 
						cmddata.argc = argc;
 | 
				
			||||||
	if (cmd_pack_argv(argc, argv, cmddata.argv, sizeof cmddata.argv) != 0) {
 | 
						if (cmd_pack_argv(argc, argv, cmddata.argv, sizeof cmddata.argv) != 0) {
 | 
				
			||||||
@@ -266,20 +305,19 @@ prepare_cmd(enum msgtype *msg, void **buf, size_t *len, int argc, char **argv)
 | 
				
			|||||||
int
 | 
					int
 | 
				
			||||||
main(int argc, char **argv)
 | 
					main(int argc, char **argv)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct client_ctx	 cctx;
 | 
						struct cmd_list	*cmdlist;
 | 
				
			||||||
	struct cmd_list		*cmdlist;
 | 
					 	struct cmd	*cmd;
 | 
				
			||||||
 	struct cmd		*cmd;
 | 
						struct pollfd	 pfd;
 | 
				
			||||||
	struct pollfd	 	 pfd;
 | 
						enum msgtype	 msg;
 | 
				
			||||||
	enum msgtype		 msg;
 | 
						struct passwd	*pw;
 | 
				
			||||||
	struct passwd		*pw;
 | 
						struct options	*so, *wo;
 | 
				
			||||||
	struct options		*so, *wo;
 | 
						struct keylist	*keylist;
 | 
				
			||||||
	struct keylist		*keylist;
 | 
						struct imsgbuf	*ibuf;
 | 
				
			||||||
	char			*s, *shellcmd, *path, *label, *home, *cause;
 | 
						char		*s, *shellcmd, *path, *label, *home, *cause;
 | 
				
			||||||
	char			 cwd[MAXPATHLEN], **var;
 | 
						char		 cwd[MAXPATHLEN], **var;
 | 
				
			||||||
	void			*buf;
 | 
						void		*buf;
 | 
				
			||||||
	size_t			 len;
 | 
						size_t		 len;
 | 
				
			||||||
	int	 		 retcode, opt, flags, cmdflags = 0;
 | 
						int	 	 nfds, retcode, opt, flags, cmdflags = 0;
 | 
				
			||||||
	int			 nfds;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	flags = 0;
 | 
						flags = 0;
 | 
				
			||||||
	shellcmd = label = path = NULL;
 | 
						shellcmd = label = path = NULL;
 | 
				
			||||||
@@ -518,19 +556,17 @@ main(int argc, char **argv)
 | 
				
			|||||||
		cmd_list_free(cmdlist);
 | 
							cmd_list_free(cmdlist);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 	memset(&cctx, 0, sizeof cctx);
 | 
						if ((ibuf = client_init(path, cmdflags, flags)) == NULL)
 | 
				
			||||||
	if (client_init(path, &cctx, cmdflags, flags) != 0)
 | 
					 | 
				
			||||||
		exit(1);
 | 
							exit(1);
 | 
				
			||||||
	xfree(path);
 | 
						xfree(path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	client_write_server(&cctx, msg, buf, len);
 | 
					 	imsg_compose(ibuf, msg, PROTOCOL_VERSION, -1, -1, buf, len);
 | 
				
			||||||
	memset(buf, 0, len);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	retcode = 0;
 | 
						retcode = 0;
 | 
				
			||||||
	for (;;) {
 | 
						for (;;) {
 | 
				
			||||||
		pfd.fd = cctx.ibuf.fd;
 | 
							pfd.fd = ibuf->fd;
 | 
				
			||||||
		pfd.events = POLLIN;
 | 
							pfd.events = POLLIN;
 | 
				
			||||||
		if (cctx.ibuf.w.queued != 0)
 | 
							if (ibuf->w.queued != 0)
 | 
				
			||||||
			pfd.events |= POLLOUT;
 | 
								pfd.events |= POLLOUT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if ((nfds = poll(&pfd, 1, INFTIM)) == -1) {
 | 
							if ((nfds = poll(&pfd, 1, INFTIM)) == -1) {
 | 
				
			||||||
@@ -545,12 +581,12 @@ main(int argc, char **argv)
 | 
				
			|||||||
			fatalx("socket error");
 | 
								fatalx("socket error");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (pfd.revents & POLLIN) {
 | 
					                if (pfd.revents & POLLIN) {
 | 
				
			||||||
			if (dispatch_imsg(&cctx, shellcmd, &retcode) != 0)
 | 
								if (dispatch_imsg(ibuf, shellcmd, &retcode) != 0)
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (pfd.revents & POLLOUT) {
 | 
							if (pfd.revents & POLLOUT) {
 | 
				
			||||||
			if (msgbuf_write(&cctx.ibuf.w) < 0)
 | 
								if (msgbuf_write(&ibuf->w) < 0)
 | 
				
			||||||
				fatalx("msgbuf_write failed");
 | 
									fatalx("msgbuf_write failed");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -562,18 +598,18 @@ main(int argc, char **argv)
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int
 | 
					int
 | 
				
			||||||
dispatch_imsg(struct client_ctx *cctx, const char *shellcmd, int *retcode)
 | 
					dispatch_imsg(struct imsgbuf *ibuf, const char *shellcmd, int *retcode)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct imsg		imsg;
 | 
						struct imsg		imsg;
 | 
				
			||||||
	ssize_t			n, datalen;
 | 
						ssize_t			n, datalen;
 | 
				
			||||||
	struct msg_print_data	printdata;
 | 
						struct msg_print_data	printdata;
 | 
				
			||||||
	struct msg_shell_data	shelldata;
 | 
						struct msg_shell_data	shelldata;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ((n = imsg_read(&cctx->ibuf)) == -1 || n == 0)
 | 
					        if ((n = imsg_read(ibuf)) == -1 || n == 0)
 | 
				
			||||||
		fatalx("imsg_read failed");
 | 
							fatalx("imsg_read failed");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (;;) {
 | 
						for (;;) {
 | 
				
			||||||
		if ((n = imsg_get(&cctx->ibuf, &imsg)) == -1)
 | 
							if ((n = imsg_get(ibuf, &imsg)) == -1)
 | 
				
			||||||
			fatalx("imsg_get failed");
 | 
								fatalx("imsg_get failed");
 | 
				
			||||||
		if (n == 0)
 | 
							if (n == 0)
 | 
				
			||||||
			return (0);
 | 
								return (0);
 | 
				
			||||||
@@ -601,8 +637,7 @@ dispatch_imsg(struct client_ctx *cctx, const char *shellcmd, int *retcode)
 | 
				
			|||||||
			if (datalen != 0)
 | 
								if (datalen != 0)
 | 
				
			||||||
				fatalx("bad MSG_READY size");
 | 
									fatalx("bad MSG_READY size");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			*retcode = client_main(cctx);
 | 
								client_main();	/* doesn't return */
 | 
				
			||||||
			return (-1);
 | 
					 | 
				
			||||||
		case MSG_VERSION:
 | 
							case MSG_VERSION:
 | 
				
			||||||
			if (datalen != 0)
 | 
								if (datalen != 0)
 | 
				
			||||||
				fatalx("bad MSG_VERSION size");
 | 
									fatalx("bad MSG_VERSION size");
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										23
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								tmux.h
									
									
									
									
									
								
							@@ -1052,19 +1052,6 @@ struct client {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
ARRAY_DECL(clients, struct client *);
 | 
					ARRAY_DECL(clients, struct client *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Client context. */
 | 
					 | 
				
			||||||
struct client_ctx {
 | 
					 | 
				
			||||||
	struct imsgbuf	 ibuf;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	enum {
 | 
					 | 
				
			||||||
		CCTX_DETACH,
 | 
					 | 
				
			||||||
		CCTX_EXIT,
 | 
					 | 
				
			||||||
		CCTX_DIED,
 | 
					 | 
				
			||||||
		CCTX_SHUTDOWN
 | 
					 | 
				
			||||||
	} exittype;
 | 
					 | 
				
			||||||
	const char	*errstr;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Key/command line command. */
 | 
					/* Key/command line command. */
 | 
				
			||||||
struct cmd_ctx {
 | 
					struct cmd_ctx {
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
@@ -1503,14 +1490,8 @@ void	cmd_buffer_free(struct cmd *);
 | 
				
			|||||||
size_t	cmd_buffer_print(struct cmd *, char *, size_t);
 | 
					size_t	cmd_buffer_print(struct cmd *, char *, size_t);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* client.c */
 | 
					/* client.c */
 | 
				
			||||||
int	 client_init(char *, struct client_ctx *, int, int);
 | 
					struct imsgbuf *client_init(char *, int, int);
 | 
				
			||||||
int	 client_main(struct client_ctx *);
 | 
					__dead void	client_main(void);
 | 
				
			||||||
int	 client_msg_dispatch(struct client_ctx *);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* client-fn.c */
 | 
					 | 
				
			||||||
void	 client_write_server(struct client_ctx *, enum msgtype, void *, size_t);
 | 
					 | 
				
			||||||
void	 client_fill_session(struct msg_command_data *);
 | 
					 | 
				
			||||||
void	 client_suspend(void);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* key-bindings.c */
 | 
					/* key-bindings.c */
 | 
				
			||||||
extern struct key_bindings key_bindings;
 | 
					extern struct key_bindings key_bindings;
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user