From: PatR Date: Wed, 16 Feb 2022 08:36:26 +0000 (-0800) Subject: groundwork for nethackrc name on command line X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f588a707bb53957e59d68fa02d1def4a2424190d;p=nethack groundwork for nethackrc name on command line I've implemented 'nethack -nethackrc=filename' as an alternative to 'NETHACKOPTIONS='@filename' nethack' but at the moment it doesn't work because the command line parsing comes after the run-time config file has already been processed. But this part should work, or maybe have problems spotted and fixed if it doesn't. The RC file part of initoptions_finish() has been rewritten so that it won't need extra replication of | set_error_handling() | process_file() | reset_error_handling() | if (NETHACKOPTIONS) { | set_error_handling() | process_options() | reset_error_handling() | } I've tried to test all the combinations mentioned in the comment but am not sure that I covered everything, particulary for repeating earlier tests after making incremental changes. --- diff --git a/include/decl.h b/include/decl.h index 934cc90dd..a71493535 100644 --- a/include/decl.h +++ b/include/decl.h @@ -1,4 +1,4 @@ -/* NetHack 3.7 decl.h $NHDT-Date: 1627408982 2021/07/27 18:03:02 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.265 $ */ +/* NetHack 3.7 decl.h $NHDT-Date: 1645000560 2022/02/16 08:36:00 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.283 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Michael Allison, 2007. */ /* NetHack may be freely redistributed. See license for details. */ @@ -918,6 +918,7 @@ struct instance_globals { struct rogueroom r[3][3]; /* files.c */ + char *cmdline_rcfile; /* set in unixmain.c, used in options.c */ char wizkit[WIZKIT_MAX]; int lockptr; char *config_section_chosen; diff --git a/src/decl.c b/src/decl.c index 180b9f7a0..e2a5f77d7 100644 --- a/src/decl.c +++ b/src/decl.c @@ -1,4 +1,4 @@ -/* NetHack 3.7 decl.c $NHDT-Date: 1606919256 2020/12/02 14:27:36 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.221 $ */ +/* NetHack 3.7 decl.c $NHDT-Date: 1645000574 2022/02/16 08:36:14 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.248 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Michael Allison, 2009. */ /* NetHack may be freely redistributed. See license for details. */ @@ -405,6 +405,7 @@ const struct instance_globals g_init = { UNDEFINED_VALUES, /* files.c */ + NULL, /* cmdline_rcfile */ UNDEFINED_VALUES, /* wizkit */ UNDEFINED_VALUE, /* lockptr */ NULL, /* config_section_chosen */ diff --git a/src/options.c b/src/options.c index ba4b5e8ad..5a8491138 100644 --- a/src/options.c +++ b/src/options.c @@ -1,4 +1,4 @@ -/* NetHack 3.7 options.c $NHDT-Date: 1644531493 2022/02/10 22:18:13 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.538 $ */ +/* NetHack 3.7 options.c $NHDT-Date: 1645000577 2022/02/16 08:36:17 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.540 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Michael Allison, 2008. */ /* NetHack may be freely redistributed. See license for details. */ @@ -5843,43 +5843,85 @@ initoptions_init(void) nmcpy(g.pl_fruit, OBJ_NAME(objects[SLIME_MOLD]), PL_FSIZ); } +/* + * Process user's run-time configuration file: + * get value of NETHACKOPTIONS; + * if command line specified -nethackrc=filename, use that; + * if NETHACKOPTIONS is present, + * honor it if it has a list of options to set + * or ignore it if it specifies a file name; + * else if not specified on command line and NETHACKOPTIONS names a file, + * use that as the config file; + * no extra options (normal use of NETHACKOPTIONS) will be set; + * otherwise (not on command line and either no NETHACKOPTIONS or that + * isn't a file name), + * pass Null to read_config_file() so that it will read ~/.nethackrc + * by default, + * then process the value of NETHACKOPTIONS as extra options. + */ void initoptions_finish(void) { nhsym sym = 0; + char *opts = 0, *xtraopts = 0; #ifndef MAC - char *opts = getenv("NETHACKOPTIONS"); - - if (!opts) - opts = getenv("HACKOPTIONS"); - if (opts) { - if (*opts == '/' || *opts == '\\' || *opts == '@') { - if (*opts == '@') - opts++; /* @filename */ - /* looks like a filename */ - if (strlen(opts) < BUFSZ / 2) { - config_error_init(TRUE, opts, CONFIG_ERROR_SECURE); - (void) read_config_file(opts, set_in_config); - config_error_done(); - } - } else { - config_error_init(TRUE, (char *) 0, FALSE); - (void) read_config_file((char *) 0, set_in_config); - config_error_done(); - /* let the total length of options be long; - * parseoptions() will check each individually - */ - config_error_init(FALSE, "NETHACKOPTIONS", FALSE); - (void) parseoptions(opts, TRUE, FALSE); - config_error_done(); - } + const char *envname, *namesrc, *nameval; + + /* getenv() instead of nhgetenv(): let total length of options be long; + parseoptions() will check each individually */ + envname = "NETHACKOPTIONS"; + opts = getenv(envname); + if (!opts) { + /* fall back to original name; discouraged */ + envname = "HACKOPTIONS"; + opts = getenv(envname); + } + + if (g.cmdline_rcfile) { + namesrc = "command line"; + nameval = g.cmdline_rcfile; + free((genericptr_t) g.cmdline_rcfile), g.cmdline_rcfile = 0; + xtraopts = opts; + if (opts && (*opts == '/' || *opts == '\\' || *opts == '@')) + xtraopts = 0; /* NETHACKOPTIONS is a file name; ignore it */ + } else if (opts && (*opts == '/' || *opts == '\\' || *opts == '@')) { + /* NETHACKOPTIONS is a file name; use that instead of the default */ + if (*opts == '@') + ++opts; /* @filename */ + namesrc = envname; + nameval = opts; + xtraopts = 0; } else #endif /* !MAC */ /*else*/ { - config_error_init(TRUE, (char *) 0, FALSE); - (void) read_config_file((char *) 0, set_in_config); + /* either no NETHACKOPTIONS or it wasn't a file name; + read the default configuration file */ + nameval = namesrc = 0; + xtraopts = opts; + } + + /* seemingly arbitrary name length restriction is to prevent error + messages, if any were to be delivered while accessing the file, + from potentially overflowing buffers */ + if (nameval && (int) strlen(nameval) >= BUFSZ / 2) { + config_error_init(TRUE, namesrc, FALSE); + config_error_add( + "nethackrc file name \"%.40s\"... too long; using default", + nameval); + config_error_done(); + nameval = namesrc = 0; /* revert to default nethackrc */ + } + + config_error_init(TRUE, nameval, nameval ? CONFIG_ERROR_SECURE : FALSE); + (void) read_config_file(nameval, set_in_config); + config_error_done(); + if (xtraopts) { + /* NETHACKOPTIONS is present and not a file name */ + config_error_init(FALSE, envname, FALSE); + (void) parseoptions(xtraopts, TRUE, FALSE); config_error_done(); } + /*[end of nethackrc handling]*/ (void) fruitadd(g.pl_fruit, (struct fruit *) 0); /*