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