mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-10 12:41:35 -10:00
git-svn-id: svn://svn.icculus.org/fs2open/trunk/fs2_open@9815 387891d4-d844-0410-90c0-e4c51a9137d3
501 lines
9.4 KiB
C++
501 lines
9.4 KiB
C++
/*
|
|
* Copyright (C) Volition, Inc. 1999. All rights reserved.
|
|
*
|
|
* All source code herein is the property of Volition, Inc. You may not sell
|
|
* or otherwise commercially exploit the source or things you created based on the
|
|
* source.
|
|
*
|
|
*/
|
|
|
|
#ifndef WIN32 // Goober5000
|
|
|
|
#include <string.h>
|
|
#include "globalincs/pstypes.h"
|
|
#include "osapi/osregistry.h"
|
|
#include "osapi/osapi.h"
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
|
|
// ------------------------------------------------------------------------------------------------------------
|
|
// REGISTRY DEFINES/VARS
|
|
//
|
|
|
|
const char *Osreg_company_name = "Volition";
|
|
const char *Osreg_class_name = "FreeSpace2Class";
|
|
|
|
const char *Osreg_app_name = "FreeSpace2";
|
|
const char *Osreg_title = "FreeSpace 2";
|
|
#ifdef __APPLE__
|
|
const char *Osreg_user_dir = "Library/FS2_Open";
|
|
#else
|
|
const char *Osreg_user_dir = ".fs2_open";
|
|
#endif // __APPLE__
|
|
#define PROFILE_NAME "fs2_open.ini"
|
|
|
|
#define DEFAULT_SECTION "Default"
|
|
|
|
typedef struct KeyValue
|
|
{
|
|
char *key;
|
|
char *value;
|
|
|
|
struct KeyValue *next;
|
|
} KeyValue;
|
|
|
|
typedef struct Section
|
|
{
|
|
char *name;
|
|
|
|
struct KeyValue *pairs;
|
|
struct Section *next;
|
|
} Section;
|
|
|
|
typedef struct Profile
|
|
{
|
|
struct Section *sections;
|
|
} Profile;
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------------------
|
|
// REGISTRY FUNCTIONS
|
|
//
|
|
|
|
static char *read_line_from_file(FILE *fp)
|
|
{
|
|
char *buf, *buf_start;
|
|
int buflen, len, eol;
|
|
|
|
buflen = 80;
|
|
buf = (char *)vm_malloc(buflen);
|
|
buf_start = buf;
|
|
eol = 0;
|
|
|
|
do {
|
|
if (buf == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if (fgets(buf_start, 80, fp) == NULL) {
|
|
if (buf_start == buf) {
|
|
vm_free(buf);
|
|
return NULL;
|
|
} else {
|
|
*buf_start = 0;
|
|
return buf;
|
|
}
|
|
}
|
|
|
|
len = strlen(buf_start);
|
|
|
|
if (buf_start[len-1] == '\n') {
|
|
buf_start[len-1] = 0;
|
|
eol = 1;
|
|
} else {
|
|
buflen += 80;
|
|
|
|
buf = (char *)vm_realloc(buf, buflen);
|
|
|
|
/* be sure to skip over the proper amount of nulls */
|
|
buf_start = buf+(buflen-80)-(buflen/80)+1;
|
|
}
|
|
} while (!eol);
|
|
|
|
return buf;
|
|
}
|
|
|
|
static char *trim_string(char *str)
|
|
{
|
|
char *ptr;
|
|
int len;
|
|
|
|
if (str == NULL)
|
|
return NULL;
|
|
|
|
/* kill any comment */
|
|
ptr = strchr(str, ';');
|
|
if (ptr)
|
|
*ptr = 0;
|
|
ptr = strchr(str, '#');
|
|
if (ptr)
|
|
*ptr = 0;
|
|
|
|
ptr = str;
|
|
len = strlen(str);
|
|
if (len > 0) {
|
|
ptr += len-1;
|
|
}
|
|
|
|
while ((ptr > str) && isspace(*ptr)) {
|
|
ptr--;
|
|
}
|
|
|
|
if (*ptr) {
|
|
ptr++;
|
|
*ptr = 0;
|
|
}
|
|
|
|
ptr = str;
|
|
while (*ptr && isspace(*ptr)) {
|
|
ptr++;
|
|
}
|
|
|
|
return ptr;
|
|
}
|
|
|
|
static Profile *profile_read(char *file)
|
|
{
|
|
char fullname[MAX_PATH_LEN];
|
|
FILE *fp = NULL;
|
|
char *str;
|
|
|
|
snprintf(fullname, MAX_PATH_LEN, "%s%s%s%s%s", detect_home(), DIR_SEPARATOR_STR, Osreg_user_dir, DIR_SEPARATOR_STR, file);
|
|
|
|
fp = fopen(fullname, "rt");
|
|
|
|
if (fp == NULL)
|
|
return NULL;
|
|
|
|
Profile *profile = (Profile *)vm_malloc(sizeof(Profile));
|
|
profile->sections = NULL;
|
|
|
|
Section **sp_ptr = &(profile->sections);
|
|
Section *sp = NULL;
|
|
|
|
KeyValue **kvp_ptr = NULL;
|
|
|
|
while ((str = read_line_from_file(fp)) != NULL) {
|
|
char *ptr = trim_string(str);
|
|
|
|
if (*ptr == '[') {
|
|
ptr++;
|
|
|
|
char *pend = strchr(ptr, ']');
|
|
if (pend != NULL) {
|
|
// if (pend[1]) { /* trailing garbage! */ }
|
|
|
|
*pend = 0;
|
|
|
|
if (*ptr) {
|
|
sp = (Section *)vm_malloc(sizeof(Section));
|
|
sp->next = NULL;
|
|
|
|
sp->name = vm_strdup(ptr);
|
|
sp->pairs = NULL;
|
|
|
|
*sp_ptr = sp;
|
|
sp_ptr = &(sp->next);
|
|
|
|
kvp_ptr = &(sp->pairs);
|
|
} // else { /* null name! */ }
|
|
} // else { /* incomplete section name! */ }
|
|
} else {
|
|
if (*ptr) {
|
|
char *key = ptr;
|
|
char *value = NULL;
|
|
|
|
ptr = strchr(ptr, '=');
|
|
if (ptr != NULL) {
|
|
*ptr = 0;
|
|
ptr++;
|
|
|
|
value = ptr;
|
|
} // else { /* random garbage! */ }
|
|
|
|
if (key && *key && value /* && *value */) {
|
|
if (sp != NULL) {
|
|
KeyValue *kvp = (KeyValue *)vm_malloc(sizeof(KeyValue));
|
|
|
|
kvp->key = vm_strdup(key);
|
|
kvp->value = vm_strdup(value);
|
|
|
|
kvp->next = NULL;
|
|
|
|
*kvp_ptr = kvp;
|
|
kvp_ptr = &(kvp->next);
|
|
} // else { /* key/value with no section! */
|
|
} // else { /* malformed key/value entry! */ }
|
|
} // else it's just a comment or empty string
|
|
}
|
|
|
|
vm_free(str);
|
|
}
|
|
|
|
fclose(fp);
|
|
|
|
return profile;
|
|
}
|
|
|
|
static void profile_free(Profile *profile)
|
|
{
|
|
if (profile == NULL)
|
|
return;
|
|
|
|
Section *sp = profile->sections;
|
|
while (sp != NULL) {
|
|
Section *st = sp;
|
|
KeyValue *kvp = sp->pairs;
|
|
|
|
while (kvp != NULL) {
|
|
KeyValue *kvt = kvp;
|
|
|
|
vm_free(kvp->key);
|
|
vm_free(kvp->value);
|
|
|
|
kvp = kvp->next;
|
|
vm_free(kvt);
|
|
}
|
|
|
|
vm_free(sp->name);
|
|
|
|
sp = sp->next;
|
|
vm_free(st);
|
|
}
|
|
|
|
vm_free(profile);
|
|
}
|
|
|
|
static Profile *profile_update(Profile *profile, const char *section, const char *key, const char *value)
|
|
{
|
|
if (profile == NULL) {
|
|
profile = (Profile *)vm_malloc(sizeof(Profile));
|
|
|
|
profile->sections = NULL;
|
|
}
|
|
|
|
KeyValue *kvp;
|
|
|
|
Section **sp_ptr = &(profile->sections);
|
|
Section *sp = profile->sections;
|
|
|
|
while (sp != NULL) {
|
|
if (strcmp(section, sp->name) == 0) {
|
|
KeyValue **kvp_ptr = &(sp->pairs);
|
|
kvp = sp->pairs;
|
|
|
|
while (kvp != NULL) {
|
|
if (strcmp(key, kvp->key) == 0) {
|
|
vm_free(kvp->value);
|
|
|
|
if (value == NULL) {
|
|
*kvp_ptr = kvp->next;
|
|
|
|
vm_free(kvp->key);
|
|
vm_free(kvp);
|
|
} else {
|
|
kvp->value = vm_strdup(value);
|
|
}
|
|
|
|
/* all done */
|
|
return profile;
|
|
}
|
|
|
|
kvp_ptr = &(kvp->next);
|
|
kvp = kvp->next;
|
|
}
|
|
|
|
if (value != NULL) {
|
|
/* key not found */
|
|
kvp = (KeyValue *)vm_malloc(sizeof(KeyValue));
|
|
kvp->next = NULL;
|
|
kvp->key = vm_strdup(key);
|
|
kvp->value = vm_strdup(value);
|
|
}
|
|
|
|
*kvp_ptr = kvp;
|
|
|
|
/* all done */
|
|
return profile;
|
|
}
|
|
|
|
sp_ptr = &(sp->next);
|
|
sp = sp->next;
|
|
}
|
|
|
|
/* section not found */
|
|
sp = (Section *)vm_malloc(sizeof(Section));
|
|
sp->next = NULL;
|
|
sp->name = vm_strdup(section);
|
|
|
|
kvp = (KeyValue *)vm_malloc(sizeof(KeyValue));
|
|
kvp->next = NULL;
|
|
kvp->key = vm_strdup(key);
|
|
kvp->value = vm_strdup(value);
|
|
|
|
sp->pairs = kvp;
|
|
|
|
*sp_ptr = sp;
|
|
|
|
return profile;
|
|
}
|
|
|
|
static char *profile_get_value(Profile *profile, const char *section, const char *key)
|
|
{
|
|
if (profile == NULL)
|
|
return NULL;
|
|
|
|
Section *sp = profile->sections;
|
|
|
|
while (sp != NULL) {
|
|
if (strcmp(section, sp->name) == 0) {
|
|
KeyValue *kvp = sp->pairs;
|
|
|
|
while (kvp != NULL) {
|
|
if (strcmp(key, kvp->key) == 0) {
|
|
return kvp->value;
|
|
}
|
|
kvp = kvp->next;
|
|
}
|
|
}
|
|
|
|
sp = sp->next;
|
|
}
|
|
|
|
/* not found */
|
|
return NULL;
|
|
}
|
|
|
|
static void profile_save(Profile *profile, char *file)
|
|
{
|
|
FILE *fp = NULL;
|
|
char tmp[MAX_PATH] = "";
|
|
char tmp2[MAX_PATH] = "";
|
|
char fullname[MAX_PATH_LEN];
|
|
|
|
if (profile == NULL)
|
|
return;
|
|
|
|
snprintf(fullname, MAX_PATH_LEN, "%s%s%s%s%s", detect_home(), DIR_SEPARATOR_STR, Osreg_user_dir, DIR_SEPARATOR_STR, file);
|
|
|
|
fp = fopen(fullname, "wt");
|
|
|
|
if (fp == NULL)
|
|
return;
|
|
|
|
Section *sp = profile->sections;
|
|
|
|
while (sp != NULL) {
|
|
sprintf(tmp, NOX("[%s]\n"), sp->name);
|
|
fputs(tmp, fp);
|
|
|
|
KeyValue *kvp = sp->pairs;
|
|
while (kvp != NULL) {
|
|
sprintf(tmp2, NOX("%s=%s\n"), kvp->key, kvp->value);
|
|
fputs(tmp2, fp);
|
|
kvp = kvp->next;
|
|
}
|
|
|
|
fprintf(fp, "\n");
|
|
|
|
sp = sp->next;
|
|
}
|
|
|
|
fclose(fp);
|
|
}
|
|
|
|
// os registry functions -------------------------------------------------------------
|
|
|
|
static char szCompanyName[128];
|
|
static char szAppName[128];
|
|
static char szAppVersion[128];
|
|
|
|
int Os_reg_inited = 0;
|
|
|
|
// initialize the registry. setup default keys to use
|
|
void os_init_registry_stuff(const char *company, const char *app, const char *version)
|
|
{
|
|
if(company){
|
|
strcpy_s( szCompanyName, company );
|
|
} else {
|
|
strcpy_s( szCompanyName, Osreg_company_name);
|
|
}
|
|
|
|
if(app){
|
|
strcpy_s( szAppName, app );
|
|
} else {
|
|
strcpy_s( szAppName, Osreg_app_name);
|
|
}
|
|
|
|
if(version){
|
|
strcpy_s( szAppVersion, version);
|
|
} else {
|
|
strcpy_s( szAppVersion, "1.0");
|
|
}
|
|
|
|
Os_reg_inited = 1;
|
|
}
|
|
|
|
static char tmp_string_data[1024];
|
|
|
|
const char *os_config_read_string(const char *section, const char *name, const char *default_value)
|
|
{
|
|
nprintf(( "Registry", "os_config_read_string(): section = \"%s\", name = \"%s\", default value: \"%s\"\n",
|
|
(section) ? section : DEFAULT_SECTION, name, (default_value) ? default_value : NOX("NULL") ));
|
|
|
|
Profile *p = profile_read(PROFILE_NAME);
|
|
|
|
if (section == NULL)
|
|
section = DEFAULT_SECTION;
|
|
|
|
char *ptr = profile_get_value(p, section, name);
|
|
|
|
if (ptr != NULL) {
|
|
strncpy(tmp_string_data, ptr, 1023);
|
|
default_value = tmp_string_data;
|
|
}
|
|
|
|
profile_free(p);
|
|
|
|
return default_value;
|
|
}
|
|
|
|
unsigned int os_config_read_uint(const char *section, const char *name, unsigned int default_value)
|
|
{
|
|
Profile *p = profile_read(PROFILE_NAME);
|
|
|
|
if (section == NULL)
|
|
section = DEFAULT_SECTION;
|
|
|
|
char *ptr = profile_get_value(p, section, name);
|
|
|
|
if (ptr != NULL) {
|
|
default_value = atoi(ptr);
|
|
}
|
|
|
|
profile_free(p);
|
|
|
|
return default_value;
|
|
}
|
|
|
|
void os_config_write_string(const char *section, const char *name, const char *value)
|
|
{
|
|
Profile *p = profile_read(PROFILE_NAME);
|
|
|
|
if (section == NULL)
|
|
section = DEFAULT_SECTION;
|
|
|
|
p = profile_update(p, section, name, value);
|
|
profile_save(p, PROFILE_NAME);
|
|
profile_free(p);
|
|
}
|
|
|
|
void os_config_write_uint(const char *section, const char *name, unsigned int value)
|
|
{
|
|
static char buf[21];
|
|
|
|
snprintf(buf, 20, "%u", value);
|
|
|
|
Profile *p = profile_read(PROFILE_NAME);
|
|
|
|
if (section == NULL)
|
|
section = DEFAULT_SECTION;
|
|
|
|
p = profile_update(p, section, name, buf);
|
|
profile_save(p, PROFILE_NAME);
|
|
profile_free(p);
|
|
}
|
|
|
|
#endif // Goober5000 - #ifndef WIN32
|