]> prime8.dev >> repos - ttyd.git/commitdiff
src: reformat with clang-format
authorShuanglei Tao <tsl0922@gmail.com>
Sat, 14 Mar 2020 09:41:06 +0000 (17:41 +0800)
committerShuanglei Tao <tsl0922@gmail.com>
Sat, 14 Mar 2020 09:46:26 +0000 (17:46 +0800)
.clang-format [new file with mode: 0644]
src/http.c
src/protocol.c
src/server.c
src/server.h
src/terminal.c
src/terminal.h
src/utils.c
src/utils.h

diff --git a/.clang-format b/.clang-format
new file mode 100644 (file)
index 0000000..a327123
--- /dev/null
@@ -0,0 +1,2 @@
+BasedOnStyle:  Google
+Language: Cpp
index deefe92d44c45c1d10e4fca79e0e2b09655d900d..70b7368add39d68326d27a31324edab1d518a556 100644 (file)
-#include <string.h>
 #include <libwebsockets.h>
 #include <openssl/ssl.h>
+#include <string.h>
 #include <zlib.h>
 
-#include "server.h"
 #include "html.h"
+#include "server.h"
 #include "utils.h"
 
-enum {
-    AUTH_OK, AUTH_FAIL, AUTH_ERROR
-};
+enum { AUTH_OK, AUTH_FAIL, AUTH_ERROR };
 
-static char * html_cache = NULL;
+static char *html_cache = NULL;
 static size_t html_cache_len = 0;
 
-static int
-check_auth(struct lws *wsi, struct pss_http *pss) {
-    if (server->credential == NULL)
-        return AUTH_OK;
-
-    int hdr_length = lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_AUTHORIZATION);
-    char buf[hdr_length + 1];
-    int len = lws_hdr_copy(wsi, buf, sizeof(buf), WSI_TOKEN_HTTP_AUTHORIZATION);
-    if (len > 0) {
-        // extract base64 text from authorization header
-        char *ptr = &buf[0];
-        char *token, *b64_text = NULL;
-        int i = 1;
-        while ((token = strsep(&ptr, " ")) != NULL) {
-            if (strlen(token) == 0)
-                continue;
-            if (i++ == 2) {
-                b64_text = token;
-                break;
-            }
-        }
-        if (b64_text != NULL && !strcmp(b64_text, server->credential))
-            return AUTH_OK;
+static int check_auth(struct lws *wsi, struct pss_http *pss) {
+  if (server->credential == NULL) return AUTH_OK;
+
+  int hdr_length = lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_AUTHORIZATION);
+  char buf[hdr_length + 1];
+  int len = lws_hdr_copy(wsi, buf, sizeof(buf), WSI_TOKEN_HTTP_AUTHORIZATION);
+  if (len > 0) {
+    // extract base64 text from authorization header
+    char *ptr = &buf[0];
+    char *token, *b64_text = NULL;
+    int i = 1;
+    while ((token = strsep(&ptr, " ")) != NULL) {
+      if (strlen(token) == 0) continue;
+      if (i++ == 2) {
+        b64_text = token;
+        break;
+      }
     }
-
-    unsigned char buffer[1024 + LWS_PRE], *p, *end;
-    p = buffer + LWS_PRE;
-    end = p + sizeof(buffer) - LWS_PRE;
-
-    char *body = strdup("401 Unauthorized\n");
-    size_t n = strlen(body);
-
-    if (lws_add_http_header_status(wsi, HTTP_STATUS_UNAUTHORIZED, &p, end))
-        return AUTH_ERROR;
-    if (lws_add_http_header_by_token(wsi,
-                                     WSI_TOKEN_HTTP_WWW_AUTHENTICATE,
-                                     (unsigned char *) "Basic realm=\"ttyd\"",
-                                     18, &p, end))
-        return AUTH_ERROR;
-    if (lws_add_http_header_content_length(wsi, n, &p, end))
-        return AUTH_ERROR;
-    if (lws_finalize_http_header(wsi, &p, end))
-        return AUTH_ERROR;
-    if (lws_write(wsi, buffer + LWS_PRE, p - (buffer + LWS_PRE), LWS_WRITE_HTTP_HEADERS) < 0)
-        return AUTH_ERROR;
-
-    pss->buffer = pss->ptr = body;
-    pss->len = n;
-    lws_callback_on_writable(wsi);
-
-    return AUTH_FAIL;
+    if (b64_text != NULL && !strcmp(b64_text, server->credential))
+      return AUTH_OK;
+  }
+
+  unsigned char buffer[1024 + LWS_PRE], *p, *end;
+  p = buffer + LWS_PRE;
+  end = p + sizeof(buffer) - LWS_PRE;
+
+  char *body = strdup("401 Unauthorized\n");
+  size_t n = strlen(body);
+
+  if (lws_add_http_header_status(wsi, HTTP_STATUS_UNAUTHORIZED, &p, end))
+    return AUTH_ERROR;
+  if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_WWW_AUTHENTICATE,
+                                   (unsigned char *)"Basic realm=\"ttyd\"", 18,
+                                   &p, end))
+    return AUTH_ERROR;
+  if (lws_add_http_header_content_length(wsi, n, &p, end)) return AUTH_ERROR;
+  if (lws_finalize_http_header(wsi, &p, end)) return AUTH_ERROR;
+  if (lws_write(wsi, buffer + LWS_PRE, p - (buffer + LWS_PRE),
+                LWS_WRITE_HTTP_HEADERS) < 0)
+    return AUTH_ERROR;
+
+  pss->buffer = pss->ptr = body;
+  pss->len = n;
+  lws_callback_on_writable(wsi);
+
+  return AUTH_FAIL;
 }
 
-static bool
-accept_gzip(struct lws *wsi) {
-    int hdr_length = lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_ACCEPT_ENCODING);
-    char buf[hdr_length + 1];
-    int len = lws_hdr_copy(wsi, buf, sizeof(buf), WSI_TOKEN_HTTP_ACCEPT_ENCODING);
-    return len > 0 && strstr(buf, "gzip") != NULL;
+static bool accept_gzip(struct lws *wsi) {
+  int hdr_length = lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_ACCEPT_ENCODING);
+  char buf[hdr_length + 1];
+  int len = lws_hdr_copy(wsi, buf, sizeof(buf), WSI_TOKEN_HTTP_ACCEPT_ENCODING);
+  return len > 0 && strstr(buf, "gzip") != NULL;
 }
 
-static bool
-uncompress_html(char **output, size_t *output_len) {
-    if (html_cache == NULL || html_cache_len == 0) {
-        z_stream stream;
-        memset(&stream, 0, sizeof(stream));
-        if (inflateInit2(&stream, 16 + 15) != Z_OK)
-            return false;
-
-        html_cache_len = index_html_size;
-        html_cache = xmalloc(html_cache_len);
-
-        stream.avail_in = index_html_len;
-        stream.avail_out = html_cache_len;
-        stream.next_in = (void *) index_html;
-        stream.next_out = (void *) html_cache;
-
-        int ret = inflate(&stream, Z_SYNC_FLUSH);
-        inflateEnd(&stream);
-        if (ret != Z_STREAM_END) {
-            free(html_cache);
-            html_cache = NULL;
-            html_cache_len = 0;
-            return false;
-        }
+static bool uncompress_html(char **output, size_t *output_len) {
+  if (html_cache == NULL || html_cache_len == 0) {
+    z_stream stream;
+    memset(&stream, 0, sizeof(stream));
+    if (inflateInit2(&stream, 16 + 15) != Z_OK) return false;
+
+    html_cache_len = index_html_size;
+    html_cache = xmalloc(html_cache_len);
+
+    stream.avail_in = index_html_len;
+    stream.avail_out = html_cache_len;
+    stream.next_in = (void *)index_html;
+    stream.next_out = (void *)html_cache;
+
+    int ret = inflate(&stream, Z_SYNC_FLUSH);
+    inflateEnd(&stream);
+    if (ret != Z_STREAM_END) {
+      free(html_cache);
+      html_cache = NULL;
+      html_cache_len = 0;
+      return false;
     }
+  }
 
-    *output = html_cache;
-    *output_len = html_cache_len;
+  *output = html_cache;
+  *output_len = html_cache_len;
 
-    return true;
+  return true;
 }
 
-static void
-pss_buffer_free(struct pss_http *pss) {
-    if (pss->buffer != (char *) index_html && pss->buffer != html_cache)
-        free(pss->buffer);
+static void pss_buffer_free(struct pss_http *pss) {
+  if (pss->buffer != (char *)index_html && pss->buffer != html_cache)
+    free(pss->buffer);
 }
 
-static void
-access_log(struct lws *wsi, const char *path) {
-    char rip[50];
+static void access_log(struct lws *wsi, const char *path) {
+  char rip[50];
 
 #if LWS_LIBRARY_VERSION_NUMBER >= 2004000
-    lws_get_peer_simple(lws_get_network_wsi(wsi), rip, sizeof(rip));
+  lws_get_peer_simple(lws_get_network_wsi(wsi), rip, sizeof(rip));
 #else
-    char name[100];
-    lws_get_peer_addresses(wsi, lws_get_socket_fd(wsi), name, sizeof(name), rip, sizeof(rip));
+  char name[100];
+  lws_get_peer_addresses(wsi, lws_get_socket_fd(wsi), name, sizeof(name), rip,
+                         sizeof(rip));
 #endif
-    lwsl_notice("HTTP %s - %s\n", path, rip);
+  lwsl_notice("HTTP %s - %s\n", path, rip);
 }
 
-int
-callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) {
-    struct pss_http *pss = (struct pss_http *) user;
-    unsigned char buffer[4096 + LWS_PRE], *p, *end;
-    char buf[256];
-    bool done = false;
-
-    switch (reason) {
-        case LWS_CALLBACK_HTTP:
-            access_log(wsi, (const char *) in);
-            snprintf(pss->path, sizeof(pss->path), "%s", (const char *) in);
-            switch (check_auth(wsi, pss)) {
-                case AUTH_OK:
-                    break;
-                case AUTH_FAIL:
-                    return 0;
-                case AUTH_ERROR:
-                default:
-                    return 1;
-            }
-
-            p = buffer + LWS_PRE;
-            end = p + sizeof(buffer) - LWS_PRE;
-
-            if (strcmp(pss->path, endpoints.token) == 0) {
-                const char *credential = server->credential != NULL ? server->credential : "";
-                size_t n = sprintf(buf, "{\"token\": \"%s\"}", credential);
-                if (lws_add_http_header_status(wsi, HTTP_STATUS_OK, &p, end))
-                    return 1;
-                if (lws_add_http_header_by_token(wsi,
-                                                 WSI_TOKEN_HTTP_CONTENT_TYPE,
-                                                 (unsigned char *) "application/json;charset=utf-8",
-                                                 30, &p, end))
-                    return 1;
-                if (lws_add_http_header_content_length(wsi, (unsigned long) n, &p, end))
-                    return 1;
-                if (lws_finalize_http_header(wsi, &p, end))
-                    return 1;
-                if (lws_write(wsi, buffer + LWS_PRE, p - (buffer + LWS_PRE), LWS_WRITE_HTTP_HEADERS) < 0)
-                    return 1;
-                pss->buffer = pss->ptr = strdup(buf);
-                pss->len = n;
-                lws_callback_on_writable(wsi);
-                break;
-            }
-
-            if (strcmp(pss->path, endpoints.index) != 0) {
-                lws_return_http_status(wsi, HTTP_STATUS_NOT_FOUND, NULL);
-                goto try_to_reuse;
-            }
-
-            const char* content_type = "text/html";
-            if (server->index != NULL) {
-                int n = lws_serve_http_file(wsi, server->index, content_type, NULL, 0);
-                if (n < 0 || (n > 0 && lws_http_transaction_completed(wsi)))
-                    return 1;
-            } else {
-                char *output = (char *) index_html;
-                size_t output_len = index_html_len;
-                if (lws_add_http_header_status(wsi, HTTP_STATUS_OK, &p, end))
-                    return 1;
-                if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE, (const unsigned char *) content_type, 9, &p, end))
-                    return 1;
+int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user,
+                  void *in, size_t len) {
+  struct pss_http *pss = (struct pss_http *)user;
+  unsigned char buffer[4096 + LWS_PRE], *p, *end;
+  char buf[256];
+  bool done = false;
+
+  switch (reason) {
+    case LWS_CALLBACK_HTTP:
+      access_log(wsi, (const char *)in);
+      snprintf(pss->path, sizeof(pss->path), "%s", (const char *)in);
+      switch (check_auth(wsi, pss)) {
+        case AUTH_OK:
+          break;
+        case AUTH_FAIL:
+          return 0;
+        case AUTH_ERROR:
+        default:
+          return 1;
+      }
+
+      p = buffer + LWS_PRE;
+      end = p + sizeof(buffer) - LWS_PRE;
+
+      if (strcmp(pss->path, endpoints.token) == 0) {
+        const char *credential =
+            server->credential != NULL ? server->credential : "";
+        size_t n = sprintf(buf, "{\"token\": \"%s\"}", credential);
+        if (lws_add_http_header_status(wsi, HTTP_STATUS_OK, &p, end)) return 1;
+        if (lws_add_http_header_by_token(
+                wsi, WSI_TOKEN_HTTP_CONTENT_TYPE,
+                (unsigned char *)"application/json;charset=utf-8", 30, &p, end))
+          return 1;
+        if (lws_add_http_header_content_length(wsi, (unsigned long)n, &p, end))
+          return 1;
+        if (lws_finalize_http_header(wsi, &p, end)) return 1;
+        if (lws_write(wsi, buffer + LWS_PRE, p - (buffer + LWS_PRE),
+                      LWS_WRITE_HTTP_HEADERS) < 0)
+          return 1;
+        pss->buffer = pss->ptr = strdup(buf);
+        pss->len = n;
+        lws_callback_on_writable(wsi);
+        break;
+      }
+
+      if (strcmp(pss->path, endpoints.index) != 0) {
+        lws_return_http_status(wsi, HTTP_STATUS_NOT_FOUND, NULL);
+        goto try_to_reuse;
+      }
+
+      const char *content_type = "text/html";
+      if (server->index != NULL) {
+        int n = lws_serve_http_file(wsi, server->index, content_type, NULL, 0);
+        if (n < 0 || (n > 0 && lws_http_transaction_completed(wsi))) return 1;
+      } else {
+        char *output = (char *)index_html;
+        size_t output_len = index_html_len;
+        if (lws_add_http_header_status(wsi, HTTP_STATUS_OK, &p, end)) return 1;
+        if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE,
+                                         (const unsigned char *)content_type, 9,
+                                         &p, end))
+          return 1;
 #ifdef LWS_WITH_HTTP_STREAM_COMPRESSION
-                if (!uncompress_html(&output, &output_len))
-                    return 1;
+        if (!uncompress_html(&output, &output_len)) return 1;
 #else
-                if (accept_gzip(wsi)) {
-                    if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_ENCODING, (unsigned char *) "gzip", 4, &p, end))
-                        return 1;
-                } else {
-                    if (!uncompress_html(&output, &output_len))
-                        return 1;
-                }
+        if (accept_gzip(wsi)) {
+          if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_ENCODING,
+                                           (unsigned char *)"gzip", 4, &p, end))
+            return 1;
+        } else {
+          if (!uncompress_html(&output, &output_len)) return 1;
+        }
 #endif
 
