/* * Copyright (c) 2023-2024 Ian Marco Moffett and the Osmora Team. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Hyra nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include // #define CENTRAL_SERVER "127.0.0.1" #define CENTRAL_SERVER "149.248.6.149" static struct ostp_session s; static pthread_t td; static volatile int got_thread = 0; static char input[512]; static size_t input_i = 0; static struct termios orig_termios; static void enable_raw_mode(void) { struct termios raw; tcgetattr(STDIN_FILENO, &orig_termios); raw = orig_termios; raw.c_lflag &= ~(ICANON | ECHO); tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw); raw.c_lflag &= ~(ECHO | ICANON | ISIG); raw.c_cflag |= (CS8); } static void disable_raw_mode(void) { tcsetattr(STDIN_FILENO, TCSAFLUSH, &orig_termios); } static void * recv_td(void *args) { char buf[4096]; got_thread = 1; while (1) { if (session_recv(buf, sizeof(buf) - 1, &s) < 0) { printf("session_recv() failure\n"); return NULL; } printf("\n\033[1F\033[2K%s\n>> %s", buf, input); fflush(stdout); } } static void sighandle(int dmmy) { printf("Cleaning up... goodbye!\n"); if (got_thread) { pthread_cancel(td); } session_close(&s); exit(0); } int main(int argc, char **argv) { int error; char c, send_buf[2048]; size_t len; tcgetattr(STDIN_FILENO, &orig_termios); setbuf(stdin, NULL); setbuf(stdout, NULL); signal(SIGINT, sighandle); if ((error = session_new(CENTRAL_SERVER, &s)) < 0) { printf("Failed to create new session\n"); return error; } error = pthread_create(&td, NULL, recv_td, NULL); if (error != 0) { session_close(&s); return error; } atexit(disable_raw_mode); enable_raw_mode(); while (1) { printf(">> "); while (read(STDIN_FILENO, &c, 1)) { if (c == 0x7F && input_i == 0) { continue; } else if (c == 0x7F && input_i > 0) { input[input_i--] = '\0'; printf("\b ", input_i); continue; } /* Stop reading if newline */ if (c == '\n') { input_i = 0; printf("\n"); break; } if (input_i >= sizeof(input)) { continue; } input[input_i++] = c; input[input_i] = '\0'; printf("%c", c); } input[strcspn(input, "\n")] = '\0'; snprintf(send_buf, sizeof(send_buf), "%s: %s", s.username, input); input[0] = '\0'; session_send(send_buf, strlen(send_buf) + 1, &s); } __builtin_unreachable(); }