SYSCF bits

(This covers some thing that Pat found and some things I found while working
on those.)
Unscramble duplicate use of GREPPATH and GDBPATH symbols.
Add some more info to config.h.
Make missing SYSCF_FILE a fatal error.
Make a parse error in SYSCF_FILE a fatal error.
Rename PANICTRACE_GLIBC (et al) to PANICTRACE_LIBC (et al) since FreeBSD
 and Mac OS X (at least) also implement the needed API.
Allow SYSCF_FILE to be unreadable by the user (for setgid installs).
If SYSCF, do NOT fall back to the compiled in WIZARD account.
Put WIZARD into sysopt and remove special cases in authorize_wizard_mode().
This commit is contained in:
keni
2012-01-27 20:15:31 +00:00
parent a871ad06e9
commit 1d219b4e1b
11 changed files with 147 additions and 82 deletions

View File

@@ -150,7 +150,8 @@
* 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)
@@ -164,6 +165,10 @@
*
* 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 */
@@ -177,6 +182,13 @@
# 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 */

View File

@@ -742,7 +742,7 @@ E void FDECL(unlock_file, (const char *));
#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);
@@ -2357,6 +2357,9 @@ E void NDECL(port_help);
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 ### */
@@ -2384,6 +2387,9 @@ E int NDECL(dosh);
# 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 ### */

View File

@@ -382,7 +382,10 @@ struct savefile_info {
#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

View File

@@ -25,8 +25,8 @@ struct sysopt {
char *gdbpath;
char *greppath;
int panictrace_gdb;
# ifdef PANICTRACE_GLIBC
int panictrace_glibc;
# ifdef PANICTRACE_LIBC
int panictrace_libc;
# endif
#endif
int seduce;

View File

@@ -77,13 +77,13 @@ extern void FDECL(nethack_exit,(int));
#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
@@ -91,17 +91,17 @@ extern void FDECL(nethack_exit,(int));
*/
# 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
@@ -109,7 +109,7 @@ static void NDECL(NH_abort);
# 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
@@ -163,19 +163,19 @@ static void
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 */
@@ -183,7 +183,7 @@ NH_abort()
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 */
@@ -194,9 +194,9 @@ NH_abort()
}
static boolean
NH_panictrace_glibc()
NH_panictrace_libc()
{
# ifdef PANICTRACE_GLIBC
# ifdef PANICTRACE_LIBC
void *bt[20];
size_t count;
char **info;
@@ -212,22 +212,22 @@ NH_panictrace_glibc()
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()
@@ -235,8 +235,8 @@ 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;

View File

@@ -183,7 +183,7 @@ STATIC_DCL void FDECL(docompress_file, (const char *,BOOLEAN_P));
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
@@ -1772,8 +1772,9 @@ const char *backward_compat_configfile = "nethack.cnf";
#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)
@@ -1781,16 +1782,18 @@ const char *filename;
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);
@@ -2148,16 +2151,16 @@ int src;
}
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);
@@ -2167,10 +2170,18 @@ int src;
}
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);
@@ -2377,7 +2388,7 @@ const char *filename;
}
#endif /* USER_SOUNDS */
void
boolean
read_config_file(filename, src)
const char *filename;
int src;
@@ -2397,8 +2408,9 @@ 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
@@ -2422,6 +2434,7 @@ OR: Forbid multiline stuff for alternate config sources.
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);
@@ -2445,7 +2458,7 @@ OR: Forbid multiline stuff for alternate config sources.
Strcpy(bones, levels);
# endif /* MFLOPPY */
#endif /* MICRO */
return;
return rv;
}
#ifdef WIZARD

View File

@@ -572,7 +572,13 @@ initoptions()
#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();

View File

@@ -4,16 +4,25 @@
#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 */
@@ -32,17 +41,17 @@ sys_early_init(){
#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

View File

@@ -41,12 +41,12 @@ MAXPLAYERS=10
# 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

View File

@@ -555,26 +555,15 @@ port_help()
}
#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;
@@ -585,17 +574,12 @@ wd_message()
{
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
@@ -675,4 +659,21 @@ get_unix_pw()
}
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*/

View File

@@ -371,3 +371,18 @@ gid_t
}
#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