From: Shuanglei Tao Date: Tue, 3 Dec 2019 16:12:38 +0000 (+0800) Subject: protocol: split forkpty to separate file X-Git-Url: http://git.prime8.dev/?a=commitdiff_plain;h=ca91f400484657606d0cdb257231aa54e7a09f1d;p=ttyd.git protocol: split forkpty to separate file --- diff --git a/CMakeLists.txt b/CMakeLists.txt index e2c91e6..522f9f4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,7 +30,7 @@ else() endif() set(LIBWEBSOCKETS_MIN_VERSION 1.7.0) -set(SOURCE_FILES src/server.c src/http.c src/protocol.c src/utils.c) +set(SOURCE_FILES src/server.c src/http.c src/protocol.c src/terminal.c src/utils.c) find_package(OpenSSL REQUIRED) find_package(Libwebsockets ${LIBWEBSOCKETS_MIN_VERSION} QUIET) diff --git a/src/protocol.c b/src/protocol.c index 8f019a3..692a638 100644 --- a/src/protocol.c +++ b/src/protocol.c @@ -1,24 +1,15 @@ #include +#include #include #include #include -#include -#include #include -#include - -#if defined(__OpenBSD__) || defined(__APPLE__) -#include -#elif defined(__FreeBSD__) -#include -#else -#include -#endif #include #include #include "server.h" +#include "terminal.h" #include "utils.h" // initial message list @@ -51,8 +42,7 @@ send_initial_message(struct lws *wsi, int index) { } bool -parse_window_size(const char *json, struct winsize *size) { - int columns, rows; +parse_window_size(const char *json, int *cols, int *rows) { json_object *obj = json_tokener_parse(json); struct json_object *o = NULL; @@ -60,18 +50,14 @@ parse_window_size(const char *json, struct winsize *size) { lwsl_err("columns field not exists, json: %s\n", json); return false; } - columns = json_object_get_int(o); + *cols = json_object_get_int(o); if (!json_object_object_get_ex(obj, "rows", &o)) { lwsl_err("rows field not exists, json: %s\n", json); return false; } - rows = json_object_get_int(o); + *rows = json_object_get_int(o); json_object_put(obj); - memset(size, 0, sizeof(struct winsize)); - size->ws_col = (unsigned short) columns; - size->ws_row = (unsigned short) rows; - return true; } @@ -189,37 +175,16 @@ spawn_process(struct pss_tty *pss) { uv_signal_start(&pss->watcher, child_cb, SIGCHLD); - int pty; - pid_t pid = forkpty(&pty, NULL, NULL, NULL); - if (pid < 0) { /* error */ - lwsl_err("forkpty failed: %d (%s)\n", errno, strerror(errno)); + pss->pid = pty_fork(&pss->pty, argv[0], argv, server->terminal_type); + if (pss->pid < 0) { + lwsl_err("pty_fork: %d (%s)\n", errno, strerror(errno)); return 1; - } else if (pid == 0) { /* child */ - setenv("TERM", server->terminal_type, true); -#if LWS_LIBRARY_VERSION_NUMBER < 3001000 - // libwebsockets set FD_CLOEXEC since v3.1.0 - close(lws_get_socket_fd(pss->wsi)); -#endif - if (execvp(argv[0], argv) < 0) { - perror("execvp failed\n"); - _exit(-errno); - } - } - - // set the file descriptor close-on-exec - int status_flags = fcntl(pty, F_GETFL); - if (status_flags != -1) { - fcntl(pty, F_SETFD, status_flags | FD_CLOEXEC); } - lwsl_notice("started process, pid: %d\n", pid); - pss->pid = pid; - pss->pty = pty; - if (pss->size.ws_row > 0 && pss->size.ws_col > 0) - ioctl(pss->pty, TIOCSWINSZ, &pss->size); + lwsl_notice("started process, pid: %d\n", pss->pid); pss->pipe.data = pss; - uv_pipe_open(&pss->pipe, pty); + uv_pipe_open(&pss->pipe, pss->pty); lws_callback_on_writable(pss->wsi); @@ -380,9 +345,12 @@ callback_tty(struct lws *wsi, enum lws_callback_reasons reason, } break; case RESIZE_TERMINAL: - if (parse_window_size(pss->buffer + 1, &pss->size) && pss->pty > 0) { - if (ioctl(pss->pty, TIOCSWINSZ, &pss->size) == -1) { - lwsl_err("ioctl TIOCSWINSZ: %d (%s)\n", errno, strerror(errno)); + { + int cols, rows; + if (parse_window_size(pss->buffer + 1, &cols, &rows)) { + if (pty_resize(pss->pty, cols, rows) < 0) { + lwsl_err("pty_resize: %d (%s)\n", errno, strerror(errno)); + } } } break; diff --git a/src/server.h b/src/server.h index d3a60e5..42e9a29 100644 --- a/src/server.h +++ b/src/server.h @@ -1,5 +1,4 @@ #include -#include #include // client message @@ -35,11 +34,10 @@ struct pss_tty { int argc; struct lws *wsi; - struct winsize size; char *buffer; size_t len; - int pid; + pid_t pid; int pty; char *pty_buffer; ssize_t pty_len; diff --git a/src/terminal.c b/src/terminal.c new file mode 100644 index 0000000..b0e53c2 --- /dev/null +++ b/src/terminal.c @@ -0,0 +1,51 @@ +#include +#include +#include +#include +#include +#include +#include + +#if defined(__OpenBSD__) || defined(__APPLE__) +#include +#elif defined(__FreeBSD__) +#include +#else +#include +#endif + +pid_t +pty_fork(int *pty, const char *file, char *const argv[], const char *term) { + pid_t pid = forkpty(pty, NULL, NULL, NULL); + + if (pid < 0) { + return pid; + } else if (pid == 0) { + setenv("TERM", term, true); + int ret = execvp(file, argv); + if (ret < 0) { + perror("execvp failed\n"); + _exit(-errno); + } + } + + // set the file descriptor close-on-exec + int status_flags = fcntl(*pty, F_GETFL); + if (status_flags != -1) { + fcntl(*pty, F_SETFD, status_flags | FD_CLOEXEC); + } + + return pid; +} + +int +pty_resize(pid_t pty, int cols, int rows) { + struct winsize size; + + size.ws_col = (unsigned short) cols; + size.ws_row = (unsigned short) rows; + size.ws_xpixel = 0; + size.ws_ypixel = 0; + + return ioctl(pty, TIOCSWINSZ, &size); +} diff --git a/src/terminal.h b/src/terminal.h new file mode 100644 index 0000000..2dc9c02 --- /dev/null +++ b/src/terminal.h @@ -0,0 +1,10 @@ +#ifndef TTYD_TERMINAL_H +#define TTYD_TERMINAL_H + +int +pty_fork(int *pty, const char *file, char *const argv[], const char *term); + +int +pty_resize(int pty, int cols, int rows); + +#endif //TTYD_TERMINAL_H