]>
Commit | Line | Data |
---|---|---|
3bbb7e14 | 1 | Index: conf.c |
2 | =================================================================== | |
3 | RCS file: /cvsroot/poldek/poldek/conf.c,v | |
4 | retrieving revision 1.85 | |
5 | retrieving revision 1.86 | |
6 | diff -w -u -r1.85 -r1.86 | |
7 | --- conf.c 28 Jun 2007 15:58:20 -0000 1.85 | |
8 | +++ conf.c 30 Jan 2008 15:16:41 -0000 1.86 | |
9 | @@ -22,6 +22,8 @@ | |
10 | #include <unistd.h> | |
11 | #include <fnmatch.h> | |
12 | #include <sys/param.h> /* for PATH_MAX */ | |
13 | +#include <sys/types.h> | |
14 | +#include <dirent.h> | |
15 | ||
16 | #include <trurl/nhash.h> | |
17 | #include <trurl/narray.h> | |
18 | @@ -44,6 +46,7 @@ | |
19 | ||
20 | static const char *global_tag = "global"; | |
21 | static const char *include_tag = "%include"; | |
22 | +static const char *includedir_tag = "%includedir"; | |
23 | ||
24 | static struct poldek_conf_tag unknown_tag = { | |
25 | NULL, CONF_TYPE_STRING | CONF_TYPE_F_ENV | CONF_TYPE_F_MULTI_EXCL, | |
26 | @@ -719,14 +722,19 @@ | |
27 | %include path|url | |
28 | %include_<section_name> path|url -> load only <section_name> | |
29 | */ | |
30 | -static char *include_path(char *path, size_t size, char *line, char **sectnam, | |
31 | +static char *prepare_include_path(const char *tag, char *path, size_t size, | |
32 | + char *line, char **sectnam, | |
33 | tn_hash *ht, tn_hash *ht_global) | |
34 | { | |
35 | char expenval[PATH_MAX], expval[PATH_MAX], *p; | |
36 | ||
37 | + if (n_str_eq(tag, include_tag)) | |
38 | *sectnam = NULL; | |
39 | - p = line + strlen(include_tag); | |
40 | - if (*p == '_') { | |
41 | + else | |
42 | + n_assert(sectnam == NULL); /* irrelevant for non %include */ | |
43 | + | |
44 | + p = line + strlen(tag); | |
45 | + if (n_str_eq(tag, include_tag) && *p == '_') { | |
46 | p++; | |
47 | *sectnam = p; | |
48 | while (!isspace(*p)) | |
49 | @@ -756,7 +764,6 @@ | |
50 | tn_array *arr_sect; | |
51 | tn_hash *ht_sect = NULL; | |
52 | ||
53 | - | |
54 | arr_sect = n_hash_get(htconf, sectnam); | |
55 | DBGF("[%s] sect=%p, is_multi=%d\n", sectnam, sect, | |
56 | sect ? sect->is_multi : -1); | |
57 | @@ -927,8 +934,54 @@ | |
58 | } | |
59 | } | |
60 | ||
61 | -static | |
62 | -tn_hash *do_ldconf(tn_hash *af_htconf, | |
63 | +static tn_array *includedir_files(const char *dirpath, const char *ppath) | |
64 | +{ | |
65 | + tn_array *configs = NULL; | |
66 | + struct dirent *ent; | |
67 | + DIR *dir; | |
68 | + char *sep = "/", tmpath[PATH_MAX]; | |
69 | + | |
70 | + | |
71 | + if (*dirpath != '/' && strrchr(ppath, '/') != NULL) { | |
72 | + char *s; | |
73 | + int n; | |
74 | + | |
75 | + n = n_snprintf(tmpath, sizeof(tmpath), "%s", ppath); | |
76 | + s = strrchr(tmpath, '/'); | |
77 | + n_assert(s); | |
78 | + | |
79 | + n_snprintf(s + 1, sizeof(tmpath) - n, "%s", dirpath); | |
80 | + dirpath = tmpath; | |
81 | + } | |
82 | + | |
83 | + if ((dir = opendir(dirpath)) == NULL) { | |
84 | + logn(LOGERR, "%%includedir %s: %m", dirpath); | |
85 | + return NULL; | |
86 | + } | |
87 | + | |
88 | + configs = n_array_new(32, free, (tn_fn_cmp)strcmp); | |
89 | + | |
90 | + while ((ent = readdir(dir))) { | |
91 | + char path[PATH_MAX]; | |
92 | + int n; | |
93 | + | |
94 | + if (fnmatch("*.conf", ent->d_name, 0) != 0) | |
95 | + continue; | |
96 | + | |
97 | + n = n_snprintf(path, sizeof(path), "%s%s%s", dirpath, sep, ent->d_name); | |
98 | + n_array_push(configs, n_strdupl(path, n)); | |
99 | + } | |
100 | + closedir(dir); | |
101 | + | |
102 | + n_array_sort(configs); | |
103 | + if (n_array_size(configs) == 0) | |
104 | + n_array_cfree(&configs); | |
105 | + | |
106 | + return configs; | |
107 | +} | |
108 | + | |
109 | + | |
110 | +static tn_hash *do_ldconf(tn_hash *af_htconf, | |
111 | const char *path, const char *parent_path, | |
112 | const char *section_to_load, unsigned flags) | |
113 | { | |
114 | @@ -974,32 +1027,67 @@ | |
115 | n_hash_insert(af_htconf, af->path, NULL); | |
116 | ||
117 | while (n_stream_gets(af->vf->vf_tnstream, buf, sizeof(buf) - 1)) { | |
118 | - char *name, *value, *p; | |
119 | + char *name, *value, *line; | |
120 | ||
121 | nline++; | |
122 | - p = eat_wws(buf); | |
123 | - if (*p == '#' || *p == '\0') | |
124 | + line = eat_wws(buf); | |
125 | + if (*line == '#' || *line == '\0') | |
126 | + continue; | |
127 | + | |
128 | + /* %includedir <directory> */ | |
129 | + if (strncmp(line, includedir_tag, strlen(includedir_tag)) == 0) { | |
130 | + char ipath[PATH_MAX]; | |
131 | + tn_array *configs; | |
132 | + int i; | |
133 | + | |
134 | + | |
135 | + if (flags & POLDEK_LDCONF_NOINCLUDE) | |
136 | + continue; | |
137 | + | |
138 | + line = prepare_include_path(includedir_tag, ipath, sizeof(ipath), line, | |
139 | + NULL, ht_sect, ht); | |
140 | + | |
141 | + if (line == NULL) { | |
142 | + logn(LOGERR, _("%s:%d: wrong %%includedir"), af->path, nline); | |
143 | + is_err = 1; | |
144 | + goto l_end; | |
145 | + } | |
146 | + DBGF("includedir %s\n", line); | |
147 | + | |
148 | + if ((configs = includedir_files(line, af->path)) == NULL) | |
149 | continue; | |
150 | ||
151 | - if (strncmp(p, include_tag, strlen(include_tag)) == 0) { | |
152 | + for (i=0; i < n_array_size(configs); i++) { | |
153 | + char *path = n_array_nth(configs, i); | |
154 | + | |
155 | + if (!do_ldconf(af_htconf, path, af->path, NULL, flags)) { | |
156 | + n_array_free(configs); | |
157 | + is_err = 1; | |
158 | + goto l_end; | |
159 | + } | |
160 | + } | |
161 | + n_array_free(configs); | |
162 | + continue; | |
163 | + } | |
164 | + | |
165 | + /* %include <file> */ | |
166 | + if (strncmp(line, include_tag, strlen(include_tag)) == 0) { | |
167 | char *section_to_load = NULL, ipath[PATH_MAX]; | |
168 | - tn_hash *inc_ht; | |
169 | ||
170 | if (flags & POLDEK_LDCONF_NOINCLUDE) | |
171 | continue; | |
172 | ||
173 | - p = include_path(ipath, sizeof(ipath), p, §ion_to_load, | |
174 | - ht_sect, ht); | |
175 | + line = prepare_include_path(include_tag, ipath, sizeof(ipath), | |
176 | + line, §ion_to_load, ht_sect, ht); | |
177 | ||
178 | - if (p == NULL) { | |
179 | + if (line == NULL) { | |
180 | logn(LOGERR, _("%s:%d: wrong %%include"), af->path, nline); | |
181 | is_err = 1; | |
182 | goto l_end; | |
183 | } | |
184 | ||
185 | - DBGF("open %s %s, i %s\n", p, sectnam, inc_sectnam); | |
186 | - inc_ht = do_ldconf(af_htconf, p, af->path, section_to_load, flags); | |
187 | - if (inc_ht == NULL) { | |
188 | + DBGF("open %s %s, i %s\n", line, sectnam, inc_sectnam); | |
189 | + if (!do_ldconf(af_htconf, line, af->path, section_to_load, flags)) { | |
190 | is_err = 1; | |
191 | goto l_end; | |
192 | } | |
193 | @@ -1008,18 +1096,18 @@ | |
194 | ||
195 | read_continuation(af, buf, sizeof(buf), &nline); | |
196 | ||
197 | - if (*p == '%') /* unknown directive */ | |
198 | + if (*line == '%') /* unknown directive */ | |
199 | continue; | |
200 | ||
201 | - if (*p == '[') { /* section */ | |
202 | + if (*line == '[') { /* section */ | |
203 | const struct poldek_conf_section *sect = NULL; | |
204 | ||
205 | - p++; | |
206 | - name = p; | |
207 | + line++; | |
208 | + name = line; | |
209 | ||
210 | - while (isalnum(*p) || *p == '-') | |
211 | - p++; | |
212 | - *p = '\0'; | |
213 | + while (isalnum(*line) || *line == '-') | |
214 | + line++; | |
215 | + *line = '\0'; | |
216 | ||
217 | if (validate && (sect = find_section(name)) == NULL) { | |
218 | logn(LOGERR, _("%s:%d: '%s': invalid section name"), | |
219 | @@ -1036,7 +1124,7 @@ | |
220 | continue; | |
221 | } | |
222 | ||
223 | - if (!split_option_line(p, &name, &value, af->path, nline)) | |
224 | + if (!split_option_line(line, &name, &value, af->path, nline)) | |
225 | goto l_end; | |
226 | ||
227 | if (ht_sect) { |