Home | History | Annotate | Line # | Download | only in dist
tmux.c revision 1.13
      1   1.4  christos /* $OpenBSD$ */
      2   1.1      jmmv 
      3   1.1      jmmv /*
      4   1.5  christos  * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott (at) gmail.com>
      5   1.1      jmmv  *
      6   1.1      jmmv  * Permission to use, copy, modify, and distribute this software for any
      7   1.1      jmmv  * purpose with or without fee is hereby granted, provided that the above
      8   1.1      jmmv  * copyright notice and this permission notice appear in all copies.
      9   1.1      jmmv  *
     10   1.1      jmmv  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     11   1.1      jmmv  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     12   1.1      jmmv  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     13   1.1      jmmv  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     14   1.1      jmmv  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
     15   1.1      jmmv  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
     16   1.1      jmmv  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     17   1.1      jmmv  */
     18   1.1      jmmv 
     19   1.1      jmmv #include <sys/types.h>
     20   1.1      jmmv #include <sys/stat.h>
     21  1.11  christos #include <sys/utsname.h>
     22   1.1      jmmv 
     23   1.1      jmmv #include <errno.h>
     24   1.1      jmmv #include <fcntl.h>
     25   1.5  christos #include <langinfo.h>
     26   1.3  christos #include <locale.h>
     27   1.1      jmmv #include <pwd.h>
     28  1.12  christos #include <signal.h>
     29   1.1      jmmv #include <stdlib.h>
     30   1.1      jmmv #include <string.h>
     31   1.4  christos #include <time.h>
     32   1.1      jmmv #include <unistd.h>
     33   1.1      jmmv 
     34   1.1      jmmv #include "tmux.h"
     35   1.1      jmmv 
     36   1.5  christos struct options	*global_options;	/* server options */
     37   1.5  christos struct options	*global_s_options;	/* session options */
     38   1.5  christos struct options	*global_w_options;	/* window options */
     39   1.5  christos struct environ	*global_environ;
     40   1.1      jmmv 
     41   1.5  christos struct timeval	 start_time;
     42   1.5  christos const char	*socket_path;
     43   1.6  christos int		 ptm_fd = -1;
     44   1.7  christos const char	*shell_command;
     45   1.1      jmmv 
     46   1.6  christos static __dead void	 usage(void);
     47   1.8  christos static char		*make_label(const char *, char **);
     48   1.1      jmmv 
     49  1.12  christos static int		 areshell(const char *);
     50   1.6  christos static const char	*getshell(void);
     51   1.1      jmmv 
     52   1.6  christos static __dead void
     53   1.1      jmmv usage(void)
     54   1.1      jmmv {
     55   1.1      jmmv 	fprintf(stderr,
     56  1.12  christos 	    "usage: %s [-2CDlNuvV] [-c shell-command] [-f file] [-L socket-name]\n"
     57  1.12  christos 	    "            [-S socket-path] [-T features] [command [flags]]\n",
     58   1.6  christos 	    getprogname());
     59   1.1      jmmv 	exit(1);
     60   1.1      jmmv }
     61   1.1      jmmv 
     62   1.6  christos static const char *
     63   1.1      jmmv getshell(void)
     64   1.1      jmmv {
     65   1.1      jmmv 	struct passwd	*pw;
     66   1.1      jmmv 	const char	*shell;
     67   1.1      jmmv 
     68   1.1      jmmv 	shell = getenv("SHELL");
     69   1.1      jmmv 	if (checkshell(shell))
     70   1.1      jmmv 		return (shell);
     71   1.1      jmmv 
     72   1.1      jmmv 	pw = getpwuid(getuid());
     73   1.1      jmmv 	if (pw != NULL && checkshell(pw->pw_shell))
     74   1.1      jmmv 		return (pw->pw_shell);
     75   1.1      jmmv 
     76   1.1      jmmv 	return (_PATH_BSHELL);
     77   1.1      jmmv }
     78   1.1      jmmv 
     79  1.12  christos int
     80   1.1      jmmv checkshell(const char *shell)
     81   1.1      jmmv {
     82   1.6  christos 	if (shell == NULL || *shell != '/')
     83   1.3  christos 		return (0);
     84   1.3  christos 	if (areshell(shell))
     85   1.1      jmmv 		return (0);
     86   1.1      jmmv 	if (access(shell, X_OK) != 0)
     87   1.1      jmmv 		return (0);
     88   1.1      jmmv 	return (1);
     89   1.1      jmmv }
     90   1.1      jmmv 
     91  1.12  christos static int
     92   1.1      jmmv areshell(const char *shell)
     93   1.1      jmmv {
     94   1.1      jmmv 	const char	*progname, *ptr;
     95   1.1      jmmv 
     96   1.1      jmmv 	if ((ptr = strrchr(shell, '/')) != NULL)
     97   1.1      jmmv 		ptr++;
     98   1.1      jmmv 	else
     99   1.1      jmmv 		ptr = shell;
    100   1.6  christos 	progname = getprogname();
    101   1.1      jmmv 	if (*progname == '-')
    102   1.1      jmmv 		progname++;
    103   1.1      jmmv 	if (strcmp(ptr, progname) == 0)
    104   1.1      jmmv 		return (1);
    105   1.1      jmmv 	return (0);
    106   1.1      jmmv }
    107   1.1      jmmv 
    108   1.5  christos static char *
    109  1.12  christos expand_path(const char *path, const char *home)
    110  1.12  christos {
    111  1.12  christos 	char			*expanded, *name;
    112  1.12  christos 	const char		*end;
    113  1.12  christos 	struct environ_entry	*value;
    114  1.12  christos 
    115  1.12  christos 	if (strncmp(path, "~/", 2) == 0) {
    116  1.12  christos 		if (home == NULL)
    117  1.12  christos 			return (NULL);
    118  1.12  christos 		xasprintf(&expanded, "%s%s", home, path + 1);
    119  1.12  christos 		return (expanded);
    120  1.12  christos 	}
    121  1.12  christos 
    122  1.12  christos 	if (*path == '$') {
    123  1.12  christos 		end = strchr(path, '/');
    124  1.12  christos 		if (end == NULL)
    125  1.12  christos 			name = xstrdup(path + 1);
    126  1.12  christos 		else
    127  1.12  christos 			name = xstrndup(path + 1, end - path - 1);
    128  1.12  christos 		value = environ_find(global_environ, name);
    129  1.12  christos 		free(name);
    130  1.12  christos 		if (value == NULL)
    131  1.12  christos 			return (NULL);
    132  1.12  christos 		if (end == NULL)
    133  1.12  christos 			end = "";
    134  1.12  christos 		xasprintf(&expanded, "%s%s", value->value, end);
    135  1.12  christos 		return (expanded);
    136  1.12  christos 	}
    137  1.12  christos 
    138  1.12  christos 	return (xstrdup(path));
    139  1.12  christos }
    140  1.12  christos 
    141  1.12  christos static void
    142  1.12  christos expand_paths(const char *s, char ***paths, u_int *n, int ignore_errors)
    143  1.12  christos {
    144  1.12  christos 	const char	*home = find_home();
    145  1.12  christos 	char		*copy, *next, *tmp, resolved[PATH_MAX], *expanded;
    146  1.12  christos 	char		*path;
    147  1.12  christos 	u_int		 i;
    148  1.12  christos 
    149  1.12  christos 	*paths = NULL;
    150  1.12  christos 	*n = 0;
    151  1.12  christos 
    152  1.12  christos 	copy = tmp = xstrdup(s);
    153  1.12  christos 	while ((next = strsep(&tmp, ":")) != NULL) {
    154  1.12  christos 		expanded = expand_path(next, home);
    155  1.12  christos 		if (expanded == NULL) {
    156  1.12  christos 			log_debug("%s: invalid path: %s", __func__, next);
    157  1.12  christos 			continue;
    158  1.12  christos 		}
    159  1.12  christos 		if (realpath(expanded, resolved) == NULL) {
    160  1.12  christos 			log_debug("%s: realpath(\"%s\") failed: %s", __func__,
    161  1.12  christos 			    expanded, strerror(errno));
    162  1.12  christos 			if (ignore_errors) {
    163  1.12  christos 				free(expanded);
    164  1.12  christos 				continue;
    165  1.12  christos 			}
    166  1.12  christos 			path = expanded;
    167  1.12  christos 		} else {
    168  1.12  christos 			path = xstrdup(resolved);
    169  1.12  christos 			free(expanded);
    170  1.12  christos 		}
    171  1.12  christos 		for (i = 0; i < *n; i++) {
    172  1.12  christos 			if (strcmp(path, (*paths)[i]) == 0)
    173  1.12  christos 				break;
    174  1.12  christos 		}
    175  1.12  christos 		if (i != *n) {
    176  1.12  christos 			log_debug("%s: duplicate path: %s", __func__, path);
    177  1.12  christos 			free(path);
    178  1.12  christos 			continue;
    179  1.12  christos 		}
    180  1.12  christos 		*paths = xreallocarray(*paths, (*n) + 1, sizeof *paths);
    181  1.12  christos 		(*paths)[(*n)++] = path;
    182  1.12  christos 	}
    183  1.12  christos 	free(copy);
    184  1.12  christos }
    185  1.12  christos 
    186  1.12  christos static char *
    187   1.8  christos make_label(const char *label, char **cause)
    188   1.1      jmmv {
    189  1.12  christos 	char		**paths, *path, *base;
    190  1.12  christos 	u_int		  i, n;
    191  1.12  christos 	struct stat	  sb;
    192  1.12  christos 	uid_t		  uid;
    193   1.8  christos 
    194   1.8  christos 	*cause = NULL;
    195   1.5  christos 	if (label == NULL)
    196   1.5  christos 		label = "default";
    197   1.1      jmmv 	uid = getuid();
    198   1.5  christos 
    199  1.12  christos 	expand_paths(TMUX_SOCK, &paths, &n, 1);
    200  1.12  christos 	if (n == 0) {
    201  1.12  christos 		xasprintf(cause, "no suitable socket path");
    202  1.12  christos 		return (NULL);
    203   1.8  christos 	}
    204  1.12  christos 	path = paths[0]; /* can only have one socket! */
    205  1.12  christos 	for (i = 1; i < n; i++)
    206  1.12  christos 		free(paths[i]);
    207  1.12  christos 	free(paths);
    208   1.1      jmmv 
    209  1.12  christos 	xasprintf(&base, "%s/tmux-%ld", path, (long)uid);
    210  1.12  christos 	if (mkdir(base, S_IRWXU) != 0 && errno != EEXIST)
    211   1.5  christos 		goto fail;
    212  1.12  christos 	if (lstat(base, &sb) != 0)
    213   1.5  christos 		goto fail;
    214   1.1      jmmv 	if (!S_ISDIR(sb.st_mode)) {
    215   1.1      jmmv 		errno = ENOTDIR;
    216   1.5  christos 		goto fail;
    217   1.1      jmmv 	}
    218   1.4  christos 	if (sb.st_uid != uid || (sb.st_mode & S_IRWXO) != 0) {
    219   1.1      jmmv 		errno = EACCES;
    220   1.5  christos 		goto fail;
    221   1.1      jmmv 	}
    222  1.12  christos 	xasprintf(&path, "%s/%s", base, label);
    223  1.12  christos 	free(base);
    224   1.5  christos 	return (path);
    225   1.3  christos 
    226   1.5  christos fail:
    227  1.12  christos 	xasprintf(cause, "error creating %s (%s)", base, strerror(errno));
    228  1.12  christos 	free(base);
    229   1.5  christos 	return (NULL);
    230   1.1      jmmv }
    231   1.1      jmmv 
    232   1.2    martin void
    233   1.2    martin setblocking(int fd, int state)
    234   1.2    martin {
    235   1.2    martin 	int mode;
    236   1.2    martin 
    237   1.2    martin 	if ((mode = fcntl(fd, F_GETFL)) != -1) {
    238   1.2    martin 		if (!state)
    239   1.2    martin 			mode |= O_NONBLOCK;
    240   1.2    martin 		else
    241   1.2    martin 			mode &= ~O_NONBLOCK;
    242   1.2    martin 		fcntl(fd, F_SETFL, mode);
    243   1.2    martin 	}
    244   1.2    martin }
    245   1.2    martin 
    246  1.12  christos uint64_t
    247  1.12  christos get_timer(void)
    248  1.12  christos {
    249  1.12  christos 	struct timespec	ts;
    250  1.12  christos 
    251  1.12  christos 	/*
    252  1.12  christos 	 * We want a timestamp in milliseconds suitable for time measurement,
    253  1.12  christos 	 * so prefer the monotonic clock.
    254  1.12  christos 	 */
    255  1.12  christos 	if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0)
    256  1.12  christos 		clock_gettime(CLOCK_REALTIME, &ts);
    257  1.12  christos 	return ((ts.tv_sec * 1000ULL) + (ts.tv_nsec / 1000000ULL));
    258  1.12  christos }
    259  1.12  christos 
    260  1.12  christos const char *
    261  1.12  christos sig2name(int signo)
    262  1.12  christos {
    263  1.12  christos      static char	s[11];
    264  1.12  christos 
    265  1.12  christos #ifdef HAVE_SYS_SIGNAME
    266  1.12  christos      if (signo > 0 && signo < NSIG)
    267  1.12  christos 	     return (sys_signame[signo]);
    268  1.12  christos #endif
    269  1.12  christos      xsnprintf(s, sizeof s, "%d", signo);
    270  1.12  christos      return (s);
    271  1.12  christos }
    272  1.12  christos 
    273   1.4  christos const char *
    274   1.9  christos find_cwd(void)
    275   1.9  christos {
    276   1.9  christos 	char		 resolved1[PATH_MAX], resolved2[PATH_MAX];
    277   1.9  christos 	static char	 cwd[PATH_MAX];
    278   1.9  christos 	const char	*pwd;
    279   1.9  christos 
    280   1.9  christos 	if (getcwd(cwd, sizeof cwd) == NULL)
    281   1.9  christos 		return (NULL);
    282   1.9  christos 	if ((pwd = getenv("PWD")) == NULL || *pwd == '\0')
    283   1.9  christos 		return (cwd);
    284   1.9  christos 
    285   1.9  christos 	/*
    286   1.9  christos 	 * We want to use PWD so that symbolic links are maintained,
    287   1.9  christos 	 * but only if it matches the actual working directory.
    288   1.9  christos 	 */
    289   1.9  christos 	if (realpath(pwd, resolved1) == NULL)
    290   1.9  christos 		return (cwd);
    291   1.9  christos 	if (realpath(cwd, resolved2) == NULL)
    292   1.9  christos 		return (cwd);
    293   1.9  christos 	if (strcmp(resolved1, resolved2) != 0)
    294   1.9  christos 		return (cwd);
    295   1.9  christos 	return (pwd);
    296   1.9  christos }
    297   1.9  christos 
    298   1.9  christos const char *
    299   1.4  christos find_home(void)
    300   1.1      jmmv {
    301   1.4  christos 	struct passwd		*pw;
    302   1.4  christos 	static const char	*home;
    303   1.1      jmmv 
    304   1.4  christos 	if (home != NULL)
    305   1.4  christos 		return (home);
    306   1.1      jmmv 
    307   1.4  christos 	home = getenv("HOME");
    308   1.4  christos 	if (home == NULL || *home == '\0') {
    309   1.4  christos 		pw = getpwuid(getuid());
    310   1.4  christos 		if (pw != NULL)
    311   1.4  christos 			home = pw->pw_dir;
    312   1.4  christos 		else
    313   1.4  christos 			home = NULL;
    314   1.4  christos 	}
    315   1.1      jmmv 
    316   1.4  christos 	return (home);
    317   1.1      jmmv }
    318   1.1      jmmv 
    319  1.11  christos const char *
    320  1.11  christos getversion(void)
    321  1.11  christos {
    322  1.11  christos 	return TMUX_VERSION;
    323  1.11  christos }
    324  1.11  christos 
    325   1.1      jmmv int
    326   1.1      jmmv main(int argc, char **argv)
    327   1.1      jmmv {
    328  1.12  christos 	char					*path = NULL, *label = NULL;
    329  1.12  christos 	char					*cause, **var;
    330  1.12  christos 	const char				*s, *cwd;
    331  1.13  christos 	int					 opt, keys, feat = 0, fflag = 0;
    332  1.12  christos 	uint64_t				 flags = 0;
    333   1.6  christos 	const struct options_table_entry	*oe;
    334  1.12  christos 	u_int					 i;
    335   1.5  christos 
    336   1.7  christos 	if (setlocale(LC_CTYPE, "en_US.UTF-8") == NULL &&
    337   1.7  christos 	    setlocale(LC_CTYPE, "C.UTF-8") == NULL) {
    338   1.5  christos 		if (setlocale(LC_CTYPE, "") == NULL)
    339   1.5  christos 			errx(1, "invalid LC_ALL, LC_CTYPE or LANG");
    340   1.5  christos 		s = nl_langinfo(CODESET);
    341   1.6  christos 		if (strcasecmp(s, "UTF-8") != 0 && strcasecmp(s, "UTF8") != 0)
    342   1.5  christos 			errx(1, "need UTF-8 locale (LC_CTYPE) but have %s", s);
    343   1.5  christos 	}
    344   1.1      jmmv 
    345   1.3  christos 	setlocale(LC_TIME, "");
    346   1.4  christos 	tzset();
    347   1.4  christos 
    348   1.4  christos 	if (**argv == '-')
    349   1.4  christos 		flags = CLIENT_LOGIN;
    350   1.3  christos 
    351  1.12  christos 	global_environ = environ_create();
    352  1.12  christos 	for (var = environ; *var != NULL; var++)
    353  1.12  christos 		environ_put(global_environ, *var, 0);
    354  1.12  christos 	if ((cwd = find_cwd()) != NULL)
    355  1.12  christos 		environ_set(global_environ, "PWD", 0, "%s", cwd);
    356  1.12  christos 	expand_paths(TMUX_CONF, &cfg_files, &cfg_nfiles, 1);
    357  1.12  christos 
    358  1.12  christos 	while ((opt = getopt(argc, argv, "2c:CDdf:lL:NqS:T:uUvV")) != -1) {
    359   1.1      jmmv 		switch (opt) {
    360   1.1      jmmv 		case '2':
    361  1.12  christos 			tty_add_features(&feat, "256", ":,");
    362   1.1      jmmv 			break;
    363   1.1      jmmv 		case 'c':
    364   1.7  christos 			shell_command = optarg;
    365   1.1      jmmv 			break;
    366  1.12  christos 		case 'D':
    367  1.12  christos 			flags |= CLIENT_NOFORK;
    368  1.12  christos 			break;
    369   1.3  christos 		case 'C':
    370   1.3  christos 			if (flags & CLIENT_CONTROL)
    371   1.3  christos 				flags |= CLIENT_CONTROLCONTROL;
    372   1.3  christos 			else
    373   1.3  christos 				flags |= CLIENT_CONTROL;
    374   1.3  christos 			break;
    375   1.1      jmmv 		case 'f':
    376  1.13  christos 			if (!fflag) {
    377  1.13  christos 				fflag = 1;
    378  1.13  christos 				for (i = 0; i < cfg_nfiles; i++)
    379  1.13  christos 					free(cfg_files[i]);
    380  1.13  christos 				cfg_nfiles = 0;
    381  1.13  christos 			}
    382  1.13  christos 			cfg_files = xreallocarray(cfg_files, cfg_nfiles + 1,
    383  1.13  christos 			    sizeof *cfg_files);
    384  1.13  christos 			cfg_files[cfg_nfiles++] = xstrdup(optarg);
    385  1.12  christos 			cfg_quiet = 0;
    386   1.1      jmmv 			break;
    387  1.11  christos  		case 'V':
    388  1.11  christos 			printf("%s %s\n", getprogname(), getversion());
    389  1.11  christos  			exit(0);
    390   1.1      jmmv 		case 'l':
    391   1.4  christos 			flags |= CLIENT_LOGIN;
    392   1.1      jmmv 			break;
    393   1.1      jmmv 		case 'L':
    394   1.3  christos 			free(label);
    395   1.1      jmmv 			label = xstrdup(optarg);
    396   1.1      jmmv 			break;
    397  1.12  christos 		case 'N':
    398  1.12  christos 			flags |= CLIENT_NOSTARTSERVER;
    399  1.12  christos 			break;
    400   1.1      jmmv 		case 'q':
    401   1.1      jmmv 			break;
    402   1.1      jmmv 		case 'S':
    403   1.3  christos 			free(path);
    404   1.1      jmmv 			path = xstrdup(optarg);
    405   1.1      jmmv 			break;
    406  1.12  christos 		case 'T':
    407  1.12  christos 			tty_add_features(&feat, optarg, ":,");
    408  1.12  christos 			break;
    409   1.1      jmmv 		case 'u':
    410   1.3  christos 			flags |= CLIENT_UTF8;
    411   1.1      jmmv 			break;
    412   1.1      jmmv 		case 'v':
    413   1.5  christos 			log_add_level();
    414   1.1      jmmv 			break;
    415   1.1      jmmv 		default:
    416   1.1      jmmv 			usage();
    417   1.1      jmmv 		}
    418   1.1      jmmv 	}
    419   1.1      jmmv 	argc -= optind;
    420   1.1      jmmv 	argv += optind;
    421   1.1      jmmv 
    422   1.7  christos 	if (shell_command != NULL && argc != 0)
    423   1.1      jmmv 		usage();
    424  1.12  christos 	if ((flags & CLIENT_NOFORK) && argc != 0)
    425  1.12  christos 		usage();
    426   1.1      jmmv 
    427   1.7  christos 	if ((ptm_fd = getptmfd()) == -1)
    428   1.7  christos 		err(1, "getptmfd");
    429   1.5  christos 	if (pledge("stdio rpath wpath cpath flock fattr unix getpw sendfd "
    430   1.5  christos 	    "recvfd proc exec tty ps", NULL) != 0)
    431   1.5  christos 		err(1, "pledge");
    432   1.1      jmmv 
    433   1.5  christos 	/*
    434   1.5  christos 	 * tmux is a UTF-8 terminal, so if TMUX is set, assume UTF-8.
    435   1.5  christos 	 * Otherwise, if the user has set LC_ALL, LC_CTYPE or LANG to contain
    436   1.5  christos 	 * UTF-8, it is a safe assumption that either they are using a UTF-8
    437   1.5  christos 	 * terminal, or if not they know that output from UTF-8-capable
    438   1.5  christos 	 * programs may be wrong.
    439   1.5  christos 	 */
    440   1.5  christos 	if (getenv("TMUX") != NULL)
    441   1.5  christos 		flags |= CLIENT_UTF8;
    442   1.5  christos 	else {
    443   1.5  christos 		s = getenv("LC_ALL");
    444   1.5  christos 		if (s == NULL || *s == '\0')
    445   1.5  christos 			s = getenv("LC_CTYPE");
    446   1.5  christos 		if (s == NULL || *s == '\0')
    447   1.5  christos 			s = getenv("LANG");
    448   1.5  christos 		if (s == NULL || *s == '\0')
    449   1.5  christos 			s = "";
    450   1.5  christos 		if (strcasestr(s, "UTF-8") != NULL ||
    451   1.5  christos 		    strcasestr(s, "UTF8") != NULL)
    452   1.3  christos 			flags |= CLIENT_UTF8;
    453   1.1      jmmv 	}
    454   1.1      jmmv 
    455   1.5  christos 	global_options = options_create(NULL);
    456   1.5  christos 	global_s_options = options_create(NULL);
    457   1.6  christos 	global_w_options = options_create(NULL);
    458   1.6  christos 	for (oe = options_table; oe->name != NULL; oe++) {
    459  1.10  christos 		if (oe->scope & OPTIONS_TABLE_SERVER)
    460   1.6  christos 			options_default(global_options, oe);
    461  1.10  christos 		if (oe->scope & OPTIONS_TABLE_SESSION)
    462   1.6  christos 			options_default(global_s_options, oe);
    463  1.10  christos 		if (oe->scope & OPTIONS_TABLE_WINDOW)
    464   1.6  christos 			options_default(global_w_options, oe);
    465   1.6  christos 	}
    466   1.1      jmmv 
    467   1.6  christos 	/*
    468   1.6  christos 	 * The default shell comes from SHELL or from the user's passwd entry
    469   1.6  christos 	 * if available.
    470   1.6  christos 	 */
    471  1.12  christos 	options_set_string(global_s_options, "default-shell", 0, "%s",
    472  1.12  christos 	    getshell());
    473   1.1      jmmv 
    474   1.2    martin 	/* Override keys to vi if VISUAL or EDITOR are set. */
    475   1.1      jmmv 	if ((s = getenv("VISUAL")) != NULL || (s = getenv("EDITOR")) != NULL) {
    476  1.12  christos 		options_set_string(global_options, "editor", 0, "%s", s);
    477   1.1      jmmv 		if (strrchr(s, '/') != NULL)
    478   1.1      jmmv 			s = strrchr(s, '/') + 1;
    479   1.1      jmmv 		if (strstr(s, "vi") != NULL)
    480   1.1      jmmv 			keys = MODEKEY_VI;
    481   1.2    martin 		else
    482   1.2    martin 			keys = MODEKEY_EMACS;
    483   1.5  christos 		options_set_number(global_s_options, "status-keys", keys);
    484   1.5  christos 		options_set_number(global_w_options, "mode-keys", keys);
    485   1.1      jmmv 	}
    486   1.1      jmmv 
    487   1.1      jmmv 	/*
    488   1.5  christos 	 * If socket is specified on the command-line with -S or -L, it is
    489   1.5  christos 	 * used. Otherwise, $TMUX is checked and if that fails "default" is
    490   1.5  christos 	 * used.
    491   1.1      jmmv 	 */
    492   1.5  christos 	if (path == NULL && label == NULL) {
    493   1.5  christos 		s = getenv("TMUX");
    494   1.5  christos 		if (s != NULL && *s != '\0' && *s != ',') {
    495   1.5  christos 			path = xstrdup(s);
    496   1.6  christos 			path[strcspn(path, ",")] = '\0';
    497   1.1      jmmv 		}
    498   1.1      jmmv 	}
    499  1.12  christos 	if (path == NULL) {
    500  1.12  christos 		if ((path = make_label(label, &cause)) == NULL) {
    501  1.12  christos 			if (cause != NULL) {
    502  1.12  christos 				fprintf(stderr, "%s\n", cause);
    503  1.12  christos 				free(cause);
    504  1.12  christos 			}
    505  1.12  christos 			exit(1);
    506   1.8  christos 		}
    507  1.12  christos 		flags |= CLIENT_DEFAULTSOCKET;
    508   1.3  christos 	}
    509   1.5  christos 	socket_path = path;
    510   1.5  christos 	free(label);
    511   1.1      jmmv 
    512   1.1      jmmv 	/* Pass control to the client. */
    513  1.12  christos 	exit(client_main(osdep_event_init(), argc, argv, flags, feat));
    514   1.1      jmmv }
    515