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