mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 09:26:05 +00:00 
			
		
		
		
	Tidy up and improve target (-t) argument parsing:
- move the code back into cmd.c and merge with the existing functions where possible; - accept "-tttyp0" as well as "-t/dev/ttyp0" for clients; - when looking up session names, try an exact match first, and if that fails look for it as an fnmatch pattern and then as the start of a name - if more that one session matches an error is given; so if there is one session called "mysession", -tmysession, -tmysess, -tmysess* are equivalent but if there is also "mysession2", the last two are errors; - similarly for windows, if the argument is not a valid index or exact window name match, try it against the window names as an fnmatch pattern and a prefix.
This commit is contained in:
		
							
								
								
									
										2
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								Makefile
									
									
									
									
									
								
							@@ -1,7 +1,7 @@
 | 
				
			|||||||
# $OpenBSD$
 | 
					# $OpenBSD$
 | 
				
			||||||
 | 
					
 | 
				
			||||||
PROG=	tmux
 | 
					PROG=	tmux
 | 
				
			||||||
SRCS=	arg.c attributes.c buffer-poll.c buffer.c cfg.c client-fn.c \
 | 
					SRCS=	attributes.c buffer-poll.c buffer.c cfg.c client-fn.c \
 | 
				
			||||||
	client-msg.c client.c clock.c cmd-attach-session.c cmd-bind-key.c \
 | 
						client-msg.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 \
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										194
									
								
								arg.c
									
									
									
									
									
								
							
							
						
						
									
										194
									
								
								arg.c
									
									
									
									
									
								
							@@ -1,194 +0,0 @@
 | 
				
			|||||||
/* $OpenBSD$ */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Copyright (c) 2008 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 <fnmatch.h>
 | 
					 | 
				
			||||||
#include <stdlib.h>
 | 
					 | 
				
			||||||
#include <string.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "tmux.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct client	*arg_lookup_client(const char *);
 | 
					 | 
				
			||||||
struct session	*arg_lookup_session(const char *);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct client *
 | 
					 | 
				
			||||||
arg_lookup_client(const char *name)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct client	*c;
 | 
					 | 
				
			||||||
	u_int		 i;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
 | 
					 | 
				
			||||||
		c = ARRAY_ITEM(&clients, i);
 | 
					 | 
				
			||||||
		if (c != NULL && strcmp(name, c->tty.path) == 0)
 | 
					 | 
				
			||||||
			return (c);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return (NULL);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct session *
 | 
					 | 
				
			||||||
