diff options
author | Nicholas Marriott <nicholas.marriott@gmail.com> | 2007-08-27 13:45:26 +0000 |
---|---|---|
committer | Nicholas Marriott <nicholas.marriott@gmail.com> | 2007-08-27 13:45:26 +0000 |
commit | 04f4e4219b63187630aab706f65245e2ea1ade5a (patch) | |
tree | 65b22a0f5bdb79daa7dbc6aafa1d1ce496154d53 /tmux.c | |
parent | 6e210bb005ee5193fe030f5e8cfe8877aac6260d (diff) | |
download | rtmux-04f4e4219b63187630aab706f65245e2ea1ade5a.tar.gz rtmux-04f4e4219b63187630aab706f65245e2ea1ade5a.tar.bz2 rtmux-04f4e4219b63187630aab706f65245e2ea1ade5a.zip |
Change command format.
Diffstat (limited to 'tmux.c')
-rw-r--r-- | tmux.c | 294 |
1 files changed, 173 insertions, 121 deletions
@@ -1,4 +1,4 @@ -/* $Id: tmux.c,v 1.2 2007-07-25 23:13:18 nicm Exp $ */ +/* $Id: tmux.c,v 1.3 2007-08-27 13:45:26 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -40,13 +40,15 @@ const char *malloc_options = "AFGJPX"; #endif +void op_new(char *, struct winsize *); +void op_attach(char *, struct winsize *); int connect_server(void); -int process_server(struct buffer *); -int process_local(struct buffer *, struct buffer *); +int process_server(char **); +int process_local(void); void sighandler(int); __dead void usage(void); __dead void main_list(char *); -void process_list(struct buffer *, const char *); +void process_list(const char *); /* SIGWINCH received flag. */ volatile sig_atomic_t sigwinch; @@ -60,11 +62,21 @@ int debug_level; /* Path to server socket. */ char socket_path[MAXPATHLEN]; +/* Server socket and buffers. */ +int server_fd = -1; +struct buffer *server_in; +struct buffer *server_out; + +/* Local socket and buffers. */ +int local_fd = -1; +struct buffer *local_in; +struct buffer *local_out; + __dead void usage(void) { fprintf(stderr, - "usage: %s [-v] [-n name] [-s path]\n", __progname); + "usage: %s [-v] [-n name] [-s path] command\n", __progname); exit(1); } @@ -87,13 +99,12 @@ sighandler(int sig) int main(int argc, char **argv) { - int opt, srv_fd, loc_fd, mode, listf, n; - char *path, name[MAXNAMELEN]; + int opt, mode, n; + char *path, *error, name[MAXNAMELEN]; FILE *f; - struct buffer *srv_in, *srv_out, *loc_in, *loc_out; + enum op op; struct pollfd pfds[2]; struct hdr hdr; - struct identify_data id; struct size_data sd; struct winsize ws; struct sigaction act; @@ -101,13 +112,9 @@ main(int argc, char **argv) *name = '\0'; path = NULL; - listf = 0; - while ((opt = getopt(argc, argv, "ln:s:v?")) != EOF) { + while ((opt = getopt(argc, argv, "n:s:v?")) != EOF) { switch (opt) { - case 'l': - listf = 1; - break; case 'n': if (strlcpy(name, optarg, sizeof name) >= sizeof name) errx(1, "name too long"); @@ -125,7 +132,17 @@ main(int argc, char **argv) } argc -= optind; argv += optind; - if (argc != 0) + if (argc != 1) + usage(); + + /* Determine command. */ + if (strncmp(argv[0], "list", strlen(argv[0])) == 0) + op = OP_LIST; + else if (strncmp(argv[0], "new", strlen(argv[0])) == 0) + op = OP_NEW; + else if (strncmp(argv[0], "attach", strlen(argv[0])) == 0) + op = OP_ATTACH; + else usage(); /* Sort out socket path. */ @@ -137,18 +154,33 @@ main(int argc, char **argv) err(1, "realpath"); xfree(path); - /* Skip to list function if listing. */ - if (listf) { - if (*name == '\0') - main_list(NULL); - else - main_list(name); + /* Start server if necessary. */ + if (stat(socket_path, &sb) != 0) { + if (errno != ENOENT) + err(1, "%s", socket_path); + else if (op != OP_LIST) { + if (server_start() != 0) + errx(1, "couldn't start server"); + sleep(1); + } + } else { + if (!S_ISSOCK(sb.st_mode)) + errx(1, "%s: not a socket", socket_path); } - /* And fill name. */ - if (*name == '\0') - xsnprintf(name, sizeof name, "s-%lu", (u_long) getpid()); - + /* Connect to server. */ + if ((server_fd = connect_server()) == -1) + errx(1, "couldn't find server"); + if ((mode = fcntl(server_fd, F_GETFL)) == -1) + err(1, "fcntl"); + if (fcntl(server_fd, F_SETFL, mode|O_NONBLOCK) == -1) + err(1, "fcntl"); + server_in = buffer_create(BUFSIZ); + server_out = buffer_create(BUFSIZ); + + if (op == OP_LIST) + main_list(name); + /* Check stdin/stdout. */ if (!isatty(STDIN_FILENO)) errx(1, "stdin is not a tty"); @@ -181,42 +213,21 @@ main(int argc, char **argv) if (sigaction(SIGCHLD, &act, NULL) != 0) err(1, "sigaction"); - /* Start server if necessary. */ - if (stat(socket_path, &sb) != 0) { - if (errno != ENOENT) - err(1, "%s", socket_path); - else { - if (server_start() != 0) - errx(1, "couldn't start server"); - sleep(1); - } - } else { - if (!S_ISSOCK(sb.st_mode)) - errx(1, "%s: not a socket", socket_path); - } - - /* Connect to server. */ - if ((srv_fd = connect_server()) == -1) - errx(1, "couldn't find server"); - if ((mode = fcntl(srv_fd, F_GETFL)) == -1) - err(1, "fcntl"); - if (fcntl(srv_fd, F_SETFL, mode|O_NONBLOCK) == -1) - err(1, "fcntl"); - srv_in = buffer_create(BUFSIZ); - srv_out = buffer_create(BUFSIZ); - /* Find window size. */ if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1) err(1, "ioctl(TIOCGWINSZ)"); /* Send initial data. */ - hdr.code = MSG_IDENTIFY; - hdr.size = sizeof id; - buffer_write(srv_out, &hdr, sizeof hdr); - strlcpy(id.name, name, sizeof id.name); - id.sx = ws.ws_col; - id.sy = ws.ws_row; - buffer_write(srv_out, &id, hdr.size); + switch (op) { + case OP_NEW: + op_new(name, &ws); + break; + case OP_ATTACH: + op_attach(name, &ws); + break; + default: + fatalx("unknown op"); + } /* Start logging to file. */ if (debug_level > 0) { @@ -226,39 +237,36 @@ main(int argc, char **argv) log_open(f, LOG_USER, debug_level); xfree(path); } - - /* Initialise terminal. */ - loc_fd = local_init(&loc_in, &loc_out); setproctitle("client (%s)", name); /* Main loop. */ n = 0; while (!sigterm) { /* Handle SIGWINCH if necessary. */ - if (sigwinch) { + if (local_fd != -1 && sigwinch) { if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1) fatal("ioctl failed"); - hdr.code = MSG_SIZE; + hdr.type = MSG_SIZE; hdr.size = sizeof sd; - buffer_write(srv_out, &hdr, sizeof hdr); + buffer_write(server_out, &hdr, sizeof hdr); sd.sx = ws.ws_col; sd.sy = ws.ws_row; - buffer_write(srv_out, &sd, hdr.size); + buffer_write(server_out, &sd, hdr.size); sigwinch = 0; } /* Set up pollfds. */ - pfds[0].fd = srv_fd; + pfds[0].fd = server_fd; pfds[0].events = POLLIN; - if (BUFFER_USED(srv_out) > 0) + if (BUFFER_USED(server_out) > 0) pfds[0].events |= POLLOUT; - pfds[1].fd = loc_fd; + pfds[1].fd = local_fd; pfds[1].events = POLLIN; - if (BUFFER_USED(loc_out) > 0) + if (local_fd != -1 && BUFFER_USED(local_out) > 0) pfds[1].events |= POLLOUT; - + /* Do the poll. */ if (poll(pfds, 2, INFTIM) == -1) { if (errno == EAGAIN || errno == EINTR) @@ -267,9 +275,10 @@ main(int argc, char **argv) } /* Read/write from sockets. */ - if (buffer_poll(&pfds[0], srv_in, srv_out) != 0) + if (buffer_poll(&pfds[0], server_in, server_out) != 0) goto server_dead; - if (buffer_poll(&pfds[1], loc_in, loc_out) != 0) + if (local_fd != -1 && + buffer_poll(&pfds[1], local_in, local_out) != 0) fatalx("lost local socket"); /* Output flushed; pause if requested. */ @@ -277,13 +286,17 @@ main(int argc, char **argv) usleep(750000); /* Process any data. */ - if ((n = process_server(srv_in)) == -1) + if ((n = process_server(&error)) == -1) break; - if (process_local(loc_in, srv_out) == -1) + if (process_local() == -1) break; } - local_done(); + if (local_fd != -1) + local_done(); + + if (error != NULL) + errx(1, "%s", error); if (!sigterm) printf("[detached]\n"); @@ -292,12 +305,47 @@ main(int argc, char **argv) exit(0); server_dead: - local_done(); + if (local_fd != -1) + local_done(); printf("[lost server]\n"); exit(1); } +/* New command. */ +void +op_new(char *name, struct winsize *ws) +{ + struct new_data data; + struct hdr hdr; + + hdr.type = MSG_NEW; + hdr.size = sizeof data; + buffer_write(server_out, &hdr, sizeof hdr); + + strlcpy(data.name, name, sizeof data.name); + data.sx = ws->ws_col; + data.sy = ws->ws_row; + buffer_write(server_out, &data, hdr.size); +} + +/* Attach command. */ +void +op_attach(char *name, struct winsize *ws) +{ + struct attach_data data; + struct hdr hdr; + + hdr.type = MSG_ATTACH; + hdr.size = sizeof data; + buffer_write(server_out, &hdr, sizeof hdr); + + strlcpy(data.name, name, sizeof data.name); + data.sx = ws->ws_col; + data.sy = ws->ws_row; + buffer_write(server_out, &data, hdr.size); +} + /* Connect to server socket from PID. */ int connect_server(void) @@ -323,21 +371,30 @@ connect_server(void) /* Handle data from server. */ int -process_server(struct buffer *srv_in) +process_server(char **error) { struct hdr hdr; + *error = NULL; for (;;) { - if (BUFFER_USED(srv_in) < sizeof hdr) + if (BUFFER_USED(server_in) < sizeof hdr) break; - memcpy(&hdr, BUFFER_OUT(srv_in), sizeof hdr); - if (BUFFER_USED(srv_in) < (sizeof hdr) + hdr.size) + memcpy(&hdr, BUFFER_OUT(server_in), sizeof hdr); + if (BUFFER_USED(server_in) < (sizeof hdr) + hdr.size) + break; + buffer_remove(server_in, sizeof hdr); + + switch (hdr.type) { + case MSG_READY: + if (hdr.size != 0) { + xasprintf(error, "%.*s", + (int) hdr.size, BUFFER_OUT(server_in)); + return (-1); + } + local_fd = local_init(&local_in, &local_out); break; - buffer_remove(srv_in, sizeof hdr); - - switch (hdr.code) { case MSG_OUTPUT: - local_output(srv_in, hdr.size); + local_output(server_in, hdr.size); break; case MSG_PAUSE: if (hdr.size != 0) @@ -345,6 +402,8 @@ process_server(struct buffer *srv_in) return (1); case MSG_EXIT: return (-1); + default: + fatalx("unexpected message"); } } @@ -353,13 +412,16 @@ process_server(struct buffer *srv_in) /* Handle data from local terminal. */ int -process_local(struct buffer *loc_in, struct buffer *srv_out) +process_local(void) { struct buffer *b; struct hdr hdr; size_t size; int n, key; + if (local_fd == -1) + return (0); + n = 0; b = buffer_create(BUFSIZ); @@ -368,10 +430,10 @@ process_local(struct buffer *loc_in, struct buffer *srv_out) if (key == cmd_prefix) { if ((key = local_key(NULL)) == KEYC_NONE) { - buffer_reverse_remove(loc_in, size); + buffer_reverse_remove(local_in, size); break; } - n = cmd_execute(key, srv_out); + n = cmd_execute(key, server_out); break; } @@ -385,10 +447,10 @@ process_local(struct buffer *loc_in, struct buffer *srv_out) } log_debug("transmitting %zu bytes of input", BUFFER_USED(b)); - hdr.code = MSG_INPUT; + hdr.type = MSG_INPUT; hdr.size = BUFFER_USED(b); - buffer_write(srv_out, &hdr, sizeof hdr); - buffer_write(srv_out, BUFFER_OUT(b), BUFFER_USED(b)); + buffer_write(server_out, &hdr, sizeof hdr); + buffer_write(server_out, BUFFER_OUT(b), BUFFER_USED(b)); buffer_destroy(b); return (n); @@ -400,41 +462,29 @@ main_list(char *name) { struct sessions_data sd; struct windows_data wd; - int srv_fd, mode; - struct buffer *srv_in, *srv_out; struct pollfd pfd; struct hdr hdr; - /* Connect to server. */ - if ((srv_fd = connect_server()) == -1) - errx(1, "couldn't find server"); - if ((mode = fcntl(srv_fd, F_GETFL)) == -1) - err(1, "fcntl"); - if (fcntl(srv_fd, F_SETFL, mode|O_NONBLOCK) == -1) - err(1, "fcntl"); - srv_in = buffer_create(BUFSIZ); - srv_out = buffer_create(BUFSIZ); - /* Send query data. */ - if (name == NULL) { - hdr.code = MSG_SESSIONS; + if (*name == '\0') { + hdr.type = MSG_SESSIONS; hdr.size = sizeof sd; - buffer_write(srv_out, &hdr, sizeof hdr); - buffer_write(srv_out, &sd, hdr.size); + buffer_write(server_out, &hdr, sizeof hdr); + buffer_write(server_out, &sd, hdr.size); } else { - hdr.code = MSG_WINDOWS; + hdr.type = MSG_WINDOWS; hdr.size = sizeof wd; - buffer_write(srv_out, &hdr, sizeof hdr); + buffer_write(server_out, &hdr, sizeof hdr); strlcpy(wd.name, name, sizeof wd.name); - buffer_write(srv_out, &wd, hdr.size); + buffer_write(server_out, &wd, hdr.size); } /* Main loop. */ for (;;) { /* Set up pollfd. */ - pfd.fd = srv_fd; + pfd.fd = server_fd; pfd.events = POLLIN; - if (BUFFER_USED(srv_out) > 0) + if (BUFFER_USED(server_out) > 0) pfd.events |= POLLOUT; /* Do the poll. */ @@ -445,16 +495,16 @@ main_list(char *name) } /* Read/write from sockets. */ - if (buffer_poll(&pfd, srv_in, srv_out) != 0) + if (buffer_poll(&pfd, server_in, server_out) != 0) errx(1, "lost server"); /* Process data. */ - process_list(srv_in, name); + process_list(name); } } void -process_list(struct buffer *srv_in, const char *name) +process_list(const char *name) { struct sessions_data sd; struct sessions_entry se; @@ -464,25 +514,25 @@ process_list(struct buffer *srv_in, const char *name) char *tim; for (;;) { - if (BUFFER_USED(srv_in) < sizeof hdr) + if (BUFFER_USED(server_in) < sizeof hdr) break; - memcpy(&hdr, BUFFER_OUT(srv_in), sizeof hdr); - if (BUFFER_USED(srv_in) < (sizeof hdr) + hdr.size) + memcpy(&hdr, BUFFER_OUT(server_in), sizeof hdr); + if (BUFFER_USED(server_in) < (sizeof hdr) + hdr.size) break; - buffer_remove(srv_in, sizeof hdr); + buffer_remove(server_in, sizeof hdr); - switch (hdr.code) { + switch (hdr.type) { case MSG_SESSIONS: if (hdr.size < sizeof sd) errx(1, "bad MSG_SESSIONS size"); - buffer_read(srv_in, &sd, sizeof sd); + buffer_read(server_in, &sd, sizeof sd); hdr.size -= sizeof sd; if (sd.sessions == 0 && hdr.size == 0) exit(0); if (hdr.size < sd.sessions * sizeof se) errx(1, "bad MSG_SESSIONS size"); while (sd.sessions-- > 0) { - buffer_read(srv_in, &se, sizeof se); + buffer_read(server_in, &se, sizeof se); tim = ctime(&se.tim); *strchr(tim, '\n') = '\0'; printf("%s: %u windows (created %s)\n", @@ -492,14 +542,14 @@ process_list(struct buffer *srv_in, const char *name) case MSG_WINDOWS: if (hdr.size < sizeof wd) errx(1, "bad MSG_WINDOWS size"); - buffer_read(srv_in, &wd, sizeof wd); + buffer_read(server_in, &wd, sizeof wd); hdr.size -= sizeof wd; if (wd.windows == 0 && hdr.size == 0) errx(1, "session \"%s\" not found", name); if (hdr.size < wd.windows * sizeof we) errx(1, "bad MSG_WINDOWS size"); while (wd.windows-- > 0) { - buffer_read(srv_in, &we, sizeof we); + buffer_read(server_in, &we, sizeof we); if (*we.title != '\0') { printf("%u: %s \"%s\" (%s)\n", we.idx, we.name, we.title, we.tty); @@ -509,6 +559,8 @@ process_list(struct buffer *srv_in, const char *name) } } exit(0); + default: + fatalx("unexpected message"); } } } |