in src/files.c [1788:2127]
HUP raw_printf("Perhaps there is an old %s around?",
lockname);
nesting--;
return FALSE;
}
break;
case ENOENT:
HUP raw_printf("Can't find file %s to lock!", filename);
nesting--;
return FALSE;
case EACCES:
HUP raw_printf("No write permission to lock %s!", filename);
nesting--;
return FALSE;
#ifdef VMS /* c__translate(vmsfiles.c) */
case EPERM:
/* could be misleading, but usually right */
HUP raw_printf("Can't lock %s due to directory protection.",
filename);
nesting--;
return FALSE;
#endif
case EROFS:
/* take a wild guess at the underlying cause */
HUP perror(lockname);
HUP raw_printf("Cannot lock %s.", filename);
HUP raw_printf(
"(Perhaps you are running NetHack from inside the distribution package?).");
nesting--;
return FALSE;
default:
HUP perror(lockname);
HUP raw_printf("Cannot lock %s for unknown reason (%d).",
filename, errnosv);
nesting--;
return FALSE;
}
#endif /* USE_FCNTL */
}
#endif /* UNIX || VMS */
#if (defined(AMIGA) || defined(WIN32) || defined(MSDOS)) \
&& !defined(USE_FCNTL)
#ifdef AMIGA
#define OPENFAILURE(fd) (!fd)
lockptr = 0;
#else
#define OPENFAILURE(fd) (fd < 0)
lockptr = -1;
#endif
while (--retryct && OPENFAILURE(lockptr)) {
#if defined(WIN32) && !defined(WIN_CE)
lockptr = sopen(lockname, O_RDWR | O_CREAT, SH_DENYRW, S_IWRITE);
#else
(void) DeleteFile(lockname); /* in case dead process was here first */
#ifdef AMIGA
lockptr = Open(lockname, MODE_NEWFILE);
#else
lockptr = open(lockname, O_RDWR | O_CREAT | O_EXCL, S_IWRITE);
#endif
#endif
if (OPENFAILURE(lockptr)) {
raw_printf("Waiting for access to %s. (%d retries left).",
filename, retryct);
Delay(50);
}
}
if (!retryct) {
raw_printf("I give up. Sorry.");
nesting--;
return FALSE;
}
#endif /* AMIGA || WIN32 || MSDOS */
return TRUE;
}
#ifdef VMS /* for unlock_file, use the unlink() routine in vmsunix.c */
#ifdef unlink
#undef unlink
#endif
#define unlink(foo) vms_unlink(foo)
#endif
/* unlock file, which must be currently locked by lock_file */
void
unlock_file(filename)
const char *filename;
{
#ifndef USE_FCNTL
char locknambuf[BUFSZ];
const char *lockname;
#endif
if (nesting == 1) {
#ifdef USE_FCNTL
sflock.l_type = F_UNLCK;
if (lockfd >= 0) {
if (fcntl(lockfd, F_SETLK, &sflock) == -1)
HUP raw_printf("Can't remove fcntl lock on %s.", filename);
(void) close(lockfd), lockfd = -1;
}
#else
lockname = make_lockname(filename, locknambuf);
#ifndef NO_FILE_LINKS /* LOCKDIR should be subsumed by LOCKPREFIX */
lockname = fqname(lockname, LOCKPREFIX, 2);
#endif
#if defined(UNIX) || defined(VMS)
if (unlink(lockname) < 0)
HUP raw_printf("Can't unlink %s.", lockname);
#ifdef NO_FILE_LINKS
(void) nhclose(lockfd), lockfd = -1;
#endif
#endif /* UNIX || VMS */
#if defined(AMIGA) || defined(WIN32) || defined(MSDOS)
if (lockptr)
Close(lockptr);
DeleteFile(lockname);
lockptr = 0;
#endif /* AMIGA || WIN32 || MSDOS */
#endif /* USE_FCNTL */
}
nesting--;
}
/* ---------- END FILE LOCKING HANDLING ----------- */
/* ---------- BEGIN CONFIG FILE HANDLING ----------- */
const char *default_configfile =
#ifdef UNIX
".nethackrc";
#else
#if defined(MAC) || defined(__BEOS__)
"NetHack Defaults";
#else
#if defined(MSDOS) || defined(WIN32)
CONFIG_FILE;
#else
"NetHack.cnf";
#endif
#endif
#endif
/* used for messaging */
char configfile[BUFSZ];
#ifdef MSDOS
/* conflict with speed-dial under windows
* for XXX.cnf file so support of NetHack.cnf
* is for backward compatibility only.
* Preferred name (and first tried) is now defaults.nh but
* the game will try the old name if there
* is no defaults.nh.
*/
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
STATIC_OVL FILE *
fopen_config_file(filename, src)
const char *filename;
int src;
{
FILE *fp;
#if defined(UNIX) || defined(VMS)
char tmp_config[BUFSZ];
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 && *filename) {
set_configfile_name(filename);
#ifdef UNIX
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).", configfile, errno);
wait_synch();
/* fall through to standard names */
} else
#endif
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).",
configfile, errno);
wait_synch();
#endif
}
}
/* fall through to standard names */
return (FILE *) 0; /* NLE: Stop here, don't read .nethackrc etc. */
#if defined(MICRO) || defined(MAC) || defined(__BEOS__) || defined(WIN32)
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
set_configfile_name(fqname(backward_compat_configfile, CONFIGPREFIX, 0));
if ((fp = fopenp(configfile, "r")) != (FILE *) 0) {
return fp;
} else if (strcmp(backward_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
/* no punctuation, so might be a logical name */
set_configfile_name("nethackini");
if ((fp = fopenp(configfile, "r")) != (FILE *) 0)
return fp;
set_configfile_name("sys$login:nethack.ini");
if ((fp = fopenp(configfile, "r")) != (FILE *) 0)
return fp;
envp = nh_getenv("HOME");
if (!envp || !*envp)
Strcpy(tmp_config, "NetHack.cnf");
else
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");
if (!envp)
Strcpy(tmp_config, ".nethackrc");
else
Sprintf(tmp_config, "%s/%s", envp, ".nethackrc");
set_configfile_name(tmp_config);
if ((fp = fopenp(configfile, "r")) != (FILE *) 0)
return fp;
#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");
set_configfile_name(tmp_config);
if ((fp = fopenp(configfile, "r")) != (FILE *) 0)
return fp;
/* may be easier for user to edit if filename has '.txt' suffix */
Sprintf(tmp_config, "%s/%s", envp,
"Library/Preferences/NetHack Defaults.txt");
set_configfile_name(tmp_config);
if ((fp = fopenp(configfile, "r")) != (FILE *) 0)
return fp;
}
#endif /*__APPLE__*/
if (errno != ENOENT) {
const char *details;
/* 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).",
configfile, details, errno);
wait_synch();
}
#endif /* !VMS => Unix */
#endif /* !(MICRO || MAC || __BEOS__ || WIN32) */
return (FILE *) 0;
}
/*
* Retrieve a list of integers from buf into a uchar array.
*
* NOTE: zeros are inserted unless modlist is TRUE, in which case the list
* location is unchanged. Callers must handle zeros if modlist is FALSE.
*/
STATIC_OVL int
get_uchars(bufp, list, modlist, size, name)
char *bufp; /* current pointer */
uchar *list; /* return list */
boolean modlist; /* TRUE: list is being modified in place */
int size; /* return list size */
const char *name; /* name of option for error message */
{
unsigned int num = 0;
int count = 0;
boolean havenum = FALSE;
while (1) {
switch (*bufp) {
case ' ':
case '\0':
case '\t':
case '\n':
if (havenum) {