arg_lookup_session(const char *name)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct session	*s, *newest = NULL;
 | 
					 | 
				
			||||||
	struct timeval	*tv;
 | 
					 | 
				
			||||||
	u_int		 i;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	tv = NULL;
 | 
					 | 
				
			||||||
	for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
 | 
					 | 
				
			||||||
		s = ARRAY_ITEM(&sessions, i);
 | 
					 | 
				
			||||||
		if (s == NULL || fnmatch(name, s->name, 0) != 0)
 | 
					 | 
				
			||||||
			continue;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (tv == NULL || timercmp(&s->tv, tv, >)) {
 | 
					 | 
				
			||||||
			newest = s;
 | 
					 | 
				
			||||||
			tv = &s->tv;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return (newest);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct client *
 | 
					 | 
				
			||||||
arg_parse_client(const char *arg)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct client	*c;
 | 
					 | 
				
			||||||
	char		*arg2;
 | 
					 | 
				
			||||||
	size_t		 n;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (arg != NULL && (arg[0] != ':' || arg[1] != '\0')) {
 | 
					 | 
				
			||||||
		arg2 = xstrdup(arg);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/* Trim a trailing : if any from the argument. */
 | 
					 | 
				
			||||||
		n = strlen(arg2);
 | 
					 | 
				
			||||||
		if (n && arg2[n - 1] == ':')
 | 
					 | 
				
			||||||
			arg2[n - 1] = '\0';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/* Try and look up the client name. */
 | 
					 | 
				
			||||||
		c = arg_lookup_client(arg2);
 | 
					 | 
				
			||||||
		xfree(arg2);
 | 
					 | 
				
			||||||
		return (c);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return (NULL);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct session *
 | 
					 | 
				
			||||||
arg_parse_session(const char *arg)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct session	*s;
 | 
					 | 
				
			||||||
	struct client	*c;
 | 
					 | 
				
			||||||
	char		*arg2;
 | 
					 | 
				
			||||||
	size_t		 n;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (arg != NULL && (arg[0] != ':' || arg[1] != '\0')) {
 | 
					 | 
				
			||||||
		arg2 = xstrdup(arg);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/* Trim a trailing : if any from the argument. */
 | 
					 | 
				
			||||||
		n = strlen(arg2);
 | 
					 | 
				
			||||||
		if (n && arg2[n - 1] == ':')
 | 
					 | 
				
			||||||
			arg2[n - 1] = '\0';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/* See if the argument matches a session. */
 | 
					 | 
				
			||||||
		if ((s = arg_lookup_session(arg2)) != NULL) {
 | 
					 | 
				
			||||||
			xfree(arg2);
 | 
					 | 
				
			||||||
			return (s);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/* If not try a client. */
 | 
					 | 
				
			||||||
		if ((c = arg_lookup_client(arg2)) != NULL) {
 | 
					 | 
				
			||||||
			xfree(arg2);
 | 
					 | 
				
			||||||
			return (c->session);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		xfree(arg2);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return (NULL);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int
 | 
					 | 
				
			||||||
arg_parse_window(const char *arg, struct session **s, int *idx)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	char		*arg2, *ptr;
 | 
					 | 
				
			||||||
	const char	*errstr;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	*idx = -1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Handle no argument or a single :. */
 | 
					 | 
				
			||||||
	if (arg == NULL || (arg[0] == ':' && arg[1] == '\0')) {
 | 
					 | 
				
			||||||
		*s = arg_parse_session(NULL);
 | 
					 | 
				
			||||||
		return (0);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Find the separator if any. */
 | 
					 | 
				
			||||||
	arg2 = xstrdup(arg);
 | 
					 | 
				
			||||||
	ptr = strrchr(arg2, ':');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/*
 | 
					 | 
				
			||||||
	 * If it is first, this means no session name, so use current session
 | 
					 | 
				
			||||||
	 * and try to convert the rest as index.
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	if (ptr == arg2) {
 | 
					 | 
				
			||||||
		*idx = strtonum(ptr + 1, 0, INT_MAX, &errstr);
 | 
					 | 
				
			||||||
		if (errstr != NULL) {
 | 
					 | 
				
			||||||
			xfree(arg2);
 | 
					 | 
				
			||||||
			return (1);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		xfree(arg2);
 | 
					 | 
				
			||||||
		*s = arg_parse_session(NULL);
 | 
					 | 
				
			||||||
		return (0);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* If missing, try as an index, else look up immediately. */
 | 
					 | 
				
			||||||
	if (ptr == NULL) {
 | 
					 | 
				
			||||||
		*idx = strtonum(arg2, 0, INT_MAX, &errstr);
 | 
					 | 
				
			||||||
		if (errstr == NULL) {
 | 
					 | 
				
			||||||
			/* This is good as an index; use current session. */
 | 
					 | 
				
			||||||
			xfree(arg2);
 | 
					 | 
				
			||||||
			*s = arg_parse_session(NULL);
 | 
					 | 
				
			||||||
			return (0);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		*idx = -1;
 | 
					 | 
				
			||||||
		goto lookup;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* If last, strip it and look up as a session. */
 | 
					 | 
				
			||||||
	if (ptr[1] == '\0') {
 | 
					 | 
				
			||||||
		*ptr = '\0';
 | 
					 | 
				
			||||||
		goto lookup;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Present but not first and not last. Break and convert both. */
 | 
					 | 
				
			||||||
	*ptr = '\0';
 | 
					 | 
				
			||||||
	*idx = strtonum(ptr + 1, 0, INT_MAX, &errstr);
 | 
					 | 
				
			||||||
	if (errstr != NULL) {
 | 
					 | 
				
			||||||
		xfree(arg2);
 | 
					 | 
				
			||||||
		return (1);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
lookup:
 | 
					 | 
				
			||||||
	/* Look up as session. */
 | 
					 | 
				
			||||||
	*s = arg_parse_session(arg2);
 | 
					 | 
				
			||||||
	xfree(arg2);
 | 
					 | 
				
			||||||
	if (*s == NULL)
 | 
					 | 
				
			||||||
		return (1);
 | 
					 | 
				
			||||||
	return (0);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -52,19 +52,8 @@ cmd_link_window_exec(struct cmd *self, struct cmd_ctx *ctx)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	if ((wl_src = cmd_find_window(ctx, data->src, NULL)) == NULL)
 | 
						if ((wl_src = cmd_find_window(ctx, data->src, NULL)) == NULL)
 | 
				
			||||||
		return (-1);
 | 
							return (-1);
 | 
				
			||||||
 | 
						if ((idx = cmd_find_index(ctx, data->dst, &dst)) == -2)
 | 
				
			||||||
	if (arg_parse_window(data->dst, &dst, &idx) != 0) {
 | 
					 | 
				
			||||||
		ctx->error(ctx, "bad window: %s", data->dst);
 | 
					 | 
				
			||||||
		return (-1);
 | 
							return (-1);
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (dst == NULL)
 | 
					 | 
				
			||||||
		dst = ctx->cursession;
 | 
					 | 
				
			||||||
	if (dst == NULL)
 | 
					 | 
				
			||||||
		dst = cmd_current_session(ctx);
 | 
					 | 
				
			||||||
	if (dst == NULL) {
 | 
					 | 
				
			||||||
		ctx->error(ctx, "session not found: %s", data->dst);
 | 
					 | 
				
			||||||
		return (-1);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wl_dst = NULL;
 | 
						wl_dst = NULL;
 | 
				
			||||||
	if (idx != -1)
 | 
						if (idx != -1)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -54,19 +54,8 @@ cmd_move_window_exec(struct cmd *self, struct cmd_ctx *ctx)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	if ((wl_src = cmd_find_window(ctx, data->src, &src)) == NULL)
 | 
						if ((wl_src = cmd_find_window(ctx, data->src, &src)) == NULL)
 | 
				
			||||||
		return (-1);
 | 
							return (-1);
 | 
				
			||||||
 | 
						if ((idx = cmd_find_index(ctx, data->dst, &dst)) == -2)
 | 
				
			||||||
	if (arg_parse_window(data->dst, &dst, &idx) != 0) {
 | 
					 | 
				
			||||||
		ctx->error(ctx, "bad window: %s", data->dst);
 | 
					 | 
				
			||||||
		return (-1);
 | 
							return (-1);
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (dst == NULL)
 | 
					 | 
				
			||||||
		dst = ctx->cursession;
 | 
					 | 
				
			||||||
	if (dst == NULL)
 | 
					 | 
				
			||||||
		dst = cmd_current_session(ctx);
 | 
					 | 
				
			||||||
	if (dst == NULL) {
 | 
					 | 
				
			||||||
		ctx->error(ctx, "session not found: %s", data->dst);
 | 
					 | 
				
			||||||
		return (-1);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wl_dst = NULL;
 | 
						wl_dst = NULL;
 | 
				
			||||||
	if (idx != -1)
 | 
						if (idx != -1)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -126,18 +126,8 @@ cmd_new_window_exec(struct cmd *self, struct cmd_ctx *ctx)
 | 
				
			|||||||
	if (data == NULL)
 | 
						if (data == NULL)
 | 
				
			||||||
		return (0);
 | 
							return (0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (arg_parse_window(data->target, &s, &idx) != 0) {
 | 
						if ((idx = cmd_find_index(ctx, data->target, &s)) == -2)
 | 
				
			||||||
		ctx->error(ctx, "bad window: %s", data->target);
 | 
					 | 
				
			||||||
		return (-1);
 | 
							return (-1);
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (s == NULL)
 | 
					 | 
				
			||||||
		s = ctx->cursession;
 | 
					 | 
				
			||||||
	if (s == NULL)
 | 
					 | 
				
			||||||
		s = cmd_current_session(ctx);
 | 
					 | 
				
			||||||
	if (s == NULL) {
 | 
					 | 
				
			||||||
		ctx->error(ctx, "session not found: %s", data->target);
 | 
					 | 
				
			||||||
		return (-1);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wl = NULL;
 | 
						wl = NULL;
 | 
				
			||||||
	if (idx != -1)
 | 
						if (idx != -1)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										420
									
								
								cmd.c
									
									
									
									
									
								
							
							
						
						
									
										420
									
								
								cmd.c
									
									
									
									
									
								
							@@ -19,6 +19,8 @@
 | 
				
			|||||||
#include <sys/types.h>
 | 
					#include <sys/types.h>
 | 
				
			||||||
#include <sys/time.h>
 | 
					#include <sys/time.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <fnmatch.h>
 | 
				
			||||||
 | 
					#include <paths.h>
 | 
				
			||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
#include <unistd.h>
 | 
					#include <unistd.h>
 | 
				
			||||||
@@ -100,6 +102,11 @@ const struct cmd_entry *cmd_table[] = {
 | 
				
			|||||||
	NULL
 | 
						NULL
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct session	*cmd_newest_session(void);
 | 
				
			||||||
 | 
					struct client	*cmd_lookup_client(const char *);
 | 
				
			||||||
 | 
					struct session	*cmd_lookup_session(const char *, int *);
 | 
				
			||||||
 | 
					struct winlink	*cmd_lookup_window(struct session *, const char *, int *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct cmd *
 | 
					struct cmd *
 | 
				
			||||||
cmd_parse(int argc, char **argv, char **cause)
 | 
					cmd_parse(int argc, char **argv, char **cause)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -294,106 +301,421 @@ cmd_recv_string(struct buffer *b)
 | 
				
			|||||||
	return (s);
 | 
						return (s);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Figure out the current session. Use: 1) the current session, if the command
 | 
				
			||||||
 | 
					 * context has one; 2) the session specified in the TMUX variable from the
 | 
				
			||||||
 | 
					 * environment (as passed from the client); 3) the newest session.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
struct session *
 | 
					struct session *
 | 
				
			||||||
cmd_current_session(struct cmd_ctx *ctx)
 | 
					cmd_current_session(struct cmd_ctx *ctx)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct msg_command_data	*data = ctx->msgdata;
 | 
						struct msg_command_data	*data = ctx->msgdata;
 | 
				
			||||||
	struct timeval		*tv;
 | 
						struct session		*s;
 | 
				
			||||||
	struct session		*s, *newest = NULL;
 | 
					 | 
				
			||||||
	u_int			 i;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (ctx->cursession != NULL)
 | 
						if (ctx->cursession != NULL)
 | 
				
			||||||
		return (ctx->cursession);
 | 
							return (ctx->cursession);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (data != NULL && data->pid != -1) {
 | 
						if (data != NULL && data->pid != -1) {
 | 
				
			||||||
		if (data->pid != getpid()) {
 | 
							if (data->pid != getpid())
 | 
				
			||||||
			ctx->error(ctx, "wrong server: %ld", (long) data->pid);
 | 
					 | 
				
			||||||
			return (NULL);
 | 
								return (NULL);
 | 
				
			||||||
		}
 | 
							if (data->idx > ARRAY_LENGTH(&sessions))
 | 
				
			||||||
		if (data->idx > ARRAY_LENGTH(&sessions)) {
 | 
					 | 
				
			||||||
			ctx->error(ctx, "index out of range: %d", data->idx);
 | 
					 | 
				
			||||||
			return (NULL);
 | 
								return (NULL);
 | 
				
			||||||
		}
 | 
							if ((s = ARRAY_ITEM(&sessions, data->idx)) == NULL)
 | 
				
			||||||
		if ((s = ARRAY_ITEM(&sessions, data->idx)) == NULL) {
 | 
					 | 
				
			||||||
			ctx->error(ctx, "session doesn't exist: %u", data->idx);
 | 
					 | 
				
			||||||
			return (NULL);
 | 
								return (NULL);
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return (s);
 | 
							return (s);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	tv = NULL;
 | 
						return (cmd_newest_session());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Find the newest session. */
 | 
				
			||||||
 | 
					struct session *
 | 
				
			||||||
 | 
					cmd_newest_session(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct session	*s, *snewest;
 | 
				
			||||||
 | 
						struct timeval	*tv = NULL;
 | 
				
			||||||
 | 
						u_int		 i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						snewest = NULL;
 | 
				
			||||||
	for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
 | 
						for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
 | 
				
			||||||
		s = ARRAY_ITEM(&sessions, i);
 | 
							if ((s = ARRAY_ITEM(&sessions, i)) == NULL)
 | 
				
			||||||
		if (s != NULL && (tv == NULL || timercmp(&s->tv, tv, >))) {
 | 
								continue;
 | 
				
			||||||
			newest = ARRAY_ITEM(&sessions, i);
 | 
					
 | 
				
			||||||
 | 
							if (tv == NULL || timercmp(&s->tv, tv, >)) {
 | 
				
			||||||
 | 
								snewest = s;
 | 
				
			||||||
			tv = &s->tv;
 | 
								tv = &s->tv;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return (newest);
 | 
					
 | 
				
			||||||
 | 
						return (snewest);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Find the target client or report an error and return NULL. */
 | 
				
			||||||
struct client *
 | 
					struct client *
 | 
				
			||||||
cmd_find_client(struct cmd_ctx *ctx, const char *arg)
 | 
					cmd_find_client(struct cmd_ctx *ctx, const char *arg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct client	*c;
 | 
						struct client	*c;
 | 
				
			||||||
 | 
						char		*tmparg;
 | 
				
			||||||
 | 
						size_t		 arglen;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* A NULL argument means the current client. */
 | 
				
			||||||
	if (arg == NULL)
 | 
						if (arg == NULL)
 | 
				
			||||||
		c = ctx->curclient;
 | 
							return (ctx->curclient);
 | 
				
			||||||
	else {
 | 
						tmparg = xstrdup(arg);
 | 
				
			||||||
		if ((c = arg_parse_client(arg)) == NULL) {
 | 
					
 | 
				
			||||||
			if (arg != NULL)
 | 
						/* Trim a single trailing colon if any. */
 | 
				
			||||||
				ctx->error(ctx, "client not found: %s", arg);
 | 
						arglen = strlen(tmparg);
 | 
				
			||||||
			else
 | 
						if (arglen != 0 && tmparg[arglen - 1] == ':')
 | 
				
			||||||
				ctx->error(ctx, "no client found");
 | 
							tmparg[arglen - 1] = '\0';
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
	}
 | 
						/* Find the client, if any. */
 | 
				
			||||||
 | 
						c = cmd_lookup_client(tmparg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* If no client found, report an error. */
 | 
				
			||||||
 | 
						if (c == NULL)
 | 
				
			||||||
 | 
							ctx->error(ctx, "client not found: %s", tmparg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						xfree(tmparg);
 | 
				
			||||||
	return (c);
 | 
						return (c);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Lookup a client by device path. Either of a full match and a match without a
 | 
				
			||||||
 | 
					 * leading _PATH_DEV ("/dev/") is accepted.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct client *
 | 
				
			||||||
 | 
					cmd_lookup_client(const char *name)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct client	*c;
 | 
				
			||||||
 | 
						const char	*path;
 | 
				
			||||||
 | 
						u_int		 i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
 | 
				
			||||||
 | 
							if ((c = ARRAY_ITEM(&clients, i)) == NULL)
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
							path = c->tty.path;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* Check for exact matches. */
 | 
				
			||||||
 | 
							if (strcmp(name, path) == 0)
 | 
				
			||||||
 | 
								return (c);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* Check without leading /dev if present. */
 | 
				
			||||||
 | 
							if (strncmp(path, _PATH_DEV, (sizeof _PATH_DEV) - 1) != 0)
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
							if (strcmp(name, path + (sizeof _PATH_DEV) - 1) == 0)
 | 
				
			||||||
 | 
								return (c);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return (NULL);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Lookup a session by name. If no session is found, NULL is returned. */
 | 
				
			||||||
 | 
					struct session *
 | 
				
			||||||
 | 
					cmd_lookup_session(const char *name, int *ambiguous)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct session	*s, *sfound;
 | 
				
			||||||
 | 
						u_int		 i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*ambiguous = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Look for matches. Session names must be unique so an exact match
 | 
				
			||||||
 | 
						 * can't be ambigious and can just be returned.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						sfound = NULL;
 | 
				
			||||||
 | 
						for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {	
 | 
				
			||||||
 | 
							if ((s = ARRAY_ITEM(&sessions, i)) == NULL)
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* Check for an exact match and return it if found. */
 | 
				
			||||||
 | 
							if (strcmp(name, s->name) == 0)
 | 
				
			||||||
 | 
								return (s);
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							/* Then check for pattern matches. */
 | 
				
			||||||
 | 
							if (strncmp(name, s->name, strlen(name)) == 0 ||
 | 
				
			||||||
 | 
							    fnmatch(name, s->name, 0) == 0) {
 | 
				
			||||||
 | 
								if (sfound != NULL) {
 | 
				
			||||||
 | 
									*ambiguous = 1;
 | 
				
			||||||
 | 
									return (NULL);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								sfound = s;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
					 	return (sfound);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Lookup a window or return -1 if not found or ambigious. First try as an index
 | 
				
			||||||
 | 
					 * and if invalid, use fnmatch or leading prefix.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct winlink *
 | 
				
			||||||
 | 
					cmd_lookup_window(struct session *s, const char *name, int *ambiguous)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct winlink	*wl, *wlfound;
 | 
				
			||||||
 | 
						struct window	*w;
 | 
				
			||||||
 | 
						const char	*errstr;
 | 
				
			||||||
 | 
						u_int		 idx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*ambiguous = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* First see if this is a valid window index in this session. */
 | 
				
			||||||
 | 
						idx = strtonum(name, 0, INT_MAX, &errstr);
 | 
				
			||||||
 | 
						if (errstr == NULL) {
 | 
				
			||||||
 | 
							if ((wl = winlink_find_by_index(&s->windows, idx)) != NULL)
 | 
				
			||||||
 | 
								return (wl);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
						/* Look for exact matches, error if more than one. */
 | 
				
			||||||
 | 
						wlfound = NULL;
 | 
				
			||||||
 | 
						RB_FOREACH(wl, winlinks, &s->windows) {
 | 
				
			||||||
 | 
							w = wl->window;
 | 
				
			||||||
 | 
							if (strcmp(name, w->name) == 0) {
 | 
				
			||||||
 | 
								if (wlfound != NULL) {
 | 
				
			||||||
 | 
									*ambiguous = 1;
 | 
				
			||||||
 | 
									return (NULL);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								wlfound = wl;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (wlfound != NULL)
 | 
				
			||||||
 | 
							return (wlfound);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Now look for pattern matches, again error if multiple. */
 | 
				
			||||||
 | 
						wlfound = NULL;
 | 
				
			||||||
 | 
						RB_FOREACH(wl, winlinks, &s->windows) {
 | 
				
			||||||
 | 
							w = wl->window;
 | 
				
			||||||
 | 
							if (strncmp(name, w->name, strlen(name)) == 0 ||
 | 
				
			||||||
 | 
							    fnmatch(name, w->name, 0) == 0) {
 | 
				
			||||||
 | 
								if (wlfound != NULL) {
 | 
				
			||||||
 | 
									*ambiguous = 1;
 | 
				
			||||||
 | 
									return (NULL);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								wlfound = wl;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}	
 | 
				
			||||||
 | 
						if (wlfound != NULL)
 | 
				
			||||||
 | 
							return (wlfound);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return (NULL);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Find the target session or report an error and return NULL. */
 | 
				
			||||||
struct session *
 | 
					struct session *
 | 
				
			||||||
cmd_find_session(struct cmd_ctx *ctx, const char *arg)
 | 
					cmd_find_session(struct cmd_ctx *ctx, const char *arg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct session	*s;
 | 
						struct session	*s;
 | 
				
			||||||
 | 
						struct client	*c;
 | 
				
			||||||
 | 
						char		*tmparg;
 | 
				
			||||||
 | 
						size_t		 arglen;
 | 
				
			||||||
 | 
						int		 ambiguous;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* A NULL argument means the current session. */
 | 
				
			||||||
	if (arg == NULL)
 | 
						if (arg == NULL)
 | 
				
			||||||
		s = cmd_current_session(ctx);
 | 
							return (cmd_current_session(ctx));
 | 
				
			||||||
	else {
 | 
						tmparg = xstrdup(arg);
 | 
				
			||||||
		if ((s = arg_parse_session(arg)) == NULL) {
 | 
					
 | 
				
			||||||
			if (arg != NULL)
 | 
						/* Trim a single trailing colon if any. */
 | 
				
			||||||
				ctx->error(ctx, "session not found: %s", arg);
 | 
						arglen = strlen(tmparg);
 | 
				
			||||||
			else
 | 
						if (arglen != 0 && tmparg[arglen - 1] == ':')
 | 
				
			||||||
				ctx->error(ctx, "no session found");
 | 
							tmparg[arglen - 1] = '\0';
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
 | 
						/* Find the session, if any. */
 | 
				
			||||||
 | 
						s = cmd_lookup_session(tmparg, &ambiguous);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* If it doesn't, try to match it as a client. */
 | 
				
			||||||
 | 
						if (s == NULL && (c = cmd_lookup_client(tmparg)) != NULL)
 | 
				
			||||||
 | 
							s = c->session;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* If no session found, report an error. */
 | 
				
			||||||
 | 
						if (s == NULL) {
 | 
				
			||||||
 | 
							if (ambiguous)
 | 
				
			||||||
 | 
								ctx->error(ctx, "more than one session: %s", tmparg);
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								ctx->error(ctx, "session not found: %s", tmparg);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						xfree(tmparg);
 | 
				
			||||||
	return (s);
 | 
						return (s);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Find the target session and window or report an error and return NULL. */
 | 
				
			||||||
struct winlink *
 | 
					struct winlink *
 | 
				
			||||||
cmd_find_window(struct cmd_ctx *ctx, const char *arg, struct session **sp)
 | 
					cmd_find_window(struct cmd_ctx *ctx, const char *arg, struct session **sp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct session	*s;
 | 
						struct session	*s;
 | 
				
			||||||
	struct winlink	*wl;
 | 
						struct winlink	*wl;
 | 
				
			||||||
	int		 idx;
 | 
						const char	*winptr;
 | 
				
			||||||
 | 
						char		*sessptr = NULL;
 | 
				
			||||||
 | 
						int		 ambiguous = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wl = NULL;
 | 
						/*
 | 
				
			||||||
	if (arg_parse_window(arg, &s, &idx) != 0) {
 | 
						 * Find the current session. There must always be a current session, if
 | 
				
			||||||
		ctx->error(ctx, "bad window: %s", arg);
 | 
						 * it can't be found, report an error.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if ((s = cmd_current_session(ctx)) == NULL) {
 | 
				
			||||||
 | 
							ctx->error(ctx, "can't establish current session");
 | 
				
			||||||
		return (NULL);
 | 
							return (NULL);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (s == NULL)
 | 
					
 | 
				
			||||||
		s = ctx->cursession;
 | 
						/* A NULL argument means the current session and window. */
 | 
				
			||||||
	if (s == NULL)
 | 
						if (arg == NULL) {
 | 
				
			||||||
		s = cmd_current_session(ctx);
 | 
							if (sp != NULL)
 | 
				
			||||||
	if (s == NULL)
 | 
								*sp = s;
 | 
				
			||||||
		return (NULL);
 | 
							return (s->curw);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Time to look at the argument. If it is empty, that is an error. */
 | 
				
			||||||
 | 
						if (*arg == '\0')
 | 
				
			||||||
 | 
							goto not_found;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Find the separating colon. If none, assume the current session. */
 | 
				
			||||||
 | 
						winptr = strchr(arg, ':');
 | 
				
			||||||
 | 
						if (winptr == NULL)
 | 
				
			||||||
 | 
							winptr = xstrdup(arg);
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
							winptr++;	/* skip : */
 | 
				
			||||||
 | 
							sessptr = xstrdup(arg);
 | 
				
			||||||
 | 
							*strchr(sessptr, ':') = '\0';
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						log_debug("%s: winptr=%s, sessptr=%s", __func__, winptr, sessptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Try to lookup the session if present. */
 | 
				
			||||||
 | 
						if (sessptr != NULL && *sessptr != '\0') {
 | 
				
			||||||
 | 
							if  ((s = cmd_lookup_session(sessptr, &ambiguous)) == NULL)
 | 
				
			||||||
 | 
								goto no_session;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	if (sp != NULL)
 | 
						if (sp != NULL)
 | 
				
			||||||
		*sp = s;
 | 
							*sp = s;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (idx == -1)
 | 
						/*
 | 
				
			||||||
 | 
						 * Then work out the window. An empty string is the current window,
 | 
				
			||||||
 | 
						 * otherwise try to look it up in the session.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (winptr == NULL || *winptr == '\0')
 | 
				
			||||||
		wl = s->curw;
 | 
							wl = s->curw;
 | 
				
			||||||
	else
 | 
						else if ((wl = cmd_lookup_window(s, winptr, &ambiguous)) == NULL)
 | 
				
			||||||
		wl = winlink_find_by_index(&s->windows, idx);
 | 
							goto not_found;
 | 
				
			||||||
	if (wl == NULL)
 | 
						
 | 
				
			||||||
		ctx->error(ctx, "window not found: %s:%d", s->name, idx);
 | 
						if (sessptr != NULL)
 | 
				
			||||||
 | 
							xfree(sessptr);
 | 
				
			||||||
	return (wl);
 | 
						return (wl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					no_session:
 | 
				
			||||||
 | 
						if (ambiguous)
 | 
				
			||||||
 | 
							ctx->error(ctx, "multiple sessions: %s", sessptr);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							ctx->error(ctx, "session not found: %s", sessptr);
 | 
				
			||||||
 | 
						if (sessptr != NULL)
 | 
				
			||||||
 | 
							xfree(sessptr);
 | 
				
			||||||
 | 
						return (NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					not_found:
 | 
				
			||||||
 | 
						if (ambiguous)
 | 
				
			||||||
 | 
							ctx->error(ctx, "multiple windows: %s", arg);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							ctx->error(ctx, "window not found: %s", arg);
 | 
				
			||||||
 | 
						if (sessptr != NULL)
 | 
				
			||||||
 | 
							xfree(sessptr);
 | 
				
			||||||
 | 
						return (NULL);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Find the target session and window index, whether or not it exists in the
 | 
				
			||||||
 | 
					 * session. Return -2 on error or -1 if no window index is specified. This is
 | 
				
			||||||
 | 
					 * used when parsing an argument for a window target that may not be exist (for
 | 
				
			||||||
 | 
					 * example it is going to be created).
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					cmd_find_index(struct cmd_ctx *ctx, const char *arg, struct session **sp)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct session	*s;
 | 
				
			||||||
 | 
						struct winlink	*wl;
 | 
				
			||||||
 | 
						const char	*winptr, *errstr;
 | 
				
			||||||
 | 
						char		*sessptr = NULL;
 | 
				
			||||||
 | 
						int		 idx, ambiguous = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Find the current session. There must always be a current session, if
 | 
				
			||||||
 | 
						 * it can't be found, report an error.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if ((s = cmd_current_session(ctx)) == NULL) {
 | 
				
			||||||
 | 
							ctx->error(ctx, "can't establish current session");
 | 
				
			||||||
 | 
							return (NULL);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* A NULL argument means the current session and "no window" (-1). */
 | 
				
			||||||
 | 
						if (arg == NULL) {
 | 
				
			||||||
 | 
							if (sp != NULL)
 | 
				
			||||||
 | 
								*sp = s;
 | 
				
			||||||
 | 
							return (-1);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Time to look at the argument. If it is empty, that is an error. */
 | 
				
			||||||
 | 
						if (*arg == '\0')
 | 
				
			||||||
 | 
							goto not_found;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Find the separating colon. If none, assume the current session. */
 | 
				
			||||||
 | 
						winptr = strchr(arg, ':');
 | 
				
			||||||
 | 
						if (winptr == NULL)
 | 
				
			||||||
 | 
							winptr = xstrdup(arg);
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
							winptr++;	/* skip : */
 | 
				
			||||||
 | 
							sessptr = xstrdup(arg);
 | 
				
			||||||
 | 
							*strchr(sessptr, ':') = '\0';
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						log_debug("%s: winptr=%s, sessptr=%s", __func__, winptr, sessptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Try to lookup the session if present. */
 | 
				
			||||||
 | 
						if (sessptr != NULL && *sessptr != '\0') {
 | 
				
			||||||
 | 
							if  ((s = cmd_lookup_session(sessptr, &ambiguous)) == NULL)
 | 
				
			||||||
 | 
								goto no_session;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (sp != NULL)
 | 
				
			||||||
 | 
							*sp = s;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Then work out the window. No : means "no window" (-1), an empty
 | 
				
			||||||
 | 
						 * string is the current window, otherwise try to look it up in the
 | 
				
			||||||
 | 
						 * session.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (winptr == NULL)
 | 
				
			||||||
 | 
							idx = -1;
 | 
				
			||||||
 | 
						else if (*winptr == '\0')
 | 
				
			||||||
 | 
							idx = s->curw->idx;
 | 
				
			||||||
 | 
						else if ((wl = cmd_lookup_window(s, winptr, &ambiguous)) == NULL) {
 | 
				
			||||||
 | 
							if (ambiguous)
 | 
				
			||||||
 | 
								goto not_found;
 | 
				
			||||||
 | 
							/* Don't care it doesn't exist if this is a valid index. */
 | 
				
			||||||
 | 
							idx = strtonum(winptr, 0, INT_MAX, &errstr);
 | 
				
			||||||
 | 
							if (errstr != NULL)  {
 | 
				
			||||||
 | 
								ctx->error(ctx, "index %s: %s", errstr, winptr);
 | 
				
			||||||
 | 
								idx = -2;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else
 | 
				
			||||||
 | 
							idx = wl->idx;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						if (sessptr != NULL)
 | 
				
			||||||
 | 
							xfree(sessptr);
 | 
				
			||||||
 | 
						return (idx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					no_session:
 | 
				
			||||||
 | 
						if (ambiguous)
 | 
				
			||||||
 | 
					 		ctx->error(ctx, "multiple sessions: %s", sessptr);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							ctx->error(ctx, "session not found: %s", sessptr);
 | 
				
			||||||
 | 
						if (sessptr != NULL)
 | 
				
			||||||
 | 
							xfree(sessptr);
 | 
				
			||||||
 | 
						return (-2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					not_found:
 | 
				
			||||||
 | 
						if (ambiguous)
 | 
				
			||||||
 | 
							ctx->error(ctx, "multiple windows: %s", arg);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							ctx->error(ctx, "window not found: %s", arg);
 | 
				
			||||||
 | 
						if (sessptr != NULL)
 | 
				
			||||||
 | 
							xfree(sessptr);
 | 
				
			||||||
 | 
						return (-2);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										41
									
								
								tmux.1
									
									
									
									
									
								
							
							
						
						
									
										41
									
								
								tmux.1
									
									
									
									
									
								
							@@ -500,8 +500,14 @@ These specify the client, session or window which a command should affect.
 | 
				
			|||||||
.Ar target-client
 | 
					.Ar target-client
 | 
				
			||||||
is the name of the
 | 
					is the name of the
 | 
				
			||||||
.Xr pty 4
 | 
					.Xr pty 4
 | 
				
			||||||
file to which the client is connected, for example
 | 
					file to which the client is connected, for example either of
 | 
				
			||||||
 | 
					.Pa /dev/ttyp1
 | 
				
			||||||
 | 
					or
 | 
				
			||||||
 | 
					.Pa ttyp1
 | 
				
			||||||
 | 
					for the client attached to 
 | 
				
			||||||
.Pa /dev/ttyp1 .
 | 
					.Pa /dev/ttyp1 .
 | 
				
			||||||
 | 
					If no client is specified, the current client is chosen, if possible, or an
 | 
				
			||||||
 | 
					error is reported.
 | 
				
			||||||
Clients may be listed with the
 | 
					Clients may be listed with the
 | 
				
			||||||
.Ic list-clients
 | 
					.Ic list-clients
 | 
				
			||||||
command.
 | 
					command.
 | 
				
			||||||
@@ -509,23 +515,32 @@ command.
 | 
				
			|||||||
.Ar target-session
 | 
					.Ar target-session
 | 
				
			||||||
is either the name of a session (as listed by the
 | 
					is either the name of a session (as listed by the
 | 
				
			||||||
.Ic list-sessions
 | 
					.Ic list-sessions
 | 
				
			||||||
command) or the name of a client,
 | 
					command) or the name of a client with the same syntax as
 | 
				
			||||||
.Ar target-client ,
 | 
					.Ar target-client ,
 | 
				
			||||||
in which case the session attached to the client is used.
 | 
					in which case the session attached to the client is used.
 | 
				
			||||||
An
 | 
					When looking for the session name, 
 | 
				
			||||||
 | 
					.Nm
 | 
				
			||||||
 | 
					initially searches for an exact match; if none is found, the session names
 | 
				
			||||||
 | 
					are checked for any for which
 | 
				
			||||||
 | 
					.Ar target-session
 | 
				
			||||||
 | 
					is a prefix or for which it matches as an
 | 
				
			||||||
.Xr fnmatch 3
 | 
					.Xr fnmatch 3
 | 
				
			||||||
pattern may be used to match the session name.
 | 
					pattern.
 | 
				
			||||||
If a session is omitted when required,
 | 
					If a single match is found, it is used as the target session; multiple matches
 | 
				
			||||||
.Nm tmux
 | 
					produce an error
 | 
				
			||||||
attempts to use the current session; if no current session is available, the
 | 
					If a session is omitted, the current session is used if available; if no
 | 
				
			||||||
most recently created is chosen.
 | 
					current session is available, the most recently created is chosen.
 | 
				
			||||||
If no client is specified, the current client is chosen, if possible, or an
 | 
					 | 
				
			||||||
error is reported.
 | 
					 | 
				
			||||||
.Pp
 | 
					.Pp
 | 
				
			||||||
.Ar target-window
 | 
					.Ar target-window
 | 
				
			||||||
specifies a window in the form
 | 
					specifies a window in the form
 | 
				
			||||||
.Em session Ns \&: Ns Em index ,
 | 
					.Em session Ns \&: Ns Em window ,
 | 
				
			||||||
for example mysession:1.
 | 
					where
 | 
				
			||||||
 | 
					.Em window
 | 
				
			||||||
 | 
					is a window index, for example mysession:1, or a window name,
 | 
				
			||||||
 | 
					.Xr fnmatch 3
 | 
				
			||||||
 | 
					pattern, or prefix, such as mysession:mywin[0-3].
 | 
				
			||||||
 | 
					If the latter, the window is looked up in a similar fashion to session name
 | 
				
			||||||
 | 
					searches described above.
 | 
				
			||||||
The session is in the same form as for
 | 
					The session is in the same form as for
 | 
				
			||||||
.Ar target-session .
 | 
					.Ar target-session .
 | 
				
			||||||
.Em session ,
 | 
					.Em session ,
 | 
				
			||||||
@@ -536,7 +551,7 @@ If
 | 
				
			|||||||
is omitted, the same rules as for
 | 
					is omitted, the same rules as for
 | 
				
			||||||
.Ar target-session
 | 
					.Ar target-session
 | 
				
			||||||
are followed; if
 | 
					are followed; if
 | 
				
			||||||
.Em index
 | 
					.Em window
 | 
				
			||||||
is not present, the current window for the given session is used.
 | 
					is not present, the current window for the given session is used.
 | 
				
			||||||
When the argument does not contain a colon,
 | 
					When the argument does not contain a colon,
 | 
				
			||||||
.Nm
 | 
					.Nm
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										9
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										9
									
								
								tmux.h
									
									
									
									
									
								
							@@ -1076,11 +1076,6 @@ int		 paste_replace(struct paste_stack *, u_int, char *);
 | 
				
			|||||||
/* clock.c */
 | 
					/* clock.c */
 | 
				
			||||||
void		 clock_draw(struct screen_write_ctx *, u_int, int);
 | 
					void		 clock_draw(struct screen_write_ctx *, u_int, int);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* arg.c */
 | 
					 | 
				
			||||||
struct client 	*arg_parse_client(const char *);
 | 
					 | 
				
			||||||
struct session 	*arg_parse_session(const char *);
 | 
					 | 
				
			||||||
int		 arg_parse_window(const char *, struct session **, int *);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* cmd.c */
 | 
					/* cmd.c */
 | 
				
			||||||
struct cmd	*cmd_parse(int, char **, char **);
 | 
					struct cmd	*cmd_parse(int, char **, char **);
 | 
				
			||||||
int		 cmd_exec(struct cmd *, struct cmd_ctx *);
 | 
					int		 cmd_exec(struct cmd *, struct cmd_ctx *);
 | 
				
			||||||
@@ -1094,7 +1089,9 @@ struct session	*cmd_current_session(struct cmd_ctx *);
 | 
				
			|||||||
struct client	*cmd_find_client(struct cmd_ctx *, const char *);
 | 
					struct client	*cmd_find_client(struct cmd_ctx *, const char *);
 | 
				
			||||||
struct session	*cmd_find_session(struct cmd_ctx *, const char *);
 | 
					struct session	*cmd_find_session(struct cmd_ctx *, const char *);
 | 
				
			||||||
struct winlink	*cmd_find_window(
 | 
					struct winlink	*cmd_find_window(
 | 
				
			||||||
    		     struct cmd_ctx *, const char *, struct session **);
 | 
							     struct cmd_ctx *, const char *, struct session **);
 | 
				
			||||||
 | 
					int		 cmd_find_index(
 | 
				
			||||||
 | 
							     struct cmd_ctx *, const char *, struct session **);
 | 
				
			||||||
extern const struct cmd_entry *cmd_table[];
 | 
					extern const struct cmd_entry *cmd_table[];
 | 
				
			||||||
extern const struct cmd_entry cmd_attach_session_entry;
 | 
					extern const struct cmd_entry cmd_attach_session_entry;
 | 
				
			||||||
extern const struct cmd_entry cmd_bind_key_entry;
 | 
					extern const struct cmd_entry cmd_bind_key_entry;
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user