FS2_Open
Open source remastering of the Freespace 2 engine
osregistry_unix.cpp
Go to the documentation of this file.
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 
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 
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 
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 
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 
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 
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 
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 
405 
406 // initialize the registry. setup default keys to use
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 
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 
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 
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 
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
const char * Osreg_app_name
#define vm_free(ptr)
Definition: pstypes.h:548
struct Section * next
int Os_reg_inited
GLsizei const GLfloat * value
Definition: Glext.h:5646
#define MAX_PATH
const char * Osreg_user_dir
const char * Osreg_company_name
int key
const char * detect_home(void)
Definition: osapi.cpp:101
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: Glext.h:7308
#define DEFAULT_SECTION
const char * os_config_read_string(const char *section, const char *name, const char *default_value)
const char * Osreg_title
#define nprintf(args)
Definition: pstypes.h:239
#define DIR_SEPARATOR_STR
Definition: pstypes.h:44
struct KeyValue * next
struct KeyValue KeyValue
sprintf(buf,"(%f,%f,%f)", v3->xyz.x, v3->xyz.y, v3->xyz.z)
#define vm_strdup(ptr)
Definition: pstypes.h:549
struct KeyValue * pairs
void os_config_write_uint(const char *section, const char *name, unsigned int value)
const char * Osreg_class_name
cfbp fp
Definition: cfile.cpp:1065
#define NOX(s)
Definition: pstypes.h:473
#define vm_malloc(size)
Definition: pstypes.h:547
GLuint const GLchar * name
Definition: Glext.h:5608
#define MAX_PATH_LEN
Definition: pstypes.h:325
#define vm_realloc(ptr, size)
Definition: pstypes.h:551
unsigned int os_config_read_uint(const char *section, const char *name, unsigned int default_value)
struct Profile Profile
struct Section Section
GLfloat GLfloat p
Definition: Glext.h:8373
GLenum GLsizei len
Definition: Glext.h:6283
void os_init_registry_stuff(const char *company, const char *app, const char *version)
void os_config_write_string(const char *section, const char *name, const char *value)
#define PROFILE_NAME
struct Section * sections
#define strcpy_s(...)
Definition: safe_strings.h:67