xref: /minix3/external/bsd/tmux/dist/tmux.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc /* Id */
2eda6f593SDavid van Moolenbroek 
3eda6f593SDavid van Moolenbroek /*
4eda6f593SDavid van Moolenbroek  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
5eda6f593SDavid van Moolenbroek  *
6eda6f593SDavid van Moolenbroek  * Permission to use, copy, modify, and distribute this software for any
7eda6f593SDavid van Moolenbroek  * purpose with or without fee is hereby granted, provided that the above
8eda6f593SDavid van Moolenbroek  * copyright notice and this permission notice appear in all copies.
9eda6f593SDavid van Moolenbroek  *
10eda6f593SDavid van Moolenbroek  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11eda6f593SDavid van Moolenbroek  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12eda6f593SDavid van Moolenbroek  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13eda6f593SDavid van Moolenbroek  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14eda6f593SDavid van Moolenbroek  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15eda6f593SDavid van Moolenbroek  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16eda6f593SDavid van Moolenbroek  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17eda6f593SDavid van Moolenbroek  */
18eda6f593SDavid van Moolenbroek 
19eda6f593SDavid van Moolenbroek #include <sys/types.h>
20eda6f593SDavid van Moolenbroek #include <sys/stat.h>
21eda6f593SDavid van Moolenbroek 
22eda6f593SDavid van Moolenbroek #include <errno.h>
23eda6f593SDavid van Moolenbroek #include <event.h>
24eda6f593SDavid van Moolenbroek #include <fcntl.h>
25*0a6a1f1dSLionel Sambuc #include <locale.h>
26eda6f593SDavid van Moolenbroek #include <pwd.h>
27eda6f593SDavid van Moolenbroek #include <stdlib.h>
28eda6f593SDavid van Moolenbroek #include <string.h>
29eda6f593SDavid van Moolenbroek #include <unistd.h>
30eda6f593SDavid van Moolenbroek 
31eda6f593SDavid van Moolenbroek #include "tmux.h"
32eda6f593SDavid van Moolenbroek 
33eda6f593SDavid van Moolenbroek #if defined(DEBUG) && defined(__OpenBSD__)
34eda6f593SDavid van Moolenbroek extern char	*malloc_options;
35eda6f593SDavid van Moolenbroek #endif
36eda6f593SDavid van Moolenbroek 
37eda6f593SDavid van Moolenbroek struct options	 global_options;	/* server options */
38eda6f593SDavid van Moolenbroek struct options	 global_s_options;	/* session options */
39eda6f593SDavid van Moolenbroek struct options	 global_w_options;	/* window options */
40eda6f593SDavid van Moolenbroek struct environ	 global_environ;
41eda6f593SDavid van Moolenbroek 
42eda6f593SDavid van Moolenbroek struct event_base *ev_base;
43eda6f593SDavid van Moolenbroek 
44eda6f593SDavid van Moolenbroek char		*cfg_file;
45eda6f593SDavid van Moolenbroek char		*shell_cmd;
46eda6f593SDavid van Moolenbroek int		 debug_level;
47eda6f593SDavid van Moolenbroek time_t		 start_time;
48eda6f593SDavid van Moolenbroek char		 socket_path[MAXPATHLEN];
49eda6f593SDavid van Moolenbroek int		 login_shell;
50eda6f593SDavid van Moolenbroek char		*environ_path;
51eda6f593SDavid van Moolenbroek 
52eda6f593SDavid van Moolenbroek __dead void	 usage(void);
53eda6f593SDavid van Moolenbroek char 		*makesocketpath(const char *);
54eda6f593SDavid van Moolenbroek 
55eda6f593SDavid van Moolenbroek #ifndef HAVE___PROGNAME
56eda6f593SDavid van Moolenbroek char      *__progname = (char *) "tmux";
57eda6f593SDavid van Moolenbroek #endif
58eda6f593SDavid van Moolenbroek 
59eda6f593SDavid van Moolenbroek __dead void
usage(void)60eda6f593SDavid van Moolenbroek usage(void)
61eda6f593SDavid van Moolenbroek {
62eda6f593SDavid van Moolenbroek 	fprintf(stderr,
63*0a6a1f1dSLionel Sambuc 	    "usage: %s [-2lquvV] [-c shell-command] [-f file] [-L socket-name]\n"
64eda6f593SDavid van Moolenbroek 	    "            [-S socket-path] [command [flags]]\n",
65eda6f593SDavid van Moolenbroek 	    __progname);
66eda6f593SDavid van Moolenbroek 	exit(1);
67eda6f593SDavid van Moolenbroek }
68eda6f593SDavid van Moolenbroek 
69eda6f593SDavid van Moolenbroek void
logfile(const char * name)70eda6f593SDavid van Moolenbroek logfile(const char *name)
71eda6f593SDavid van Moolenbroek {
72eda6f593SDavid van Moolenbroek 	char	*path;
73eda6f593SDavid van Moolenbroek 
74eda6f593SDavid van Moolenbroek 	if (debug_level > 0) {
75eda6f593SDavid van Moolenbroek 		xasprintf(&path, "tmux-%s-%ld.log", name, (long) getpid());
76*0a6a1f1dSLionel Sambuc 		log_open(debug_level, path);
77*0a6a1f1dSLionel Sambuc 		free(path);
78eda6f593SDavid van Moolenbroek 	}
79eda6f593SDavid van Moolenbroek }
80eda6f593SDavid van Moolenbroek 
81eda6f593SDavid van Moolenbroek const char *
getshell(void)82eda6f593SDavid van Moolenbroek getshell(void)
83eda6f593SDavid van Moolenbroek {
84eda6f593SDavid van Moolenbroek 	struct passwd	*pw;
85eda6f593SDavid van Moolenbroek 	const char	*shell;
86eda6f593SDavid van Moolenbroek 
87eda6f593SDavid van Moolenbroek 	shell = getenv("SHELL");
88eda6f593SDavid van Moolenbroek 	if (checkshell(shell))
89eda6f593SDavid van Moolenbroek 		return (shell);
90eda6f593SDavid van Moolenbroek 
91eda6f593SDavid van Moolenbroek 	pw = getpwuid(getuid());
92eda6f593SDavid van Moolenbroek 	if (pw != NULL && checkshell(pw->pw_shell))
93eda6f593SDavid van Moolenbroek 		return (pw->pw_shell);
94eda6f593SDavid van Moolenbroek 
95eda6f593SDavid van Moolenbroek 	return (_PATH_BSHELL);
96eda6f593SDavid van Moolenbroek }
97eda6f593SDavid van Moolenbroek 
98eda6f593SDavid van Moolenbroek int
checkshell(const char * shell)99eda6f593SDavid van Moolenbroek checkshell(const char *shell)
100eda6f593SDavid van Moolenbroek {
101*0a6a1f1dSLionel Sambuc 	if (shell == NULL || *shell == '\0' || *shell != '/')
102*0a6a1f1dSLionel Sambuc 		return (0);
103*0a6a1f1dSLionel Sambuc 	if (areshell(shell))
104eda6f593SDavid van Moolenbroek 		return (0);
105eda6f593SDavid van Moolenbroek 	if (access(shell, X_OK) != 0)
106eda6f593SDavid van Moolenbroek 		return (0);
107eda6f593SDavid van Moolenbroek 	return (1);
108eda6f593SDavid van Moolenbroek }
109eda6f593SDavid van Moolenbroek 
110eda6f593SDavid van Moolenbroek int
areshell(const char * shell)111eda6f593SDavid van Moolenbroek areshell(const char *shell)
112eda6f593SDavid van Moolenbroek {
113eda6f593SDavid van Moolenbroek 	const char	*progname, *ptr;
114eda6f593SDavid van Moolenbroek 
115eda6f593SDavid van Moolenbroek 	if ((ptr = strrchr(shell, '/')) != NULL)
116eda6f593SDavid van Moolenbroek 		ptr++;
117eda6f593SDavid van Moolenbroek 	else
118eda6f593SDavid van Moolenbroek 		ptr = shell;
119eda6f593SDavid van Moolenbroek 	progname = __progname;
120eda6f593SDavid van Moolenbroek 	if (*progname == '-')
121eda6f593SDavid van Moolenbroek 		progname++;
122eda6f593SDavid van Moolenbroek 	if (strcmp(ptr, progname) == 0)
123eda6f593SDavid van Moolenbroek 		return (1);
124eda6f593SDavid van Moolenbroek 	return (0);
125eda6f593SDavid van Moolenbroek }
126eda6f593SDavid van Moolenbroek 
127eda6f593SDavid van Moolenbroek char *
makesocketpath(const char * label)128eda6f593SDavid van Moolenbroek makesocketpath(const char *label)
129eda6f593SDavid van Moolenbroek {
130*0a6a1f1dSLionel Sambuc 	char		base[MAXPATHLEN], realbase[MAXPATHLEN], *path, *s;
131eda6f593SDavid van Moolenbroek 	struct stat	sb;
132eda6f593SDavid van Moolenbroek 	u_int		uid;
133eda6f593SDavid van Moolenbroek 
134eda6f593SDavid van Moolenbroek 	uid = getuid();
135*0a6a1f1dSLionel Sambuc 	if ((s = getenv("TMUX_TMPDIR")) != NULL && *s != '\0')
136*0a6a1f1dSLionel Sambuc 		xsnprintf(base, sizeof base, "%s/", s);
137*0a6a1f1dSLionel Sambuc 	else if ((s = getenv("TMPDIR")) != NULL && *s != '\0')
138eda6f593SDavid van Moolenbroek 		xsnprintf(base, sizeof base, "%s/tmux-%u", s, uid);
139*0a6a1f1dSLionel Sambuc 	else
140*0a6a1f1dSLionel Sambuc 		xsnprintf(base, sizeof base, "%s/tmux-%u", _PATH_TMP, uid);
141eda6f593SDavid van Moolenbroek 
142eda6f593SDavid van Moolenbroek 	if (mkdir(base, S_IRWXU) != 0 && errno != EEXIST)
143eda6f593SDavid van Moolenbroek 		return (NULL);
144eda6f593SDavid van Moolenbroek 
145eda6f593SDavid van Moolenbroek 	if (lstat(base, &sb) != 0)
146eda6f593SDavid van Moolenbroek 		return (NULL);
147eda6f593SDavid van Moolenbroek 	if (!S_ISDIR(sb.st_mode)) {
148eda6f593SDavid van Moolenbroek 		errno = ENOTDIR;
149eda6f593SDavid van Moolenbroek 		return (NULL);
150eda6f593SDavid van Moolenbroek 	}
151*0a6a1f1dSLionel Sambuc 	if (sb.st_uid != uid || (!S_ISDIR(sb.st_mode) &&
152*0a6a1f1dSLionel Sambuc 		sb.st_mode & (S_IRWXG|S_IRWXO)) != 0) {
153eda6f593SDavid van Moolenbroek 		errno = EACCES;
154eda6f593SDavid van Moolenbroek 		return (NULL);
155eda6f593SDavid van Moolenbroek 	}
156eda6f593SDavid van Moolenbroek 
157*0a6a1f1dSLionel Sambuc 	if (realpath(base, realbase) == NULL)
158*0a6a1f1dSLionel Sambuc 		strlcpy(realbase, base, sizeof realbase);
159*0a6a1f1dSLionel Sambuc 
160*0a6a1f1dSLionel Sambuc 	xasprintf(&path, "%s/%s", realbase, label);
161eda6f593SDavid van Moolenbroek 	return (path);
162eda6f593SDavid van Moolenbroek }
163eda6f593SDavid van Moolenbroek 
164eda6f593SDavid van Moolenbroek void
setblocking(int fd,int state)165eda6f593SDavid van Moolenbroek setblocking(int fd, int state)
166eda6f593SDavid van Moolenbroek {
167eda6f593SDavid van Moolenbroek 	int mode;
168eda6f593SDavid van Moolenbroek 
169eda6f593SDavid van Moolenbroek 	if ((mode = fcntl(fd, F_GETFL)) != -1) {
170eda6f593SDavid van Moolenbroek 		if (!state)
171eda6f593SDavid van Moolenbroek 			mode |= O_NONBLOCK;
172eda6f593SDavid van Moolenbroek 		else
173eda6f593SDavid van Moolenbroek 			mode &= ~O_NONBLOCK;
174eda6f593SDavid van Moolenbroek 		fcntl(fd, F_SETFL, mode);
175eda6f593SDavid van Moolenbroek 	}
176eda6f593SDavid van Moolenbroek }
177eda6f593SDavid van Moolenbroek 
178eda6f593SDavid van Moolenbroek __dead void
shell_exec(const char * shell,const char * shellcmd)179eda6f593SDavid van Moolenbroek shell_exec(const char *shell, const char *shellcmd)
180eda6f593SDavid van Moolenbroek {
181eda6f593SDavid van Moolenbroek 	const char	*shellname, *ptr;
182eda6f593SDavid van Moolenbroek 	char		*argv0;
183eda6f593SDavid van Moolenbroek 
184eda6f593SDavid van Moolenbroek 	ptr = strrchr(shell, '/');
185eda6f593SDavid van Moolenbroek 	if (ptr != NULL && *(ptr + 1) != '\0')
186eda6f593SDavid van Moolenbroek 		shellname = ptr + 1;
187eda6f593SDavid van Moolenbroek 	else
188eda6f593SDavid van Moolenbroek 		shellname = shell;
189eda6f593SDavid van Moolenbroek 	if (login_shell)
190eda6f593SDavid van Moolenbroek 		xasprintf(&argv0, "-%s", shellname);
191eda6f593SDavid van Moolenbroek 	else
192eda6f593SDavid van Moolenbroek 		xasprintf(&argv0, "%s", shellname);
193eda6f593SDavid van Moolenbroek 	setenv("SHELL", shell, 1);
194eda6f593SDavid van Moolenbroek 
195eda6f593SDavid van Moolenbroek 	setblocking(STDIN_FILENO, 1);
196eda6f593SDavid van Moolenbroek 	setblocking(STDOUT_FILENO, 1);
197eda6f593SDavid van Moolenbroek 	setblocking(STDERR_FILENO, 1);
198eda6f593SDavid van Moolenbroek 	closefrom(STDERR_FILENO + 1);
199eda6f593SDavid van Moolenbroek 
200eda6f593SDavid van Moolenbroek 	execl(shell, argv0, "-c", shellcmd, (char *) NULL);
201eda6f593SDavid van Moolenbroek 	fatal("execl failed");
202eda6f593SDavid van Moolenbroek }
203eda6f593SDavid van Moolenbroek 
204eda6f593SDavid van Moolenbroek static void
init_std_fds(void)205eda6f593SDavid van Moolenbroek init_std_fds(void)
206eda6f593SDavid van Moolenbroek {
207eda6f593SDavid van Moolenbroek 	int fd;
208eda6f593SDavid van Moolenbroek 
209eda6f593SDavid van Moolenbroek 	/*
210eda6f593SDavid van Moolenbroek 	 * Make sure the standard file descriptors are populated, so we
211eda6f593SDavid van Moolenbroek 	 * don't end up forwarding (for example) the event descriptor
212eda6f593SDavid van Moolenbroek 	 * instead of stdin to the server.
213eda6f593SDavid van Moolenbroek 	 */
214eda6f593SDavid van Moolenbroek 
215eda6f593SDavid van Moolenbroek 	while ((fd = open("/dev/null", O_RDWR)) <= 2)
216eda6f593SDavid van Moolenbroek 		;
217eda6f593SDavid van Moolenbroek 	close(fd);
218eda6f593SDavid van Moolenbroek }
219eda6f593SDavid van Moolenbroek 
220eda6f593SDavid van Moolenbroek int
main(int argc,char ** argv)221eda6f593SDavid van Moolenbroek main(int argc, char **argv)
222eda6f593SDavid van Moolenbroek {
223eda6f593SDavid van Moolenbroek 	struct passwd	*pw;
224*0a6a1f1dSLionel Sambuc 	char		*s, *path, *label, **var, tmp[MAXPATHLEN];
225*0a6a1f1dSLionel Sambuc 	char		 in[256];
226*0a6a1f1dSLionel Sambuc 	const char	*home;
227*0a6a1f1dSLionel Sambuc 	long long	 pid;
228*0a6a1f1dSLionel Sambuc 	int	 	 opt, flags, quiet, keys, session;
229eda6f593SDavid van Moolenbroek 
230eda6f593SDavid van Moolenbroek #if defined(DEBUG) && defined(__OpenBSD__)
231eda6f593SDavid van Moolenbroek 	malloc_options = (char *) "AFGJPX";
232eda6f593SDavid van Moolenbroek #endif
233eda6f593SDavid van Moolenbroek 
234*0a6a1f1dSLionel Sambuc 	setlocale(LC_TIME, "");
235*0a6a1f1dSLionel Sambuc 
236eda6f593SDavid van Moolenbroek 	quiet = flags = 0;
237eda6f593SDavid van Moolenbroek 	label = path = NULL;
238eda6f593SDavid van Moolenbroek 	login_shell = (**argv == '-');
239*0a6a1f1dSLionel Sambuc 	while ((opt = getopt(argc, argv, "2c:Cdf:lL:qS:uUVv")) != -1) {
240eda6f593SDavid van Moolenbroek 		switch (opt) {
241eda6f593SDavid van Moolenbroek 		case '2':
242*0a6a1f1dSLionel Sambuc 			flags |= CLIENT_256COLOURS;
243eda6f593SDavid van Moolenbroek 			break;
244eda6f593SDavid van Moolenbroek 		case 'c':
245*0a6a1f1dSLionel Sambuc 			free(shell_cmd);
246eda6f593SDavid van Moolenbroek 			shell_cmd = xstrdup(optarg);
247eda6f593SDavid van Moolenbroek 			break;
248*0a6a1f1dSLionel Sambuc 		case 'C':
249*0a6a1f1dSLionel Sambuc 			if (flags & CLIENT_CONTROL)
250*0a6a1f1dSLionel Sambuc 				flags |= CLIENT_CONTROLCONTROL;
251*0a6a1f1dSLionel Sambuc 			else
252*0a6a1f1dSLionel Sambuc 				flags |= CLIENT_CONTROL;
253*0a6a1f1dSLionel Sambuc 			break;
254eda6f593SDavid van Moolenbroek 		case 'V':
255eda6f593SDavid van Moolenbroek 			printf("%s %s\n", __progname, VERSION);
256eda6f593SDavid van Moolenbroek 			exit(0);
257eda6f593SDavid van Moolenbroek 		case 'f':
258*0a6a1f1dSLionel Sambuc 			free(cfg_file);
259eda6f593SDavid van Moolenbroek 			cfg_file = xstrdup(optarg);
260eda6f593SDavid van Moolenbroek 			break;
261eda6f593SDavid van Moolenbroek 		case 'l':
262eda6f593SDavid van Moolenbroek 			login_shell = 1;
263eda6f593SDavid van Moolenbroek 			break;
264eda6f593SDavid van Moolenbroek 		case 'L':
265*0a6a1f1dSLionel Sambuc 			free(label);
266eda6f593SDavid van Moolenbroek 			label = xstrdup(optarg);
267eda6f593SDavid van Moolenbroek 			break;
268eda6f593SDavid van Moolenbroek 		case 'q':
269eda6f593SDavid van Moolenbroek 			quiet = 1;
270eda6f593SDavid van Moolenbroek 			break;
271eda6f593SDavid van Moolenbroek 		case 'S':
272*0a6a1f1dSLionel Sambuc 			free(path);
273eda6f593SDavid van Moolenbroek 			path = xstrdup(optarg);
274eda6f593SDavid van Moolenbroek 			break;
275eda6f593SDavid van Moolenbroek 		case 'u':
276*0a6a1f1dSLionel Sambuc 			flags |= CLIENT_UTF8;
277eda6f593SDavid van Moolenbroek 			break;
278eda6f593SDavid van Moolenbroek 		case 'v':
279eda6f593SDavid van Moolenbroek 			debug_level++;
280eda6f593SDavid van Moolenbroek 			break;
281eda6f593SDavid van Moolenbroek 		default:
282eda6f593SDavid van Moolenbroek 			usage();
283eda6f593SDavid van Moolenbroek 		}
284eda6f593SDavid van Moolenbroek 	}
285eda6f593SDavid van Moolenbroek 	argc -= optind;
286eda6f593SDavid van Moolenbroek 	argv += optind;
287eda6f593SDavid van Moolenbroek 
288eda6f593SDavid van Moolenbroek 	if (shell_cmd != NULL && argc != 0)
289eda6f593SDavid van Moolenbroek 		usage();
290eda6f593SDavid van Moolenbroek 
291eda6f593SDavid van Moolenbroek 	init_std_fds();
292eda6f593SDavid van Moolenbroek 
293*0a6a1f1dSLionel Sambuc 	if (!(flags & CLIENT_UTF8)) {
294eda6f593SDavid van Moolenbroek 		/*
295eda6f593SDavid van Moolenbroek 		 * If the user has set whichever of LC_ALL, LC_CTYPE or LANG
296eda6f593SDavid van Moolenbroek 		 * exist (in that order) to contain UTF-8, it is a safe
297eda6f593SDavid van Moolenbroek 		 * assumption that either they are using a UTF-8 terminal, or
298eda6f593SDavid van Moolenbroek 		 * if not they know that output from UTF-8-capable programs may
299eda6f593SDavid van Moolenbroek 		 * be wrong.
300eda6f593SDavid van Moolenbroek 		 */
301*0a6a1f1dSLionel Sambuc 		if ((s = getenv("LC_ALL")) == NULL || *s == '\0') {
302*0a6a1f1dSLionel Sambuc 			if ((s = getenv("LC_CTYPE")) == NULL || *s == '\0')
303eda6f593SDavid van Moolenbroek 				s = getenv("LANG");
304eda6f593SDavid van Moolenbroek 		}
305eda6f593SDavid van Moolenbroek 		if (s != NULL && (strcasestr(s, "UTF-8") != NULL ||
306eda6f593SDavid van Moolenbroek 		    strcasestr(s, "UTF8") != NULL))
307*0a6a1f1dSLionel Sambuc 			flags |= CLIENT_UTF8;
308eda6f593SDavid van Moolenbroek 	}
309eda6f593SDavid van Moolenbroek 
310eda6f593SDavid van Moolenbroek 	environ_init(&global_environ);
311eda6f593SDavid van Moolenbroek 	for (var = environ; *var != NULL; var++)
312eda6f593SDavid van Moolenbroek 		environ_put(&global_environ, *var);
313*0a6a1f1dSLionel Sambuc 	if (getcwd(tmp, sizeof tmp) != NULL)
314*0a6a1f1dSLionel Sambuc 		environ_set(&global_environ, "PWD", tmp);
315eda6f593SDavid van Moolenbroek 
316eda6f593SDavid van Moolenbroek 	options_init(&global_options, NULL);
317eda6f593SDavid van Moolenbroek 	options_table_populate_tree(server_options_table, &global_options);
318eda6f593SDavid van Moolenbroek 	options_set_number(&global_options, "quiet", quiet);
319eda6f593SDavid van Moolenbroek 
320eda6f593SDavid van Moolenbroek 	options_init(&global_s_options, NULL);
321eda6f593SDavid van Moolenbroek 	options_table_populate_tree(session_options_table, &global_s_options);
322eda6f593SDavid van Moolenbroek 	options_set_string(&global_s_options, "default-shell", "%s", getshell());
323eda6f593SDavid van Moolenbroek 
324eda6f593SDavid van Moolenbroek 	options_init(&global_w_options, NULL);
325eda6f593SDavid van Moolenbroek 	options_table_populate_tree(window_options_table, &global_w_options);
326eda6f593SDavid van Moolenbroek 
327eda6f593SDavid van Moolenbroek 	/* Enable UTF-8 if the first client is on UTF-8 terminal. */
328*0a6a1f1dSLionel Sambuc 	if (flags & CLIENT_UTF8) {
329eda6f593SDavid van Moolenbroek 		options_set_number(&global_s_options, "status-utf8", 1);
330eda6f593SDavid van Moolenbroek 		options_set_number(&global_s_options, "mouse-utf8", 1);
331eda6f593SDavid van Moolenbroek 		options_set_number(&global_w_options, "utf8", 1);
332eda6f593SDavid van Moolenbroek 	}
333eda6f593SDavid van Moolenbroek 
334eda6f593SDavid van Moolenbroek 	/* Override keys to vi if VISUAL or EDITOR are set. */
335eda6f593SDavid van Moolenbroek 	if ((s = getenv("VISUAL")) != NULL || (s = getenv("EDITOR")) != NULL) {
336eda6f593SDavid van Moolenbroek 		if (strrchr(s, '/') != NULL)
337eda6f593SDavid van Moolenbroek 			s = strrchr(s, '/') + 1;
338eda6f593SDavid van Moolenbroek 		if (strstr(s, "vi") != NULL)
339eda6f593SDavid van Moolenbroek 			keys = MODEKEY_VI;
340eda6f593SDavid van Moolenbroek 		else
341eda6f593SDavid van Moolenbroek 			keys = MODEKEY_EMACS;
342eda6f593SDavid van Moolenbroek 		options_set_number(&global_s_options, "status-keys", keys);
343eda6f593SDavid van Moolenbroek 		options_set_number(&global_w_options, "mode-keys", keys);
344eda6f593SDavid van Moolenbroek 	}
345eda6f593SDavid van Moolenbroek 
346eda6f593SDavid van Moolenbroek 	/* Locate the configuration file. */
347eda6f593SDavid van Moolenbroek 	if (cfg_file == NULL) {
348eda6f593SDavid van Moolenbroek 		home = getenv("HOME");
349eda6f593SDavid van Moolenbroek 		if (home == NULL || *home == '\0') {
350eda6f593SDavid van Moolenbroek 			pw = getpwuid(getuid());
351eda6f593SDavid van Moolenbroek 			if (pw != NULL)
352eda6f593SDavid van Moolenbroek 				home = pw->pw_dir;
353*0a6a1f1dSLionel Sambuc 			else
354*0a6a1f1dSLionel Sambuc 				home = NULL;
355eda6f593SDavid van Moolenbroek 		}
356*0a6a1f1dSLionel Sambuc 		if (home != NULL) {
357*0a6a1f1dSLionel Sambuc 			xasprintf(&cfg_file, "%s/.tmux.conf", home);
358eda6f593SDavid van Moolenbroek 			if (access(cfg_file, R_OK) != 0 && errno == ENOENT) {
359*0a6a1f1dSLionel Sambuc 				free(cfg_file);
360eda6f593SDavid van Moolenbroek 				cfg_file = NULL;
361eda6f593SDavid van Moolenbroek 			}
362eda6f593SDavid van Moolenbroek 		}
363*0a6a1f1dSLionel Sambuc 	}
364*0a6a1f1dSLionel Sambuc 
365*0a6a1f1dSLionel Sambuc 	/* Get path from environment. */
366*0a6a1f1dSLionel Sambuc 	s = getenv("TMUX");
367*0a6a1f1dSLionel Sambuc 	if (s != NULL && sscanf(s, "%255[^,],%lld,%d", in, &pid, &session) == 3)
368*0a6a1f1dSLionel Sambuc 		environ_path = xstrdup(in);
369eda6f593SDavid van Moolenbroek 
370eda6f593SDavid van Moolenbroek 	/*
371eda6f593SDavid van Moolenbroek 	 * Figure out the socket path. If specified on the command-line with -S
372eda6f593SDavid van Moolenbroek 	 * or -L, use it, otherwise try $TMUX or assume -L default.
373eda6f593SDavid van Moolenbroek 	 */
374eda6f593SDavid van Moolenbroek 	if (path == NULL) {
375eda6f593SDavid van Moolenbroek 		/* If no -L, use the environment. */
376eda6f593SDavid van Moolenbroek 		if (label == NULL) {
377eda6f593SDavid van Moolenbroek 			if (environ_path != NULL)
378eda6f593SDavid van Moolenbroek 				path = xstrdup(environ_path);
379eda6f593SDavid van Moolenbroek 			else
380eda6f593SDavid van Moolenbroek 				label = xstrdup("default");
381eda6f593SDavid van Moolenbroek 		}
382eda6f593SDavid van Moolenbroek 
383eda6f593SDavid van Moolenbroek 		/* -L or default set. */
384eda6f593SDavid van Moolenbroek 		if (label != NULL) {
385eda6f593SDavid van Moolenbroek 			if ((path = makesocketpath(label)) == NULL) {
386*0a6a1f1dSLionel Sambuc 				fprintf(stderr, "can't create socket: %s\n",
387*0a6a1f1dSLionel Sambuc 					strerror(errno));
388eda6f593SDavid van Moolenbroek 				exit(1);
389eda6f593SDavid van Moolenbroek 			}
390eda6f593SDavid van Moolenbroek 		}
391eda6f593SDavid van Moolenbroek 	}
392*0a6a1f1dSLionel Sambuc 	free(label);
393*0a6a1f1dSLionel Sambuc 
394*0a6a1f1dSLionel Sambuc 	if (strlcpy(socket_path, path, sizeof socket_path) >= sizeof socket_path) {
395*0a6a1f1dSLionel Sambuc 		fprintf(stderr, "socket path too long: %s\n", path);
396*0a6a1f1dSLionel Sambuc 		exit(1);
397*0a6a1f1dSLionel Sambuc 	}
398*0a6a1f1dSLionel Sambuc 	free(path);
399eda6f593SDavid van Moolenbroek 
400eda6f593SDavid van Moolenbroek #ifdef HAVE_SETPROCTITLE
401eda6f593SDavid van Moolenbroek 	/* Set process title. */
402eda6f593SDavid van Moolenbroek 	setproctitle("%s (%s)", __progname, socket_path);
403eda6f593SDavid van Moolenbroek #endif
404eda6f593SDavid van Moolenbroek 
405eda6f593SDavid van Moolenbroek 	/* Pass control to the client. */
406eda6f593SDavid van Moolenbroek 	ev_base = osdep_event_init();
407eda6f593SDavid van Moolenbroek 	exit(client_main(argc, argv, flags));
408eda6f593SDavid van Moolenbroek }
409