]> prime8.dev >> repos - ttyd.git/commitdiff
protocol: split forkpty to separate file
authorShuanglei Tao <tsl0922@gmail.com>
Tue, 3 Dec 2019 16:12:38 +0000 (00:12 +0800)
committerShuanglei Tao <tsl0922@gmail.com>
Thu, 5 Dec 2019 14:28:58 +0000 (22:28 +0800)
CMakeLists.txt
src/protocol.c
src/server.h
src/terminal.c [new file with mode: 0644]
src/terminal.h [new file with mode: 0644]

index e2c91e6d9aec12c53f840a64332a04a417f5eab2..522f9f4364e468f601e529c46ae41f74d3d86612 100644 (file)
@@ -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)
index 8f019a37277c563ca16f2d4cb3323a7eabdd4224..692a638df73811bf27b88d0a97800a08bd1da2d5 100644 (file)
@@ -1,24 +1,15 @@
 #include <stdbool.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <signal.h>
-#include <unistd.h>
-#include <fcntl.h>
 #include <errno.h>
-#include <sys/ioctl.h>
-
-#if defined(__OpenBSD__) || defined(__APPLE__)
-#include <util.h>
-#elif defined(__FreeBSD__)
-#include <libutil.h>
-#else
-#include <pty.h>
-#endif
 
 #include <libwebsockets.h>
 #include <json.h>
 
 #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;
index d3a60e5472c3c14691064bcda7269d73d56c04d8..42e9a2987c01279f667763df6a2d9315f84636da 100644 (file)
@@ -1,5 +1,4 @@
 #include <stdbool.h>
-#include <sys/ioctl.h>
 #include <uv.h>
 
 // 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 (file)
index 0000000..b0e53c2
--- /dev/null
@@ -0,0 +1,51 @@
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+
+#if defined(__OpenBSD__) || defined(__APPLE__)
+#include <util.h>
+#elif defined(__FreeBSD__)
+#include <libutil.h>
+#else
+#include <pty.h>
+#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 (file)
index 0000000..2dc9c02
--- /dev/null
@@ -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