lol
1diff --git a/src/file.c b/src/file.c
2index d1d1982..1655f6f 100644
3--- a/src/file.c
4+++ b/src/file.c
5@@ -125,6 +125,8 @@ int hcompar(const void *, const void *);
6 int loadscores(char *);
7 static int parseline(char *, char **, char **);
8 void readconfig(void);
9+void mkconfig(char *filename);
10+void mkscore(char *filename);
11 static void readfile(char *, int);
12 static void setoptions(char *, char *, int);
13
14@@ -1125,7 +1127,7 @@ void
15 readconfig(void)
16 {
17 char *envhome;
18- char userhigh[MAXPATHLEN], userconf[MAXPATHLEN];
19+ char userhigh[MAXPATHLEN], userconf[MAXPATHLEN], confdir[MAXPATHLEN];
20 struct stat sb;
21
22 if (xsnprintf(ruledir, sizeof(ruledir), "%s", RULEDIR)) {
23@@ -1140,18 +1142,33 @@ readconfig(void)
24 readfile(CONFIGFILE, 1);
25
26 if ((envhome = getenv("HOME")) == NULL)
27- return;
28+ xerr(1, "readconfig: environment variable HOME not set");
29
30 if (xsnprintf(userconf, sizeof(userconf), "%s/.typespeed/config",
31- envhome))
32- return;
33+ envhome))
34+ xerr(1, "readconfig: string error");
35+ if (xsnprintf(userhigh, sizeof(userhigh), "%s/.typespeed/score",
36+ envhome))
37+ xerr(1, "readconfig: string error");
38
39 if (stat(userconf, &sb) || (sb.st_mode & S_IFMT) != S_IFREG)
40- return;
41-
42- if (xsnprintf(userhigh, sizeof(userhigh), "%s/.typespeed/score",
43- envhome))
44- return;
45+ {
46+ if (xsnprintf(confdir, sizeof(confdir), "%s/.typespeed",
47+ envhome))
48+ xerr(1, "readconfig: string error");
49+ if(stat(confdir, &sb) == -1)
50+ if(mkdir(confdir, S_IRWXU | S_IRWXG | S_IRWXO))
51+ xerr(1, "readconfig: could not create config directory %s",
52+ confdir);
53+ /* create the user configuration with default values */
54+ mkconfig(userconf);
55+ }
56+ /* check for the high score file */
57+ if (stat(userhigh, &sb) || (sb.st_mode & S_IFMT) != S_IFREG)
58+ {
59+ /* create a blank high score file */
60+ mkscore(userhigh);
61+ }
62
63 /*
64 * Open a user writable high score.
65@@ -1159,14 +1176,48 @@ readconfig(void)
66 * file. Protect system-wide high score file with group
67 * write permissions: privileged gid already dropped.
68 */
69- if (close(hfd) == -1)
70- xerr(1, "readconfig: close");
71- if ((hfd = open(userhigh, O_RDWR, 0)) == -1)
72+ if ((hfd = open(userhigh, O_RDWR)) == -1)
73 xerr(1, "readconfig: open: %s", userhigh);
74
75 readfile(userconf, 1);
76 }
77
78+#define DEFAULT_CONFIG "cheat = no\n" \
79+ "highorder = score cps tcps\n" \
80+ "ruledir = " RULEDIR "\n" \
81+ "worddir = " WORDDIR "\n"
82+
83+/*
84+ * Create the user configuration, with default values, at the given path.
85+ */
86+void
87+mkconfig(char *filename)
88+{
89+ int cfd;
90+
91+ if((cfd = open(filename, O_WRONLY | O_CREAT, S_IRWXU | S_IRWXG | S_IRWXO)) == -1)
92+ xerr(1, "mkconfig: open: %s", filename);
93+ if(write(cfd, DEFAULT_CONFIG, sizeof(DEFAULT_CONFIG)/sizeof(DEFAULT_CONFIG[0]) - 1) == -1)
94+ xerr(1, "mkconfig: write: %s", filename);
95+ if(close(cfd) == -1)
96+ xerr(1, "mkconfig: close: %s", filename);
97+}
98+
99+/*
100+ * Create the user high score file, which is just a blank file.
101+ */
102+void
103+mkscore(char *filename)
104+{
105+ int sfd;
106+ if((sfd = open(filename, O_WRONLY | O_CREAT, S_IRWXU | S_IRWXG | S_IRWXO)) == -1)
107+ xerr(1, "mkscore: open: %s", filename);
108+ if(write(sfd, "", 0) == -1)
109+ xerr(1, "mkconfig: write: %s", filename);
110+ if(close(sfd) == -1)
111+ xerr(1, "mkconfig: close: %s", filename);
112+}
113+
114 /*
115 * Function used to open configuration and game rule files and to
116 * set options with function setoptions.
117diff --git a/src/typespeed.c b/src/typespeed.c
118index 7ac5ee2..77e9acb 100644
119--- a/src/typespeed.c
120+++ b/src/typespeed.c
121@@ -319,8 +319,13 @@ main(int argc, char **argv)
122 progname++;
123
124 /* just open high score file while being setgid games */
125- if ((hfd = open(HIGHFILE, O_RDWR, 0)) == -1)
126- xerr(1, "main: open: %s", HIGHFILE);
127+ /*
128+ * For NixOS, a global high score file doesn't make sense, so we just comment
129+ * this out. A high score file in the user's home directory will be opened
130+ * later in readconfig().
131+ */
132+/* if ((hfd = open(HIGHFILE, O_RDWR, 0)) == -1)
133+ xerr(1, "main: open: %s", HIGHFILE); */
134
135 #ifndef WIN32
136 /* drop privileges */
137@@ -348,9 +353,9 @@ main(int argc, char **argv)
138 #endif /* WIN32 */
139
140 /* check file descriptors for consistency */
141- if (hfd == STDIN_FILENO || hfd == STDOUT_FILENO ||
142+/* if (hfd == STDIN_FILENO || hfd == STDOUT_FILENO ||
143 hfd == STDERR_FILENO)
144- exit(1);
145+ exit(1); */
146 if (!isatty(STDIN_FILENO) || !isatty(STDOUT_FILENO) ||
147 !isatty(STDERR_FILENO))
148 xerrx(1, "not fully connected to a terminal");