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