Merge branch 'collectd-3.11'
[collectd.git] / src / libconfig / conf_section.c
1 #include "compat.h"
2 #include "libconfig.h"
3 #include "libconfig_private.h"
4 #include "conf_section.h"
5
6 #ifdef HAVE_STDIO_H
7 #include <stdio.h>
8 #endif
9
10 #ifdef HAVE_STRING_H
11 #include <string.h>
12 #endif
13
14 int lc_process_conf_section(const char *appname, const char *configfile) {
15         LC_FILE *configfp = NULL;
16         const char *local_lc_errfile;
17         char linebuf[LC_LINEBUF_LEN] = {0}, *linebuf_ptr = NULL;
18         char qualifbuf[LC_LINEBUF_LEN] = {0};
19         char *cmd = NULL, *value = NULL, *sep = NULL, *cmdend = NULL;
20         char *currsection = NULL;
21         char *fgetsret = NULL;
22         int lcpvret = -1;
23         int invalid_section = 1, ignore_section = 0;
24         int local_lc_errline;
25         int retval = 0;
26         lc_err_t save_lc_errno = LC_ERR_NONE;
27
28         local_lc_errfile = configfile;
29         local_lc_errline = 0;
30
31         if (appname == NULL || configfile == NULL) {
32                 lc_errfile = local_lc_errfile;
33                 lc_errline = local_lc_errline;
34                 lc_errno = LC_ERR_INVDATA;
35                 return(-1);
36         }
37
38         configfp = lc_fopen(configfile, "r");
39
40         if (configfp == NULL) {
41                 lc_errfile = local_lc_errfile;
42                 lc_errline = local_lc_errline;
43                 lc_errno = LC_ERR_CANTOPEN;
44                 return(-1);
45         }
46
47         while (1) {
48                 fgetsret = lc_fgets(linebuf, sizeof(linebuf) - 1, configfp);
49                 if (fgetsret == NULL) {
50                         break;
51                 }
52                 if (lc_feof(configfp)) {
53                         break;
54                 }
55
56                 local_lc_errline++;
57
58                 /* Remove trailing crap (but not spaces). */
59                 linebuf_ptr = &linebuf[strlen(linebuf) - 1];
60                 while (*linebuf_ptr < ' ' && linebuf_ptr >= linebuf) {
61                         *linebuf_ptr = '\0';
62                         linebuf_ptr--;
63                 }
64
65                 /* Handle section header. */
66                 if (linebuf[0] == '[' && linebuf[strlen(linebuf) - 1] == ']') {
67                         linebuf[strlen(linebuf) - 1] = '\0';
68                         linebuf_ptr = &linebuf[1];
69
70                         /* If a section was open, close it. */
71                         if (currsection != NULL) {
72                                 lcpvret = lc_process_var(currsection, NULL, NULL, LC_FLAGS_SECTIONEND);
73                                 if (lcpvret < 0) {
74 #ifdef DEBUG
75                                         fprintf(stderr, "Invalid section terminating: \"%s\"\n", currsection);
76 #endif
77                                 }
78                                 free(currsection);
79                         }
80
81                         /* Open new section. */
82                         currsection = strdup(linebuf_ptr);
83                         lcpvret = lc_process_var(currsection, NULL, NULL, LC_FLAGS_SECTIONSTART);
84                         if (lcpvret < 0) {
85 #ifdef DEBUG
86                                 fprintf(stderr, "Invalid section: \"%s\"\n", currsection);
87 #endif
88                                 invalid_section = 1;
89                                 lc_errfile = local_lc_errfile;
90                                 lc_errline = local_lc_errline;
91                                 lc_errno = LC_ERR_INVSECTION;
92                                 retval = -1;
93                         } else {
94                                 invalid_section = 0;
95                                 ignore_section = 0;
96                         }
97
98                         if (lcpvret == LC_CBRET_IGNORESECTION) {
99                                 ignore_section = 1;
100                         }
101                         continue;
102                 }
103
104                 /* Remove leading spaces. */
105                 linebuf_ptr = &linebuf[0];
106                 while (*linebuf_ptr == ' ') {
107                         linebuf_ptr++;
108                 }
109
110                 /* Drop comments and blank lines. */
111                 if (*linebuf_ptr == ';' || *linebuf_ptr == '\0') {
112                         continue;
113                 }
114
115                 /* Don't handle things for a section that doesn't exist. */
116                 if (invalid_section == 1) {
117 #ifdef DEBUG
118                         fprintf(stderr, "Ignoring line (because invalid section): %s\n", linebuf);
119 #endif
120                         continue;
121                 }
122
123                 /* Don't process commands if this section is specifically ignored. */
124                 if (ignore_section == 1) {
125 #ifdef DEBUG
126                         fprintf(stderr, "Ignoring line (because ignored section): %s\n", linebuf);
127 #endif
128                         continue;
129                 }
130
131                 /* Find the command and the data in the line. */
132                 cmdend = sep = strpbrk(linebuf_ptr, "=");
133                 if (sep == NULL) {
134 #ifdef DEBUG
135                         fprintf(stderr, "Invalid line: \"%s\"\n", linebuf);
136 #endif
137                         continue;
138                 }
139
140                 /* Delete space at the end of the command. */
141                 cmdend--; /* It currently derefs to the seperator.. */
142                 while (*cmdend <= ' ') {
143                         *cmdend = '\0';
144                         cmdend--;
145                 }
146
147                 cmd = linebuf_ptr;
148
149                 /* Delete the seperator char and any leading space. */
150                 *sep = '\0';
151                 sep++;
152                 while (*sep == ' ' || *sep == '\t') {
153                         sep++;
154                 }
155                 value = sep;
156
157                 /* Create the fully qualified variable name. */
158                 if (currsection == NULL) {
159                         strncpy(qualifbuf, cmd, sizeof(qualifbuf) - 1);
160                 } else {
161                         snprintf(qualifbuf, sizeof(qualifbuf) - 1, "%s.%s", currsection, cmd);
162                 }
163
164                 /* Call the parent and tell them we have data. */
165                 save_lc_errno = lc_errno;
166                 lc_errno = LC_ERR_NONE;
167                 lcpvret = lc_process_var(qualifbuf, NULL, value, LC_FLAGS_VAR);
168                 if (lcpvret < 0) {
169                         if (lc_errno == LC_ERR_NONE) {
170 #ifdef DEBUG
171                                 fprintf(stderr, "Invalid command: \"%s\"\n", cmd);
172 #endif
173                                 lc_errno = LC_ERR_INVCMD;
174                         } else {
175 #ifdef DEBUG
176                                 fprintf(stderr, "Error processing command (command was valid, but an error occured, errno was set)\n");
177 #endif
178                         }
179                         lc_errfile = local_lc_errfile;
180                         lc_errline = local_lc_errline;
181                         retval = -1;
182                 } else {
183                         lc_errno = save_lc_errno;
184                 }
185         }
186
187         /* Close any open section, and clean-up. */
188         if (currsection != NULL) {
189                 lcpvret = lc_process_var(currsection, NULL, NULL, LC_FLAGS_SECTIONEND);
190                 if (lcpvret < 0) {
191 #ifdef DEBUG
192                         fprintf(stderr, "Invalid section terminating: \"%s\"\n", currsection);
193 #endif
194                 }
195                 free(currsection);
196         }
197
198         lc_fclose(configfp);
199
200         return(retval);
201 }