summaryrefslogtreecommitdiffstats
path: root/tmux.c
diff options
context:
space:
mode:
authorNicholas Marriott <nicm@openbsd.org>2010-10-18 20:00:02 +0000
committerNicholas Marriott <nicm@openbsd.org>2010-10-18 20:00:02 +0000
commit248fb14f089216bf384c8914163cc77b4f219154 (patch)
tree7c55d3a23461ce64809f39a3ad01c487e1de53b2 /tmux.c
parent31954339d1487d2a179f6180867e67cbd22aabd1 (diff)
Merge the before and after attach client code into one in client.c
(instead of two in tmux.c and client.c).
Diffstat (limited to 'tmux.c')
-rw-r--r--tmux.c274
1 files changed, 43 insertions, 231 deletions
diff --git a/tmux.c b/tmux.c
index f6601cdf..3a3f82f9 100644
--- a/tmux.c
+++ b/tmux.c
@@ -18,17 +18,14 @@
#include <sys/types.h>
#include <sys/stat.h>
-#include <sys/wait.h>
#include <errno.h>
#include <event.h>
#include <fcntl.h>
#include <paths.h>
#include <pwd.h>
-#include <signal.h>
#include <stdlib.h>
#include <string.h>
-#include <syslog.h>
#include <unistd.h>
#include "tmux.h"
@@ -37,7 +34,6 @@
extern char *malloc_options;
#endif
-char *cfg_file;
struct options global_options; /* server options */
struct options global_s_options; /* session options */
struct options global_w_options; /* window options */
@@ -45,28 +41,19 @@ struct environ global_environ;
struct event_base *ev_base;
+char *cfg_file;
+char *shell_cmd;
int debug_level;
time_t start_time;
-char *socket_path;
+char socket_path[MAXPATHLEN];
int login_shell;
-
-struct env_data {
- char *path;
- pid_t pid;
- u_int idx;
-};
+char *environ_path;
+pid_t environ_pid;
+u_int environ_idx;
__dead void usage(void);
-void parse_env(struct env_data *);
-char *makesockpath(const char *);
-__dead void shell_exec(const char *, const char *);
-
-struct imsgbuf *main_ibuf;
-struct event main_event;
-
-void main_signal(int, short, unused void *);
-void main_callback(int, short, void *);
-void main_dispatch(const char *);
+void parseenvironment(void);
+char *makesocketpath(const char *);
__dead void
usage(void)
@@ -136,14 +123,14 @@ areshell(const char *shell)
}
void
-parse_env(struct env_data *data)
+parseenvironment(void)
{
char *env, *path_pid, *pid_idx, buf[256];
size_t len;
const char *errstr;
long long ll;
- data->pid = -1;
+ environ_pid = -1;
if ((env = getenv("TMUX")) == NULL)
return;
@@ -156,9 +143,9 @@ parse_env(struct env_data *data)
/* path */
len = path_pid - env;
- data->path = xmalloc (len + 1);
- memcpy(data->path, env, len);
- data->path[len] = '\0';
+ environ_path = xmalloc(len + 1);
+ memcpy(environ_path, env, len);
+ environ_path[len] = '\0';
/* pid */
len = pid_idx - path_pid - 1;
@@ -170,17 +157,17 @@ parse_env(struct env_data *data)
ll = strtonum(buf, 0, LONG_MAX, &errstr);
if (errstr != NULL)
return;
- data->pid = ll;
+ environ_pid = ll;
/* idx */
- ll = strtonum(pid_idx+1, 0, UINT_MAX, &errstr);
+ ll = strtonum(pid_idx + 1, 0, UINT_MAX, &errstr);
if (errstr != NULL)
return;
- data->idx = ll;
+ environ_idx = ll;
}
char *
-makesockpath(const char *label)
+makesocketpath(const char *label)
{
char base[MAXPATHLEN], *path;
struct stat sb;
@@ -240,28 +227,18 @@ shell_exec(const char *shell, const char *shellcmd)
int
main(int argc, char **argv)
{
- struct cmd_list *cmdlist;
- struct cmd *cmd;
- enum msgtype msg;
- struct passwd *pw;
- struct options *oo, *so, *wo;
- struct keylist *keylist;
- struct env_data envdata;
- struct msg_command_data cmddata;
- char *s, *shellcmd, *path, *label, *home, *cause;
- char **var;
- void *buf;
- size_t len;
- int opt, flags, quiet = 0, cmdflags = 0;
- short events;
+ struct passwd *pw;
+ struct options *oo, *so, *wo;
+ struct keylist *keylist;
+ char *s, *path, *label, *home, **var;
+ int opt, flags, quiet = 0;
#ifdef DEBUG
malloc_options = (char *) "AFGJPX";
#endif
flags = 0;
- shellcmd = label = path = NULL;
- envdata.path = NULL;
+ label = path = NULL;
login_shell = (**argv == '-');
while ((opt = getopt(argc, argv, "28c:df:lL:qS:uUv")) != -1) {
switch (opt) {
@@ -274,9 +251,9 @@ main(int argc, char **argv)
flags &= ~IDENTIFY_256COLOURS;
break;
case 'c':
- if (shellcmd != NULL)
- xfree(shellcmd);
- shellcmd = xstrdup(optarg);
+ if (shell_cmd != NULL)
+ xfree(shell_cmd);
+ shell_cmd = xstrdup(optarg);
break;
case 'f':
if (cfg_file != NULL)
@@ -312,7 +289,7 @@ main(int argc, char **argv)
argc -= optind;
argv += optind;
- if (shellcmd != NULL && argc != 0)
+ if (shell_cmd != NULL && argc != 0)
usage();
log_open_tty(debug_level);
@@ -448,6 +425,7 @@ main(int argc, char **argv)
options_set_number(wo, "utf8", 0);
}
+ /* Locate the configuration file. */
if (cfg_file == NULL) {
home = getenv("HOME");
if (home == NULL || *home == '\0') {
@@ -463,21 +441,22 @@ main(int argc, char **argv)
}
/*
- * Figure out the socket path. If specified on the command-line with
- * -S or -L, use it, otherwise try $TMUX or assume -L default.
+ * Figure out the socket path. If specified on the command-line with -S
+ * or -L, use it, otherwise try $TMUX or assume -L default.
*/
- parse_env(&envdata);
+ parseenvironment();
if (path == NULL) {
- /* No -L. Try $TMUX, or default. */
+ /* If no -L, use the environment. */
if (label == NULL) {
- path = envdata.path;
- if (path == NULL)
+ if (environ_path != NULL)
+ path = xstrdup(environ_path);
+ else
label = xstrdup("default");
}
/* -L or default set. */
if (label != NULL) {
- if ((path = makesockpath(label)) == NULL) {
+ if ((path = makesocketpath(label)) == NULL) {
log_warn("can't create socket");
exit(1);
}
@@ -485,181 +464,14 @@ main(int argc, char **argv)
}
if (label != NULL)
xfree(label);
-
- if (shellcmd != NULL) {
- msg = MSG_SHELL;
- buf = NULL;
- len = 0;
- } else {
- cmddata.pid = envdata.pid;
- cmddata.idx = envdata.idx;
-
- /* Prepare command for server. */
- cmddata.argc = argc;
- if (cmd_pack_argv(
- argc, argv, cmddata.argv, sizeof cmddata.argv) != 0) {
- log_warnx("command too long");
- exit(1);
- }
-
- msg = MSG_COMMAND;
- buf = &cmddata;
- len = sizeof cmddata;
- }
-
- if (shellcmd != NULL)
- cmdflags |= CMD_STARTSERVER;
- else if (argc == 0) /* new-session is the default */
- cmdflags |= CMD_STARTSERVER|CMD_SENDENVIRON|CMD_CANTNEST;
- else {
- /*
- * It sucks parsing the command string twice (in client and
- * later in server) but it is necessary to get the start server
- * flag.
- */
- if ((cmdlist = cmd_list_parse(argc, argv, &cause)) == NULL) {
- log_warnx("%s", cause);
- exit(1);
- }
- cmdflags &= ~CMD_STARTSERVER;
- TAILQ_FOREACH(cmd, &cmdlist->list, qentry) {
- if (cmd->entry->flags & CMD_STARTSERVER)
- cmdflags |= CMD_STARTSERVER;
- if (cmd->entry->flags & CMD_SENDENVIRON)
- cmdflags |= CMD_SENDENVIRON;
- if (cmd->entry->flags & CMD_CANTNEST)
- cmdflags |= CMD_CANTNEST;
- }
- cmd_list_free(cmdlist);
- }
-
- /*
- * Check if this could be a nested session, if the command can't nest:
- * if the socket path matches $TMUX, this is probably the same server.
- */
- if (shellcmd == NULL && envdata.path != NULL &&
- cmdflags & CMD_CANTNEST &&
- (path == envdata.path || strcmp(path, envdata.path) == 0)) {
- log_warnx("sessions should be nested with care. "
- "unset $TMUX to force.");
- exit(1);
- }
-
- ev_base = event_init();
- set_signals(main_signal);
-
- /* Initialise the client socket/start the server. */
- if ((main_ibuf = client_init(path, cmdflags, flags)) == NULL)
- exit(1);
+ if (realpath(path, socket_path) == NULL)
+ strlcpy(socket_path, path, sizeof socket_path);
xfree(path);
- imsg_compose(main_ibuf, msg, PROTOCOL_VERSION, -1, -1, buf, len);
-
- events = EV_READ;
- if (main_ibuf->w.queued > 0)
- events |= EV_WRITE;
- event_set(&main_event, main_ibuf->fd, events, main_callback, shellcmd);
- event_add(&main_event, NULL);
-
- event_dispatch();
+ /* Set process title. */
+ setproctitle("%s (%s)", __progname, socket_path);
- event_del(&main_event);
-
- clear_signals(0);
- client_main(); /* doesn't return */
-}
-
-/* ARGSUSED */
-void
-main_signal(int sig, unused short events, unused void *data)
-{
- int status;
-
- switch (sig) {
- case SIGTERM:
- exit(1);
- case SIGCHLD:
- waitpid(WAIT_ANY, &status, WNOHANG);
- break;
- }
-}
-
-/* ARGSUSED */
-void
-main_callback(unused int fd, short events, void *data)
-{
- char *shellcmd = data;
-
- if (events & EV_READ)
- main_dispatch(shellcmd);
-
- if (events & EV_WRITE) {
- if (msgbuf_write(&main_ibuf->w) < 0)
- fatalx("msgbuf_write failed");
- }
-
- event_del(&main_event);
- events = EV_READ;
- if (main_ibuf->w.queued > 0)
- events |= EV_WRITE;
- event_set(&main_event, main_ibuf->fd, events, main_callback, shellcmd);
- event_add(&main_event, NULL);
-}
-
-void
-main_dispatch(const char *shellcmd)
-{
- struct imsg imsg;
- ssize_t n, datalen;
- struct msg_shell_data shelldata;
- struct msg_exit_data exitdata;
-
- if ((n = imsg_read(main_ibuf)) == -1 || n == 0)
- fatalx("imsg_read failed");
-
- for (;;) {
- if ((n = imsg_get(main_ibuf, &imsg)) == -1)
- fatalx("imsg_get failed");
- if (n == 0)
- return;
- datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
-
- switch (imsg.hdr.type) {
- case MSG_EXIT:
- case MSG_SHUTDOWN:
- if (datalen != sizeof exitdata) {
- if (datalen != 0)
- fatalx("bad MSG_EXIT size");
- exit(0);
- }
- memcpy(&exitdata, imsg.data, sizeof exitdata);
- exit(exitdata.retcode);
- case MSG_READY:
- if (datalen != 0)
- fatalx("bad MSG_READY size");
-
- event_loopexit(NULL); /* move to client_main() */
- break;
- case MSG_VERSION:
- if (datalen != 0)
- fatalx("bad MSG_VERSION size");
-
- log_warnx("protocol version mismatch (client %u, "
- "server %u)", PROTOCOL_VERSION, imsg.hdr.peerid);
- exit(1);
- case MSG_SHELL:
- if (datalen != sizeof shelldata)
- fatalx("bad MSG_SHELL size");
- memcpy(&shelldata, imsg.data, sizeof shelldata);
- shelldata.shell[(sizeof shelldata.shell) - 1] = '\0';
-
- clear_signals(0);
-
- shell_exec(shelldata.shell, shellcmd);
- default:
- fatalx("unexpected message");
- }
-
- imsg_free(&imsg);
- }
+ /* Pass control to the client. */
+ ev_base = event_init();
+ exit(client_main(argc, argv, flags));
}