diff --git a/include/extern.h b/include/extern.h index 03e364612..cf8d85a08 100644 --- a/include/extern.h +++ b/include/extern.h @@ -347,6 +347,10 @@ extern void disregard_this_config_statement(int); extern boolean config_unmatched_ignored(void); extern void clear_ignore_errors_on_unmatched(void); extern void set_ignore_errors_on_unmatched(void); +extern void rcfile_only_this_statement(int); +#ifdef WIN32 +extern boolean check_for_portable_config(void); +#endif #ifdef MSWIN_GRAPHICS extern void disregard_some_mswin_options(void); extern void rcfile_only_some_mswin_options(void); diff --git a/src/cfgfiles.c b/src/cfgfiles.c index 4fe3f5da3..4e410c880 100644 --- a/src/cfgfiles.c +++ b/src/cfgfiles.c @@ -35,6 +35,9 @@ staticfn char *is_config_section(char *); staticfn boolean handle_config_section(char *); boolean parse_config_line(char *); staticfn char *find_optparam(char *); +#ifdef WIN32 +staticfn boolean portable_sysconf_only_this_statement(int); +#endif #ifndef SFCTOOL staticfn boolean cnf_line_OPTIONS(char *); staticfn boolean cnf_line_AUTOPICKUP_EXCEPTION(char *); @@ -108,7 +111,7 @@ staticfn void cnf_parser_init(struct _cnf_parser_state *parser); staticfn void cnf_parser_done(struct _cnf_parser_state *parser); staticfn void parse_conf_buf(struct _cnf_parser_state *parser, boolean (*proc)(char *arg)); -/* next one is in extern.h; why here too? */ + /* next one is in extern.h; why here too? */ boolean parse_conf_str(const char *str, boolean (*proc)(char *arg)); static boolean ignore_errors_on_unmatched = FALSE, ignore_statement_errors = FALSE; @@ -2040,6 +2043,84 @@ rcfile_only_this_option(enum opt heeded_option) ignore_statement_errors = FALSE; } +void +rcfile_only_this_statement(int statementid) +{ + allopt_array_init(); + disregard_all_options(); + disregard_all_config_statements(); + heed_this_config_statement(statementid); + set_ignore_errors_on_unmatched(); + ignore_statement_errors = TRUE; + rcfile(); + heed_all_config_statements(); + heed_all_options(); + clear_ignore_errors_on_unmatched(); + ignore_statement_errors = FALSE; +} + +#ifdef WIN32 +extern char portable_device_path[_MAX_PATH]; /* windsys.c */ +extern boolean portable; + +staticfn boolean +portable_sysconf_only_this_statement(int statementid) +{ + const char *exepath; + char portable_sysconf[_MAX_PATH]; + + exepath = windows_exepath(); + if (exepath) { + Snprintf(portable_sysconf, sizeof portable_sysconf, "%s/sysconf", + exepath); + if (portable_sysconf[0] && file_exists(portable_sysconf)) { +#ifdef SYSCF +#ifdef SYSCF_FILE + allopt_array_init(); + disregard_all_options(); + disregard_all_config_statements(); + heed_this_config_statement(statementid); + set_ignore_errors_on_unmatched(); + ignore_statement_errors = TRUE; + + config_error_init(TRUE, portable_sysconf, FALSE); + go.opt_phase = syscf_opt; + (void) read_config_file(portable_sysconf, set_in_sysconf); + config_error_done(); + heed_all_config_statements(); + heed_all_options(); + clear_ignore_errors_on_unmatched(); + ignore_statement_errors = FALSE; + if (sysopt.portable_device_paths) { + Snprintf(portable_device_path, sizeof portable_device_path, + "%s\\", exepath); + return TRUE; + } +#endif +#endif /* SYSCF */ + } + } + return FALSE; +} + +boolean +check_for_portable_config(void) +{ + int i, target_index = -1; + + for (i = 0; i < SIZE(config_line_stmt); i++) { + if (!strcmp(config_line_stmt[i].name, "PORTABLE_DEVICE_PATHS")) { + target_index = i; + break; + } + } + if (target_index >= 0) { + return portable_sysconf_only_this_statement(target_index); + } + return FALSE; +} +#endif + #ifdef MSWIN_GRAPHICS void disregard_some_mswin_options(void) diff --git a/sys/windows/windmain.c b/sys/windows/windmain.c index e384031b1..6e7a44db7 100644 --- a/sys/windows/windmain.c +++ b/sys/windows/windmain.c @@ -59,6 +59,7 @@ void windows_nhbell(void); int windows_nh_poskey(int *, int *, int *); void windows_raw_print(const char *); char windows_yn_function(const char *, const char *, char); +boolean portable = FALSE; /* static void windows_getlin(const char *, char *); */ #ifdef WIN32CON @@ -206,8 +207,11 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/ } gh.hname = "NetHack"; /* used for syntax messages */ set_default_prefix_locations( - argv[0]); /* must be re-done after initoptions_init() - * which clears out gp.fqn_prefix[] */ + argv[0]); /* must be re-done again after initoptions_init() + * because that function clears out gp.fqn_prefix[] */ +#ifdef MSWIN_GRAPHICS + disregard_some_mswin_options(); +#endif copy_sysconf_content(); copy_symbols_content(); /* Now that sysconf has had a chance to set the TROUBLEPREFIX, don't @@ -260,9 +264,7 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/ early_options(&argc, &argv, &dir); program_state.early_options = 0; -#ifdef MSWIN_GRAPHICS - disregard_some_mswin_options(); -#endif + initoptions(); #if defined(CHDIR) && !defined(NOCWD_ASSUMPTIONS) chdir(gf.fqn_prefix[HACKPREFIX]); @@ -802,15 +804,19 @@ copy_symbols_content(void) void copy_sysconf_content(void) { - /* Using the SYSCONFPREFIX path, lock it so that it does not change */ - fqn_prefix_locked[SYSCONFPREFIX] = TRUE; + if (sysopt.portable_device_paths) { + portable = TRUE; + } else { + /* Using the SYSCONFPREFIX path, lock it so that it does not change */ + fqn_prefix_locked[SYSCONFPREFIX] = TRUE; - update_file(gf.fqn_prefix[SYSCONFPREFIX], SYSCF_TEMPLATE, - gf.fqn_prefix[DATAPREFIX], SYSCF_TEMPLATE, FALSE); + update_file(gf.fqn_prefix[SYSCONFPREFIX], SYSCF_TEMPLATE, + gf.fqn_prefix[DATAPREFIX], SYSCF_TEMPLATE, FALSE); - /* If the required early game file does not exist, copy it */ - copy_file(gf.fqn_prefix[SYSCONFPREFIX], SYSCF_FILE, - gf.fqn_prefix[DATAPREFIX], SYSCF_TEMPLATE, FALSE); + /* If the required early game file does not exist, copy it */ + copy_file(gf.fqn_prefix[SYSCONFPREFIX], SYSCF_FILE, + gf.fqn_prefix[DATAPREFIX], SYSCF_TEMPLATE, FALSE); + } } void diff --git a/sys/windows/windsys.c b/sys/windows/windsys.c index f7c2e3d55..a951ea6fe 100644 --- a/sys/windows/windsys.c +++ b/sys/windows/windsys.c @@ -44,10 +44,11 @@ * */ -static char portable_device_path[MAX_PATH]; +char portable_device_path[_MAX_PATH]; static boolean path_buffer_set = FALSE; static char path_buffer[MAX_PATH]; +extern boolean portable; #ifndef SFCTOOL /* runtime cursor display control switch */ @@ -88,9 +89,7 @@ int build_known_folder_path(const KNOWNFOLDERID *folder_id, char *path, void build_environment_path(const char *env_str, const char *folder, char *path, size_t path_size); boolean folder_file_exists(const char *folder, const char *file_name); -boolean test_portable_config(const char *executable_path, - char *portable_device_path, - size_t portable_device_path_size); + /* The function pointer nt_kbhit contains a kbhit() equivalent * which varies depending on which window port is active. * For the tty port it is tty_kbhit() [from consoletty.c] @@ -1042,9 +1041,8 @@ set_default_prefix_locations(const char *programPath UNUSED) append_slash(executable_path); #ifndef SFCTOOL - if (test_portable_config(executable_path, portable_device_path, - sizeof portable_device_path)) { - gf.fqn_prefix[SYSCONFPREFIX] = executable_path; + if (portable || (portable = check_for_portable_config())) { + gf.fqn_prefix[SYSCONFPREFIX] = portable_device_path; gf.fqn_prefix[CONFIGPREFIX] = portable_device_path; gf.fqn_prefix[HACKPREFIX] = portable_device_path; gf.fqn_prefix[SAVEPREFIX] = portable_device_path; @@ -1053,7 +1051,7 @@ set_default_prefix_locations(const char *programPath UNUSED) gf.fqn_prefix[SCOREPREFIX] = portable_device_path; gf.fqn_prefix[LOCKPREFIX] = portable_device_path; gf.fqn_prefix[TROUBLEPREFIX] = portable_device_path; - gf.fqn_prefix[DATAPREFIX] = executable_path; + gf.fqn_prefix[DATAPREFIX] = portable_device_path; } else { #endif /* SFCTOOL */ if (!build_known_folder_path(&FOLDERID_Profile, profile_path, @@ -1110,53 +1108,6 @@ append_slash(char *name) } void set_default_prefix_locations(const char *programPath); -boolean -test_portable_config(const char *executable_path, char *portable_device_path, - size_t portable_device_path_size) -{ - int lth = 0; - const char *sysconf = "sysconf"; - char tmppath[MAX_PATH]; - boolean retval = FALSE, - save_initoptions_noterminate = iflags.initoptions_noterminate; - - if (portable_device_path - && folder_file_exists(executable_path, "sysconf")) { - /* - There is a sysconf file (not just sysconf.template) present in - the exe path, which is not the way NetHack is initially - distributed, so assume it means that the admin/installer wants to - override something, perhaps set up for a fully-portable - configuration that leaves no traces behind elsewhere on this - computer's hard drive - delve into that... - */ - - *portable_device_path = '\0'; - lth = sizeof tmppath - strlen(sysconf); - (void) strncpy(tmppath, executable_path, lth - 1); - tmppath[lth - 1] = '\0'; - (void) strcat(tmppath, sysconf); - - iflags.initoptions_noterminate = 1; - /* assure_syscf_file(); */ - config_error_init(TRUE, tmppath, FALSE); - /* ... and _must_ parse correctly. */ - if (read_config_file(tmppath, set_in_sysconf) - && sysopt.portable_device_paths) - retval = TRUE; - (void) config_error_done(); - iflags.initoptions_noterminate = save_initoptions_noterminate; - sysopt_release(); /* the real sysconf processing comes later */ - } - if (retval) { - lth = strlen(executable_path); - if (lth <= (int) portable_device_path_size - 1) - Strcpy(portable_device_path, executable_path); - else - retval = FALSE; - } - return retval; -} const char * get_portable_device(void)