1 /*
2 * Copyright (C) Volition, Inc. 1999. All rights reserved.
3 *
4 * All source code herein is the property of Volition, Inc. You may not sell
5 * or otherwise commercially exploit the source or things you created based on the
6 * source.
7 *
8 */
9
10 #ifndef WIN32 // Goober5000
11
12 #include <string.h>
13 #include "globalincs/pstypes.h"
14 #include "osapi/osregistry.h"
15 #include "osapi/osapi.h"
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <ctype.h>
21
22 // ------------------------------------------------------------------------------------------------------------
23 // REGISTRY DEFINES/VARS
24 //
25
26 const char *Osreg_company_name = "Volition";
27 const char *Osreg_class_name = "FreeSpace2Class";
28
29 const char *Osreg_app_name = "FreeSpace2";
30 const char *Osreg_title = "FreeSpace 2";
31 #ifdef __APPLE__
32 const char *Osreg_user_dir = "Library/FS2_Open";
33 #else
34 const char *Osreg_user_dir = ".fs2_open";
35 #endif // __APPLE__
36 #define PROFILE_NAME "fs2_open.ini"
37
38 #define DEFAULT_SECTION "Default"
39
40 typedef struct KeyValue
41 {
42 char *key;
43 char *value;
44
45 struct KeyValue *next;
46 } KeyValue;
47
48 typedef struct Section
49 {
50 char *name;
51
52 struct KeyValue *pairs;
53 struct Section *next;
54 } Section;
55
56 typedef struct Profile
57 {
58 struct Section *sections;
59 } Profile;
60
61
62 // ------------------------------------------------------------------------------------------------------------
63 // REGISTRY FUNCTIONS
64 //
65
read_line_from_file(FILE * fp)66 static char *read_line_from_file(FILE *fp)
67 {
68 char *buf, *buf_start;
69 int buflen, len, eol;
70
71 buflen = 80;
72 buf = (char *)vm_malloc(buflen);
73 buf_start = buf;
74 eol = 0;
75
76 do {
77 if (buf == NULL) {
78 return NULL;
79 }
80
81 if (fgets(buf_start, 80, fp) == NULL) {
82 if (buf_start == buf) {
83 vm_free(buf);
84 return NULL;
85 } else {
86 *buf_start = 0;
87 return buf;
88 }
89 }
90
91 len = strlen(buf_start);
92
93 if (buf_start[len-1] == '\n') {
94 buf_start[len-1] = 0;
95 eol = 1;
96 } else {
97 buflen += 80;
98
99 buf = (char *)vm_realloc(buf, buflen);
100
101 /* be sure to skip over the proper amount of nulls */
102 buf_start = buf+(buflen-80)-(buflen/80)+1;
103 }
104 } while (!eol);
105
106 return buf;
107 }
108
trim_string(char * str)109 static char *trim_string(char *str)
110 {
111 char *ptr;
112 int len;
113
114 if (str == NULL)
115 return NULL;
116
117 /* kill any comment */
118 ptr = strchr(str, ';');
119 if (ptr)
120 *ptr = 0;
121 ptr = strchr(str, '#');
122 if (ptr)
123 *ptr = 0;
124
125 ptr = str;
126 len = strlen(str);
127 if (len > 0) {
128 ptr += len-1;
129 }
130
131 while ((ptr > str) && isspace(*ptr)) {
132 ptr--;
133 }
134
135 if (*ptr) {
136 ptr++;
137 *ptr = 0;
138 }
139
140 ptr = str;
141 while (*ptr && isspace(*ptr)) {
142 ptr++;
143 }
144
145 return ptr;
146 }
147
profile_read(char * file)148 static Profile *profile_read(char *file)
149 {
150 char fullname[MAX_PATH_LEN];
151 FILE *fp = NULL;
152 char *str;
153
154 snprintf(fullname, MAX_PATH_LEN, "%s%s%s%s%s", detect_home(), DIR_SEPARATOR_STR, Osreg_user_dir, DIR_SEPARATOR_STR, file);
155
156 fp = fopen(fullname, "rt");
157
158 if (fp == NULL)
159 return NULL;
160
161 Profile *profile = (Profile *)vm_malloc(sizeof(Profile));
162 profile->sections = NULL;
163
164 Section **sp_ptr = &(profile->sections);
165 Section *sp = NULL;
166
167 KeyValue **kvp_ptr = NULL;
168
169 while ((str = read_line_from_file(fp)) != NULL) {
170 char *ptr = trim_string(str);
171
172 if (*ptr == '[') {
173 ptr++;
174
175 char *pend = strchr(ptr, ']');
176 if (pend != NULL) {
177 // if (pend[1]) { /* trailing garbage! */ }
178
179 *pend = 0;
180
181 if (*ptr) {
182 sp = (Section *)vm_malloc(sizeof(Section));
183 sp->next = NULL;
184
185 sp->name = vm_strdup(ptr);
186 sp->pairs = NULL;
187
188 *sp_ptr = sp;
189 sp_ptr = &(sp->next);
190
191 kvp_ptr = &(sp->pairs);
192 } // else { /* null name! */ }
193 } // else { /* incomplete section name! */ }
194 } else {
195 if (*ptr) {
196 char *key = ptr;
197 char *value = NULL;
198
199 ptr = strchr(ptr, '=');
200 if (ptr != NULL) {
201 *ptr = 0;
202 ptr++;
203
204 value = ptr;
205 } // else { /* random garbage! */ }
206
207 if (key && *key && value /* && *value */) {
208 if (sp != NULL) {
209 KeyValue *kvp = (KeyValue *)vm_malloc(sizeof(KeyValue));
210
211 kvp->key = vm_strdup(key);
212 kvp->value = vm_strdup(value);
213
214 kvp->next = NULL;
215
216 *kvp_ptr = kvp;
217 kvp_ptr = &(kvp->next);
218 } // else { /* key/value with no section! */
219 } // else { /* malformed key/value entry! */ }
220 } // else it's just a comment or empty string
221 }
222
223 vm_free(str);
224 }
225
226 fclose(fp);
227
228 return profile;
229 }
230
profile_free(Profile * profile)231 static void profile_free(Profile *profile)
232 {
233 if (profile == NULL)
234 return;
235
236 Section *sp = profile->sections;
237 while (sp != NULL) {
238 Section *st = sp;
239 KeyValue *kvp = sp->pairs;
240
241 while (kvp != NULL) {
242 KeyValue *kvt = kvp;
243
244 vm_free(kvp->key);
245 vm_free(kvp->value);
246
247 kvp = kvp->next;
248 vm_free(kvt);
249 }
250
251 vm_free(sp->name);
252
253 sp = sp->next;
254 vm_free(st);
255 }
256
257 vm_free(profile);
258 }
259
profile_update(Profile * profile,const char * section,const char * key,const char * value)260 static Profile *profile_update(Profile *profile, const char *section, const char *key, const char *value)
261 {
262 if (profile == NULL) {
263 profile = (Profile *)vm_malloc(sizeof(Profile));
264
265 profile->sections = NULL;
266 }
267
268 KeyValue *kvp;
269
270 Section **sp_ptr = &(profile->sections);
271 Section *sp = profile->sections;
272
273 while (sp != NULL) {
274 if (strcmp(section, sp->name) == 0) {
275 KeyValue **kvp_ptr = &(sp->pairs);
276 kvp = sp->pairs;
277
278 while (kvp != NULL) {
279 if (strcmp(key, kvp->key) == 0) {
280 vm_free(kvp->value);
281
282 if (value == NULL) {
283 *kvp_ptr = kvp->next;
284
285 vm_free(kvp->key);
286 vm_free(kvp);
287 } else {
288 kvp->value = vm_strdup(value);
289 }
290
291 /* all done */
292 return profile;
293 }
294
295 kvp_ptr = &(kvp->next);
296 kvp = kvp->next;
297 }
298
299 if (value != NULL) {
300 /* key not found */
301 kvp = (KeyValue *)vm_malloc(sizeof(KeyValue));
302 kvp->next = NULL;
303 kvp->key = vm_strdup(key);
304 kvp->value = vm_strdup(value);
305 }
306
307 *kvp_ptr = kvp;
308
309 /* all done */
310 return profile;
311 }
312
313 sp_ptr = &(sp->next);
314 sp = sp->next;
315 }
316
317 /* section not found */
318 sp = (Section *)vm_malloc(sizeof(Section));
319 sp->next = NULL;
320 sp->name = vm_strdup(section);
321
322 kvp = (KeyValue *)vm_malloc(sizeof(KeyValue));
323 kvp->next = NULL;
324 kvp->key = vm_strdup(key);
325 kvp->value = vm_strdup(value);
326
327 sp->pairs = kvp;
328
329 *sp_ptr = sp;
330
331 return profile;
332 }
333
profile_get_value(Profile * profile,const char * section,const char * key)334 static char *profile_get_value(Profile *profile, const char *section, const char *key)
335 {
336 if (profile == NULL)
337 return NULL;
338
339 Section *sp = profile->sections;
340
341 while (sp != NULL) {
342 if (strcmp(section, sp->name) == 0) {
343 KeyValue *kvp = sp->pairs;
344
345 while (kvp != NULL) {
346 if (strcmp(key, kvp->key) == 0) {
347 return kvp->value;
348 }
349 kvp = kvp->next;
350 }
351 }
352
353 sp = sp->next;
354 }
355
356 /* not found */
357 return NULL;
358 }
359
profile_save(Profile * profile,char * file)360 static void profile_save(Profile *profile, char *file)
361 {
362 FILE *fp = NULL;
363 char tmp[MAX_PATH] = "";
364 char tmp2[MAX_PATH] = "";
365 char fullname[MAX_PATH_LEN];
366
367 if (profile == NULL)
368 return;
369
370 snprintf(fullname, MAX_PATH_LEN, "%s%s%s%s%s", detect_home(), DIR_SEPARATOR_STR, Osreg_user_dir, DIR_SEPARATOR_STR, file);
371
372 fp = fopen(fullname, "wt");
373
374 if (fp == NULL)
375 return;
376
377 Section *sp = profile->sections;
378
379 while (sp != NULL) {
380 sprintf(tmp, NOX("[%s]\n"), sp->name);
381 fputs(tmp, fp);
382
383 KeyValue *kvp = sp->pairs;
384 while (kvp != NULL) {
385 sprintf(tmp2, NOX("%s=%s\n"), kvp->key, kvp->value);
386 fputs(tmp2, fp);
387 kvp = kvp->next;
388 }
389
390 fprintf(fp, "\n");
391
392 sp = sp->next;
393 }
394
395 fclose(fp);
396 }
397
398 // os registry functions -------------------------------------------------------------
399
400 static char szCompanyName[128];
401 static char szAppName[128];
402 static char szAppVersion[128];
403
404 int Os_reg_inited = 0;
405
406 // initialize the registry. setup default keys to use
os_init_registry_stuff(const char * company,const char * app,const char * version)407 void os_init_registry_stuff(const char *company, const char *app, const char *version)
408 {
409 if(company){
410 strcpy_s( szCompanyName, company );
411 } else {
412 strcpy_s( szCompanyName, Osreg_company_name);
413 }
414
415 if(app){
416 strcpy_s( szAppName, app );
417 } else {
418 strcpy_s( szAppName, Osreg_app_name);
419 }
420
421 if(version){
422 strcpy_s( szAppVersion, version);
423 } else {
424 strcpy_s( szAppVersion, "1.0");
425 }
426
427 Os_reg_inited = 1;
428 }
429
430 static char tmp_string_data[1024];
431
os_config_read_string(const char * section,const char * name,const char * default_value)432 const char *os_config_read_string(const char *section, const char *name, const char *default_value)
433 {
434 nprintf(( "Registry", "os_config_read_string(): section = \"%s\", name = \"%s\", default value: \"%s\"\n",
435 (section) ? section : DEFAULT_SECTION, name, (default_value) ? default_value : NOX("NULL") ));
436
437 Profile *p = profile_read(PROFILE_NAME);
438
439 if (section == NULL)
440 section = DEFAULT_SECTION;
441
442 char *ptr = profile_get_value(p, section, name);
443
444 if (ptr != NULL) {
445 strncpy(tmp_string_data, ptr, 1023);
446 default_value = tmp_string_data;
447 }
448
449 profile_free(p);
450
451 return default_value;
452 }
453
os_config_read_uint(const char * section,const char * name,unsigned int default_value)454 unsigned int os_config_read_uint(const char *section, const char *name, unsigned int default_value)
455 {
456 Profile *p = profile_read(PROFILE_NAME);
457
458 if (section == NULL)
459 section = DEFAULT_SECTION;
460
461 char *ptr = profile_get_value(p, section, name);
462
463 if (ptr != NULL) {
464 default_value = atoi(ptr);
465 }
466
467 profile_free(p);
468
469 return default_value;
470 }
471
os_config_write_string(const char * section,const char * name,const char * value)472 void os_config_write_string(const char *section, const char *name, const char *value)
473 {
474 Profile *p = profile_read(PROFILE_NAME);
475
476 if (section == NULL)
477 section = DEFAULT_SECTION;
478
479 p = profile_update(p, section, name, value);
480 profile_save(p, PROFILE_NAME);
481 profile_free(p);
482 }
483
os_config_write_uint(const char * section,const char * name,unsigned int value)484 void os_config_write_uint(const char *section, const char *name, unsigned int value)
485 {
486 static char buf[21];
487
488 snprintf(buf, 20, "%u", value);
489
490 Profile *p = profile_read(PROFILE_NAME);
491
492 if (section == NULL)
493 section = DEFAULT_SECTION;
494
495 p = profile_update(p, section, name, buf);
496 profile_save(p, PROFILE_NAME);
497 profile_free(p);
498 }
499
500 #endif // Goober5000 - #ifndef WIN32
501