fix #H4060 - sysconf is re-read if no config file
Config file handling remembers the name of the last config file read in order for options processing to use it in messages, but it was also reused as default config file name if user-supplied config file name failed access() test. So the SYSCF file became the default user config file after it was used. The config file handling was a real mess. This patch fixes it for Unix but there is a lot of scope for typos in the changes for other platforms. Testing is needed.
This commit is contained in:
@@ -288,6 +288,8 @@ using /? to look up something by name, supplying multiple spaces (with no
|
||||
add support for the 'altmeta' option to the 'what-does' command ('&' or '?f')
|
||||
when wielded weapon becomes untouchable (after alignment change or polymorph)
|
||||
hero could be 'blasted by its power' twice in succession
|
||||
at startup, if sysconf had been read but user's own config file couldn't be
|
||||
read, sysconf got processed again as if it contained user's options
|
||||
|
||||
|
||||
Fixes to Post-3.6.0 Problems that Were Exposed Via git Repository
|
||||
|
||||
@@ -185,8 +185,6 @@ E NEARDATA struct kinfo {
|
||||
} killer;
|
||||
|
||||
E long done_money;
|
||||
E const char *configfile;
|
||||
E char lastconfigfile[BUFSZ]; /* used for messaging */
|
||||
E NEARDATA char plname[PL_NSIZ];
|
||||
E NEARDATA char dogname[];
|
||||
E NEARDATA char catname[];
|
||||
|
||||
131
src/files.c
131
src/files.c
@@ -188,6 +188,7 @@ STATIC_DCL boolean FDECL(make_compressed_name, (const char *, char *));
|
||||
#ifndef USE_FCNTL
|
||||
STATIC_DCL char *FDECL(make_lockname, (const char *, char *));
|
||||
#endif
|
||||
STATIC_DCL void FDECL(set_configfile_name, (const char *));
|
||||
STATIC_DCL FILE *FDECL(fopen_config_file, (const char *, int));
|
||||
STATIC_DCL int FDECL(get_uchars, (FILE *, char *, char *, uchar *, BOOLEAN_P,
|
||||
int, const char *));
|
||||
@@ -1821,7 +1822,7 @@ const char *filename;
|
||||
|
||||
/* ---------- BEGIN CONFIG FILE HANDLING ----------- */
|
||||
|
||||
const char *configfile =
|
||||
const char *default_configfile =
|
||||
#ifdef UNIX
|
||||
".nethackrc";
|
||||
#else
|
||||
@@ -1837,7 +1838,7 @@ const char *configfile =
|
||||
#endif
|
||||
|
||||
/* used for messaging */
|
||||
char lastconfigfile[BUFSZ];
|
||||
char configfile[BUFSZ];
|
||||
|
||||
#ifdef MSDOS
|
||||
/* conflict with speed-dial under windows
|
||||
@@ -1850,6 +1851,16 @@ char lastconfigfile[BUFSZ];
|
||||
const char *backward_compat_configfile = "nethack.cnf";
|
||||
#endif
|
||||
|
||||
/* remember the name of the file we're accessing;
|
||||
if may be used in option reject messages */
|
||||
STATIC_OVL void
|
||||
set_configfile_name(fname)
|
||||
const char *fname;
|
||||
{
|
||||
(void) strncpy(configfile, fname, sizeof configfile - 1);
|
||||
configfile[sizeof configfile - 1] = '\0';
|
||||
}
|
||||
|
||||
#ifndef MFLOPPY
|
||||
#define fopenp fopen
|
||||
#endif
|
||||
@@ -1865,84 +1876,86 @@ int src;
|
||||
char *envp;
|
||||
#endif
|
||||
|
||||
if (src == SET_IN_SYS) {
|
||||
/* SYSCF_FILE; if we can't open it, caller will bail */
|
||||
if (filename && *filename) {
|
||||
set_configfile_name(fqname(filename, SYSCONFPREFIX, 0));
|
||||
fp = fopenp(configfile, "r");
|
||||
} else
|
||||
fp = (FILE *) 0;
|
||||
return fp;
|
||||
}
|
||||
/* If src != SET_IN_SYS, "filename" is an environment variable, so it
|
||||
* should hang around. If set, it is expected to be a full path name
|
||||
* (if relevant) */
|
||||
if (filename) {
|
||||
* (if relevant)
|
||||
*/
|
||||
if (filename && *filename) {
|
||||
set_configfile_name(filename);
|
||||
#ifdef UNIX
|
||||
if ((src != SET_IN_SYS) && access(filename, 4) == -1) {
|
||||
/* 4 is R_OK on newer systems */
|
||||
if (access(configfile, 4) == -1) { /* 4 is R_OK on newer systems */
|
||||
/* nasty sneaky attempt to read file through
|
||||
* NetHack's setuid permissions -- this is the only
|
||||
* place a file name may be wholly under the player's
|
||||
* control (but SYSCF_FILE is not under the player's
|
||||
* control so it's OK).
|
||||
*/
|
||||
raw_printf("Access to %s denied (%d).", filename, errno);
|
||||
raw_printf("Access to %s denied (%d).", configfile, errno);
|
||||
wait_synch();
|
||||
/* fall through to standard names */
|
||||
} else
|
||||
#endif
|
||||
#ifdef PREFIXES_IN_USE
|
||||
if (src == SET_IN_SYS) {
|
||||
(void) strncpy(lastconfigfile, fqname(filename, SYSCONFPREFIX, 0),
|
||||
BUFSZ - 1);
|
||||
} else
|
||||
#endif
|
||||
/* always honor sysconf first before anything else */
|
||||
(void) strncpy(lastconfigfile, filename, BUFSZ - 1);
|
||||
lastconfigfile[BUFSZ - 1] = '\0';
|
||||
if ((fp = fopenp(lastconfigfile, "r")) != (FILE *) 0)
|
||||
return fp;
|
||||
if ((fp = fopenp(filename, "r")) != (FILE *) 0) {
|
||||
if ((fp = fopenp(configfile, "r")) != (FILE *) 0) {
|
||||
return fp;
|
||||
#if defined(UNIX) || defined(VMS)
|
||||
} else {
|
||||
/* access() above probably caught most problems for UNIX */
|
||||
raw_printf("Couldn't open requested config file %s (%d).",
|
||||
filename, errno);
|
||||
configfile, errno);
|
||||
wait_synch();
|
||||
/* fall through to standard names */
|
||||
#endif
|
||||
}
|
||||
}
|
||||
/* fall through to standard names */
|
||||
|
||||
#if defined(MICRO) || defined(MAC) || defined(__BEOS__) || defined(WIN32)
|
||||
if ((fp = fopenp(fqname(configfile, CONFIGPREFIX, 0), "r")) != (FILE *) 0)
|
||||
return fp;
|
||||
if ((fp = fopenp(configfile, "r")) != (FILE *) 0)
|
||||
set_configfile_name(fqname(default_configfile, CONFIGPREFIX, 0)):
|
||||
if ((fp = fopenp(configfile, "r")) != (FILE *) 0) {
|
||||
return fp;
|
||||
} else if (strcmp(default_configfile, configfile)) {
|
||||
set_configfile_name(default_configfile);
|
||||
if ((fp = fopenp(configfile, "r")) != (FILE *) 0)
|
||||
return fp;
|
||||
}
|
||||
#ifdef MSDOS
|
||||
if ((fp = fopenp(fqname(backward_compat_configfile, CONFIGPREFIX, 0),
|
||||
"r")) != (FILE *) 0)
|
||||
return fp;
|
||||
if ((fp = fopenp(backward_compat_configfile, "r")) != (FILE *) 0)
|
||||
set_configfile_name(fqname(backward_compat_configfile, CONFIGPREFIX, 0));
|
||||
if ((fp = fopenp(configfile, "r")) != (FILE *) 0) {
|
||||
return fp;
|
||||
} else if (strcmp(backwad_compat_configfile, configfile)) {
|
||||
set_configfile_name(backward_compat_configfile);
|
||||
if ((fp = fopenp(configfile, "r")) != (FILE *) 0)
|
||||
return fp;
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
/* constructed full path names don't need fqname() */
|
||||
#ifdef VMS
|
||||
(void) strncpy(lastconfigfile, fqname("nethackini", CONFIGPREFIX, 0),
|
||||
BUFSZ - 1);
|
||||
lastconfigfile[BUFSZ - 1] = '\0';
|
||||
if ((fp = fopenp(lastconfigfile, "r")) != (FILE *) 0) {
|
||||
/* no punctuation, so might be a logical name */
|
||||
set_configfile_name(fqname("nethackini", CONFIGPREFIX, 0));
|
||||
if ((fp = fopenp(configfile, "r")) != (FILE *) 0)
|
||||
return fp;
|
||||
}
|
||||
(void) strncpy(lastconfigfile, "sys$login:nethack.ini", BUFSZ - 1);
|
||||
lastconfigfile[BUFSZ - 1] = '\0';
|
||||
if ((fp = fopenp(lastconfigfile, "r")) != (FILE *) 0) {
|
||||
set_configfile_name("sys$login:nethack.ini");
|
||||
if ((fp = fopenp(configfile, "r")) != (FILE *) 0)
|
||||
return fp;
|
||||
}
|
||||
|
||||
envp = nh_getenv("HOME");
|
||||
if (!envp)
|
||||
if (!envp || !*envp)
|
||||
Strcpy(tmp_config, "NetHack.cnf");
|
||||
else
|
||||
Sprintf(tmp_config, "%s%s", envp, "NetHack.cnf");
|
||||
|
||||
(void) strncpy(lastconfigfile, tmp_config, BUFSZ - 1);
|
||||
lastconfigfile[BUFSZ - 1] = '\0';
|
||||
if ((fp = fopenp(tmp_config, "r")) != (FILE *) 0)
|
||||
Sprintf(tmp_config, "%s%s%s", envp,
|
||||
!index(":]>/", envp[strlen(envp) - 1]) ? "/" : "",
|
||||
"NetHack.cnf");
|
||||
set_configfile_name(tmp_config);
|
||||
if ((fp = fopenp(configfile, "r")) != (FILE *) 0)
|
||||
return fp;
|
||||
#else /* should be only UNIX left */
|
||||
envp = nh_getenv("HOME");
|
||||
@@ -1951,43 +1964,41 @@ int src;
|
||||
else
|
||||
Sprintf(tmp_config, "%s/%s", envp, ".nethackrc");
|
||||
|
||||
(void) strncpy(lastconfigfile, tmp_config, BUFSZ - 1);
|
||||
lastconfigfile[BUFSZ - 1] = '\0';
|
||||
if ((fp = fopenp(lastconfigfile, "r")) != (FILE *) 0)
|
||||
set_configfile_name(tmp_config);
|
||||
if ((fp = fopenp(configfile, "r")) != (FILE *) 0)
|
||||
return fp;
|
||||
#if defined(__APPLE__)
|
||||
#if defined(__APPLE__) /* UNIX+__APPLE__ => MacOSX */
|
||||
/* try an alternative */
|
||||
if (envp) {
|
||||
/* OSX-style configuration settings */
|
||||
Sprintf(tmp_config, "%s/%s", envp,
|
||||
"Library/Preferences/NetHack Defaults");
|
||||
(void) strncpy(lastconfigfile, tmp_config, BUFSZ - 1);
|
||||
lastconfigfile[BUFSZ - 1] = '\0';
|
||||
if ((fp = fopenp(lastconfigfile, "r")) != (FILE *) 0)
|
||||
set_configfile_name(tmp_config);
|
||||
if ((fp = fopenp(configfile, "r")) != (FILE *) 0)
|
||||
return fp;
|
||||
/* may be easier for user to edit if filename as '.txt' suffix */
|
||||
Sprintf(tmp_config, "%s/%s", envp,
|
||||
"Library/Preferences/NetHack Defaults.txt");
|
||||
(void) strncpy(lastconfigfile, tmp_config, BUFSZ - 1);
|
||||
lastconfigfile[BUFSZ - 1] = '\0';
|
||||
if ((fp = fopenp(lastconfigfile, "r")) != (FILE *) 0)
|
||||
set_configfile_name(tmp_config);
|
||||
if ((fp = fopenp(configfile, "r")) != (FILE *) 0)
|
||||
return fp;
|
||||
}
|
||||
#endif
|
||||
#endif /*__APPLE__*/
|
||||
if (errno != ENOENT) {
|
||||
const char *details;
|
||||
|
||||
/* e.g., problems when setuid NetHack can't search home
|
||||
* directory restricted to user */
|
||||
|
||||
/* e.g., problems when setuid NetHack can't search home
|
||||
directory restricted to user */
|
||||
#if defined(NHSTDC) && !defined(NOTSTDC)
|
||||
if ((details = strerror(errno)) == 0)
|
||||
#endif
|
||||
details = "";
|
||||
raw_printf("Couldn't open default config file %s %s(%d).",
|
||||
lastconfigfile, details, errno);
|
||||
configfile, details, errno);
|
||||
wait_synch();
|
||||
}
|
||||
#endif /* Unix */
|
||||
#endif
|
||||
#endif /* !VMS => Unix */
|
||||
#endif /* !(MICRO || MAC || __BEOS__ || WIN32) */
|
||||
return (FILE *) 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -420,6 +420,8 @@ static struct Comp_Opt {
|
||||
|
||||
#else /* use rest of file */
|
||||
|
||||
extern char configfile[]; /* for messages */
|
||||
|
||||
extern struct symparse loadsyms[];
|
||||
static boolean need_redraw; /* for doset() */
|
||||
|
||||
@@ -917,10 +919,10 @@ rejectoption(optname)
|
||||
const char *optname;
|
||||
{
|
||||
#ifdef MICRO
|
||||
pline("\"%s\" settable only from %s.", optname, lastconfigfile);
|
||||
pline("\"%s\" settable only from %s.", optname, configfile);
|
||||
#else
|
||||
pline("%s can be set only from NETHACKOPTIONS or %s.", optname,
|
||||
lastconfigfile);
|
||||
configfile);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -941,7 +943,7 @@ const char *opts;
|
||||
#endif
|
||||
|
||||
if (from_file)
|
||||
raw_printf("Bad syntax in OPTIONS in %s: %s%s.\n", lastconfigfile,
|
||||
raw_printf("Bad syntax in OPTIONS in %s: %s%s.\n", configfile,
|
||||
#ifdef WIN32
|
||||
"\n",
|
||||
#else
|
||||
@@ -5318,7 +5320,7 @@ option_help()
|
||||
winid datawin;
|
||||
|
||||
datawin = create_nhwindow(NHW_TEXT);
|
||||
Sprintf(buf, "Set options as OPTIONS=<options> in %s", lastconfigfile);
|
||||
Sprintf(buf, "Set options as OPTIONS=<options> in %s", configfile);
|
||||
opt_intro[CONFIG_SLOT] = (const char *) buf;
|
||||
for (i = 0; opt_intro[i]; i++)
|
||||
putstr(datawin, 0, opt_intro[i]);
|
||||
|
||||
@@ -55,7 +55,7 @@ void ClearCol(struct Window *w);
|
||||
void
|
||||
EditColor()
|
||||
{
|
||||
extern const char *configfile;
|
||||
extern char configfile[];
|
||||
int i, done = 0, okay = 0;
|
||||
long code, qual, class;
|
||||
register struct Gadget *gd, *dgad;
|
||||
|
||||
Reference in New Issue
Block a user