tmux.c revision 1.13.2.1 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.13.2.1 martin static __dead void usage(int);
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.13.2.1 martin usage(int status)
54 1.1 jmmv {
55 1.13.2.1 martin fprintf(status ? stderr : stdout,
56 1.13.2.1 martin "usage: %s [-2CDhlNuVv] [-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.13.2.1 martin exit(status);
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.13.2.1 martin expand_paths(const char *s, char ***paths, u_int *n, int no_realpath)
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.13.2.1 martin if (no_realpath)
160 1.13.2.1 martin path = expanded;
161 1.13.2.1 martin else {
162 1.13.2.1 martin if (realpath(expanded, resolved) == NULL) {
163 1.13.2.1 martin log_debug("%s: realpath(\"%s\") failed: %s", __func__,
164 1.13.2.1 martin expanded, strerror(errno));
165 1.12 christos free(expanded);
166 1.12 christos continue;
167 1.12 christos }
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.13.2.1 martin expand_paths(TMUX_SOCK, &paths, &n, 0);
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.13.2.1 martin free(path);
211 1.13.2.1 martin if (mkdir(base, S_IRWXU) != 0 && errno != EEXIST) {
212 1.13.2.1 martin xasprintf(cause, "couldn't create directory %s (%s)", base,
213 1.13.2.1 martin strerror(errno));
214 1.5 christos goto fail;
215 1.13.2.1 martin }
216 1.13.2.1 martin if (lstat(base, &sb) != 0) {
217 1.13.2.1 martin xasprintf(cause, "couldn't read directory %s (%s)", base,
218 1.13.2.1 martin strerror(errno));
219 1.5 christos goto fail;
220 1.13.2.1 martin }
221 1.1 jmmv if (!S_ISDIR(sb.st_mode)) {
222 1.13.2.1 martin xasprintf(cause, "%s is not a directory", base);
223 1.5 christos goto fail;
224 1.1 jmmv }
225 1.13.2.1 martin if (sb.st_uid != uid || (sb.st_mode & TMUX_SOCK_PERM) != 0) {
226 1.13.2.1 martin xasprintf(cause, "directory %s has unsafe permissions", base);
227 1.5 christos goto fail;
228 1.1 jmmv }
229 1.12 christos xasprintf(&path, "%s/%s", base, label);
230 1.12 christos free(base);
231 1.5 christos return (path);
232 1.3 christos
233 1.5 christos fail:
234 1.12 christos free(base);
235 1.5 christos return (NULL);
236 1.1 jmmv }
237 1.1 jmmv
238 1.13.2.1 martin char *
239 1.13.2.1 martin shell_argv0(const char *shell, int is_login)
240 1.13.2.1 martin {
241 1.13.2.1 martin const char *slash, *name;
242 1.13.2.1 martin char *argv0;
243 1.13.2.1 martin
244 1.13.2.1 martin slash = strrchr(shell, '/');
245 1.13.2.1 martin if (slash != NULL && slash[1] != '\0')
246 1.13.2.1 martin name = slash + 1;
247 1.13.2.1 martin else
248 1.13.2.1 martin name = shell;
249 1.13.2.1 martin if (is_login)
250 1.13.2.1 martin xasprintf(&argv0, "-%s", name);
251 1.13.2.1 martin else
252 1.13.2.1 martin xasprintf(&argv0, "%s", name);
253 1.13.2.1 martin return (argv0);
254 1.13.2.1 martin }
255 1.13.2.1 martin
256 1.2 martin void
257 1.2 martin setblocking(int fd, int state)
258 1.2 martin {
259 1.2 martin int mode;
260 1.2 martin
261 1.2 martin if ((mode = fcntl(fd, F_GETFL)) != -1) {
262 1.2 martin if (!state)
263 1.2 martin mode |= O_NONBLOCK;
264 1.2 martin else
265 1.2 martin mode &= ~O_NONBLOCK;
266 1.2 martin fcntl(fd, F_SETFL, mode);
267 1.2 martin }
268 1.2 martin }
269 1.2 martin
270 1.12 christos uint64_t
271 1.12 christos get_timer(void)
272 1.12 christos {
273 1.12 christos struct timespec ts;
274 1.12 christos
275 1.12 christos /*
276 1.12 christos * We want a timestamp in milliseconds suitable for time measurement,
277 1.12 christos * so prefer the monotonic clock.
278 1.12 christos */
279 1.12 christos if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0)
280 1.12 christos clock_gettime(CLOCK_REALTIME, &ts);
281 1.12 christos return ((ts.tv_sec * 1000ULL) + (ts.tv_nsec / 1000000ULL));
282 1.12 christos }
283 1.12 christos
284 1.12 christos const char *
285 1.12 christos sig2name(int signo)
286 1.12 christos {
287 1.12 christos static char s[11];
288 1.12 christos
289 1.12 christos #ifdef HAVE_SYS_SIGNAME
290 1.12 christos if (signo > 0 && signo < NSIG)
291 1.12 christos return (sys_signame[signo]);
292 1.12 christos #endif
293 1.12 christos xsnprintf(s, sizeof s, "%d", signo);
294 1.12 christos return (s);
295 1.12 christos }
296 1.12 christos
297 1.4 christos const char *
298 1.9 christos find_cwd(void)
299 1.9 christos {
300 1.9 christos char resolved1[PATH_MAX], resolved2[PATH_MAX];
301 1.9 christos static char cwd[PATH_MAX];
302 1.9 christos const char *pwd;
303 1.9 christos
304 1.9 christos if (getcwd(cwd, sizeof cwd) == NULL)
305 1.9 christos return (NULL);
306 1.9 christos if ((pwd = getenv("PWD")) == NULL || *pwd == '\0')
307 1.9 christos return (cwd);
308 1.9 christos
309 1.9 christos /*
310 1.9 christos * We want to use PWD so that symbolic links are maintained,
311 1.9 christos * but only if it matches the actual working directory.
312 1.9 christos */
313 1.9 christos if (realpath(pwd, resolved1) == NULL)
314 1.9 christos return (cwd);
315 1.9 christos if (realpath(cwd, resolved2) == NULL)
316 1.9 christos return (cwd);
317 1.9 christos if (strcmp(resolved1, resolved2) != 0)
318 1.9 christos return (cwd);
319 1.9 christos return (pwd);
320 1.9 christos }
321 1.9 christos
322 1.9 christos const char *
323 1.4 christos find_home(void)
324 1.1 jmmv {
325 1.4 christos struct passwd *pw;
326 1.4 christos static const char *home;
327 1.1 jmmv
328 1.4 christos if (home != NULL)
329 1.4 christos return (home);
330 1.1 jmmv
331 1.4 christos home = getenv("HOME");
332 1.4 christos if (home == NULL || *home == '\0') {
333 1.4 christos pw = getpwuid(getuid());
334 1.4 christos if (pw != NULL)
335 1.4 christos home = pw->pw_dir;
336 1.4 christos else
337 1.4 christos home = NULL;
338 1.4 christos }
339 1.1 jmmv
340 1.4 christos return (home);
341 1.1 jmmv }
342 1.1 jmmv
343 1.11 christos const char *
344 1.11 christos getversion(void)
345 1.11 christos {
346 1.13.2.1 martin return (TMUX_VERSION);
347 1.11 christos }
348 1.11 christos
349 1.1 jmmv int
350 1.1 jmmv main(int argc, char **argv)
351 1.1 jmmv {
352 1.12 christos char *path = NULL, *label = NULL;
353 1.12 christos char *cause, **var;
354 1.12 christos const char *s, *cwd;
355 1.13 christos int opt, keys, feat = 0, fflag = 0;
356 1.12 christos uint64_t flags = 0;
357 1.6 christos const struct options_table_entry *oe;
358 1.12 christos u_int i;
359 1.5 christos
360 1.7 christos if (setlocale(LC_CTYPE, "en_US.UTF-8") == NULL &&
361 1.7 christos setlocale(LC_CTYPE, "C.UTF-8") == NULL) {
362 1.5 christos if (setlocale(LC_CTYPE, "") == NULL)
363 1.5 christos errx(1, "invalid LC_ALL, LC_CTYPE or LANG");
364 1.5 christos s = nl_langinfo(CODESET);
365 1.6 christos if (strcasecmp(s, "UTF-8") != 0 && strcasecmp(s, "UTF8") != 0)
366 1.5 christos errx(1, "need UTF-8 locale (LC_CTYPE) but have %s", s);
367 1.5 christos }
368 1.1 jmmv
369 1.3 christos setlocale(LC_TIME, "");
370 1.4 christos tzset();
371 1.4 christos
372 1.4 christos if (**argv == '-')
373 1.4 christos flags = CLIENT_LOGIN;
374 1.3 christos
375 1.12 christos global_environ = environ_create();
376 1.12 christos for (var = environ; *var != NULL; var++)
377 1.12 christos environ_put(global_environ, *var, 0);
378 1.12 christos if ((cwd = find_cwd()) != NULL)
379 1.12 christos environ_set(global_environ, "PWD", 0, "%s", cwd);
380 1.12 christos expand_paths(TMUX_CONF, &cfg_files, &cfg_nfiles, 1);
381 1.12 christos
382 1.13.2.1 martin while ((opt = getopt(argc, argv, "2c:CDdf:hlL:NqS:T:uUvV")) != -1) {
383 1.1 jmmv switch (opt) {
384 1.1 jmmv case '2':
385 1.12 christos tty_add_features(&feat, "256", ":,");
386 1.1 jmmv break;
387 1.1 jmmv case 'c':
388 1.7 christos shell_command = optarg;
389 1.1 jmmv break;
390 1.12 christos case 'D':
391 1.12 christos flags |= CLIENT_NOFORK;
392 1.12 christos break;
393 1.3 christos case 'C':
394 1.3 christos if (flags & CLIENT_CONTROL)
395 1.3 christos flags |= CLIENT_CONTROLCONTROL;
396 1.3 christos else
397 1.3 christos flags |= CLIENT_CONTROL;
398 1.3 christos break;
399 1.1 jmmv case 'f':
400 1.13 christos if (!fflag) {
401 1.13 christos fflag = 1;
402 1.13 christos for (i = 0; i < cfg_nfiles; i++)
403 1.13 christos free(cfg_files[i]);
404 1.13 christos cfg_nfiles = 0;
405 1.13 christos }
406 1.13 christos cfg_files = xreallocarray(cfg_files, cfg_nfiles + 1,
407 1.13 christos sizeof *cfg_files);
408 1.13 christos cfg_files[cfg_nfiles++] = xstrdup(optarg);
409 1.12 christos cfg_quiet = 0;
410 1.1 jmmv break;
411 1.13.2.1 martin case 'h':
412 1.13.2.1 martin usage(0);
413 1.13.2.1 martin case 'V':
414 1.13.2.1 martin printf("tmux %s\n", getversion());
415 1.13.2.1 martin exit(0);
416 1.1 jmmv case 'l':
417 1.4 christos flags |= CLIENT_LOGIN;
418 1.1 jmmv break;
419 1.1 jmmv case 'L':
420 1.3 christos free(label);
421 1.1 jmmv label = xstrdup(optarg);
422 1.1 jmmv break;
423 1.12 christos case 'N':
424 1.12 christos flags |= CLIENT_NOSTARTSERVER;
425 1.12 christos break;
426 1.1 jmmv case 'q':
427 1.1 jmmv break;
428 1.1 jmmv case 'S':
429 1.3 christos free(path);
430 1.1 jmmv path = xstrdup(optarg);
431 1.1 jmmv break;
432 1.12 christos case 'T':
433 1.12 christos tty_add_features(&feat, optarg, ":,");
434 1.12 christos break;
435 1.1 jmmv case 'u':
436 1.3 christos flags |= CLIENT_UTF8;
437 1.1 jmmv break;
438 1.1 jmmv case 'v':
439 1.5 christos log_add_level();
440 1.1 jmmv break;
441 1.1 jmmv default:
442 1.13.2.1 martin usage(1);
443 1.1 jmmv }
444 1.1 jmmv }
445 1.1 jmmv argc -= optind;
446 1.1 jmmv argv += optind;
447 1.1 jmmv
448 1.7 christos if (shell_command != NULL && argc != 0)
449 1.13.2.1 martin usage(1);
450 1.12 christos if ((flags & CLIENT_NOFORK) && argc != 0)
451 1.13.2.1 martin usage(1);
452 1.1 jmmv
453 1.7 christos if ((ptm_fd = getptmfd()) == -1)
454 1.7 christos err(1, "getptmfd");
455 1.5 christos if (pledge("stdio rpath wpath cpath flock fattr unix getpw sendfd "
456 1.5 christos "recvfd proc exec tty ps", NULL) != 0)
457 1.5 christos err(1, "pledge");
458 1.1 jmmv
459 1.5 christos /*
460 1.5 christos * tmux is a UTF-8 terminal, so if TMUX is set, assume UTF-8.
461 1.5 christos * Otherwise, if the user has set LC_ALL, LC_CTYPE or LANG to contain
462 1.5 christos * UTF-8, it is a safe assumption that either they are using a UTF-8
463 1.5 christos * terminal, or if not they know that output from UTF-8-capable
464 1.5 christos * programs may be wrong.
465 1.5 christos */
466 1.5 christos if (getenv("TMUX") != NULL)
467 1.5 christos flags |= CLIENT_UTF8;
468 1.5 christos else {
469 1.5 christos s = getenv("LC_ALL");
470 1.5 christos if (s == NULL || *s == '\0')
471 1.5 christos s = getenv("LC_CTYPE");
472 1.5 christos if (s == NULL || *s == '\0')
473 1.5 christos s = getenv("LANG");
474 1.5 christos if (s == NULL || *s == '\0')
475 1.5 christos s = "";
476 1.5 christos if (strcasestr(s, "UTF-8") != NULL ||
477 1.5 christos strcasestr(s, "UTF8") != NULL)
478 1.3 christos flags |= CLIENT_UTF8;
479 1.1 jmmv }
480 1.1 jmmv
481 1.5 christos global_options = options_create(NULL);
482 1.5 christos global_s_options = options_create(NULL);
483 1.6 christos global_w_options = options_create(NULL);
484 1.6 christos for (oe = options_table; oe->name != NULL; oe++) {
485 1.10 christos if (oe->scope & OPTIONS_TABLE_SERVER)
486 1.6 christos options_default(global_options, oe);
487 1.10 christos if (oe->scope & OPTIONS_TABLE_SESSION)
488 1.6 christos options_default(global_s_options, oe);
489 1.10 christos if (oe->scope & OPTIONS_TABLE_WINDOW)
490 1.6 christos options_default(global_w_options, oe);
491 1.6 christos }
492 1.1 jmmv
493 1.6 christos /*
494 1.6 christos * The default shell comes from SHELL or from the user's passwd entry
495 1.6 christos * if available.
496 1.6 christos */
497 1.12 christos options_set_string(global_s_options, "default-shell", 0, "%s",
498 1.12 christos getshell());
499 1.1 jmmv
500 1.2 martin /* Override keys to vi if VISUAL or EDITOR are set. */
501 1.1 jmmv if ((s = getenv("VISUAL")) != NULL || (s = getenv("EDITOR")) != NULL) {
502 1.12 christos options_set_string(global_options, "editor", 0, "%s", s);
503 1.1 jmmv if (strrchr(s, '/') != NULL)
504 1.1 jmmv s = strrchr(s, '/') + 1;
505 1.1 jmmv if (strstr(s, "vi") != NULL)
506 1.1 jmmv keys = MODEKEY_VI;
507 1.2 martin else
508 1.2 martin keys = MODEKEY_EMACS;
509 1.5 christos options_set_number(global_s_options, "status-keys", keys);
510 1.5 christos options_set_number(global_w_options, "mode-keys", keys);
511 1.1 jmmv }
512 1.1 jmmv
513 1.1 jmmv /*
514 1.5 christos * If socket is specified on the command-line with -S or -L, it is
515 1.5 christos * used. Otherwise, $TMUX is checked and if that fails "default" is
516 1.5 christos * used.
517 1.1 jmmv */
518 1.5 christos if (path == NULL && label == NULL) {
519 1.5 christos s = getenv("TMUX");
520 1.5 christos if (s != NULL && *s != '\0' && *s != ',') {
521 1.5 christos path = xstrdup(s);
522 1.6 christos path[strcspn(path, ",")] = '\0';
523 1.1 jmmv }
524 1.1 jmmv }
525 1.12 christos if (path == NULL) {
526 1.12 christos if ((path = make_label(label, &cause)) == NULL) {
527 1.12 christos if (cause != NULL) {
528 1.12 christos fprintf(stderr, "%s\n", cause);
529 1.12 christos free(cause);
530 1.12 christos }
531 1.12 christos exit(1);
532 1.8 christos }
533 1.12 christos flags |= CLIENT_DEFAULTSOCKET;
534 1.3 christos }
535 1.5 christos socket_path = path;
536 1.5 christos free(label);
537 1.1 jmmv
538 1.1 jmmv /* Pass control to the client. */
539 1.12 christos exit(client_main(osdep_event_init(), argc, argv, flags, feat));
540 1.1 jmmv }
541