1 #include "compat.h"
2 #include "libconfig.h"
3 #include "libconfig_private.h"
4 #include "conf_section.h"
6 #ifdef HAVE_STDIO_H
7 #include <stdio.h>
8 #endif
10 #ifdef HAVE_STRING_H
11 #include <string.h>
12 #endif
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;
28 local_lc_errfile = configfile;
29 local_lc_errline = 0;
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 }
38 configfp = lc_fopen(configfile, "r");
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 }
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 }
56 local_lc_errline++;
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 }
65 /* Handle section header. */
66 if (linebuf[0] == '[' && linebuf[strlen(linebuf) - 1] == ']') {
67 linebuf[strlen(linebuf) - 1] = '\0';
68 linebuf_ptr = &linebuf[1];
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 }
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 }
98 if (lcpvret == LC_CBRET_IGNORESECTION) {
99 ignore_section = 1;
100 }
101 continue;
102 }
104 /* Remove leading spaces. */
105 linebuf_ptr = &linebuf[0];
106 while (*linebuf_ptr == ' ') {
107 linebuf_ptr++;
108 }
110 /* Drop comments and blank lines. */
111 if (*linebuf_ptr == ';' || *linebuf_ptr == '\0') {
112 continue;
113 }
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 }
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 }
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 }
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 }
147 cmd = linebuf_ptr;
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;
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 }
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 }
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 }
198 lc_fclose(configfp);
200 return(retval);
201 }