From: Shuanglei Tao Date: Sun, 14 Apr 2019 14:21:21 +0000 (+0800) Subject: server: add support for cli args via url X-Git-Url: http://git.prime8.dev/?a=commitdiff_plain;h=74e091f9543e6025f5454a436b467941b8cb8b60;p=ttyd.git server: add support for cli args via url --- diff --git a/html/js/app.js b/html/js/app.js index 16965ff..ff18f70 100644 --- a/html/js/app.js +++ b/html/js/app.js @@ -172,7 +172,7 @@ function handleReceive(zsession) { var terminalContainer = document.getElementById('terminal-container'), httpsEnabled = window.location.protocol === 'https:', url = (httpsEnabled ? 'wss://' : 'ws://') + window.location.host + window.location.pathname - + (window.location.pathname.endsWith('/') ? '' : '/') + 'ws', + + (window.location.pathname.endsWith('/') ? '' : '/') + 'ws' + window.location.search, textDecoder = new TextDecoder(), textEncoder = new TextEncoder(), authToken = (typeof tty_auth_token !== 'undefined') ? tty_auth_token : null, diff --git a/man/ttyd.1 b/man/ttyd.1 index a5197cd..be484ff 100644 --- a/man/ttyd.1 +++ b/man/ttyd.1 @@ -58,6 +58,11 @@ Cross platform: macOS, Linux, FreeBSD/OpenBSD, OpenWrt/LEDE, Windows \-r, \-\-reconnect Time to reconnect for the client in seconds (default: 10) +.PP +\-a, \-\-url\-arg + Allow client to send command line arguments in URL (eg: +\[la]http://localhost:7681?arg=foo&arg=bar\[ra]) + .PP \-R, \-\-readonly Do not allow clients to write to the TTY diff --git a/man/ttyd.man.md b/man/ttyd.man.md index 47ef981..4169239 100644 --- a/man/ttyd.man.md +++ b/man/ttyd.man.md @@ -40,6 +40,9 @@ ttyd 1 "September 2016" ttyd "User Manual" -r, --reconnect Time to reconnect for the client in seconds (default: 10) + -a, --url-arg + Allow client to send command line arguments in URL (eg: http://localhost:7681?arg=foo&arg=bar) + -R, --readonly Do not allow clients to write to the TTY diff --git a/src/index.html b/src/index.html index 2ec7eb9..5c029ec 100644 --- a/src/index.html +++ b/src/index.html @@ -1 +1 @@ -ttyd - Terminal
\ No newline at end of file +ttyd - Terminal
\ No newline at end of file diff --git a/src/protocol.c b/src/protocol.c index 8e1e4b7..027cdff 100644 --- a/src/protocol.c +++ b/src/protocol.c @@ -158,6 +158,10 @@ cleanup: if (client->buffer != NULL) free(client->buffer); + for (int i = 0; i < client->argc; i++) { + free(client->args[i]); + } + pthread_mutex_destroy(&client->mutex); // remove from client list @@ -166,11 +170,21 @@ cleanup: void * thread_run_command(void *args) { - struct tty_client *client; + struct tty_client *client = (struct tty_client *) args; + + // append url args to arguments + char *argv[server->argc + client->argc + 1]; + int i, n = 0; + for (i = 0; i < server->argc; i++) { + argv[n++] = server->argv[i]; + } + for (i = 0; i < client->argc; i++) { + argv[n++] = client->args[i]; + } + argv[n] = NULL; + int pty; fd_set des_set; - - client = (struct tty_client *) args; pid_t pid = forkpty(&pty, NULL, NULL, NULL); switch (pid) { @@ -184,7 +198,7 @@ thread_run_command(void *args) { } // Don't pass the web socket onto child processes close(lws_get_socket_fd(client->wsi)); - if (execvp(server->argv[0], server->argv) < 0) { + if (execvp(argv[0], argv) < 0) { perror("execvp"); pthread_exit((void *) 1); } @@ -264,6 +278,18 @@ callback_tty(struct lws *wsi, enum lws_callback_reasons reason, client->buffer = NULL; client->state = STATE_INIT; client->pty_len = 0; + client->argc = 0; + + if (server->url_arg) { + while (lws_hdr_copy_fragment(wsi, buf, sizeof(buf), WSI_TOKEN_HTTP_URI_ARGS, n++) > 0) { + if (strncmp(buf, "arg=", 4) == 0) { + client->args = xrealloc(client->args, (client->argc + 1) * sizeof(char *)); + client->args[client->argc] = strdup(&buf[4]); + client->argc++; + } + } + } + pthread_mutex_init(&client->mutex, NULL); pthread_cond_init(&client->cond, NULL); lws_get_peer_addresses(wsi, lws_get_socket_fd(wsi), @@ -274,8 +300,8 @@ callback_tty(struct lws *wsi, enum lws_callback_reasons reason, LIST_INSERT_HEAD(&server->clients, client, list); server->client_count++; pthread_mutex_unlock(&server->mutex); - lws_hdr_copy(wsi, buf, sizeof(buf), WSI_TOKEN_GET_URI); + lws_hdr_copy(wsi, buf, sizeof(buf), WSI_TOKEN_GET_URI); lwsl_notice("WS %s - %s (%s), clients: %d\n", buf, client->address, client->hostname, server->client_count); break; diff --git a/src/server.c b/src/server.c index 219eb36..ff848aa 100644 --- a/src/server.c +++ b/src/server.c @@ -46,11 +46,12 @@ static const struct option options[] = { {"signal", required_argument, NULL, 's'}, {"reconnect", required_argument, NULL, 'r'}, {"index", required_argument, NULL, 'I'}, - {"ipv6", no_argument, NULL, '6'}, + {"ipv6", no_argument, NULL, '6'}, {"ssl", no_argument, NULL, 'S'}, {"ssl-cert", required_argument, NULL, 'C'}, {"ssl-key", required_argument, NULL, 'K'}, {"ssl-ca", required_argument, NULL, 'A'}, + {"url-arg", no_argument, NULL, 'a'}, {"readonly", no_argument, NULL, 'R'}, {"check-origin", no_argument, NULL, 'O'}, {"max-clients", required_argument, NULL, 'm'}, @@ -77,6 +78,7 @@ void print_help() { " -g, --gid Group id to run with\n" " -s, --signal Signal to send to the command when exit it (default: 1, SIGHUP)\n" " -r, --reconnect Time to reconnect for the client in seconds (default: 10)\n" + " -a, --url-arg Allow client to send command line arguments in URL (eg: http://localhost:7681?arg=foo&arg=bar)\n" " -R, --readonly Do not allow clients to write to the TTY\n" " -t, --client-option Send option to client (format: key=value), repeat to add more options\n" " -T, --terminal-type Terminal type to report, default: xterm-256color\n" @@ -126,6 +128,7 @@ tty_server_new(int argc, char **argv, int start) { } } ts->argv[cmd_argc] = NULL; + ts->argc = cmd_argc; ts->command = xmalloc(cmd_len + 1); char *ptr = ts->command; @@ -264,6 +267,9 @@ main(int argc, char **argv) { case 'd': debug_level = atoi(optarg); break; + case 'a': + server->url_arg = true; + break; case 'R': server->readonly = true; break; @@ -436,6 +442,8 @@ main(int argc, char **argv) { lwsl_notice(" reconnect timeout: %ds\n", server->reconnect); if (server->check_origin) lwsl_notice(" check origin: true\n"); + if (server->url_arg) + lwsl_notice(" allow url arg: true\n"); if (server->readonly) lwsl_notice(" readonly: true\n"); if (server->max_clients > 0) diff --git a/src/server.h b/src/server.h index 3d262c4..b605875 100644 --- a/src/server.h +++ b/src/server.h @@ -33,6 +33,8 @@ struct tty_client { bool authenticated; char hostname[100]; char address[50]; + char **args; + int argc; struct lws *wsi; struct winsize size; @@ -67,8 +69,10 @@ struct tty_server { char *index; // custom index.html char *command; // full command line char **argv; // command with arguments + int argc; // command + arguments count int sig_code; // close signal char sig_name[20]; // human readable signal string + bool url_arg; // allow client to send cli arguments in URL bool readonly; // whether not allow clients to write to the TTY bool check_origin; // whether allow websocket connection from different origin int max_clients; // maximum clients to support