* If SYSCF is defined, the following configuration info is
* available in a global config space, with the compiled-in
* entries as defaults:
- * WIZARDS ( a value of * allows anyone to be wizard)
+ * WIZARDS (a value of * allows anyone to be wizard)
+ * (this does NOT default to compiled-in value)
* MAXPLAYERS (see MAX_NR_OF_PLAYERS above and nethack.sh)
* SUPPORT (how to get local support)(no default)
* RECOVER (how to recover a game at your site)(no default)
*
* The following options select how the config space is stored:
* SYSCF_FILE in the named file
+ *
+ * The following options pertain to crash reporting:
+ * GREPPATH (the path to the system grep(1) utility)
+ * GDBPATH (the path to the system gdb(1) program)
*/
#ifndef WIZARD /* allow for compile-time or Makefile changes */
# endif
#endif
+#ifndef GDBPATH
+# define GDBPATH "/usr/bin/gdb"
+#endif
+#ifndef GREPPATH
+# define GREPPATH "/bin/grep"
+#endif
+
#define LOGFILE "logfile" /* larger file for debugging purposes */
#define NEWS "news" /* the file containing the latest hack news */
#define PANICLOG "paniclog" /* log of panic and impossible events */
#ifdef USER_SOUNDS
E boolean FDECL(can_read_file, (const char *));
#endif
-E void FDECL(read_config_file, (const char *, int));
+E boolean FDECL(read_config_file, (const char *, int));
E void FDECL(check_recordfile, (const char *));
#if defined(WIZARD)
E void NDECL(read_wizkit);
E void FDECL(sethanguphandler, (void (*)(int)));
E boolean NDECL(authorize_wizard_mode);
E boolean FDECL(check_user_string, (char *));
+# ifdef SYSCF_FILE
+E void NDECL(assure_syscf_file);
+# endif
#endif /* UNIX */
/* ### unixtty.c ### */
# if defined(SHELL) || defined(DEF_PAGER) || defined(DEF_MAILREADER)
E int FDECL(child, (int));
# endif
+# ifdef PANICTRACE
+E boolean FDECL(file_exists, (const char *));
+# endif
#endif /* UNIX */
/* ### unixres.c ### */
#endif
/* The following are meaningless if PANICTRACE is not defined: */
#if defined(__linux__) && defined(__GLIBC__) && (__GLIBC__ >= 2)
-# define PANICTRACE_GLIBC
+# define PANICTRACE_LIBC
+#endif
+#if defined(MACOSX)
+# define PANICTRACE_LIBC
#endif
#ifdef UNIX
# define PANICTRACE_GDB
char *gdbpath;
char *greppath;
int panictrace_gdb;
-# ifdef PANICTRACE_GLIBC
- int panictrace_glibc;
+# ifdef PANICTRACE_LIBC
+ int panictrace_libc;
# endif
#endif
int seduce;
#ifdef PANICTRACE
# include <errno.h>
-# ifdef PANICTRACE_GLIBC
+# ifdef PANICTRACE_LIBC
# include <execinfo.h>
# endif
/* What do we try and in what order? Tradeoffs:
- * glibc: +no external programs required
- * -requires newish glibc
+ * libc: +no external programs required
+ * -requires newish libc/glibc
* -requires -rdynamic
* gdb: +gives more detailed information
* +works on more OS versions
*/
# ifdef SYSCF
# define SYSOPT_PANICTRACE_GDB sysopt.panictrace_gdb
-# ifdef PANICTRACE_GLIBC
-# define SYSOPT_PANICTRACE_GLIBC sysopt.panictrace_glibc
+# ifdef PANICTRACE_LIBC
+# define SYSOPT_PANICTRACE_LIBC sysopt.panictrace_libc
# else
-# define SYSOPT_PANICTRACE_GLIBC 0
+# define SYSOPT_PANICTRACE_LIBC 0
# endif
# else
# define SYSOPT_PANICTRACE_GDB (nh_getenv("NETHACK_USE_GDB")==0?0:2)
-# ifdef PANICTRACE_GLIBC
-# define SYSOPT_PANICTRACE_GLIBC 1
+# ifdef PANICTRACE_LIBC
+# define SYSOPT_PANICTRACE_LIBC 1
# else
-# define SYSOPT_PANICTRACE_GLIBC 0
+# define SYSOPT_PANICTRACE_LIBC 0
# endif
# endif
# ifndef NO_SIGNAL
static void FDECL(panictrace_handler, (int));
# endif
-static boolean NDECL(NH_panictrace_glibc);
+static boolean NDECL(NH_panictrace_libc);
static boolean NDECL(NH_panictrace_gdb);
# ifndef NO_SIGNAL
NH_abort()
{
int gdb_prio = SYSOPT_PANICTRACE_GDB;
- int glibc_prio = SYSOPT_PANICTRACE_GLIBC;
+ int libc_prio = SYSOPT_PANICTRACE_LIBC;
static boolean aborting = FALSE;
if(aborting) return;
aborting = TRUE;
# ifndef VMS
- if(gdb_prio == glibc_prio && gdb_prio > 0) gdb_prio++;
+ if(gdb_prio == libc_prio && gdb_prio > 0) gdb_prio++;
- if(gdb_prio > glibc_prio){
- NH_panictrace_gdb() || (glibc_prio && NH_panictrace_glibc());
+ if(gdb_prio > libc_prio){
+ NH_panictrace_gdb() || (libc_prio && NH_panictrace_libc());
} else {
- NH_panictrace_glibc() || (gdb_prio && NH_panictrace_gdb());
+ NH_panictrace_libc() || (gdb_prio && NH_panictrace_gdb());
}
# else /* VMS */
traceback and exit; 2 = show traceback and stay in debugger */
/* if (wizard && gdb_prio == 1) gdb_prio = 2; */
vms_traceback(gdb_prio);
- (void)glibc_prio; /* half-hearted attempt at lint suppression */
+ (void)libc_prio; /* half-hearted attempt at lint suppression */
# endif /* ?VMS */
}
static boolean
-NH_panictrace_glibc()
+NH_panictrace_libc()
{
-# ifdef PANICTRACE_GLIBC
+# ifdef PANICTRACE_LIBC
void *bt[20];
size_t count;
char **info;
return TRUE;
# else
return FALSE;
-# endif /* !PANICTRACE_GLIBC */
+# endif /* !PANICTRACE_LIBC */
}
+/*
+ * fooPATH file system path for foo
+ * fooVAR (possibly const) variable containing fooPATH
+ */
# ifdef PANICTRACE_GDB
# ifdef SYSCF
-# define GDBPATH sysopt.gdbpath
-# define GREPPATH sysopt.greppath
-# else
-# ifndef GDBPATH
-# define GDBPATH "/usr/bin/gdb"
-# endif
-# ifndef GREPPATH
-# define GREPPATH "/bin/grep"
-# endif
-# endif /* !SYSCF */
-# endif /* PANICTRACE_GDB */
+# define GDBVAR sysopt.gdbpath
+# define GREPVAR sysopt.greppath
+# else /* SYSCF */
+# define GDBVAR GDBPATH
+# define GREPVAR GREPPATH
+# endif /* SYSCF */
+# endif /* PANICTRACE_GDB */
static boolean
NH_panictrace_gdb()
# ifdef PANICTRACE_GDB
/* A (more) generic method to get a stack trace - invoke
* gdb on ourself. */
- char *gdbpath = GDBPATH;
- char *greppath = GREPPATH;
+ char *gdbpath = GDBVAR;
+ char *greppath = GREPVAR;
char buf[BUFSZ];
FILE *gdb;
STATIC_DCL boolean FDECL(make_compressed_name, (const char *, char *));
#endif
STATIC_DCL char *FDECL(make_lockname, (const char *,char *));
-STATIC_DCL FILE *FDECL(fopen_config_file, (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 *));
int FDECL(parse_config_line, (FILE *,char *,char *,char *,int));
#ifdef LOADSYMSETS
#endif
STATIC_OVL FILE *
-fopen_config_file(filename)
+fopen_config_file(filename, src)
const char *filename;
+int src;
{
FILE *fp;
#if defined(UNIX) || defined(VMS)
char *envp;
#endif
- /* "filename" is an environment variable, so it should hang around */
- /* if set, it is expected to be a full path name (if relevant) */
+ /* 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) {
#ifdef UNIX
- if (access(filename, 4) == -1) {
+ if ((src!=SET_IN_SYS) && access(filename, 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
+ * control (but SYSCF_FILE is not under the player's
+ * control so it's OK).
*/
raw_printf("Access to %s denied (%d).",
filename, errno);
}
sysopt.pointsmin = temp;
# ifdef PANICTRACE
-# ifdef PANICTRACE_GLIBC
+# ifdef PANICTRACE_LIBC
} else if (src == SET_IN_SYS &&
- match_varname(buf, "PANICTRACE_GLIBC", 16)) {
+ match_varname(buf, "PANICTRACE_LIBC", 15)) {
int temp = atoi(bufp);
if (temp < 0 || temp > 2) {
- raw_printf("Illegal value in PANICTRACE_GLIBC (not 0,1,2).");
+ raw_printf("Illegal value in PANICTRACE_LIBC (not 0,1,2).");
return 0;
}
- sysopt.panictrace_glibc = temp;
-# endif /* PANICTRACE_GLIBC */
+ sysopt.panictrace_libc = temp;
+# endif /* PANICTRACE_LIBC */
} else if (src == SET_IN_SYS &&
match_varname(buf, "PANICTRACE_GDB", 14)) {
int temp = atoi(bufp);
}
sysopt.panictrace_gdb = temp;
} else if ( (src==SET_IN_SYS) && match_varname(buf, "GDBPATH", 7)) {
+ if(!file_exists(bufp)){
+ raw_printf("File specified in GDBPATH does not exist.");
+ return 0;
+ }
if(sysopt.gdbpath) free(sysopt.gdbpath);
sysopt.gdbpath = (char*)alloc(strlen(bufp)+1);
Strcpy(sysopt.gdbpath, bufp);
} else if ( (src==SET_IN_SYS) && match_varname(buf, "GREPPATH", 7)) {
+ if(!file_exists(bufp)){
+ raw_printf("File specified in GREPPATH does not exist.");
+ return 0;
+ }
if(sysopt.greppath) free(sysopt.greppath);
sysopt.greppath = (char*)alloc(strlen(bufp)+1);
Strcpy(sysopt.greppath, bufp);
}
#endif /* USER_SOUNDS */
-void
+boolean
read_config_file(filename, src)
const char *filename;
int src;
#endif
char buf[4*BUFSZ];
FILE *fp;
+ boolean rv = TRUE; /* assume successful parse */
- if (!(fp = fopen_config_file(filename))) return;
+ if (!(fp = fopen_config_file(filename, src))) return FALSE;
#if defined(MICRO) || defined(WIN32)
# ifdef MFLOPPY
if (!parse_config_line(fp, buf, tmp_ramdisk, tmp_levels, src)) {
raw_printf("Bad option line: \"%.50s\"", buf);
wait_synch();
+ rv = FALSE;
}
}
(void) fclose(fp);
Strcpy(bones, levels);
# endif /* MFLOPPY */
#endif /* MICRO */
- return;
+ return rv;
}
#ifdef WIZARD
#ifdef SYSCF
/* someday there may be other SYSCF alternatives besides text file */
# ifdef SYSCF_FILE
- read_config_file(SYSCF_FILE, SET_IN_SYS);
+ /* If SYSCF_FILE is specified, it _must_ exist... */
+ assure_syscf_file();
+ /* ... and _must_ parse correctly. */
+ if(!read_config_file(SYSCF_FILE, SET_IN_SYS)){
+ raw_printf("Error(s) found in SYSCF_FILE, quitting.");
+ terminate(EXIT_FAILURE);
+ }
# endif
#endif
initoptions_finish();
#include "hack.h"
+/* for KR1ED config, WIZARD is 0 or 1 and WIZARD_NAME is a string;
+ for usual config, WIZARD is the string; forcing WIZARD_NAME to match it
+ eliminates conditional testing for which one to use in string ops */
+#ifndef KR1ED
+# undef WIZARD_NAME
+# define WIZARD_NAME WIZARD
+#endif
+
struct sysopt sysopt;
void
sys_early_init(){
sysopt.support = NULL;
sysopt.recover = NULL;
-#ifdef notyet
- /* replace use of WIZARD vs WIZARD_NAME vs KR1ED, by filling this in */
-#endif
+#ifdef SYSCF
sysopt.wizards = NULL;
+#else
+ sysopt.wizards = WIZARD_NAME;
+#endif
sysopt.shellers = NULL;
sysopt.maxplayers = 0; /* XXX eventually replace MAX_NR_OF_PLAYERS */
#ifdef PANICTRACE
/* panic options */
- sysopt.gdbpath = NULL;
- sysopt.greppath = NULL;
+ sysopt.gdbpath = strdup(GDBPATH);
+ sysopt.greppath = strdup(GREPPATH);
# ifdef BETA
sysopt.panictrace_gdb = 1;
-# ifdef PANICTRACE_GLIBC
- sysopt.panictrace_glibc = 2;
+# ifdef PANICTRACE_LIBC
+ sysopt.panictrace_libc = 2;
# endif
# else
sysopt.panictrace_gdb = 0;
-# ifdef PANICTRACE_GLIBC
- sysopt.panictrace_glibc = 0;
+# ifdef PANICTRACE_LIBC
+ sysopt.panictrace_libc = 0;
# endif
# endif
#endif
# Try to get more info in case of a program bug or crash. Using GDB can
# get more information and works on more systems but requires gdb be available;
-# using GLIBC only works if NetHack is linked with glibc. Both require
-# certain compilation options. See src/end.c and sys/unix/hints/* for
-# more information.
+# using LIBC only works if NetHack is linked with a libc that supports the
+# backtrace(3) API. Both require certain compilation options. See
+# src/end.c and sys/unix/hints/* for more information.
GDBPATH=/usr/bin/gdb
GREPPATH=/bin/grep
# Values are priorities: 0 - do not use this method, 1 - low priority,
# 2 - high priority. Non-zero priority methods are tried in order.
PANICTRACE_GDB=1
-PANICTRACE_GLIBC=2
+PANICTRACE_LIBC=2
}
#endif
-/* for KR1ED config, WIZARD is 0 or 1 and WIZARD_NAME is a string;
- for usual config, WIZARD is the string; forcing WIZARD_NAME to match it
- eliminates conditional testing for which one to use in string ops */
-#ifndef KR1ED
-# undef WIZARD_NAME
-# define WIZARD_NAME WIZARD
-#endif
-
/* validate wizard mode if player has requested access to it */
boolean
authorize_wizard_mode()
{
#ifdef WIZARD
struct passwd *pw = get_unix_pw();
-#ifdef SYSCF
if (pw && sysopt.wizards && sysopt.wizards[0]) {
if(check_user_string(sysopt.wizards)) return TRUE;
- } else
-#endif
- if (pw && !strcmp(pw->pw_name, WIZARD_NAME)) return TRUE;
+ }
#endif /* WIZARD */
wiz_error_flag = TRUE; /* not being allowed into wizard mode */
return FALSE;
{
if (wiz_error_flag) {
#ifdef WIZARD
-# ifdef SYSCF
if (sysopt.wizards && sysopt.wizards[0]) {
char *tmp = build_english_list(sysopt.wizards);
pline("Only user%s %s may access debug (wizard) mode.",
index(sysopt.wizards, ' ')?"s":"", tmp);
free(tmp);
} else
-# else
- pline("Only user \"%s\" may access debug (wizard) mode.",
- WIZARD_NAME);
-# endif
#else
pline("Debug mode is not available.");
#endif
}
return pw;
}
+
+#ifdef SYSCF_FILE
+void
+assure_syscf_file(){
+ /* All we really care about is the end result - can we read the file?
+ * So just check that directly. */
+ int fd;
+ fd = open(SYSCF_FILE, O_RDONLY);
+ if(fd >= 0){
+ /* readable */
+ close(fd);
+ return;
+ }
+ raw_printf("Unable to open SYSCF_FILE.\n");
+ exit(EXIT_FAILURE);
+}
+#endif
/*unixmain.c*/
}
#endif /* GETRES_SUPPORT */
+
+/* XXX should be ifdef PANICTRACE_GDB, but there's no such symbol yet */
+#ifdef PANICTRACE
+boolean
+file_exists(const char *path){
+ /* Just see if it's there - trying to figure out if we can actually
+ * execute it in all cases is too hard - we really just want to
+ * catch typos in SYSCF. */
+ struct stat sb;
+ if(stat(path, &sb)){
+ return FALSE;
+ }
+ return TRUE;
+}
+#endif