1 #include "../declarations.h"
2 #include "../conf_str.h"
3 #include "remotetool_conf.h"
4
5
6
conf_read(void)7 int conf_read(void) {
8 unsigned int i;
9
10 char *p;
11
12 size_t t;
13
14 t = CONFIG_PATH_LENGTH;
15
16 if((p = malloc(t + sizeof(char))) == NULL) {
17 (void) fprintf(
18 stderr,
19 SUBSYSTEM "Failed to allocate %lu bytes of memory: %s.%c",
20 (unsigned long) (t + sizeof(char)), strerror(errno), CONFIG_LINE_FEED
21 );
22
23 return(-1);
24 }
25
26 for(i = 0; ; i++) {
27 if(c_d_t[i] == NULL) break;
28
29 if(conf_read_try(c_d_t[i], CONFIG_FILE, p, t) != 0) continue;
30 if(conf_read_real(p) == 0) {
31 (void) free(p);
32
33 return(0);
34 }
35 }
36
37 (void) fprintf(
38 stderr,
39 SUBSYSTEM "Failed to read configuration file '%s' from any of these directories:%c%c",
40 CONFIG_FILE, CONFIG_LINE_FEED, CONFIG_LINE_FEED
41 );
42
43 for(i = 0; ; i++) {
44 if(c_d_t[i] == NULL) break;
45
46 (void) fprintf(
47 stderr,
48 " %u. %s%c%c",
49 (i + 1), c_d_t[i], CONFIG_PATH_DELIM, CONFIG_LINE_FEED
50 );
51 }
52
53 (void) fprintf(stderr, "%c", CONFIG_LINE_FEED);
54
55 (void) free(p);
56
57 return(-1);
58 }
59
conf_read_try(const char * c,char * d,char * p,size_t t)60 int conf_read_try(const char *c, char *d, char *p, size_t t) {
61 unsigned int i;
62
63 char *s, *v;
64
65 if(strncmp((const char *) c, "@", sizeof(char)) == 0) {
66 (void) snprintf(p, t, "%s%s%c%s", DIR_PLACE_PRE, c + sizeof(char), CONFIG_PATH_DELIM, d);
67 }
68 else if(strncmp((const char *) c, "~", sizeof(char)) == 0) {
69 if((s = node_get_homedir()) == NULL) return(-1);
70
71 (void) snprintf(p, t, "%s%s%c%s", s, c + sizeof(char), CONFIG_PATH_DELIM, d);
72 }
73 else if(strncmp((const char *) c, "$", sizeof(char)) == 0) {
74 if((v = malloc(t + sizeof(char))) == NULL) {
75 (void) fprintf(
76 stderr,
77 SUBSYSTEM "Failed to allocate %lu bytes of memory: %s.%c",
78 (unsigned long) (t + sizeof(char)), strerror(errno), CONFIG_LINE_FEED
79 );
80
81 return(-1);
82 }
83
84 for(i = 0; ; i++) {
85 if((size_t) i >= t || c[i + sizeof(char)] == 0 || c[i + sizeof(char)] == CONFIG_PATH_DELIM) break;
86
87 v[i] = c[i + sizeof(char)];
88 }
89
90 v[i] = 0;
91
92 if((s = env_get(v)) == NULL) {
93 (void) free(v);
94
95 return(-1);
96 }
97
98 (void) free(v);
99
100 (void) snprintf(p, t, "%s%c%s", s, CONFIG_PATH_DELIM, d);
101
102 (void) env_free(s);
103 }
104 else (void) snprintf(p, t, "%s%c%s", c, CONFIG_PATH_DELIM, d);
105
106 return(0);
107 }
108
conf_read_def(void)109 char *conf_read_def(void) {
110 unsigned int i;
111
112 char *p;
113
114 size_t t;
115
116 FILE *f;
117
118 t = CONFIG_PATH_LENGTH;
119
120 if((p = malloc(t + sizeof(char))) == NULL) {
121 (void) fprintf(
122 stderr,
123 SUBSYSTEM "Failed to allocate %lu bytes of memory: %s.%c",
124 (unsigned long) (t + sizeof(char)), strerror(errno), CONFIG_LINE_FEED
125 );
126
127 return(NULL);
128 }
129
130 for(i = 0; ; i++) {
131 if(c_d_t[i] == NULL) break;
132
133 if(conf_read_try(c_d_t[i], CONFIG_FILE, p, t) != 0) continue;
134
135 if((f = fopen((const char *) p, FILE_MODE_READ)) != NULL) {
136 (void) fclose(f);
137
138 return(p);
139 }
140 }
141
142 (void) free(p);
143
144 return(NULL);
145 }
146
conf_read_def_free(char * s)147 void conf_read_def_free(char *s) {
148 if(s != NULL) (void) free(s);
149 }
150
conf_read_real(char * s)151 static int conf_read_real(char *s) {
152 unsigned int k;
153
154 char *p;
155
156 size_t t;
157
158 FILE *f;
159
160 if(s == NULL) return(-1);
161
162 t = CONFIG_LINE_LENGTH;
163
164 if((p = malloc(t + sizeof(char))) == NULL) {
165 (void) fprintf(
166 stderr,
167 SUBSYSTEM "Failed to allocate %lu bytes of memory: %s.%c",
168 (unsigned long) (t + sizeof(char)), strerror(errno), CONFIG_LINE_FEED
169 );
170
171 return(-1);
172 }
173
174 if((f = fopen((const char *) s, FILE_MODE_READ)) != NULL) {
175 k = 1;
176
177 while(fgets(p, (int) t, f) != NULL) {
178 if(p[0] == '\r' || p[0] == '\n' || p[0] == '#' || p[0] == '%' || p[0] == ';' || p[0] == '!') {
179 ++k;
180
181 continue;
182 }
183
184 (void) conf_read_op(c_f_t, p, k);
185
186 ++k;
187 }
188
189 if(fclose(f) != 0) {
190 (void) fprintf(
191 stderr,
192 SUBSYSTEM "Failed to close configuration '%s': %s.%c",
193 s, strerror(errno), CONFIG_LINE_FEED
194 );
195 }
196
197 (void) free(p);
198
199 return(0);
200 }
201
202 (void) free(p);
203
204 return(-1);
205 }
206
conf_read_op(struct c_f * c,char * p,unsigned int k)207 static int conf_read_op(struct c_f *c, char *p, unsigned int k) {
208 unsigned int i;
209
210 char *a;
211
212 for(i = 0; ; i++) {
213 if(c[i].ck == NULL) break;
214 if(strncasecmp((const char *) c[i].ck, (const char *) p, str_len(c[i].ck, STRING_ASCII)) == 0) {
215 if((a = conf_read_it(p)) == NULL) break;
216
217 if(a == (char *) -1) {
218 switch(c[i].c_t) {
219 case CONFIG_TYPE_BOOLEAN:
220 (void) fprintf(
221 stderr,
222 "Keyword %s at line %u requires a boolean (yes/no/1/0) value, going with builtin default.%c",
223 c[i].ck, k, CONFIG_LINE_FEED
224 );
225
226 break;
227 case CONFIG_TYPE_INTEGER:
228 (void) fprintf(
229 stderr,
230 "Keyword %s at line %u requires a numeral (<-0->) value, going with builtin default.%c",
231 c[i].ck, k, CONFIG_LINE_FEED
232 );
233
234 break;
235 case CONFIG_TYPE_FLOAT:
236 (void) fprintf(
237 stderr,
238 "Keyword %s at line %u requires a numeral (<-0.0->) value, going with builtin default.%c",
239 c[i].ck, k, CONFIG_LINE_FEED
240 );
241
242 break;
243 case CONFIG_TYPE_STRING:
244 (void) fprintf(
245 stderr,
246 "Keyword %s at line %u requires a string value, going with builtin default.%c",
247 c[i].ck, k, CONFIG_LINE_FEED
248 );
249
250 break;
251 default:
252 (void) fprintf(
253 stderr,
254 "Keyword %s at line %u requires a value of type %d.%c",
255 c[i].ck, k, c[i].c_t, CONFIG_LINE_FEED
256 );
257
258 break;
259 }
260
261 break;
262 }
263
264 switch(c[i].c_t) {
265 case CONFIG_TYPE_BOOLEAN:
266 if((conf_boolean(a, &c[i].c_i)) != 0) {
267 (void) fprintf(
268 stderr,
269 "Keyword %s at line %u requires a boolean (yes/no/1/0) value.%c",
270 c[i].ck, k, CONFIG_LINE_FEED
271 );
272
273 break;
274 }
275
276 break;
277 case CONFIG_TYPE_INTEGER:
278 if((conf_integer(a, &c[i].c_i)) != 0) {
279 (void) fprintf(
280 stderr,
281 "Keyword %s at line %u requires a numeral (<-0->) value.%c",
282 c[i].ck, k, CONFIG_LINE_FEED
283 );
284
285 break;
286 }
287
288 break;
289 case CONFIG_TYPE_FLOAT:
290 if((conf_float(a, &c[i].c_d)) != 0) {
291 (void) fprintf(
292 stderr,
293 "Keyword %s at line %u requires a numeral (<-0.0->) value.%c",
294 c[i].ck, k, CONFIG_LINE_FEED
295 );
296
297 break;
298 }
299
300 break;
301 case CONFIG_TYPE_STRING:
302 if(c[i].c_s == NULL) {
303 if((c[i].c_s = malloc((size_t) CONFIG_LINE_LENGTH)) == NULL) {
304 (void) fprintf(
305 stderr,
306 SUBSYSTEM "Failed to allocate %lu bytes of memory: %s.%c",
307 (unsigned long) CONFIG_LINE_LENGTH, strerror(errno), CONFIG_LINE_FEED
308 );
309
310 break;
311 }
312
313 (void) memset((void *) c[i].c_s, 0, CONFIG_LINE_LENGTH);
314 }
315
316 (void) conf_string(a, c[i].c_s);
317
318 break;
319 default:
320 (void) fprintf(
321 stderr,
322 "Unknown value type %d for keyword %s at line %u.%c",
323 c[i].c_t, c[i].ck, k, CONFIG_LINE_FEED
324 );
325
326 break;
327 }
328
329 c[i].c_q = 2;
330
331 return(0);
332 }
333 }
334
335 return(-1);
336 }
337
conf_read_it(char * s)338 static char *conf_read_it(char *s) {
339 char *e;
340
341 size_t t;
342
343 if((e = str_chr((const char *) s, '=')) == NULL) {
344 if((e = str_chr((const char *) s, ':')) == NULL) {
345 return(NULL);
346 }
347 }
348
349 if((t = str_len(++e, STRING_ASCII)) < 2) {
350 return(NULL);
351 }
352
353 if(e[t - 2] == '\r') {
354 e[t - 2] = 0;
355 }
356 else e[t - 1] = 0;
357
358 while(*e == ' ' || *e == '\t') e++;
359
360 if(*e == '\r' || *e == '\n' || *e == 0) return((char *) -1);
361
362 return(e);
363 }
364
conf_boolean(char * a,int * o)365 static int conf_boolean(char *a, int *o) {
366 if((strncasecmp((const char *) a, "yes", 3)) == 0) {
367 *o = CONFIG_TYPE_BOOLEAN_YES;
368
369 return(0);
370 }
371 else if((strncasecmp((const char *) a, "no", 2)) == 0) {
372 *o = CONFIG_TYPE_BOOLEAN_NO;
373
374 return(0);
375 }
376 else if((strncasecmp((const char *) a, "y", 1)) == 0) {
377 *o = CONFIG_TYPE_BOOLEAN_YES;
378
379 return(0);
380 }
381 else if((strncasecmp((const char *) a, "n", 1)) == 0) {
382 *o = CONFIG_TYPE_BOOLEAN_NO;
383
384 return(0);
385 }
386 else if((strncasecmp((const char *) a, "1", 1)) == 0) {
387 *o = CONFIG_TYPE_BOOLEAN_YES;
388
389 return(0);
390 }
391 else if((strncasecmp((const char *) a, "0", 1)) == 0) {
392 *o = CONFIG_TYPE_BOOLEAN_NO;
393
394 return(0);
395 }
396
397 return(-1);
398 }
399
conf_integer(char * a,int * o)400 static int conf_integer(char *a, int *o) {
401 char *e, *f;
402
403 (void) flush_error();
404
405 e = a;
406
407 *o = (int) strtol((const char *) e, &f, 0);
408
409 if(errno == ERANGE || (errno != 0 && *o == 0) || e == f) return(-1);
410
411 return(0);
412 }
413
conf_float(char * a,double * o)414 static int conf_float(char *a, double *o) {
415 char *e, *f;
416
417 (void) flush_error();
418
419 e = a;
420
421 *o = strtod((const char *) e, &f);
422
423 if(errno == ERANGE || e == f) return(-1);
424
425 return(0);
426 }
427
conf_string(char * a,char * o)428 static int conf_string(char *a, char *o) {
429 size_t t;
430
431 t = str_len(a, STRING_ASCII);
432
433 if(t > CONFIG_LINE_LENGTH - 1) t = CONFIG_LINE_LENGTH - 1;
434
435 (void) memcpy((void *) o, (const void *) a, t);
436
437 o[t] = 0;
438
439 return(0);
440 }
441
conf_free(void)442 void conf_free(void) {
443 (void) conf_free_op(c_f_t);
444 }
445
conf_free_op(void * v)446 void conf_free_op(void *v) {
447 unsigned int i;
448
449 struct c_f *c;
450
451 c = (struct c_f *) v;
452
453 for(i = 0; ; i++) {
454 if(c[i].ck == NULL) break;
455 if(c[i].c_t == CONFIG_TYPE_STRING && c[i].c_s != NULL) {
456 (void) free(c[i].c_s);
457
458 c[i].c_s = NULL;
459 }
460 }
461 }
462
conf_fetch(char * s)463 void *conf_fetch(char *s) {
464 void *r;
465
466 if((r = conf_fetch_op(c_f_t, s)) == (void *) -1) {
467 (void) flush_error();
468
469 (void) fprintf(
470 stderr,
471 "Configuration parameter '%s' does not exist, please check configuration definitions.%c",
472 s, CONFIG_LINE_FEED
473 );
474
475 return(NULL);
476 }
477
478 return(r);
479 }
480
conf_fetch_op(void * v,char * s)481 void *conf_fetch_op(void *v, char *s) {
482 unsigned int i;
483
484 size_t t;
485
486 struct c_f *c;
487
488 if(s == NULL) return(NULL);
489
490 t = str_len(s, STRING_ASCII);
491
492 c = (struct c_f *) v;
493
494 for(i = 0; ; i++) {
495 if(c[i].ck == NULL) break;
496 if(str_len(c[i].ck, STRING_ASCII) != t) continue;
497 if(strncasecmp((const char *) c[i].ck, (const char *) s, t) == 0) {
498 /* Leave if non-boolean parameter is not supplied by user */
499 if(c[i].c_t != CONFIG_TYPE_BOOLEAN && c[i].c_q == 0) return(NULL);
500
501 switch(c[i].c_t) {
502 case CONFIG_TYPE_BOOLEAN:
503 return(&c[i].c_i);
504 case CONFIG_TYPE_INTEGER:
505 return(&c[i].c_i);
506 case CONFIG_TYPE_FLOAT:
507 return(&c[i].c_d);
508 case CONFIG_TYPE_STRING:
509 if(c[i].c_s == NULL || c[i].c_s[0] == 0) return(NULL);
510
511 return(c[i].c_s);
512 default:
513 (void) flush_error();
514
515 (void) fprintf(
516 stderr,
517 "Configuration parameter '%s' has unknown type, please check configuration definitions.%c",
518 s, CONFIG_LINE_FEED
519 );
520
521 return(NULL);
522 }
523 }
524 }
525
526 return((void *) -1);
527 }
528
conf_update_boolean(char * s,char * o)529 void conf_update_boolean(char *s, char *o) {
530 (void) conf_update_boolean_op(c_f_t, s, o);
531 }
532
conf_update_boolean_op(struct c_f * c,char * s,__UNUSED__ char * o)533 static void conf_update_boolean_op(struct c_f *c, char *s, __UNUSED__ char *o) {
534 unsigned int i;
535
536 for(i = 0; ; i++) {
537 if(c[i].ck == NULL) return;
538 if(strncasecmp((const char *) c[i].ck, (const char *) s, str_len(c[i].ck, STRING_ASCII)) == 0) {
539 c[i].c_i = CONFIG_TYPE_BOOLEAN_YES;
540 c[i].c_q = 1;
541
542 return;
543 }
544 }
545 }
546
conf_update_integer(char * s,char * o)547 void conf_update_integer(char *s, char *o) {
548 (void) conf_update_integer_op(c_f_t, s, o);
549 }
550
conf_update_integer_op(struct c_f * c,char * s,char * o)551 static void conf_update_integer_op(struct c_f *c, char *s, char *o) {
552 unsigned int i;
553
554 char *e, *f;
555
556 for(i = 0; ; i++) {
557 if(c[i].ck == NULL) return;
558 if(strncasecmp((const char *) c[i].ck, (const char *) s, str_len(c[i].ck, STRING_ASCII)) == 0) {
559 (void) flush_error();
560
561 e = o;
562
563 c[i].c_i = (int) strtol((const char *) e, &f, 0);
564
565 if(errno == ERANGE || (errno != 0 && c[i].c_i == 0) || e == f) {
566 if(e == f) (void) set_error(EINVAL);
567
568 (void) fprintf(
569 stderr,
570 "Parameter '%s' requires numeral (<-0->) value.%c",
571 s, CONFIG_LINE_FEED
572 );
573
574 (void) conf_free();
575 (void) exit(1);
576 }
577
578 c[i].c_q = 1;
579
580 return;
581 }
582 }
583 }
584
conf_update_float(char * s,char * o)585 void conf_update_float(char *s, char *o) {
586 (void) conf_update_float_op(c_f_t, s, o);
587 }
588
conf_update_float_op(struct c_f * c,char * s,char * o)589 static void conf_update_float_op(struct c_f *c, char *s, char *o) {
590 unsigned int i;
591
592 char *e, *f;
593
594 for(i = 0; ; i++) {
595 if(c[i].ck == NULL) return;
596 if(strncasecmp((const char *) c[i].ck, (const char *) s, str_len(c[i].ck, STRING_ASCII)) == 0) {
597 (void) flush_error();
598
599 e = o;
600
601 c[i].c_d = strtod((const char *) e, &f);
602
603 if(errno == ERANGE || e == f) {
604 if(e == f) (void) set_error(EINVAL);
605
606 (void) fprintf(
607 stderr,
608 "Parameter '%s' requires numeral floating point (<-0.0->) value.%c",
609 s, CONFIG_LINE_FEED
610 );
611
612 (void) conf_free();
613 (void) exit(1);
614 }
615
616 c[i].c_q = 1;
617
618 return;
619 }
620 }
621 }
622
conf_update_string(char * s,char * o)623 void conf_update_string(char *s, char *o) {
624 (void) conf_update_string_op(c_f_t, s, o);
625 }
626
conf_update_string_op(struct c_f * c,char * s,char * o)627 static void conf_update_string_op(struct c_f *c, char *s, char *o) {
628 unsigned int i;
629
630 size_t t;
631
632 for(i = 0; ; i++) {
633 if(c[i].ck == NULL) return;
634 if(strncasecmp((const char *) c[i].ck, (const char *) s, str_len(c[i].ck, STRING_ASCII)) == 0) {
635 t = str_len(o, STRING_ASCII);
636
637 if(t > CONFIG_LINE_LENGTH - 1) {
638 (void) fprintf(
639 stderr,
640 "Parameter for '%s' is too long, it will be chopped.%c",
641 s, CONFIG_LINE_FEED
642 );
643
644 t = CONFIG_LINE_LENGTH - 1;
645 }
646
647 if(c[i].c_s == NULL) {
648 if((c[i].c_s = malloc((size_t) CONFIG_LINE_LENGTH)) == NULL) {
649 (void) fprintf(
650 stderr,
651 SUBSYSTEM "Failed to allocate %lu bytes of memory: %s.%c",
652 (unsigned long) CONFIG_LINE_LENGTH, strerror(errno), CONFIG_LINE_FEED
653 );
654
655 return;
656 }
657
658 (void) memset((void *) c[i].c_s, 0, CONFIG_LINE_LENGTH);
659 }
660
661 (void) snprintf(c[i].c_s, t + sizeof(char), "%s", o);
662
663 c[i].c_q = 1;
664
665 return;
666 }
667 }
668 }
669
conf_get_default_conf_path(unsigned int i)670 char *conf_get_default_conf_path(unsigned int i) {
671 return(c_d_t[i]);
672 }
673