(WIP) --config=<f> param, read it, set values from it
This commit is contained in:
parent
893de1b4be
commit
b24cee83c6
4 changed files with 182 additions and 28 deletions
4
Makefile
4
Makefile
|
@ -16,6 +16,10 @@ OPTIM ?= 2
|
||||||
CFLAGS = -g -O$(OPTIM) -I./src/ -D_GNU_SOURCE=1 -DVERSION_MAJOR=$(VERSION_MAJOR) -DVERSION_MINOR=$(VERSION_MINOR) -DPATCHLEVEL=$(PATCHLEVEL)
|
CFLAGS = -g -O$(OPTIM) -I./src/ -D_GNU_SOURCE=1 -DVERSION_MAJOR=$(VERSION_MAJOR) -DVERSION_MINOR=$(VERSION_MINOR) -DPATCHLEVEL=$(PATCHLEVEL)
|
||||||
LIBS = -lm
|
LIBS = -lm
|
||||||
|
|
||||||
|
### lua
|
||||||
|
CFLAGS += $(shell pkg-config --cflags lua)
|
||||||
|
LIBS += $(shell pkg-config --libs lua)
|
||||||
|
|
||||||
### debugger
|
### debugger
|
||||||
CFLAGS += $(shell pkg-config --cflags readline)
|
CFLAGS += $(shell pkg-config --cflags readline)
|
||||||
LIBS += $(shell pkg-config --libs readline)
|
LIBS += $(shell pkg-config --libs readline)
|
||||||
|
|
18
dist/config.lua
vendored
Normal file
18
dist/config.lua
vendored
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
-- Configuration file for x48ng
|
||||||
|
|
||||||
|
-- local os = os
|
||||||
|
|
||||||
|
rom = "/usr/share/x48ng/ROMs/gxrom-r"
|
||||||
|
|
||||||
|
ram = config_dir .. "/ram"
|
||||||
|
state = config_dir .. "/state"
|
||||||
|
port1 = config_dir .. "/port1"
|
||||||
|
port2 = config_dir .. "/port2"
|
||||||
|
|
||||||
|
-- serial_line = "/dev/tty0"
|
||||||
|
|
||||||
|
debugger = true
|
||||||
|
|
||||||
|
throttle = false
|
||||||
|
|
||||||
|
frontend = "sdl"
|
|
@ -5,9 +5,14 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
|
|
||||||
|
#include <lua.h>
|
||||||
|
#include <lauxlib.h>
|
||||||
|
|
||||||
#include "runtime_options.h"
|
#include "runtime_options.h"
|
||||||
|
|
||||||
char* progname = "x48ng";
|
char* progname = "x48ng";
|
||||||
|
@ -23,6 +28,7 @@ int resetOnStartup = 0;
|
||||||
char* serialLine = "/dev/ttyS0";
|
char* serialLine = "/dev/ttyS0";
|
||||||
|
|
||||||
char* configDir = ".x48ng";
|
char* configDir = ".x48ng";
|
||||||
|
char* config_file = "config.lua";
|
||||||
char* romFileName = "rom";
|
char* romFileName = "rom";
|
||||||
char* ramFileName = "ram";
|
char* ramFileName = "ram";
|
||||||
char* stateFileName = "hp48";
|
char* stateFileName = "hp48";
|
||||||
|
@ -63,12 +69,127 @@ char* largeFont = "-*-fixed-medium-r-normal-*-20-*-*-*-*-*-iso8859-1";
|
||||||
char* connFont = "-*-fixed-medium-r-normal-*-12-*-*-*-*-*-iso8859-1";
|
char* connFont = "-*-fixed-medium-r-normal-*-12-*-*-*-*-*-iso8859-1";
|
||||||
|
|
||||||
char normalized_config_path[ MAX_LENGTH_FILENAME ];
|
char normalized_config_path[ MAX_LENGTH_FILENAME ];
|
||||||
|
char normalized_config_file[ MAX_LENGTH_FILENAME ];
|
||||||
char normalized_rom_path[ MAX_LENGTH_FILENAME ];
|
char normalized_rom_path[ MAX_LENGTH_FILENAME ];
|
||||||
char normalized_ram_path[ MAX_LENGTH_FILENAME ];
|
char normalized_ram_path[ MAX_LENGTH_FILENAME ];
|
||||||
char normalized_state_path[ MAX_LENGTH_FILENAME ];
|
char normalized_state_path[ MAX_LENGTH_FILENAME ];
|
||||||
char normalized_port1_path[ MAX_LENGTH_FILENAME ];
|
char normalized_port1_path[ MAX_LENGTH_FILENAME ];
|
||||||
char normalized_port2_path[ MAX_LENGTH_FILENAME ];
|
char normalized_port2_path[ MAX_LENGTH_FILENAME ];
|
||||||
|
|
||||||
|
/* https://boston.conman.org/2023/09/29.1 */
|
||||||
|
lua_State* gL;
|
||||||
|
|
||||||
|
bool config_read( const char* conf )
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
assert( conf != NULL );
|
||||||
|
|
||||||
|
/*---------------------------------------------------
|
||||||
|
; Create the Lua state, which includes NO predefined
|
||||||
|
; functions or values. This is literally an empty
|
||||||
|
; slate.
|
||||||
|
;----------------------------------------------------*/
|
||||||
|
|
||||||
|
gL = luaL_newstate();
|
||||||
|
if ( gL == NULL ) {
|
||||||
|
fprintf( stderr, "cannot create Lua state" );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------
|
||||||
|
; For the truly paranoid about sandboxing, enable the
|
||||||
|
; following code, which removes the string library,
|
||||||
|
; which some people find problematic to leave un-sand-
|
||||||
|
; boxed. But in my opinion, if you are worried about
|
||||||
|
; such attacks in a configuration file, you have bigger
|
||||||
|
; security issues to worry about than this.
|
||||||
|
;------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifdef PARANOID
|
||||||
|
lua_pushliteral( gL, "x" );
|
||||||
|
lua_pushnil( gL );
|
||||||
|
lua_setmetatable( gL, -2 );
|
||||||
|
lua_pop( gL, 1 );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*-----------------------------------------------------
|
||||||
|
; Lua 5.2+ can restrict scripts to being text only,
|
||||||
|
; to avoid a potential problem with loading pre-compiled
|
||||||
|
; Lua scripts that may have malformed Lua VM code that
|
||||||
|
; could possibly lead to an exploit, but again, if you
|
||||||
|
; have to worry about that, you have bigger security
|
||||||
|
; issues to worry about. But in any case, here I'm
|
||||||
|
; restricting the file to "text" only.
|
||||||
|
;------------------------------------------------------*/
|
||||||
|
|
||||||
|
rc = luaL_loadfilex( gL, conf, "t" );
|
||||||
|
if ( rc != LUA_OK ) {
|
||||||
|
fprintf( stderr, "Lua error: (%d) %s", rc, lua_tostring( gL, -1 ) );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = lua_pcall( gL, 0, 0, 0 );
|
||||||
|
if ( rc != LUA_OK ) {
|
||||||
|
fprintf( stderr, "Lua error: (%d) %s", rc, lua_tostring( gL, -1 ) );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------
|
||||||
|
; the Lua state gL contains our configuration,
|
||||||
|
; we can now query it for values
|
||||||
|
;---------------------------------------------*/
|
||||||
|
lua_getglobal( gL, "rom" );
|
||||||
|
romFileName = lua_tostring( gL, -1 );
|
||||||
|
fprintf( stderr, "config.rom = %s\n", romFileName );
|
||||||
|
|
||||||
|
lua_getglobal( gL, "ram" );
|
||||||
|
ramFileName = lua_tostring( gL, -1 );
|
||||||
|
fprintf( stderr, "config.ram = %s\n", ramFileName );
|
||||||
|
|
||||||
|
lua_getglobal( gL, "state" );
|
||||||
|
stateFileName = lua_tostring( gL, -1 );
|
||||||
|
fprintf( stderr, "config.state = %s\n", stateFileName );
|
||||||
|
|
||||||
|
lua_getglobal( gL, "port1" );
|
||||||
|
port1FileName = lua_tostring( gL, -1 );
|
||||||
|
fprintf( stderr, "config.port1 = %s\n", port1FileName );
|
||||||
|
|
||||||
|
lua_getglobal( gL, "port2" );
|
||||||
|
port2FileName = lua_tostring( gL, -1 );
|
||||||
|
fprintf( stderr, "config.port2 = %s\n", port2FileName );
|
||||||
|
|
||||||
|
lua_getglobal( gL, "serial_line" );
|
||||||
|
serialLine = lua_tostring( gL, -1 );
|
||||||
|
fprintf( stderr, "config.serial_line = %s\n", serialLine );
|
||||||
|
|
||||||
|
lua_getglobal( gL, "debugger" );
|
||||||
|
useDebugger = lua_toboolean( gL, -1 );
|
||||||
|
fprintf( stderr, "config.debugger = %i\n", useDebugger );
|
||||||
|
|
||||||
|
lua_getglobal( gL, "throttle" );
|
||||||
|
throttle = lua_toboolean( gL, -1 );
|
||||||
|
fprintf( stderr, "config.throttle = %i\n", throttle );
|
||||||
|
|
||||||
|
lua_getglobal( gL, "frontend" );
|
||||||
|
const char* config_lua__frontend = lua_tostring( gL, -1 );
|
||||||
|
fprintf( stderr, "config.frontend = %s\n", config_lua__frontend );
|
||||||
|
#ifdef HAS_X11
|
||||||
|
if ( strcmp( config_lua__frontend, "x11" ) == 0 )
|
||||||
|
frontend_type = FRONTEND_X11;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
#ifdef HAS_SDL
|
||||||
|
if ( strcmp( config_lua__frontend, "sdl" ) == 0 )
|
||||||
|
frontend_type = FRONTEND_SDL;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
if ( strcmp( config_lua__frontend, "text" ) == 0 )
|
||||||
|
frontend_type = FRONTEND_TEXT;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void get_absolute_config_dir( char* source, char* dest )
|
void get_absolute_config_dir( char* source, char* dest )
|
||||||
{
|
{
|
||||||
char* home;
|
char* home;
|
||||||
|
@ -97,10 +218,19 @@ void get_absolute_config_dir( char* source, char* dest )
|
||||||
strcat( dest, "/" );
|
strcat( dest, "/" );
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void normalize_filenames( void )
|
static inline void normalize_filename( const char* orig, char* dest )
|
||||||
|
{
|
||||||
|
if ( orig[ 0 ] == '/' )
|
||||||
|
strcpy( dest, "" );
|
||||||
|
else
|
||||||
|
strcpy( dest, normalized_config_path );
|
||||||
|
strcat( dest, orig );
|
||||||
|
}
|
||||||
|
|
||||||
|
int normalized_config_path_exist = 1;
|
||||||
|
static inline void normalize_config_dir( void )
|
||||||
{
|
{
|
||||||
struct stat st;
|
struct stat st;
|
||||||
int normalized_config_path_exist = 1;
|
|
||||||
|
|
||||||
get_absolute_config_dir( configDir, normalized_config_path );
|
get_absolute_config_dir( configDir, normalized_config_path );
|
||||||
if ( verbose )
|
if ( verbose )
|
||||||
|
@ -109,6 +239,16 @@ static inline void normalize_filenames( void )
|
||||||
if ( stat( normalized_config_path, &st ) == -1 )
|
if ( stat( normalized_config_path, &st ) == -1 )
|
||||||
if ( errno == ENOENT )
|
if ( errno == ENOENT )
|
||||||
normalized_config_path_exist = 0;
|
normalized_config_path_exist = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void normalize_filenames( void )
|
||||||
|
{
|
||||||
|
normalize_filename( config_file, normalized_config_file );
|
||||||
|
|
||||||
|
normalize_filename( ramFileName, normalized_ram_path );
|
||||||
|
normalize_filename( stateFileName, normalized_state_path );
|
||||||
|
normalize_filename( port1FileName, normalized_port1_path );
|
||||||
|
normalize_filename( port2FileName, normalized_port2_path );
|
||||||
|
|
||||||
if ( romFileName[ 0 ] == '/' )
|
if ( romFileName[ 0 ] == '/' )
|
||||||
strcpy( normalized_rom_path, "" );
|
strcpy( normalized_rom_path, "" );
|
||||||
|
@ -122,30 +262,6 @@ static inline void normalize_filenames( void )
|
||||||
strcpy( normalized_rom_path, normalized_config_path );
|
strcpy( normalized_rom_path, normalized_config_path );
|
||||||
}
|
}
|
||||||
strcat( normalized_rom_path, romFileName );
|
strcat( normalized_rom_path, romFileName );
|
||||||
|
|
||||||
if ( ramFileName[ 0 ] == '/' )
|
|
||||||
strcpy( normalized_ram_path, "" );
|
|
||||||
else
|
|
||||||
strcpy( normalized_ram_path, normalized_config_path );
|
|
||||||
strcat( normalized_ram_path, ramFileName );
|
|
||||||
|
|
||||||
if ( stateFileName[ 0 ] == '/' )
|
|
||||||
strcpy( normalized_state_path, "" );
|
|
||||||
else
|
|
||||||
strcpy( normalized_state_path, normalized_config_path );
|
|
||||||
strcat( normalized_state_path, stateFileName );
|
|
||||||
|
|
||||||
if ( port1FileName[ 0 ] == '/' )
|
|
||||||
strcpy( normalized_port1_path, "" );
|
|
||||||
else
|
|
||||||
strcpy( normalized_port1_path, normalized_config_path );
|
|
||||||
strcat( normalized_port1_path, port1FileName );
|
|
||||||
|
|
||||||
if ( port2FileName[ 0 ] == '/' )
|
|
||||||
strcpy( normalized_port2_path, "" );
|
|
||||||
else
|
|
||||||
strcpy( normalized_port2_path, normalized_config_path );
|
|
||||||
strcat( normalized_port2_path, port2FileName );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int parse_args( int argc, char* argv[] )
|
int parse_args( int argc, char* argv[] )
|
||||||
|
@ -153,9 +269,10 @@ int parse_args( int argc, char* argv[] )
|
||||||
int option_index;
|
int option_index;
|
||||||
int c = '?';
|
int c = '?';
|
||||||
|
|
||||||
char* optstring = "c:S:u:hvVtsirT";
|
char* optstring = "c:hvVtsirT";
|
||||||
static struct option long_options[] = {
|
static struct option long_options[] = {
|
||||||
{"config-dir", required_argument, NULL, 1000 },
|
{"config", required_argument, NULL, 'c' },
|
||||||
|
{ "config-dir", required_argument, NULL, 1000 },
|
||||||
{ "rom", required_argument, NULL, 1010 },
|
{ "rom", required_argument, NULL, 1010 },
|
||||||
{ "ram", required_argument, NULL, 1011 },
|
{ "ram", required_argument, NULL, 1011 },
|
||||||
{ "state", required_argument, NULL, 1012 },
|
{ "state", required_argument, NULL, 1012 },
|
||||||
|
@ -273,6 +390,9 @@ int parse_args( int argc, char* argv[] )
|
||||||
fprintf( stdout, "%s %d.%d.%d\n", progname, VERSION_MAJOR, VERSION_MINOR, PATCHLEVEL );
|
fprintf( stdout, "%s %d.%d.%d\n", progname, VERSION_MAJOR, VERSION_MINOR, PATCHLEVEL );
|
||||||
exit( 0 );
|
exit( 0 );
|
||||||
break;
|
break;
|
||||||
|
case 'c':
|
||||||
|
config_file = optarg;
|
||||||
|
break;
|
||||||
case 1000:
|
case 1000:
|
||||||
configDir = optarg;
|
configDir = optarg;
|
||||||
break;
|
break;
|
||||||
|
@ -346,6 +466,16 @@ int parse_args( int argc, char* argv[] )
|
||||||
fprintf( stderr, "\n" );
|
fprintf( stderr, "\n" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
normalize_config_dir();
|
||||||
|
|
||||||
|
/* read config.lua */
|
||||||
|
/* TODO: handle having no config_file */
|
||||||
|
/* TODO: command-line options should have priority over config file's values */
|
||||||
|
/* TODO: handle config_file being absolute or relative */
|
||||||
|
normalize_filename( config_file, normalized_config_file );
|
||||||
|
if ( !config_read( normalized_config_file ) )
|
||||||
|
exit( 1 );
|
||||||
|
|
||||||
normalize_filenames();
|
normalize_filenames();
|
||||||
|
|
||||||
if ( verbose ) {
|
if ( verbose ) {
|
||||||
|
|
|
@ -25,6 +25,7 @@ extern int frontend_type;
|
||||||
extern char* serialLine;
|
extern char* serialLine;
|
||||||
|
|
||||||
extern char* configDir;
|
extern char* configDir;
|
||||||
|
extern char* config_file;
|
||||||
extern char* romFileName;
|
extern char* romFileName;
|
||||||
extern char* ramFileName;
|
extern char* ramFileName;
|
||||||
extern char* stateFileName;
|
extern char* stateFileName;
|
||||||
|
@ -55,6 +56,7 @@ extern char* connFont;
|
||||||
|
|
||||||
#define MAX_LENGTH_FILENAME 2048
|
#define MAX_LENGTH_FILENAME 2048
|
||||||
extern char normalized_config_path[ MAX_LENGTH_FILENAME ];
|
extern char normalized_config_path[ MAX_LENGTH_FILENAME ];
|
||||||
|
extern char normalized_config_file[ MAX_LENGTH_FILENAME ];
|
||||||
extern char normalized_rom_path[ MAX_LENGTH_FILENAME ];
|
extern char normalized_rom_path[ MAX_LENGTH_FILENAME ];
|
||||||
extern char normalized_ram_path[ MAX_LENGTH_FILENAME ];
|
extern char normalized_ram_path[ MAX_LENGTH_FILENAME ];
|
||||||
extern char normalized_state_path[ MAX_LENGTH_FILENAME ];
|
extern char normalized_state_path[ MAX_LENGTH_FILENAME ];
|
||||||
|
|
Loading…
Reference in a new issue