2 * Copyright (c) 2011, Andy Spencer <andy753421@gmail.com>
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
25 typedef enum { number, string } type_t;
40 static int conf_cmp(const void *_a, const void *_b)
42 const entry_t *a = _a;
43 const entry_t *b = _b;
44 return strcmp(a->key, b->key);
47 static entry_t *conf_get(const char *key)
49 entry_t try = { .key = (char*)key };
50 entry_t **found = tfind(&try, &conf, conf_cmp);
51 return found ? *found : NULL;
54 static void conf_set(const char *key, int num, const char *str)
59 if ((entry = conf_get(key))) {
60 tdelete(entry, &conf, conf_cmp);
62 if (entry->type == string)
68 entry = new0(entry_t);
69 entry->key = strdup(key);
72 entry->str = strdup(str);
77 tsearch(entry, &conf, conf_cmp);
80 static char *strtrim(char *str)
82 while (*str == ' ' || *str == '\t' || *str == '\n')
84 char *end = strchr(str, '\0');
85 while (end > str && (*end == ' ' || *end == '\t' ||
86 *end == '\n' || *end == '\0'))
91 /* Read an ini file into the configuration
92 * - this does not properly handle excape sequences
93 * - could probably make this into a real parser.. */
94 static void load_file(const char *path)
96 char line[256]={}, section[256]={};
97 char key[256]={}, val[256]={};
98 FILE *fd = fopen(path, "rt");
100 printf("load_file: %s\n", path);
101 while (fgets(line, sizeof(line), fd)) {
102 /* Find special characters */
103 char *lbrace = strchr( line , '[');
104 char *rbrace = strchr((lbrace ?: line)+1, ']');
105 char *equal = strchr( line , '=');
106 char *lquote = strchr((equal ?: line)+1, '"');
107 char *rquote = strchr((lquote ?: line)+1, '"');
108 char *hash = strchr((rquote ?: line)+1, '#');
112 if (lbrace && rbrace) {
113 /* Check for secions */
114 memcpy(section, lbrace+1, rbrace-lbrace-1);
116 else if (section[0] && equal && lquote && rquote) {
117 /* Check for numbers/plain strings */
118 memcpy(key, line, equal-line);
119 memcpy(val, lquote+1, rquote-lquote-1);
120 char *_key = strtrim(key);
121 conf_set_str(_key, val);
122 printf(" [%s.%s] = [%s]\n", section, _key, val);
124 else if (section[0] && equal) {
125 /* Check for strings */
126 memcpy(key, line, equal-line);
127 strcpy(val, equal+1);
128 char *_key = strtrim(key);
129 char *_val = strtrim(val);
131 int num = strtol(_val, &end, 10);
132 if (end != val && *end == '\0')
133 conf_set_int(_key, num);
134 else if (!strcasecmp(_val, "true"))
135 conf_set_int(_key, 1);
136 else if (!strcasecmp(_val, "false"))
137 conf_set_int(_key, 0);
139 conf_set_str(_key, _val);
140 printf(" [%s.%s] = [%s]\n", section, _key, _val);
146 static void load_args(int argc, char **argv)
152 /* Configuration file functions */
153 int conf_get_int(const char *key)
155 entry_t *entry = conf_get(key);
156 return entry ? entry->num : 0;
159 void conf_set_int(const char *key, int value)
161 conf_set(key, value, NULL);
164 const char *conf_get_str(const char *key)
166 entry_t *entry = conf_get(key);
167 return entry ? entry->str : NULL;
170 void conf_set_str(const char *key, const char *value)
172 conf_set(key, 0, value);
175 void conf_init(int argc, char **argv)
177 /* Load configuration */
179 snprintf(path, sizeof(path), "%s/%s", getenv("HOME"), ".wmpus");
181 load_args(argc, argv);