diff --git a/include/extern.h b/include/extern.h index 02d7f3b31..604b341c9 100644 --- a/include/extern.h +++ b/include/extern.h @@ -2123,6 +2123,7 @@ extern int dohistory(void); extern void chdirx(char *, boolean); #endif /* CHDIR */ extern boolean authorize_wizard_mode(void); +extern boolean authorize_explore_mode(void); #endif #if defined(WIN32) extern int getlock(void); @@ -3100,6 +3101,7 @@ extern void port_help(void); #endif extern void sethanguphandler(void(*)(int)); extern boolean authorize_wizard_mode(void); +extern boolean authorize_explore_mode(void); extern void append_slash(char *); extern boolean check_user_string(const char *); extern char *get_login_name(void); @@ -3264,6 +3266,7 @@ extern void chdirx(const char *, boolean); #endif /* CHDIR */ extern void sethanguphandler(void(*)(int)); extern boolean authorize_wizard_mode(void); +extern boolean authorize_explore_mode(void); /* ### vmsmisc.c ### */ diff --git a/include/flag.h b/include/flag.h index 7338f027e..4b8557793 100644 --- a/include/flag.h +++ b/include/flag.h @@ -412,6 +412,8 @@ struct instance_flags { chosen_windowport[], but do not switch to it in the midst of options processing */ genericptr_t returning_missile; /* 'struct obj *'; Mjollnir or aklys */ + boolean wiz_error_flag; /* flag for tracking failed wizmode auth */ + boolean explore_error_flag; /* ditto for explore mode */ boolean obsolete; /* obsolete options can point at this, it isn't used */ }; diff --git a/src/cmd.c b/src/cmd.c index a823b7486..941d71822 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -965,10 +965,7 @@ enter_explore_mode(void) } else { const char *oldmode = !wizard ? "normal game" : "debug mode"; -#ifdef SYSCF -#if defined(UNIX) - if (!sysopt.explorers || !sysopt.explorers[0] - || !check_user_string(sysopt.explorers)) { + if (!authorize_explore_mode()) { if (!wizard) { You("cannot access explore mode."); return ECMD_OK; @@ -978,8 +975,6 @@ enter_explore_mode(void) /* keep going */ } } -#endif -#endif pline("Beware! From explore mode there will be no return to %s,", oldmode); if (paranoid_query(ParanoidQuit, diff --git a/src/options.c b/src/options.c index 7354481f3..d939b3dd4 100644 --- a/src/options.c +++ b/src/options.c @@ -10257,11 +10257,17 @@ set_playmode(void) gp.plnamelen = (int) strlen(strcpy(gp.plname, "wizard")); else wizard = FALSE; /* not allowed or not available */ - /* force explore mode if we didn't make it into wizard mode */ + /* try explore mode if we didn't make it into wizard mode */ + /* if requesting wizard mode when restoring a normal game, this will + set iflags.deferred_X and prompt to activate explore mode after the + save file has already been deleted */ discover = !wizard; iflags.deferred_X = FALSE; } - /* don't need to do anything special for explore mode or normal play */ + if (discover && !authorize_explore_mode()) { + discover = iflags.deferred_X = FALSE; + } + /* don't need to do anything special for normal play */ } static void diff --git a/src/restore.c b/src/restore.c index fc475f9d3..6570ddbfc 100644 --- a/src/restore.c +++ b/src/restore.c @@ -512,7 +512,7 @@ restgamestate(NHFILE *nhfp) struct obj *bc_obj; char timebuf[15]; unsigned long uid = 0; - boolean defer_perm_invent; + boolean defer_perm_invent, restoring_special; if (nhfp->structlevel) Mread(nhfp->fd, &uid, sizeof uid); @@ -557,11 +557,12 @@ restgamestate(NHFILE *nhfp) in the discover case, we don't want to set that for a normal game until after the save file has been removed */ iflags.deferred_X = (newgameflags.explore && !discover); + restoring_special = (wizard || discover); if (newgameflags.debug) { /* authorized by startup code; wizard mode exists and is allowed */ wizard = TRUE, discover = iflags.deferred_X = FALSE; - } else if (wizard) { - /* specified by save file; check authorization now */ + } else if (restoring_special) { + /* specified by save file; check authorization now. */ set_playmode(); } role_init(); /* Reset the initial role, race, gender, and alignment */ @@ -572,6 +573,13 @@ restgamestate(NHFILE *nhfp) Mread(nhfp->fd, &u, sizeof u); gy.youmonst.cham = u.mcham; + if (restoring_special && iflags.explore_error_flag) { + /* savefile has wizard or explore mode, but player is no longer + authorized to access either; can't downgrade mode any further, so + fail restoration. */ + u.uhp = 0; + } + if (nhfp->structlevel) Mread(nhfp->fd, timebuf, 14); timebuf[14] = '\0'; diff --git a/sys/libnh/libnhmain.c b/sys/libnh/libnhmain.c index 40be3b467..631b9152c 100644 --- a/sys/libnh/libnhmain.c +++ b/sys/libnh/libnhmain.c @@ -50,7 +50,6 @@ extern void init_linux_cons(void); #endif static void wd_message(void); -static boolean wiz_error_flag = FALSE; static struct passwd *get_unix_pw(void); #ifdef __EMSCRIPTEN__ @@ -597,28 +596,48 @@ port_help(void) boolean authorize_wizard_mode(void) { - struct passwd *pw = get_unix_pw(); - - if (pw && sysopt.wizards && sysopt.wizards[0]) { + if (sysopt.wizards && sysopt.wizards[0]) { if (check_user_string(sysopt.wizards)) return TRUE; } - wiz_error_flag = TRUE; /* not being allowed into wizard mode */ + iflags.wiz_error_flag = TRUE; /* not being allowed into wizard mode */ return FALSE; } +/* similar to above, validate explore mode access */ +boolean +authorize_explore_mode(void) +{ +#ifdef SYSCF + if (sysopt.explorers && sysopt.explorers[0]) { + if (check_user_string(sysopt.explorers)) + return TRUE; + } + iflags.explore_error_flag = TRUE; /* not allowed into explore mode */ + return FALSE; +#else + return TRUE; /* if sysconf disabled, no restrictions on explore mode */ +#endif +} + static void wd_message(void) { - if (wiz_error_flag) { + if (iflags.wiz_error_flag) { if (sysopt.wizards && sysopt.wizards[0]) { char *tmp = build_english_list(sysopt.wizards); pline("Only user%s %s may access debug (wizard) mode.", strchr(sysopt.wizards, ' ') ? "s" : "", tmp); free(tmp); - } else + } else { + You("cannot access debug (wizard) mode."); + } + wizard = FALSE; /* (paranoia) */ + if (!iflags.explore_error_flag) pline("Entering explore/discovery mode instead."); - wizard = 0, discover = 1; /* (paranoia) */ + } else if (iflags.explore_error_flag) { + You("cannot access explore mode."); /* same as enter_explore_mode */ + discover = iflags.deferred_X = FALSE; /* (more paranoia) */ } else if (discover) You("are in non-scoring explore/discovery mode."); } diff --git a/sys/share/pcmain.c b/sys/share/pcmain.c index 5706651be..3744ee490 100644 --- a/sys/share/pcmain.c +++ b/sys/share/pcmain.c @@ -720,6 +720,13 @@ authorize_wizard_mode(void) return FALSE; } +/* similar to above, validate explore mode access */ +boolean +authorize_explore_mode(void) +{ + return TRUE; /* no restrictions on explore mode */ +} + #ifdef EXEPATH #ifdef __DJGPP__ #define PATH_SEPARATOR '/' diff --git a/sys/unix/unixmain.c b/sys/unix/unixmain.c index 2b041d0e8..122c2a96d 100644 --- a/sys/unix/unixmain.c +++ b/sys/unix/unixmain.c @@ -53,7 +53,6 @@ extern void init_linux_cons(void); #endif static void wd_message(void); -static boolean wiz_error_flag = FALSE; static struct passwd *get_unix_pw(void); int @@ -956,28 +955,48 @@ port_help(void) boolean authorize_wizard_mode(void) { - struct passwd *pw = get_unix_pw(); - - if (pw && sysopt.wizards && sysopt.wizards[0]) { + if (sysopt.wizards && sysopt.wizards[0]) { if (check_user_string(sysopt.wizards)) return TRUE; } - wiz_error_flag = TRUE; /* not being allowed into wizard mode */ + iflags.wiz_error_flag = TRUE; /* not being allowed into wizard mode */ return FALSE; } +/* similar to above, validate explore mode access */ +boolean +authorize_explore_mode(void) +{ +#ifdef SYSCF + if (sysopt.explorers && sysopt.explorers[0]) { + if (check_user_string(sysopt.explorers)) + return TRUE; + } + iflags.explore_error_flag = TRUE; /* not allowed into explore mode */ + return FALSE; +#else + return TRUE; /* if sysconf disabled, no restrictions on explore mode */ +#endif +} + static void wd_message(void) { - if (wiz_error_flag) { + if (iflags.wiz_error_flag) { if (sysopt.wizards && sysopt.wizards[0]) { char *tmp = build_english_list(sysopt.wizards); pline("Only user%s %s may access debug (wizard) mode.", strchr(sysopt.wizards, ' ') ? "s" : "", tmp); free(tmp); - } else + } else { + You("cannot access debug (wizard) mode."); + } + wizard = FALSE; /* (paranoia) */ + if (!iflags.explore_error_flag) pline("Entering explore/discovery mode instead."); - wizard = 0, discover = 1; /* (paranoia) */ + } else if (iflags.explore_error_flag) { + You("cannot access explore mode."); /* same as enter_explore_mode */ + discover = iflags.deferred_X = FALSE; /* (more paranoia) */ } else if (discover) You("are in non-scoring explore/discovery mode."); } diff --git a/sys/vms/vmsmain.c b/sys/vms/vmsmain.c index 7dd2536f9..4e7c6ab89 100644 --- a/sys/vms/vmsmain.c +++ b/sys/vms/vmsmain.c @@ -484,6 +484,13 @@ authorize_wizard_mode(void) return FALSE; } +/* similar to above, validate explore mode access */ +boolean +authorize_explore_mode(void) +{ + return TRUE; /* no restrictions on explore mode */ +} + static void wd_message(void) { diff --git a/sys/windows/windmain.c b/sys/windows/windmain.c index 5966615b4..0be7ef9cd 100644 --- a/sys/windows/windmain.c +++ b/sys/windows/windmain.c @@ -1021,6 +1021,13 @@ authorize_wizard_mode(void) return FALSE; } +/* similar to above, validate explore mode access */ +boolean +authorize_explore_mode(void) +{ + return TRUE; /* no restrictions on explore mode */ +} + #define PATH_SEPARATOR '\\' #if defined(WIN32) && !defined(WIN32CON)