mirror of
https://github.com/eddyem/tty_term.git
synced 2025-12-06 02:25:11 +03:00
add input data types (text/raw/hex), TODO: output types & fix \r bug
This commit is contained in:
parent
934cbc04fd
commit
84bfe8b499
4
main.c
4
main.c
@ -29,7 +29,7 @@ static chardevice conndev = {.dev = NULL, .mutex = PTHREAD_MUTEX_INITIALIZER, .n
|
||||
|
||||
void signals(int signo){
|
||||
signal(signo, SIG_IGN);
|
||||
closedev(&conndev);
|
||||
closedev();
|
||||
deinit_ncurses();
|
||||
deinit_readline();
|
||||
DBG("Exit");
|
||||
@ -84,7 +84,7 @@ int main(int argc, char **argv){
|
||||
while(1){
|
||||
if(0 == pthread_mutex_lock(&conndev.mutex)){
|
||||
int l;
|
||||
char *buf = ReadData(&conndev, &l);
|
||||
char *buf = ReadData(&l);
|
||||
if(buf && l > 0){
|
||||
char *eol = NULL, *estr = buf + l;
|
||||
do{
|
||||
|
||||
@ -26,7 +26,6 @@
|
||||
#include <readline/history.h>
|
||||
#include <readline/readline.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -34,11 +33,14 @@
|
||||
#include "dbg.h"
|
||||
#include "ttysocket.h"
|
||||
#include "ncurses_and_readline.h"
|
||||
#include "popup_msg.h"
|
||||
#include "string_functions.h"
|
||||
|
||||
enum { // using colors
|
||||
BKG_NO = 1,
|
||||
NORMAL_NO = 2,
|
||||
MARKED_NO = 3
|
||||
BKGMARKED_NO = 2,
|
||||
NORMAL_NO = 3,
|
||||
MARKED_NO = 4
|
||||
};
|
||||
#define COLOR(x) COLOR_PAIR(x ## _NO)
|
||||
|
||||
@ -48,6 +50,10 @@ static bool visual_mode = false;
|
||||
static bool insert_mode = true;
|
||||
static bool should_exit = false;
|
||||
|
||||
static disptype disp_type = DISP_TEXT; // type of displaying data
|
||||
static disptype input_type = DISP_TEXT; // parsing type of input data
|
||||
const char *dispnames[] = {"TEXT", "RAW", "HEX"};
|
||||
|
||||
static chardevice *dtty = NULL;
|
||||
|
||||
static void fail_exit(const char *msg){
|
||||
@ -94,26 +100,54 @@ static void forward_to_readline(char c){
|
||||
rl_callback_read_char();
|
||||
}
|
||||
|
||||
// functions to modify output data
|
||||
static char *text_putchar(char *next){
|
||||
char c = *next++;
|
||||
DBG("put 0x%02X (%c)", c, c);
|
||||
if(c < 31 || c > 126){
|
||||
wattron(msg_win, COLOR(MARKED));
|
||||
//waddch(msg_win, c);
|
||||
wprintw(msg_win, "%02X", (uint8_t)c);
|
||||
wattroff(msg_win, COLOR(MARKED));
|
||||
}else{
|
||||
//wprintw(msg_win, "%c" COLOR_GREEN "green" COLOR_RED "red" COLOR_OLD, c);
|
||||
waddch(msg_win, c);
|
||||
}
|
||||
return next;
|
||||
}
|
||||
static char *raw_putchar(char *next){
|
||||
waddch(msg_win, *next);
|
||||
return next+1;
|
||||
}
|
||||
static char *hex_putchar(char *next){
|
||||
waddch(msg_win, *next);
|
||||
return next+1;
|
||||
}
|
||||
|
||||
static void msg_win_redisplay(bool for_resize){
|
||||
werase(msg_win);
|
||||
Line *l = firstline;
|
||||
static char *buf = NULL;
|
||||
//static char *buf = NULL;
|
||||
int nlines = 0; // total amount of lines @ output
|
||||
for(; l && (nlines < LINES - 2); l = l->next){
|
||||
int linemax = LINES - 2;
|
||||
char *(*putfn)(char *);
|
||||
switch(disp_type){
|
||||
case DISP_RAW:
|
||||
putfn = raw_putchar;
|
||||
break;
|
||||
case DISP_HEX:
|
||||
putfn = hex_putchar;
|
||||
break;
|
||||
default:
|
||||
putfn = text_putchar;
|
||||
}
|
||||
for(; l && (nlines < linemax); l = l->next){
|
||||
wmove(msg_win, nlines, 0);
|
||||
size_t contlen = strlen(l->contents) + 128;
|
||||
buf = realloc(buf, contlen);
|
||||
int sz = strlen(l->contents);
|
||||
//size_t contlen = strlen(l->contents) + 128;
|
||||
//buf = realloc(buf, contlen);
|
||||
char *ptr = l->contents;
|
||||
for(int i = 0; i < sz; ++i, ++ptr){
|
||||
char c = *ptr;
|
||||
if(c <'a' || c > 'z'){
|
||||
wattron(msg_win, COLOR(MARKED));
|
||||
waddch(msg_win, c);
|
||||
wattroff(msg_win, COLOR(MARKED));
|
||||
}else{
|
||||
waddch(msg_win, c);
|
||||
}
|
||||
while((ptr = putfn(ptr)) && *ptr && nlines < linemax){
|
||||
nlines = msg_win->_cury;
|
||||
}
|
||||
++nlines;
|
||||
}
|
||||
@ -122,7 +156,7 @@ static void msg_win_redisplay(bool for_resize){
|
||||
}
|
||||
|
||||
static void cmd_win_redisplay(bool for_resize){
|
||||
int cursor_col = 2 + rl_point; // "> " width is 2
|
||||
int cursor_col = 3 + strlen(dispnames[input_type]) + rl_point; // " > " width is 3
|
||||
werase(cmd_win);
|
||||
int x = 0, maxw = COLS-2;
|
||||
if(cursor_col > maxw){
|
||||
@ -130,7 +164,7 @@ static void cmd_win_redisplay(bool for_resize){
|
||||
cursor_col = maxw;
|
||||
}
|
||||
char abuf[4096];
|
||||
snprintf(abuf, 4096, "> %s", rl_line_buffer);
|
||||
snprintf(abuf, 4096, "%s > %s", dispnames[input_type], rl_line_buffer);
|
||||
waddstr(cmd_win, abuf+x);
|
||||
wmove(cmd_win, 0, cursor_col);
|
||||
if(for_resize) wnoutrefresh(cmd_win);
|
||||
@ -145,26 +179,27 @@ static void readline_redisplay(){
|
||||
}
|
||||
|
||||
static void show_mode(bool for_resize){
|
||||
static const char *insmodetext = "INSERT (F1 - help)";
|
||||
wclear(sep_win);
|
||||
char buf[128];
|
||||
if(insert_mode){
|
||||
if(dtty){
|
||||
switch(dtty->type){
|
||||
case DEV_NETSOCKET:
|
||||
snprintf(buf, 127, "INSERT (TAB to switch, ctrl+D to quit) HOST: %s, ENDLINE: %s, PORT: %s",
|
||||
dtty->name, dtty->seol, dtty->port);
|
||||
snprintf(buf, 127, "%s HOST: %s, ENDLINE: %s, PORT: %s",
|
||||
insmodetext, dtty->name, dtty->seol, dtty->port);
|
||||
break;
|
||||
case DEV_UNIXSOCKET:
|
||||
if(*dtty->name)
|
||||
snprintf(buf, 127, "INSERT (TAB to switch, ctrl+D to quit) PATH: %s, ENDLINE: %s",
|
||||
dtty->name, dtty->seol);
|
||||
snprintf(buf, 127, "%s PATH: %s, ENDLINE: %s",
|
||||
insmodetext, dtty->name, dtty->seol);
|
||||
else // name starting from \0
|
||||
snprintf(buf, 127, "INSERT (TAB to switch, ctrl+D to quit) PATH: \\0%s, ENDLINE: %s",
|
||||
dtty->name+1, dtty->seol);
|
||||
snprintf(buf, 127, "%s PATH: \\0%s, ENDLINE: %s",
|
||||
insmodetext, dtty->name+1, dtty->seol);
|
||||
break;
|
||||
case DEV_TTY:
|
||||
snprintf(buf, 127, "INSERT (TAB to switch, ctrl+D to quit) DEV: %s, ENDLINE: %s, SPEED: %d, FORMAT: %s",
|
||||
dtty->name, dtty->seol, dtty->speed, dtty->port);
|
||||
snprintf(buf, 127, "%s DEV: %s, ENDLINE: %s, SPEED: %d, FORMAT: %s",
|
||||
insmodetext, dtty->name, dtty->seol, dtty->speed, dtty->port);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -172,8 +207,11 @@ static void show_mode(bool for_resize){
|
||||
snprintf(buf, 127, "INSERT (TAB to switch, ctrl+D to quit) NOT INITIALIZED");
|
||||
}
|
||||
}else{
|
||||
snprintf(buf, 127, "SCROLL (TAB to switch, q to quit) ENDLINE: %s", dtty?dtty->seol:"n");
|
||||
snprintf(buf, 127, "SCROLL (F1 - help) ENDLINE: %s", dtty?dtty->seol:"n");
|
||||
}
|
||||
wattron(sep_win, COLOR(BKGMARKED));
|
||||
wprintw(sep_win, "%s ", dispnames[disp_type]);
|
||||
wattroff(sep_win, COLOR(BKGMARKED));
|
||||
wprintw(sep_win, "%s", buf);
|
||||
if(for_resize) wnoutrefresh(sep_win);
|
||||
else wrefresh(sep_win);
|
||||
@ -253,6 +291,7 @@ void init_ncurses(){
|
||||
fail_exit("Failed to allocate windows");
|
||||
if(has_colors()){
|
||||
init_pair(BKG_NO, COLOR_WHITE, COLOR_BLUE);
|
||||
init_pair(BKGMARKED_NO, 1, COLOR_BLUE); // COLOR_RED used in my usefull_macros
|
||||
init_pair(NORMAL_NO, COLOR_WHITE, COLOR_BLACK);
|
||||
init_pair(MARKED_NO, COLOR_CYAN, COLOR_BLACK);
|
||||
wbkgd(sep_win, COLOR(BKG));
|
||||
@ -271,16 +310,18 @@ void deinit_ncurses(){
|
||||
endwin();
|
||||
}
|
||||
|
||||
static char *previous_line = NULL; // previous line in readline input
|
||||
static void got_command(char *line){
|
||||
if(!line) // Ctrl-D pressed on empty line
|
||||
should_exit = true;
|
||||
else{
|
||||
if(!*line) return; // zero length
|
||||
add_history(line);
|
||||
if(SendData(dtty, line) == -1){
|
||||
if(!previous_line || strcmp(previous_line, line)) add_history(line); // omit repeats
|
||||
FREE(previous_line);
|
||||
if(convert_and_send(input_type, line) == -1){
|
||||
ERRX("Device disconnected");
|
||||
}
|
||||
FREE(line);
|
||||
previous_line = line;
|
||||
}
|
||||
}
|
||||
|
||||
@ -293,7 +334,22 @@ void init_readline(){
|
||||
rl_getc_function = readline_getc;
|
||||
rl_input_available_hook = readline_input_avail;
|
||||
rl_redisplay_function = readline_redisplay;
|
||||
rl_callback_handler_install("> ", got_command);
|
||||
rl_callback_handler_install("", got_command);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief change_disp - change input or output data types (text/raw/hex)
|
||||
* @param in, out - types for input and display
|
||||
*/
|
||||
static void change_disp(disptype in, disptype out){
|
||||
if(in >= DISP_TEXT && in < DISP_UNCHANGED){
|
||||
input_type = in;
|
||||
DBG("input -> %s", dispnames[in]);
|
||||
}
|
||||
if(out >= DISP_TEXT && out < DISP_UNCHANGED){
|
||||
disp_type = out;
|
||||
}
|
||||
show_mode(false);
|
||||
}
|
||||
|
||||
void deinit_readline(){
|
||||
@ -318,6 +374,33 @@ static void rollup(){
|
||||
}
|
||||
}
|
||||
|
||||
static const char *help[] = {
|
||||
"Common commands:",
|
||||
" F1 - show this help",
|
||||
" F2 - text mode",
|
||||
" F3 - raw mode (all symbols in hex codes)",
|
||||
" F4 - hexdump mode (like hexdump output)",
|
||||
" mouse scroll - scroll text output",
|
||||
" q,^c,^d - quit",
|
||||
" TAB - switch between scroll and edit modes",
|
||||
" to change display/input (text/raw/hex) press Fx when scroll/edit",
|
||||
" in scroll mode keys are almost the same like for this help"
|
||||
" Text mode: in input and output all special symbols are like \\code",
|
||||
" Raw mode: output only in hex, input in dec, 0xhex, 0bbin, 0oct (space separated)",
|
||||
" Hexdump mode: output like hexdump, input only hex (with or without spaces)",
|
||||
"",
|
||||
"This help:",
|
||||
" ^p,<Up> - scroll the viewport up by one row",
|
||||
" ^n,<Down> - scroll the viewport down by one row",
|
||||
" ^l,<Left> - scroll the viewport left by one column",
|
||||
" ^r,<Right> - scroll the viewport right by one column",
|
||||
" h,<Home> - scroll the viewport to top of file",
|
||||
" ^F,<PageDn> - scroll to the next page",
|
||||
" ^B,<PageUp> - scroll to the previous page",
|
||||
" e,<End> - scroll the viewport to end of file",
|
||||
0
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief cmdline - console reading process; runs as separate thread
|
||||
* @param arg - tty/socket device to write strings entered by user
|
||||
@ -331,7 +414,24 @@ void *cmdline(void* arg){
|
||||
int c = wgetch(cmd_win);
|
||||
bool processed = true;
|
||||
//DBG("wgetch got %d", c);
|
||||
disptype dt = DISP_UNCHANGED;
|
||||
switch(c){ // common keys for both modes
|
||||
case KEY_F(1): // help
|
||||
DBG("\n\nASK for help\n\n");
|
||||
popup_msg(msg_win, help);
|
||||
break;
|
||||
case KEY_F(2): // TEXT mode
|
||||
DBG("\n\nIN TEXT mode\n\n");
|
||||
dt = DISP_TEXT;
|
||||
break;
|
||||
case KEY_F(3): // RAW mode
|
||||
DBG("\n\nIN RAW mode\n\n");
|
||||
dt = DISP_RAW;
|
||||
break;
|
||||
case KEY_F(4): // HEX mode
|
||||
DBG("\n\nIN HEX mode\n\n");
|
||||
dt = DISP_HEX;
|
||||
break;
|
||||
case KEY_MOUSE:
|
||||
if(getmouse(&event) == OK){
|
||||
if(event.bstate & (BUTTON4_PRESSED)) rolldown(); // wheel up
|
||||
@ -348,6 +448,10 @@ void *cmdline(void* arg){
|
||||
default:
|
||||
processed = false;
|
||||
}
|
||||
if(dt != DISP_UNCHANGED){
|
||||
if(insert_mode) change_disp(dt, DISP_UNCHANGED);
|
||||
else change_disp(DISP_UNCHANGED, dt);
|
||||
}
|
||||
if(processed) continue;
|
||||
if(insert_mode){
|
||||
DBG("forward_to_readline(%d)", c);
|
||||
@ -396,7 +500,7 @@ void *cmdline(void* arg){
|
||||
while(*ptr) forward_to_readline(*ptr++);
|
||||
}
|
||||
}else{
|
||||
switch(c){
|
||||
switch(c){ // TODO: add home/end
|
||||
case KEY_UP: // roll down for one item
|
||||
rolldown();
|
||||
break;
|
||||
|
||||
@ -22,6 +22,13 @@
|
||||
#include "dbg.h"
|
||||
#include "ttysocket.h"
|
||||
|
||||
typedef enum{ // display/input data as
|
||||
DISP_TEXT, // text (non-ASCII input and output as \xxx)
|
||||
DISP_RAW, // hex output as xx xx xx, input in as numbers in bin (0bxx), oct(0xx), hex (0xxx||0Xxx) or dec and letters
|
||||
DISP_HEX, // hexdump output, input in hex only (with or without spaces)
|
||||
DISP_UNCHANGED // old
|
||||
} disptype;
|
||||
|
||||
void init_readline();
|
||||
void deinit_readline();
|
||||
void init_ncurses();
|
||||
|
||||
187
popup_msg.c
Normal file
187
popup_msg.c
Normal file
@ -0,0 +1,187 @@
|
||||
/*
|
||||
* This file is part of the ttyterm project.
|
||||
* Copyright 2023 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
* Copyright 2018-2020,2021 Thomas E. Dickey *
|
||||
* Copyright 2017 Free Software Foundation, Inc. *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a *
|
||||
* copy of this software and associated documentation files (the *
|
||||
* "Software"), to deal in the Software without restriction, including *
|
||||
* without limitation the rights to use, copy, modify, merge, publish, *
|
||||
* distribute, distribute with modifications, sublicense, and/or sell *
|
||||
* copies of the Software, and to permit persons to whom the Software is *
|
||||
* furnished to do so, subject to the following conditions: *
|
||||
* *
|
||||
* The above copyright notice and this permission notice shall be included *
|
||||
* in all copies or substantial portions of the Software. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
|
||||
* IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
|
||||
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
|
||||
* THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
* *
|
||||
* Except as contained in this notice, the name(s) of the above copyright *
|
||||
* holders shall not be used in advertising or otherwise to promote the *
|
||||
* sale, use or other dealings in this Software without prior written *
|
||||
* authorization. *
|
||||
****************************************************************************/
|
||||
/*
|
||||
* $Id: popup_msg.c,v 1.11 2021/12/18 21:19:19 tom Exp $
|
||||
*
|
||||
* Show a multi-line message in a window which may extend beyond the screen.
|
||||
*
|
||||
* Thomas Dickey - 2017/4/15.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "dbg.h"
|
||||
#include "popup_msg.h"
|
||||
|
||||
static WINDOW *old_window;
|
||||
|
||||
static void begin_popup(void){
|
||||
doupdate();
|
||||
old_window = dupwin(curscr);
|
||||
}
|
||||
|
||||
static void end_popup(void){
|
||||
touchwin(old_window);
|
||||
wnoutrefresh(old_window);
|
||||
doupdate();
|
||||
delwin(old_window);
|
||||
}
|
||||
|
||||
/*
|
||||
* Display a temporary window, e.g., to display a help-message.
|
||||
*/
|
||||
void popup_msg(WINDOW *parent, const char *const *msg){
|
||||
int x0 = 4;
|
||||
int y0 = 2;
|
||||
int y1 = 0, x1 = 0;
|
||||
int y2 = 0;
|
||||
int wide = getmaxx(parent) - ((x0 + 1) * 2);
|
||||
int high = getmaxy(parent) - ((y0 + 1) * 2);
|
||||
WINDOW *help;
|
||||
WINDOW *data;
|
||||
int n;
|
||||
int width = 0;
|
||||
int length;
|
||||
int last_y, last_x;
|
||||
int ch = ERR;
|
||||
|
||||
for (n = 0; msg[n] != 0; ++n) {
|
||||
int check = (int) strlen(msg[n]);
|
||||
if (width < check) width = check;
|
||||
}
|
||||
length = n;
|
||||
last_x = width - wide + 4;
|
||||
|
||||
if ((help = newwin(high, wide, y0, x0)) == 0)
|
||||
return;
|
||||
if ((data = newpad(length + 1, width + 1)) == 0) {
|
||||
delwin(help);
|
||||
return;
|
||||
}
|
||||
|
||||
begin_popup();
|
||||
|
||||
keypad(data, TRUE);
|
||||
|
||||
for (n = 0; n < length; ++n){
|
||||
waddstr(data, msg[n]);
|
||||
if ((n + 1) < length) waddch(data, '\n');
|
||||
}
|
||||
y2 = getcury(data);
|
||||
last_y = (y2 - (high - 3));
|
||||
|
||||
do{
|
||||
switch (ch){
|
||||
case KEY_HOME:
|
||||
y1 = 0;
|
||||
break;
|
||||
case KEY_END:
|
||||
y1 = last_y;
|
||||
break;
|
||||
case KEY_PREVIOUS:
|
||||
case KEY_PPAGE:
|
||||
if (y1 > 0) {
|
||||
y1 -= high / 2;
|
||||
if (y1 < 0)
|
||||
y1 = 0;
|
||||
} else {
|
||||
beep();
|
||||
}
|
||||
break;
|
||||
case KEY_NEXT:
|
||||
case KEY_NPAGE:
|
||||
if (y1 < last_y) {
|
||||
y1 += high / 2;
|
||||
if (y1 > last_y)
|
||||
y1 = last_y;
|
||||
} else {
|
||||
beep();
|
||||
}
|
||||
break;
|
||||
case CTRL('P'):
|
||||
case KEY_UP:
|
||||
if (y1 > 0)
|
||||
--y1;
|
||||
else
|
||||
beep();
|
||||
break;
|
||||
case CTRL('N'):
|
||||
case KEY_DOWN:
|
||||
if (y1 < last_y)
|
||||
++y1;
|
||||
else
|
||||
beep();
|
||||
break;
|
||||
case CTRL('L'):
|
||||
case KEY_LEFT:
|
||||
if(x1 > 0) --x1;
|
||||
else beep();
|
||||
break;
|
||||
case CTRL('R'):
|
||||
case KEY_RIGHT:
|
||||
if(x1 < last_x) ++x1;
|
||||
else beep();
|
||||
break;
|
||||
default:
|
||||
beep();
|
||||
break;
|
||||
case ERR:
|
||||
break;
|
||||
}
|
||||
werase(help);
|
||||
box(help, 0, 0);
|
||||
wnoutrefresh(help);
|
||||
pnoutrefresh(data, y1, x1, y0 + 1, x0 + 1, high, wide);
|
||||
doupdate();
|
||||
} while ((ch = wgetch(data)) != ERR && ch != QUIT && ch != ESCAPE);
|
||||
werase(help);
|
||||
wrefresh(help);
|
||||
delwin(help);
|
||||
delwin(data);
|
||||
|
||||
end_popup();
|
||||
}
|
||||
25
popup_msg.h
Normal file
25
popup_msg.h
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* This file is part of the ttyterm project.
|
||||
* Copyright 2023 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <curses.h>
|
||||
|
||||
#define QUIT CTRL('Q')
|
||||
#define ESCAPE CTRL('[')
|
||||
|
||||
void popup_msg(WINDOW *parent, const char *const *msg);
|
||||
220
string_functions.c
Normal file
220
string_functions.c
Normal file
@ -0,0 +1,220 @@
|
||||
/*
|
||||
* This file is part of the ttyterm project.
|
||||
* Copyright 2023 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "string_functions.h"
|
||||
|
||||
// read text string and throw out all < 31 and > 126
|
||||
static inline const char *omit_nonletters(const char *line){
|
||||
while(*line){
|
||||
char c = *line;
|
||||
if(c > 31 && c < 127) break;
|
||||
++line;
|
||||
}
|
||||
return line;
|
||||
}
|
||||
|
||||
// return hex of given sybol (0..9, a..f or A..F) or -1
|
||||
static inline int hex2i(char c){
|
||||
if(c >= '0' && c <= '9') return c - '0';
|
||||
else if(c >= 'A' && c <= 'F') return c - 'A' + 10;
|
||||
else if(c >= 'a' && c <= 'f') return c - 'a' + 10;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline const char *getbin(const char *line, int *ch){
|
||||
char c = *line;
|
||||
if(c < '0' || c > '1'){
|
||||
*ch = -1;
|
||||
return line+1;
|
||||
}
|
||||
int num = 0, ctr = 8;
|
||||
do{
|
||||
if(--ctr < 0) break; // nineth symbol
|
||||
if(c < '0' || c > '1'){
|
||||
break;
|
||||
}
|
||||
num <<= 1;
|
||||
if(c == '1') num |= 1;
|
||||
++line;
|
||||
}while((c = *line));
|
||||
*ch = num < 256 ? num : -1;
|
||||
return line;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief getoct read octal number without first '0' (up to three symbols)
|
||||
* @param line - pointer to string
|
||||
* @param ch - data read (or -1 if error)
|
||||
* @return pointer to next symbol after this (or first incorrect symbol)
|
||||
*/
|
||||
static inline const char *getoct(const char *line, int *ch){
|
||||
char c = *line;
|
||||
if(c < '0' || c > '7'){
|
||||
*ch = -1;
|
||||
return line+1;
|
||||
}
|
||||
int num = 0, ctr = 3;
|
||||
do{
|
||||
if(--ctr < 0) break; // fourth symbol
|
||||
if(c < '0' || c > '7'){ // other symbol
|
||||
break;
|
||||
}
|
||||
num <<= 3;
|
||||
num += c - '0';
|
||||
++line;
|
||||
}while((c = *line));
|
||||
*ch = num < 256 ? num : -1;
|
||||
return line;
|
||||
|
||||
}
|
||||
|
||||
static inline const char *getdec(const char *line, int *ch){
|
||||
char c = *line;
|
||||
if(c < '0' || c > '9'){
|
||||
*ch = -1;
|
||||
return line+1;
|
||||
}
|
||||
int num = 0, ctr = 3;
|
||||
do{
|
||||
if(--ctr < 0) break; // fourth symbol
|
||||
if(c < '0' || c > '9'){ // other symbol
|
||||
break;
|
||||
}
|
||||
num *= 10;
|
||||
num += c - '0';
|
||||
++line;
|
||||
}while((c = *line));
|
||||
*ch = num < 256 ? num : -1;
|
||||
return line;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief gethex - read hex number without first '\x'
|
||||
* @param line - pointer to string
|
||||
* @param ch - data read (or -1 if error)
|
||||
* @return pointer to next symbol after hex number (x or xx)
|
||||
*/
|
||||
static inline const char *gethex(const char *line, int *ch){
|
||||
int i = hex2i(*line++);
|
||||
if(i > -1){
|
||||
int j = hex2i(*line);
|
||||
if(j > -1){
|
||||
i = (i<<4) | j;
|
||||
++line;
|
||||
}
|
||||
}
|
||||
*ch = i;
|
||||
return line;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief getspec - get special symbol (after '\') (without unicode support!)
|
||||
* @param line - pointer to string
|
||||
* @param ch - data read (or -1 if error)
|
||||
* @return pointer to next symbol after this
|
||||
*/
|
||||
static inline const char *getspec(const char *line, int *ch){
|
||||
if(!*line){ *ch = -1; return line; }
|
||||
int got = -1, s = *line++; // next symbol after '\'
|
||||
if(s >= '0' && s <= '7'){ // octal symbol
|
||||
line = getoct(line-1, &got);
|
||||
}else switch(s){
|
||||
case 'a': got = '\a'; break;
|
||||
case 'b': got = '\b'; break;
|
||||
case 'e': got = '\e'; break;
|
||||
case 'f': got = '\f'; break;
|
||||
case 'n': got = '\n'; break;
|
||||
case 'r': got = '\r'; break;
|
||||
case 't': got = '\t'; break;
|
||||
case 'v': got = '\v'; break;
|
||||
case 'x': line = gethex(line, &got); break; // hex symbol
|
||||
default:// return "as is" all other printable symbols
|
||||
if(s > 31 && s < 127) got = s;
|
||||
break;
|
||||
}
|
||||
*ch = got;
|
||||
return line;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief convert_and_send - convert input line and send it (in text mode add `eol`)
|
||||
* @param line - line with data
|
||||
* @return amount of bytes sent, 0 if error or -1 if disconnect
|
||||
*/
|
||||
int convert_and_send(disptype input_type, const char *line){
|
||||
static char *buf = NULL;
|
||||
static size_t bufsiz = 0;
|
||||
size_t curpos = 0; // position in `buf`
|
||||
line = omit_nonletters(line);
|
||||
while(*line){
|
||||
if(curpos >= bufsiz){ // out ouptut buffer can't be larger than input
|
||||
bufsiz += BUFSIZ;
|
||||
buf = realloc(buf, bufsiz);
|
||||
}
|
||||
int ch = -1;
|
||||
switch(input_type){
|
||||
case DISP_TEXT: // only check for '\'
|
||||
ch = *line++;
|
||||
if(ch == '\\') line = getspec(line, &ch);
|
||||
break;
|
||||
case DISP_RAW: // read next uint8_t and put into buffer
|
||||
ch = *line++;
|
||||
if(ch == '0'){ // number: 0, 0xHH, 0OOO, 0bBBBBBBBB
|
||||
ch = *line;
|
||||
switch(ch){
|
||||
case 'x': // hexadecimal
|
||||
case 'X':
|
||||
line = gethex(line + 1, &ch);
|
||||
break;
|
||||
case 'b':
|
||||
case 'B':
|
||||
line = getbin(line + 1, &ch);
|
||||
break;
|
||||
default: // zero or octal
|
||||
if(ch >= '0' && ch <= '7') line = getoct(line, &ch);
|
||||
else ch = 0;
|
||||
break;
|
||||
}
|
||||
}else if(ch > '0' && ch <= '9'){ // decimal number
|
||||
line = getdec(line-1, &ch);
|
||||
} // else - letter (without escape-symbols!)
|
||||
break;
|
||||
case DISP_HEX: // read next 2 hex bytes and put into buffer
|
||||
line = gethex(line, &ch);
|
||||
break;
|
||||
default:
|
||||
return 0; // unknown display type
|
||||
}
|
||||
if(ch > -1) buf[curpos++] = ch;
|
||||
line = omit_nonletters(line);
|
||||
}
|
||||
// now insert EOL in text mode
|
||||
if(input_type == DISP_TEXT){
|
||||
if(curpos+2 >= bufsiz){
|
||||
bufsiz += BUFSIZ;
|
||||
buf = realloc(buf, bufsiz);
|
||||
}
|
||||
int l; char *e = geteol(&l);
|
||||
snprintf(buf+curpos, l, "%s", e);
|
||||
curpos += l;
|
||||
}
|
||||
return SendData(buf, curpos);
|
||||
}
|
||||
23
string_functions.h
Normal file
23
string_functions.h
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* This file is part of the ttyterm project.
|
||||
* Copyright 2023 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ncurses_and_readline.h"
|
||||
|
||||
int convert_and_send(disptype input_type, const char *line);
|
||||
179
ttysocket.c
179
ttysocket.c
@ -33,6 +33,8 @@
|
||||
|
||||
static int sec = 0, usec = 100; // timeout
|
||||
static FILE *dupfile = NULL; // file for output
|
||||
static chardevice *device = NULL; // current opened device
|
||||
|
||||
// TODO: if unix socket name starts with \0 translate it as \\0 to d->name!
|
||||
|
||||
// set Read_tty timeout in milliseconds
|
||||
@ -76,31 +78,31 @@ static int waittoread(int fd){
|
||||
}
|
||||
|
||||
// substitute all EOL's by '\n'
|
||||
static size_t rmeols(chardevice *d){
|
||||
if(!d){
|
||||
static size_t rmeols(){
|
||||
if(!device){
|
||||
DBG("d is NULL");
|
||||
return 0;
|
||||
}
|
||||
TTY_descr2 *D = d->dev;
|
||||
TTY_descr2 *D = device->dev;
|
||||
if(!D || D->comfd < 0){
|
||||
DBG("D bad");
|
||||
return 0;
|
||||
}
|
||||
if(0 == strcmp(d->eol, "\n")){
|
||||
if(0 == strcmp(device->eol, "\n")){
|
||||
DBG("No subs need");
|
||||
return D->buflen; // don't need to do this
|
||||
}
|
||||
int L = strlen(D->buf);
|
||||
char *newbuf = MALLOC(char, L), *ptr = D->buf, *eptr = D->buf + L;
|
||||
while(ptr < eptr){
|
||||
char *eol = strstr(ptr, d->eol);
|
||||
char *eol = strstr(ptr, device->eol);
|
||||
if(eol){
|
||||
eol[0] = '\n';
|
||||
eol[1] = 0;
|
||||
}
|
||||
strcat(newbuf, ptr);
|
||||
if(!eol) break;
|
||||
ptr = eol + d->eollen;
|
||||
ptr = eol + device->eollen;
|
||||
}
|
||||
strcpy(D->buf, newbuf);
|
||||
FREE(newbuf);
|
||||
@ -108,10 +110,16 @@ static size_t rmeols(chardevice *d){
|
||||
return D->buflen;
|
||||
}
|
||||
|
||||
char *geteol(int *s){
|
||||
if(!device) return NULL;
|
||||
*s = device->eollen;
|
||||
return device->eol;
|
||||
}
|
||||
|
||||
// get data drom TTY
|
||||
static char *getttydata(chardevice *d, int *len){
|
||||
if(!d || !d->dev) return NULL;
|
||||
TTY_descr2 *D = d->dev;
|
||||
static char *getttydata(int *len){
|
||||
if(!device || !device->dev) return NULL;
|
||||
TTY_descr2 *D = device->dev;
|
||||
if(D->comfd < 0) return NULL;
|
||||
int L = 0;
|
||||
int length = D->bufsz;
|
||||
@ -130,7 +138,7 @@ static char *getttydata(chardevice *d, int *len){
|
||||
}
|
||||
ptr += l; L += l;
|
||||
length -= l;
|
||||
if(L >= d->eollen && 0 == strcmp(&ptr[-(d->eollen)], d->eol)){ // found end of line
|
||||
if(L >= device->eollen && 0 == strcmp(&ptr[-(device->eollen)], device->eol)){ // found end of line
|
||||
break;
|
||||
}
|
||||
}while(length);
|
||||
@ -138,14 +146,14 @@ static char *getttydata(chardevice *d, int *len){
|
||||
D->buf[L] = 0;
|
||||
if(len) *len = L;
|
||||
if(!L) return NULL;
|
||||
rmeols(d);
|
||||
rmeols(device);
|
||||
DBG("buffer len: %zd, content: =%s=", D->buflen, D->buf);
|
||||
return D->buf;
|
||||
}
|
||||
|
||||
static char *getsockdata(chardevice *d, int *len){
|
||||
if(!d || !d->dev) return NULL;
|
||||
TTY_descr2 *D = d->dev;
|
||||
static char *getsockdata(int *len){
|
||||
if(!device || !device->dev) return NULL;
|
||||
TTY_descr2 *D = device->dev;
|
||||
if(D->comfd < 0) return NULL;
|
||||
char *ptr = NULL;
|
||||
int n = waittoread(D->comfd);
|
||||
@ -155,7 +163,7 @@ static char *getsockdata(chardevice *d, int *len){
|
||||
ptr = D->buf;
|
||||
ptr[n] = 0;
|
||||
D->buflen = n;
|
||||
n = rmeols(d);
|
||||
n = rmeols(device);
|
||||
DBG("got %d: ..%s..", n, ptr);
|
||||
}else{
|
||||
DBG("Got nothing");
|
||||
@ -172,23 +180,24 @@ static char *getsockdata(chardevice *d, int *len){
|
||||
* @param len (o) - length of data read (-1 if device disconnected)
|
||||
* @return NULL or string
|
||||
*/
|
||||
char *ReadData(chardevice *d, int *len){
|
||||
if(!d || !d->dev) return NULL;
|
||||
char *ReadData(int *len){
|
||||
if(!device || !device->dev) return NULL;
|
||||
if(len) *len = -1;
|
||||
char *r = NULL;
|
||||
switch(d->type){
|
||||
switch(device->type){
|
||||
case DEV_TTY:
|
||||
r = getttydata(d, len);
|
||||
r = getttydata(len);
|
||||
break;
|
||||
case DEV_NETSOCKET:
|
||||
case DEV_UNIXSOCKET:
|
||||
r = getsockdata(d, len);
|
||||
r = getsockdata(len);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if(r && dupfile){
|
||||
fprintf(dupfile, "< %s", r);
|
||||
fwrite("< ", 1, 2, dupfile);
|
||||
fwrite(r, 1, *len, dupfile);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
@ -196,40 +205,33 @@ char *ReadData(chardevice *d, int *len){
|
||||
/**
|
||||
* @brief SendData - send data to tty or socket
|
||||
* @param d - device
|
||||
* @param str - text string
|
||||
* @return 0 if error, -1 if disconnected
|
||||
* @param data - buffer with data
|
||||
* @return 0 if error or empty string, -1 if disconnected
|
||||
*/
|
||||
int SendData(chardevice *d, char *str){
|
||||
char buf[BUFSIZ];
|
||||
if(!d) return -1;
|
||||
DBG("send %s", str);
|
||||
if(!str) return 0;
|
||||
int SendData(const char *data, size_t len){
|
||||
if(!device) return -1;
|
||||
if(!data || len == 0) return 0;
|
||||
int ret = 0;
|
||||
if(0 == pthread_mutex_lock(&d->mutex)){
|
||||
int l = strlen(str), lplus = l + d->eollen;
|
||||
if(l < 1) return 0;
|
||||
if(lplus > BUFSIZ-1) lplus = BUFSIZ-1;
|
||||
snprintf(buf, lplus+1, "%s%s", str, d->eol);
|
||||
DBG("SENDBUF (%d): _%s_", lplus, buf);
|
||||
switch(d->type){
|
||||
if(0 == pthread_mutex_lock(&device->mutex)){
|
||||
switch(device->type){
|
||||
case DEV_TTY:
|
||||
if(write_tty(d->dev->comfd, buf, lplus)) ret = 0;
|
||||
else ret = l;
|
||||
if(write_tty(device->dev->comfd, data, len)) ret = 0;
|
||||
else ret = len;
|
||||
break;
|
||||
case DEV_NETSOCKET:
|
||||
case DEV_UNIXSOCKET:
|
||||
if(lplus != send(d->dev->comfd, buf, lplus, MSG_NOSIGNAL)) ret = 0;
|
||||
else ret = l;
|
||||
pthread_mutex_unlock(&d->mutex);
|
||||
if(len != (size_t)send(device->dev->comfd, data, len, MSG_NOSIGNAL)) ret = 0;
|
||||
else ret = len;
|
||||
break;
|
||||
default:
|
||||
str = NULL;
|
||||
data = NULL;
|
||||
break;
|
||||
}
|
||||
if(str && dupfile){
|
||||
fprintf(dupfile, "> %s", buf);
|
||||
if(data && dupfile){
|
||||
fwrite("> ", 1, 2, dupfile);
|
||||
fwrite(data, 1, len, dupfile);
|
||||
}
|
||||
pthread_mutex_unlock(&d->mutex);
|
||||
pthread_mutex_unlock(&device->mutex);
|
||||
}else ret = -1;
|
||||
DBG("ret=%d", ret);
|
||||
return ret;
|
||||
@ -237,8 +239,8 @@ int SendData(chardevice *d, char *str){
|
||||
|
||||
static const int socktypes[] = {SOCK_STREAM, SOCK_RAW, SOCK_RDM, SOCK_SEQPACKET, SOCK_DCCP, SOCK_PACKET, SOCK_DGRAM, 0};
|
||||
|
||||
static TTY_descr2* opensocket(chardevice *d){
|
||||
if(!d) return FALSE;
|
||||
static TTY_descr2* opensocket(){
|
||||
if(!device) return FALSE;
|
||||
TTY_descr2 *descr = MALLOC(TTY_descr2, 1); // only for `buf` and bufsz/buflen
|
||||
descr->buf = MALLOC(char, BUFSIZ);
|
||||
descr->bufsz = BUFSIZ;
|
||||
@ -250,11 +252,11 @@ static TTY_descr2* opensocket(chardevice *d){
|
||||
struct sockaddr *sa = NULL;
|
||||
socklen_t addrlen = 0;
|
||||
int domain = -1;
|
||||
if(d->type == DEV_NETSOCKET){
|
||||
DBG("NETSOCK to %s", d->name);
|
||||
if(device->type == DEV_NETSOCKET){
|
||||
DBG("NETSOCK to %s", device->name);
|
||||
sa = (struct sockaddr*) &addr;
|
||||
addrlen = sizeof(addr);
|
||||
if((host = gethostbyname(d->name)) == NULL ){
|
||||
if((host = gethostbyname(device->name)) == NULL ){
|
||||
WARN("gethostbyname()");
|
||||
FREE(descr->buf);
|
||||
FREE(descr);
|
||||
@ -263,7 +265,7 @@ static TTY_descr2* opensocket(chardevice *d){
|
||||
struct in_addr *ia = (struct in_addr*)host->h_addr_list[0];
|
||||
DBG("addr: %s", inet_ntoa(*ia));
|
||||
addr.sin_family = AF_INET;
|
||||
int p = atoi(d->port); DBG("PORT: %s - %d", d->port, p);
|
||||
int p = atoi(device->port); DBG("PORT: %s - %d", device->port, p);
|
||||
addr.sin_port = htons(p);
|
||||
//addr.sin_addr.s_addr = *(long*)(host->h_addr);
|
||||
addr.sin_addr.s_addr = ia->s_addr;
|
||||
@ -273,16 +275,16 @@ static TTY_descr2* opensocket(chardevice *d){
|
||||
sa = (struct sockaddr*) &saddr;
|
||||
addrlen = sizeof(saddr);
|
||||
saddr.sun_family = AF_UNIX;
|
||||
if(*(d->name) == 0){ // if sun_path[0] == 0 then don't create a file
|
||||
if(*(device->name) == 0){ // if sun_path[0] == 0 then don't create a file
|
||||
DBG("convert name");
|
||||
saddr.sun_path[0] = 0;
|
||||
strncpy(saddr.sun_path+1, d->name+1, 105);
|
||||
strncpy(saddr.sun_path+1, device->name+1, 105);
|
||||
}
|
||||
else if(strncmp("\\0", d->name, 2) == 0){
|
||||
else if(strncmp("\\0", device->name, 2) == 0){
|
||||
DBG("convert name");
|
||||
saddr.sun_path[0] = 0;
|
||||
strncpy(saddr.sun_path+1, d->name+2, 105);
|
||||
}else strncpy(saddr.sun_path, d->name, 106);
|
||||
strncpy(saddr.sun_path+1, device->name+2, 105);
|
||||
}else strncpy(saddr.sun_path, device->name, 106);
|
||||
domain = AF_UNIX;
|
||||
}
|
||||
const int *type = socktypes;
|
||||
@ -363,17 +365,17 @@ someerr:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static TTY_descr2* opentty(chardevice *d){
|
||||
if(!d->name){
|
||||
static TTY_descr2* opentty(){
|
||||
if(!device->name){
|
||||
/// ïÔÓÕÔÓÔ×ÕÅÔ ÉÍÑ ÐÏÒÔÁ
|
||||
WARNX(_("Port name is missing"));
|
||||
return NULL;
|
||||
}
|
||||
TTY_descr2 *descr = MALLOC(TTY_descr2, 1);
|
||||
descr->portname = strdup(d->name);
|
||||
descr->speed = d->speed;
|
||||
descr->portname = strdup(device->name);
|
||||
descr->speed = device->speed;
|
||||
tcflag_t flags;
|
||||
descr->format = parse_format(d->port, &flags);
|
||||
descr->format = parse_format(device->port, &flags);
|
||||
if(!descr->format) goto someerr;
|
||||
descr->buf = MALLOC(char, BUFSIZ);
|
||||
descr->bufsz = BUFSIZ-1;
|
||||
@ -389,14 +391,14 @@ static TTY_descr2* opentty(chardevice *d){
|
||||
descr->tty.c_lflag = 0; // ~(ICANON | ECHO | ECHOE | ISIG)
|
||||
descr->tty.c_iflag = 0;
|
||||
descr->tty.c_cflag = BOTHER | flags |CREAD|CLOCAL;
|
||||
descr->tty.c_ispeed = d->speed;
|
||||
descr->tty.c_ospeed = d->speed;
|
||||
descr->tty.c_ispeed = device->speed;
|
||||
descr->tty.c_ospeed = device->speed;
|
||||
if(ioctl(descr->comfd, TCSETS2, &descr->tty)){
|
||||
WARN(_("Can't set new port config"));
|
||||
goto someerr;
|
||||
}
|
||||
ioctl(descr->comfd, TCGETS2, &descr->tty);
|
||||
d->speed = descr->tty.c_ispeed;
|
||||
device->speed = descr->tty.c_ispeed;
|
||||
#ifdef EBUG
|
||||
printf("ispeed: %d, ospeed: %d, cflag=%d (BOTHER=%d)\n", descr->tty.c_ispeed, descr->tty.c_ospeed, descr->tty.c_cflag&CBAUD, BOTHER);
|
||||
if(system("stty -F /dev/ttyUSB0")) WARN("system()");
|
||||
@ -417,20 +419,24 @@ someerr:
|
||||
int opendev(chardevice *d, char *path){
|
||||
if(!d) return FALSE;
|
||||
DBG("Try to open device");
|
||||
switch(d->type){
|
||||
device = MALLOC(chardevice, 1);
|
||||
memcpy(device, d, sizeof(chardevice));
|
||||
device->name = strdup(d->name);
|
||||
device->port = strdup(d->port);
|
||||
switch(device->type){
|
||||
case DEV_TTY:
|
||||
DBG("Serial");
|
||||
d->dev = opentty(d);
|
||||
if(!d->dev){
|
||||
WARN("Can't open device %s", d->name);
|
||||
device->dev = opentty();
|
||||
if(!device->dev){
|
||||
WARN("Can't open device %s", device->name);
|
||||
DBG("CANT OPEN");
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case DEV_NETSOCKET:
|
||||
case DEV_UNIXSOCKET:
|
||||
d->dev = opensocket(d);
|
||||
if(!d->dev){
|
||||
device->dev = opensocket();
|
||||
if(!device->dev){
|
||||
WARNX("Can't open socket");
|
||||
DBG("CANT OPEN");
|
||||
return FALSE;
|
||||
@ -443,44 +449,45 @@ int opendev(chardevice *d, char *path){
|
||||
dupfile = fopen(path, "a");
|
||||
if(!dupfile){
|
||||
WARN("Can't open %s", path);
|
||||
closedev(d);
|
||||
closedev();
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void closedev(chardevice *d){
|
||||
if(!d) return;
|
||||
pthread_mutex_unlock(&d->mutex);
|
||||
pthread_mutex_trylock(&d->mutex);
|
||||
void closedev(){
|
||||
if(!device) return;
|
||||
pthread_mutex_unlock(&device->mutex);
|
||||
pthread_mutex_trylock(&device->mutex);
|
||||
if(dupfile){
|
||||
fclose(dupfile);
|
||||
dupfile = NULL;
|
||||
}
|
||||
switch(d->type){
|
||||
switch(device->type){
|
||||
case DEV_TTY:
|
||||
if(d->dev){
|
||||
TTY_descr2 *t = d->dev;
|
||||
if(device->dev){
|
||||
TTY_descr2 *t = device->dev;
|
||||
ioctl(t->comfd, TCSETS2, &t->oldtty); // return TTY to previous state
|
||||
close(t->comfd);
|
||||
}
|
||||
break;
|
||||
case DEV_NETSOCKET:
|
||||
if(d->dev){
|
||||
close(d->dev->comfd);
|
||||
FREE(d->dev);
|
||||
if(device->dev){
|
||||
close(device->dev->comfd);
|
||||
FREE(device->dev);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
if(d->dev){
|
||||
FREE(d->dev->format);
|
||||
FREE(d->dev->portname);
|
||||
FREE(d->dev->buf);
|
||||
FREE(d->dev);
|
||||
if(device->dev){
|
||||
FREE(device->dev->format);
|
||||
FREE(device->dev->portname);
|
||||
FREE(device->dev->buf);
|
||||
FREE(device->dev);
|
||||
}
|
||||
FREE(d->name);
|
||||
FREE(device->name);
|
||||
FREE(device);
|
||||
DBG("Device closed");
|
||||
}
|
||||
|
||||
10
ttysocket.h
10
ttysocket.h
@ -23,9 +23,10 @@
|
||||
#include <pthread.h>
|
||||
#include <asm-generic/termbits.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
//#include "dbg.h"
|
||||
|
||||
typedef enum{
|
||||
typedef enum{ // device: tty terminal, network socket or UNIX socket
|
||||
DEV_TTY,
|
||||
DEV_NETSOCKET,
|
||||
DEV_UNIXSOCKET,
|
||||
@ -55,10 +56,11 @@ typedef struct{
|
||||
int eollen; // length of `eol`
|
||||
} chardevice;
|
||||
|
||||
char *ReadData(chardevice *d, int *l);
|
||||
int SendData(chardevice *d, char *str);
|
||||
char *geteol(int *s);
|
||||
char *ReadData(int *l);
|
||||
int SendData(const char *data, size_t len);
|
||||
void settimeout(int tms);
|
||||
int opendev(chardevice *d, char *path);
|
||||
void closedev(chardevice *d);
|
||||
void closedev();
|
||||
|
||||
#endif // TTY_H__
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user