1 /* configfile.c: parsing of config files
2 *
3 * Copyright (C) 2017-2018 Nikola Kolev <koue@chaosophia.net>
4 * Copyright (C) 2008 Lars Hjemli
5 *
6 * Licensed under GNU General Public License v2
7 * (see COPYING for full license text)
8 */
9
10 #include <errno.h>
11 #include <stdio.h>
12 #include <string.h>
13
14 #include "cez_config.h"
15
next_char(FILE * f)16 static int next_char(FILE *f)
17 {
18 int c = fgetc(f);
19 if (c=='\r') {
20 c = fgetc(f);
21 if (c!='\n') {
22 ungetc(c, f);
23 c = '\r';
24 }
25 }
26 return (c);
27 }
28
skip_line(FILE * f)29 static void skip_line(FILE *f)
30 {
31 int c;
32
33 while((c=next_char(f)) && c!='\n' && c!=EOF)
34 ;
35 }
36
configfile_isspace(char c)37 static int configfile_isspace(char c)
38 {
39 return c==' ' || (c<='\r' && c>='\t');
40 }
41
read_config_line(FILE * f,char * line,const char ** value,int bufsize)42 static int read_config_line(FILE *f, char *line, const char **value, int bufsize)
43 {
44 int i = 0, isname = 0;
45
46 *value = NULL;
47 while(i<bufsize-1) {
48 int c = next_char(f);
49 if (!isname && (c=='#' || c==';')) {
50 skip_line(f);
51 continue;
52 }
53 if (!isname && configfile_isspace(c))
54 continue;
55
56 if (c=='=' && !*value) {
57 line[i] = 0;
58 *value = &line[i+1];
59 } else if (c=='\n' && !isname) {
60 i = 0;
61 continue;
62 } else if (c=='\n' || c==EOF) {
63 line[i] = 0;
64 break;
65 } else {
66 line[i]=c;
67 }
68 isname = 1;
69 i++;
70 }
71 line[i+1] = 0;
72 return (i);
73 }
74
configfile_parse(const char * filename,configfile_value_fn fn)75 int configfile_parse(const char *filename, configfile_value_fn fn)
76 {
77 int len;
78 char line[256];
79 const char *value;
80 FILE *f;
81
82 if (!(f = fopen(filename, "r"))) {
83 fprintf(stderr, "[ERROR] %s: %s, %s\n", __func__, filename,
84 strerror(errno));
85 return (-1);
86 }
87 while((len = read_config_line(f, line, &value, sizeof(line))) > 0) {
88 if (value == NULL) {
89 fprintf(stderr, "[ERROR] %s: configuration error: %s\n",
90 __func__, line);
91 return (-1);
92 }
93 fn(line, value);
94 }
95 fclose(f);
96 return (0);
97 }
98