-                if (lws_add_http_header_content_length(wsi, (unsigned long) output_len, &p, end))
-                    return 1;
+        if (lws_add_http_header_content_length(wsi, (unsigned long)output_len,
+                                               &p, end))
+          return 1;
 
-                if (lws_finalize_http_header(wsi, &p, end))
-                    return 1;
-                if (lws_write(wsi, buffer + LWS_PRE, p - (buffer + LWS_PRE), LWS_WRITE_HTTP_HEADERS) < 0)
-                    return 1;
+        if (lws_finalize_http_header(wsi, &p, end)) return 1;
+        if (lws_write(wsi, buffer + LWS_PRE, p - (buffer + LWS_PRE),
+                      LWS_WRITE_HTTP_HEADERS) < 0)
+          return 1;
 #if LWS_LIBRARY_VERSION_MAJOR < 2
-                if (lws_write_http(wsi, output, output_len) < 0)
-                    return 1;
-                goto try_to_reuse;
+        if (lws_write_http(wsi, output, output_len) < 0) return 1;
+        goto try_to_reuse;
 #else
-                pss->buffer = pss->ptr = output;
-                pss->len = output_len;
-                lws_callback_on_writable(wsi);
+        pss->buffer = pss->ptr = output;
+        pss->len = output_len;
+        lws_callback_on_writable(wsi);
 #endif
-            }
-            break;
-
-        case LWS_CALLBACK_HTTP_WRITEABLE:
-            if (!pss->buffer || pss->len <= 0) {
-                goto try_to_reuse;
-            }
-
-            do {
-                int n = sizeof(buffer) - LWS_PRE;
-                int m = lws_get_peer_write_allowance(wsi);
-                if (m == 0) {
-                    lws_callback_on_writable(wsi);
-                    return 0;
-                } else if (m != -1 && m < n) {
-                    n = m;
-                }
-                if (pss->ptr + n > pss->buffer + pss->len) {
-                    n = (int) (pss->len - (pss->ptr - pss->buffer));
-                    done = true;
-                }
-                memcpy(buffer + LWS_PRE, pss->ptr, n);
-                pss->ptr += n;
-                if (lws_write_http(wsi, buffer + LWS_PRE, (size_t) n) < n) {
-                    pss_buffer_free(pss);
-                    return -1;
-                }
-            } while (!lws_send_pipe_choked(wsi) && !done);
-
-            if (!done && pss->ptr < pss->buffer + pss->len) {
-                lws_callback_on_writable(wsi);
-                break;
-            }
-
-            pss_buffer_free(pss);
-            goto try_to_reuse;
-
-        case LWS_CALLBACK_HTTP_FILE_COMPLETION:
-            goto try_to_reuse;
-
-        case LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION:
-            if (!len || (SSL_get_verify_result((SSL *) in) != X509_V_OK)) {
-                int err = X509_STORE_CTX_get_error((X509_STORE_CTX *) user);
-                int depth = X509_STORE_CTX_get_error_depth((X509_STORE_CTX *) user);
-                const char *msg = X509_verify_cert_error_string(err);
-                lwsl_err("client certificate verification error: %s (%d), depth: %d\n", msg, err, depth);
-                return 1;
-            }
-            break;
-        default:
-            break;
-    }
-
-    return 0;
-
-    /* if we're on HTTP1.1 or 2.0, will keep the idle connection alive */
+      }
+      break;
+
+    case LWS_CALLBACK_HTTP_WRITEABLE:
+      if (!pss->buffer || pss->len <= 0) {
+        goto try_to_reuse;
+      }
+
+      do {
+        int n = sizeof(buffer) - LWS_PRE;
+        int m = lws_get_peer_write_allowance(wsi);
+        if (m == 0) {
+          lws_callback_on_writable(wsi);
+          return 0;
+        } else if (m != -1 && m < n) {
+          n = m;
+        }
+        if (pss->ptr + n > pss->buffer + pss->len) {
+          n = (int)(pss->len - (pss->ptr - pss->buffer));
+          done = true;
+        }
+        memcpy(buffer + LWS_PRE, pss->ptr, n);
+        pss->ptr += n;
+        if (lws_write_http(wsi, buffer + LWS_PRE, (size_t)n) < n) {
+          pss_buffer_free(pss);
+          return -1;
+        }
+      } while (!lws_send_pipe_choked(wsi) && !done);
+
+      if (!done && pss->ptr < pss->buffer + pss->len) {
+        lws_callback_on_writable(wsi);
+        break;
+      }
+
+      pss_buffer_free(pss);
+      goto try_to_reuse;
+
+    case LWS_CALLBACK_HTTP_FILE_COMPLETION:
+      goto try_to_reuse;
+
+    case LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION:
+      if (!len || (SSL_get_verify_result((SSL *)in) != X509_V_OK)) {
+        int err = X509_STORE_CTX_get_error((X509_STORE_CTX *)user);
+        int depth = X509_STORE_CTX_get_error_depth((X509_STORE_CTX *)user);
+        const char *msg = X509_verify_cert_error_string(err);
+        lwsl_err("client certificate verification error: %s (%d), depth: %d\n",
+                 msg, err, depth);
+        return 1;
+      }
+      break;
+    default:
+      break;
+  }
+
+  return 0;
+
+  /* if we're on HTTP1.1 or 2.0, will keep the idle connection alive */
 try_to_reuse:
-    if (lws_http_transaction_completed(wsi))
-        return -1;
+  if (lws_http_transaction_completed(wsi)) return -1;
 
-    return 0;
+  return 0;
 }
index 994975915af621563529bf310ea7d94fd86534de..4a1fc0dcbf2b59a4ac72162fdc923440c417d165 100644 (file)
+#include <errno.h>
+#include <json.h>
+#include <libwebsockets.h>
+#include <signal.h>
 #include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <signal.h>
-#include <errno.h>
 #include <sys/wait.h>
 
-#include <libwebsockets.h>
-#include <json.h>
-
 #include "server.h"
 #include "terminal.h"
 #include "utils.h"
 
 // initial message list
-static char initial_cmds[] = {
-        SET_WINDOW_TITLE,
-        SET_PREFERENCES
-};
-
-static int
-send_initial_message(struct lws *wsi, int index) {
-    unsigned char message[LWS_PRE + 1 + 4096];
-    unsigned char *p = &message[LWS_PRE];
-    char buffer[128];
-    int n = 0;
-
-    char cmd = initial_cmds[index];
-    switch(cmd) {
-        case SET_WINDOW_TITLE:
-            gethostname(buffer, sizeof(buffer) - 1);
-            n = sprintf((char *) p, "%c%s (%s)", cmd, server->command, buffer);
-            break;
-        case SET_PREFERENCES:
-            n = sprintf((char *) p, "%c%s", cmd, server->prefs_json);
-            break;
-        default:
-            break;
-    }
-
-    return lws_write(wsi, p, (size_t) n, LWS_WRITE_BINARY);
+static char initial_cmds[] = {SET_WINDOW_TITLE, SET_PREFERENCES};
+
+static int send_initial_message(struct lws *wsi, int index) {
+  unsigned char message[LWS_PRE + 1 + 4096];
+  unsigned char *p = &message[LWS_PRE];
+  char buffer[128];
+  int n = 0;
+
+  char cmd = initial_cmds[index];
+  switch (cmd) {
+    case SET_WINDOW_TITLE:
+      gethostname(buffer, sizeof(buffer) - 1);
+      n = sprintf((char *)p, "%c%s (%s)", cmd, server->command, buffer);
+      break;
+    case SET_PREFERENCES:
+      n = sprintf((char *)p, "%c%s", cmd, server->prefs_json);
+      break;
+    default:
+      break;
+  }
+
+  return lws_write(wsi, p, (size_t)n, LWS_WRITE_BINARY);
 }
 
-static bool
-parse_window_size(struct pss_tty *pss, int *cols, int *rows) {
-    char json[pss->len];
-    strncpy(json, pss->buffer + 1, pss->len - 1);
-    json[pss->len-1] = '\0';
-
-    json_object *obj = json_tokener_parse(json);
-    struct json_object *o = NULL;
-
-    if (!json_object_object_get_ex(obj, "columns", &o)) {
-        lwsl_err("columns field not exists, json: %s\n", json);
-        return false;
-    }
-    *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);
-    json_object_put(obj);
-
-    return true;
+static bool parse_window_size(struct pss_tty *pss, int *cols, int *rows) {
+  char json[pss->len];
+  strncpy(json, pss->buffer + 1, pss->len - 1);
+  json[pss->len - 1] = '\0';
+
+  json_object *obj = json_tokener_parse(json);
+  struct json_object *o = NULL;
+
+  if (!json_object_object_get_ex(obj, "columns", &o)) {
+    lwsl_err("columns field not exists, json: %s\n", json);
+    return false;
+  }
+  *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);
+  json_object_put(obj);
+
+  return true;
 }
 
