(WIP) --config=<f> param, read it, set values from it

This commit is contained in:
Gwenhael Le Moine 2023-09-30 10:52:40 +02:00
parent 893de1b4be
commit b24cee83c6
No known key found for this signature in database
GPG key ID: FDFE3669426707A7
4 changed files with 182 additions and 28 deletions

View file

@ -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)
LIBS = -lm
### lua
CFLAGS += $(shell pkg-config --cflags lua)
LIBS += $(shell pkg-config --libs lua)
### debugger
CFLAGS += $(shell pkg-config --cflags readline)
LIBS += $(shell pkg-config --libs readline)

18
dist/config.lua vendored Normal file
View 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"

View file

@ -5,9 +5,14 @@
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdbool.h>
#include <assert.h>
#include <getopt.h>
#include <lua.h>
#include <lauxlib.h>
#include "runtime_options.h"
char* progname = "x48ng";
@ -23,6 +28,7 @@ int resetOnStartup = 0;
char* serialLine = "/dev/ttyS0";
char* configDir = ".x48ng";
char* config_file = "config.lua";
char* romFileName = "rom";
char* ramFileName = "ram";
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 normalized_config_path[ MAX_LENGTH_FILENAME ];
char normalized_config_file[ MAX_LENGTH_FILENAME ];
char normalized_rom_path[ MAX_LENGTH_FILENAME ];
char normalized_ram_path[ MAX_LENGTH_FILENAME ];
char normalized_state_path[ MAX_LENGTH_FILENAME ];
char normalized_port1_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 )
{
char* home;
@ -97,10 +218,19 @@ void get_absolute_config_dir( char* source, char* 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;
int normalized_config_path_exist = 1;
get_absolute_config_dir( configDir, normalized_config_path );
if ( verbose )
@ -109,6 +239,16 @@ static inline void normalize_filenames( void )
if ( stat( normalized_config_path, &st ) == -1 )
if ( errno == ENOENT )
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 ] == '/' )
strcpy( normalized_rom_path, "" );
@ -122,30 +262,6 @@ static inline void normalize_filenames( void )
strcpy( normalized_rom_path, normalized_config_path );
}
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[] )
@ -153,9 +269,10 @@ int parse_args( int argc, char* argv[] )
int option_index;
int c = '?';
char* optstring = "c:S:u:hvVtsirT";
char* optstring = "c:hvVtsirT";
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 },
{ "ram", required_argument, NULL, 1011 },
{ "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 );
exit( 0 );
break;
case 'c':
config_file = optarg;
break;
case 1000:
configDir = optarg;
break;
@ -346,6 +466,16 @@ int parse_args( int argc, char* argv[] )
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();
if ( verbose ) {

View file

@ -25,6 +25,7 @@ extern int frontend_type;
extern char* serialLine;
extern char* configDir;
extern char* config_file;
extern char* romFileName;
extern char* ramFileName;
extern char* stateFileName;
@ -55,6 +56,7 @@ extern char* connFont;
#define MAX_LENGTH_FILENAME 2048
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_ram_path[ MAX_LENGTH_FILENAME ];
extern char normalized_state_path[ MAX_LENGTH_FILENAME ];