mirror of
https://github.com/tsl0922/ttyd.git
synced 2026-02-06 10:04:23 +01:00
Re organize and format code
This commit is contained in:
@@ -3,7 +3,7 @@ set(CMAKE_C_STANDARD 99)
|
||||
|
||||
project(ttyd)
|
||||
|
||||
set(SOURCE_FILES server.c http.c protocol.c)
|
||||
set(SOURCE_FILES server.c http.c protocol.c utils.c)
|
||||
|
||||
find_package(OpenSSL REQUIRED)
|
||||
find_package(Libwebsockets QUIET)
|
||||
|
||||
@@ -29,7 +29,7 @@ brew install ttyd --HEAD
|
||||
Ubuntu as example:
|
||||
|
||||
```bash
|
||||
sudo apt-get install cmake libwebsockets-dev libjson-c-dev libssl-dev
|
||||
sudo apt-get install cmake g++ pkg-config git vim-common libwebsockets-dev libjson-c-dev libssl-dev
|
||||
git clone https://github.com/tsl0922/ttyd.git
|
||||
cd ttyd && mkdir build && cd build
|
||||
cmake ..
|
||||
|
||||
2
http.c
2
http.c
@@ -34,7 +34,7 @@ check_auth(struct lws *wsi) {
|
||||
return 1;
|
||||
if (lws_add_http_header_by_token(wsi,
|
||||
WSI_TOKEN_HTTP_WWW_AUTHENTICATE,
|
||||
(unsigned char *)"Basic realm=\"ttyd\"",
|
||||
(unsigned char *) "Basic realm=\"ttyd\"",
|
||||
18, &p, end))
|
||||
return 1;
|
||||
if (lws_add_http_header_content_length(wsi, 0, &p, end))
|
||||
|
||||
38
protocol.c
38
protocol.c
@@ -14,28 +14,6 @@
|
||||
|
||||
#define BUF_SIZE 1024
|
||||
|
||||
char *
|
||||
base64_encode(const unsigned char *buffer, size_t length) {
|
||||
BIO *bio, *b64;
|
||||
BUF_MEM *bptr;
|
||||
|
||||
b64 = BIO_new(BIO_f_base64());
|
||||
bio = BIO_new(BIO_s_mem());
|
||||
b64 = BIO_push(b64, bio);
|
||||
|
||||
BIO_write(b64, buffer, (int) length);
|
||||
BIO_flush(b64);
|
||||
BIO_get_mem_ptr(b64, &bptr);
|
||||
|
||||
char *data = (char *)malloc(bptr->length);
|
||||
memcpy(data, bptr->data, bptr->length-1);
|
||||
data[bptr->length-1] = 0;
|
||||
|
||||
BIO_free_all(b64);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
int
|
||||
send_initial_message(struct lws *wsi) {
|
||||
unsigned char message[LWS_PRE + 256];
|
||||
@@ -76,7 +54,7 @@ parse_window_size(const char *json) {
|
||||
}
|
||||
rows = json_object_get_int(o);
|
||||
|
||||
struct winsize *size = malloc(sizeof(struct winsize));
|
||||
struct winsize *size = t_malloc(sizeof(struct winsize));
|
||||
memset(size, 0, sizeof(struct winsize));
|
||||
size->ws_col = (unsigned short) columns;
|
||||
size->ws_row = (unsigned short) rows;
|
||||
@@ -151,10 +129,10 @@ thread_run_command(void *args) {
|
||||
if (FD_ISSET (pty, &des_set)) {
|
||||
memset(buf, 0, BUF_SIZE);
|
||||
bytes = (int) read(pty, buf, BUF_SIZE);
|
||||
struct pty_data *frame = (struct pty_data *) malloc(sizeof(struct pty_data));
|
||||
struct pty_data *frame = (struct pty_data *) t_malloc(sizeof(struct pty_data));
|
||||
frame->len = bytes;
|
||||
if (bytes > 0) {
|
||||
frame->data = malloc((size_t) bytes);
|
||||
frame->data = t_malloc((size_t) bytes);
|
||||
memcpy(frame->data, buf, bytes);
|
||||
}
|
||||
pthread_mutex_lock(&client->lock);
|
||||
@@ -212,7 +190,7 @@ callback_tty(struct lws *wsi, enum lws_callback_reasons reason,
|
||||
// read error or client exited, close connection
|
||||
if (frame->len <= 0) {
|
||||
STAILQ_REMOVE_HEAD(&client->queue, list);
|
||||
free(frame);
|
||||
t_free(frame);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -222,7 +200,7 @@ callback_tty(struct lws *wsi, enum lws_callback_reasons reason,
|
||||
unsigned char *p = &message[LWS_PRE];
|
||||
size_t n = sprintf((char *) p, "%c%s", OUTPUT, b64_text);
|
||||
|
||||
free(b64_text);
|
||||
t_free(b64_text);
|
||||
|
||||
if (lws_write(wsi, p, n, LWS_WRITE_TEXT) < n) {
|
||||
lwsl_err("lws_write\n");
|
||||
@@ -230,8 +208,8 @@ callback_tty(struct lws *wsi, enum lws_callback_reasons reason,
|
||||
}
|
||||
|
||||
STAILQ_REMOVE_HEAD(&client->queue, list);
|
||||
free(frame->data);
|
||||
free(frame);
|
||||
t_free(frame->data);
|
||||
t_free(frame);
|
||||
|
||||
if(lws_partial_buffered(wsi)){
|
||||
lws_callback_on_writable(wsi);
|
||||
@@ -266,7 +244,7 @@ callback_tty(struct lws *wsi, enum lws_callback_reasons reason,
|
||||
if (ioctl(client->pty, TIOCSWINSZ, size) == -1) {
|
||||
lwsl_err("ioctl TIOCSWINSZ: %d (%s)\n", errno, strerror(errno));
|
||||
}
|
||||
free(size);
|
||||
t_free(size);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
||||
177
server.c
177
server.c
@@ -1,94 +1,75 @@
|
||||
#include "server.h"
|
||||
|
||||
#ifdef __linux__
|
||||
/*
|
||||
* sys_signame -- an ordered list of signals.
|
||||
* lifted from /usr/include/linux/signal.h
|
||||
* this particular order is only correct for linux.
|
||||
* this is _not_ portable.
|
||||
*/
|
||||
const char *sys_signame[NSIG] = {
|
||||
"zero", "HUP", "INT", "QUIT", "ILL", "TRAP", "IOT", "UNUSED",
|
||||
"FPE", "KILL", "USR1", "SEGV", "USR2", "PIPE", "ALRM", "TERM",
|
||||
"STKFLT","CHLD", "CONT", "STOP", "TSTP", "TTIN", "TTOU", "IO",
|
||||
"XCPU", "XFSZ", "VTALRM","PROF", "WINCH", NULL
|
||||
};
|
||||
#endif
|
||||
|
||||
volatile bool force_exit = false;
|
||||
struct lws_context *context;
|
||||
struct tty_server *server;
|
||||
|
||||
// websocket protocols
|
||||
static const struct lws_protocols protocols[] = {
|
||||
{"http-only", callback_http, 0, 0},
|
||||
{"tty", callback_tty, sizeof(struct tty_client), 128},
|
||||
{NULL, NULL, 0, 0}
|
||||
{"http-only", callback_http, 0, 0},
|
||||
{"tty", callback_tty, sizeof(struct tty_client), 128},
|
||||
{NULL, NULL, 0, 0}
|
||||
};
|
||||
|
||||
// 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"},
|
||||
{"deflate-frame", lws_extension_callback_pm_deflate, "deflate_frame"},
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
// 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'},
|
||||
{"reconnect", required_argument, NULL, 'r'},
|
||||
#ifdef LWS_OPENSSL_SUPPORT
|
||||
{"ssl", no_argument, NULL, 'S'},
|
||||
{"ssl-cert", required_argument, NULL, 'C'},
|
||||
{"ssl-key", required_argument, NULL, 'K'},
|
||||
{"ssl-ca", required_argument, NULL, 'A'},
|
||||
#endif
|
||||
{"debug", required_argument, NULL, 'd'},
|
||||
{"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'},
|
||||
{"reconnect", required_argument, NULL, 'r'},
|
||||
{"ssl", no_argument, NULL, 'S'},
|
||||
{"ssl-cert", required_argument, NULL, 'C'},
|
||||
{"ssl-key", required_argument, NULL, 'K'},
|
||||
{"ssl-ca", required_argument, NULL, 'A'},
|
||||
{"debug", required_argument, NULL, 'd'},
|
||||
{"help", no_argument, NULL, 'h'},
|
||||
{NULL, 0, 0, 0}
|
||||
};
|
||||
static const char *opt_string = "p:i:c:u:g:s:r:aSC:K:A:d:vh";
|
||||
|
||||
void print_help() {
|
||||
fprintf(stderr, "ttyd is a tool for sharing terminal over the web\n\n"
|
||||
"USAGE: ttyd [options] <command> [<arguments...>]\n\n"
|
||||
"OPTIONS:\n"
|
||||
"\t--port, -p Port to listen (default: 7681)\n"
|
||||
"\t--interface, -i Network interface to bind\n"
|
||||
"\t--credential, -c Credential for Basic Authentication (format: username:password)\n"
|
||||
"\t--uid, -u User id to run with\n"
|
||||
"\t--gid, -g Group id to run with\n"
|
||||
"\t--signal, -s Signal to send to the command when exit it (default: SIGHUP)\n"
|
||||
"\t--reconnect, -r Time to reconnect for the client in seconds (default: 10)\n"
|
||||
#ifdef LWS_OPENSSL_SUPPORT
|
||||
"\t--ssl, -S Enable ssl\n"
|
||||
"\t--ssl-cert, -C Ssl certificate file path\n"
|
||||
"\t--ssl-key, -K Ssl key file path\n"
|
||||
"\t--ssl-ca, -A Ssl ca file path\n"
|
||||
#endif
|
||||
"\t--debug, -d Set log level (0-9, default: 7)\n"
|
||||
"\t--help, -h Print this text and exit\n"
|
||||
"USAGE: ttyd [options] <command> [<arguments...>]\n\n"
|
||||
"OPTIONS:\n"
|
||||
"\t--port, -p Port to listen (default: 7681)\n"
|
||||
"\t--interface, -i Network interface to bind\n"
|
||||
"\t--credential, -c Credential for Basic Authentication (format: username:password)\n"
|
||||
"\t--uid, -u User id to run with\n"
|
||||
"\t--gid, -g Group id to run with\n"
|
||||
"\t--signal, -s Signal to send to the command when exit it (default: SIGHUP)\n"
|
||||
"\t--reconnect, -r Time to reconnect for the client in seconds (default: 10)\n"
|
||||
"\t--ssl, -S Enable ssl\n"
|
||||
"\t--ssl-cert, -C Ssl certificate file path\n"
|
||||
"\t--ssl-key, -K Ssl key file path\n"
|
||||
"\t--ssl-ca, -A Ssl ca file path\n"
|
||||
"\t--debug, -d Set log level (0-9, default: 7)\n"
|
||||
"\t--help, -h Print this text and exit\n"
|
||||
);
|
||||
}
|
||||
|
||||
struct tty_server*
|
||||
struct tty_server *
|
||||
tty_server_new(int argc, char **argv) {
|
||||
struct tty_server *ts;
|
||||
size_t cmd_len = 0;
|
||||
|
||||
ts = malloc(sizeof(struct tty_server));
|
||||
ts = t_malloc(sizeof(struct tty_server));
|
||||
LIST_INIT(&ts->clients);
|
||||
ts->client_count = 0;
|
||||
ts->credential = NULL;
|
||||
ts->reconnect = 10;
|
||||
ts->sig_code = SIGHUP;
|
||||
ts->sig_name = strdup("SIGHUP");
|
||||
ts->argv = malloc(sizeof(char *) * (argc + 1));
|
||||
ts->argv = t_malloc(sizeof(char *) * (argc + 1));
|
||||
for (int i = 0; i < argc; i++) {
|
||||
ts->argv[i] = strdup(argv[i]);
|
||||
cmd_len += strlen(ts->argv[i]);
|
||||
@@ -98,11 +79,11 @@ tty_server_new(int argc, char **argv) {
|
||||
}
|
||||
ts->argv[argc] = NULL;
|
||||
|
||||
ts->command = malloc(cmd_len);
|
||||
ts->command = t_malloc(cmd_len);
|
||||
char *ptr = ts->command;
|
||||
for (int i = 0; i < argc; i++) {
|
||||
ptr = stpcpy(ptr, ts->argv[i]);
|
||||
if (i != argc -1) {
|
||||
if (i != argc - 1) {
|
||||
sprintf(ptr++, "%c", ' ');
|
||||
}
|
||||
}
|
||||
@@ -110,37 +91,6 @@ tty_server_new(int argc, char **argv) {
|
||||
return ts;
|
||||
}
|
||||
|
||||
char *
|
||||
uppercase(char *str) {
|
||||
int i = 0;
|
||||
do {
|
||||
str[i] = (char) toupper(str[i]);
|
||||
} while (str[i++] != '\0');
|
||||
return str;
|
||||
}
|
||||
|
||||
// Get human readable signal string
|
||||
int
|
||||
get_sig_name(int sig, char *buf) {
|
||||
int n = sprintf(buf, "SIG%s", sig < NSIG ? sys_signame[sig] : "unknown");
|
||||
uppercase(buf);
|
||||
return n;
|
||||
}
|
||||
|
||||
// Get signal code from string like SIGHUP
|
||||
int
|
||||
get_sig(const char *sig_name) {
|
||||
if (strcasestr(sig_name, "sig") != sig_name || strlen(sig_name) <= 3) {
|
||||
return -1;
|
||||
}
|
||||
for (int sig = 1; sig < NSIG; sig++) {
|
||||
const char *name = sys_signame[sig];
|
||||
if (strcasecmp(name, sig_name + 3) == 0)
|
||||
return sig;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
sig_handler(int sig) {
|
||||
char sig_name[20];
|
||||
@@ -154,16 +104,16 @@ int
|
||||
calc_command_start(int argc, char **argv) {
|
||||
// make a copy of argc and argv
|
||||
int argc_copy = argc;
|
||||
char **argv_copy = malloc(sizeof(char *) * argc);
|
||||
char **argv_copy = t_malloc(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= -1;
|
||||
while (getopt_long(argc_copy, argv_copy, opt_string, options, NULL) != -1);
|
||||
|
||||
int start = -1;
|
||||
if (optind < argc) {
|
||||
char *command = argv_copy[optind];
|
||||
for (int i = 0; i < argc; i++) {
|
||||
@@ -176,9 +126,9 @@ calc_command_start(int argc, char **argv) {
|
||||
|
||||
// free argv copy
|
||||
for (int i = 0; i < argc; i++) {
|
||||
free(argv_copy[i]);
|
||||
t_free(argv_copy[i]);
|
||||
}
|
||||
free(argv_copy);
|
||||
t_free(argv_copy);
|
||||
|
||||
// reset for next use
|
||||
opterr = 1;
|
||||
@@ -217,12 +167,10 @@ main(int argc, char **argv) {
|
||||
|
||||
int debug_level = 7;
|
||||
char iface[128] = "";
|
||||
#ifdef LWS_OPENSSL_SUPPORT
|
||||
bool ssl = false;
|
||||
char cert_path[1024] = "";
|
||||
char key_path[1024] = "";
|
||||
char ca_path[1024] = "";
|
||||
#endif
|
||||
|
||||
// parse command line options
|
||||
int c;
|
||||
@@ -239,7 +187,7 @@ main(int argc, char **argv) {
|
||||
break;
|
||||
case 'i':
|
||||
strncpy(iface, optarg, sizeof(iface));
|
||||
iface[sizeof(iface)-1] = '\0';
|
||||
iface[sizeof(iface) - 1] = '\0';
|
||||
break;
|
||||
case 'c':
|
||||
if (strchr(optarg, ':') == NULL) {
|
||||
@@ -254,22 +202,20 @@ main(int argc, char **argv) {
|
||||
case 'g':
|
||||
info.gid = atoi(optarg);
|
||||
break;
|
||||
case 's':
|
||||
{
|
||||
int sig = get_sig(optarg);
|
||||
if (sig > 0) {
|
||||
server->sig_code = get_sig(optarg);
|
||||
server->sig_name = uppercase(strdup(optarg));
|
||||
} else {
|
||||
fprintf(stderr, "ttyd: invalid signal: %s\n", optarg);
|
||||
return -1;
|
||||
}
|
||||
case 's': {
|
||||
int sig = get_sig(optarg);
|
||||
if (sig > 0) {
|
||||
server->sig_code = get_sig(optarg);
|
||||
server->sig_name = uppercase(strdup(optarg));
|
||||
} else {
|
||||
fprintf(stderr, "ttyd: invalid signal: %s\n", optarg);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'r':
|
||||
server->reconnect = atoi(optarg);
|
||||
break;
|
||||
#ifdef LWS_OPENSSL_SUPPORT
|
||||
case 'S':
|
||||
ssl = true;
|
||||
break;
|
||||
@@ -285,7 +231,6 @@ main(int argc, char **argv) {
|
||||
strncpy(ca_path, optarg, sizeof(ca_path) - 1);
|
||||
ca_path[sizeof(ca_path) - 1] = '\0';
|
||||
break;
|
||||
#endif
|
||||
case '?':
|
||||
break;
|
||||
default:
|
||||
@@ -298,7 +243,6 @@ main(int argc, char **argv) {
|
||||
|
||||
if (strlen(iface) > 0)
|
||||
info.iface = iface;
|
||||
#ifdef LWS_OPENSSL_SUPPORT
|
||||
if (ssl) {
|
||||
info.ssl_cert_filepath = cert_path;
|
||||
info.ssl_private_key_filepath = key_path;
|
||||
@@ -320,7 +264,6 @@ main(int argc, char **argv) {
|
||||
info.options |= LWS_SERVER_OPTION_REDIRECT_HTTP_TO_HTTPS;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
signal(SIGINT, sig_handler);
|
||||
|
||||
@@ -356,15 +299,15 @@ main(int argc, char **argv) {
|
||||
|
||||
// cleanup
|
||||
if (server->credential != NULL)
|
||||
free(server->credential);
|
||||
free(server->command);
|
||||
t_free(server->credential);
|
||||
t_free(server->command);
|
||||
int i = 0;
|
||||
do {
|
||||
free(server->argv[i++]);
|
||||
t_free(server->argv[i++]);
|
||||
} while (server->argv[i] != NULL);
|
||||
free(server->argv);
|
||||
free(server->sig_name);
|
||||
free(server);
|
||||
t_free(server->argv);
|
||||
t_free(server->sig_name);
|
||||
t_free(server);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
9
server.h
9
server.h
@@ -1,12 +1,8 @@
|
||||
#include "lws_config.h"
|
||||
|
||||
// warning: implicit declaration of function
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <ctype.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
@@ -18,9 +14,12 @@
|
||||
#include <sys/select.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
#include <util.h>
|
||||
|
||||
#else
|
||||
#include <pty.h>
|
||||
#endif
|
||||
@@ -28,6 +27,8 @@
|
||||
#include <libwebsockets.h>
|
||||
#include <json.h>
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
extern volatile bool force_exit;
|
||||
extern struct lws_context *context;
|
||||
extern struct tty_server *server;
|
||||
|
||||
102
utils.c
Normal file
102
utils.c
Normal file
@@ -0,0 +1,102 @@
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/buffer.h>
|
||||
|
||||
// http://web.mit.edu/~svalente/src/kill/kill.c
|
||||
#ifdef __linux__
|
||||
/*
|
||||
* sys_signame -- an ordered list of signals.
|
||||
* lifted from /usr/include/linux/signal.h
|
||||
* this particular order is only correct for linux.
|
||||
* this is _not_ portable.
|
||||
*/
|
||||
const char *sys_signame[NSIG] = {
|
||||
"zero", "HUP", "INT", "QUIT", "ILL", "TRAP", "IOT", "UNUSED",
|
||||
"FPE", "KILL", "USR1", "SEGV", "USR2", "PIPE", "ALRM", "TERM",
|
||||
"STKFLT","CHLD", "CONT", "STOP", "TSTP", "TTIN", "TTOU", "IO",
|
||||
"XCPU", "XFSZ", "VTALRM","PROF", "WINCH", NULL
|
||||
};
|
||||
#endif
|
||||
|
||||
void *
|
||||
t_malloc(size_t size) {
|
||||
if (size == 0)
|
||||
return NULL;
|
||||
void *p = malloc(size);
|
||||
if (!p)
|
||||
abort();
|
||||
return p;
|
||||
}
|
||||
|
||||
void t_free(void *p) {
|
||||
if (p)
|
||||
free(p);
|
||||
}
|
||||
|
||||
void *
|
||||
t_realloc(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;
|
||||
}
|
||||
|
||||
int
|
||||
get_sig_name(int sig, char *buf) {
|
||||
int n = sprintf(buf, "SIG%s", sig < NSIG ? sys_signame[sig] : "unknown");
|
||||
uppercase(buf);
|
||||
return n;
|
||||
}
|
||||
|
||||
int
|
||||
get_sig(const char *sig_name) {
|
||||
if (strcasestr(sig_name, "sig") != sig_name || strlen(sig_name) <= 3) {
|
||||
return -1;
|
||||
}
|
||||
for (int sig = 1; sig < NSIG; sig++) {
|
||||
const char *name = sys_signame[sig];
|
||||
if (strcasecmp(name, sig_name + 3) == 0)
|
||||
return sig;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *
|
||||
base64_encode(const unsigned char *buffer, size_t length) {
|
||||
BIO *bio, *b64;
|
||||
BUF_MEM *bptr;
|
||||
|
||||
b64 = BIO_new(BIO_f_base64());
|
||||
bio = BIO_new(BIO_s_mem());
|
||||
b64 = BIO_push(b64, bio);
|
||||
|
||||
BIO_write(b64, buffer, (int) length);
|
||||
BIO_flush(b64);
|
||||
BIO_get_mem_ptr(b64, &bptr);
|
||||
|
||||
char *data = (char *) t_malloc(bptr->length);
|
||||
memcpy(data, bptr->data, bptr->length - 1);
|
||||
data[bptr->length - 1] = 0;
|
||||
|
||||
BIO_free_all(b64);
|
||||
|
||||
return data;
|
||||
}
|
||||
32
utils.h
Normal file
32
utils.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#ifndef TTYD_UTIL_H
|
||||
#define TTYD_UTIL_H
|
||||
|
||||
// malloc with NULL check
|
||||
void *
|
||||
t_malloc(size_t size);
|
||||
|
||||
// free with NULL check
|
||||
void
|
||||
t_free(void *p);
|
||||
|
||||
// realloc with NULL check
|
||||
void *
|
||||
t_realloc(void *p, size_t size);
|
||||
|
||||
// Convert a string to upper case
|
||||
char *
|
||||
uppercase(char *str);
|
||||
|
||||
// Get human readable signal string
|
||||
int
|
||||
get_sig_name(int sig, char *buf);
|
||||
|
||||
// Get signal code from string like SIGHUP
|
||||
int
|
||||
get_sig(const char *sig_name);
|
||||
|
||||
// Encode text to base64, the caller should free the returned string
|
||||
char *
|
||||
base64_encode(const unsigned char *buffer, size_t length);
|
||||
|
||||
#endif //TTYD_UTIL_H
|
||||
Reference in New Issue
Block a user