-static bool
-check_host_origin(struct lws *wsi) {
-    int origin_length = lws_hdr_total_length(wsi, WSI_TOKEN_ORIGIN);
-    char buf[origin_length + 1];
-    memset(buf, 0, sizeof(buf));
-    int len = lws_hdr_copy(wsi, buf, sizeof(buf), WSI_TOKEN_ORIGIN);
-    if (len <= 0) {
-        return false;
-    }
-
-    const char *prot, *address, *path;
-    int port;
-    if (lws_parse_uri(buf, &prot, &address, &port, &path))
-        return false;
-    if (port == 80 || port == 443) {
-        sprintf(buf, "%s", address);
-    } else {
-        sprintf(buf, "%s:%d", address, port);
-    }
-
-    int host_length = lws_hdr_total_length(wsi, WSI_TOKEN_HOST);
-    if (host_length != strlen(buf))
-        return false;
-    char host_buf[host_length + 1];
-    memset(host_buf, 0, sizeof(host_buf));
-    len = lws_hdr_copy(wsi, host_buf, sizeof(host_buf), WSI_TOKEN_HOST);
-
-    return len > 0 && strcasecmp(buf, host_buf) == 0;
+static bool check_host_origin(struct lws *wsi) {
+  int origin_length = lws_hdr_total_length(wsi, WSI_TOKEN_ORIGIN);
+  char buf[origin_length + 1];
+  memset(buf, 0, sizeof(buf));
+  int len = lws_hdr_copy(wsi, buf, sizeof(buf), WSI_TOKEN_ORIGIN);
+  if (len <= 0) {
+    return false;
+  }
+
+  const char *prot, *address, *path;
+  int port;
+  if (lws_parse_uri(buf, &prot, &address, &port, &path)) return false;
+  if (port == 80 || port == 443) {
+    sprintf(buf, "%s", address);
+  } else {
+    sprintf(buf, "%s:%d", address, port);
+  }
+
+  int host_length = lws_hdr_total_length(wsi, WSI_TOKEN_HOST);
+  if (host_length != strlen(buf)) return false;
+  char host_buf[host_length + 1];
+  memset(host_buf, 0, sizeof(host_buf));
+  len = lws_hdr_copy(wsi, host_buf, sizeof(host_buf), WSI_TOKEN_HOST);
+
+  return len > 0 && strcasecmp(buf, host_buf) == 0;
 }
 
-static void
-pty_proc_free(struct pty_proc *proc) {
-    uv_read_stop((uv_stream_t *) &proc->pipe);
-    uv_close((uv_handle_t*) &proc->pipe, NULL);
+static void pty_proc_free(struct pty_proc *proc) {
+  uv_read_stop((uv_stream_t *)&proc->pipe);
+  uv_close((uv_handle_t *)&proc->pipe, NULL);
 
-    close(proc->pty);
+  close(proc->pty);
 
-    if (proc->pty_buffer != NULL) {
-        free(proc->pty_buffer);
-        proc->pty_buffer = NULL;
-    }
+  if (proc->pty_buffer != NULL) {
+    free(proc->pty_buffer);
+    proc->pty_buffer = NULL;
+  }
 
-    for (int i = 0; i < proc->argc; i++) {
-        free(proc->args[i]);
-    }
+  for (int i = 0; i < proc->argc; i++) {
+    free(proc->args[i]);
+  }
 
-    free(proc);
+  free(proc);
 }
 
-static void
-alloc_cb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) {
-    buf->base = xmalloc(suggested_size);
-    buf->len = suggested_size;
+static void alloc_cb(uv_handle_t *handle, size_t suggested_size,
+                     uv_buf_t *buf) {
+  buf->base = xmalloc(suggested_size);
+  buf->len = suggested_size;
 }
 
-static void
-read_cb(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) {
-    struct pss_tty *pss = (struct pss_tty *) stream->data;
-    struct pty_proc *proc = pss->proc;
-    proc->pty_len = nread;
-
-    uv_read_stop(stream);
-
-    if (nread <= 0) {
-        if (nread == UV_ENOBUFS || nread == 0)
-            return;
-        proc->pty_buffer = NULL;
-        if (nread == UV_EOF)
-            proc->pty_len = 0;
-        else
-            lwsl_err("read_cb: %s\n", uv_err_name(nread));
-    } else {
-        proc->pty_buffer = xmalloc(LWS_PRE + 1 + (size_t ) nread);
-        memcpy(proc->pty_buffer + LWS_PRE + 1, buf->base, (size_t ) nread);
-    }
-    free(buf->base);
-
-    lws_callback_on_writable(pss->wsi);
+static void read_cb(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) {
+  struct pss_tty *pss = (struct pss_tty *)stream->data;
+  struct pty_proc *proc = pss->proc;
+  proc->pty_len = nread;
+
+  uv_read_stop(stream);
+
+  if (nread <= 0) {
+    if (nread == UV_ENOBUFS || nread == 0) return;
+    proc->pty_buffer = NULL;
+    if (nread == UV_EOF)
+      proc->pty_len = 0;
+    else
+      lwsl_err("read_cb: %s\n", uv_err_name(nread));
+  } else {
+    proc->pty_buffer = xmalloc(LWS_PRE + 1 + (size_t)nread);
+    memcpy(proc->pty_buffer + LWS_PRE + 1, buf->base, (size_t)nread);
+  }
+  free(buf->base);
+
+  lws_callback_on_writable(pss->wsi);
 }
 
-static void
-child_cb(uv_signal_t *handle, int signum) {
-    pid_t pid;
-    int stat;
-
-    struct pty_proc *proc;
-    LIST_HEAD(proc, pty_proc) *procs = handle->data;
-    LIST_FOREACH(proc, procs, entry) {
-        do
-            pid = waitpid(proc->pid, &stat, WNOHANG);
-        while (pid == -1 && errno == EINTR);
-
-        if (pid <= 0)
-            continue;
-
-        if (WIFEXITED(stat)) {
-            proc->status = WEXITSTATUS(stat);
-            lwsl_notice("process exited with code %d, pid: %d\n", proc->status, proc->pid);
-        } else if (WIFSIGNALED(stat)) {
-            int sig = WTERMSIG(stat);
-            char sig_name[20];
-
-            proc->status = 128 + sig;
-            get_sig_name(sig, sig_name, sizeof(sig_name));
-            lwsl_notice("process killed with signal %d (%s), pid: %d\n", sig, sig_name, proc->pid);
-        }
+static void child_cb(uv_signal_t *handle, int signum) {
+  pid_t pid;
+  int stat;
+
+  struct pty_proc *proc;
+  LIST_HEAD(proc, pty_proc) *procs = handle->data;
+  LIST_FOREACH(proc, procs, entry) {
+    do
+      pid = waitpid(proc->pid, &stat, WNOHANG);
+    while (pid == -1 && errno == EINTR);
+
+    if (pid <= 0) continue;
+
+    if (WIFEXITED(stat)) {
+      proc->status = WEXITSTATUS(stat);
+      lwsl_notice("process exited with code %d, pid: %d\n", proc->status,
+                  proc->pid);
+    } else if (WIFSIGNALED(stat)) {
+      int sig = WTERMSIG(stat);
+      char sig_name[20];
+
+      proc->status = 128 + sig;
+      get_sig_name(sig, sig_name, sizeof(sig_name));
+      lwsl_notice("process killed with signal %d (%s), pid: %d\n", sig,
+                  sig_name, proc->pid);
+    }
 
-        LIST_REMOVE(proc, entry);
-        if (proc->state == STATE_KILL) {
-            pty_proc_free(proc);
-        } else {
-            proc->state = STATE_EXIT;
-        }
+    LIST_REMOVE(proc, entry);
+    if (proc->state == STATE_KILL) {
+      pty_proc_free(proc);
+    } else {
+      proc->state = STATE_EXIT;
     }
+  }
 }
 
-static int
-spawn_process(struct pss_tty *pss) {
-    struct pty_proc *proc = pss->proc;
-    // append url args to arguments
-    char *argv[server->argc + proc->argc + 1];
-    int i, n = 0;
-    for (i = 0; i < server->argc; i++) {
-        argv[n++] = server->argv[i];
-    }
-    for (i = 0; i < proc->argc; i++) {
-        argv[n++] = proc->args[i];
-    }
-    argv[n] = NULL;
+static int spawn_process(struct pss_tty *pss) {
+  struct pty_proc *proc = pss->proc;
+  // append url args to arguments
+  char *argv[server->argc + proc->argc + 1];
+  int i, n = 0;
+  for (i = 0; i < server->argc; i++) {
+    argv[n++] = server->argv[i];
+  }
+  for (i = 0; i < proc->argc; i++) {
+    argv[n++] = proc->args[i];
+  }
+  argv[n] = NULL;
 
-    uv_signal_start(&server->watcher, child_cb, SIGCHLD);
+  uv_signal_start(&server->watcher, child_cb, SIGCHLD);
 
-    // ensure the lws socket fd close-on-exec
-    fd_set_cloexec(lws_get_socket_fd(pss->wsi));
+  // ensure the lws socket fd close-on-exec
+  fd_set_cloexec(lws_get_socket_fd(pss->wsi));
 
-    // create process with pseudo-tty
-    proc->pid = pty_fork(&proc->pty, argv[0], argv, server->terminal_type);
-    if (proc->pid < 0) {
-        lwsl_err("pty_fork: %d (%s)\n", errno, strerror(errno));
-        return 1;
-    }
+  // create process with pseudo-tty
+  proc->pid = pty_fork(&proc->pty, argv[0], argv, server->terminal_type);
+  if (proc->pid < 0) {
+    lwsl_err("pty_fork: %d (%s)\n", errno, strerror(errno));
+    return 1;
+  }
 
-    lwsl_notice("started process, pid: %d\n", proc->pid);
+  lwsl_notice("started process, pid: %d\n", proc->pid);
 
-    proc->pipe.data = pss;
-    uv_pipe_open(&proc->pipe, proc->pty);
+  proc->pipe.data = pss;
+  uv_pipe_open(&proc->pipe, proc->pty);
 
-    lws_callback_on_writable(pss->wsi);
+  lws_callback_on_writable(pss->wsi);
 
-    return 0;
+  return 0;
 }
 
-static void
-kill_process(struct pty_proc *proc) {
-    if (proc->pid <= 0) return;
+static void kill_process(struct pty_proc *proc) {
+  if (proc->pid <= 0) return;
 
-    pid_t pid = proc->pid;
-    int sig = server->sig_code;
-    char *sig_name = server->sig_name;
+  pid_t pid = proc->pid;
+  int sig = server->sig_code;
+  char *sig_name = server->sig_name;
 
-    lwsl_notice("killing process %d with signal: %d (%s)\n", pid, sig, sig_name);
-    int pgid = getpgid(pid);
-    if (uv_kill(pgid > 0 ? -pgid : pid, sig) != 0) {
-        lwsl_err("kill: %d, errno: %d (%s)\n", pid, errno, strerror(errno));
-    }
+  lwsl_notice("killing process %d with signal: %d (%s)\n", pid, sig, sig_name);
+  int pgid = getpgid(pid);
+  if (uv_kill(pgid > 0 ? -pgid : pid, sig) != 0) {
+    lwsl_err("kill: %d, errno: %d (%s)\n", pid, errno, strerror(errno));
+  }
 }
 
-static void
-write_cb(uv_write_t* req, int status) {
-    if (status != 0)
-        lwsl_warn("uv_write callback returned status: %d\n", status);
-    free(req->data);
-    free(req);
+static void write_cb(uv_write_t *req, int status) {
+  if (status != 0) lwsl_warn("uv_write callback returned status: %d\n", status);
+  free(req->data);
+  free(req);
 }
 
-int
-callback_tty(struct lws *wsi, enum lws_callback_reasons reason,
-             void *user, void *in, size_t len) {
-    struct pss_tty *pss = (struct pss_tty *) user;
-    struct pty_proc *proc;
-    char buf[256];
-    size_t n = 0;
-
-    switch (reason) {
-        case LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION:
-            if (server->once && server->client_count > 0) {
-                lwsl_warn("refuse to serve WS client due to the --once option.\n");
-                return 1;
-            }
-            if (server->max_clients > 0 && server->client_count == server->max_clients) {
-                lwsl_warn("refuse to serve WS client due to the --max-clients option.\n");
-                return 1;
-            }
-            if (lws_hdr_copy(wsi, buf, sizeof(buf), WSI_TOKEN_GET_URI) <= 0 || strcmp(buf, endpoints.ws) != 0) {
-                lwsl_warn("refuse to serve WS client for illegal ws path: %s\n", buf);
-                return 1;
-            }
+int callback_tty(struct lws *wsi, enum lws_callback_reasons reason, void *user,
+                 void *in, size_t len) {
+  struct pss_tty *pss = (struct pss_tty *)user;
+  struct pty_proc *proc;
+  char buf[256];
+  size_t n = 0;
+
+  switch (reason) {
+    case LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION:
+      if (server->once && server->client_count > 0) {
+        lwsl_warn("refuse to serve WS client due to the --once option.\n");
+        return 1;
+      }
+      if (server->max_clients > 0 &&
+          server->client_count == server->max_clients) {
+        lwsl_warn(
+            "refuse to serve WS client due to the --max-clients option.\n");
+        return 1;
+      }
+      if (lws_hdr_copy(wsi, buf, sizeof(buf), WSI_TOKEN_GET_URI) <= 0 ||
+          strcmp(buf, endpoints.ws) != 0) {
+        lwsl_warn("refuse to serve WS client for illegal ws path: %s\n", buf);
+        return 1;
+      }
 
-            if (server->check_origin && !check_host_origin(wsi)) {
-                lwsl_warn("refuse to serve WS client from different origin due to the --check-origin option.\n");
-                return 1;
-            }
-            break;
-
-        case LWS_CALLBACK_ESTABLISHED:
-            pss->initialized = false;
-            pss->initial_cmd_index = 0;
-            pss->authenticated = false;
-            pss->wsi = wsi;
-            pss->buffer = NULL;
-
-            pss->proc = proc = xmalloc(sizeof(struct pty_proc));
-            memset(proc, 0, sizeof(struct pty_proc));
-            proc->status = -1;
-            proc->state = STATE_INIT;
-            uv_pipe_init(server->loop, &proc->pipe, 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) {
-                        proc->args = xrealloc(proc->args, (proc->argc + 1) * sizeof(char *));
-                        proc->args[proc->argc] = strdup(&buf[4]);
-                        proc->argc++;
-                    }
-                }
-            }
+      if (server->check_origin && !check_host_origin(wsi)) {
+        lwsl_warn(
+            "refuse to serve WS client from different origin due to the "
+            "--check-origin option.\n");
+        return 1;
+      }
+      break;
+
+    case LWS_CALLBACK_ESTABLISHED:
+      pss->initialized = false;
+      pss->initial_cmd_index = 0;
+      pss->authenticated = false;
+      pss->wsi = wsi;
+      pss->buffer = NULL;
+
+      pss->proc = proc = xmalloc(sizeof(struct pty_proc));
+      memset(proc, 0, sizeof(struct pty_proc));
+      proc->status = -1;
+      proc->state = STATE_INIT;
+      uv_pipe_init(server->loop, &proc->pipe, 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) {
+            proc->args =
+                xrealloc(proc->args, (proc->argc + 1) * sizeof(char *));
+            proc->args[proc->argc] = strdup(&buf[4]);
+            proc->argc++;
+          }
+        }
+      }
 
-            LIST_INSERT_HEAD(&server->procs, proc, entry);
-            server->client_count++;
+      LIST_INSERT_HEAD(&server->procs, proc, entry);
+      server->client_count++;
 
-            lws_hdr_copy(wsi, buf, sizeof(buf), WSI_TOKEN_GET_URI);
+      lws_hdr_copy(wsi, buf, sizeof(buf), WSI_TOKEN_GET_URI);
 
 #if LWS_LIBRARY_VERSION_NUMBER >= 2004000
-            lws_get_peer_simple(lws_get_network_wsi(wsi), pss->address, sizeof(pss->address));
+      lws_get_peer_simple(lws_get_network_wsi(wsi), pss->address,
+                          sizeof(pss->address));
 #else
-            char name[100];
-            lws_get_peer_addresses(wsi, lws_get_socket_fd(wsi), name, sizeof(name), pss->address, sizeof(pss->address));
+      char name[100];
+      lws_get_peer_addresses(wsi, lws_get_socket_fd(wsi), name, sizeof(name),
+                             pss->address, sizeof(pss->address));
 #endif
-            lwsl_notice("WS   %s - %s, clients: %d\n", buf, pss->address, server->client_count);
-            break;
-
-        case LWS_CALLBACK_SERVER_WRITEABLE:
-            proc = pss->proc;
-            if (!pss->initialized) {
-                if (pss->initial_cmd_index == sizeof(initial_cmds)) {
-                    pss->initialized = true;
-                    uv_read_start((uv_stream_t *)& proc->pipe, alloc_cb, read_cb);
-                    break;
-                }
-                if (send_initial_message(wsi, pss->initial_cmd_index) < 0) {
-                    lwsl_err("failed to send initial message, index: %d\n", pss->initial_cmd_index);
-                    lws_close_reason(wsi, LWS_CLOSE_STATUS_UNEXPECTED_CONDITION, NULL, 0);
-                    return -1;
-                }
-                pss->initial_cmd_index++;
-                lws_callback_on_writable(wsi);
-                break;
-            }
-
-            // read error or client exited, close connection
-            if (proc->status == 0 || proc->pty_len == 0) {
-                lws_close_reason(wsi, LWS_CLOSE_STATUS_NORMAL, NULL, 0);
-                return 1;
-            } else if (proc->status > 0 || proc->pty_len < 0) {
-                lws_close_reason(wsi, LWS_CLOSE_STATUS_UNEXPECTED_CONDITION, NULL, 0);
-                return -1;
-            }
-
-            if (proc->pty_buffer == NULL)
-                break;
-
-            proc->pty_buffer[LWS_PRE] = OUTPUT;
-            n = (size_t) (proc->pty_len + 1);
-            if (lws_write(wsi, (unsigned char *) proc->pty_buffer + LWS_PRE, n, LWS_WRITE_BINARY) < n) {
-                lwsl_err("write OUTPUT to WS\n");
-            }
-            free(proc->pty_buffer);
-            proc->pty_buffer = NULL;
-            uv_read_start((uv_stream_t *)& proc->pipe, alloc_cb, read_cb);
-            break;
-
-        case LWS_CALLBACK_RECEIVE:
-            if (pss->buffer == NULL) {
-                pss->buffer = xmalloc(len);
-                pss->len = len;
-                memcpy(pss->buffer, in, len);
-            } else {
-                pss->buffer = xrealloc(pss->buffer, pss->len + len);
-                memcpy(pss->buffer + pss->len, in, len);
-                pss->len += len;
-            }
-
-            const char command = pss->buffer[0];
-
-            // check auth
-            if (server->credential != NULL && !pss->authenticated && command != JSON_DATA) {
-                lwsl_warn("WS client not authenticated\n");
-                return 1;
-            }
-
-            // check if there are more fragmented messages
-            if (lws_remaining_packet_payload(wsi) > 0 || !lws_is_final_fragment(wsi)) {
-                return 0;
-            }
-
-            proc = pss->proc;
-            switch (command) {
-                case INPUT:
-                    if (proc->pty == 0)
-                        break;
-                    if (server->readonly)
-                        return 0;
-
-                    char *data = xmalloc(pss->len - 1);
-                    memcpy(data, pss->buffer + 1, pss->len - 1);
-
-                    uv_buf_t b = { data, pss->len - 1 };
-                    uv_write_t *req = xmalloc(sizeof(uv_write_t));
-                    req->data = data;
-
-                    int err = uv_write(req, (uv_stream_t *) &proc->pipe, &b, 1, write_cb);
-                    if (err) {
-                        lwsl_err("uv_write: %s\n", uv_err_name(err));
-                        return -1;
-                    }
-                    break;
-                case RESIZE_TERMINAL:
-                    {
-                        int cols, rows;
-                        if (parse_window_size(pss, &cols, &rows)) {
-                            if (pty_resize(proc->pty, cols, rows) < 0) {
-                                lwsl_err("pty_resize: %d (%s)\n", errno, strerror(errno));
-                            }
-                        }
-                    }
-                    break;
-                case JSON_DATA:
-                    if (proc->pid > 0)
-                        break;
-                    if (server->credential != NULL) {
-                        json_object *obj = json_tokener_parse(pss->buffer);
-                        struct json_object *o = NULL;
-                        if (json_object_object_get_ex(obj, "AuthToken", &o)) {
-                            const char *token = json_object_get_string(o);
-                            if (token != NULL && !strcmp(token, server->credential))
-                                pss->authenticated = true;
-                            else
-                                lwsl_warn("WS authentication failed with token: %s\n", token);
-                        }
-                        if (!pss->authenticated) {
-                            lws_close_reason(wsi, LWS_CLOSE_STATUS_POLICY_VIOLATION, NULL, 0);
-                            return -1;
-                        }
-                    }
-                    if (spawn_process(pss) != 0) return 1;
-                    break;
-                default:
-                    lwsl_warn("ignored unknown message type: %c\n", command);
-                    break;
-            }
-
-            if (pss->buffer != NULL) {
-                free(pss->buffer);
-                pss->buffer = NULL;
-            }
-            break;
-
-        case LWS_CALLBACK_CLOSED:
-            if (pss->wsi == NULL)
-                break;
-
-            server->client_count--;
-            lwsl_notice("WS closed from %s, clients: %d\n", pss->address, server->client_count);
-            if (pss->buffer != NULL) {
-                free(pss->buffer);
+      lwsl_notice("WS   %s - %s, clients: %d\n", buf, pss->address,
+                  server->client_count);
+      break;
+
+    case LWS_CALLBACK_SERVER_WRITEABLE:
+      proc = pss->proc;
+      if (!pss->initialized) {
+        if (pss->initial_cmd_index == sizeof(initial_cmds)) {
+          pss->initialized = true;
+          uv_read_start((uv_stream_t *)&proc->pipe, alloc_cb, read_cb);
+          break;
+        }
+        if (send_initial_message(wsi, pss->initial_cmd_index) < 0) {
+          lwsl_err("failed to send initial message, index: %d\n",
+                   pss->initial_cmd_index);
+          lws_close_reason(wsi, LWS_CLOSE_STATUS_UNEXPECTED_CONDITION, NULL, 0);
+          return -1;
+        }
+        pss->initial_cmd_index++;
+        lws_callback_on_writable(wsi);
+        break;
+      }
+
+      // read error or client exited, close connection
+      if (proc->status == 0 || proc->pty_len == 0) {
+        lws_close_reason(wsi, LWS_CLOSE_STATUS_NORMAL, NULL, 0);
+        return 1;
+      } else if (proc->status > 0 || proc->pty_len < 0) {
+        lws_close_reason(wsi, LWS_CLOSE_STATUS_UNEXPECTED_CONDITION, NULL, 0);
+        return -1;
+      }
+
+      if (proc->pty_buffer == NULL) break;
+
+      proc->pty_buffer[LWS_PRE] = OUTPUT;
+      n = (size_t)(proc->pty_len + 1);
+      if (lws_write(wsi, (unsigned char *)proc->pty_buffer + LWS_PRE, n,
+                    LWS_WRITE_BINARY) < n) {
+        lwsl_err("write OUTPUT to WS\n");
+      }
+      free(proc->pty_buffer);
+      proc->pty_buffer = NULL;
+      uv_read_start((uv_stream_t *)&proc->pipe, alloc_cb, read_cb);
+      break;
+
+    case LWS_CALLBACK_RECEIVE:
+      if (pss->buffer == NULL) {
+        pss->buffer = xmalloc(len);
+        pss->len = len;
+        memcpy(pss->buffer, in, len);
+      } else {
+        pss->buffer = xrealloc(pss->buffer, pss->len + len);
+        memcpy(pss->buffer + pss->len, in, len);
+        pss->len += len;
+      }
+
+      const char command = pss->buffer[0];
+
+      // check auth
+      if (server->credential != NULL && !pss->authenticated &&
+          command != JSON_DATA) {
+        lwsl_warn("WS client not authenticated\n");
+        return 1;
+      }
+
+      // check if there are more fragmented messages
+      if (lws_remaining_packet_payload(wsi) > 0 ||
+          !lws_is_final_fragment(wsi)) {
+        return 0;
+      }
+
+      proc = pss->proc;
+      switch (command) {
+        case INPUT:
+          if (proc->pty == 0) break;
+          if (server->readonly) return 0;
+
+          char *data = xmalloc(pss->len - 1);
+          memcpy(data, pss->buffer + 1, pss->len - 1);
+
+          uv_buf_t b = {data, pss->len - 1};
+          uv_write_t *req = xmalloc(sizeof(uv_write_t));
+          req->data = data;
+
+          int err = uv_write(req, (uv_stream_t *)&proc->pipe, &b, 1, write_cb);
+          if (err) {
+            lwsl_err("uv_write: %s\n", uv_err_name(err));
+            return -1;
+          }
+          break;
+        case RESIZE_TERMINAL: {
+          int cols, rows;
+          if (parse_window_size(pss, &cols, &rows)) {
+            if (pty_resize(proc->pty, cols, rows) < 0) {
+              lwsl_err("pty_resize: %d (%s)\n", errno, strerror(errno));
             }
-
-            proc = pss->proc;
-            if (proc->state == STATE_EXIT) {
-                pty_proc_free(proc);
-            } else {
-                proc->state = STATE_KILL;
-                uv_read_stop((uv_stream_t *) &proc->pipe);
-                kill_process(proc);
+          }
+        } break;
+        case JSON_DATA:
+          if (proc->pid > 0) break;
+          if (server->credential != NULL) {
+            json_object *obj = json_tokener_parse(pss->buffer);
+            struct json_object *o = NULL;
+            if (json_object_object_get_ex(obj, "AuthToken", &o)) {
+              const char *token = json_object_get_string(o);
+              if (token != NULL && !strcmp(token, server->credential))
+                pss->authenticated = true;
+              else
+                lwsl_warn("WS authentication failed with token: %s\n", token);
             }
-
-            if (server->once && server->client_count == 0) {
-                lwsl_notice("exiting due to the --once option.\n");
-                force_exit = true;
-                lws_cancel_service(context);
-                exit(0);
+            if (!pss->authenticated) {
+              lws_close_reason(wsi, LWS_CLOSE_STATUS_POLICY_VIOLATION, NULL, 0);
+              return -1;
             }
-            break;
-
+          }
+          if (spawn_process(pss) != 0) return 1;
+          break;
         default:
-            break;
-    }
-
-    return 0;
+          lwsl_warn("ignored unknown message type: %c\n", command);
+          break;
+      }
+
+      if (pss->buffer != NULL) {
+        free(pss->buffer);
+        pss->buffer = NULL;
+      }
+      break;
+
+    case LWS_CALLBACK_CLOSED:
+      if (pss->wsi == NULL) break;
+
+      server->client_count--;
+      lwsl_notice("WS closed from %s, clients: %d\n", pss->address,
+                  server->client_count);
+      if (pss->buffer != NULL) {
+        free(pss->buffer);
+      }
+
+      proc = pss->proc;
+      if (proc->state == STATE_EXIT) {
+        pty_proc_free(proc);
+      } else {
+        proc->state = STATE_KILL;
+        uv_read_stop((uv_stream_t *)&proc->pipe);
+        kill_process(proc);
+      }
+
+      if (server->once && server->client_count == 0) {
+        lwsl_notice("exiting due to the --once option.\n");
+        force_exit = true;
+        lws_cancel_service(context);
+        exit(0);
+      }
+      break;
+
+    default:
+      break;
+  }
+
+  return 0;
 }
index 7a58d625bf41a172320985a570ae729ca87683bc..3debb14ba32d206e875bbce54089c561abca31e9 100644 (file)
@@ -1,16 +1,16 @@
-#include <stdio.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <string.h>
+#include "server.h"
+
 #include <errno.h>
 #include <getopt.h>
+#include <json.h>
+#include <libwebsockets.h>
 #include <signal.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
 #include <sys/stat.h>
 
-#include <libwebsockets.h>
-#include <json.h>
-
-#include "server.h"
 #include "utils.h"
 
 #ifndef TTYD_VERSION
@@ -22,533 +22,537 @@ struct lws_context *context;
 struct server *server;
 struct endpoints endpoints = {"/ws", "/", "/token"};
 
+extern int callback_http(struct lws *wsi, enum lws_callback_reasons reason,
+                         void *user, void *in, size_t len);
+extern int callback_tty(struct lws *wsi, enum lws_callback_reasons reason,
+                        void *user, void *in, size_t len);
+
 // websocket protocols
 static const struct lws_protocols protocols[] = {
-        {"http-only", callback_http, sizeof(struct pss_http), 0},
-        {"tty",       callback_tty,  sizeof(struct pss_tty),  0},
-        {NULL, NULL,                 0,                       0}
-};
+    {"http-only", callback_http, sizeof(struct pss_http), 0},
+    {"tty", callback_tty, sizeof(struct pss_tty), 0},
+    {NULL, NULL, 0, 0}};
 
 #ifndef LWS_WITHOUT_EXTENSIONS
 // websocket extensions
 static const struct lws_extension extensions[] = {
-        {"permessage-deflate", lws_extension_callback_pm_deflate, "permessage-deflate"},
-        {"deflate-frame",      lws_extension_callback_pm_deflate, "deflate_frame"},
-        {NULL, NULL, NULL}
-};
+    {"permessage-deflate", lws_extension_callback_pm_deflate,
+     "permessage-deflate"},
+    {"deflate-frame", lws_extension_callback_pm_deflate, "deflate_frame"},
+    {NULL, NULL, NULL}};
 #endif
 
 // command line options
 static const struct option options[] = {
-        {"port",          required_argument, NULL, 'p'},
-        {"interface",     required_argument, NULL, 'i'},
-        {"credential",    required_argument, NULL, 'c'},
-        {"uid",           required_argument, NULL, 'u'},
-        {"gid",           required_argument, NULL, 'g'},
-        {"signal",        required_argument, NULL, 's'},
-        {"index",         required_argument, NULL, 'I'},
-        {"base-path",     required_argument, NULL, 'b'},
-        {"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'},
-        {"terminal-type", required_argument, NULL, 'T'},
-        {"client-option", required_argument, NULL, 't'},
-        {"check-origin",  no_argument,       NULL, 'O'},
-        {"max-clients",   required_argument, NULL, 'm'},
-        {"once",          no_argument,       NULL, 'o'},
-        {"browser",       no_argument,       NULL, 'B'},
-        {"debug",         required_argument, NULL, 'd'},
-        {"version",       no_argument,       NULL, 'v'},
-        {"help",          no_argument,       NULL, 'h'},
-        {NULL, 0, 0,                               0}
-};
+    {"port", required_argument, NULL, 'p'},
+    {"interface", required_argument, NULL, 'i'},
+    {"credential", required_argument, NULL, 'c'},
+    {"uid", required_argument, NULL, 'u'},
+    {"gid", required_argument, NULL, 'g'},
+    {"signal", required_argument, NULL, 's'},
+    {"index", required_argument, NULL, 'I'},
+    {"base-path", required_argument, NULL, 'b'},
+    {"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'},
+    {"terminal-type", required_argument, NULL, 'T'},
+    {"client-option", required_argument, NULL, 't'},
+    {"check-origin", no_argument, NULL, 'O'},
+    {"max-clients", required_argument, NULL, 'm'},
+    {"once", no_argument, NULL, 'o'},
+    {"browser", no_argument, NULL, 'B'},
+    {"debug", required_argument, NULL, 'd'},
+    {"version", no_argument, NULL, 'v'},
+    {"help", no_argument, NULL, 'h'},
+    {NULL, 0, 0, 0}};
 static const char *opt_string = "p:i:c:u:g:s:I:b:6aSC:K:A:Rt:T:Om:oBd:vh";
 
-static void
-print_help() {
-    fprintf(stderr, "ttyd is a tool for sharing terminal over the web\n\n"
-                    "USAGE:\n"
-                    "    ttyd [options] <command> [<arguments...>]\n\n"
-                    "VERSION:\n"
-                    "    %s\n\n"
-                    "OPTIONS:\n"
-                    "    -p, --port              Port to listen (default: 7681, use `0` for random port)\n"
-                    "    -i, --interface         Network interface to bind (eg: eth0), or UNIX domain socket path (eg: /var/run/ttyd.sock)\n"
-                    "    -c, --credential        Credential for Basic Authentication (format: username:password)\n"
-                    "    -u, --uid               User id to run with\n"
-                    "    -g, --gid               Group id to run with\n"
-                    "    -s, --signal            Signal to send to the command when exit it (default: 1, SIGHUP)\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"
-                    "    -O, --check-origin      Do not allow websocket connection from different origin\n"
-                    "    -m, --max-clients       Maximum clients to support (default: 0, no limit)\n"
-                    "    -o, --once              Accept only one client and exit on disconnection\n"
-                    "    -B, --browser           Open terminal with the default system browser\n"
-                    "    -I, --index             Custom index.html path\n"
-                    "    -b, --base-path         Expected base path for requests coming from a reverse proxy (eg: /mounted/here)\n"
+static void print_help() {
+  // clang-format off
+  fprintf(stderr, "ttyd is a tool for sharing terminal over the web\n\n"
+                  "USAGE:\n"
+                  "    ttyd [options] <command> [<arguments...>]\n\n"
+                  "VERSION:\n"
+                  "    %s\n\n"
+                  "OPTIONS:\n"
+                  "    -p, --port              Port to listen (default: 7681, use `0` for random port)\n"
+                  "    -i, --interface         Network interface to bind (eg: eth0), or UNIX domain socket path (eg: /var/run/ttyd.sock)\n"
+                  "    -c, --credential        Credential for Basic Authentication (format: username:password)\n"
+                  "    -u, --uid               User id to run with\n"
+                  "    -g, --gid               Group id to run with\n"
+                  "    -s, --signal            Signal to send to the command when exit it (default: 1, SIGHUP)\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"
+                  "    -O, --check-origin      Do not allow websocket connection from different origin\n"
+                  "    -m, --max-clients       Maximum clients to support (default: 0, no limit)\n"
+                  "    -o, --once              Accept only one client and exit on disconnection\n"
+                  "    -B, --browser           Open terminal with the default system browser\n"
+                  "    -I, --index             Custom index.html path\n"
+                  "    -b, --base-path         Expected base path for requests coming from a reverse proxy (eg: /mounted/here)\n"
 #ifdef LWS_WITH_IPV6
-                    "    -6, --ipv6              Enable IPv6 support\n"
+                  "    -6, --ipv6              Enable IPv6 support\n"
 #endif
-                    "    -S, --ssl               Enable SSL\n"
-                    "    -C, --ssl-cert          SSL certificate file path\n"
-                    "    -K, --ssl-key           SSL key file path\n"
-                    "    -A, --ssl-ca            SSL CA file path for client certificate verification\n"
-                    "    -d, --debug             Set log level (default: 7)\n"
-                    "    -v, --version           Print the version and exit\n"
-                    "    -h, --help              Print this text and exit\n\n"
-                    "Visit https://github.com/tsl0922/ttyd to get more information and report bugs.\n",
-            TTYD_VERSION
-    );
+                  "    -S, --ssl               Enable SSL\n"
+                  "    -C, --ssl-cert          SSL certificate file path\n"
+                  "    -K, --ssl-key           SSL key file path\n"
+                  "    -A, --ssl-ca            SSL CA file path for client certificate verification\n"
+                  "    -d, --debug             Set log level (default: 7)\n"
+                  "    -v, --version           Print the version and exit\n"
+                  "    -h, --help              Print this text and exit\n\n"
+                  "Visit https://github.com/tsl0922/ttyd to get more information and report bugs.\n",
+          TTYD_VERSION
+  );
+  // clang-format on
 }
 
-static struct server *
-server_new(int argc, char **argv, int start) {
-    struct server *ts;
-    size_t cmd_len = 0;
-
-    ts = xmalloc(sizeof(struct server));
-
-    memset(ts, 0, sizeof(struct server));
-    LIST_INIT(&ts->procs);
-    ts->client_count = 0;
-    ts->sig_code = SIGHUP;
-    sprintf(ts->terminal_type, "%s", "xterm-256color");
-    get_sig_name(ts->sig_code, ts->sig_name, sizeof(ts->sig_name));
-    if (start == argc)
-        return ts;
-
-    int cmd_argc = argc - start;
-    char **cmd_argv = &argv[start];
-    ts->argv = xmalloc(sizeof(char *) * (cmd_argc + 1));
-    for (int i = 0; i < cmd_argc; i++) {
-        ts->argv[i] = strdup(cmd_argv[i]);
-        cmd_len += strlen(ts->argv[i]);
-        if (i != cmd_argc - 1) {
-            cmd_len++; // for space
-        }
+static struct server *server_new(int argc, char **argv, int start) {
+  struct server *ts;
+  size_t cmd_len = 0;
+
+  ts = xmalloc(sizeof(struct server));
+
+  memset(ts, 0, sizeof(struct server));
+  LIST_INIT(&ts->procs);
+  ts->client_count = 0;
+  ts->sig_code = SIGHUP;
+  sprintf(ts->terminal_type, "%s", "xterm-256color");
+  get_sig_name(ts->sig_code, ts->sig_name, sizeof(ts->sig_name));
+  if (start == argc) return ts;
+
+  int cmd_argc = argc - start;
+  char **cmd_argv = &argv[start];
+  ts->argv = xmalloc(sizeof(char *) * (cmd_argc + 1));
+  for (int i = 0; i < cmd_argc; i++) {
+    ts->argv[i] = strdup(cmd_argv[i]);
+    cmd_len += strlen(ts->argv[i]);
+    if (i != cmd_argc - 1) {
+      cmd_len++;  // for space
     }
-    ts->argv[cmd_argc] = NULL;
-    ts->argc = cmd_argc;
-
-    ts->command = xmalloc(cmd_len + 1);
-    char *ptr = ts->command;
-    for (int i = 0; i < cmd_argc; i++) {
-        ptr = stpcpy(ptr, ts->argv[i]);
-        if (i != cmd_argc - 1) {
-            *ptr++ = ' ';
-        }
+  }
+  ts->argv[cmd_argc] = NULL;
+  ts->argc = cmd_argc;
+
+  ts->command = xmalloc(cmd_len + 1);
+  char *ptr = ts->command;
+  for (int i = 0; i < cmd_argc; i++) {
+    ptr = stpcpy(ptr, ts->argv[i]);
+    if (i != cmd_argc - 1) {
+      *ptr++ = ' ';
     }
-    *ptr = '\0'; // null terminator
+  }
+  *ptr = '\0';  // null terminator
 
-    ts->loop = xmalloc(sizeof *ts->loop);
-    uv_loop_init(ts->loop);
-    uv_signal_init(ts->loop, &ts->watcher);
-    ts->watcher.data = &ts->procs;
+  ts->loop = xmalloc(sizeof *ts->loop);
+  uv_loop_init(ts->loop);
+  uv_signal_init(ts->loop, &ts->watcher);
+  ts->watcher.data = &ts->procs;
 
-    return ts;
+  return ts;
 }
 
-static void
-server_free(struct server *ts) {
-    if (ts == NULL)
-        return;
-    if (ts->credential != NULL)
-        free(ts->credential);
-    if (ts->index != NULL)
-        free(ts->index);
-    free(ts->command);
-    free(ts->prefs_json);
-    int i = 0;
-    do {
-        free(ts->argv[i++]);
-    } while (ts->argv[i] != NULL);
-    free(ts->argv);
-    if (strlen(ts->socket_path) > 0) {
-        struct stat st;
-        if (!stat(ts->socket_path, &st)) {
-            unlink(ts->socket_path);
-        }
+static void server_free(struct server *ts) {
+  if (ts == NULL) return;
+  if (ts->credential != NULL) free(ts->credential);
+  if (ts->index != NULL) free(ts->index);
+  free(ts->command);
+  free(ts->prefs_json);
+  int i = 0;
+  do {
+    free(ts->argv[i++]);
+  } while (ts->argv[i] != NULL);
+  free(ts->argv);
+  if (strlen(ts->socket_path) > 0) {
+    struct stat st;
+    if (!stat(ts->socket_path, &st)) {
+      unlink(ts->socket_path);
     }
-    uv_signal_stop(&ts->watcher);
-    uv_loop_close(ts->loop);
-    free(ts->loop);
-    free(ts);
+  }
+  uv_signal_stop(&ts->watcher);
+  uv_loop_close(ts->loop);
+  free(ts->loop);
+  free(ts);
 }
 
-static void
-signal_cb(uv_signal_t *watcher, int signum) {
-    char sig_name[20];
-
-    switch (watcher->signum) {
-        case SIGINT:
-        case SIGTERM:
-            get_sig_name(watcher->signum, sig_name, sizeof(sig_name));
-            lwsl_notice("received signal: %s (%d), exiting...\n", sig_name, watcher->signum);
-            break;
-        default:
-            signal(SIGABRT, SIG_DFL);
-            abort();
-    }
-
-    if (force_exit)
-        exit(EXIT_FAILURE);
-    force_exit = true;
-    lws_cancel_service(context);
+static void signal_cb(uv_signal_t *watcher, int signum) {
+  char sig_name[20];
+
+  switch (watcher->signum) {
+    case SIGINT:
+    case SIGTERM:
+      get_sig_name(watcher->signum, sig_name, sizeof(sig_name));
+      lwsl_notice("received signal: %s (%d), exiting...\n", sig_name,
+                  watcher->signum);
+      break;
+    default:
+      signal(SIGABRT, SIG_DFL);
+      abort();
+  }
+
+  if (force_exit) exit(EXIT_FAILURE);
+  force_exit = true;
+  lws_cancel_service(context);
 #if LWS_LIBRARY_VERSION_MAJOR >= 3
-    uv_stop(server->loop);
-    lwsl_notice("send ^C to force exit.\n");
+  uv_stop(server->loop);
+  lwsl_notice("send ^C to force exit.\n");
 #else
-    lws_libuv_stop(context);
-    exit(EXIT_SUCCESS);
+  lws_libuv_stop(context);
+  exit(EXIT_SUCCESS);
 #endif
 }
 
-static int
-calc_command_start(int argc, char **argv) {
-    // make a copy of argc and argv
-    int argc_copy = argc;
-    char **argv_copy = xmalloc(sizeof(char *) * argc);
+static int calc_command_start(int argc, char **argv) {
+  // make a copy of argc and argv
+  int argc_copy = argc;
+  char **argv_copy = xmalloc(sizeof(char *) * argc);
+  for (int i = 0; i < argc; i++) {
+    argv_copy[i] = strdup(argv[i]);
+  }
+
+  // do not print error message for invalid option
+  opterr = 0;
+  while (getopt_long(argc_copy, argv_copy, opt_string, options, NULL) != -1)
+    ;
+
+  int start = argc;
+  if (optind < argc) {
+    char *command = argv_copy[optind];
     for (int i = 0; i < argc; i++) {
-        argv_copy[i] = strdup(argv[i]);
-    }
-
-    // do not print error message for invalid option
-    opterr = 0;
-    while (getopt_long(argc_copy, argv_copy, opt_string, options, NULL) != -1)
-        ;
-
-    int start = argc;
-    if (optind < argc) {
-        char *command = argv_copy[optind];
-        for (int i = 0; i < argc; i++) {
-            if (strcmp(argv[i], command) == 0) {
-                start = i;
-                break;
-            }
-        }
+      if (strcmp(argv[i], command) == 0) {
+        start = i;
+        break;
+      }
     }
+  }
 
-    // free argv copy
-    for (int i = 0; i < argc; i++) {
-        free(argv_copy[i]);
-    }
-    free(argv_copy);
+  // free argv copy
+  for (int i = 0; i < argc; i++) {
+    free(argv_copy[i]);
+  }
+  free(argv_copy);
 
-    // reset for next use
-    opterr = 1;
-    optind = 0;
+  // reset for next use
+  opterr = 1;
+  optind = 0;
 
-    return start;
+  return start;
 }
 
-int
-main(int argc, char **argv) {
-    if (argc == 1) {
-        print_help();
-        return 0;
-    }
-
-    int start = calc_command_start(argc, argv);
-    server = server_new(argc, argv, start);
-
-    struct lws_context_creation_info info;
-    memset(&info, 0, sizeof(info));
-    info.port = 7681;
-    info.iface = NULL;
-    info.protocols = protocols;
-    info.ssl_cert_filepath = NULL;
-    info.ssl_private_key_filepath = NULL;
-    info.gid = -1;
-    info.uid = -1;
-    info.max_http_header_pool = 16;
-    info.options = LWS_SERVER_OPTION_LIBUV | LWS_SERVER_OPTION_VALIDATE_UTF8 | LWS_SERVER_OPTION_DISABLE_IPV6;
+int main(int argc, char **argv) {
+  if (argc == 1) {
+    print_help();
+    return 0;
+  }
+
+  int start = calc_command_start(argc, argv);
+  server = server_new(argc, argv, start);
+
+  struct lws_context_creation_info info;
+  memset(&info, 0, sizeof(info));
+  info.port = 7681;
+  info.iface = NULL;
+  info.protocols = protocols;
+  info.ssl_cert_filepath = NULL;
+  info.ssl_private_key_filepath = NULL;
+  info.gid = -1;
+  info.uid = -1;
+  info.max_http_header_pool = 16;
+  info.options = LWS_SERVER_OPTION_LIBUV | LWS_SERVER_OPTION_VALIDATE_UTF8 |
+                 LWS_SERVER_OPTION_DISABLE_IPV6;
 #ifndef LWS_WITHOUT_EXTENSIONS
-    info.extensions = extensions;
+  info.extensions = extensions;
 #endif
-    info.max_http_header_data = 20480;
-
-    int debug_level = LLL_ERR | LLL_WARN | LLL_NOTICE;
-    char iface[128] = "";
-    bool browser = false;
-    bool ssl = false;
-    char cert_path[1024] = "";
-    char key_path[1024] = "";
-    char ca_path[1024] = "";
-
-    struct json_object *client_prefs = json_object_new_object();
-
-    // parse command line options
-    int c;
-    while ((c = getopt_long(start, argv, opt_string, options, NULL)) != -1) {
-        switch (c) {
-            case 'h':
-                print_help();
-                return 0;
-            case 'v':
-                printf("ttyd version %s\n", TTYD_VERSION);
-                return 0;
-            case 'd':
-                debug_level = atoi(optarg);
-                break;
-            case 'a':
-                server->url_arg = true;
-                break;
-            case 'R':
-                server->readonly = true;
-                break;
-            case 'O':
-                server->check_origin = true;
-                break;
-            case 'm':
-                server->max_clients = atoi(optarg);
-                break;
-            case 'o':
-                server->once = true;
-                break;
-            case 'B':
-                browser = true;
-                break;
-            case 'p':
-                info.port = atoi(optarg);
-                if (info.port < 0) {
-                    fprintf(stderr, "ttyd: invalid port: %s\n", optarg);
-                    return -1;
-                }
-                break;
-            case 'i':
-                strncpy(iface, optarg, sizeof(iface) - 1);
-                iface[sizeof(iface) - 1] = '\0';
-                break;
-            case 'c':
-                if (strchr(optarg, ':') == NULL) {
-                    fprintf(stderr, "ttyd: invalid credential, format: username:password\n");
-                    return -1;
-                }
-                server->credential = base64_encode((const unsigned char *) optarg, strlen(optarg));
-                break;
-            case 'u':
-                info.uid = atoi(optarg);
-                break;
-            case 'g':
-                info.gid = atoi(optarg);
-                break;
-            case 's': {
-                int sig = get_sig(optarg);
-                if (sig > 0) {
-                    server->sig_code = sig;
-                    get_sig_name(sig, server->sig_name, sizeof(server->sig_name));
-                } else {
-                    fprintf(stderr, "ttyd: invalid signal: %s\n", optarg);
-                    return -1;
-                }
-            }
-                break;
-            case 'I':
-                if (!strncmp(optarg, "~/", 2)) {
-                    const char *home = getenv("HOME");
-                    server->index = malloc(strlen(home) + strlen(optarg) - 1);
-                    sprintf(server->index, "%s%s", home, optarg + 1);
-                } else {
-                    server->index = strdup(optarg);
-                }
-                struct stat st;
-                if (stat(server->index, &st) == -1) {
-                    fprintf(stderr, "Can not stat index.html: %s, error: %s\n", server->index, strerror(errno));
-                    return -1;
-                }
-                if (S_ISDIR(st.st_mode)) {
-                    fprintf(stderr, "Invalid index.html path: %s, is it a dir?\n", server->index);
-                    return -1;
-                }
-                break;
-            case 'b': {
-                char path[128];
-                strncpy(path, optarg, 128);
-                size_t len = strlen(path);
-                #define sc(f) \
-                  strncpy(path + len, endpoints.f, 128 - len); \
-                  endpoints.f = strdup(path);
-                sc(ws) sc(index) sc(token)
-                #undef sc
-            }
-                break;
-            case '6':
-                info.options &= ~(LWS_SERVER_OPTION_DISABLE_IPV6);
-                break;
-            case 'S':
-                ssl = true;
-                break;
-            case 'C':
-                strncpy(cert_path, optarg, sizeof(cert_path) - 1);
-                cert_path[sizeof(cert_path) - 1] = '\0';
-                break;
-            case 'K':
-                strncpy(key_path, optarg, sizeof(key_path) - 1);
-                key_path[sizeof(key_path) - 1] = '\0';
-                break;
-            case 'A':
-                strncpy(ca_path, optarg, sizeof(ca_path) - 1);
-                ca_path[sizeof(ca_path) - 1] = '\0';
-                break;
-            case 'T':
-                strncpy(server->terminal_type, optarg, sizeof(server->terminal_type) - 1);
-                server->terminal_type[sizeof(server->terminal_type) - 1] = '\0';
-                break;
-            case '?':
-                break;
-            case 't':
-                optind--;
-                for (; optind < start && *argv[optind] != '-'; optind++) {
-                    char *option = strdup(optarg);
-                    char *key = strsep(&option, "=");
-                    if (key == NULL) {
-                        fprintf(stderr, "ttyd: invalid client option: %s, format: key=value\n", optarg);
-                        return -1;
-                    }
-                    char *value = strsep(&option, "=");
-                    if (value == NULL) {
-                        fprintf(stderr, "ttyd: invalid client option: %s, format: key=value\n", optarg);
-                        return -1;
-                    }
-                    free(option);
-                    struct json_object *obj = json_tokener_parse(value);
-                    json_object_object_add(client_prefs, key, obj != NULL ? obj : json_object_new_string(value));
-                }
-                break;
-            default:
-                print_help();
-                return -1;
+  info.max_http_header_data = 20480;
+
+  int debug_level = LLL_ERR | LLL_WARN | LLL_NOTICE;
+  char iface[128] = "";
+  bool browser = false;
+  bool ssl = false;
+  char cert_path[1024] = "";
+  char key_path[1024] = "";
+  char ca_path[1024] = "";
+
+  struct json_object *client_prefs = json_object_new_object();
+
+  // parse command line options
+  int c;
+  while ((c = getopt_long(start, argv, opt_string, options, NULL)) != -1) {
+    switch (c) {
+      case 'h':
+        print_help();
+        return 0;
+      case 'v':
+        printf("ttyd version %s\n", TTYD_VERSION);
+        return 0;
+      case 'd':
+        debug_level = atoi(optarg);
+        break;
+      case 'a':
+        server->url_arg = true;
+        break;
+      case 'R':
+        server->readonly = true;
+        break;
+      case 'O':
+        server->check_origin = true;
+        break;
+      case 'm':
+        server->max_clients = atoi(optarg);
+        break;
+      case 'o':
+        server->once = true;
+        break;
+      case 'B':
+        browser = true;
+        break;
+      case 'p':
+        info.port = atoi(optarg);
+        if (info.port < 0) {
+          fprintf(stderr, "ttyd: invalid port: %s\n", optarg);
+          return -1;
         }
-    }
-    server->prefs_json = strdup(json_object_to_json_string(client_prefs));
-    json_object_put(client_prefs);
-
-    if (server->command == NULL || strlen(server->command) == 0) {
-        fprintf(stderr, "ttyd: missing start command\n");
+        break;
+      case 'i':
+        strncpy(iface, optarg, sizeof(iface) - 1);
+        iface[sizeof(iface) - 1] = '\0';
+        break;
+      case 'c':
+        if (strchr(optarg, ':') == NULL) {
+          fprintf(stderr,
+                  "ttyd: invalid credential, format: username:password\n");
+          return -1;
+        }
+        server->credential =
+            base64_encode((const unsigned char *)optarg, strlen(optarg));
+        break;
+      case 'u':
+        info.uid = atoi(optarg);
+        break;
+      case 'g':
+        info.gid = atoi(optarg);
+        break;
+      case 's': {
+        int sig = get_sig(optarg);
+        if (sig > 0) {
+          server->sig_code = sig;
+          get_sig_name(sig, server->sig_name, sizeof(server->sig_name));
+        } else {
+          fprintf(stderr, "ttyd: invalid signal: %s\n", optarg);
+          return -1;
+        }
+      } break;
+      case 'I':
+        if (!strncmp(optarg, "~/", 2)) {
+          const char *home = getenv("HOME");
+          server->index = malloc(strlen(home) + strlen(optarg) - 1);
+          sprintf(server->index, "%s%s", home, optarg + 1);
+        } else {
+          server->index = strdup(optarg);
+        }
+        struct stat st;
+        if (stat(server->index, &st) == -1) {
+          fprintf(stderr, "Can not stat index.html: %s, error: %s\n",
+                  server->index, strerror(errno));
+          return -1;
+        }
+        if (S_ISDIR(st.st_mode)) {
+          fprintf(stderr, "Invalid index.html path: %s, is it a dir?\n",
+                  server->index);
+          return -1;
+        }
+        break;
+      case 'b': {
+        char path[128];
+        strncpy(path, optarg, 128);
+        size_t len = strlen(path);
+#define sc(f)                                  \
+  strncpy(path + len, endpoints.f, 128 - len); \
+  endpoints.f = strdup(path);
+        sc(ws) sc(index) sc(token)
+#undef sc
+      } break;
+      case '6':
+        info.options &= ~(LWS_SERVER_OPTION_DISABLE_IPV6);
+        break;
+      case 'S':
+        ssl = true;
+        break;
+      case 'C':
+        strncpy(cert_path, optarg, sizeof(cert_path) - 1);
+        cert_path[sizeof(cert_path) - 1] = '\0';
+        break;
+      case 'K':
+        strncpy(key_path, optarg, sizeof(key_path) - 1);
+        key_path[sizeof(key_path) - 1] = '\0';
+        break;
+      case 'A':
+        strncpy(ca_path, optarg, sizeof(ca_path) - 1);
+        ca_path[sizeof(ca_path) - 1] = '\0';
+        break;
+      case 'T':
+        strncpy(server->terminal_type, optarg,
+                sizeof(server->terminal_type) - 1);
+        server->terminal_type[sizeof(server->terminal_type) - 1] = '\0';
+        break;
+      case '?':
+        break;
+      case 't':
+        optind--;
+        for (; optind < start && *argv[optind] != '-'; optind++) {
+          char *option = strdup(optarg);
+          char *key = strsep(&option, "=");
+          if (key == NULL) {
+            fprintf(stderr,
+                    "ttyd: invalid client option: %s, format: key=value\n",
+                    optarg);
+            return -1;
+          }
+          char *value = strsep(&option, "=");
+          if (value == NULL) {
+            fprintf(stderr,
+                    "ttyd: invalid client option: %s, format: key=value\n",
+                    optarg);
+            return -1;
+          }
+          free(option);
+          struct json_object *obj = json_tokener_parse(value);
+          json_object_object_add(
+              client_prefs, key,
+              obj != NULL ? obj : json_object_new_string(value));
+        }
+        break;
+      default:
+        print_help();
         return -1;
     }
+  }
+  server->prefs_json = strdup(json_object_to_json_string(client_prefs));
+  json_object_put(client_prefs);
 
-    lws_set_log_level(debug_level, NULL);
+  if (server->command == NULL || strlen(server->command) == 0) {
+    fprintf(stderr, "ttyd: missing start command\n");
+    return -1;
+  }
+
+  lws_set_log_level(debug_level, NULL);
 
 #if LWS_LIBRARY_VERSION_MAJOR >= 2
-    char server_hdr[128] = "";
-    sprintf(server_hdr, "ttyd/%s (libwebsockets/%s)", TTYD_VERSION, LWS_LIBRARY_VERSION);
-    info.server_string = server_hdr;
+  char server_hdr[128] = "";
+  sprintf(server_hdr, "ttyd/%s (libwebsockets/%s)", TTYD_VERSION,
+          LWS_LIBRARY_VERSION);
+  info.server_string = server_hdr;
 #if LWS_LIBRARY_VERSION_MINOR >= 1
-    info.ws_ping_pong_interval = 5;
+  info.ws_ping_pong_interval = 5;
 #endif
 #endif
 
-    if (strlen(iface) > 0) {
-        info.iface = iface;
-        if (endswith(info.iface, ".sock") || endswith(info.iface, ".socket")) {
+  if (strlen(iface) > 0) {
+    info.iface = iface;
+    if (endswith(info.iface, ".sock") || endswith(info.iface, ".socket")) {
 #if defined(LWS_USE_UNIX_SOCK) || defined(LWS_WITH_UNIX_SOCK)
-            info.options |= LWS_SERVER_OPTION_UNIX_SOCK;
-            strncpy(server->socket_path, info.iface, sizeof(server->socket_path) - 1);
+      info.options |= LWS_SERVER_OPTION_UNIX_SOCK;
+      strncpy(server->socket_path, info.iface, sizeof(server->socket_path) - 1);
 #else
-            fprintf(stderr, "libwebsockets is not compiled with UNIX domain socket support");
-            return -1;
+      fprintf(stderr,
+              "libwebsockets is not compiled with UNIX domain socket support");
+      return -1;
 #endif
-        }
     }
-
-    if (ssl) {
-        info.ssl_cert_filepath = cert_path;
-        info.ssl_private_key_filepath = key_path;
-        info.ssl_ca_filepath = ca_path;
-        if (strlen(info.ssl_ca_filepath) > 0)
-            info.options |= LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT;
+  }
+
+  if (ssl) {
+    info.ssl_cert_filepath = cert_path;
+    info.ssl_private_key_filepath = key_path;
+    info.ssl_ca_filepath = ca_path;
+    if (strlen(info.ssl_ca_filepath) > 0)
+      info.options |= LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT;
 #if LWS_LIBRARY_VERSION_MAJOR >= 2
-        info.options |= LWS_SERVER_OPTION_REDIRECT_HTTP_TO_HTTPS;
+    info.options |= LWS_SERVER_OPTION_REDIRECT_HTTP_TO_HTTPS;
 #endif
-    }
-
-    lwsl_notice("ttyd %s (libwebsockets %s)\n", TTYD_VERSION, LWS_LIBRARY_VERSION);
-    lwsl_notice("tty configuration:\n");
-    if (server->credential != NULL)
-        lwsl_notice("  credential: %s\n", server->credential);
-    lwsl_notice("  start command: %s\n", server->command);
-    lwsl_notice("  close signal: %s (%d)\n", server->sig_name, server->sig_code);
-    lwsl_notice("  terminal type: %s\n", server->terminal_type);
-    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)
-        lwsl_notice("  max clients: %d\n", server->max_clients);
-    if (server->once)
-        lwsl_notice("  once: true\n");
-    if (server->index != NULL) {
-        lwsl_notice("  custom index.html: %s\n", server->index);
-    }
+  }
+
+  lwsl_notice("ttyd %s (libwebsockets %s)\n", TTYD_VERSION,
+              LWS_LIBRARY_VERSION);
+  lwsl_notice("tty configuration:\n");
+  if (server->credential != NULL)
+    lwsl_notice("  credential: %s\n", server->credential);
+  lwsl_notice("  start command: %s\n", server->command);
+  lwsl_notice("  close signal: %s (%d)\n", server->sig_name, server->sig_code);
+  lwsl_notice("  terminal type: %s\n", server->terminal_type);
+  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)
+    lwsl_notice("  max clients: %d\n", server->max_clients);
+  if (server->once) lwsl_notice("  once: true\n");
+  if (server->index != NULL) {
+    lwsl_notice("  custom index.html: %s\n", server->index);
+  }
 
 #if LWS_LIBRARY_VERSION_MAJOR >= 3
-    void *foreign_loops[1];
-    foreign_loops[0] = server->loop;
-    info.foreign_loops = foreign_loops;
-    info.options |= LWS_SERVER_OPTION_EXPLICIT_VHOSTS;
+  void *foreign_loops[1];
+  foreign_loops[0] = server->loop;
+  info.foreign_loops = foreign_loops;
+  info.options |= LWS_SERVER_OPTION_EXPLICIT_VHOSTS;
 #endif
 
-    context = lws_create_context(&info);
-    if (context == NULL) {
-        lwsl_err("libwebsockets context creation failed\n");
-        return 1;
-    }
+  context = lws_create_context(&info);
+  if (context == NULL) {
+    lwsl_err("libwebsockets context creation failed\n");
+    return 1;
+  }
 
 #if LWS_LIBRARY_VERSION_MAJOR >= 3
-    struct lws_vhost *vhost = lws_create_vhost(context, &info);
-    if (vhost == NULL) {
-        lwsl_err("libwebsockets vhost creation failed\n");
-        return 1;
-    }
-    int port = lws_get_vhost_listen_port(vhost);
+  struct lws_vhost *vhost = lws_create_vhost(context, &info);
+  if (vhost == NULL) {
+    lwsl_err("libwebsockets vhost creation failed\n");
+    return 1;
+  }
+  int port = lws_get_vhost_listen_port(vhost);
 #else
-    int port = info.port;
+  int port = info.port;
 #endif
-    lwsl_notice(" Listening on port: %d\n", port);
+  lwsl_notice(" Listening on port: %d\n", port);
 
-    if (browser) {
-        char url[30];
-        sprintf(url, "%s://localhost:%d", ssl ? "https" : "http", port);
-        open_uri(url);
-    }
+  if (browser) {
+    char url[30];
+    sprintf(url, "%s://localhost:%d", ssl ? "https" : "http", port);
+    open_uri(url);
+  }
 
 #if LWS_LIBRARY_VERSION_MAJOR >= 3
-    int sig_nums[] = {SIGINT, SIGTERM};
-    int ns = sizeof(sig_nums)/sizeof(sig_nums[0]);
-    uv_signal_t signals[ns];
-    for (int i = 0; i < ns; i++) {
-        uv_signal_init(server->loop, &signals[i]);
-        uv_signal_start(&signals[i], signal_cb, sig_nums[i]);
-    }
-
-    lws_service(context, 0);
-
-    for (int i = 0; i < ns; i++) {
-        uv_signal_stop(&signals[i]);
-    }
+  int sig_nums[] = {SIGINT, SIGTERM};
+  int ns = sizeof(sig_nums) / sizeof(sig_nums[0]);
+  uv_signal_t signals[ns];
+  for (int i = 0; i < ns; i++) {
+    uv_signal_init(server->loop, &signals[i]);
+    uv_signal_start(&signals[i], signal_cb, sig_nums[i]);
+  }
+
+  lws_service(context, 0);
+
+  for (int i = 0; i < ns; i++) {
+    uv_signal_stop(&signals[i]);
+  }
 #else
 #if LWS_LIBRARY_VERSION_MAJOR < 2
-    lws_uv_initloop(context, server->loop, signal_cb, 0);
+  lws_uv_initloop(context, server->loop, signal_cb, 0);
 #else
-    lws_uv_sigint_cfg(context, 1, signal_cb);
-    lws_uv_initloop(context, server->loop, 0);
+  lws_uv_sigint_cfg(context, 1, signal_cb);
+  lws_uv_initloop(context, server->loop, 0);
 #endif
-    lws_libuv_run(context, 0);
+  lws_libuv_run(context, 0);
 #endif
 
-    lws_context_destroy(context);
+  lws_context_destroy(context);
 
-    // cleanup
-    server_free(server);
+  // cleanup
+  server_free(server);
 
-    return 0;
+  return 0;
 }
index 7fed37d5a14acc9756ee142d13ffed2bc49c90f2..cd6f49d73b35a8b76b4fc2066c0face803cde238 100644 (file)
@@ -15,9 +15,9 @@
 
 // url paths
 struct endpoints {
-    char *ws;
-    char *index;
-    char *token;
+  char *ws;
+  char *index;
+  char *token;
 };
 
 extern volatile bool force_exit;
@@ -25,74 +25,66 @@ extern struct lws_context *context;
 extern struct server *server;
 extern struct endpoints endpoints;
 
-typedef enum {
-    STATE_INIT, STATE_KILL, STATE_EXIT
-} proc_state;
+typedef enum { STATE_INIT, STATE_KILL, STATE_EXIT } proc_state;
 
 struct pss_http {
-    char path[128];
-    char *buffer;
-    char *ptr;
-    size_t len;
+  char path[128];
+  char *buffer;
+  char *ptr;
+  size_t len;
 };
 
 struct pty_proc {
-    char **args;
-    int argc;
+  char **args;
+  int argc;
 
-    pid_t pid;
-    int status;
-    proc_state state;
+  pid_t pid;
+  int status;
+  proc_state state;
 
-    int pty;
-    char *pty_buffer;
-    ssize_t pty_len;
+  int pty;
+  char *pty_buffer;
+  ssize_t pty_len;
 
-    uv_pipe_t pipe;
+  uv_pipe_t pipe;
 
-    LIST_ENTRY(pty_proc) entry;
+  LIST_ENTRY(pty_proc) entry;
 };
 
 struct pss_tty {
-    bool initialized;
-    int initial_cmd_index;
-    bool authenticated;
-    char address[50];
+  bool initialized;
+  int initial_cmd_index;
+  bool authenticated;
+  char address[50];
 
-    struct lws *wsi;
-    char *buffer;
-    size_t len;
+  struct lws *wsi;
+  char *buffer;
+  size_t len;
 
-    struct pty_proc *proc;
+  struct pty_proc *proc;
 };
 
 struct server {
-    int client_count;                         // client count
-    char *prefs_json;                         // client preferences
-    char *credential;                         // encoded basic auth credential
-    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
-    bool once;                                // whether accept only one client and exit on disconnection
-    char socket_path[255];                    // UNIX domain socket path
-    char terminal_type[30];                   // terminal type to report
-
-    uv_loop_t *loop;                          // the libuv event loop
-    uv_signal_t watcher;                      // SIGCHLD watcher
-
-    LIST_HEAD(proc, pty_proc) procs;         // started process list
+  int client_count;   // client count
+  char *prefs_json;   // client preferences
+  char *credential;   // encoded basic auth credential
+  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
+  bool once;         // whether accept only one client and exit on disconnection
+  char socket_path[255];   // UNIX domain socket path
+  char terminal_type[30];  // terminal type to report
+
+  uv_loop_t *loop;      // the libuv event loop
+  uv_signal_t watcher;  // SIGCHLD watcher
+
+  LIST_HEAD(proc, pty_proc) procs;  // started process list
 };
-
-extern int
-callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len);
-
-extern int
-callback_tty(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len);
-
index 3992ffbd687ec96496189c3516fb69f6c443f632..140573fe28e9a6b913daffb6b365302bd9d04990 100644 (file)
@@ -1,10 +1,10 @@
+#include <errno.h>
+#include <fcntl.h>
 #include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <errno.h>
-#include <unistd.h>
-#include <fcntl.h>
 #include <sys/ioctl.h>
+#include <unistd.h>
 
 #if defined(__OpenBSD__) || defined(__APPLE__)
 #include <util.h>
 
 #include "utils.h"
 
-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);
-        }
-    }
+pid_t pty_fork(int *pty, const char *file, char *const argv[],
+               const char *term) {
+  pid_t pid = forkpty(pty, NULL, NULL, NULL);
 
-    // set the file descriptor non blocking
-    int flags = fcntl(*pty, F_GETFL);
-    if (flags != -1) {
-        fcntl(*pty, F_SETFD, flags | O_NONBLOCK);
+  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
-    fd_set_cloexec(*pty);
+  }
 
-    return pid;
+  // set the file descriptor non blocking
+  int flags = fcntl(*pty, F_GETFL);
+  if (flags != -1) {
+    fcntl(*pty, F_SETFD, flags | O_NONBLOCK);
+  }
+  // set the file descriptor close-on-exec
+  fd_set_cloexec(*pty);
+
+  return pid;
 }
 
-int
-pty_resize(pid_t pty, int cols, int rows) {
-    struct winsize size;
+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;
+  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);
+  return ioctl(pty, TIOCSWINSZ, &size);
 }
index 2dc9c02351308ef9a76845f14d4c5149aa6a092b..63253e9e80d6400cd8498140a20c41ab4624c7aa 100644 (file)
@@ -1,10 +1,8 @@
 #ifndef TTYD_TERMINAL_H
 #define TTYD_TERMINAL_H
 
-int
-pty_fork(int *pty, const char *file, char *const argv[], const char *term);
+int pty_fork(int *pty, const char *file, char *const argv[], const char *term);
 
-int
-pty_resize(int pty, int cols, int rows);
+int pty_resize(int pty, int cols, int rows);
 
-#endif //TTYD_TERMINAL_H
+#endif  // TTYD_TERMINAL_H
index 4853456e8f9b8926ffd6c787a745b16a6daf6c00..052345189e6fee5086f1783f52a777323a31cdbb 100644 (file)
+#include <ctype.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <stdbool.h>
-#include <ctype.h>
 #include <string.h>
-#include <signal.h>
-#include <fcntl.h>
 
 #if defined(__linux__) && !defined(__ANDROID__)
 // https://github.com/karelzak/util-linux/blob/master/misc-utils/kill.c
 const char *sys_signame[NSIG] = {
-    "zero",  "HUP",  "INT",   "QUIT", "ILL",   "TRAP", "ABRT", "UNUSED",
-    "FPE",   "KILL", "USR1",  "SEGV", "USR2",  "PIPE", "ALRM", "TERM",
-    "STKFLT","CHLD", "CONT",  "STOP", "TSTP",  "TTIN", "TTOU", "URG",
-    "XCPU",  "XFSZ", "VTALRM","PROF", "WINCH", "IO",   "PWR",  "SYS", NULL
-};
+    "zero", "HUP",   "INT",  "QUIT", "ILL",  "TRAP", "ABRT", "UNUSED", "FPE",
+    "KILL", "USR1",  "SEGV", "USR2", "PIPE", "ALRM", "TERM", "STKFLT", "CHLD",
+    "CONT", "STOP",  "TSTP", "TTIN", "TTOU", "URG",  "XCPU", "XFSZ",   "VTALRM",
+    "PROF", "WINCH", "IO",   "PWR",  "SYS",  NULL};
 #endif
 
 #if defined(_WIN32) || defined(__CYGWIN__)
-#include <windows.h>
 #include <shellapi.h>
+#include <windows.h>
 // https://github.com/mirror/newlib-cygwin/blob/master/winsup/cygwin/strsig.cc
 #ifndef NSIG
 #define NSIG 33
 #endif
 const char *sys_signame[NSIG] = {
-    "zero",  "HUP",  "INT",   "QUIT", "ILL",   "TRAP", "IOT",  "EMT",
-    "FPE",   "KILL", "BUS",   "SEGV", "SYS",   "PIPE", "ALRM", "TERM",
-    "URG",   "STOP", "TSTP",  "CONT", "CHLD",  "TTIN", "TTOU", "IO",
-    "XCPU",  "XFSZ", "VTALRM","PROF", "WINCH", "PWR",  "USR1", "USR2", NULL
-};
+    "zero", "HUP",   "INT",  "QUIT", "ILL",  "TRAP", "IOT",  "EMT",  "FPE",
+    "KILL", "BUS",   "SEGV", "SYS",  "PIPE", "ALRM", "TERM", "URG",  "STOP",
+    "TSTP", "CONT",  "CHLD", "TTIN", "TTOU", "IO",   "XCPU", "XFSZ", "VTALRM",
+    "PROF", "WINCH", "PWR",  "USR1", "USR2", NULL};
 #endif
 
-void *
-xmalloc(size_t size) {
-    if (size == 0)
-        return NULL;
-    void *p = malloc(size);
-    if (!p)
-        abort();
-    return p;
+void *xmalloc(size_t size) {
+  if (size == 0) return NULL;
+  void *p = malloc(size);
+  if (!p) abort();
+  return p;
 }
 
-void *
-xrealloc(void *p, size_t size) {
-    if ((size == 0) && (p == NULL))
-        return NULL;
-    p = realloc(p, size);
-    if (!p)
-        abort();
-    return p;
+void *xrealloc(void *p, size_t size) {
+  if ((size == 0) && (p == NULL)) return NULL;
+  p = realloc(p, size);
+  if (!p) abort();
+  return p;
 }
 
-char *
-uppercase(char *str) {
-    int i = 0;
-    do {
-        str[i] = (char) toupper(str[i]);
-    } while (str[i++] != '\0');
-    return str;
+char *uppercase(char *str) {
+  int i = 0;
+  do {
+    str[i] = (char)toupper(str[i]);
+  } while (str[i++] != '\0');
+  return str;
 }
 
-bool
-endswith(const char *str, const char *suffix) {
-    size_t str_len = strlen(str);
-    size_t suffix_len = strlen(suffix);
-    return str_len > suffix_len && !strcmp(str + (str_len - suffix_len), suffix);
+bool endswith(const char *str, const char *suffix) {
+  size_t str_len = strlen(str);
+  size_t suffix_len = strlen(suffix);
+  return str_len > suffix_len && !strcmp(str + (str_len - suffix_len), suffix);
 }
 
-int
-get_sig_name(int sig, char *buf, size_t len) {
-    int n = snprintf(buf, len, "SIG%s", sig < NSIG ? sys_signame[sig] : "unknown");
-    uppercase(buf);
-    return n;
+int get_sig_name(int sig, char *buf, size_t len) {
+  int n =
+      snprintf(buf, len, "SIG%s", sig < NSIG ? sys_signame[sig] : "unknown");
+  uppercase(buf);
+  return n;
 }
 
-int
-get_sig(const char *sig_name) {
-    for (int sig = 1; sig < NSIG; sig++) {
-        const char *name = sys_signame[sig];
-        if (name != NULL && (strcasecmp(name, sig_name) == 0 || strcasecmp(name, sig_name + 3) == 0))
-            return sig;
-    }
-    return atoi(sig_name);
+int get_sig(const char *sig_name) {
+  for (int sig = 1; sig < NSIG; sig++) {
+    const char *name = sys_signame[sig];
+    if (name != NULL && (strcasecmp(name, sig_name) == 0 ||
+                         strcasecmp(name, sig_name + 3) == 0))
+      return sig;
+  }
+  return atoi(sig_name);
 }
 
-bool
-fd_set_cloexec(const int fd) {
-    int flags = fcntl(fd, F_GETFD);
-    if (flags < 0)
-        return false;
-    return (flags & FD_CLOEXEC) == 0 || fcntl(fd, F_SETFD, flags | FD_CLOEXEC) != -1;
+bool fd_set_cloexec(const int fd) {
+  int flags = fcntl(fd, F_GETFD);
+  if (flags < 0) return false;
+  return (flags & FD_CLOEXEC) == 0 ||
+         fcntl(fd, F_SETFD, flags | FD_CLOEXEC) != -1;
 }
 
-int
-open_uri(char *uri) {
+int open_uri(char *uri) {
 #ifdef __APPLE__
-    char command[256];
-    sprintf(command, "open %s > /dev/null 2>&1", uri);
-    return system(command);
+  char command[256];
+  sprintf(command, "open %s > /dev/null 2>&1", uri);
+  return system(command);
 #elif defined(_WIN32) || defined(__CYGWIN__)
-    return ShellExecute(0, 0, uri, 0, 0 , SW_SHOW) > 32 ? 0 : 1;
+  return ShellExecute(0, 0, uri, 0, 0, SW_SHOW) > 32 ? 0 : 1;
 #else
-    // check if X server is running
-    if (system("xset -q > /dev/null 2>&1"))
-        return 1;
-    char command[256];
-    sprintf(command, "xdg-open %s > /dev/null 2>&1", uri);
-    return system(command);
+  // check if X server is running
+  if (system("xset -q > /dev/null 2>&1")) return 1;
+  char command[256];
+  sprintf(command, "xdg-open %s > /dev/null 2>&1", uri);
+  return system(command);
 #endif
 }
 
 // https://github.com/darkk/redsocks/blob/master/base64.c
-char *
-base64_encode(const unsigned char *buffer, size_t length) {
-    static const char b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-    char *ret, *dst;
-    unsigned i_bits = 0;
-    int i_shift = 0;
-    int bytes_remaining = (int) length;
+char *base64_encode(const unsigned char *buffer, size_t length) {
+  static const char b64[] =
+      "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+  char *ret, *dst;
+  unsigned i_bits = 0;
+  int i_shift = 0;
+  int bytes_remaining = (int)length;
 
-    ret = dst = xmalloc((size_t) (((length + 2) / 3 * 4) + 1));
-    while (bytes_remaining) {
-        i_bits = (i_bits << 8) + *buffer++;
-        bytes_remaining--;
-        i_shift += 8;
+  ret = dst = xmalloc((size_t)(((length + 2) / 3 * 4) + 1));
+  while (bytes_remaining) {
+    i_bits = (i_bits << 8) + *buffer++;
+    bytes_remaining--;
+    i_shift += 8;
 
-        do {
-            *dst++ = b64[(i_bits << 6 >> i_shift) & 0x3f];
-            i_shift -= 6;
-        } while (i_shift > 6 || (bytes_remaining == 0 && i_shift > 0));
-    }
-    while ((dst - ret) & 3)
-        *dst++ = '=';
-    *dst = '\0';
+    do {
+      *dst++ = b64[(i_bits << 6 >> i_shift) & 0x3f];
+      i_shift -= 6;
+    } while (i_shift > 6 || (bytes_remaining == 0 && i_shift > 0));
+  }
+  while ((dst - ret) & 3) *dst++ = '=';
+  *dst = '\0';
 
-    return ret;
+  return ret;
 }
index a02d0c2dd60f66f2ebb440885b5198649ccb8621..935bec461f7176105da88716853e97f5c902e094 100644 (file)
@@ -2,39 +2,30 @@
 #define TTYD_UTIL_H
 
 // malloc with NULL check
-void *
-xmalloc(size_t size);
+void *xmalloc(size_t size);
 
 // realloc with NULL check
-void *
-xrealloc(void *p, size_t size);
+void *xrealloc(void *p, size_t size);
 
 // Convert a string to upper case
-char *
-uppercase(char *str);
+char *uppercase(char *str);
 
 // Check whether str ends with suffix
-bool
-endswith(const char *str, const char *suffix);
+bool endswith(const char *str, const char *suffix);
 
 // Get human readable signal string
-int
-get_sig_name(int sig, char *buf, size_t len);
+int get_sig_name(int sig, char *buf, size_t len);
 
 // Get signal code from string like SIGHUP
-int
-get_sig(const char *sig_name);
+int get_sig(const char *sig_name);
 
 // Set the given file descriptor close-on-exec
-bool
-fd_set_cloexec(const int fd);
+bool fd_set_cloexec(const int fd);
 
 // Open uri with the default application of system
-int
-open_uri(char *uri);
+int open_uri(char *uri);
 
 // Encode text to base64, the caller should free the returned string
-char *
-base64_encode(const unsigned char *buffer, size_t length);
+char *base64_encode(const unsigned char *buffer, size_t length);
 
-#endif //TTYD_UTIL_H
+#endif  // TTYD_UTIL_H