xref: /openbsd/usr.bin/tmux/names.c (revision b52f0cbf)
1*b52f0cbfSnicm /* $OpenBSD: names.c,v 1.45 2021/08/20 17:50:42 nicm Exp $ */
2311827fbSnicm 
3311827fbSnicm /*
498ca8272Snicm  * Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
5311827fbSnicm  *
6311827fbSnicm  * Permission to use, copy, modify, and distribute this software for any
7311827fbSnicm  * purpose with or without fee is hereby granted, provided that the above
8311827fbSnicm  * copyright notice and this permission notice appear in all copies.
9311827fbSnicm  *
10311827fbSnicm  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11311827fbSnicm  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12311827fbSnicm  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13311827fbSnicm  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14311827fbSnicm  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15311827fbSnicm  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16311827fbSnicm  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17311827fbSnicm  */
18311827fbSnicm 
19311827fbSnicm #include <sys/types.h>
20311827fbSnicm 
21311827fbSnicm #include <ctype.h>
22311827fbSnicm #include <libgen.h>
237d053cf9Snicm #include <stdlib.h>
24311827fbSnicm #include <string.h>
25311827fbSnicm 
26311827fbSnicm #include "tmux.h"
27311827fbSnicm 
289883b791Snicm static void	 name_time_callback(int, short, void *);
299883b791Snicm static int	 name_time_expired(struct window *, struct timeval *);
30f5015e68Snicm 
31ced21769Snicm static char	*format_window_name(struct window *);
32ced21769Snicm 
339883b791Snicm static void
name_time_callback(__unused int fd,__unused short events,void * arg)34d0e2e7f1Snicm name_time_callback(__unused int fd, __unused short events, void *arg)
35311827fbSnicm {
3600b2deccSnicm 	struct window	*w = arg;
37f5015e68Snicm 
3800b2deccSnicm 	/* The event loop will call check_window_name for us on the way out. */
3900b2deccSnicm 	log_debug("@%u name timer expired", w->id);
4000b2deccSnicm }
41f5015e68Snicm 
429883b791Snicm static int
name_time_expired(struct window * w,struct timeval * tv)4300b2deccSnicm name_time_expired(struct window *w, struct timeval *tv)
4400b2deccSnicm {
4500b2deccSnicm 	struct timeval	offset;
4600b2deccSnicm 
4700b2deccSnicm 	timersub(tv, &w->name_time, &offset);
4800b2deccSnicm 	if (offset.tv_sec != 0 || offset.tv_usec > NAME_INTERVAL)
4900b2deccSnicm 		return (0);
5000b2deccSnicm 	return (NAME_INTERVAL - offset.tv_usec);
51f5015e68Snicm }
52f5015e68Snicm 
53f5015e68Snicm void
check_window_name(struct window * w)5400b2deccSnicm check_window_name(struct window *w)
55f5015e68Snicm {
5600b2deccSnicm 	struct timeval	 tv, next;
57203ea44bSnicm 	char		*name;
5800b2deccSnicm 	int		 left;
59311827fbSnicm 
60a3560846Snicm 	if (w->active == NULL)
61a3560846Snicm 		return;
62a3560846Snicm 
63d89252e5Snicm 	if (!options_get_number(w->options, "automatic-rename"))
6400b2deccSnicm 		return;
6500b2deccSnicm 
6600b2deccSnicm 	if (~w->active->flags & PANE_CHANGED) {
6700b2deccSnicm 		log_debug("@%u active pane not changed", w->id);
6891e80530Snicm 		return;
69f5015e68Snicm 	}
7000b2deccSnicm 	log_debug("@%u active pane changed", w->id);
71b0b8e5bfSnicm 
7200b2deccSnicm 	gettimeofday(&tv, NULL);
7300b2deccSnicm 	left = name_time_expired(w, &tv);
7400b2deccSnicm 	if (left != 0) {
7500b2deccSnicm 		if (!event_initialized(&w->name_event))
7600b2deccSnicm 			evtimer_set(&w->name_event, name_time_callback, w);
7700b2deccSnicm 		if (!evtimer_pending(&w->name_event, NULL)) {
786ae61da3Snicm 			log_debug("@%u name timer queued (%d left)", w->id,
796ae61da3Snicm 			    left);
8000b2deccSnicm 			timerclear(&next);
8100b2deccSnicm 			next.tv_usec = left;
8200b2deccSnicm 			event_add(&w->name_event, &next);
836ae61da3Snicm 		} else {
846ae61da3Snicm 			log_debug("@%u name timer already queued (%d left)",
856ae61da3Snicm 			    w->id, left);
866ae61da3Snicm 		}
875b9cc8aaSnicm 		return;
8800b2deccSnicm 	}
8900b2deccSnicm 	memcpy(&w->name_time, &tv, sizeof w->name_time);
9000b2deccSnicm 	if (event_initialized(&w->name_event))
9100b2deccSnicm 		evtimer_del(&w->name_event);
9200b2deccSnicm 
935b9cc8aaSnicm 	w->active->flags &= ~PANE_CHANGED;
945b9cc8aaSnicm 
95203ea44bSnicm 	name = format_window_name(w);
96203ea44bSnicm 	if (strcmp(name, w->name) != 0) {
9700b2deccSnicm 		log_debug("@%u new name %s (was %s)", w->id, name, w->name);
98203ea44bSnicm 		window_set_name(w, name);
9901c0c428Snicm 		server_redraw_window_borders(w);
100311827fbSnicm 		server_status_window(w);
10100b2deccSnicm 	} else
10200b2deccSnicm 		log_debug("@%u name not changed (still %s)", w->id, w->name);
10300b2deccSnicm 
104203ea44bSnicm 	free(name);
105311827fbSnicm }
106311827fbSnicm 
107311827fbSnicm char *
default_window_name(struct window * w)108311827fbSnicm default_window_name(struct window *w)
109311827fbSnicm {
11058034113Snicm 	char	*cmd, *s;
11158034113Snicm 
112c6ae5393Snicm 	if (w->active == NULL)
113c6ae5393Snicm 		return (xstrdup(""));
11458034113Snicm 	cmd = cmd_stringify_argv(w->active->argc, w->active->argv);
11558034113Snicm 	if (cmd != NULL && *cmd != '\0')
11658034113Snicm 		s = parse_window_name(cmd);
11758034113Snicm 	else
11858034113Snicm 		s = parse_window_name(w->active->shell);
11958034113Snicm 	free(cmd);
12058034113Snicm 	return (s);
121311827fbSnicm }
122311827fbSnicm 
123ced21769Snicm static char *
format_window_name(struct window * w)124203ea44bSnicm format_window_name(struct window *w)
125203ea44bSnicm {
126203ea44bSnicm 	struct format_tree	*ft;
12724a64db7Snicm 	const char		*fmt;
12824a64db7Snicm 	char			*name;
129203ea44bSnicm 
130d559dd45Snicm 	ft = format_create(NULL, NULL, FORMAT_WINDOW|w->id, 0);
131f426771eSnicm 	format_defaults_window(ft, w);
132f426771eSnicm 	format_defaults_pane(ft, w->active);
133203ea44bSnicm 
134d89252e5Snicm 	fmt = options_get_string(w->options, "automatic-rename-format");
135203ea44bSnicm 	name = format_expand(ft, fmt);
136203ea44bSnicm 
137203ea44bSnicm 	format_free(ft);
138203ea44bSnicm 	return (name);
139203ea44bSnicm }
140203ea44bSnicm 
141203ea44bSnicm char *
parse_window_name(const char * in)14266fd4858Snicm parse_window_name(const char *in)
143311827fbSnicm {
14466fd4858Snicm 	char	*copy, *name, *ptr;
145311827fbSnicm 
146311827fbSnicm 	name = copy = xstrdup(in);
1473fa4d618Snicm 	if (*name == '"')
1483fa4d618Snicm 		name++;
1493fa4d618Snicm 	name[strcspn(name, "\"")] = '\0';
1503fa4d618Snicm 
15166fd4858Snicm 	if (strncmp(name, "exec ", (sizeof "exec ") - 1) == 0)
15266fd4858Snicm 		name = name + (sizeof "exec ") - 1;
153311827fbSnicm 
154203ea44bSnicm 	while (*name == ' ' || *name == '-')
155311827fbSnicm 		name++;
156311827fbSnicm 	if ((ptr = strchr(name, ' ')) != NULL)
157311827fbSnicm 		*ptr = '\0';
158311827fbSnicm 
159311827fbSnicm 	if (*name != '\0') {
160311827fbSnicm 		ptr = name + strlen(name) - 1;
161d4dc61b7Snicm 		while (ptr > name &&
162d4dc61b7Snicm 		    !isalnum((u_char)*ptr) &&
163d4dc61b7Snicm 		    !ispunct((u_char)*ptr))
164311827fbSnicm 			*ptr-- = '\0';
165311827fbSnicm 	}
166311827fbSnicm 
167311827fbSnicm 	if (*name == '/')
168311827fbSnicm 		name = basename(name);
169311827fbSnicm 	name = xstrdup(name);
1707d053cf9Snicm 	free(copy);
171311827fbSnicm 	return (name);
172311827fbSnicm }
173