From 57f86662fd9d2157e288d544e078d78648dc8818 Mon Sep 17 00:00:00 2001 From: nhmall Date: Sun, 22 Dec 2024 19:58:52 -0500 Subject: [PATCH] try harder to have --showpaths succeed This helps avoid a potential chicken-and-egg scenario with the system configuration file (sysconf). If sysconf wasn't accessible at the expected location, it caused an immediate exit, without relaying any helpful information. That happened even when using: 'nethack --showpaths' That's particularly unhelpful, because the --showpaths output might have been useful towards understanding where NetHack was looking for such things. That left you without an easy recourse to identify where the game is looking for the sysconf file. That might be especially troublesome if you didn't build the game yourself. --- include/decl.h | 4 ++++ include/extern.h | 4 +++- src/decl.c | 2 ++ src/files.c | 35 ++++++++++++++++++++++++++++++++--- src/options.c | 5 +++++ sys/libnh/libnhmain.c | 10 ++-------- sys/unix/unixmain.c | 18 ++++++++---------- sys/vms/vmsmain.c | 12 +++--------- sys/windows/windmain.c | 26 +++++++++++--------------- 9 files changed, 70 insertions(+), 46 deletions(-) diff --git a/include/decl.h b/include/decl.h index 415d710b1..9859c3e24 100644 --- a/include/decl.h +++ b/include/decl.h @@ -340,6 +340,10 @@ struct instance_globals_d { boolean decor_fumble_override; boolean decor_levitate_override; + /* new */ + boolean deferred_showpaths; + const char *deferred_showpaths_dir; + boolean havestate; unsigned long magic; /* validate that structure layout is preserved */ }; diff --git a/include/extern.h b/include/extern.h index 35bb33138..760ad30e2 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1072,11 +1072,12 @@ extern int nhclose(int); #ifdef DEBUG extern boolean debugcore(const char *, boolean); #endif -extern void reveal_paths(void); +extern void reveal_paths(int); extern boolean read_tribute(const char *, const char *, int, char *, int, unsigned); extern boolean Death_quote(char *, int) NONNULLARG1; extern void livelog_add(long ll_type, const char *) NONNULLARG2; +ATTRNORETURN extern void do_deferred_showpaths(int) NORETURN; /* ### fountain.c ### */ @@ -3379,6 +3380,7 @@ extern void append_slash(char *) NONNULLARG1; extern boolean check_user_string(const char *) NONNULLARG1; extern char *get_login_name(void); extern unsigned long sys_random_seed(void); +ATTRNORETURN extern void after_opt_showpaths(const char *) NORETURN; #endif /* UNIX */ /* ### unixtty.c ### */ diff --git a/src/decl.c b/src/decl.c index 08b54e4f7..e21cfc8db 100644 --- a/src/decl.c +++ b/src/decl.c @@ -339,6 +339,8 @@ static const struct instance_globals_d g_init_d = { /* pickup.c */ FALSE, /* decor_fumble_override */ FALSE, /* decor_levitate_override */ + FALSE, /* deferred_showpaths */ + NULL, /* deferred_showpaths_dir */ TRUE, /* havestate*/ IVMAGIC /* d_magic to validate that structure layout has been preserved */ }; diff --git a/src/files.c b/src/files.c index d7ce06f60..8a23a0175 100644 --- a/src/files.c +++ b/src/files.c @@ -4467,6 +4467,8 @@ assure_syscf_file(void) close(fd); return; } + if (gd.deferred_showpaths) + do_deferred_showpaths(1); /* does not return */ raw_printf("Unable to open SYSCF_FILE.\n"); exit(EXIT_FAILURE); } @@ -4474,6 +4476,26 @@ assure_syscf_file(void) #endif /* SYSCF_FILE */ #endif /* SYSCF */ +ATTRNORETURN void +do_deferred_showpaths(int code) +{ + gd.deferred_showpaths = FALSE; + reveal_paths(code); + +#ifdef UNIX + after_opt_showpaths(gd.deferred_showpaths_dir); +#else +#ifdef CHDIR + chdirx(gd.deferred_showpaths_dir, 0); +#endif +#if defined(WIN32) || defined(MICRO) || defined(OS2) + nethack_exit(EXIT_SUCCESS); +#else + exit(EXIT_SUCCESS); +#endif +#endif +} + #ifdef DEBUG /* used by debugpline() to decide whether to issue a message * from a particular source file; caller passes __FILE__ and we check @@ -4534,9 +4556,11 @@ debugcore(const char *filename, boolean wildcards) #endif void -reveal_paths(void) +reveal_paths(int code) { - const char *fqn, *nodumpreason; + const char *fqn, *nodumpreason, + *sysconffile = "system configuration file"; + char buf[BUFSZ]; #if defined(SYSCF) || !defined(UNIX) || defined(DLB) const char *filep; @@ -4570,7 +4594,8 @@ reveal_paths(void) #else buf[0] = '\0'; #endif - raw_printf("%s system configuration file%s:", s_suffix(gamename), buf); + raw_printf("%s %s%s:", + s_suffix(gamename), sysconffile, buf); #ifdef SYSCF_FILE filep = SYSCF_FILE; #else @@ -4582,6 +4607,10 @@ reveal_paths(void) filep = configfile; } raw_printf(" \"%s\"", filep); + if (code == 1) { + raw_printf("NOTE: The %s above is missing or inaccessible!", + sysconffile); + } #else /* !SYSCF */ raw_printf("No system configuration file."); #endif /* ?SYSCF */ diff --git a/src/options.c b/src/options.c index 0a9a7dc85..30d7709f4 100644 --- a/src/options.c +++ b/src/options.c @@ -6942,6 +6942,11 @@ initoptions(void) */ #endif #endif /* SYSCF */ + + /* Carry out options that got deferred from early_options */ + if (gd.deferred_showpaths) + do_deferred_showpaths(0); /* does not return */ + initoptions_finish(); } diff --git a/sys/libnh/libnhmain.c b/sys/libnh/libnhmain.c index 20835dda6..289ee2c5f 100644 --- a/sys/libnh/libnhmain.c +++ b/sys/libnh/libnhmain.c @@ -108,14 +108,8 @@ nhmain(int argc, char *argv[]) #endif if (argcheck(argc, argv, ARG_SHOWPATHS) == 2) { -#ifdef CHDIR - chdirx((char *) 0, 0); -#endif - iflags.initoptions_noterminate = TRUE; - initoptions(); - iflags.initoptions_noterminate = FALSE; - reveal_paths(); - exit(EXIT_SUCCESS); + gd.deferred_showpaths = TRUE; + return; } if (argcheck(argc, argv, ARG_DEBUG) == 1) { argc--; diff --git a/sys/unix/unixmain.c b/sys/unix/unixmain.c index e6b09492c..617a1ef06 100644 --- a/sys/unix/unixmain.c +++ b/sys/unix/unixmain.c @@ -36,7 +36,6 @@ static void consume_two_args(int, int *, char ***); static void early_options(int *, char ***, char **); ATTRNORETURN static void opt_terminate(void) NORETURN; ATTRNORETURN static void opt_usage(const char *) NORETURN; -static void opt_showpaths(const char *); ATTRNORETURN static void scores_only(int, char **, const char *) NORETURN; #ifdef SND_LIB_INTEGRATED uint32_t soundlibchoice = soundlib_nosound; @@ -702,9 +701,10 @@ early_options(int *argc_p, char ***argv_p, char **hackdir_p) break; case 's': if (argcheck(argc, argv, ARG_SHOWPATHS) == 2) { - opt_showpaths(*hackdir_p); - opt_terminate(); - /*NOTREACHED*/ + gd.deferred_showpaths = TRUE; + gd.deferred_showpaths_dir = *hackdir_p; + config_error_done(); + return; } /* check for "-s" request to show scores */ if (lopt(arg, ((ArgValDisallowed | ArgErrComplain) @@ -785,18 +785,16 @@ opt_usage(const char *hackdir) /* show the sysconf file name, playground directory, run-time configuration file name, dumplog file name if applicable, and some other things */ -static void -opt_showpaths(const char *dir) +ATTRNORETURN void +after_opt_showpaths(const char *dir) { #ifdef CHDIR chdirx(dir, FALSE); #else nhUse(dir); #endif - iflags.initoptions_noterminate = TRUE; - initoptions(); - iflags.initoptions_noterminate = FALSE; - reveal_paths(); + opt_terminate(); + /*NOTREACHED*/ } /* handle "-s [character-names]" to show all the entries diff --git a/sys/vms/vmsmain.c b/sys/vms/vmsmain.c index dcb681caa..25c40b842 100644 --- a/sys/vms/vmsmain.c +++ b/sys/vms/vmsmain.c @@ -80,15 +80,9 @@ main(int argc, char *argv[]) exit(EXIT_SUCCESS); if (argcheck(argc, argv, ARG_SHOWPATHS) == 2) { -#ifdef CHDIR - chdirx((char *) 0, 0); -#endif - iflags.initoptions_noterminate = TRUE; - initoptions(); - iflags.initoptions_noterminate = FALSE; - reveal_paths(); - exit(EXIT_SUCCESS); - } + gd.deferred_showpaths = TRUE; + return; + } if (argcheck(argc, argv, ARG_DEBUG) == 1) { argc--; argv++; diff --git a/sys/windows/windmain.c b/sys/windows/windmain.c index df7144a20..15cb8442f 100644 --- a/sys/windows/windmain.c +++ b/sys/windows/windmain.c @@ -18,9 +18,9 @@ #error You must #define SAFEPROCS to build windmain.c #endif -static void process_options(int argc, char **argv); static void nhusage(void); static char *get_executable_path(void); +static void early_options(int argc, char **argv); char *translate_path_variables(const char *, char *); char *exename(void); boolean fakeconsole(void); @@ -242,6 +242,7 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/ iflags.windowtype_deferred = TRUE; copy_sysconf_content(); copy_symbols_content(); + early_options(argc, argv); initoptions(); /* Now that sysconf has had a chance to set the TROUBLEPREFIX, don't @@ -249,7 +250,6 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/ fqn_prefix_locked[TROUBLEPREFIX] = TRUE; copy_config_content(); - process_options(argc, argv); /* did something earlier flag a need to exit without starting a game? */ if (windows_startup_state > 0) { @@ -462,23 +462,18 @@ attempt_restore: RESTORE_WARNING_UNREACHABLE_CODE static void -process_options(int argc, char * argv[]) +early_options(int argc, char *argv[]) { int i; - /* - * Process options. - */ if (argc > 1) { if (argcheck(argc, argv, ARG_VERSION) == 2) nethack_exit(EXIT_SUCCESS); if (argcheck(argc, argv, ARG_SHOWPATHS) == 2) { - iflags.initoptions_noterminate = TRUE; - initoptions(); - iflags.initoptions_noterminate = FALSE; - reveal_paths(); - nethack_exit(EXIT_SUCCESS); + gd.deferred_showpaths = TRUE; + /* gd.deferred_showpaths is not used by windows */ + return; } #ifndef NODUMPENUMS if (argcheck(argc, argv, ARG_DUMPENUMS) == 2) { @@ -509,7 +504,7 @@ process_options(int argc, char * argv[]) */ argc--; argv++; - const char * dir = argv[0] + 2; + const char *dir = argv[0] + 2; if (*dir == '=' || *dir == ':') dir++; if (!*dir && argc > 1) { @@ -578,7 +573,8 @@ process_options(int argc, char * argv[]) #endif case 'u': if (argv[0][2]) - (void) strncpy(svp.plname, argv[0] + 2, sizeof(svp.plname) - 1); + (void) strncpy(svp.plname, argv[0] + 2, + sizeof(svp.plname) - 1); else if (argc > 1) { argc--; argv++; @@ -634,8 +630,8 @@ process_options(int argc, char * argv[]) break; } else raw_printf("\nUnknown switch: %s", argv[0]); - FALLTHROUGH; - /* FALLTHRU */ + FALLTHROUGH; + /* FALLTHRU */ case '?': nhusage(); nethack_exit(EXIT_SUCCESS);