*/
/* fnameat.c */
extern char *fnameat(const char *, const char *);
+extern FILE *fopenat(const char *, const char *, const char *);
/* fsize.c */
extern int fsize(int);
extern int blksize(int);
static int read_custom_table_file(char *);
+/*
+ * Read builtin configuration tables.
+ * Return 0 on success, -1 on failure.
+ */
int
read_builtin_tables(void)
{
*/
for (ep = empfile; ep->name; ep++) {
if (!EF_IS_GAME_STATE(ep->uid) && ep->file) {
- if ((fp = fopen(ep->file, "r")) == NULL) {
+ if ((fp = fopenat(ep->file, "r", builtindir)) == NULL) {
fprintf(stderr, "Can't open %s for reading (%s)\n",
ep->file, strerror(errno));
return -1;
int lineno, res, n;
FILE *fp;
- if (!(fp = fopen(fname, "r"))) {
+ if (!(fp = fopenat(fname, "r", configdir))) {
fprintf(stderr, "Can't open config table %s for reading (%s)\n",
fname, strerror(errno));
return -1;
return fname[0] == '/';
#endif
}
+
+/*
+ * Open a stream like fopen(), optionally relative to a directory.
+ * This is exactly like fopen(), except FNAME is interpreted relative
+ * to DIR if that is neither null nor empty.
+ */
+FILE *
+fopenat(const char *fname, const char *mode, const char *dir)
+{
+ char *fnat;
+ FILE *fp;
+
+ fnat = fnameat(fname, dir);
+ if (!fnat)
+ return NULL;
+
+ fp = fopen(fnat, mode);
+
+ if (fnat != fname)
+ free(fnat);
+
+ return fp;
+}
if (emp_config(config_file) < 0)
exit(EXIT_FAILURE);
ef_init();
- if (chdir(configdir)) {
- fprintf(stderr, "Can't chdir to %s (%s)\n",
- configdir, strerror(errno));
- exit(EXIT_FAILURE);
- }
- if (chdir(builtindir)) {
- fprintf(stderr, "Can't chdir to %s (%s)\n",
- builtindir, strerror(errno));
- exit(EXIT_FAILURE);
- }
if (read_builtin_tables() < 0)
exit(EXIT_FAILURE);
- if (chdir(configdir)) {
- fprintf(stderr, "Can't chdir to %s (%s)\n",
- configdir, strerror(errno));
- exit(EXIT_FAILURE);
- }
if (read_custom_tables() < 0)
exit(EXIT_FAILURE);
if (chdir(gamedir)) {