cfg.c - rohrpost - A commandline mail client to change the world as we see it.
(HTM) git clone git://r-36.net/rohrpost
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
(DIR) LICENSE
---
cfg.c (5892B)
---
1 /*
2 * Copy me if you can.
3 * by 20h
4 */
5
6 #include <unistd.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <stdarg.h>
10 #include <string.h>
11 #include <strings.h>
12 #include <errno.h>
13 #include <libgen.h>
14 #include <sys/stat.h>
15 #include <sys/types.h>
16 #include <dirent.h>
17 #include <ctype.h>
18
19 #include "ind.h"
20 #include "arg.h"
21 #include "llist.h"
22 #include "path.h"
23 #include "cfg.h"
24
25 config_t *
26 config_init(char *cfgn)
27 {
28 char *path;
29 config_t *cfg;
30
31 if (cfgn == NULL)
32 cfgn = "default";
33
34 path = path_mkcfgfile(cfgn);
35 cfg = config_read(path);
36 if (cfg == NULL)
37 cfg = config_new();
38 cfg->path = memdups(path);
39 free(path);
40
41 if (cfg->name == NULL) {
42 cfg->name = memdups("default");
43 } else {
44 cfg->name = memdups(cfgn);
45 }
46
47 return cfg;
48 }
49
50 void
51 config_default(char *cfgn)
52 {
53 char *path, *cwd;
54 struct stat sbuf;
55
56 cwd = getcwd(NULL, 0);
57 if (cwd == NULL)
58 edie("getcwd");
59
60 path = path_mkrppath(NULL);
61 if (chdir(path) < 0)
62 edie("chdir");
63 if (lstat("default", &sbuf) >= 0) {
64 if (remove("default") < 0)
65 edie("remove");
66 }
67 if (symlink(cfgn, "default") < 0)
68 edie("symlink");
69
70 if (chdir(cwd) < 0)
71 edie("chdir");
72
73 free(cwd);
74 free(path);
75 }
76
77 void
78 config_list(void)
79 {
80 char *path;
81 struct dirent **dirlist;
82 int ndir;
83
84 path = path_mkrppath(NULL);
85
86 ndir = scandir(path, &dirlist, NULL, alphasort);
87 free(path);
88 if (ndir < 0)
89 edie("scandir");
90 for (--ndir; ndir >= 0; ndir--) {
91 if (!strcmp(dirlist[ndir]->d_name, "."))
92 continue;
93 if (!strcmp(dirlist[ndir]->d_name, ".."))
94 continue;
95 if (!strcmp(dirlist[ndir]->d_name, "default"))
96 continue;
97 printf("%s\n", dirlist[ndir]->d_name);
98 }
99 free(dirlist);
100 }
101
102 void
103 config_stop(config_t *cfg)
104 {
105 char *path;
106
107 if (cfg->changed) {
108 path = path_mkcfgfile(cfg->name);
109 if (config_write(cfg, NULL) == NULL)
110 edie("config_write");
111 free(path);
112 }
113
114 config_free(cfg);
115 }
116
117 llistelem_t *
118 config_checkget(config_t *cfg, char *key)
119 {
120 llistelem_t *result;
121
122 result = config_get(cfg, key);
123 if (result == NULL)
124 die("config_checkget: %s not found in config.\n", key);
125
126 return result;
127 }
128
129 char *
130 config_getstr(config_t *cfg, char *key)
131 {
132 llistelem_t *selitem;
133 char *rstr, *envval, *ukey;
134 int i;
135
136 /*
137 * The environment is:
138 * RP${KEY}
139 */
140 ukey = smprintf("RP%s", key);
141 for (i = 2; i < strlen(ukey); i++)
142 ukey[i] = (char)toupper(ukey[i]);
143
144 envval = getenv(ukey);
145 free(ukey);
146 if (envval != NULL)
147 return memdups(envval);
148
149 if (cfg == NULL)
150 return NULL;
151
152 selitem = config_get(cfg, key);
153 if (selitem != NULL && selitem->data != NULL) {
154 rstr = memdup(selitem->data, selitem->datalen+1);
155 } else {
156 rstr = NULL;
157 }
158
159 return rstr;
160 }
161
162 char *
163 config_checkgetstr(config_t *cfg, char *key)
164 {
165 char *rstr;
166
167 rstr = config_getstr(cfg, key);
168 if (rstr == NULL)
169 die("config_checkgetstr: %s not found in config.\n", key);
170
171 return rstr;
172 }
173
174 void
175 configprintelem(llistelem_t *elem, int onlydata)
176 {
177 if (onlydata) {
178 llistelem_printdata(elem);
179 } else {
180 llistelem_print(elem);
181 }
182 }
183
184 void
185 configusage(char *argv0)
186 {
187 die("usage: %s [-hiqv] [-c cfg] [-e cfg|-l|key"
188 " [value]]|-d key|-s regex|-n]\n", argv0);
189 }
190
191 int
192 configmain(int argc, char *argv[])
193 {
194 int status;
195 char *key, *value, *cfgn, *def, *argv0;
196 config_t *cfg;
197 llist_t *results;
198 llistelem_t *result, *elem;
199
200 enum {
201 BEQUIET = 0x01,
202 ONLYDATA = 0x02,
203 DOLIST = 0x04,
204 DODELETE = 0x08,
205 DOSEARCH = 0x10,
206 DOINIT = 0x20,
207 DODEFAULT = 0x40,
208 DONAMECFG = 0x80
209 };
210
211 status = 0;
212 key = NULL;
213 value = NULL;
214 cfgn = NULL;
215 def = NULL;
216
217 ARGBEGIN(argv0) {
218 case 'c':
219 cfgn = EARGF(configusage(argv0));
220 break;
221 case 'd':
222 status |= DODELETE;
223 break;
224 case 'e':
225 def = ARGF();
226 status |= DODEFAULT;
227 break;
228 case 'i':
229 status |= DOINIT;
230 break;
231 case 'n':
232 status |= DONAMECFG;
233 break;
234 case 'q':
235 status |= BEQUIET;
236 break;
237 case 'v':
238 status |= ONLYDATA;
239 break;
240 case 'l':
241 status |= DOLIST;
242 break;
243 case 's':
244 status |= DOSEARCH;
245 break;
246 default:
247 configusage(argv0);
248 } ARGEND;
249
250 if (status & DODEFAULT) {
251 if (def) {
252 config_default(def);
253 if (!(status & BEQUIET)) {
254 printf("Default configuration set to '%s'.\n",
255 def);
256 }
257 return 0;
258 } else {
259 config_list();
260 return 0;
261 }
262 }
263
264 cfg = config_init(cfgn);
265
266 if (status & DONAMECFG) {
267 if (cfg->name != NULL)
268 printf("%s\n", cfg->name);
269 return 0;
270 }
271
272 if (status & DOLIST) {
273 if (config_len(cfg) > 0) {
274 llist_sort(cfg->values);
275 forllist(cfg->values, elem)
276 configprintelem(elem, status & ONLYDATA);
277 }
278 return 0;
279 }
280
281 if (argc > 0) {
282 key = argv[0];
283 if (argc > 1)
284 value = argv[1];
285 } else {
286 configusage(argv0);
287 }
288
289 if (value != NULL) {
290 result = config_set(cfg, key, value);
291 if (!(status & BEQUIET))
292 configprintelem(result, status & ONLYDATA);
293 config_stop(cfg);
294 return 0;
295 }
296
297 if ((status & DOSEARCH) && !(status & DODELETE)) {
298 results = config_find(cfg, key);
299 if (results == NULL) {
300 if (!(status & BEQUIET))
301 printf("No matching key found.\n");
302 return 1;
303 }
304 forllist(results, elem)
305 configprintelem(elem, status & ONLYDATA);
306 return 0;
307 }
308 if (status & DODELETE) {
309 if (status & DOSEARCH) {
310 results = config_find(cfg, key);
311 if (results == NULL) {
312 if (!(status & BEQUIET))
313 printf("No such key in config.\n");
314 return 1;
315 }
316
317 forllist(results, elem)
318 config_del(cfg, elem->key);
319 if (!(status & BEQUIET))
320 printf("%d keys removed from config\n",
321 results->len);
322 config_stop(cfg);
323 } else {
324 result = config_del(cfg, key);
325 if (result == NULL) {
326 if (!(status & BEQUIET))
327 printf("Nothing deleted.\n");
328 return 1;
329 } else {
330 if (!(status & BEQUIET))
331 printf("One key removed from "
332 "config.\n");
333 config_stop(cfg);
334 }
335 }
336 return 0;
337 }
338
339 result = config_get(cfg, key);
340 if (result == NULL) {
341 if (!(status & BEQUIET))
342 printf("No such key in config.\n");
343 return 1;
344 }
345 configprintelem(result, status & ONLYDATA);
346
347 return 0;
348 }
349