From d433fe69565db25b4248b8e9f0316d2cd04fe7e3 Mon Sep 17 00:00:00 2001 From: Nicolas Viennot Date: Tue, 29 Mar 2016 01:42:07 -0400 Subject: [PATCH 01/75] nits --- tmate-ssh-client.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tmate-ssh-client.c b/tmate-ssh-client.c index 7495d584..b280400d 100644 --- a/tmate-ssh-client.c +++ b/tmate-ssh-client.c @@ -319,7 +319,7 @@ static void on_ssh_client_event(struct tmate_ssh_client *client) request_passphrase(client); } else { kill_ssh_client(client, "SSH keys not found." - " Run 'ssh-keygen' to create keys and try again."); + " Run 'ssh-keygen' to create keys."); return; } From fe81322cc4801860c33b1e31970b8f0f6bf603c7 Mon Sep 17 00:00:00 2001 From: Nicolas Viennot Date: Thu, 21 Apr 2016 16:05:52 -0400 Subject: [PATCH 02/75] Keep alive the socket to make reconnections work properly --- tmate-ssh-client.c | 44 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/tmate-ssh-client.c b/tmate-ssh-client.c index b280400d..8b78f5cc 100644 --- a/tmate-ssh-client.c +++ b/tmate-ssh-client.c @@ -165,22 +165,48 @@ static void request_passphrase(struct tmate_ssh_client *client) data->password_cb_private = client; } +#define KEEPALIVE_CNT 3 +#define KEEPALIVE_IDLE 20 +#define KEEPALIVE_INTVL 10 + +static void setup_socket(int fd) +{ +#define SSO(level, optname, val) ({ \ + int _flag = val; \ + if (setsockopt(fd, level, optname, &(_flag), sizeof(int)) < 0) { \ + tmate_warn("setsockopt(" #level ", " #optname ", %d) failed", val); \ + } \ +}) + + SSO(IPPROTO_TCP, TCP_NODELAY, 1); + SSO(SOL_SOCKET, SO_KEEPALIVE, 1); +#ifdef TCP_KEEPALIVE + SSO(IPPROTO_TCP, TCP_KEEPALIVE, KEEPALIVE_IDLE); +#endif +#ifdef TCP_KEEPCNT + SSO(IPPROTO_TCP, TCP_KEEPCNT, KEEPALIVE_CNT); +#endif +#ifdef TCP_KEEPIDLE + SSO(IPPROTO_TCP, TCP_KEEPIDLE, KEEPALIVE_IDLE); +#endif +#ifdef TCP_KEEPINTVL + SSO(IPPROTO_TCP, TCP_KEEPINTVL, KEEPALIVE_INTVL); +#endif +#undef SSO +} + static void init_conn_fd(struct tmate_ssh_client *client) { + int fd; + if (client->has_init_conn_fd) return; - if (ssh_get_fd(client->session) < 0) + if ((fd = ssh_get_fd(client->session)) < 0) return; - { - int flag = 1; - setsockopt(ssh_get_fd(client->session), IPPROTO_TCP, - TCP_NODELAY, &flag, sizeof(flag)); - } - - event_set(&client->ev_ssh, ssh_get_fd(client->session), - EV_READ | EV_PERSIST, __on_ssh_client_event, client); + setup_socket(fd); + event_set(&client->ev_ssh, fd, EV_READ | EV_PERSIST, __on_ssh_client_event, client); event_add(&client->ev_ssh, NULL); client->has_init_conn_fd = true; From 27169b7c076376718abf98f7a1a6b484bd579314 Mon Sep 17 00:00:00 2001 From: Nicolas Viennot Date: Sun, 5 Jun 2016 12:54:25 -0400 Subject: [PATCH 03/75] Add missing incldues for FreeBSD --- tmate-session.c | 1 + tmate-ssh-client.c | 1 + 2 files changed, 2 insertions(+) diff --git a/tmate-session.c b/tmate-session.c index b43a261b..8d647203 100644 --- a/tmate-session.c +++ b/tmate-session.c @@ -2,6 +2,7 @@ #include #include +#include #include #include diff --git a/tmate-ssh-client.c b/tmate-ssh-client.c index 8b78f5cc..f13db90a 100644 --- a/tmate-ssh-client.c +++ b/tmate-ssh-client.c @@ -1,4 +1,5 @@ #include +#include #include #include #include From b27f3bacc0308a86a5f3e3494bd0383cd7583971 Mon Sep 17 00:00:00 2001 From: Nicolas Viennot Date: Fri, 10 Jun 2016 18:00:50 -0400 Subject: [PATCH 04/75] Crash fix in search prev/next match Fixes #87 --- window-copy.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/window-copy.c b/window-copy.c index 3862a688..939d3e19 100644 --- a/window-copy.c +++ b/window-copy.c @@ -1054,6 +1054,11 @@ window_copy_search_up(struct window_pane *wp, const char *searchstr) int n, wrapped, wrapflag, cis; const char *ptr; +#ifdef TMATE + if (!searchstr) + return; +#endif + if (*searchstr == '\0') return; wrapflag = options_get_number(wp->window->options, "wrap-search"); @@ -1120,6 +1125,11 @@ window_copy_search_down(struct window_pane *wp, const char *searchstr) int n, wrapped, wrapflag, cis; const char *ptr; +#ifdef TMATE + if (!searchstr) + return; +#endif + if (*searchstr == '\0') return; wrapflag = options_get_number(wp->window->options, "wrap-search"); From 608763a41a2437a8d3e0e54482d0b5f3d1c1e686 Mon Sep 17 00:00:00 2001 From: Nicolas Viennot Date: Tue, 14 Jun 2016 13:46:15 -0400 Subject: [PATCH 05/75] Attempt to fix environment related crash Fixes #89 --- cmd-string.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cmd-string.c b/cmd-string.c index 757d4cdb..fdef4a82 100644 --- a/cmd-string.c +++ b/cmd-string.c @@ -307,6 +307,10 @@ cmd_string_variable(const char *s, size_t *p) free(buf); if (envent == NULL) return (xstrdup("")); +#ifdef TMATE + if (envent->value == NULL) + return (xstrdup("")); +#endif return (xstrdup(envent->value)); error: From 3f6c6d44472a5ccab0403ebf89fc59e7df58b6b2 Mon Sep 17 00:00:00 2001 From: Natanael Copa Date: Thu, 28 Sep 2017 10:28:42 +0000 Subject: [PATCH 06/75] Fix building with or without backtrace(3) backtrace(3) and execinfo.h are GNU extensions and may or may not be available, and they may be provided via libexecinfo. Fix detection of libexecinfo and allow building without any support of backtrace, in which case we let kernel create core dump. Fixes #116 #117 --- configure.ac | 5 +++++ tmate-debug.c | 10 ++++++++++ 2 files changed, 15 insertions(+) diff --git a/configure.ac b/configure.ac index 02d2872b..05c1c482 100644 --- a/configure.ac +++ b/configure.ac @@ -102,6 +102,7 @@ AC_CHECK_HEADERS( bitstring.h \ curses.h \ dirent.h \ + execinfo.h \ fcntl.h \ inttypes.h \ libutil.h \ @@ -121,9 +122,13 @@ AC_CHECK_HEADERS( # Look for library needed for flock. AC_SEARCH_LIBS(flock, bsd) +# Look for library needed for backtrace +AC_SEARCH_LIBS(backtrace, execinfo) + # Check for some functions that are replaced or omitted. AC_CHECK_FUNCS( [ \ + backtrace \ dirfd \ flock \ setproctitle \ diff --git a/tmate-debug.c b/tmate-debug.c index f1fd971f..f58efe0e 100644 --- a/tmate-debug.c +++ b/tmate-debug.c @@ -1,10 +1,19 @@ +#ifdef HAVE_EXECINFO_H #include +#endif #include #include #include #include #include "tmate.h" +#ifndef HAVE_BACKTRACE + +void tmate_print_stack_trace(void) {} +void tmate_catch_sigsegv(void) {} + +#else + #if DEBUG static int print_resolved_stack_frame(const char *frame) @@ -88,3 +97,4 @@ void tmate_catch_sigsegv(void) { signal(SIGSEGV, handle_sigsegv); } +#endif From 25f6a934cf498e32bd5e13ea9e03b6840ab7064d Mon Sep 17 00:00:00 2001 From: David Bishop Date: Tue, 23 Oct 2018 17:39:10 -0600 Subject: [PATCH 07/75] Update MAN page to properly reference tmate where applicable While there are still plenty of places where tmate uses tmux, including config files and environment variables, I have updated the various examples to use tmate where applicable. --- tmux.1 | 45 +++++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/tmux.1 b/tmux.1 index 776b6faf..b55b3682 100644 --- a/tmux.1 +++ b/tmux.1 @@ -15,13 +15,13 @@ .\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" .Dd $Mdocdate: March 25 2013 $ -.Dt TMUX 1 +.Dt TMATE 1 .Os .Sh NAME -.Nm tmux +.Nm tmate .Nd terminal multiplexer .Sh SYNOPSIS -.Nm tmux +.Nm tmate .Bk -words .Op Fl 2CluvV .Op Fl c Ar shell-command @@ -80,7 +80,7 @@ key strokes). .Nm may be reattached using: .Pp -.Dl $ tmux attach +.Dl $ tmate attach .Pp In .Nm , @@ -126,7 +126,9 @@ By default, loads the system configuration file from .Pa @SYSCONFDIR@/tmux.conf , if present, then looks for a user configuration file at -.Pa ~/.tmux.conf . +.Pa ~/.tmux.conf +and +.Pa ~/.tmate.conf . .Pp The configuration file is a set of .Nm @@ -167,7 +169,9 @@ directories are missing). .It Fl l Behave as a login shell. This flag currently has no effect and is for compatibility with other shells -when using tmux as a login shell. +when using +.Nm +as a login shell. .It Fl S Ar socket-path Specify a full alternative path to the server socket. If @@ -597,7 +601,7 @@ to be given as multiple arguments and executed directly (without This can avoid issues with shell quoting. For example: .Bd -literal -offset indent -$ tmux new-window vi /etc/passwd +$ tmate new-window vi /etc/passwd .Ed .Pp Will run @@ -616,7 +620,7 @@ bind-key F1 set-window-option force-width 81 Or if using .Xr sh 1 : .Bd -literal -offset indent -$ tmux bind-key F1 set-window-option force-width 81 +$ tmate bind-key F1 set-window-option force-width 81 .Ed .Pp Multiple commands may be specified together as part of a @@ -648,11 +652,11 @@ bind-key R source-file ~/.tmux.conf \e; \e Or from .Xr sh 1 : .Bd -literal -offset indent -$ tmux kill-window -t :1 +$ tmate kill-window -t :1 -$ tmux new-window \e; split-window -d +$ tmate new-window \e; split-window -d -$ tmux new-session -d 'vi /etc/passwd' \e; split-window -d \e; attach +$ tmate new-session -d 'vi /etc/passwd' \e; split-window -d \e; attach .Ed .Sh CLIENTS AND SESSIONS The @@ -1236,10 +1240,10 @@ command displays the layout of each window in a form suitable for use with .Ic select-layout . For example: .Bd -literal -offset indent -$ tmux list-windows +$ tmate list-windows 0: ksh [159x48] layout: bb62,159x48,0,0{79x48,0,0,79x48,80,0} -$ tmux select-layout bb62,159x48,0,0{79x48,0,0,79x48,80,0} +$ tmate select-layout bb62,159x48,0,0{79x48,0,0,79x48,80,0} .Ed .Pp .Nm @@ -2307,8 +2311,8 @@ User options may have any name, so long as they are prefixed with and be set to any string. For example: .Bd -literal -offset indent -$ tmux setw -q @foo "abc123" -$ tmux showw -v @foo +$ tmate setw -q @foo "abc123" +$ tmate showw -v @foo abc123 .Ed .Pp @@ -2394,7 +2398,8 @@ to work correctly, this .Em must be set to .Ql screen , -.Ql tmux +.Ql tmux , +.Ql tmate or a derivative of them. .It Ic escape-time Ar time Set the time in milliseconds for which @@ -4172,18 +4177,18 @@ To create a new session running .Xr vi 1 : .Pp -.Dl $ tmux new-session vi +.Dl $ tmate new-session vi .Pp Most commands have a shorter form, known as an alias. For new-session, this is .Ic new : .Pp -.Dl $ tmux new vi +.Dl $ tmate new vi .Pp Alternatively, the shortest unambiguous form of a command is accepted. If there are several options, they are listed: .Bd -literal -offset indent -$ tmux n +$ tmate n ambiguous command: n, could be: new-session, new-window, next-window .Ed .Pp @@ -4213,7 +4218,7 @@ A session may be detached using .Xr ssh 1 disconnection) and reattached with: .Pp -.Dl $ tmux attach-session +.Dl $ tmate attach-session .Pp Typing .Ql C-b \&? From 2ffcbbd18508d6fdb28660ee2e8826acc5899a12 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Wed, 20 Mar 2019 19:05:49 +0100 Subject: [PATCH 08/75] ssh-client: Use SHA256 finger prints Signed-off-by: Andreas Schneider --- options-table.c | 4 ++-- tmate-ssh-client.c | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/options-table.c b/options-table.c index 6b0c248b..90d3297b 100644 --- a/options-table.c +++ b/options-table.c @@ -925,13 +925,13 @@ const struct options_table_entry options_table[] = { { .name = "tmate-server-rsa-fingerprint", .type = OPTIONS_TABLE_STRING, .scope = OPTIONS_TABLE_SERVER, - .default_str = "af:2d:81:c1:fe:49:70:2d:7f:09:a9:d7:4b:32:e3:be" + .default_str = "SHA256:Hthk2T/M/Ivqfk1YYUn5ijC2Att3+UPzD7Rn72P5VWs" }, { .name = "tmate-server-ecdsa-fingerprint", .type = OPTIONS_TABLE_STRING, .scope = OPTIONS_TABLE_SERVER, - .default_str = "c7:a1:51:36:d2:bb:35:4b:0a:1a:c0:43:97:74:ea:42" + .default_str = "SHA256:8GmKHYHEJ6n0TEdciHeEGkKOigQfCFuBULdt6vZIhDc" }, { .name = "tmate-display-time", diff --git a/tmate-ssh-client.c b/tmate-ssh-client.c index f13db90a..fbe9a470 100644 --- a/tmate-ssh-client.c +++ b/tmate-ssh-client.c @@ -287,12 +287,14 @@ static void on_ssh_client_event(struct tmate_ssh_client *client) if (ssh_get_publickey(session, &pubkey) < 0) tmate_fatal("ssh_get_publickey"); - if (ssh_get_publickey_hash(pubkey, SSH_PUBLICKEY_HASH_MD5, &hash, &hash_len) < 0) { + if (ssh_get_publickey_hash(pubkey, SSH_PUBLICKEY_HASH_SHA256, + &hash, &hash_len) < 0) { kill_ssh_client(client, "Cannot authenticate server"); return; } - hash_str = ssh_get_hexa(hash, hash_len); + hash_str = ssh_get_fingerprint_hash(SSH_PUBLICKEY_HASH_SHA256, + hash, hash_len); if (!hash_str) tmate_fatal("malloc failed"); From b645ce15cb1b64183a002e82112f2ac4830cd693 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Wed, 20 Mar 2019 19:06:18 +0100 Subject: [PATCH 09/75] ssh-client: Add support for ed25519 keys Signed-off-by: Andreas Schneider --- options-table.c | 6 ++++++ tmate-ssh-client.c | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/options-table.c b/options-table.c index 90d3297b..a44f9445 100644 --- a/options-table.c +++ b/options-table.c @@ -934,6 +934,12 @@ const struct options_table_entry options_table[] = { .default_str = "SHA256:8GmKHYHEJ6n0TEdciHeEGkKOigQfCFuBULdt6vZIhDc" }, + { .name = "tmate-server-ed25519-fingerprint", + .type = OPTIONS_TABLE_STRING, + .scope = OPTIONS_TABLE_SERVER, + .default_str = "" + }, + { .name = "tmate-display-time", .type = OPTIONS_TABLE_NUMBER, .scope = OPTIONS_TABLE_SESSION, diff --git a/tmate-ssh-client.c b/tmate-ssh-client.c index fbe9a470..bdad138d 100644 --- a/tmate-ssh-client.c +++ b/tmate-ssh-client.c @@ -309,6 +309,10 @@ static void on_ssh_client_event(struct tmate_ssh_client *client) server_hash_str = options_get_string(global_options, "tmate-server-ecdsa-fingerprint"); break; + case SSH_KEYTYPE_ED25519: + server_hash_str = options_get_string(global_options, + "tmate-server-ed25519-fingerprint"); + break; default: server_hash_str = ""; } From b01c6ecebde69726b330c3d2c5ba0fa757dc6447 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Wed, 20 Mar 2019 19:12:33 +0100 Subject: [PATCH 10/75] configure: Require libssh >= 0.8.4 Signed-off-by: Andreas Schneider --- configure.ac | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 05c1c482..8c6c5b98 100644 --- a/configure.ac +++ b/configure.ac @@ -214,7 +214,7 @@ fi PKG_CHECK_MODULES( LIBSSH, - libssh >= 0.6.0, + libssh >= 0.8.4, [ CPPFLAGS="$LIBSSH_CFLAGS $CPPFLAGS" LIBS="$LIBSSH_LIBS $LIBS" @@ -223,7 +223,7 @@ PKG_CHECK_MODULES( found_libssh=no ) if test "x$found_libssh" = xno; then - AC_MSG_ERROR("libssh >= 0.6.0 not found") + AC_MSG_ERROR("libssh >= 0.8.4 not found") fi # Check for b64_ntop. From 32d48cbc9df07045af43e0e8d76bd7a58647cce1 Mon Sep 17 00:00:00 2001 From: Nicolas Viennot Date: Sun, 7 Apr 2019 10:20:22 -0400 Subject: [PATCH 11/75] Update ed25519 server key (not yet in production) --- options-table.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/options-table.c b/options-table.c index a44f9445..4966431c 100644 --- a/options-table.c +++ b/options-table.c @@ -937,7 +937,7 @@ const struct options_table_entry options_table[] = { { .name = "tmate-server-ed25519-fingerprint", .type = OPTIONS_TABLE_STRING, .scope = OPTIONS_TABLE_SERVER, - .default_str = "" + .default_str = "SHA256:jfttvoypkHiQYUqUCwKeqd9d1fJj/ZiQlFOHVl6E9sI" }, { .name = "tmate-display-time", From fd4ac27d59604aae0117ad578b1a7e6dccf97bf7 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Wed, 20 Mar 2019 19:17:46 +0100 Subject: [PATCH 12/75] ssh-client: Don't use keys from the ssh-agent Fixes #138 Signed-off-by: Andreas Schneider --- tmate-ssh-client.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tmate-ssh-client.c b/tmate-ssh-client.c index bdad138d..96da14c8 100644 --- a/tmate-ssh-client.c +++ b/tmate-ssh-client.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include @@ -260,6 +261,9 @@ static void on_ssh_client_event(struct tmate_ssh_client *client) * regular one doesn't. */ ssh_options_set(session, SSH_OPTIONS_IDENTITY, identity); + + /* Do not use keys from ssh-agent. */ + unsetenv("SSH_AUTH_SOCK"); free(identity); } From 299c7c670c3d56ad6eaf73618dcf0c3c5d6fa2ec Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Tue, 30 Jul 2019 08:15:59 +0200 Subject: [PATCH 13/75] add new channel after authentication With libssh commit 8a885f0b ("channels: Add check if we are authenticated before we create a channel") connection fails if channel is added before successful authentication. So add the channel after authentication. Fixes #154 --- tmate-ssh-client.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tmate-ssh-client.c b/tmate-ssh-client.c index 96da14c8..2a9afee0 100644 --- a/tmate-ssh-client.c +++ b/tmate-ssh-client.c @@ -241,12 +241,6 @@ static void on_ssh_client_event(struct tmate_ssh_client *client) ssh_set_callbacks(session, &client->ssh_callbacks); - client->channel = channel = ssh_channel_new(session); - if (!channel) { - tmate_fatal("cannot initialize"); - return; - } - ssh_set_blocking(session, 0); ssh_options_set(session, SSH_OPTIONS_HOST, client->server_ip); ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity); @@ -370,6 +364,12 @@ static void on_ssh_client_event(struct tmate_ssh_client *client) case SSH_AUTH_SUCCESS: tmate_debug("Auth successful"); client->state = SSH_OPEN_CHANNEL; + + client->channel = channel = ssh_channel_new(session); + if (!channel) { + tmate_fatal("cannot initialize"); + return; + } /* fall through */ } From e25ab3cc8bb4d42b137625b376d677707bc4fbe2 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Tue, 30 Jul 2019 14:48:37 +0200 Subject: [PATCH 14/75] ssh-client: Add missing ecdsa keytypes of libssh 0.9 --- tmate-ssh-client.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tmate-ssh-client.c b/tmate-ssh-client.c index 2a9afee0..943ebf49 100644 --- a/tmate-ssh-client.c +++ b/tmate-ssh-client.c @@ -218,7 +218,7 @@ static void on_ssh_client_event(struct tmate_ssh_client *client) { char *identity; ssh_key pubkey; - int key_type; + enum ssh_keytypes_e key_type; unsigned char *hash; ssize_t hash_len; char *hash_str; @@ -304,6 +304,11 @@ static void on_ssh_client_event(struct tmate_ssh_client *client) "tmate-server-rsa-fingerprint"); break; case SSH_KEYTYPE_ECDSA: +#if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0, 9, 0) + case SSH_KEYTYPE_ECDSA_P256: + case SSH_KEYTYPE_ECDSA_P384: + case SSH_KEYTYPE_ECDSA_P521: +#endif server_hash_str = options_get_string(global_options, "tmate-server-ecdsa-fingerprint"); break; From 4e7caeb536629fc4ddc4d413ca867f754b1257c3 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Tue, 30 Jul 2019 15:37:35 +0200 Subject: [PATCH 15/75] ssh-client: Use ssh_get_server_publickey() if possible --- tmate-ssh-client.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tmate-ssh-client.c b/tmate-ssh-client.c index 943ebf49..c5fb4243 100644 --- a/tmate-ssh-client.c +++ b/tmate-ssh-client.c @@ -282,8 +282,13 @@ static void on_ssh_client_event(struct tmate_ssh_client *client) } case SSH_AUTH_SERVER: +#if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0, 9, 0) + if (ssh_get_server_publickey(session, &pubkey) < 0) + tmate_fatal("ssh_get_server_publickey"); +#else if (ssh_get_publickey(session, &pubkey) < 0) tmate_fatal("ssh_get_publickey"); +#endif if (ssh_get_publickey_hash(pubkey, SSH_PUBLICKEY_HASH_SHA256, &hash, &hash_len) < 0) { From 3e5d919b14e8f5c6aa703e45092247c4a737194e Mon Sep 17 00:00:00 2001 From: Nicolas Viennot Date: Wed, 31 Jul 2019 21:02:18 -0400 Subject: [PATCH 16/75] Bump to version 2.3.0 --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 8c6c5b98..647ae333 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ # configure.ac -AC_INIT(tmate, 2.2.1) +AC_INIT(tmate, 2.3.0) AC_CONFIG_AUX_DIR(etc) AM_INIT_AUTOMAKE([foreign subdir-objects]) From d654ff22194bde5fc6e02b2f93ae55cb69c4ddcc Mon Sep 17 00:00:00 2001 From: Nicolas Viennot Date: Wed, 18 Sep 2019 23:35:07 -0400 Subject: [PATCH 17/75] Send TMATE_READY message when the config files are done loading This fixes bug where webhooks are not registering correctly, leading to a disconnect and reconnect. --- server.c | 4 ---- tmate-session.c | 1 + 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/server.c b/server.c index 81334f1e..a2378959 100644 --- a/server.c +++ b/server.c @@ -205,10 +205,6 @@ server_start(struct event_base *base, int lockfd, char *lockfile) status_prompt_load_history(); -#ifdef TMATE - tmate_write_ready(); -#endif - server_add_accept(0); proc_loop(server_proc, server_loop); diff --git a/tmate-session.c b/tmate-session.c index 8d647203..106687e1 100644 --- a/tmate-session.c +++ b/tmate-session.c @@ -138,6 +138,7 @@ void tmate_session_start(void) * - While we are parsing the config file, we need to be able to * serialize it, and so we need a worker encoder. */ + tmate_write_ready(); lookup_and_connect(); } From 44635e752d17993943885c1e77864f5395d740f6 Mon Sep 17 00:00:00 2001 From: Nicolas Viennot Date: Sat, 12 Oct 2019 13:50:27 -0400 Subject: [PATCH 18/75] Use docker to build static releases Static builds are possible with the musl C library. glibc is capricious when it comes to static linking and DNS support (and other things). --- Dockerfile | 27 +++++++++++++++++++ Makefile.static-build | 61 ------------------------------------------ compat/clock_gettime.c | 9 ------- compat/memcpy.c | 11 -------- configure.ac | 15 ++--------- 5 files changed, 29 insertions(+), 94 deletions(-) create mode 100644 Dockerfile delete mode 100644 Makefile.static-build delete mode 100644 compat/clock_gettime.c delete mode 100644 compat/memcpy.c diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..82d75ef4 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,27 @@ +FROM alpine:3.10 + +WORKDIR /build + +RUN apk add --no-cache wget cmake make gcc g++ linux-headers zlib-dev openssl-dev \ + automake autoconf libevent-dev ncurses-dev msgpack-c-dev libexecinfo-dev \ + ncurses-static libexecinfo-static libevent-static msgpack-c ncurses-libs \ + libevent libexecinfo openssl zlib + +RUN set -ex; \ + mkdir -p /src/libssh/build; \ + cd /src; \ + wget -O libssh.tar.xz https://www.libssh.org/files/0.9/libssh-0.9.0.tar.xz; \ + tar -xf libssh.tar.xz -C /src/libssh --strip-components=1; \ + cd /src/libssh/build; \ + cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr \ + -DWITH_SFTP=OFF -DWITH_SERVER=OFF -DWITH_PCAP=OFF \ + -DWITH_STATIC_LIB=ON -DWITH_GSSAPI=OFF ..; \ + make -j $(nproc); \ + make install + +COPY . . + +RUN ./autogen.sh +RUN ./configure --enable-static +RUN make -j $(nproc) +RUN strip tmate diff --git a/Makefile.static-build b/Makefile.static-build deleted file mode 100644 index 9bc83d92..00000000 --- a/Makefile.static-build +++ /dev/null @@ -1,61 +0,0 @@ -LIBSSH=libssh-0.7.2 -LIBSSH_URL=https://red.libssh.org/attachments/download/177/$(LIBSSH).tar.xz -LIBSSH_LIB=ext/lib/libssh.a - -MSGPACK=msgpack-1.3.0 -MSGPACK_URL=https://github.com/msgpack/msgpack-c/releases/download/cpp-1.3.0/$(MSGPACK).tar.gz -MSGPACK_LIB=ext/lib/libmsgpack.a - -TMATE_CONFIGURE=PKG_CONFIG_PATH=./ext/lib/pkgconfig - -LIBC=$(shell gcc -print-file-name=libc.a) -STATIC_LIBC_OBJECTS=fdelt_chk -STATIC_COMPAT_OBJECTS=memcpy clock_gettime - -all: tmate - -dependencies: - apt-get install build-essential cmake libssl-dev autoconf automake pkg-config libtool libevent-dev libncurses-dev zlib1g-dev - -downloads/$(notdir $(LIBSSH_URL)): - mkdir -p downloads - wget -O $@ $(LIBSSH_URL) - -$(LIBSSH)/.ready: downloads/$(notdir $(LIBSSH_URL)) - tar xf $< - touch $@ - -downloads/$(notdir $(MSGPACK_URL)): - mkdir -p downloads - wget -O $@ $(MSGPACK_URL) - -$(MSGPACK)/.ready: downloads/$(notdir $(MSGPACK_URL)) - tar xf $< - touch $@ - -$(LIBSSH_LIB): $(LIBSSH)/.ready - mkdir -p $(LIBSSH)/build - cd $(LIBSSH)/build; ([ -f Makefile ] || cmake -DCMAKE_INSTALL_PREFIX:PATH=$(shell pwd)/ext .. -DWITH_SFTP=OFF -DWITH_SERVER=OFF -DWITH_PCAP=OFF -DWITH_STATIC_LIB=ON -DWITH_GSSAPI=OFF) - +make -C $(LIBSSH)/build install - -$(MSGPACK_LIB): $(MSGPACK)/.ready - mkdir -p $(MSGPACK)/build - cd $(MSGPACK)/build; ([ -f Makefile ] || cmake -DCMAKE_INSTALL_PREFIX:PATH=$(shell pwd)/ext ..) - +make -C $(MSGPACK)/build install - -libc/%.o: - mkdir -p libc - cd libc; ar x $(LIBC) $(notdir $@) - -compat/%.o: compat/%.c - gcc -c -o $@ $< - -tmate: $(MSGPACK_LIB) $(LIBSSH_LIB) $(patsubst %,libc/%.o,$(STATIC_LIBC_OBJECTS)) $(patsubst %,compat/%.o,$(STATIC_COMPAT_OBJECTS)) - ./autogen.sh - $(TMATE_CONFIGURE) ./configure --enable-static - +make - strip tmate - -clean: - rm -rf ext libc $(LIBSSH) $(MSGPACK) - +make clean diff --git a/compat/clock_gettime.c b/compat/clock_gettime.c deleted file mode 100644 index 0b631b79..00000000 --- a/compat/clock_gettime.c +++ /dev/null @@ -1,9 +0,0 @@ -#define _GNU_SOURCE -#include -#include -#include - -int clock_gettime(clockid_t clk_id, struct timespec *tp) -{ - return syscall(SYS_clock_gettime, clk_id, tp); -} diff --git a/compat/memcpy.c b/compat/memcpy.c deleted file mode 100644 index 37092a33..00000000 --- a/compat/memcpy.c +++ /dev/null @@ -1,11 +0,0 @@ -// http://stackoverflow.com/questions/8823267/linking-against-older-symbol-version-in-a-so-file - -#include - -/* some systems do not have newest memcpy@@GLIBC_2.14 - stay with old good one */ -asm (".symver memcpy, memcpy@GLIBC_2.2.5"); - -void *__wrap_memcpy(void *dest, const void *src, size_t n) -{ - return memcpy(dest, src, n); -} diff --git a/configure.ac b/configure.ac index 647ae333..2681300a 100644 --- a/configure.ac +++ b/configure.ac @@ -47,10 +47,11 @@ AC_ARG_ENABLE( found_static=$enable_static ) if test "x$found_static" = xyes; then + # XXX Static build are only doable with the musl library PKG_CONFIG="pkg-config --static" CFLAGS="$CFLAGS -flto" - LDFLAGS="$LDFLAGS -flto" + LDFLAGS="$LDFLAGS -flto -static -no-pie" PKG_CHECK_MODULES([ZLIB], [zlib], [ CPPFLAGS="$ZLIB_CFLAGS $CPPFLAGS" @@ -61,7 +62,6 @@ if test "x$found_static" = xyes; then CPPFLAGS="$LIBCRYPTO_CFLAGS $CPPFLAGS" LIBS="$LIBCRYPTO_LIBS $LIBS" ]) - # See more static settings below... (search for found_static) fi # Is this gcc? @@ -462,17 +462,6 @@ if test "x$found_getopt" != xno; then fi AM_CONDITIONAL(NO_GETOPT, [test "x$found_getopt" = xno]) -if test "x$found_static" = xyes; then - # libc and libdl should be dynamically linked. - # but we want to lower our requirements for libc's version. - # so we extract some symobls and add them here - if test `uname -m` = x86_64; then - LIBS="compat/memcpy.o -Wl,--wrap=memcpy $LIBS" - fi - LIBS="compat/clock_gettime.o libc/fdelt_chk.o $LIBS" - LIBS="-Wl,-Bstatic ${LIBS/-ldl/} -Wl,-Bdynamic -ldl" -fi - # Check for BSD-style integer types. AC_MSG_CHECKING(for BSD-style unsigned types) AC_COMPILE_IFELSE([AC_LANG_SOURCE( From 74ff5229830afcca8cd57976a48632fef6f85c17 Mon Sep 17 00:00:00 2001 From: Nicolas Viennot Date: Sat, 12 Oct 2019 14:13:12 -0400 Subject: [PATCH 19/75] Build static build releases on travis-ci --- .travis.yml | 42 ++++++++++++++++++++++++++++++++++-------- Dockerfile | 27 ++++++++++++++------------- package_release.sh | 14 ++++++++++++++ 3 files changed, 62 insertions(+), 21 deletions(-) create mode 100755 package_release.sh diff --git a/.travis.yml b/.travis.yml index a1d7e427..a02e89a8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,36 @@ language: c +services: +- docker + matrix: - include: - - compiler: gcc - - compiler: clang - env: CFLAGS="-g -O2" -before_install: - - sudo apt-get update -qq - - sudo apt-get -y install debhelper autotools-dev dh-autoreconf file libncurses5-dev libevent-dev pkg-config libutempter-dev build-essential -script: (CFLAGS= ./autogen.sh) && ./configure --enable-debug && make + include: + - arch: amd64 + env: PLATFORM=amd64 + - arch: amd64 + env: PLATFORM=i386 + - arch: arm64 + env: PLATFORM=arm32v6 + - arch: arm64 + env: PLATFORM=arm32v7 + - arch: arm64 + env: PLATFORM=arm64v8 + +script: +- 'docker build . --tag local-$PLATFORM/tmate-build --build-arg PLATFORM=$PLATFORM' +# On arch=arm64, some directories are not setup correctly, and 'ruby -S gem +# install dpl' required by the release push scripts fails. +- 'if [ "$TRAVIS_TAG" ]; then sudo chown -R $USER: /var/lib/gems /usr/local/bin; fi' +- 'if [ "$TRAVIS_TAG" ]; then ./package_release.sh $TRAVIS_TAG $PLATFORM; fi' + +deploy: + provider: releases + api_key: + secure: T2109tjjOsrVLEpJZK/uxmO0AuDGXYFdN4AAsNTmVwu/W5dcX57Kk2TCgqDuLfD21iGGXP0U/OYHM06IfBDODBWCA9P8ASHYsenS7wIiFnvCEMbfzoAFyBMrXN2kNdM2+ho3aqc0xE2lQKOKDLxpGm5FZrzujscXXzxQjWBU5Hk= + skip_cleanup: true + overwrite: true + file_glob: true + file: /tmp/tmate-release/*.tar.* + on: + repo: tmate-io/tmate + branch: master + tags: true diff --git a/Dockerfile b/Dockerfile index 82d75ef4..c7aa2b9f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,5 @@ -FROM alpine:3.10 +ARG PLATFORM=amd64 +FROM ${PLATFORM}/alpine:3.10 WORKDIR /build @@ -8,20 +9,20 @@ RUN apk add --no-cache wget cmake make gcc g++ linux-headers zlib-dev openssl-de libevent libexecinfo openssl zlib RUN set -ex; \ - mkdir -p /src/libssh/build; \ - cd /src; \ - wget -O libssh.tar.xz https://www.libssh.org/files/0.9/libssh-0.9.0.tar.xz; \ - tar -xf libssh.tar.xz -C /src/libssh --strip-components=1; \ - cd /src/libssh/build; \ - cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr \ - -DWITH_SFTP=OFF -DWITH_SERVER=OFF -DWITH_PCAP=OFF \ - -DWITH_STATIC_LIB=ON -DWITH_GSSAPI=OFF ..; \ - make -j $(nproc); \ - make install + mkdir -p /src/libssh/build; \ + cd /src; \ + wget -O libssh.tar.xz https://www.libssh.org/files/0.9/libssh-0.9.0.tar.xz; \ + tar -xf libssh.tar.xz -C /src/libssh --strip-components=1; \ + cd /src/libssh/build; \ + cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr \ + -DWITH_SFTP=OFF -DWITH_SERVER=OFF -DWITH_PCAP=OFF \ + -DWITH_STATIC_LIB=ON -DWITH_GSSAPI=OFF ..; \ + make -j $(nproc); \ + make install COPY . . -RUN ./autogen.sh -RUN ./configure --enable-static +RUN ./autogen.sh && ./configure --enable-static RUN make -j $(nproc) RUN strip tmate +RUN ./tmate -V diff --git a/package_release.sh b/package_release.sh new file mode 100755 index 00000000..f4186e3c --- /dev/null +++ b/package_release.sh @@ -0,0 +1,14 @@ +#!/bin/bash +set -eux +VERSION=$1 +PLATFORM=$2 +RELEASE_NAME=tmate-$VERSION-static-linux-$PLATFORM + +# This assumes the follow command has already been run: +# docker build . --tag local-$PLATFORM/tmate-build --build-arg PLATFORM=$PLATFORM + +mkdir -p /tmp/tmate-release/$RELEASE_NAME +cd /tmp/tmate-release +docker run --rm local-$PLATFORM/tmate-build cat tmate > $RELEASE_NAME/tmate +chmod +x $RELEASE_NAME/tmate +tar -cf - $RELEASE_NAME | xz > tmate-$VERSION-static-linux-$PLATFORM.tar.xz From 7153958e9908658383438745592d9a8da64b2a3f Mon Sep 17 00:00:00 2001 From: Nicolas Viennot Date: Sat, 12 Oct 2019 21:09:39 -0400 Subject: [PATCH 20/75] Allow the use of C.UTF-8 locale --- tmux.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tmux.c b/tmux.c index d55c2e1d..d7cf8d97 100644 --- a/tmux.c +++ b/tmux.c @@ -205,12 +205,12 @@ main(int argc, char **argv) const char *s; int opt, flags, keys; - if (setlocale(LC_CTYPE, "en_US.UTF-8") == NULL) { + if (setlocale(LC_CTYPE, "en_US.UTF-8") == NULL && + setlocale(LC_CTYPE, "C.UTF-8") == NULL) { if (setlocale(LC_CTYPE, "") == NULL) errx(1, "invalid LC_ALL, LC_CTYPE or LANG"); s = nl_langinfo(CODESET); - if (strcasecmp(s, "UTF-8") != 0 && - strcasecmp(s, "UTF8") != 0) + if (strcasecmp(s, "UTF-8") != 0 && strcasecmp(s, "UTF8") != 0) errx(1, "need UTF-8 locale (LC_CTYPE) but have %s", s); } From 7262aead737af678923ae7b9209ae220b0f915b9 Mon Sep 17 00:00:00 2001 From: Nicolas Viennot Date: Sat, 12 Oct 2019 19:29:48 -0400 Subject: [PATCH 21/75] Bump to version 2.3.1 --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 2681300a..f623cadc 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ # configure.ac -AC_INIT(tmate, 2.3.0) +AC_INIT(tmate, 2.3.1) AC_CONFIG_AUX_DIR(etc) AM_INIT_AUTOMAKE([foreign subdir-objects]) From 4efe25d91d5c5de0fcb4df2cf9199a96b13afd66 Mon Sep 17 00:00:00 2001 From: Nicolas Viennot Date: Tue, 15 Oct 2019 03:04:24 -0400 Subject: [PATCH 22/75] During SSH authentication, try the none auth method first --- tmate-ssh-client.c | 44 ++++++++++++++++++++++++++++++++------------ tmate.h | 4 +++- 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/tmate-ssh-client.c b/tmate-ssh-client.c index c5fb4243..e33f4b17 100644 --- a/tmate-ssh-client.c +++ b/tmate-ssh-client.c @@ -235,7 +235,7 @@ static void on_ssh_client_event(struct tmate_ssh_client *client) case SSH_INIT: client->session = session = ssh_new(); if (!session) { - tmate_fatal("cannot initialize"); + tmate_fatal("cannot ssh_new()"); return; } @@ -344,13 +344,30 @@ static void on_ssh_client_event(struct tmate_ssh_client *client) */ tmate_debug("Connected to %s", client->server_ip); on_ssh_auth_server_complete(client); - client->state = SSH_AUTH_CLIENT; + client->state = SSH_AUTH_CLIENT_NONE; /* fall through */ - case SSH_AUTH_CLIENT: + case SSH_AUTH_CLIENT_NONE: + switch (ssh_userauth_none(session, NULL)) { + case SSH_AUTH_AGAIN: + return; + case SSH_AUTH_ERROR: + kill_ssh_client(client, "Auth error: %s", ssh_get_error(session)); + return; + case SSH_AUTH_SUCCESS: + tmate_debug("Auth successful via none method"); + client->state = SSH_NEW_CHANNEL; + goto SSH_NEW_CHANNEL; + case SSH_AUTH_PARTIAL: + case SSH_AUTH_DENIED: + client->state = SSH_AUTH_CLIENT_PUBKEY; + /* fall through */ + } + + case SSH_AUTH_CLIENT_PUBKEY: client->tried_passphrase = client->tmate_session->passphrase; - switch (ssh_userauth_autopubkey(session, client->tried_passphrase)) { + switch (ssh_userauth_publickey_auto(session, NULL, client->tried_passphrase)) { case SSH_AUTH_AGAIN: return; case SSH_AUTH_PARTIAL: @@ -372,17 +389,20 @@ static void on_ssh_client_event(struct tmate_ssh_client *client) kill_ssh_client(client, "Auth error: %s", ssh_get_error(session)); return; case SSH_AUTH_SUCCESS: - tmate_debug("Auth successful"); - client->state = SSH_OPEN_CHANNEL; - - client->channel = channel = ssh_channel_new(session); - if (!channel) { - tmate_fatal("cannot initialize"); - return; - } + tmate_debug("Auth successful with pubkey"); + client->state = SSH_NEW_CHANNEL; /* fall through */ } +SSH_NEW_CHANNEL: + case SSH_NEW_CHANNEL: + client->channel = channel = ssh_channel_new(session); + if (!channel) { + tmate_fatal("cannot ssh_channel_new()"); + return; + } + client->state = SSH_OPEN_CHANNEL; + case SSH_OPEN_CHANNEL: switch (ssh_channel_open_session(channel)) { case SSH_AGAIN: diff --git a/tmate.h b/tmate.h index f096a35c..7deb0ba6 100644 --- a/tmate.h +++ b/tmate.h @@ -106,7 +106,9 @@ enum tmate_ssh_client_state_types { SSH_INIT, SSH_CONNECT, SSH_AUTH_SERVER, - SSH_AUTH_CLIENT, + SSH_AUTH_CLIENT_NONE, + SSH_AUTH_CLIENT_PUBKEY, + SSH_NEW_CHANNEL, SSH_OPEN_CHANNEL, SSH_BOOTSTRAP, SSH_READY, From 7f693a97aede385aad30db1412c48f0093b72509 Mon Sep 17 00:00:00 2001 From: Nicolas Viennot Date: Sun, 20 Oct 2019 21:23:48 -0400 Subject: [PATCH 23/75] Add options for customizing session names (WIP) --- options-table.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/options-table.c b/options-table.c index 4966431c..617ba05e 100644 --- a/options-table.c +++ b/options-table.c @@ -959,6 +959,24 @@ const struct options_table_entry options_table[] = { .scope = OPTIONS_TABLE_SERVER, .default_str = "" }, + + { .name = "tmate-account-key", + .type = OPTIONS_TABLE_STRING, + .scope = OPTIONS_TABLE_SERVER, + .default_str = "" + }, + + { .name = "tmate-session-name", + .type = OPTIONS_TABLE_STRING, + .scope = OPTIONS_TABLE_SERVER, + .default_str = "" + }, + + { .name = "tmate-session-name-ro", + .type = OPTIONS_TABLE_STRING, + .scope = OPTIONS_TABLE_SERVER, + .default_str = "" + }, #endif { .name = NULL } From 6e84bab68ca80f90023d4336467a44098d17a06f Mon Sep 17 00:00:00 2001 From: Nicolas Viennot Date: Sun, 3 Nov 2019 05:11:37 -0500 Subject: [PATCH 24/75] Add foreground mode with -F --- cfg.c | 18 ++++++++++++++++ client.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++ cmd-new-session.c | 3 +++ log.c | 49 +++++++++++++++++++++++++++++++------------- proc.c | 10 +++++++-- server.c | 14 ++++++++++--- session.c | 21 +++++++++++++++---- signal.c | 18 ++++++++++++++++ tmate-msg.c | 2 +- tmate-session.c | 2 +- tmate-ssh-client.c | 14 +++++++------ tmate.h | 7 +++---- tmux.c | 13 ++++++++++-- tmux.h | 12 ++++++++++- 14 files changed, 196 insertions(+), 38 deletions(-) diff --git a/cfg.c b/cfg.c index 572f8369..68894cb2 100644 --- a/cfg.c +++ b/cfg.c @@ -149,6 +149,20 @@ load_cfg(const char *path, struct cmd_q *cmdq, char **cause) return (found); } +static void print_cfg_errors(void) +{ + u_int i; + + for (i = 0; i < cfg_ncauses; i++) { + tmate_info("%s", cfg_causes[i]); + free(cfg_causes[i]); + } + + free(cfg_causes); + cfg_causes = NULL; + cfg_ncauses = 0; +} + void cfg_default_done(__unused struct cmd_q *cmdq) { @@ -158,6 +172,10 @@ cfg_default_done(__unused struct cmd_q *cmdq) #ifdef TMATE tmate_session_start(); + if (tmate_foreground && cfg_ncauses) { + print_cfg_errors(); + exit(1); + } #endif if (!RB_EMPTY(&sessions)) diff --git a/client.c b/client.c index 164abdd3..ad349972 100644 --- a/client.c +++ b/client.c @@ -32,6 +32,7 @@ #include #include "tmux.h" +#include "tmate.h" struct tmuxproc *client_proc; struct tmuxpeer *client_peer; @@ -213,8 +214,56 @@ client_exit_message(void) #ifdef TMATE extern const struct cmd_entry cmd_attach_session_entry; extern const struct cmd_entry cmd_new_session_entry; + +/* For foreground mode */ +static int __argc; +static char **__argv; #endif +static void _run_initial_client_cmd(int argc, char **argv) +{ + struct cmd_q *cmd_q; + struct cmd_list *cmdlist; + char *cause; + const char *default_argv[] = {"new-session"}; + + if (argc == 0) { + argc = 1; + argv = (char **)default_argv; + } + + cmd_q = cmdq_new(NULL); /* No client */ + + if ((cmdlist = cmd_list_parse(argc, (char **)argv, NULL, 0, &cause)) == NULL) { + tmate_fatal("%s", cause); + } + + cmdq_run(cmd_q, cmdlist, NULL); + cmd_list_free(cmdlist); + cmdq_free(cmd_q); + + /* error messages land in cfg_causes */ + extern char **cfg_causes; + extern u_int cfg_ncauses; + int has_error = !!cfg_ncauses; + for (u_int i = 0; i < cfg_ncauses; i++) { + tmate_info("%s", cfg_causes[i]); + free(cfg_causes[i]); + } + + free(cfg_causes); + cfg_causes = NULL; + cfg_ncauses = 0; + + if (has_error) + exit(1); +} + +void run_initial_client_cmd(void) +{ + _run_initial_client_cmd(__argc, __argv); +} + /* Client main loop. */ int client_main(struct event_base *base, int argc, char **argv, int flags, @@ -232,6 +281,8 @@ client_main(struct event_base *base, int argc, char **argv, int flags, size_t size; #ifdef TMATE int cant_nest = 0; + __argc = argc; + __argv = argv; #endif /* Ignore SIGCHLD now or daemon() in the server will leave a zombie. */ diff --git a/cmd-new-session.c b/cmd-new-session.c index 357ffed1..fb2f7eab 100644 --- a/cmd-new-session.c +++ b/cmd-new-session.c @@ -131,6 +131,9 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq) if (c == NULL) detached = 1; + if (tmate_foreground) + detached = 1; + /* Is this client already attached? */ already_attached = 0; if (c != NULL && c->session != NULL) diff --git a/log.c b/log.c index 018348cf..bc798778 100644 --- a/log.c +++ b/log.c @@ -32,6 +32,11 @@ static int log_level; static void log_event_cb(int, const char *); static void log_vwrite(const char *, va_list); +static int is_log_stdout(void) +{ + return fileno(log_file) <= 2; +} + /* Log callback for libevent. */ static void log_event_cb(__unused int severity, const char *msg) @@ -53,6 +58,18 @@ log_get_level(void) return (log_level); } +void +log_open_fp(FILE *f) +{ + if (log_file != NULL && !is_log_stdout()) + fclose(log_file); + + log_file = f; + + setvbuf(log_file, NULL, _IOLBF, 0); + event_set_log_callback(log_event_cb); +} + /* Open logging to file. */ void log_open(const char *name) @@ -62,24 +79,18 @@ log_open(const char *name) if (log_level == 0) return; - if (log_file != NULL) - fclose(log_file); - xasprintf(&path, "tmate-%s-%ld.log", name, (long)getpid()); - log_file = fopen(path, "w"); + FILE *f = fopen(path, "w"); free(path); - if (log_file == NULL) - return; - - setvbuf(log_file, NULL, _IOLBF, 0); - event_set_log_callback(log_event_cb); + if (f) + log_open_fp(f); } /* Close logging. */ void log_close(void) { - if (log_file != NULL) + if (log_file != NULL && !is_log_stdout()) fclose(log_file); log_file = NULL; @@ -102,9 +113,16 @@ log_vwrite(const char *msg, va_list ap) exit(1); gettimeofday(&tv, NULL); - if (fprintf(log_file, "%lld.%06d %s\n", (long long)tv.tv_sec, - (int)tv.tv_usec, out) == -1) - exit(1); + + if (is_log_stdout()) { + if (fprintf(log_file, "%s\n", out) == -1) + exit(1); + } else { + if (fprintf(log_file, "%lld.%06d %s\n", (long long)tv.tv_sec, + (int)tv.tv_usec, out) == -1) + exit(1); + } + fflush(log_file); free(out); @@ -113,10 +131,13 @@ log_vwrite(const char *msg, va_list ap) /* Log a debug message. */ void -log_debug(const char *msg, ...) +log_emit(int level, const char *msg, ...) { va_list ap; + if (log_level < level) + return; + va_start(ap, msg); log_vwrite(msg, ap); va_end(ap); diff --git a/proc.c b/proc.c index 27880f57..edd4a6f8 100644 --- a/proc.c +++ b/proc.c @@ -172,7 +172,7 @@ proc_start(const char *name, struct event_base *base, int forkflag, struct tmuxproc *tp; struct utsname u; - if (forkflag) { + if (forkflag && !tmate_foreground) { switch (fork()) { case -1: fatal("fork failed"); @@ -189,7 +189,13 @@ proc_start(const char *name, struct event_base *base, int forkflag, fatalx("event_reinit failed"); } - log_open(name); + if (tmate_foreground) { + if (forkflag) + clear_signals(0); + log_open_fp(stdout); + } else { + log_open(name); + } #ifdef HAVE_SETPROCTITLE setproctitle("%s (%s)", name, socket_path); diff --git a/server.c b/server.c index a2378959..05706769 100644 --- a/server.c +++ b/server.c @@ -152,14 +152,16 @@ server_start(struct event_base *base, int lockfd, char *lockfile) { int pair[2]; - if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pair) != 0) - fatal("socketpair failed"); + if (!tmate_foreground) + if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pair) != 0) + fatal("socketpair failed"); server_proc = proc_start("server", base, 1, server_signal); if (server_proc == NULL) { close(pair[1]); return (pair[0]); } + close(pair[0]); if (log_get_level() > 3) @@ -190,7 +192,8 @@ server_start(struct event_base *base, int lockfd, char *lockfile) if (server_fd == -1) fatal("couldn't create socket"); server_update_socket(); - server_client_create(pair[1]); + if (!tmate_foreground) + server_client_create(pair[1]); if (lockfd >= 0) { unlink(lockfile); @@ -207,11 +210,15 @@ server_start(struct event_base *base, int lockfd, char *lockfile) server_add_accept(0); + if (tmate_foreground) + run_initial_client_cmd(); + proc_loop(server_proc, server_loop); status_prompt_save_history(); #ifdef TMATE unlink(socket_path); #endif + exit(0); } @@ -361,6 +368,7 @@ server_signal(int sig) int fd; switch (sig) { + case SIGINT: case SIGTERM: server_exit = 1; server_send_exit(); diff --git a/session.c b/session.c index 5a3b867a..91fb9c1d 100644 --- a/session.c +++ b/session.c @@ -215,10 +215,6 @@ session_destroy(struct session *s) log_debug("session %s destroyed", s->name); -#ifdef TMATE - tmate_write_fin(); -#endif - RB_REMOVE(sessions, &sessions, s); notify_session_closed(s); @@ -240,6 +236,23 @@ session_destroy(struct session *s) free((void *)s->cwd); session_unref(s); + +#ifdef TMATE + if (tmate_foreground && !server_exit) { + tmate_info("Shell exited, restarting"); + /* + * throttle restarts. This is a blocking sleep. + * It's simpler than using a timer, but fairly harmless + * from a blocking perspective. + */ + usleep(500*1000); + next_session_id = 0; + run_initial_client_cmd(); + } else { + tmate_info("Session terminated"); + tmate_write_fin(); + } +#endif } /* Check a session name is valid: not empty and no colons or periods. */ diff --git a/signal.c b/signal.c index 19938638..f20a0257 100644 --- a/signal.c +++ b/signal.c @@ -24,6 +24,7 @@ #include "tmux.h" +struct event ev_sigint; struct event ev_sighup; struct event ev_sigchld; struct event ev_sigcont; @@ -40,15 +41,23 @@ set_signals(void (*handler)(int, short, void *), void *arg) sigemptyset(&sigact.sa_mask); sigact.sa_flags = SA_RESTART; sigact.sa_handler = SIG_IGN; +#ifndef TMATE if (sigaction(SIGINT, &sigact, NULL) != 0) fatal("sigaction failed"); +#endif if (sigaction(SIGPIPE, &sigact, NULL) != 0) fatal("sigaction failed"); if (sigaction(SIGUSR2, &sigact, NULL) != 0) fatal("sigaction failed"); +#ifndef TMATE if (sigaction(SIGTSTP, &sigact, NULL) != 0) fatal("sigaction failed"); +#endif +#ifdef TMATE + signal_set(&ev_sigint, SIGINT, handler, arg); + signal_add(&ev_sigint, NULL); +#endif signal_set(&ev_sighup, SIGHUP, handler, arg); signal_add(&ev_sighup, NULL); signal_set(&ev_sigchld, SIGCHLD, handler, arg); @@ -72,16 +81,24 @@ clear_signals(int after_fork) sigemptyset(&sigact.sa_mask); sigact.sa_flags = SA_RESTART; sigact.sa_handler = SIG_DFL; +#ifndef TMATE if (sigaction(SIGINT, &sigact, NULL) != 0) fatal("sigaction failed"); +#endif if (sigaction(SIGPIPE, &sigact, NULL) != 0) fatal("sigaction failed"); if (sigaction(SIGUSR2, &sigact, NULL) != 0) fatal("sigaction failed"); +#ifndef TMATE if (sigaction(SIGTSTP, &sigact, NULL) != 0) fatal("sigaction failed"); +#endif if (after_fork) { +#ifdef TMATE + if (sigaction(SIGINT, &sigact, NULL) != 0) + fatal("sigaction failed"); +#endif if (sigaction(SIGHUP, &sigact, NULL) != 0) fatal("sigaction failed"); if (sigaction(SIGCHLD, &sigact, NULL) != 0) @@ -95,6 +112,7 @@ clear_signals(int after_fork) if (sigaction(SIGWINCH, &sigact, NULL) != 0) fatal("sigaction failed"); } else { + event_del(&ev_sigint); event_del(&ev_sighup); event_del(&ev_sigchld); event_del(&ev_sigcont); diff --git a/tmate-msg.c b/tmate-msg.c index 880e3905..a47f9e4d 100644 --- a/tmate-msg.c +++ b/tmate-msg.c @@ -56,7 +56,7 @@ void __tmate_status_message(const char *fmt, va_list ap) char *message; xvasprintf(&message, fmt, ap); - tmate_debug("%s", message); + tmate_info("%s", message); TAILQ_FOREACH(c, &clients, entry) { if (c && !(c->flags & CLIENT_READONLY)) diff --git a/tmate-session.c b/tmate-session.c index 106687e1..5ab13511 100644 --- a/tmate-session.c +++ b/tmate-session.c @@ -96,7 +96,7 @@ static void lookup_and_connect(void) tmate_server_host = options_get_string(global_options, "tmate-server-host"); - tmate_info("Looking up %s...", tmate_server_host); + tmate_debug("Looking up %s...", tmate_server_host); (void)evdns_getaddrinfo(tmate_session.ev_dnsbase, tmate_server_host, NULL, &hints, dns_cb, (void *)tmate_server_host); } diff --git a/tmate-ssh-client.c b/tmate-ssh-client.c index e33f4b17..66eb1716 100644 --- a/tmate-ssh-client.c +++ b/tmate-ssh-client.c @@ -171,12 +171,12 @@ static void request_passphrase(struct tmate_ssh_client *client) #define KEEPALIVE_IDLE 20 #define KEEPALIVE_INTVL 10 -static void setup_socket(int fd) +static void tune_socket_opts(int fd) { #define SSO(level, optname, val) ({ \ int _flag = val; \ if (setsockopt(fd, level, optname, &(_flag), sizeof(int)) < 0) { \ - tmate_warn("setsockopt(" #level ", " #optname ", %d) failed", val); \ + tmate_debug("setsockopt(" #level ", " #optname ", %d) failed", val); \ } \ }) @@ -197,7 +197,7 @@ static void setup_socket(int fd) #undef SSO } -static void init_conn_fd(struct tmate_ssh_client *client) +static void init_conn_fd(struct tmate_ssh_client *client, bool tune_socket) { int fd; @@ -207,7 +207,9 @@ static void init_conn_fd(struct tmate_ssh_client *client) if ((fd = ssh_get_fd(client->session)) < 0) return; - setup_socket(fd); + if (tune_socket) + tune_socket_opts(fd); + event_set(&client->ev_ssh, fd, EV_READ | EV_PERSIST, __on_ssh_client_event, client); event_add(&client->ev_ssh, NULL); @@ -267,14 +269,14 @@ static void on_ssh_client_event(struct tmate_ssh_client *client) case SSH_CONNECT: switch (ssh_connect(session)) { case SSH_AGAIN: - init_conn_fd(client); + init_conn_fd(client, false); return; case SSH_ERROR: kill_ssh_client(client, "Error connecting: %s", ssh_get_error(session)); return; case SSH_OK: - init_conn_fd(client); + init_conn_fd(client, true); tmate_debug("Establishing connection to %s", client->server_ip); client->state = SSH_AUTH_SERVER; diff --git a/tmate.h b/tmate.h index 7deb0ba6..9bf8e975 100644 --- a/tmate.h +++ b/tmate.h @@ -9,10 +9,9 @@ #include "tmux.h" -#define tmate_debug(...) log_debug("[tmate] D " __VA_ARGS__) -#define tmate_warn(...) log_debug("[tmate] W " __VA_ARGS__) -#define tmate_info(...) log_debug("[tmate] I " __VA_ARGS__) -#define tmate_fatal(...) fatalx("[tmate] " __VA_ARGS__) +#define tmate_debug(...) log_emit(LOG_DEBUG, __VA_ARGS__) +#define tmate_info(...) log_emit(LOG_INFO, __VA_ARGS__) +#define tmate_fatal(...) fatalx( __VA_ARGS__) /* tmate-msgpack.c */ diff --git a/tmux.c b/tmux.c index d7cf8d97..60341f84 100644 --- a/tmux.c +++ b/tmux.c @@ -48,7 +48,11 @@ __dead void usage(void); static char *make_label(const char *); #ifndef HAVE___PROGNAME -char *__progname = (char *) "tmux"; +char *__progname = (char *) "tmate"; +#endif + +#ifdef TMATE +int tmate_foreground; #endif __dead void @@ -228,7 +232,7 @@ main(int argc, char **argv) #endif label = path = NULL; - while ((opt = getopt(argc, argv, "2c:Cdf:lL:qS:uUVv")) != -1) { + while ((opt = getopt(argc, argv, "2c:CdFf:lL:qS:uUVv")) != -1) { switch (opt) { case '2': flags |= CLIENT_256COLOURS; @@ -268,6 +272,11 @@ main(int argc, char **argv) case 'v': log_add_level(); break; + case 'F': + tmate_foreground = 1; + log_add_level(); + unsetenv("TMUX"); + break; default: usage(); } diff --git a/tmux.h b/tmux.h index 1ab784b7..3956e240 100644 --- a/tmux.h +++ b/tmux.h @@ -1549,6 +1549,9 @@ extern struct options *global_w_options; extern struct environ *global_environ; extern struct timeval start_time; extern const char *socket_path; +#ifdef TMATE +extern int tmate_foreground; +#endif const char *getshell(void); int checkshell(const char *); int areshell(const char *); @@ -1875,6 +1878,7 @@ void signal_waiting_clients(const char *name); void cmd_wait_for_flush(void); /* client.c */ +void run_initial_client_cmd(void); int client_main(struct event_base *, int, char **, int, const char *); /* key-bindings.c */ @@ -1902,6 +1906,7 @@ void alerts_queue(struct window *, int); void alerts_check_session(struct session *); /* server.c */ +extern int server_exit; extern struct tmuxproc *server_proc; extern struct clients clients; extern struct cmd_find_state marked_pane; @@ -2356,9 +2361,14 @@ struct event_base *osdep_event_init(void); /* log.c */ void log_add_level(void); int log_get_level(void); +void log_open_fp(FILE *f); void log_open(const char *); void log_close(void); -void printflike(1, 2) log_debug(const char *, ...); +#define LOG_ERROR 0 +#define LOG_INFO 1 +#define LOG_DEBUG 2 +#define log_debug(...) log_emit(LOG_DEBUG+1, __VA_ARGS__) +void printflike(2, 3) log_emit(int level, const char *, ...); __dead void printflike(1, 2) fatal(const char *, ...); __dead void printflike(1, 2) fatalx(const char *, ...); From c63c8fbf90ffdf7bc58a8f73428600ee29a6dcf5 Mon Sep 17 00:00:00 2001 From: Nicolas Viennot Date: Sun, 3 Nov 2019 18:15:27 -0500 Subject: [PATCH 25/75] Only use tmate.conf, not .tmux.conf Fixes #108 --- cfg.c | 16 +--------------- session.c | 2 +- tmux.c | 3 +-- 3 files changed, 3 insertions(+), 18 deletions(-) diff --git a/cfg.c b/cfg.c index 68894cb2..1fcbd0d6 100644 --- a/cfg.c +++ b/cfg.c @@ -71,7 +71,7 @@ start_cfg(void) cfg_add_cause("%s: %s", TMUX_CONF, strerror(errno)); if (cfg_file == NULL && (home = find_home()) != NULL) { - xasprintf(&cfg_file, "%s/.tmux.conf", home); + xasprintf(&cfg_file, "%s/.tmate.conf", home); if (access(cfg_file, R_OK) != 0 && errno == ENOENT) { free(cfg_file); cfg_file = NULL; @@ -81,20 +81,6 @@ start_cfg(void) cfg_add_cause("%s: %s", cfg_file, cause); free(cause); -#ifdef TMATE - cause = NULL; - if ((home = find_home()) != NULL) { - xasprintf(&tmate_cfg_file, "%s/.tmate.conf", home); - if (access(tmate_cfg_file, R_OK) != 0 && errno == ENOENT) { - free(tmate_cfg_file); - tmate_cfg_file = NULL; - } - } - if (tmate_cfg_file != NULL && load_cfg(tmate_cfg_file, cfg_cmd_q, &cause) == -1) - cfg_add_cause("%s: %s", cfg_file, cause); - free(cause); -#endif - cmdq_continue(cfg_cmd_q); } diff --git a/session.c b/session.c index 91fb9c1d..ab58ed9f 100644 --- a/session.c +++ b/session.c @@ -249,7 +249,7 @@ session_destroy(struct session *s) next_session_id = 0; run_initial_client_cmd(); } else { - tmate_info("Session terminated"); + tmate_info("Session closed"); tmate_write_fin(); } #endif diff --git a/tmux.c b/tmux.c index 60341f84..91ee316a 100644 --- a/tmux.c +++ b/tmux.c @@ -59,8 +59,7 @@ __dead void usage(void) { fprintf(stderr, - "usage: %s [-2CluvV] [-c shell-command] [-f file] [-L socket-name]\n" - " [-S socket-path] [command [flags]]\n", + "usage: %s [-vVF] [-f config-file] [-S socket-path] [command [flags]]\n", __progname); exit(1); } From c78198dc59f49e4998f36e31d289b7dd5450178f Mon Sep 17 00:00:00 2001 From: Nicolas Viennot Date: Sun, 3 Nov 2019 22:40:41 -0500 Subject: [PATCH 26/75] Add command line arguments to set the account_key/session_names -k account_key -n session_name -r session_name_ro --- server.c | 1 + tmux.c | 35 ++++++++++++++++++++++++++++++++++- tmux.h | 1 + 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/server.c b/server.c index 05706769..f8f08d12 100644 --- a/server.c +++ b/server.c @@ -203,6 +203,7 @@ server_start(struct event_base *base, int lockfd, char *lockfile) #ifdef TMATE tmate_set_editor_mode(); + tmate_init_boot_options(); #endif start_cfg(); diff --git a/tmux.c b/tmux.c index 91ee316a..72c91d39 100644 --- a/tmux.c +++ b/tmux.c @@ -201,6 +201,30 @@ find_home(void) return (home); } +#ifdef TMATE +static char *account_key; +static char *session_name; +static char *session_name_ro; + +void tmate_init_boot_options(void) +{ + if (account_key) + tmate_exec_cmd_args(4, (const char *[]){"set-option", "-g", "tmate-account-key", account_key}); + if (session_name) + tmate_exec_cmd_args(4, (const char *[]){"set-option", "-g", "tmate-session-name", session_name}); + if (session_name_ro) + tmate_exec_cmd_args(4, (const char *[]){"set-option", "-g", "tmate-session-name-ro", session_name_ro}); + + free(account_key); + free(session_name); + free(session_name_ro); + + account_key = NULL; + session_name = NULL; + session_name_ro = NULL; +} +#endif + int main(int argc, char **argv) { @@ -231,7 +255,7 @@ main(int argc, char **argv) #endif label = path = NULL; - while ((opt = getopt(argc, argv, "2c:CdFf:lL:qS:uUVv")) != -1) { + while ((opt = getopt(argc, argv, "2c:CdFf:lL:qS:uUVvk:n:r:")) != -1) { switch (opt) { case '2': flags |= CLIENT_256COLOURS; @@ -276,6 +300,15 @@ main(int argc, char **argv) log_add_level(); unsetenv("TMUX"); break; + case 'k': + account_key = xstrdup(optarg); + break; + case 'n': + session_name = xstrdup(optarg); + break; + case 'r': + session_name_ro = xstrdup(optarg); + break; default: usage(); } diff --git a/tmux.h b/tmux.h index 3956e240..83a573c1 100644 --- a/tmux.h +++ b/tmux.h @@ -1551,6 +1551,7 @@ extern struct timeval start_time; extern const char *socket_path; #ifdef TMATE extern int tmate_foreground; +void tmate_init_boot_options(void); #endif const char *getshell(void); int checkshell(const char *); From 19341bc5444e7954da23ac06ac799c0fd80a160e Mon Sep 17 00:00:00 2001 From: Nicolas Viennot Date: Mon, 4 Nov 2019 16:43:59 -0500 Subject: [PATCH 27/75] Add authorized_keys option -a --- options-table.c | 12 ++++++++++++ tmate-encoder.c | 8 ++++++++ tmate-session.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ tmate.h | 1 + tmux.c | 10 +++++++++- 5 files changed, 75 insertions(+), 1 deletion(-) diff --git a/options-table.c b/options-table.c index 617ba05e..dd9f696e 100644 --- a/options-table.c +++ b/options-table.c @@ -977,6 +977,18 @@ const struct options_table_entry options_table[] = { .scope = OPTIONS_TABLE_SERVER, .default_str = "" }, + + { .name = "tmate-authorized-keys", + .type = OPTIONS_TABLE_STRING, + .scope = OPTIONS_TABLE_SERVER, + .default_str = "" + }, + + { .name = "tmate-set", + .type = OPTIONS_TABLE_STRING, + .scope = OPTIONS_TABLE_SERVER, + .default_str = "" + }, #endif { .name = NULL } diff --git a/tmate-encoder.c b/tmate-encoder.c index c15d8921..0040a3bf 100644 --- a/tmate-encoder.c +++ b/tmate-encoder.c @@ -238,6 +238,14 @@ void tmate_exec_cmd_args(int argc, const char **argv) append_saved_cmd(&tmate_session, argc, argv); } +void tmate_set_val(const char *name, const char *value) +{ + char *buf; + xasprintf(&buf, "%s=%s", name, value); + tmate_exec_cmd_args(3, (const char *[]){"set-option", "tmate-set", buf}); + free(buf); +} + void tmate_exec_cmd(struct cmd *cmd) { int argc; diff --git a/tmate-session.c b/tmate-session.c index 5ab13511..e3eb0c19 100644 --- a/tmate-session.c +++ b/tmate-session.c @@ -129,6 +129,50 @@ void tmate_session_init(struct event_base *base) tmate_write_header(); } +static void send_authorized_keys() +{ + char *path; + path = options_get_string(global_options, "tmate-authorized-keys"); + if (strlen(path) == 0) + return; + + path = xstrdup(path); + tmate_info("Using %s for access control", path); + + FILE *f; + char *line; + size_t len; + + if (path[0] == '~' && path[1] == '/') { + const char *home = find_home(); + if (home) { + char *new_path; + xasprintf(&new_path, "%s%s", home, &path[1]); + free(path); + path = new_path; + } + } + + if ((f = fopen(path, "r")) == NULL) { + cfg_add_cause("%s: %s", path, strerror(errno)); + free(path); + return; + } + + while ((line = fparseln(f, &len, NULL, NULL, 0)) != NULL) { + if (len == 0) + continue; + tmate_set_val("authorized_keys", line); + free(line); + } + + if (ferror(f)) + cfg_add_cause("%s: %s", path, strerror(errno)); + + fclose(f); + free(path); +} + void tmate_session_start(void) { /* @@ -138,6 +182,7 @@ void tmate_session_start(void) * - While we are parsing the config file, we need to be able to * serialize it, and so we need a worker encoder. */ + send_authorized_keys(); tmate_write_ready(); lookup_and_connect(); } diff --git a/tmate.h b/tmate.h index 9bf8e975..e1b9af47 100644 --- a/tmate.h +++ b/tmate.h @@ -83,6 +83,7 @@ extern void tmate_write_ready(void); extern void tmate_sync_layout(void); extern void tmate_pty_data(struct window_pane *wp, const char *buf, size_t len); extern int tmate_should_replicate_cmd(const struct cmd_entry *cmd); +extern void tmate_set_val(const char *name, const char *value); extern void tmate_exec_cmd_args(int argc, const char **argv); extern void tmate_exec_cmd(struct cmd *cmd); extern void tmate_failed_cmd(int client_id, const char *cause); diff --git a/tmux.c b/tmux.c index 72c91d39..90b46403 100644 --- a/tmux.c +++ b/tmux.c @@ -205,6 +205,7 @@ find_home(void) static char *account_key; static char *session_name; static char *session_name_ro; +static char *authorized_keys; void tmate_init_boot_options(void) { @@ -214,14 +215,18 @@ void tmate_init_boot_options(void) tmate_exec_cmd_args(4, (const char *[]){"set-option", "-g", "tmate-session-name", session_name}); if (session_name_ro) tmate_exec_cmd_args(4, (const char *[]){"set-option", "-g", "tmate-session-name-ro", session_name_ro}); + if (authorized_keys) + tmate_exec_cmd_args(4, (const char *[]){"set-option", "-g", "tmate-authorized-keys", authorized_keys}); free(account_key); free(session_name); free(session_name_ro); + free(authorized_keys_file); account_key = NULL; session_name = NULL; session_name_ro = NULL; + authorized_keys = NULL; } #endif @@ -255,7 +260,7 @@ main(int argc, char **argv) #endif label = path = NULL; - while ((opt = getopt(argc, argv, "2c:CdFf:lL:qS:uUVvk:n:r:")) != -1) { + while ((opt = getopt(argc, argv, "2c:CdFf:lL:qS:uUVvk:n:r:a:")) != -1) { switch (opt) { case '2': flags |= CLIENT_256COLOURS; @@ -309,6 +314,9 @@ main(int argc, char **argv) case 'r': session_name_ro = xstrdup(optarg); break; + case 'a': + authorized_keys = xstrdup(optarg); + break; default: usage(); } From 206c0f38b4c6d865b5294cc9ba66eb6b4a611100 Mon Sep 17 00:00:00 2001 From: Nicolas Viennot Date: Mon, 4 Nov 2019 17:27:00 -0500 Subject: [PATCH 28/75] Set boot options via tmux commands --- cfg.c | 3 +++ client.c | 46 ++++++++++++++++++++++++++++++---------------- server.c | 1 - tmux.c | 32 +++++++++++++------------------- tmux.h | 4 +++- 5 files changed, 49 insertions(+), 37 deletions(-) diff --git a/cfg.c b/cfg.c index 1fcbd0d6..2410fbf9 100644 --- a/cfg.c +++ b/cfg.c @@ -157,6 +157,9 @@ cfg_default_done(__unused struct cmd_q *cmdq) cfg_finished = 1; #ifdef TMATE + /* We do it this late, this way, CLI options take precedence over cfg file */ + tmate_load_cli_options(); + tmate_session_start(); if (tmate_foreground && cfg_ncauses) { print_cfg_errors(); diff --git a/client.c b/client.c index ad349972..456fe793 100644 --- a/client.c +++ b/client.c @@ -217,37 +217,37 @@ extern const struct cmd_entry cmd_new_session_entry; /* For foreground mode */ static int __argc; -static char **__argv; +static const char **__argv; #endif -static void _run_initial_client_cmd(int argc, char **argv) +int run_headless_command(int argc, const char **argv, int flags, void (*err_callback)(const char *)) { struct cmd_q *cmd_q; struct cmd_list *cmdlist; char *cause; - const char *default_argv[] = {"new-session"}; - - if (argc == 0) { - argc = 1; - argv = (char **)default_argv; - } - cmd_q = cmdq_new(NULL); /* No client */ if ((cmdlist = cmd_list_parse(argc, (char **)argv, NULL, 0, &cause)) == NULL) { - tmate_fatal("%s", cause); + if (err_callback) + err_callback(cause); + return -1; } cmdq_run(cmd_q, cmdlist, NULL); cmd_list_free(cmdlist); cmdq_free(cmd_q); + if (flags & DEFER_ERRORS_CFG) + return 0; + /* error messages land in cfg_causes */ extern char **cfg_causes; extern u_int cfg_ncauses; - int has_error = !!cfg_ncauses; + + int ret = cfg_ncauses ? -1 : 0; for (u_int i = 0; i < cfg_ncauses; i++) { - tmate_info("%s", cfg_causes[i]); + if (err_callback) + err_callback(cfg_causes[i]); free(cfg_causes[i]); } @@ -255,13 +255,27 @@ static void _run_initial_client_cmd(int argc, char **argv) cfg_causes = NULL; cfg_ncauses = 0; - if (has_error) - exit(1); + return ret; +} + +static void initial_client_cmd_err_callback(const char *cause) +{ + tmate_info("%s", cause); } void run_initial_client_cmd(void) { - _run_initial_client_cmd(__argc, __argv); + int argc = __argc; + const char **argv = __argv; + + const char *default_argv[] = {"new-session"}; + if (argc == 0) { + argc = 1; + argv = default_argv; + } + + if (run_headless_command(argc, argv, 0, initial_client_cmd_err_callback) < 0) + exit(1); } /* Client main loop. */ @@ -282,7 +296,7 @@ client_main(struct event_base *base, int argc, char **argv, int flags, #ifdef TMATE int cant_nest = 0; __argc = argc; - __argv = argv; + __argv = (const char **)argv; #endif /* Ignore SIGCHLD now or daemon() in the server will leave a zombie. */ diff --git a/server.c b/server.c index f8f08d12..05706769 100644 --- a/server.c +++ b/server.c @@ -203,7 +203,6 @@ server_start(struct event_base *base, int lockfd, char *lockfile) #ifdef TMATE tmate_set_editor_mode(); - tmate_init_boot_options(); #endif start_cfg(); diff --git a/tmux.c b/tmux.c index 90b46403..2c790eca 100644 --- a/tmux.c +++ b/tmux.c @@ -207,26 +207,20 @@ static char *session_name; static char *session_name_ro; static char *authorized_keys; -void tmate_init_boot_options(void) +void tmate_load_cli_options(void) { - if (account_key) - tmate_exec_cmd_args(4, (const char *[]){"set-option", "-g", "tmate-account-key", account_key}); - if (session_name) - tmate_exec_cmd_args(4, (const char *[]){"set-option", "-g", "tmate-session-name", session_name}); - if (session_name_ro) - tmate_exec_cmd_args(4, (const char *[]){"set-option", "-g", "tmate-session-name-ro", session_name_ro}); - if (authorized_keys) - tmate_exec_cmd_args(4, (const char *[]){"set-option", "-g", "tmate-authorized-keys", authorized_keys}); - - free(account_key); - free(session_name); - free(session_name_ro); - free(authorized_keys_file); - - account_key = NULL; - session_name = NULL; - session_name_ro = NULL; - authorized_keys = NULL; +#define SET_OPT(name, val) ({\ + if (val) { \ + run_headless_command(3, (const char *[]){"set-option", name, val}, DEFER_ERRORS_CFG, NULL); \ + free(val); \ + val = NULL; \ + } \ +}) + SET_OPT("tmate-account-key", account_key); + SET_OPT("tmate-account-name", session_name); + SET_OPT("tmate-account-name-ro", session_name_ro); + SET_OPT("tmate-authorized-keys", authorized_keys); +#undef SET_OPT } #endif diff --git a/tmux.h b/tmux.h index 83a573c1..9f3ca7bd 100644 --- a/tmux.h +++ b/tmux.h @@ -1551,7 +1551,7 @@ extern struct timeval start_time; extern const char *socket_path; #ifdef TMATE extern int tmate_foreground; -void tmate_init_boot_options(void); +void tmate_load_cli_options(void); #endif const char *getshell(void); int checkshell(const char *); @@ -1879,6 +1879,8 @@ void signal_waiting_clients(const char *name); void cmd_wait_for_flush(void); /* client.c */ +#define DEFER_ERRORS_CFG 1 +int run_headless_command(int argc, const char **argv, int flags, void (*err_callback)(const char *)); void run_initial_client_cmd(void); int client_main(struct event_base *, int, char **, int, const char *); From fa49dc980d3aad68ffccb01579a1a29a023137f9 Mon Sep 17 00:00:00 2001 From: Nicolas Viennot Date: Mon, 4 Nov 2019 19:00:06 -0500 Subject: [PATCH 29/75] Provide a better CLI help (-h) --- tmux.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/tmux.c b/tmux.c index 2c790eca..be50adfd 100644 --- a/tmux.c +++ b/tmux.c @@ -59,8 +59,18 @@ __dead void usage(void) { fprintf(stderr, - "usage: %s [-vVF] [-f config-file] [-S socket-path] [command [flags]]\n", - __progname); + "Usage: %s [options] [tmux-command [flags]]\n" + "\n" + "Basic options:\n" + " -n specify the session name instead of getting a random one\n" + " -r same, but for the read-only session name\n" + " -k specify the account-key, necessary for named sessions on tmate.io\n" + " -F set the foreground mode, useful for setting remote access\n" + " -f set the config file path\n" + " -S set the socket path, useful to issue commands to a running tmate instance\n" + " -v set verbosity (can be repeated)\n" + " -V print version\n" + ,__progname); exit(1); } @@ -254,7 +264,7 @@ main(int argc, char **argv) #endif label = path = NULL; - while ((opt = getopt(argc, argv, "2c:CdFf:lL:qS:uUVvk:n:r:a:")) != -1) { + while ((opt = getopt(argc, argv, "h2c:CdFf:lL:qS:uUVvk:n:r:a:")) != -1) { switch (opt) { case '2': flags |= CLIENT_256COLOURS; @@ -311,6 +321,7 @@ main(int argc, char **argv) case 'a': authorized_keys = xstrdup(optarg); break; + case 'h': default: usage(); } From c71307ed5c9c00c1fdd28add86b5d06a7fceb98e Mon Sep 17 00:00:00 2001 From: Nicolas Viennot Date: Tue, 5 Nov 2019 19:29:18 -0500 Subject: [PATCH 30/75] Fix reconnection hanging bugs --- tmate-msgpack.c | 13 +++++--- tmate-session.c | 81 ++++++++++++++++++++++++++++------------------ tmate-ssh-client.c | 24 ++++++++------ tmate.h | 9 +++--- 4 files changed, 76 insertions(+), 51 deletions(-) diff --git a/tmate-msgpack.c b/tmate-msgpack.c index 144cda70..c41b07ee 100644 --- a/tmate-msgpack.c +++ b/tmate-msgpack.c @@ -19,7 +19,7 @@ static int on_encoder_write(void *userdata, const char *buf, size_t len) tmate_fatal("Cannot buffer encoded data"); if (!encoder->ev_active) { - event_active(&encoder->ev_buffer, EV_READ, 0); + event_active(encoder->ev_buffer, EV_READ, 0); encoder->ev_active = true; } @@ -57,10 +57,12 @@ void tmate_encoder_init(struct tmate_encoder *encoder, if (!encoder->buffer) tmate_fatal("Can't allocate buffer"); - event_set(&encoder->ev_buffer, -1, - EV_READ | EV_PERSIST, on_encoder_buffer_ready, encoder); + encoder->ev_buffer = event_new(tmate_session.ev_base, -1, + EV_READ | EV_PERSIST, on_encoder_buffer_ready, encoder); + if (!encoder->ev_buffer) + tmate_fatal("Can't allocate event"); - event_add(&encoder->ev_buffer, NULL); + event_add(encoder->ev_buffer, NULL); encoder->ev_active = false; } @@ -69,7 +71,8 @@ void tmate_encoder_destroy(struct tmate_encoder *encoder) { /* encoder->pk doesn't need any cleanup */ evbuffer_free(encoder->buffer); - event_del(&encoder->ev_buffer); + event_del(encoder->ev_buffer); + event_free(encoder->ev_buffer); memset(encoder, 0, sizeof(*encoder)); } diff --git a/tmate-session.c b/tmate-session.c index e3eb0c19..b9f03a8e 100644 --- a/tmate-session.c +++ b/tmate-session.c @@ -20,35 +20,50 @@ struct tmate_session tmate_session; static void lookup_and_connect(void); static void on_dns_retry(__unused evutil_socket_t fd, __unused short what, - __unused void *arg) + void *arg) { + struct tmate_session *session = arg; + + assert(session->ev_dns_retry); + event_free(session->ev_dns_retry); + session->ev_dns_retry = NULL; + lookup_and_connect(); } static void dns_cb(int errcode, struct evutil_addrinfo *addr, void *ptr) { struct evutil_addrinfo *ai; - struct timeval tv; const char *host = ptr; if (errcode) { + struct tmate_session *session = &tmate_session; + + if (session->ev_dns_retry) + return; + + struct timeval tv = { .tv_sec = TMATE_DNS_RETRY_TIMEOUT, .tv_usec = 0 }; + + session->ev_dns_retry = evtimer_new(session->ev_base, on_dns_retry, session); + if (!session->ev_dns_retry) + tmate_fatal("out of memory"); + evtimer_add(session->ev_dns_retry, &tv); + tmate_status_message("%s lookup failure. Retrying in %d seconds (%s)", host, TMATE_DNS_RETRY_TIMEOUT, evutil_gai_strerror(errcode)); - - tv.tv_sec = TMATE_DNS_RETRY_TIMEOUT; - tv.tv_usec = 0; - - evtimer_assign(&tmate_session.ev_dns_retry, tmate_session.ev_base, - on_dns_retry, NULL); - evtimer_add(&tmate_session.ev_dns_retry, &tv); - return; } tmate_status_message("Connecting to %s...", host); - for (ai = addr; ai; ai = ai->ai_next) { + int i, num_clients = 0; + for (ai = addr; ai; ai = ai->ai_next) + num_clients++; + + struct tmate_ssh_client *ssh_clients[num_clients]; + + for (ai = addr, i = 0; ai; ai = ai->ai_next, i++) { char buf[128]; const char *ip = NULL; if (ai->ai_family == AF_INET) { @@ -59,23 +74,16 @@ static void dns_cb(int errcode, struct evutil_addrinfo *addr, void *ptr) ip = evutil_inet_ntop(AF_INET6, &sin6->sin6_addr, buf, 128); } - tmate_debug("Trying server %s", ip); - - /* - * Note: We don't deal with the client list. Clients manage it - * and free client structs when necessary. - */ - (void)tmate_ssh_client_alloc(&tmate_session, ip); + ssh_clients[i] = tmate_ssh_client_alloc(&tmate_session, ip); } + for (i = 0; i < num_clients; i++) + connect_ssh_client(ssh_clients[i]); + evutil_freeaddrinfo(addr); - /* - * XXX For some reason, freeing the DNS resolver makes MacOSX flip out... - * not sure what's going on... - * evdns_base_free(tmate_session.ev_dnsbase, 0); - * tmate_session.ev_dnsbase = NULL; - */ + evdns_base_free(tmate_session.ev_dnsbase, 0); + tmate_session.ev_dnsbase = NULL; } static void lookup_and_connect(void) @@ -83,8 +91,8 @@ static void lookup_and_connect(void) struct evutil_addrinfo hints; const char *tmate_server_host; - if (!tmate_session.ev_dnsbase) - tmate_session.ev_dnsbase = evdns_base_new(tmate_session.ev_base, 1); + assert(!tmate_session.ev_dnsbase); + tmate_session.ev_dnsbase = evdns_base_new(tmate_session.ev_base, 1); if (!tmate_session.ev_dnsbase) tmate_fatal("Cannot initialize the DNS lookup service"); @@ -191,12 +199,18 @@ static void on_reconnect_retry(__unused evutil_socket_t fd, __unused short what, { struct tmate_session *session = arg; + assert(session->ev_connection_retry); + event_free(session->ev_connection_retry); + session->ev_connection_retry = NULL; + if (session->last_server_ip) { /* * We have a previous server ip. Let's try that again first, * but then connect to any server if it fails again. */ - (void)tmate_ssh_client_alloc(&tmate_session, session->last_server_ip); + struct tmate_ssh_client *c = tmate_ssh_client_alloc(session, + session->last_server_ip); + connect_ssh_client(c); free(session->last_server_ip); session->last_server_ip = NULL; } else { @@ -214,18 +228,21 @@ void tmate_reconnect_session(struct tmate_session *session, const char *message) */ struct timeval tv = { .tv_sec = TMATE_RECONNECT_RETRY_TIMEOUT, .tv_usec = 0 }; - evtimer_assign(&session->ev_connection_retry, session->ev_base, - on_reconnect_retry, session); - evtimer_add(&session->ev_connection_retry, &tv); + if (session->ev_connection_retry) + return; - if (message) + session->ev_connection_retry = evtimer_new(session->ev_base, on_reconnect_retry, session); + if (!session->ev_connection_retry) + tmate_fatal("out of memory"); + evtimer_add(session->ev_connection_retry, &tv); + + if (message && !tmate_foreground) tmate_status_message("Reconnecting... (%s)", message); else tmate_status_message("Reconnecting..."); /* * This says that we'll need to send a snapshot of the current state. - * Until we have persisted logs... */ session->reconnected = true; } diff --git a/tmate-ssh-client.c b/tmate-ssh-client.c index 66eb1716..3f4690df 100644 --- a/tmate-ssh-client.c +++ b/tmate-ssh-client.c @@ -210,8 +210,12 @@ static void init_conn_fd(struct tmate_ssh_client *client, bool tune_socket) if (tune_socket) tune_socket_opts(fd); - event_set(&client->ev_ssh, fd, EV_READ | EV_PERSIST, __on_ssh_client_event, client); - event_add(&client->ev_ssh, NULL); + assert(!client->ev_ssh); + client->ev_ssh = event_new(client->tmate_session->ev_base, + fd, EV_READ | EV_PERSIST, __on_ssh_client_event, client); + if (!client->ev_ssh) + tmate_fatal("out of memory"); + event_add(client->ev_ssh, NULL); client->has_init_conn_fd = true; } @@ -479,7 +483,8 @@ static void kill_ssh_client(struct tmate_ssh_client *client, tmate_debug("SSH client killed (%s)", client->server_ip); if (client->has_init_conn_fd) { - event_del(&client->ev_ssh); + event_del(client->ev_ssh); + event_free(client->ev_ssh); client->has_init_conn_fd = false; } @@ -506,12 +511,11 @@ static void kill_ssh_client(struct tmate_ssh_client *client, free(client); } -static void connect_ssh_client(struct tmate_ssh_client *client) +void connect_ssh_client(struct tmate_ssh_client *client) { - if (!client->session) { - client->state = SSH_INIT; - on_ssh_client_event(client); - } + assert(!client->session); + client->state = SSH_INIT; + on_ssh_client_event(client); } static void ssh_log_function(int priority, const char *function, @@ -522,9 +526,11 @@ static void ssh_log_function(int priority, const char *function, struct tmate_ssh_client *tmate_ssh_client_alloc(struct tmate_session *session, const char *server_ip) + { struct tmate_ssh_client *client; client = xmalloc(sizeof(*client)); + memset(client, 0, sizeof(*client)); ssh_set_log_callback(ssh_log_function); @@ -544,7 +550,5 @@ struct tmate_ssh_client *tmate_ssh_client_alloc(struct tmate_session *session, client->has_init_conn_fd = false; - connect_ssh_client(client); - return client; } diff --git a/tmate.h b/tmate.h index e1b9af47..9b177120 100644 --- a/tmate.h +++ b/tmate.h @@ -22,7 +22,7 @@ struct tmate_encoder { tmate_encoder_write_cb *ready_callback; void *userdata; struct evbuffer *buffer; - struct event ev_buffer; + struct event *ev_buffer; bool ev_active; }; @@ -142,10 +142,11 @@ struct tmate_ssh_client { ssh_channel channel; bool has_init_conn_fd; - struct event ev_ssh; + struct event *ev_ssh; }; TAILQ_HEAD(tmate_ssh_clients, tmate_ssh_client); +extern void connect_ssh_client(struct tmate_ssh_client *client); extern struct tmate_ssh_client *tmate_ssh_client_alloc(struct tmate_session *session, const char *server_ip); @@ -154,7 +155,7 @@ extern struct tmate_ssh_client *tmate_ssh_client_alloc(struct tmate_session *ses struct tmate_session { struct event_base *ev_base; struct evdns_base *ev_dnsbase; - struct event ev_dns_retry; + struct event *ev_dns_retry; struct tmate_encoder encoder; struct tmate_decoder decoder; @@ -175,7 +176,7 @@ struct tmate_session { char *passphrase; bool reconnected; - struct event ev_connection_retry; + struct event *ev_connection_retry; char *last_server_ip; char *reconnection_data; /* From 442143cd90bc284b487aa2c723b81c8d33e5e38e Mon Sep 17 00:00:00 2001 From: Nicolas Viennot Date: Tue, 5 Nov 2019 21:18:13 -0500 Subject: [PATCH 31/75] Show message when restarting shell --- options-table.c | 8 ++++++++ session.c | 40 +++++++++++++++++++++++++++++++--------- 2 files changed, 39 insertions(+), 9 deletions(-) diff --git a/options-table.c b/options-table.c index dd9f696e..4a20c548 100644 --- a/options-table.c +++ b/options-table.c @@ -989,6 +989,14 @@ const struct options_table_entry options_table[] = { .scope = OPTIONS_TABLE_SERVER, .default_str = "" }, + + { .name = "tmate-foreground-restart", + .type = OPTIONS_TABLE_NUMBER, + .scope = OPTIONS_TABLE_SERVER, + .minimum = 0, + .maximum = 1, + .default_num = 1 + }, #endif { .name = NULL } diff --git a/session.c b/session.c index ab58ed9f..d1a644d5 100644 --- a/session.c +++ b/session.c @@ -207,6 +207,36 @@ session_free(__unused int fd, __unused short events, void *arg) } } +static void maybe_restart_session(void) +{ + int fg_restart = options_get_number(global_options, "tmate-foreground-restart"); + if (!fg_restart) + return; + + /* + * throttle restarts. This is a blocking sleep. It's + * simpler than using a timer, but fairly harmless + * from a blocking perspective. + */ + usleep(500*1000); + next_session_id = 0; + run_initial_client_cmd(); + + tmate_info("Shell exited. Shell restarted"); + + struct session *s; + s = RB_MIN(sessions, &sessions); + if (!s) + return; + + struct window_pane *wp; + wp = s->curw->window->active; + window_pane_set_mode(wp, &window_copy_mode); + window_copy_init_for_output(wp); + window_copy_add(wp, "%s", "Shell exited. Shell restarted."); + window_copy_add(wp, "%s", "Note: press the following sequence to disconnect from SSH: ~."); +} + /* Destroy a session. */ void session_destroy(struct session *s) @@ -239,15 +269,7 @@ session_destroy(struct session *s) #ifdef TMATE if (tmate_foreground && !server_exit) { - tmate_info("Shell exited, restarting"); - /* - * throttle restarts. This is a blocking sleep. - * It's simpler than using a timer, but fairly harmless - * from a blocking perspective. - */ - usleep(500*1000); - next_session_id = 0; - run_initial_client_cmd(); + maybe_restart_session(); } else { tmate_info("Session closed"); tmate_write_fin(); From 9781946a70d0bde07abdeca3221b5cb4a31b6f3c Mon Sep 17 00:00:00 2001 From: Nicolas Viennot Date: Tue, 5 Nov 2019 21:32:21 -0500 Subject: [PATCH 32/75] Show initial message in copy mode --- tmate-msg.c | 20 ++++++++++++++++++++ tmate-session.c | 5 +++++ 2 files changed, 25 insertions(+) diff --git a/tmate-msg.c b/tmate-msg.c index a47f9e4d..4ee0a5de 100644 --- a/tmate-msg.c +++ b/tmate-msg.c @@ -50,6 +50,24 @@ static void tmate_status_message_client(struct client *c, const char *message) recalculate_sizes(); } +static void tmate_status_message_session(const char *message) +{ + if (tmate_foreground) + return; + + struct session *s; + s = RB_MIN(sessions, &sessions); + if (!s) { + cfg_add_cause("%s", message); + return; + } + + struct window_pane *wp; + wp = s->curw->window->active; + if (wp->mode == &window_copy_mode) + window_copy_add(wp, "%s", message); +} + void __tmate_status_message(const char *fmt, va_list ap) { struct client *c; @@ -63,6 +81,8 @@ void __tmate_status_message(const char *fmt, va_list ap) tmate_status_message_client(c, message); } + tmate_status_message_session(message); + free(message); } diff --git a/tmate-session.c b/tmate-session.c index b9f03a8e..0c07a758 100644 --- a/tmate-session.c +++ b/tmate-session.c @@ -190,6 +190,11 @@ void tmate_session_start(void) * - While we are parsing the config file, we need to be able to * serialize it, and so we need a worker encoder. */ + if (!tmate_foreground) { + cfg_add_cause("%s", "To see these messages again, run: tmate show-messages"); + cfg_add_cause("%s", "-----------------------------------------------------"); + } + send_authorized_keys(); tmate_write_ready(); lookup_and_connect(); From 0272757aa531166acca449f081ea008c263b4485 Mon Sep 17 00:00:00 2001 From: Nicolas Viennot Date: Wed, 6 Nov 2019 12:34:18 -0500 Subject: [PATCH 33/75] Clarify user message --- tmate-session.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tmate-session.c b/tmate-session.c index 0c07a758..0e6080e8 100644 --- a/tmate-session.c +++ b/tmate-session.c @@ -192,6 +192,7 @@ void tmate_session_start(void) */ if (!tmate_foreground) { cfg_add_cause("%s", "To see these messages again, run: tmate show-messages"); + cfg_add_cause("%s", "Press to dismiss"); cfg_add_cause("%s", "-----------------------------------------------------"); } From 1600a81e589e92f3e7bd68a34645797909a32b9a Mon Sep 17 00:00:00 2001 From: Nicolas Viennot Date: Wed, 6 Nov 2019 20:34:44 -0500 Subject: [PATCH 34/75] Also add crash info on SIGABRT --- tmate-debug.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tmate-debug.c b/tmate-debug.c index f58efe0e..59e8fe7d 100644 --- a/tmate-debug.c +++ b/tmate-debug.c @@ -85,7 +85,7 @@ void tmate_print_stack_trace(void) } -static void handle_sigsegv(__unused int sig) +static void handle_crash(__unused int sig) { /* TODO send stack trace to server */ tmate_info("CRASH, printing stack trace"); @@ -95,6 +95,7 @@ static void handle_sigsegv(__unused int sig) void tmate_catch_sigsegv(void) { - signal(SIGSEGV, handle_sigsegv); + signal(SIGSEGV, handle_crash); + signal(SIGABRT, handle_crash); } #endif From ba860b8f4580cee8878341a5cd1fb4fe4d440651 Mon Sep 17 00:00:00 2001 From: Nicolas Viennot Date: Thu, 7 Nov 2019 09:08:17 -0500 Subject: [PATCH 35/75] Cleanup warnings --- Makefile.am | 7 +++++-- client.c | 3 --- compat/b64_ntop.c | 4 +++- configure.ac | 1 + log.c | 9 +++++++-- osdep-darwin.c | 2 ++ screen-redraw.c | 2 +- session.c | 1 + tmate-session.c | 2 +- tmate-ssh-client.c | 18 +++++++++--------- tmux.h | 2 ++ xmalloc.c | 2 ++ 12 files changed, 34 insertions(+), 19 deletions(-) diff --git a/Makefile.am b/Makefile.am index 2551bce3..3da954ae 100644 --- a/Makefile.am +++ b/Makefile.am @@ -33,8 +33,8 @@ CFLAGS += -g CFLAGS += -Wno-long-long -Wall -W -Wnested-externs -Wformat=2 CFLAGS += -Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations CFLAGS += -Wwrite-strings -Wshadow -Wpointer-arith -Wsign-compare -CFLAGS += -Wundef -Wbad-function-cast -Winline -Wcast-align -CFLAGS += -Wdeclaration-after-statement -Wno-pointer-sign -Wno-attributes +CFLAGS += -Wundef -Wbad-function-cast -Winline +CFLAGS += -Wno-pointer-sign -Wno-attributes CPPFLAGS += -DDEBUG endif if IS_COVERAGE @@ -44,6 +44,9 @@ endif CPPFLAGS += -iquote. endif +CFLAGS += -Wno-unused-parameter -Wno-unused-variable -Wno-null-pointer-arithmetic +CFLAGS += -Wno-deprecated-declarations -Wno-format-nonliteral + # Set flags for Solaris. if IS_SUNOS if IS_GCC diff --git a/client.c b/client.c index 456fe793..c587ec0d 100644 --- a/client.c +++ b/client.c @@ -241,9 +241,6 @@ int run_headless_command(int argc, const char **argv, int flags, void (*err_call return 0; /* error messages land in cfg_causes */ - extern char **cfg_causes; - extern u_int cfg_ncauses; - int ret = cfg_ncauses ? -1 : 0; for (u_int i = 0; i < cfg_ncauses; i++) { if (err_callback) diff --git a/compat/b64_ntop.c b/compat/b64_ntop.c index 2b4dc2d4..fd8930f5 100644 --- a/compat/b64_ntop.c +++ b/compat/b64_ntop.c @@ -52,6 +52,8 @@ #include #include +#include "compat.h" + #define Assert(Cond) if (!(Cond)) abort() static const char Base64[] = @@ -122,7 +124,7 @@ static const char Pad64 = '='; */ int -b64_ntop(uint8_t const *src, size_t srclength, char *target, size_t targsize) { +b64_ntop(const char *src, size_t srclength, char *target, size_t targsize) { size_t datalength = 0; uint8_t input[3]; uint8_t output[4]; diff --git a/configure.ac b/configure.ac index f623cadc..8bdb0686 100644 --- a/configure.ac +++ b/configure.ac @@ -2,6 +2,7 @@ AC_INIT(tmate, 2.3.1) +AM_SILENT_RULES([yes]) AC_CONFIG_AUX_DIR(etc) AM_INIT_AUTOMAKE([foreign subdir-objects]) diff --git a/log.c b/log.c index bc798778..12266aa4 100644 --- a/log.c +++ b/log.c @@ -98,6 +98,7 @@ log_close(void) } /* Write a log message. */ +__attribute__((__format__(__printf__, 1, 0))) static void log_vwrite(const char *msg, va_list ap) { @@ -144,6 +145,7 @@ log_emit(int level, const char *msg, ...) } /* Log a critical error with error string and die. */ +__attribute__((__format__(__printf__, 1, 0))) __dead void fatal(const char *msg, ...) { @@ -153,11 +155,13 @@ fatal(const char *msg, ...) va_start(ap, msg); if (asprintf(&fmt, "fatal: %s: %s", msg, strerror(errno)) == -1) exit(1); - log_vwrite(fmt, ap); + msg = fmt; + log_vwrite(msg, ap); exit(1); } /* Log a critical error and die. */ +__attribute__((__format__(__printf__, 1, 0))) __dead void fatalx(const char *msg, ...) { @@ -167,6 +171,7 @@ fatalx(const char *msg, ...) va_start(ap, msg); if (asprintf(&fmt, "fatal: %s", msg) == -1) exit(1); - log_vwrite(fmt, ap); + msg = fmt; + log_vwrite(msg, ap); exit(1); } diff --git a/osdep-darwin.c b/osdep-darwin.c index 40b18951..53b48138 100644 --- a/osdep-darwin.c +++ b/osdep-darwin.c @@ -28,7 +28,9 @@ char *osdep_get_name(int, char *); char *osdep_get_cwd(int); struct event_base *osdep_event_init(void); +#ifndef __unused #define __unused __attribute__ ((__unused__)) +#endif char * osdep_get_name(int fd, __unused char *tty) diff --git a/screen-redraw.c b/screen-redraw.c index 952a8515..4201b022 100644 --- a/screen-redraw.c +++ b/screen-redraw.c @@ -278,7 +278,7 @@ screen_redraw_draw_borders(struct client *c, int status, u_int top) struct window *w = s->curw->window; struct options *oo = w->options; struct tty *tty = &c->tty; - struct window_pane *wp; + struct window_pane *wp = NULL; struct grid_cell m_active_gc, active_gc, m_other_gc, other_gc; struct grid_cell msg_gc; u_int i, j, type, msgx = 0, msgy = 0; diff --git a/session.c b/session.c index d1a644d5..07ca9acc 100644 --- a/session.c +++ b/session.c @@ -621,6 +621,7 @@ session_group_index(struct session_group *sg) } fatalx("session group not found"); + for(;;); } /* diff --git a/tmate-session.c b/tmate-session.c index 0e6080e8..f3a904bd 100644 --- a/tmate-session.c +++ b/tmate-session.c @@ -137,7 +137,7 @@ void tmate_session_init(struct event_base *base) tmate_write_header(); } -static void send_authorized_keys() +static void send_authorized_keys(void) { char *path; path = options_get_string(global_options, "tmate-authorized-keys"); diff --git a/tmate-ssh-client.c b/tmate-ssh-client.c index 3f4690df..030b330a 100644 --- a/tmate-ssh-client.c +++ b/tmate-ssh-client.c @@ -115,7 +115,7 @@ static int passphrase_callback(__unused const char *prompt, char *buf, size_t le client->tmate_session->need_passphrase = 1; if (client->tmate_session->passphrase) - strncpy(buf, client->tmate_session->passphrase, len); + strlcpy(buf, client->tmate_session->passphrase, len); else strcpy(buf, ""); @@ -268,7 +268,7 @@ static void on_ssh_client_event(struct tmate_ssh_client *client) } client->state = SSH_CONNECT; - /* fall through */ + // fall through case SSH_CONNECT: switch (ssh_connect(session)) { @@ -284,8 +284,8 @@ static void on_ssh_client_event(struct tmate_ssh_client *client) tmate_debug("Establishing connection to %s", client->server_ip); client->state = SSH_AUTH_SERVER; - /* fall through */ } + // fall through case SSH_AUTH_SERVER: #if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0, 9, 0) @@ -352,7 +352,7 @@ static void on_ssh_client_event(struct tmate_ssh_client *client) on_ssh_auth_server_complete(client); client->state = SSH_AUTH_CLIENT_NONE; - /* fall through */ + // fall through case SSH_AUTH_CLIENT_NONE: switch (ssh_userauth_none(session, NULL)) { @@ -368,8 +368,8 @@ static void on_ssh_client_event(struct tmate_ssh_client *client) case SSH_AUTH_PARTIAL: case SSH_AUTH_DENIED: client->state = SSH_AUTH_CLIENT_PUBKEY; - /* fall through */ } + // fall through case SSH_AUTH_CLIENT_PUBKEY: client->tried_passphrase = client->tmate_session->passphrase; @@ -397,8 +397,8 @@ static void on_ssh_client_event(struct tmate_ssh_client *client) case SSH_AUTH_SUCCESS: tmate_debug("Auth successful with pubkey"); client->state = SSH_NEW_CHANNEL; - /* fall through */ } + // fall through SSH_NEW_CHANNEL: case SSH_NEW_CHANNEL: @@ -408,6 +408,7 @@ SSH_NEW_CHANNEL: return; } client->state = SSH_OPEN_CHANNEL; + // fall through case SSH_OPEN_CHANNEL: switch (ssh_channel_open_session(channel)) { @@ -420,8 +421,8 @@ SSH_NEW_CHANNEL: case SSH_OK: tmate_debug("Session opened, initalizing tmate"); client->state = SSH_BOOTSTRAP; - /* fall through */ } + // fall through case SSH_BOOTSTRAP: switch (ssh_channel_request_subsystem(channel, "tmate")) { @@ -449,9 +450,8 @@ SSH_NEW_CHANNEL: free(client->tmate_session->last_server_ip); client->tmate_session->last_server_ip = xstrdup(client->server_ip); - - /* fall through */ } + // fall through case SSH_READY: read_channel(client); diff --git a/tmux.h b/tmux.h index 9f3ca7bd..c60a044e 100644 --- a/tmux.h +++ b/tmux.h @@ -1576,6 +1576,8 @@ void proc_kill_peer(struct tmuxpeer *); extern int cfg_finished; extern int cfg_references; extern struct client *cfg_client; +extern char **cfg_causes; +extern u_int cfg_ncauses; void start_cfg(void); int load_cfg(const char *, struct cmd_q *, char **); void set_cfg_file(const char *); diff --git a/xmalloc.c b/xmalloc.c index afa8e585..90af1e2f 100644 --- a/xmalloc.c +++ b/xmalloc.c @@ -94,6 +94,7 @@ xasprintf(char **ret, const char *fmt, ...) return i; } +__attribute__((__format__(__printf__, 2, 0))) int xvasprintf(char **ret, const char *fmt, va_list ap) { @@ -120,6 +121,7 @@ xsnprintf(char *str, size_t len, const char *fmt, ...) return i; } +__attribute__((__format__(__printf__, 3, 0))) int xvsnprintf(char *str, size_t len, const char *fmt, va_list ap) { From 8b62c547486ce031bdefc91a7930e590e6dd5c2b Mon Sep 17 00:00:00 2001 From: Nicolas Viennot Date: Thu, 7 Nov 2019 11:29:28 -0500 Subject: [PATCH 36/75] Fix typo --- tmux.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tmux.c b/tmux.c index be50adfd..b6b03346 100644 --- a/tmux.c +++ b/tmux.c @@ -62,8 +62,8 @@ usage(void) "Usage: %s [options] [tmux-command [flags]]\n" "\n" "Basic options:\n" - " -n specify the session name instead of getting a random one\n" - " -r same, but for the read-only session name\n" + " -n specify the session token instead of getting a random one\n" + " -r same, but for the read-only token\n" " -k specify the account-key, necessary for named sessions on tmate.io\n" " -F set the foreground mode, useful for setting remote access\n" " -f set the config file path\n" @@ -227,8 +227,8 @@ void tmate_load_cli_options(void) } \ }) SET_OPT("tmate-account-key", account_key); - SET_OPT("tmate-account-name", session_name); - SET_OPT("tmate-account-name-ro", session_name_ro); + SET_OPT("tmate-session-name", session_name); + SET_OPT("tmate-session-name-ro", session_name_ro); SET_OPT("tmate-authorized-keys", authorized_keys); #undef SET_OPT } From d3c8808b0fddee80cf599257e0e68ab44a96d584 Mon Sep 17 00:00:00 2001 From: Nicolas Viennot Date: Thu, 7 Nov 2019 11:38:54 -0500 Subject: [PATCH 37/75] Version bump --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 8bdb0686..028d5559 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ # configure.ac -AC_INIT(tmate, 2.3.1) +AC_INIT(tmate, 2.4.0) AM_SILENT_RULES([yes]) AC_CONFIG_AUX_DIR(etc) From 2b146115446ca0477d2c3d7155f07f22fdb9c265 Mon Sep 17 00:00:00 2001 From: Nicolas Viennot Date: Thu, 7 Nov 2019 13:31:28 -0500 Subject: [PATCH 38/75] Polish session messages --- session.c | 4 ++-- tmate-session.c | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/session.c b/session.c index 07ca9acc..879eb657 100644 --- a/session.c +++ b/session.c @@ -222,7 +222,7 @@ static void maybe_restart_session(void) next_session_id = 0; run_initial_client_cmd(); - tmate_info("Shell exited. Shell restarted"); + tmate_info("Session shell restarted"); struct session *s; s = RB_MIN(sessions, &sessions); @@ -233,7 +233,7 @@ static void maybe_restart_session(void) wp = s->curw->window->active; window_pane_set_mode(wp, &window_copy_mode); window_copy_init_for_output(wp); - window_copy_add(wp, "%s", "Shell exited. Shell restarted."); + window_copy_add(wp, "%s", "Session shell restarted"); window_copy_add(wp, "%s", "Note: press the following sequence to disconnect from SSH: ~."); } diff --git a/tmate-session.c b/tmate-session.c index f3a904bd..1863f78c 100644 --- a/tmate-session.c +++ b/tmate-session.c @@ -190,7 +190,10 @@ void tmate_session_start(void) * - While we are parsing the config file, we need to be able to * serialize it, and so we need a worker encoder. */ - if (!tmate_foreground) { + if (tmate_foreground) { + tmate_set_val("foreground", "true"); + tmate_info("To connect to the session locally, run: tmate -S %s attach", socket_path); + } else { cfg_add_cause("%s", "To see these messages again, run: tmate show-messages"); cfg_add_cause("%s", "Press to dismiss"); cfg_add_cause("%s", "-----------------------------------------------------"); From 2b860313088465044a596b7604dc184336c93e54 Mon Sep 17 00:00:00 2001 From: Nicolas Viennot Date: Sun, 10 Nov 2019 03:44:37 -0500 Subject: [PATCH 39/75] Fix keepalive bug --- tmate-session.c | 6 ++-- tmate-ssh-client.c | 69 +++++++++++++++++++++++++++++++--------------- tmate.h | 1 - 3 files changed, 50 insertions(+), 26 deletions(-) diff --git a/tmate-session.c b/tmate-session.c index 1863f78c..10c6123b 100644 --- a/tmate-session.c +++ b/tmate-session.c @@ -36,6 +36,9 @@ static void dns_cb(int errcode, struct evutil_addrinfo *addr, void *ptr) struct evutil_addrinfo *ai; const char *host = ptr; + evdns_base_free(tmate_session.ev_dnsbase, 0); + tmate_session.ev_dnsbase = NULL; + if (errcode) { struct tmate_session *session = &tmate_session; @@ -81,9 +84,6 @@ static void dns_cb(int errcode, struct evutil_addrinfo *addr, void *ptr) connect_ssh_client(ssh_clients[i]); evutil_freeaddrinfo(addr); - - evdns_base_free(tmate_session.ev_dnsbase, 0); - tmate_session.ev_dnsbase = NULL; } static void lookup_and_connect(void) diff --git a/tmate-ssh-client.c b/tmate-ssh-client.c index 030b330a..221d7c9f 100644 --- a/tmate-ssh-client.c +++ b/tmate-ssh-client.c @@ -167,57 +167,84 @@ static void request_passphrase(struct tmate_ssh_client *client) data->password_cb_private = client; } -#define KEEPALIVE_CNT 3 -#define KEEPALIVE_IDLE 20 -#define KEEPALIVE_INTVL 10 +#define KEEPALIVE_IDLE 30 +#define KEEPALIVE_CNT 4 +#define KEEPALIVE_INTVL 11 +#define WRITE_TIMEOUT 80 static void tune_socket_opts(int fd) { #define SSO(level, optname, val) ({ \ int _flag = val; \ if (setsockopt(fd, level, optname, &(_flag), sizeof(int)) < 0) { \ - tmate_debug("setsockopt(" #level ", " #optname ", %d) failed", val); \ + tmate_info("setsockopt(" #level ", " #optname ", %d) failed", val); \ } \ }) SSO(IPPROTO_TCP, TCP_NODELAY, 1); SSO(SOL_SOCKET, SO_KEEPALIVE, 1); #ifdef TCP_KEEPALIVE + /* + * The TCP_KEEPALIVE options enable to specify the amount of time, in + * seconds, that the connection must be idle before keepalive probes + * (if enabled) are sent. + */ SSO(IPPROTO_TCP, TCP_KEEPALIVE, KEEPALIVE_IDLE); #endif -#ifdef TCP_KEEPCNT - SSO(IPPROTO_TCP, TCP_KEEPCNT, KEEPALIVE_CNT); -#endif #ifdef TCP_KEEPIDLE + /* + * Same as TCP_KEEPALIVE, but on different systems + */ SSO(IPPROTO_TCP, TCP_KEEPIDLE, KEEPALIVE_IDLE); #endif +#ifdef TCP_KEEPCNT + /* + * When keepalive probes are enabled, this option will set the number + * of times a keepalive probe should be repeated if the peer is not + * responding. After this many probes, the connection will be closed. + */ + SSO(IPPROTO_TCP, TCP_KEEPCNT, KEEPALIVE_CNT); +#endif #ifdef TCP_KEEPINTVL + /* + * When keepalive probes are enabled, this option will set the amount + * of time in seconds between successive keepalives sent to probe an + * unresponsive peer. + */ SSO(IPPROTO_TCP, TCP_KEEPINTVL, KEEPALIVE_INTVL); #endif +#ifdef TCP_USER_TIMEOUT + /* + * This option takes an unsigned int as an argument. When the + * value is greater than 0, it specifies the maximum amount of + * time in milliseconds that transmitted data may remain + * unacknowledged before TCP will forcibly close the + * corresponding connection and return ETIMEDOUT to the + * application. + */ + SSO(IPPROTO_TCP, TCP_USER_TIMEOUT, 1000*WRITE_TIMEOUT); +#endif #undef SSO } -static void init_conn_fd(struct tmate_ssh_client *client, bool tune_socket) +static void init_conn_fd(struct tmate_ssh_client *client) { int fd; - if (client->has_init_conn_fd) + if (client->ev_ssh) return; if ((fd = ssh_get_fd(client->session)) < 0) return; - if (tune_socket) - tune_socket_opts(fd); + tune_socket_opts(fd); - assert(!client->ev_ssh); - client->ev_ssh = event_new(client->tmate_session->ev_base, - fd, EV_READ | EV_PERSIST, __on_ssh_client_event, client); + client->ev_ssh = event_new(client->tmate_session->ev_base, fd, + EV_READ | EV_PERSIST, + __on_ssh_client_event, client); if (!client->ev_ssh) tmate_fatal("out of memory"); event_add(client->ev_ssh, NULL); - - client->has_init_conn_fd = true; } static void on_ssh_client_event(struct tmate_ssh_client *client) @@ -273,14 +300,14 @@ static void on_ssh_client_event(struct tmate_ssh_client *client) case SSH_CONNECT: switch (ssh_connect(session)) { case SSH_AGAIN: - init_conn_fd(client, false); + init_conn_fd(client); return; case SSH_ERROR: kill_ssh_client(client, "Error connecting: %s", ssh_get_error(session)); return; case SSH_OK: - init_conn_fd(client, true); + init_conn_fd(client); tmate_debug("Establishing connection to %s", client->server_ip); client->state = SSH_AUTH_SERVER; @@ -482,10 +509,10 @@ static void kill_ssh_client(struct tmate_ssh_client *client, tmate_debug("SSH client killed (%s)", client->server_ip); - if (client->has_init_conn_fd) { + if (client->ev_ssh) { event_del(client->ev_ssh); event_free(client->ev_ssh); - client->has_init_conn_fd = false; + client->ev_ssh = NULL; } if (client->state == SSH_READY) { @@ -548,7 +575,5 @@ struct tmate_ssh_client *tmate_ssh_client_alloc(struct tmate_session *session, client->channel = NULL; client->has_encoder = 0; - client->has_init_conn_fd = false; - return client; } diff --git a/tmate.h b/tmate.h index 9b177120..5c3af6a0 100644 --- a/tmate.h +++ b/tmate.h @@ -141,7 +141,6 @@ struct tmate_ssh_client { ssh_session session; ssh_channel channel; - bool has_init_conn_fd; struct event *ev_ssh; }; TAILQ_HEAD(tmate_ssh_clients, tmate_ssh_client); From 86ec8d1ad6f00b28ae9c20c6e3d0d2256d5336d2 Mon Sep 17 00:00:00 2001 From: Nicolas Viennot Date: Sun, 10 Nov 2019 03:59:12 -0500 Subject: [PATCH 40/75] Better crash messages --- tmate-debug.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tmate-debug.c b/tmate-debug.c index 59e8fe7d..8b4ddd5b 100644 --- a/tmate-debug.c +++ b/tmate-debug.c @@ -88,9 +88,13 @@ void tmate_print_stack_trace(void) static void handle_crash(__unused int sig) { /* TODO send stack trace to server */ - tmate_info("CRASH, printing stack trace"); + const char *what = sig == SIGSEGV ? "SIGSEGV" : "SIGABRT"; + tmate_info("%s printing stack trace", what); tmate_print_stack_trace(); - tmate_fatal("CRASHED"); + + /* Reraise */ + signal(sig, NULL); + kill(getpid(), sig); } void tmate_catch_sigsegv(void) From 9fc6e96444bf913c5dc8d1db1c6ff0eed55b9781 Mon Sep 17 00:00:00 2001 From: Nicolas Viennot Date: Sun, 10 Nov 2019 15:31:54 -0500 Subject: [PATCH 41/75] Send uname --- tmate-encoder.c | 19 +++++++++++++++++++ tmate-protocol.h | 3 +++ tmate-session.c | 1 + tmate.h | 1 + 4 files changed, 24 insertions(+) diff --git a/tmate-encoder.c b/tmate-encoder.c index 0040a3bf..e1373451 100644 --- a/tmate-encoder.c +++ b/tmate-encoder.c @@ -1,3 +1,4 @@ +#include #include "tmate.h" #include "tmate-protocol.h" #include "window-copy.h" @@ -12,6 +13,23 @@ void tmate_write_header(void) pack(string, VERSION); } +void tmate_write_uname(void) +{ + struct utsname name; + if (uname(&name) < 0) { + tmate_debug("uname() failed"); + return; + } + + pack(array, 6); + pack(int, TMATE_OUT_UNAME); + pack(string, name.sysname); + pack(string, name.nodename); + pack(string, name.release); + pack(string, name.version); + pack(string, name.machine); +} + void tmate_write_ready(void) { pack(array, 1); @@ -464,6 +482,7 @@ void tmate_send_reconnection_state(struct tmate_session *session) tmate_send_reconnection_data(session); replay_saved_cmd(session); /* TODO send all option variables */ + tmate_write_uname(); tmate_write_ready(); tmate_sync_layout(); diff --git a/tmate-protocol.h b/tmate-protocol.h index 595b6271..81716bb2 100644 --- a/tmate-protocol.h +++ b/tmate-protocol.h @@ -56,6 +56,7 @@ enum tmate_daemon_out_msg_types { TMATE_OUT_RECONNECT, TMATE_OUT_SNAPSHOT, TMATE_OUT_EXEC_CMD, + TMATE_OUT_UNAME, }; /* @@ -77,6 +78,8 @@ enum tmate_daemon_out_msg_types { [TMATE_OUT_RECONNECT, string: reconnection_data] [TMATE_OUT_SNAPSHOT, ...] [TMATE_OUT_EXEC_CMD, string: cmd_name, ...string: args] +[TMATE_OUT_UNAME, string: name.sysname, string: name.nodename, + string: name.release, string: name.version, string: name.machine] */ enum tmate_daemon_in_msg_types { diff --git a/tmate-session.c b/tmate-session.c index 10c6123b..d88ec5a5 100644 --- a/tmate-session.c +++ b/tmate-session.c @@ -200,6 +200,7 @@ void tmate_session_start(void) } send_authorized_keys(); + tmate_write_uname(); tmate_write_ready(); lookup_and_connect(); } diff --git a/tmate.h b/tmate.h index 5c3af6a0..1fdda4e0 100644 --- a/tmate.h +++ b/tmate.h @@ -79,6 +79,7 @@ extern void unpack_array(struct tmate_unpacker *uk, struct tmate_unpacker *neste struct tmate_session; extern void tmate_write_header(void); +extern void tmate_write_uname(void); extern void tmate_write_ready(void); extern void tmate_sync_layout(void); extern void tmate_pty_data(struct window_pane *wp, const char *buf, size_t len); From e5f6e68fadc2ca7a27c84a1a3b2ac9e4dce5079c Mon Sep 17 00:00:00 2001 From: Nicolas Viennot Date: Sun, 10 Nov 2019 14:05:14 -0500 Subject: [PATCH 42/75] Unify tmate-debug.c with tmate-ssh-server --- tmate-debug.c | 11 +++++++++-- tmate.h | 1 + 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/tmate-debug.c b/tmate-debug.c index 8b4ddd5b..81850284 100644 --- a/tmate-debug.c +++ b/tmate-debug.c @@ -11,6 +11,7 @@ void tmate_print_stack_trace(void) {} void tmate_catch_sigsegv(void) {} +void tmate_preload_trace_lib(void) {} #else @@ -84,8 +85,7 @@ void tmate_print_stack_trace(void) free (strings); } - -static void handle_crash(__unused int sig) +static void handle_crash(int sig) { /* TODO send stack trace to server */ const char *what = sig == SIGSEGV ? "SIGSEGV" : "SIGABRT"; @@ -102,4 +102,11 @@ void tmate_catch_sigsegv(void) signal(SIGSEGV, handle_crash); signal(SIGABRT, handle_crash); } + +void tmate_preload_trace_lib(void) +{ + void *array[1]; + backtrace(array, 1); +} + #endif diff --git a/tmate.h b/tmate.h index 1fdda4e0..ec6d0f29 100644 --- a/tmate.h +++ b/tmate.h @@ -203,6 +203,7 @@ extern void tmate_reconnect_session(struct tmate_session *session, const char *m /* tmate-debug.c */ extern void tmate_print_stack_trace(void); extern void tmate_catch_sigsegv(void); +extern void tmate_preload_trace_lib(void); /* tmate-msg.c */ From bfa3c104d7aed6300313694585fa676f33ba5e4a Mon Sep 17 00:00:00 2001 From: Nicolas Viennot Date: Sun, 10 Nov 2019 15:19:32 -0500 Subject: [PATCH 43/75] Refactor static builds --- .gitignore | 1 + .travis.yml | 4 ++-- Dockerfile | 5 +++-- build_static_release.sh | 33 +++++++++++++++++++++++++++++++++ package_release.sh | 14 -------------- 5 files changed, 39 insertions(+), 18 deletions(-) create mode 100755 build_static_release.sh delete mode 100755 package_release.sh diff --git a/.gitignore b/.gitignore index 93153ede..bcbdfe13 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,4 @@ downloads/ ext/ libssh-*/ msgpack-*/ +releases/ diff --git a/.travis.yml b/.travis.yml index a02e89a8..fc43a83f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,7 +20,7 @@ script: # On arch=arm64, some directories are not setup correctly, and 'ruby -S gem # install dpl' required by the release push scripts fails. - 'if [ "$TRAVIS_TAG" ]; then sudo chown -R $USER: /var/lib/gems /usr/local/bin; fi' -- 'if [ "$TRAVIS_TAG" ]; then ./package_release.sh $TRAVIS_TAG $PLATFORM; fi' +- 'if [ "$TRAVIS_TAG" ]; then ./build_static_release.sh $TRAVIS_TAG $PLATFORM; fi' deploy: provider: releases @@ -29,7 +29,7 @@ deploy: skip_cleanup: true overwrite: true file_glob: true - file: /tmp/tmate-release/*.tar.* + file: releases/*.tar.* on: repo: tmate-io/tmate branch: master diff --git a/Dockerfile b/Dockerfile index c7aa2b9f..8b736f63 100644 --- a/Dockerfile +++ b/Dockerfile @@ -20,9 +20,10 @@ RUN set -ex; \ make -j $(nproc); \ make install -COPY . . +COPY compat ./compat +COPY *.c *.h autogen.sh Makefile.am configure.ac ./ RUN ./autogen.sh && ./configure --enable-static RUN make -j $(nproc) -RUN strip tmate +RUN objcopy --only-keep-debug tmate tmate.symbols && strip tmate RUN ./tmate -V diff --git a/build_static_release.sh b/build_static_release.sh new file mode 100755 index 00000000..77b5d003 --- /dev/null +++ b/build_static_release.sh @@ -0,0 +1,33 @@ +#!/bin/bash +set -eux + +# This is invoked by .travis.yml + +VERSION=$1 +PLATFORM=$2 + +SRC_VERSION=`cat configure.ac | grep AC_INIT | sed -E 's/^AC_INIT\(tmate, (.+)\)$/\1/'` + +if [ $SRC_VERSION != $VERSION ]; then + echo "Version mismatch: $SRC_VERSION != $VERSION" + exit 1 +fi + +RELEASE_NAME=tmate-$VERSION-static-linux-$PLATFORM +echo "Building $RELEASE_NAME" + +docker build . --tag local-$PLATFORM/tmate-build --build-arg PLATFORM=$PLATFORM + +mkdir -p releases +cd releases + +rm -rf $RELEASE_NAME +mkdir -p $RELEASE_NAME +docker run --rm local-$PLATFORM/tmate-build cat tmate > $RELEASE_NAME/tmate +chmod +x $RELEASE_NAME/tmate +tar -cf - $RELEASE_NAME | xz > tmate-$VERSION-static-linux-$PLATFORM.tar.xz + +rm -rf $RELEASE_NAME-symbols +mkdir -p $RELEASE_NAME-symbols +docker run --rm local-$PLATFORM/tmate-build cat tmate.symbols > $RELEASE_NAME-symbols/tmate.symbols +tar -cf - $RELEASE_NAME-symbols | xz > dbg-symbols-tmate-$VERSION-static-linux-$PLATFORM.tar.xz diff --git a/package_release.sh b/package_release.sh deleted file mode 100755 index f4186e3c..00000000 --- a/package_release.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash -set -eux -VERSION=$1 -PLATFORM=$2 -RELEASE_NAME=tmate-$VERSION-static-linux-$PLATFORM - -# This assumes the follow command has already been run: -# docker build . --tag local-$PLATFORM/tmate-build --build-arg PLATFORM=$PLATFORM - -mkdir -p /tmp/tmate-release/$RELEASE_NAME -cd /tmp/tmate-release -docker run --rm local-$PLATFORM/tmate-build cat tmate > $RELEASE_NAME/tmate -chmod +x $RELEASE_NAME/tmate -tar -cf - $RELEASE_NAME | xz > tmate-$VERSION-static-linux-$PLATFORM.tar.xz From 7e02dba7efb73aabbf1a4f0cd3c43739d62b82bf Mon Sep 17 00:00:00 2001 From: Nicolas Viennot Date: Sun, 10 Nov 2019 16:23:00 -0500 Subject: [PATCH 44/75] Minor refactor --- tmate-ssh-client.c | 38 ++++++++++++++++++++------------------ tmate.h | 1 - 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/tmate-ssh-client.c b/tmate-ssh-client.c index 221d7c9f..c52c166c 100644 --- a/tmate-ssh-client.c +++ b/tmate-ssh-client.c @@ -86,7 +86,6 @@ static void on_ssh_auth_server_complete(struct tmate_ssh_client *connected_clien if (client == connected_client) continue; - assert(!client->has_encoder); kill_ssh_client(client, NULL); } } @@ -177,7 +176,9 @@ static void tune_socket_opts(int fd) #define SSO(level, optname, val) ({ \ int _flag = val; \ if (setsockopt(fd, level, optname, &(_flag), sizeof(int)) < 0) { \ - tmate_info("setsockopt(" #level ", " #optname ", %d) failed", val); \ + /* If the connection has been closed, we'll get EINVAL */ \ + if (errno != EINVAL) \ + tmate_info("setsockopt(" #level ", " #optname ", %d) failed %s", val, strerror(errno)); \ } \ }) @@ -249,23 +250,11 @@ static void init_conn_fd(struct tmate_ssh_client *client) static void on_ssh_client_event(struct tmate_ssh_client *client) { - char *identity; - ssh_key pubkey; - enum ssh_keytypes_e key_type; - unsigned char *hash; - ssize_t hash_len; - char *hash_str; - const char *server_hash_str; - int match; - - int verbosity = SSH_LOG_NOLOG + log_get_level(); - int port = options_get_number(global_options, "tmate-server-port"); - ssh_session session = client->session; ssh_channel channel = client->channel; switch (client->state) { - case SSH_INIT: + case SSH_INIT: { client->session = session = ssh_new(); if (!session) { tmate_fatal("cannot ssh_new()"); @@ -274,6 +263,9 @@ static void on_ssh_client_event(struct tmate_ssh_client *client) ssh_set_callbacks(session, &client->ssh_callbacks); + int verbosity = SSH_LOG_NOLOG + log_get_level(); + int port = options_get_number(global_options, "tmate-server-port"); + ssh_set_blocking(session, 0); ssh_options_set(session, SSH_OPTIONS_HOST, client->server_ip); ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity); @@ -281,6 +273,7 @@ static void on_ssh_client_event(struct tmate_ssh_client *client) ssh_options_set(session, SSH_OPTIONS_USER, "tmate"); ssh_options_set(session, SSH_OPTIONS_COMPRESSION, "yes"); + char *identity; if ((identity = get_identity())) { /* * FIXME libssh will continue with the next set of @@ -295,7 +288,8 @@ static void on_ssh_client_event(struct tmate_ssh_client *client) } client->state = SSH_CONNECT; - // fall through + } + // fall through case SSH_CONNECT: switch (ssh_connect(session)) { @@ -314,7 +308,15 @@ static void on_ssh_client_event(struct tmate_ssh_client *client) } // fall through - case SSH_AUTH_SERVER: + case SSH_AUTH_SERVER: { + ssh_key pubkey; + enum ssh_keytypes_e key_type; + unsigned char *hash; + ssize_t hash_len; + char *hash_str; + const char *server_hash_str; + int match; + #if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0, 9, 0) if (ssh_get_server_publickey(session, &pubkey) < 0) tmate_fatal("ssh_get_server_publickey"); @@ -379,6 +381,7 @@ static void on_ssh_client_event(struct tmate_ssh_client *client) on_ssh_auth_server_complete(client); client->state = SSH_AUTH_CLIENT_NONE; + } // fall through case SSH_AUTH_CLIENT_NONE: @@ -573,7 +576,6 @@ struct tmate_ssh_client *tmate_ssh_client_alloc(struct tmate_session *session, client->state = SSH_NONE; client->session = NULL; client->channel = NULL; - client->has_encoder = 0; return client; } diff --git a/tmate.h b/tmate.h index ec6d0f29..f4783dc8 100644 --- a/tmate.h +++ b/tmate.h @@ -130,7 +130,6 @@ struct tmate_ssh_client { char *server_ip; - int has_encoder; int state; /* From 9fe8b32293982bb85eb12b9c55991b6fa0dac400 Mon Sep 17 00:00:00 2001 From: Nicolas Viennot Date: Sun, 10 Nov 2019 16:29:05 -0500 Subject: [PATCH 45/75] Add foreground tip --- tmate-session.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tmate-session.c b/tmate-session.c index d88ec5a5..02f25c14 100644 --- a/tmate-session.c +++ b/tmate-session.c @@ -194,7 +194,8 @@ void tmate_session_start(void) tmate_set_val("foreground", "true"); tmate_info("To connect to the session locally, run: tmate -S %s attach", socket_path); } else { - cfg_add_cause("%s", "To see these messages again, run: tmate show-messages"); + cfg_add_cause("%s", "Tip: if you wish to use tmate for remote access, run tmate -F"); + cfg_add_cause("%s", "To see the following messages again, run: tmate show-messages"); cfg_add_cause("%s", "Press to dismiss"); cfg_add_cause("%s", "-----------------------------------------------------"); } From f895fe01b1ddd0f0dbd0d019c5f290c7650b7d3b Mon Sep 17 00:00:00 2001 From: Nicolas Viennot Date: Sun, 10 Nov 2019 22:27:23 -0500 Subject: [PATCH 46/75] Rename account-key -> api-key --- options-table.c | 2 +- tmux.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/options-table.c b/options-table.c index 4a20c548..e3362ba8 100644 --- a/options-table.c +++ b/options-table.c @@ -960,7 +960,7 @@ const struct options_table_entry options_table[] = { .default_str = "" }, - { .name = "tmate-account-key", + { .name = "tmate-api-key", .type = OPTIONS_TABLE_STRING, .scope = OPTIONS_TABLE_SERVER, .default_str = "" diff --git a/tmux.c b/tmux.c index b6b03346..53b984d7 100644 --- a/tmux.c +++ b/tmux.c @@ -64,7 +64,7 @@ usage(void) "Basic options:\n" " -n specify the session token instead of getting a random one\n" " -r same, but for the read-only token\n" - " -k specify the account-key, necessary for named sessions on tmate.io\n" + " -k specify an api-key, necessary for using named sessions on tmate.io\n" " -F set the foreground mode, useful for setting remote access\n" " -f set the config file path\n" " -S set the socket path, useful to issue commands to a running tmate instance\n" @@ -212,7 +212,7 @@ find_home(void) } #ifdef TMATE -static char *account_key; +static char *api_key; static char *session_name; static char *session_name_ro; static char *authorized_keys; @@ -226,7 +226,7 @@ void tmate_load_cli_options(void) val = NULL; \ } \ }) - SET_OPT("tmate-account-key", account_key); + SET_OPT("tmate-api-key", api_key); SET_OPT("tmate-session-name", session_name); SET_OPT("tmate-session-name-ro", session_name_ro); SET_OPT("tmate-authorized-keys", authorized_keys); @@ -310,7 +310,7 @@ main(int argc, char **argv) unsetenv("TMUX"); break; case 'k': - account_key = xstrdup(optarg); + api_key = xstrdup(optarg); break; case 'n': session_name = xstrdup(optarg); From 5e00bfa5e137e76c81888727712ced2b3fd99f5b Mon Sep 17 00:00:00 2001 From: Nicolas Viennot Date: Sat, 16 Nov 2019 17:08:46 -0500 Subject: [PATCH 47/75] Rephrase --- tmate-session.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tmate-session.c b/tmate-session.c index 02f25c14..62493278 100644 --- a/tmate-session.c +++ b/tmate-session.c @@ -194,10 +194,10 @@ void tmate_session_start(void) tmate_set_val("foreground", "true"); tmate_info("To connect to the session locally, run: tmate -S %s attach", socket_path); } else { - cfg_add_cause("%s", "Tip: if you wish to use tmate for remote access, run tmate -F"); - cfg_add_cause("%s", "To see the following messages again, run: tmate show-messages"); - cfg_add_cause("%s", "Press to dismiss"); - cfg_add_cause("%s", "-----------------------------------------------------"); + cfg_add_cause("%s", "Tip: if you wish to use tmate only for remote access, run: tmate -F"); + cfg_add_cause("%s", "To see the following messages again, run in a tmate session: tmate show-messages"); + cfg_add_cause("%s", "Press or to continue"); + cfg_add_cause("%s", "---------------------------------------------------------------------"); } send_authorized_keys(); From f0a4707ef35b04afb87092f11782f63776b3cdec Mon Sep 17 00:00:00 2001 From: Nicolas Viennot Date: Thu, 28 Nov 2019 16:30:32 -0500 Subject: [PATCH 48/75] Update dockerfile for size --- Dockerfile | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 8b736f63..2f6387c5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ ARG PLATFORM=amd64 -FROM ${PLATFORM}/alpine:3.10 +FROM ${PLATFORM}/alpine:3.10 AS build WORKDIR /build @@ -25,5 +25,13 @@ COPY *.c *.h autogen.sh Makefile.am configure.ac ./ RUN ./autogen.sh && ./configure --enable-static RUN make -j $(nproc) -RUN objcopy --only-keep-debug tmate tmate.symbols && strip tmate +RUN objcopy --only-keep-debug tmate tmate.symbols && chmod -x tmate.symbols && strip tmate RUN ./tmate -V + +FROM alpine:3.9 + +RUN apk --no-cache add bash +RUN mkdir /build +ENV PATH=/build:$PATH +COPY --from=build /build/tmate.symbols /build +COPY --from=build /build/tmate /build From cc01f3f13a73cba3021c072780a22d1fcbd0dceb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damian=20Szyma=C5=84ski?= Date: Fri, 29 Nov 2019 14:08:06 +0100 Subject: [PATCH 49/75] Add build on s390x and ppc64le --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index fc43a83f..5a83e0ed 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,6 +14,10 @@ matrix: env: PLATFORM=arm32v7 - arch: arm64 env: PLATFORM=arm64v8 + - arch: s390x + env: PLATFORM=s390x + - arch: ppc64le + env: PLATFORM=ppc64le script: - 'docker build . --tag local-$PLATFORM/tmate-build --build-arg PLATFORM=$PLATFORM' From ba6ac3a363ae7bdd4af946cc81a19f703d06907f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damian=20Szyma=C5=84ski?= Date: Fri, 6 Dec 2019 12:43:04 +0100 Subject: [PATCH 50/75] Update paths in build_static_release script (#178) --- build_static_release.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build_static_release.sh b/build_static_release.sh index 77b5d003..9cb35435 100755 --- a/build_static_release.sh +++ b/build_static_release.sh @@ -23,11 +23,11 @@ cd releases rm -rf $RELEASE_NAME mkdir -p $RELEASE_NAME -docker run --rm local-$PLATFORM/tmate-build cat tmate > $RELEASE_NAME/tmate +docker run --rm local-$PLATFORM/tmate-build cat /build/tmate > $RELEASE_NAME/tmate chmod +x $RELEASE_NAME/tmate tar -cf - $RELEASE_NAME | xz > tmate-$VERSION-static-linux-$PLATFORM.tar.xz rm -rf $RELEASE_NAME-symbols mkdir -p $RELEASE_NAME-symbols -docker run --rm local-$PLATFORM/tmate-build cat tmate.symbols > $RELEASE_NAME-symbols/tmate.symbols +docker run --rm local-$PLATFORM/tmate-build cat /build/tmate.symbols > $RELEASE_NAME-symbols/tmate.symbols tar -cf - $RELEASE_NAME-symbols | xz > dbg-symbols-tmate-$VERSION-static-linux-$PLATFORM.tar.xz From 9e3e39d66ddb4a610720fa37a5683c846d2a1ba6 Mon Sep 17 00:00:00 2001 From: Nicolas Viennot Date: Wed, 11 Mar 2020 11:30:33 -0400 Subject: [PATCH 51/75] Avoid initializing stdout twice Closes #190 --- log.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/log.c b/log.c index 12266aa4..45aaea46 100644 --- a/log.c +++ b/log.c @@ -61,6 +61,9 @@ log_get_level(void) void log_open_fp(FILE *f) { + if (log_file == f) + return; + if (log_file != NULL && !is_log_stdout()) fclose(log_file); From 339e6c43575244f72831654e5dda41c037febde7 Mon Sep 17 00:00:00 2001 From: Klemens Nanni Date: Thu, 2 Apr 2020 18:19:57 +0200 Subject: [PATCH 52/75] Include for global errno At least on OpenBSD the symbol `errno` is otherwise not defined; it is used in the `SSO()` macro and `send_authorized_keys()` function. --- tmate-session.c | 1 + tmate-ssh-client.c | 1 + 2 files changed, 2 insertions(+) diff --git a/tmate-session.c b/tmate-session.c index 62493278..5ba0896c 100644 --- a/tmate-session.c +++ b/tmate-session.c @@ -5,6 +5,7 @@ #include #include +#include #include #include #include diff --git a/tmate-ssh-client.c b/tmate-ssh-client.c index c52c166c..42c4e6a6 100644 --- a/tmate-ssh-client.c +++ b/tmate-ssh-client.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include From cbec43f56dfb48c2fb6e00faa2cb85443d4b7d8f Mon Sep 17 00:00:00 2001 From: Nicolas Viennot Date: Tue, 14 Apr 2020 18:22:04 -0400 Subject: [PATCH 53/75] Better debugging when keys are not matching --- tmate-ssh-client.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tmate-ssh-client.c b/tmate-ssh-client.c index 42c4e6a6..995c92a7 100644 --- a/tmate-ssh-client.c +++ b/tmate-ssh-client.c @@ -328,7 +328,7 @@ static void on_ssh_client_event(struct tmate_ssh_client *client) if (ssh_get_publickey_hash(pubkey, SSH_PUBLICKEY_HASH_SHA256, &hash, &hash_len) < 0) { - kill_ssh_client(client, "Cannot authenticate server"); + kill_ssh_client(client, "Failed to get server fingerprint"); return; } @@ -362,15 +362,17 @@ static void on_ssh_client_event(struct tmate_ssh_client *client) } match = !strcmp(hash_str, server_hash_str); + if (!match) { + kill_ssh_client(client, "Server fingerprint not recognized: " + "`%s', expected `%s'", server_hash_str, hash_str); + } ssh_key_free(pubkey); ssh_clean_pubkey_hash(&hash); free(hash_str); - if (!match) { - kill_ssh_client(client, "Cannot authenticate server"); + if (!match) return; - } /* * At this point, we abort other connection attempts to the From f6a4ae6042f4bb2b6db8eda23df31d8b788a7978 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Jacke?= Date: Thu, 18 Feb 2021 11:58:52 +0100 Subject: [PATCH 54/75] client: set IPTOS_LOWDELAY on TCP connection this helps edge routers to prioritize our interactive network traffic. --- tmate-ssh-client.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tmate-ssh-client.c b/tmate-ssh-client.c index 995c92a7..ce8d5a5a 100644 --- a/tmate-ssh-client.c +++ b/tmate-ssh-client.c @@ -183,6 +183,7 @@ static void tune_socket_opts(int fd) } \ }) + SSO(IPPROTO_IP, IP_TOS, 0x10); /* IPTOS_LOWDELAY */ SSO(IPPROTO_TCP, TCP_NODELAY, 1); SSO(SOL_SOCKET, SO_KEEPALIVE, 1); #ifdef TCP_KEEPALIVE From 8123fa34f847c658f7cedf154dd4cf966047e6bf Mon Sep 17 00:00:00 2001 From: hpcbjdic Date: Tue, 24 Mar 2020 14:56:06 +0100 Subject: [PATCH 55/75] enable redefinition of TMUX_CONF Without the added #ifndef / #endif it's not possible to _actually_ redefine TMUX_CONF by means of the compiler flag -DTMUX_CONF=... as done by the build system. The same patch has also been applied to tmux, cf. master at https://github.com/tmux/tmux/blob/master/tmux.h. --- tmux.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tmux.h b/tmux.h index c60a044e..b38615b6 100644 --- a/tmux.h +++ b/tmux.h @@ -53,7 +53,9 @@ struct tmuxpeer; struct tmuxproc; /* Default global configuration file. */ +#ifndef TMUX_CONF #define TMUX_CONF "/etc/tmux.conf" +#endif /* * Minimum layout cell size, NOT including separator line. The scroll region From e5ce3f04d2851b4c825430f87620cc42d1d946d6 Mon Sep 17 00:00:00 2001 From: Sergio de Almeida Cipriano Junior Date: Wed, 18 Nov 2020 10:59:07 -0300 Subject: [PATCH 56/75] Fix typo in ssh client --- tmate-ssh-client.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tmate-ssh-client.c b/tmate-ssh-client.c index ce8d5a5a..bed79e95 100644 --- a/tmate-ssh-client.c +++ b/tmate-ssh-client.c @@ -453,7 +453,7 @@ SSH_NEW_CHANNEL: ssh_get_error(session)); return; case SSH_OK: - tmate_debug("Session opened, initalizing tmate"); + tmate_debug("Session opened, initializing tmate"); client->state = SSH_BOOTSTRAP; } // fall through From 808b5645641c82cc09e5488ea0466908a514bba5 Mon Sep 17 00:00:00 2001 From: Sergio de Almeida Cipriano Junior Date: Wed, 18 Nov 2020 11:30:37 -0300 Subject: [PATCH 57/75] Update manpage --- tmux.1 | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/tmux.1 b/tmux.1 index b55b3682..c90b5560 100644 --- a/tmux.1 +++ b/tmux.1 @@ -19,10 +19,11 @@ .Os .Sh NAME .Nm tmate -.Nd terminal multiplexer +.Nd terminal multiplexer with instant terminal sharing .Sh SYNOPSIS .Nm tmate .Bk -words +.Op show-messages .Op Fl 2CluvV .Op Fl c Ar shell-command .Op Fl f Ar file @@ -32,13 +33,24 @@ .Ek .Sh DESCRIPTION .Nm -is a terminal multiplexer: +is a terminal multiplexer with instant terminal sharing: it enables a number of terminals to be created, accessed, and -controlled from a single screen. +controlled from a single screen and be shared with another mates. .Nm may be detached from a screen and continue running in the background, -then later reattached. +then later reattached, like as a daemon. +.Pp +.Nm +provides an instant pairing solution, allowing you to share a terminal +with one or several teammates. Together with a voice call, it's almost like +pairing in person. The terminal sharing works by using SSH connections to +backend servers maintained by tmate upstream developers; teammates need to be +given a randomly-generated token to be able to join a session. +.Pp +.Nm +is a modified version of tmux, and uses the same configurations such as +keybindings, color schemes, etc. .Pp When .Nm @@ -47,9 +59,9 @@ is started it creates a new with a single .Em window and displays it on screen. -A status line at the bottom of the screen -shows information on the current session -and is used to enter interactive commands. +A status line at the bottom of the screen shows information +on the current session, such as ssh command to share with +your mate, and is used to enter interactive commands. .Pp A session is a single collection of .Em pseudo terminals From c9ec7af63238b0a47bf659729d32dde2066ce60f Mon Sep 17 00:00:00 2001 From: n0vember Date: Wed, 27 Jan 2021 15:53:45 +0100 Subject: [PATCH 58/75] add basic information for -a option in man page and help text --- tmux.1 | 4 ++++ tmux.c | 1 + 2 files changed, 5 insertions(+) diff --git a/tmux.1 b/tmux.1 index c90b5560..55f88c98 100644 --- a/tmux.1 +++ b/tmux.1 @@ -110,6 +110,10 @@ The options are as follows: Force .Nm to assume the terminal supports 256 colours. +.It Fl a Ar file +Limit access to the public keys listed in the +.Ar file +given as argument. .It Fl C Start in control mode (see the .Sx CONTROL MODE diff --git a/tmux.c b/tmux.c index 53b984d7..730c2dfc 100644 --- a/tmux.c +++ b/tmux.c @@ -68,6 +68,7 @@ usage(void) " -F set the foreground mode, useful for setting remote access\n" " -f set the config file path\n" " -S set the socket path, useful to issue commands to a running tmate instance\n" + " -a limit access to ssh public keys listed in provided file\n" " -v set verbosity (can be repeated)\n" " -V print version\n" ,__progname); From be4a88507e082e0e8e591e18b08374ff591b3980 Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Sat, 5 Mar 2022 01:33:21 +0100 Subject: [PATCH 59/75] chore: add FUNDING.yml --- .github/FUNDING.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 00000000..ea4e6439 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +github: nviennot From 169eb64b99719eadccba1f9a00856b68b589ef35 Mon Sep 17 00:00:00 2001 From: neil Date: Wed, 3 Aug 2022 18:19:32 +0800 Subject: [PATCH 60/75] Add FreeBSD build by https://github.com/vmactions/freebsd-vm --- .github/workflows/FreeBSD.yml | 40 +++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 .github/workflows/FreeBSD.yml diff --git a/.github/workflows/FreeBSD.yml b/.github/workflows/FreeBSD.yml new file mode 100644 index 00000000..3a16af9f --- /dev/null +++ b/.github/workflows/FreeBSD.yml @@ -0,0 +1,40 @@ +name: FreeBSD +on: + push: + branches: + - '*' + paths: + - '**.c' + - '**.h' + - 'compat/*' + - '.github/workflows/FreeBSD.yml' + pull_request: + branches: + - '*' + paths: + - '**.c' + - '**.h' + - 'compat/*' + - '.github/workflows/FreeBSD.yml' + + + +jobs: + FreeBSD: + runs-on: macos-12 + steps: + - uses: actions/checkout@v2 + - uses: vmactions/freebsd-vm@v0 + with: + prepare: | + pkg install -y gmake automake autoconf libtool pkgconf libevent msgpack libssh + usesh: true + run: | + autoupdate + ./autogen.sh + ./configure + make + make install + + + From a258907cf8a8888cbb895aa478b697200081c006 Mon Sep 17 00:00:00 2001 From: neil Date: Wed, 3 Aug 2022 18:20:33 +0800 Subject: [PATCH 61/75] add NetBSD test by https://github.com/vmactions/netbsd-vm --- .github/workflows/NetBSD.yml | 40 ++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 .github/workflows/NetBSD.yml diff --git a/.github/workflows/NetBSD.yml b/.github/workflows/NetBSD.yml new file mode 100644 index 00000000..0566d3b9 --- /dev/null +++ b/.github/workflows/NetBSD.yml @@ -0,0 +1,40 @@ +name: NetBSD +on: + push: + branches: + - '*' + paths: + - '**.c' + - '**.h' + - 'compat/*' + - '.github/workflows/NetBSD.yml' + pull_request: + branches: + - '*' + paths: + - '**.c' + - '**.h' + - 'compat/*' + - '.github/workflows/NetBSD.yml' + + + +jobs: + NetBSD: + runs-on: macos-12 + steps: + - uses: actions/checkout@v2 + - uses: vmactions/netbsd-vm@v0 + with: + prepare: | + pkg_add gmake automake autoconf libtool pkgconf libevent msgpack libssh + usesh: true + run: | + autoupdate + ./autogen.sh + ./configure + make + make install + + + From b1079b43930b42f53f6f1579fd1d6afcf9134aeb Mon Sep 17 00:00:00 2001 From: neil Date: Wed, 3 Aug 2022 18:21:37 +0800 Subject: [PATCH 62/75] add OpenBSD build by https://github.com/vmactions/openbsd-vm --- .github/workflows/OpenBSD.yml | 44 +++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 .github/workflows/OpenBSD.yml diff --git a/.github/workflows/OpenBSD.yml b/.github/workflows/OpenBSD.yml new file mode 100644 index 00000000..fbeda51d --- /dev/null +++ b/.github/workflows/OpenBSD.yml @@ -0,0 +1,44 @@ +name: OpenBSD +on: + push: + branches: + - '*' + paths: + - '**.c' + - '**.h' + - 'compat/*' + - '.github/workflows/OpenBSD.yml' + pull_request: + branches: + - '*' + paths: + - '**.c' + - '**.h' + - 'compat/*' + - '.github/workflows/OpenBSD.yml' + + + +jobs: + OpenBSD: + runs-on: macos-12 + steps: + - uses: actions/checkout@v2 + - uses: vmactions/openbsd-vm@v0 + with: + prepare: | + pkg_add gmake automake-1.16.3 autoconf-2.71 libtool pkgconf libevent msgpack libssh gcc-11.2.0p2 + usesh: true + run: | + ln -s /usr/local/bin/egcc /usr/local/bin/gcc + autoupdate + aclocal --print-ac-dir + export AUTOMAKE_VERSION=1.16 + export AUTOCONF_VERSION=2.71 + ./autogen.sh + ./configure + make + make install + + + From 577e04df6c746acbca0b98e12f6ca143bf031be1 Mon Sep 17 00:00:00 2001 From: neil Date: Wed, 3 Aug 2022 23:33:18 +0800 Subject: [PATCH 63/75] fix --- .github/workflows/OpenBSD.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/OpenBSD.yml b/.github/workflows/OpenBSD.yml index fbeda51d..3c884006 100644 --- a/.github/workflows/OpenBSD.yml +++ b/.github/workflows/OpenBSD.yml @@ -31,10 +31,9 @@ jobs: usesh: true run: | ln -s /usr/local/bin/egcc /usr/local/bin/gcc - autoupdate - aclocal --print-ac-dir export AUTOMAKE_VERSION=1.16 export AUTOCONF_VERSION=2.71 + autoupdate ./autogen.sh ./configure make From ef11a7b30ed743051e703b5745fa41916ae0be9f Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 6 Aug 2022 13:39:23 +0800 Subject: [PATCH 64/75] fix OpenBSD.yml --- .github/workflows/OpenBSD.yml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/.github/workflows/OpenBSD.yml b/.github/workflows/OpenBSD.yml index 3c884006..53f06485 100644 --- a/.github/workflows/OpenBSD.yml +++ b/.github/workflows/OpenBSD.yml @@ -27,10 +27,17 @@ jobs: - uses: vmactions/openbsd-vm@v0 with: prepare: | - pkg_add gmake automake-1.16.3 autoconf-2.71 libtool pkgconf libevent msgpack libssh gcc-11.2.0p2 + pkg_add automake-1.16.3 autoconf-2.71 libtool pkgconf libevent msgpack libssh usesh: true run: | - ln -s /usr/local/bin/egcc /usr/local/bin/gcc + sed -i 's,,,' *.[ch] + curl https://raw.githubusercontent.com/openbsd/ports/master/sysutils/tmate/patches/patch-Makefile_am | patch + curl https://raw.githubusercontent.com/openbsd/ports/master/sysutils/tmate/patches/patch-server_c | patch + curl https://raw.githubusercontent.com/openbsd/ports/master/sysutils/tmate/patches/patch-tmate-debug_c | patch + curl https://raw.githubusercontent.com/openbsd/ports/master/sysutils/tmate/patches/patch-tmate_h | patch + curl https://raw.githubusercontent.com/openbsd/ports/master/sysutils/tmate/patches/patch-tmux_c | patch + curl https://raw.githubusercontent.com/openbsd/ports/master/sysutils/tmate/patches/patch-tmux_h | patch + curl https://raw.githubusercontent.com/openbsd/ports/master/sysutils/tmate/patches/patch-osdep-openbsd_c | patch export AUTOMAKE_VERSION=1.16 export AUTOCONF_VERSION=2.71 autoupdate From 17d4a8a7dfa25bcf3ddb336916010f905f2f4183 Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 6 Aug 2022 13:45:53 +0800 Subject: [PATCH 65/75] fix OpenBSD.yml --- .github/workflows/OpenBSD.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/OpenBSD.yml b/.github/workflows/OpenBSD.yml index 53f06485..8fb7901b 100644 --- a/.github/workflows/OpenBSD.yml +++ b/.github/workflows/OpenBSD.yml @@ -27,7 +27,7 @@ jobs: - uses: vmactions/openbsd-vm@v0 with: prepare: | - pkg_add automake-1.16.3 autoconf-2.71 libtool pkgconf libevent msgpack libssh + pkg_add automake-1.16.3 autoconf-2.71 libtool pkgconf libevent msgpack libssh curl usesh: true run: | sed -i 's,,,' *.[ch] From fde4b58228cd8226e7128bf101e2fe569eed5882 Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 6 Aug 2022 13:46:36 +0800 Subject: [PATCH 66/75] add MacOS.yml --- .github/workflows/MacOS.yml | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 .github/workflows/MacOS.yml diff --git a/.github/workflows/MacOS.yml b/.github/workflows/MacOS.yml new file mode 100644 index 00000000..5e118ee7 --- /dev/null +++ b/.github/workflows/MacOS.yml @@ -0,0 +1,37 @@ +name: MacOS +on: + push: + branches: + - '*' + paths: + - '**.c' + - '**.h' + - 'compat/*' + - '.github/workflows/MacOS.yml' + pull_request: + branches: + - '*' + paths: + - '**.c' + - '**.h' + - 'compat/*' + - '.github/workflows/MacOS.yml' + + + +jobs: + NetBSD: + runs-on: macos-latest + steps: + - uses: actions/checkout@v2 + - run: | + brew install automake + autoupdate + ./autogen.sh + ./configure + make + make install + + + + From 05a849ba2b29351419ad2034994111388c0817b7 Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 6 Aug 2022 13:47:18 +0800 Subject: [PATCH 67/75] fix MacOS.yml --- .github/workflows/MacOS.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/MacOS.yml b/.github/workflows/MacOS.yml index 5e118ee7..db1c9ca0 100644 --- a/.github/workflows/MacOS.yml +++ b/.github/workflows/MacOS.yml @@ -20,7 +20,7 @@ on: jobs: - NetBSD: + MacOS: runs-on: macos-latest steps: - uses: actions/checkout@v2 From 7c0bbf3e164d869073012b7fffd896869337b143 Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 6 Aug 2022 13:56:06 +0800 Subject: [PATCH 68/75] fix MacOS.yml --- .github/workflows/MacOS.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/MacOS.yml b/.github/workflows/MacOS.yml index db1c9ca0..37293260 100644 --- a/.github/workflows/MacOS.yml +++ b/.github/workflows/MacOS.yml @@ -25,7 +25,7 @@ jobs: steps: - uses: actions/checkout@v2 - run: | - brew install automake + brew install automake msgpack autoupdate ./autogen.sh ./configure From 17fcc8b76d28ae5e59b59a08a642e462eea34221 Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 6 Aug 2022 13:57:59 +0800 Subject: [PATCH 69/75] fix MacOS.yml --- .github/workflows/MacOS.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/MacOS.yml b/.github/workflows/MacOS.yml index 37293260..3dc5247e 100644 --- a/.github/workflows/MacOS.yml +++ b/.github/workflows/MacOS.yml @@ -25,7 +25,7 @@ jobs: steps: - uses: actions/checkout@v2 - run: | - brew install automake msgpack + brew install automake msgpack libssh autoupdate ./autogen.sh ./configure From 9a1aa9ae9d9c40b6d583355246089a9468dd03bc Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 6 Aug 2022 14:29:15 +0800 Subject: [PATCH 70/75] add Ubuntu.yml --- .github/workflows/Ubuntu.yml | 37 ++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 .github/workflows/Ubuntu.yml diff --git a/.github/workflows/Ubuntu.yml b/.github/workflows/Ubuntu.yml new file mode 100644 index 00000000..581e616d --- /dev/null +++ b/.github/workflows/Ubuntu.yml @@ -0,0 +1,37 @@ +name: Ubuntu +on: + push: + branches: + - '*' + paths: + - '**.c' + - '**.h' + - 'compat/*' + - '.github/workflows/Ubuntu.yml' + pull_request: + branches: + - '*' + paths: + - '**.c' + - '**.h' + - 'compat/*' + - '.github/workflows/Ubuntu.yml' + + + +jobs: + Ubuntu: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - run: | + apt-get install -y build-essential automake libtool libevent-dev libncurses5-dev libmsgpack-dev libssh-dev pkg-config + autoupdate + ACLOCAL_PATH=/usr/share/aclocal ./autogen.sh + ./configure + make + make install + + + + From 2ff8bc134d381c88eba8f382625642e5aec8d5da Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 6 Aug 2022 14:33:12 +0800 Subject: [PATCH 71/75] fix Ubuntu.yml --- .github/workflows/Ubuntu.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/Ubuntu.yml b/.github/workflows/Ubuntu.yml index 581e616d..7c8dea57 100644 --- a/.github/workflows/Ubuntu.yml +++ b/.github/workflows/Ubuntu.yml @@ -25,7 +25,7 @@ jobs: steps: - uses: actions/checkout@v2 - run: | - apt-get install -y build-essential automake libtool libevent-dev libncurses5-dev libmsgpack-dev libssh-dev pkg-config + sudo apt-get install -y build-essential automake libtool libevent-dev libncurses5-dev libmsgpack-dev libssh-dev pkg-config autoupdate ACLOCAL_PATH=/usr/share/aclocal ./autogen.sh ./configure From 3efc8496cc90d55dd9bc44d4b5f529ac9760bf66 Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 6 Aug 2022 14:34:47 +0800 Subject: [PATCH 72/75] fix Ubuntu.yml --- .github/workflows/Ubuntu.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/Ubuntu.yml b/.github/workflows/Ubuntu.yml index 7c8dea57..cecf39b9 100644 --- a/.github/workflows/Ubuntu.yml +++ b/.github/workflows/Ubuntu.yml @@ -30,7 +30,7 @@ jobs: ACLOCAL_PATH=/usr/share/aclocal ./autogen.sh ./configure make - make install + sudo make install From 15001bfa7739b144969c1181e66c65f0cb14e614 Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 6 Aug 2022 14:57:15 +0800 Subject: [PATCH 73/75] fix --- .github/workflows/FreeBSD.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/FreeBSD.yml b/.github/workflows/FreeBSD.yml index 3a16af9f..e879618e 100644 --- a/.github/workflows/FreeBSD.yml +++ b/.github/workflows/FreeBSD.yml @@ -27,7 +27,7 @@ jobs: - uses: vmactions/freebsd-vm@v0 with: prepare: | - pkg install -y gmake automake autoconf libtool pkgconf libevent msgpack libssh + pkg install -y automake autoconf libtool pkgconf libevent msgpack libssh usesh: true run: | autoupdate From 6cb27ead4e77ba8cc15982d909fe57c074239434 Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 6 Aug 2022 15:04:07 +0800 Subject: [PATCH 74/75] fix NetBSD.yml --- .github/workflows/NetBSD.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/NetBSD.yml b/.github/workflows/NetBSD.yml index 0566d3b9..0bb0924a 100644 --- a/.github/workflows/NetBSD.yml +++ b/.github/workflows/NetBSD.yml @@ -27,7 +27,7 @@ jobs: - uses: vmactions/netbsd-vm@v0 with: prepare: | - pkg_add gmake automake autoconf libtool pkgconf libevent msgpack libssh + pkg_add automake autoconf libtool pkgconf libevent msgpack libssh usesh: true run: | autoupdate From ac919516f4f1b10ec928e20b3a5034d18f609d68 Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 6 Aug 2022 15:05:07 +0800 Subject: [PATCH 75/75] add DragonflyBSD by https://github.com/vmactions/dragonflybsd-vm --- .github/workflows/DragonflyBSD.yml | 41 ++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 .github/workflows/DragonflyBSD.yml diff --git a/.github/workflows/DragonflyBSD.yml b/.github/workflows/DragonflyBSD.yml new file mode 100644 index 00000000..f014da9b --- /dev/null +++ b/.github/workflows/DragonflyBSD.yml @@ -0,0 +1,41 @@ +name: DragonflyBSD +on: + push: + branches: + - '*' + paths: + - '**.c' + - '**.h' + - 'compat/*' + - '.github/workflows/DragonflyBSD.yml' + pull_request: + branches: + - '*' + paths: + - '**.c' + - '**.h' + - 'compat/*' + - '.github/workflows/DragonflyBSD.yml' + + + +jobs: + DragonflyBSD: + runs-on: macos-12 + steps: + - uses: actions/checkout@v2 + - uses: vmactions/dragonflybsd-vm@v0 + with: + prepare: | + pkg install -y automake autoconf libtool pkgconf libevent msgpack libssh gsed + usesh: true + run: | + gsed -i "s/OK/0/g" tty-term.c + autoupdate + ./autogen.sh + ./configure + make + make install + + +