mirror of
https://github.com/tio/tio.git
synced 2026-05-01 14:57:59 +02:00
Add some subcommand-equivalent functions to the Lua API
Add following functions to Lua API tio.send_break() tio.set_local_echo() tio.set_log() tio.flush_data_io_buffer() tio.set_input_mode() tio.set_output_mode() tio.set_raw_mode() tio.set_raw_mode_interactive() tio.set_timestamp_mode() tio.set_exec_shell_command() tio.get_version()
This commit is contained in:
parent
d28b5f4452
commit
2069e77123
1 changed files with 271 additions and 13 deletions
284
src/script.c
284
src/script.c
|
|
@ -40,6 +40,7 @@
|
||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
#include "timestamp.h"
|
#include "timestamp.h"
|
||||||
#include "termios.h"
|
#include "termios.h"
|
||||||
|
#include "version.h"
|
||||||
|
|
||||||
#define MAX_BUFFER_SIZE 2000 // Maximum size of circular buffer
|
#define MAX_BUFFER_SIZE 2000 // Maximum size of circular buffer
|
||||||
#define READ_LINE_SIZE 4096 // read_line buffer length
|
#define READ_LINE_SIZE 4096 // read_line buffer length
|
||||||
|
|
@ -49,6 +50,14 @@ static lua_State *script_interp = NULL;
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static char script_init[] =
|
static char script_init[] =
|
||||||
|
"tio.C = {\n"
|
||||||
|
" EXPECT_CLEANUP_READ_SIZE = 4096,\n"
|
||||||
|
" WAIT_FOREVER = 0,\n"
|
||||||
|
" NOWAIT = -1,\n"
|
||||||
|
"}\n"
|
||||||
|
"tio.clear_screen = function()\n"
|
||||||
|
" io.write('\\x1bc')\n"
|
||||||
|
"end\n"
|
||||||
"tio.set = function(arg)\n"
|
"tio.set = function(arg)\n"
|
||||||
" local dtr = arg.DTR or -1\n"
|
" local dtr = arg.DTR or -1\n"
|
||||||
" local rts = arg.RTS or -1\n"
|
" local rts = arg.RTS or -1\n"
|
||||||
|
|
@ -58,10 +67,6 @@ static char script_init[] =
|
||||||
" local ri = arg.RI or -1\n"
|
" local ri = arg.RI or -1\n"
|
||||||
" tio.line_set(dtr, rts, cts, dsr, cd, ri)\n"
|
" tio.line_set(dtr, rts, cts, dsr, cd, ri)\n"
|
||||||
"end\n"
|
"end\n"
|
||||||
"tio.C = {}\n"
|
|
||||||
"tio.C.EXPECT_CLEANUP_READ_SIZE = 4096\n"
|
|
||||||
"tio.C.WAIT_FOREVER = 0\n"
|
|
||||||
"tio.C.NOWAIT = -1\n"
|
|
||||||
"tio.expect = function(pattern, timeout)\n"
|
"tio.expect = function(pattern, timeout)\n"
|
||||||
" local str = ''\n"
|
" local str = ''\n"
|
||||||
" while true do\n"
|
" while true do\n"
|
||||||
|
|
@ -519,6 +524,207 @@ static int api_ttysearch(lua_State *L)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// lua: tio.send_break()
|
||||||
|
static int api_send_break(lua_State *L)
|
||||||
|
{
|
||||||
|
if (device_fd == 0)
|
||||||
|
{
|
||||||
|
return luaL_error(L, "tty device not ready");
|
||||||
|
}
|
||||||
|
|
||||||
|
tcsendbreak(device_fd, 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// lua: tio.set_local_echo(boolean local_echo)
|
||||||
|
static int api_set_local_echo(lua_State *L)
|
||||||
|
{
|
||||||
|
int arg_num = lua_gettop(L);
|
||||||
|
if (arg_num == 0)
|
||||||
|
{
|
||||||
|
option.local_echo = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if ( ! (lua_isboolean(L, 1) || lua_isnil(L, 1)) )
|
||||||
|
{
|
||||||
|
return luaL_error(L, "argument is not boolean");
|
||||||
|
}
|
||||||
|
option.local_echo = lua_toboolean(L, 1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// lua: tio.set_log(boolean log)
|
||||||
|
static int api_set_log(lua_State *L)
|
||||||
|
{
|
||||||
|
int arg_num = lua_gettop(L);
|
||||||
|
if (arg_num == 0)
|
||||||
|
{
|
||||||
|
option.log = true;
|
||||||
|
}
|
||||||
|
else /* arg_num > 0 */
|
||||||
|
{
|
||||||
|
if ( ! (lua_isboolean(L, 1) || lua_isnil(L, 1)) )
|
||||||
|
{
|
||||||
|
return luaL_error(L, "argument is not boolean");
|
||||||
|
}
|
||||||
|
option.log = lua_toboolean(L, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (option.log)
|
||||||
|
{
|
||||||
|
if (log_open(option.log_filename) != 0)
|
||||||
|
{
|
||||||
|
option.log = false;
|
||||||
|
return luaL_error(L, "cant open log file");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
log_close();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// lua: tio.flush_data_io_buffer()
|
||||||
|
static int api_flush_data_io_buffer(lua_State *L)
|
||||||
|
{
|
||||||
|
if (device_fd == 0)
|
||||||
|
{
|
||||||
|
return luaL_error(L, "tty device not ready");
|
||||||
|
}
|
||||||
|
tcflush(device_fd, TCIOFLUSH);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// lua: tio.set_input_mode(tio.C.IM_NORMAL | tio.C.IM_HEX | tio.C.IM_LINE)
|
||||||
|
static int api_set_input_mode(lua_State *L)
|
||||||
|
{
|
||||||
|
int input_mode = luaL_optinteger(L, 1, INPUT_MODE_NORMAL);
|
||||||
|
switch (input_mode)
|
||||||
|
{
|
||||||
|
case INPUT_MODE_NORMAL:
|
||||||
|
case INPUT_MODE_HEX:
|
||||||
|
case INPUT_MODE_LINE:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return luaL_error(L, "invalid input mode");
|
||||||
|
}
|
||||||
|
option.input_mode = input_mode;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// lua: tio.set_output_mode(tio.C.OM_NORMAL | tio.C.OM_HEX)
|
||||||
|
static int api_set_output_mode(lua_State *L)
|
||||||
|
{
|
||||||
|
int output_mode = luaL_optinteger(L, 1, OUTPUT_MODE_NORMAL);
|
||||||
|
switch (output_mode)
|
||||||
|
{
|
||||||
|
case OUTPUT_MODE_NORMAL:
|
||||||
|
case OUTPUT_MODE_HEX:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return luaL_error(L, "invalid output mode");
|
||||||
|
}
|
||||||
|
option.output_mode = output_mode;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// lua: tio.set_raw_mode(tio.C.RAW_OFF | tio.C.RAW_ON | tio.C.RAW_ON_NODELAY)
|
||||||
|
static int api_set_raw_mode(lua_State *L)
|
||||||
|
{
|
||||||
|
int raw_mode = luaL_optinteger(L, 1, RAW_ON_DELAY);
|
||||||
|
switch (raw_mode)
|
||||||
|
{
|
||||||
|
case RAW_OFF:
|
||||||
|
case RAW_ON_DELAY:
|
||||||
|
case RAW_ON_NODELAY:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return luaL_error(L, "invalid raw mode");
|
||||||
|
}
|
||||||
|
option.raw = raw_mode;
|
||||||
|
if (state != STATE_INTERACTIVE)
|
||||||
|
{
|
||||||
|
tty_tcsetattr(device_fd);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// lua: tio.set_raw_mode_interactive(tio.C.RAW_OFF | tio.C.RAW_ON | tio.C.RAW_ON_NODELAY)
|
||||||
|
static int api_set_raw_mode_interactive(lua_State *L)
|
||||||
|
{
|
||||||
|
int raw_mode = luaL_optinteger(L, 1, RAW_ON_DELAY);
|
||||||
|
switch (raw_mode)
|
||||||
|
{
|
||||||
|
case RAW_OFF:
|
||||||
|
case RAW_ON_DELAY:
|
||||||
|
case RAW_ON_NODELAY:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return luaL_error(L, "invalid raw mode");
|
||||||
|
}
|
||||||
|
option.raw_interactive = raw_mode;
|
||||||
|
if (state == STATE_INTERACTIVE)
|
||||||
|
{
|
||||||
|
tty_tcsetattr(device_fd);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// lua: tio.set_timestamp_mode(tio.C.TS_NONE | tio.C.TS_24HOUR | ...)
|
||||||
|
static int api_set_timestamp_mode(lua_State *L)
|
||||||
|
{
|
||||||
|
int timestamp_mode = luaL_optinteger(L, 1, TIMESTAMP_24HOUR);
|
||||||
|
switch (timestamp_mode)
|
||||||
|
{
|
||||||
|
case TIMESTAMP_NONE:
|
||||||
|
case TIMESTAMP_24HOUR:
|
||||||
|
case TIMESTAMP_24HOUR_START:
|
||||||
|
case TIMESTAMP_24HOUR_DELTA:
|
||||||
|
case TIMESTAMP_ISO8601:
|
||||||
|
case TIMESTAMP_EPOCH:
|
||||||
|
case TIMESTAMP_EPOCH_USEC:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return luaL_error(L, "invalid timestamp mode");
|
||||||
|
}
|
||||||
|
option.timestamp = timestamp_mode;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// lua: tio.exec_shell_command(string:command)
|
||||||
|
int api_exec_shell_command(lua_State *L)
|
||||||
|
{
|
||||||
|
const char *command = luaL_checkstring(L, 1);
|
||||||
|
if (command == NULL)
|
||||||
|
{
|
||||||
|
return luaL_error(L, "no command");
|
||||||
|
}
|
||||||
|
if (device_fd == 0)
|
||||||
|
{
|
||||||
|
return luaL_error(L, "tty device not ready");
|
||||||
|
}
|
||||||
|
int result;
|
||||||
|
state_t state_orig = state;
|
||||||
|
state = STATE_EXEC_SHELL_COMMAND;
|
||||||
|
tty_tcsetattr(device_fd);
|
||||||
|
result = execute_shell_command(device_fd, command);
|
||||||
|
state = state_orig;
|
||||||
|
tty_tcsetattr(device_fd);
|
||||||
|
if (result < 0)
|
||||||
|
{
|
||||||
|
return luaL_error(L, "command failed.");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// lua: tio.get_version()
|
||||||
|
static int api_get_version(lua_State *L)
|
||||||
|
{
|
||||||
|
lua_pushstring(L, VERSION);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static void script_buffer_run(lua_State *L, const char *script_buffer)
|
static void script_buffer_run(lua_State *L, const char *script_buffer)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
|
|
@ -561,6 +767,19 @@ static const struct luaL_Reg tio_lib[] =
|
||||||
{ "read", api_read},
|
{ "read", api_read},
|
||||||
{ "readline", api_readline},
|
{ "readline", api_readline},
|
||||||
{ "ttysearch", api_ttysearch},
|
{ "ttysearch", api_ttysearch},
|
||||||
|
|
||||||
|
{ "send_break", api_send_break},
|
||||||
|
{ "set_local_echo", api_set_local_echo},
|
||||||
|
{ "set_log", api_set_log},
|
||||||
|
{ "flush_data_io_buffer", api_flush_data_io_buffer},
|
||||||
|
{ "set_input_mode", api_set_input_mode},
|
||||||
|
{ "set_output_mode", api_set_output_mode},
|
||||||
|
{ "set_raw_mode", api_set_raw_mode},
|
||||||
|
{ "set_raw_mode_interactive", api_set_raw_mode_interactive},
|
||||||
|
{ "set_timestamp_mode", api_set_timestamp_mode},
|
||||||
|
{ "exec_shell_command", api_exec_shell_command},
|
||||||
|
{ "get_version", api_get_version},
|
||||||
|
|
||||||
{NULL, NULL}
|
{NULL, NULL}
|
||||||
};
|
};
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
@ -577,23 +796,61 @@ static void script_load(lua_State *L)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void script_set_global(lua_State *L, const char *name, long value)
|
static void script_set_global_integer(lua_State *L, const char *name, int value)
|
||||||
{
|
{
|
||||||
lua_pushnumber(L, value);
|
lua_pushinteger(L, value);
|
||||||
lua_setglobal(L, name);
|
lua_setglobal(L, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void script_set_globals(lua_State *L)
|
static void script_set_globals(lua_State *L)
|
||||||
{
|
{
|
||||||
script_set_global(L, "toggle", 2);
|
script_set_global_integer(L, "toggle", 2);
|
||||||
script_set_global(L, "high", 1);
|
script_set_global_integer(L, "high", 1);
|
||||||
script_set_global(L, "low", 0);
|
script_set_global_integer(L, "low", 0);
|
||||||
script_set_global(L, "XMODEM_SUM", XMODEM_SUM);
|
script_set_global_integer(L, "XMODEM_SUM", XMODEM_SUM);
|
||||||
script_set_global(L, "XMODEM_CRC", XMODEM_CRC);
|
script_set_global_integer(L, "XMODEM_CRC", XMODEM_CRC);
|
||||||
script_set_global(L, "XMODEM_1K", XMODEM_1K);
|
script_set_global_integer(L, "XMODEM_1K", XMODEM_1K);
|
||||||
script_set_global(L, "YMODEM", YMODEM);
|
script_set_global_integer(L, "YMODEM", YMODEM);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void script_set_field_integer(lua_State *L, const char *name, int value)
|
||||||
|
{
|
||||||
|
lua_pushinteger(L, value);
|
||||||
|
lua_setfield(L, -2, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void script_set_consts(lua_State *L)
|
||||||
|
{
|
||||||
|
lua_getglobal(L, "tio");
|
||||||
|
lua_getfield(L, -1, "C");
|
||||||
|
|
||||||
|
script_set_field_integer(L, "IM_NORMAL", INPUT_MODE_NORMAL);
|
||||||
|
script_set_field_integer(L, "IM_HEX", INPUT_MODE_HEX);
|
||||||
|
script_set_field_integer(L, "IM_LINE", INPUT_MODE_LINE);
|
||||||
|
script_set_field_integer(L, "OM_NORMAL", OUTPUT_MODE_NORMAL);
|
||||||
|
script_set_field_integer(L, "OM_HEX", OUTPUT_MODE_HEX);
|
||||||
|
script_set_field_integer(L, "RAW_OFF", RAW_OFF);
|
||||||
|
script_set_field_integer(L, "RAW_ON", RAW_ON_DELAY);
|
||||||
|
script_set_field_integer(L, "RAW_ON_NODELAY", RAW_ON_NODELAY);
|
||||||
|
script_set_field_integer(L, "TS_OFF", TIMESTAMP_NONE);
|
||||||
|
script_set_field_integer(L, "TS_24HOUR", TIMESTAMP_24HOUR);
|
||||||
|
script_set_field_integer(L, "TS_24HOUR_START", TIMESTAMP_24HOUR_START);
|
||||||
|
script_set_field_integer(L, "TS_24HOUR_DELTA", TIMESTAMP_24HOUR_DELTA);
|
||||||
|
script_set_field_integer(L, "TS_ISO8601", TIMESTAMP_ISO8601);
|
||||||
|
script_set_field_integer(L, "TS_EPOCH", TIMESTAMP_EPOCH);
|
||||||
|
script_set_field_integer(L, "TS_EPOCH_USEC", TIMESTAMP_EPOCH_USEC);
|
||||||
|
script_set_field_integer(L, "LN_TOGGLE", 2);
|
||||||
|
script_set_field_integer(L, "LN_HIGH", 1);
|
||||||
|
script_set_field_integer(L, "LN_LOW", 0);
|
||||||
|
script_set_field_integer(L, "XM_SUM", XMODEM_SUM);
|
||||||
|
script_set_field_integer(L, "XM_CRC", XMODEM_CRC);
|
||||||
|
script_set_field_integer(L, "XM_1K", XMODEM_1K);
|
||||||
|
script_set_field_integer(L, "YM_NORMAL", YMODEM);
|
||||||
|
|
||||||
|
lua_pop(L, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#if LUA_VERSION_NUM >= 502
|
#if LUA_VERSION_NUM >= 502
|
||||||
static int luaopen_tio(lua_State *L)
|
static int luaopen_tio(lua_State *L)
|
||||||
{
|
{
|
||||||
|
|
@ -635,6 +892,7 @@ static lua_State *script_interp_new(void)
|
||||||
|
|
||||||
// Initialize globals
|
// Initialize globals
|
||||||
script_set_globals(L);
|
script_set_globals(L);
|
||||||
|
script_set_consts(L);
|
||||||
|
|
||||||
// Execute script-init file
|
// Execute script-init file
|
||||||
if (option.script_init_filename) {
|
if (option.script_init_filename) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue