]> icculus.org git repositories - taylor/freespace2.git/blob - src/osapi/osregistry-unix.cpp
Userdir patch from Taylor Richards
[taylor/freespace2.git] / src / osapi / osregistry-unix.cpp
1 #include "pstypes.h"
2 #include "osregistry.h"
3 #include "cfile.h"
4 #undef malloc
5 #undef free
6 #undef strdup
7
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <ctype.h>
12
13 char *Osreg_company_name = "Volition";
14 char *Osreg_class_name = "Freespace2Class";
15 #if defined(FS2_DEMO)
16 char *Osreg_app_name = "FreeSpace2Demo";
17 char *Osreg_title = "Freespace 2 Demo";
18 char *Osreg_user_dir = ".freespace_demo";
19 #define PROFILE_NAME "FreeSpace2Demo.ini"
20 #elif defined(OEM_BUILD)
21 char *Osreg_app_name = "FreeSpace2OEM";
22 char *Osreg_title = "Freespace 2 OEM";
23 #define PROFILE_NAME "FreeSpace2OEM.ini"
24 #else
25 char *Osreg_app_name = "FreeSpace2";
26 char *Osreg_title = "Freespace 2";
27 char *Osreg_user_dir = ".freespace2";
28 #define PROFILE_NAME "FreeSpace2.ini"
29 #endif
30
31 #define DEFAULT_SECTION "Default"
32
33 typedef struct KeyValue
34 {
35         char *key;
36         char *value;
37         
38         struct KeyValue *next;
39 } KeyValue;
40
41 typedef struct Section
42 {
43         char *name;
44         
45         struct KeyValue *pairs;
46         struct Section *next;
47 } Section;
48         
49 typedef struct Profile
50 {
51         struct Section *sections;
52 } Profile;
53
54 static char *read_line_from_file(CFILE *fp)
55 {
56         char *buf, *buf_start;
57         int buflen, len, eol;
58         
59         buflen = 80;
60         buf = (char *)malloc(buflen);
61         buf_start = buf;
62         eol = 0;
63         
64         do {
65                 if (buf == NULL) {
66                         return NULL;
67                 }
68                 
69                 if (cfgets(buf_start, 80, fp) == NULL) {
70                         if (buf_start == buf) {
71                                 free(buf);
72                                 return NULL;
73                         } else {
74                                 *buf_start = 0;
75                                 return buf;
76                         }
77                 }
78                 
79                 len = strlen(buf_start);
80                 
81                 if (buf_start[len-1] == '\n') {
82                         buf_start[len-1] = 0;
83                         eol = 1;
84                 } else {
85                         buflen += 80;
86                         
87                         buf = (char *)realloc(buf, buflen);
88                         
89                         /* be sure to skip over the proper amount of nulls */
90                         buf_start = buf+(buflen-80)-(buflen/80)+1;
91                 }
92         } while (!eol);
93         
94         return buf;
95 }
96
97 static char *trim_string(char *str)
98 {
99         char *ptr;
100         int len;
101         
102         if (str == NULL)
103                 return NULL;
104         
105         /* kill any comment */
106         ptr = strchr(str, ';');
107         if (ptr)
108                 *ptr = 0;
109         ptr = strchr(str, '#');
110         if (ptr)
111                 *ptr = 0;
112         
113         ptr = str;
114         len = strlen(str);
115         if (len > 0) {
116                 ptr += len-1;
117         }
118         
119         while ((ptr > str) && isspace(*ptr)) {
120                 ptr--;
121         }
122         
123         if (*ptr) {
124                 ptr++;
125                 *ptr = 0;
126         }
127         
128         ptr = str;
129         while (*ptr && isspace(*ptr)) {
130                 ptr++;
131         }
132         
133         return ptr;
134 }
135
136 static Profile *profile_read(char *file)
137 {
138         CFILE *fp = cfopen(file, "rt", CFILE_NORMAL, CF_TYPE_ROOT);
139         if (fp == NULL)
140                 return NULL;
141         
142         Profile *profile = (Profile *)malloc(sizeof(Profile));
143         profile->sections = NULL;
144         
145         Section **sp_ptr = &(profile->sections);
146         Section *sp = NULL;
147
148         KeyValue **kvp_ptr = NULL;
149                 
150         char *str;
151         while ((str = read_line_from_file(fp)) != NULL) {
152                 char *ptr = trim_string(str);
153                 
154                 if (*ptr == '[') {
155                         ptr++;
156                         
157                         char *pend = strchr(ptr, ']');
158                         if (pend != NULL) {
159                                 // if (pend[1]) { /* trailing garbage! */ }
160                                 
161                                 *pend = 0;                              
162                                 
163                                 if (*ptr) {
164                                         sp = (Section *)malloc(sizeof(Section));
165                                         sp->next = NULL;
166                                 
167                                         sp->name = strdup(ptr);
168                                         sp->pairs = NULL;
169                                         
170                                         *sp_ptr = sp;
171                                         sp_ptr = &(sp->next);
172                                         
173                                         kvp_ptr = &(sp->pairs);
174                                 } // else { /* null name! */ }
175                         } // else { /* incomplete section name! */ }
176                 } else {
177                         if (*ptr) {
178                                 char *key = ptr;
179                                 char *value = NULL;
180                                 
181                                 ptr = strchr(ptr, '=');
182                                 if (ptr != NULL) {
183                                         *ptr = 0;
184                                         ptr++;
185                                         
186                                         value = ptr;
187                                 } // else { /* random garbage! */ }
188                                 
189                                 if (key && *key && value /* && *value */) {
190                                         if (sp != NULL) {
191                                                 KeyValue *kvp = (KeyValue *)malloc(sizeof(KeyValue));
192                                                 
193                                                 kvp->key = strdup(key);
194                                                 kvp->value = strdup(value);
195                                                 
196                                                 kvp->next = NULL;
197                                                 
198                                                 *kvp_ptr = kvp;
199                                                 kvp_ptr = &(kvp->next);
200                                         } // else { /* key/value with no section! */
201                                 } // else { /* malformed key/value entry! */ }
202                         } // else it's just a comment or empty string
203                 }
204                                 
205                 free(str);
206         }
207         
208         cfclose(fp);
209
210         return profile;
211 }
212
213 static void profile_free(Profile *profile)
214 {
215         if (profile == NULL)
216                 return;
217                 
218         Section *sp = profile->sections;
219         while (sp != NULL) {
220                 Section *st = sp;
221                 KeyValue *kvp = sp->pairs;
222                 
223                 while (kvp != NULL) {
224                         KeyValue *kvt = kvp;
225                         
226                         free(kvp->key);
227                         free(kvp->value);
228                         
229                         kvp = kvp->next;
230                         free(kvt);
231                 }
232                 
233                 free(sp->name);
234                 
235                 sp = sp->next;
236                 free(st);
237         }
238         
239         free(profile);
240 }
241
242 static Profile *profile_update(Profile *profile, char *section, char *key, char *value)
243 {
244         if (profile == NULL) {
245                 profile = (Profile *)malloc(sizeof(Profile));
246                 
247                 profile->sections = NULL;
248         }
249         
250         KeyValue *kvp;
251         
252         Section **sp_ptr = &(profile->sections);
253         Section *sp = profile->sections;
254         while (sp != NULL) {
255                 if (strcmp(section, sp->name) == 0) {
256                         KeyValue **kvp_ptr = &(sp->pairs);
257                         kvp = sp->pairs;
258                         
259                         while (kvp != NULL) {
260                                 if (strcmp(key, kvp->key) == 0) {
261                                         free(kvp->value);
262                                         
263                                         if (value == NULL) {
264                                                 *kvp_ptr = kvp->next;
265                                                 
266                                                 free(kvp->key);
267                                                 free(kvp);
268                                         } else {
269                                                 kvp->value = strdup(value);
270                                         }
271                                         
272                                         /* all done */
273                                         return profile;
274                                 }
275                                 
276                                 kvp_ptr = &(kvp->next);
277                                 kvp = kvp->next;
278                         }
279                         
280                         if (value != NULL) {
281                                 /* key not found */
282                                 kvp = (KeyValue *)malloc(sizeof(KeyValue));
283                                 kvp->next = NULL;
284                                 kvp->key = strdup(key);
285                                 kvp->value = strdup(value);
286                         }
287                                         
288                         *kvp_ptr = kvp;
289                         
290                         /* all done */
291                         return profile;
292                 }
293                 
294                 sp_ptr = &(sp->next);
295                 sp = sp->next;
296         }
297         
298         /* section not found */
299         sp = (Section *)malloc(sizeof(Section));
300         sp->next = NULL;
301         sp->name = strdup(section);
302         
303         kvp = (KeyValue *)malloc(sizeof(KeyValue));
304         kvp->next = NULL;
305         kvp->key = strdup(key);
306         kvp->value = strdup(value);
307         
308         sp->pairs = kvp;
309         
310         *sp_ptr = sp;
311         
312         return profile;
313 }
314
315 static char *profile_get_value(Profile *profile, char *section, char *key)
316 {
317         if (profile == NULL)
318                 return NULL;
319         
320         Section *sp = profile->sections;
321         while (sp != NULL) {
322                 if (strcmp(section, sp->name) == 0) {
323                         KeyValue *kvp = sp->pairs;
324                 
325                         while (kvp != NULL) {
326                                 if (strcmp(key, kvp->key) == 0) {
327                                         return kvp->value;
328                                 }
329                                 kvp = kvp->next;
330                         }
331                 }
332                 
333                 sp = sp->next;
334         }
335         
336         /* not found */
337         return NULL;
338 }
339
340 static void profile_save(Profile *profile, char *file)
341 {
342         CFILE *fp;
343         
344         char tmp[MAX_PATH] = "";
345         char tmp2[MAX_PATH] = "";
346         
347         if (profile == NULL)
348                 return;
349                 
350         fp = cfopen(file, "wt", CFILE_NORMAL, CF_TYPE_ROOT);
351         if (fp == NULL)
352                 return;
353         
354         Section *sp = profile->sections;
355         while (sp != NULL) {
356                 sprintf(tmp, NOX("[%s]\n"), sp->name);
357                 cfputs(tmp, fp);
358                 
359                 KeyValue *kvp = sp->pairs;
360                 while (kvp != NULL) {
361                         sprintf(tmp2, NOX("%s=%s\n"), kvp->key, kvp->value);
362                         cfputs(tmp2, fp);
363                         kvp = kvp->next;
364                 }
365                 
366                 cfwrite_char('\n', fp);
367                 
368                 sp = sp->next;
369         }
370         
371         cfclose(fp);
372 }
373
374 static char tmp_string_data[1024];
375
376 char *os_config_read_string(char *section, char *name, char *default_value)
377 {
378         Profile *p = profile_read(PROFILE_NAME);
379         
380         if (section == NULL)
381                 section = DEFAULT_SECTION;
382                 
383         char *ptr = profile_get_value(p, section, name);
384         if (ptr != NULL) {
385                 strncpy(tmp_string_data, ptr, 1023);
386                 default_value = tmp_string_data;
387         }
388         
389         profile_free(p);
390         
391         return default_value;
392 }
393
394 unsigned int os_config_read_uint(char *section, char *name, unsigned int default_value)
395 {
396         Profile *p = profile_read(PROFILE_NAME);
397         
398         if (section == NULL)
399                 section = DEFAULT_SECTION;
400                 
401         char *ptr = profile_get_value(p, section, name);
402         if (ptr != NULL) {
403                 default_value = atoi(ptr);
404         }
405         
406         profile_free(p);
407         
408         return default_value;
409 }
410
411 void os_config_write_string(char *section, char *name, char *value)
412 {
413         Profile *p = profile_read(PROFILE_NAME);
414         
415         if (section == NULL)
416                 section = DEFAULT_SECTION;
417                 
418         p = profile_update(p, section, name, value);
419         profile_save(p, PROFILE_NAME);
420         profile_free(p);        
421 }
422
423 void os_config_write_uint(char *section, char *name, unsigned int value)
424 {
425         static char buf[21];
426         
427         snprintf(buf, 20, "%u", value);
428         
429         Profile *p = profile_read(PROFILE_NAME);
430         
431         if (section == NULL)
432                 section = DEFAULT_SECTION;
433         
434         p = profile_update(p, section, name, buf);
435         profile_save(p, PROFILE_NAME);
436         profile_free(p);
437 }