diff --git a/client.c b/client.c index 552cfe90..c94cbb22 100644 --- a/client.c +++ b/client.c @@ -324,6 +324,10 @@ client_send_identify(int flags) char *term; int fd; +#ifdef TMATE_SLAVE + strcpy(data.ip_address, tmate_client.ip_address); +#endif + data.flags = flags; if (getcwd(data.cwd, sizeof data.cwd) == NULL) diff --git a/server-client.c b/server-client.c index 66537c9d..1372ea67 100644 --- a/server-client.c +++ b/server-client.c @@ -109,6 +109,10 @@ server_client_create(int fd) evtimer_set(&c->repeat_timer, server_client_repeat_timer, c); +#ifdef TMATE_SLAVE + c->ip_address = NULL; +#endif + for (i = 0; i < ARRAY_LENGTH(&clients); i++) { if (ARRAY_ITEM(&clients, i) == NULL) { ARRAY_SET(&clients, i, c); @@ -154,6 +158,10 @@ server_client_lost(struct client *c) } log_debug("lost client %d", c->ibuf.fd); +#ifdef TMATE_SLAVE + tmate_notify_client_left(c); +#endif + /* * If CLIENT_TERMINAL hasn't been set, then tty_init hasn't been called * and tty_free might close an unrelated fd. @@ -194,6 +202,11 @@ server_client_lost(struct client *c) cmdq_free(c->cmdq); c->cmdq = NULL; +#ifdef TMATE_SLAVE + free(c->ip_address); + c->ip_address = NULL; +#endif + environ_free(&c->environ); close(c->ibuf.fd); @@ -1013,6 +1026,11 @@ server_client_msg_identify( if (!(data->flags & IDENTIFY_CONTROL)) c->flags |= CLIENT_TERMINAL; + +#ifdef TMATE_SLAVE + c->ip_address = xstrdup(data->ip_address); + tmate_notify_client_join(c); +#endif } /* Handle shell message. */ diff --git a/tmate-decoder.c b/tmate-decoder.c index 34701ebe..5fca3722 100644 --- a/tmate-decoder.c +++ b/tmate-decoder.c @@ -102,8 +102,10 @@ static void tmate_header(struct tmate_unpacker *uk) if (protocol != 1) decoder_error(); - tmate_debug("new master, protocol: %d", protocol); - tmate_reply_header(0); + tmate_debug("new master, protocol version: %d", protocol); + + tmate_notify("Remote session: ssh %s@%s", + tmate_session_token, TMATE_HOST); } extern u_int next_window_pane_id; diff --git a/tmate-encoder.c b/tmate-encoder.c index 8c06e4a5..52d78aa4 100644 --- a/tmate-encoder.c +++ b/tmate-encoder.c @@ -28,16 +28,63 @@ void tmate_encoder_init(struct tmate_encoder *encoder) #define pack(what, ...) msgpack_pack_##what(&tmate_encoder->pk, __VA_ARGS__) -void tmate_reply_header(unsigned long flags) +void printflike1 tmate_notify(const char *fmt, ...) { - char remote_session[256]; + va_list ap; + char msg[1024]; - pack(array, 3); - pack(int, TMATE_REPLY_HEADER); - pack(int, flags); + va_start(ap, fmt); + vsnprintf(msg, sizeof(msg), fmt, ap); + va_end(ap); - sprintf(remote_session, "ssh %s@tmate.io", tmate_session_token); - pack(string, remote_session); + pack(array, 2); + pack(int, TMATE_NOTIFY); + pack(string, msg); +} + +static int num_clients(void) +{ + unsigned int i, count = 0; + + for (i = 0; i < ARRAY_LENGTH(&clients); i++) { + if (ARRAY_ITEM(&clients, i)) + count++; + } + + return count; +} + +static void mate_notify_message(struct client *c, int join) +{ + char buf[100]; + int count; + static int multi_client; + + count = num_clients(); + if (count > 1) + multi_client = 1; + + if (multi_client) + sprintf(buf, " -- %d mate%s %sconnected", + count, + count == 1 ? " is" : "s are", + (join || !count) ? "" : "still "); + + tmate_notify("%s mate has %s the session (%s)%s", + multi_client ? "A" : "Your", + join ? "join" : "left", + c->ip_address, + multi_client ? buf : ""); +} + +void tmate_notify_client_join(struct client *c) +{ + mate_notify_message(c, 1); +} + +void tmate_notify_client_left(struct client *c) +{ + mate_notify_message(c, 0); } void tmate_client_resize(u_int sx, u_int sy) diff --git a/tmate-ssh-server.c b/tmate-ssh-server.c index d894ce60..6908386a 100644 --- a/tmate-ssh-server.c +++ b/tmate-ssh-server.c @@ -248,10 +248,11 @@ static int get_ip(int fd, char *dst, size_t len) return 0; } +struct tmate_ssh_client tmate_client; + void tmate_ssh_server_main(int port) { - struct tmate_ssh_client _client; - struct tmate_ssh_client *client = &_client; + struct tmate_ssh_client *client = &tmate_client; ssh_bind bind; pid_t pid; diff --git a/tmate.h b/tmate.h index fb0cd4fd..792f4781 100644 --- a/tmate.h +++ b/tmate.h @@ -17,8 +17,10 @@ do { \ /* tmate-encoder.c */ +#define TMATE_HOST "tmate.io" + enum tmate_client_commands { - TMATE_REPLY_HEADER, + TMATE_NOTIFY, TMATE_CLIENT_PANE_KEY, TMATE_CLIENT_RESIZE, TMATE_CLIENT_EXEC_CMD, @@ -32,7 +34,10 @@ struct tmate_encoder { extern void tmate_encoder_init(struct tmate_encoder *encoder); -extern void tmate_reply_header(unsigned long flags); +extern void printflike1 tmate_notify(const char *fmt, ...); +extern void tmate_notify_client_join(struct client *c); +extern void tmate_notify_client_left(struct client *c); + extern void tmate_client_resize(u_int sx, u_int sy); extern void tmate_client_pane_key(int pane_id, int key); extern void tmate_client_cmd(int client_id, const char *cmd); @@ -110,6 +115,7 @@ extern void tmate_flush_pty(struct tmate_ssh_client *client); #define SSH_BANNER "tmate" +extern struct tmate_ssh_client tmate_client; extern void tmate_ssh_server_main(int port); /* tmate-slave.c */ diff --git a/tmux.h b/tmux.h index f3141765..daeb3445 100644 --- a/tmux.h +++ b/tmux.h @@ -477,6 +477,10 @@ struct msg_identify_data { char term[TERMINAL_LENGTH]; +#ifdef TMATE_SLAVE + char ip_address[64]; +#endif + #define IDENTIFY_UTF8 0x1 #define IDENTIFY_256COLOURS 0x2 #define IDENTIFY_88COLOURS 0x4 @@ -1375,6 +1379,10 @@ struct client { struct cmd_q *cmdq; int references; + +#ifdef TMATE_SLAVE + char *ip_address; +#endif }; ARRAY_DECL(clients, struct client *);