Annotation of embedaddon/strongswan/src/libstrongswan/utils/parser_helper.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2014 Tobias Brunner
3: * HSR Hochschule fuer Technik Rapperswil
4: *
5: * This program is free software; you can redistribute it and/or modify it
6: * under the terms of the GNU General Public License as published by the
7: * Free Software Foundation; either version 2 of the License, or (at your
8: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9: *
10: * This program is distributed in the hope that it will be useful, but
11: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13: * for more details.
14: */
15:
16: #include <limits.h>
17: #include <ctype.h>
18: #include <stdarg.h>
19:
20: #include "parser_helper.h"
21:
22: #include <collections/array.h>
23:
24: typedef struct private_parser_helper_t private_parser_helper_t;
25: typedef struct parser_helper_file_t parser_helper_file_t;
26:
27: struct private_parser_helper_t {
28:
29: /**
30: * Public interface.
31: */
32: parser_helper_t public;
33:
34: /**
35: * Stack of included files, as parser_helper_file_t.
36: */
37: array_t *files;
38:
39: /**
40: * Helper for parsing strings.
41: */
42: bio_writer_t *writer;
43: };
44:
45: struct parser_helper_file_t {
46:
47: /**
48: * File name
49: */
50: char *name;
51:
52: /**
53: * File stream
54: */
55: FILE *file;
56:
57: /**
58: * Enumerator of paths matching the most recent inclusion pattern.
59: */
60: enumerator_t *matches;
61: };
62:
63: /**
64: * Destroy the given file data.
65: */
66: static void parser_helper_file_destroy(parser_helper_file_t *this)
67: {
68: if (this->file)
69: {
70: fclose(this->file);
71: }
72: free(this->name);
73: DESTROY_IF(this->matches);
74: free(this);
75: }
76:
77: /**
78: * Returns the current file, if any.
79: */
80: static parser_helper_file_t *current_file(private_parser_helper_t *this)
81: {
82: parser_helper_file_t *file;
83:
84: array_get(this->files, ARRAY_TAIL, &file);
85: if (file->name)
86: {
87: return file;
88: }
89: return NULL;
90: }
91:
92: METHOD(parser_helper_t, file_next, FILE*,
93: private_parser_helper_t *this)
94: {
95: parser_helper_file_t *file, *next;
96: char *name;
97:
98: array_get(this->files, ARRAY_TAIL, &file);
99: if (!file->matches && file->name)
100: {
101: array_remove(this->files, ARRAY_TAIL, NULL);
102: parser_helper_file_destroy(file);
103: /* continue with previous includes, if any */
104: array_get(this->files, ARRAY_TAIL, &file);
105: }
106: if (file->matches)
107: {
108: while (file->matches->enumerate(file->matches, &name, NULL))
109: {
110: INIT(next,
111: .name = strdup(name),
112: .file = fopen(name, "r"),
113: );
114:
115: if (next->file)
116: {
117: array_insert(this->files, ARRAY_TAIL, next);
118: return next->file;
119: }
120: PARSER_DBG2(&this->public, "unable to open '%s'", name);
121: parser_helper_file_destroy(next);
122: }
123: file->matches->destroy(file->matches);
124: file->matches = NULL;
125: }
126: return NULL;
127: }
128:
129: METHOD(parser_helper_t, file_include, void,
130: private_parser_helper_t *this, char *pattern)
131: {
132: parser_helper_file_t *file;
133: char pat[PATH_MAX];
134:
135: array_get(this->files, ARRAY_TAIL, &file);
136: if (!pattern || !*pattern)
137: {
138: PARSER_DBG1(&this->public, "no include pattern specified, ignored");
139: file->matches = enumerator_create_empty();
140: return;
141: }
142:
143: if (!file->name || path_absolute(pattern))
144: { /* absolute path */
145: if (snprintf(pat, sizeof(pat), "%s", pattern) >= sizeof(pat))
146: {
147: PARSER_DBG1(&this->public, "include pattern too long, ignored");
148: file->matches = enumerator_create_empty();
149: return;
150: }
151: }
152: else
153: { /* base relative paths to the directory of the current file */
154: char *dir = path_dirname(file->name);
155: if (snprintf(pat, sizeof(pat), "%s%s%s", dir, DIRECTORY_SEPARATOR,
156: pattern) >= sizeof(pat))
157: {
158: PARSER_DBG1(&this->public, "include pattern too long, ignored");
159: free(dir);
160: file->matches = enumerator_create_empty();
161: return;
162: }
163: free(dir);
164: }
165:
166: file->matches = enumerator_create_glob(pat);
167: if (!file->matches)
168: { /* if glob(3) is not available, try to load pattern directly */
169: file->matches = enumerator_create_single(strdup(pat), free);
170: }
171: }
172:
173: METHOD(parser_helper_t, string_init, void,
174: private_parser_helper_t *this)
175: {
176: chunk_t data;
177:
178: data = this->writer->extract_buf(this->writer);
179: chunk_free(&data);
180: }
181:
182: METHOD(parser_helper_t, string_add, void,
183: private_parser_helper_t *this, char *str)
184: {
185: this->writer->write_data(this->writer, chunk_from_str(str));
186: }
187:
188: METHOD(parser_helper_t, string_get, char*,
189: private_parser_helper_t *this)
190: {
191: chunk_t data;
192:
193: this->writer->write_data(this->writer, chunk_from_chars('\0'));
194: data = this->writer->extract_buf(this->writer);
195: return data.ptr;
196: }
197:
198: METHOD(parser_helper_t, destroy, void,
199: private_parser_helper_t *this)
200: {
201: array_destroy_function(this->files, (void*)parser_helper_file_destroy, NULL);
202: this->writer->destroy(this->writer);
203: free(this);
204: }
205:
206: /**
207: * Described in header
208: */
209: void parser_helper_log(int level, parser_helper_t *ctx, char *fmt, ...)
210: {
211: private_parser_helper_t *this = (private_parser_helper_t*)ctx;
212: parser_helper_file_t *file;
213: char msg[8192];
214: va_list args;
215: int line;
216:
217: va_start(args, fmt);
218: vsnprintf(msg, sizeof(msg), fmt, args);
219: va_end(args);
220:
221: file = current_file(this);
222: line = ctx->get_lineno ? ctx->get_lineno(ctx->scanner) : 0;
223: if (file)
224: {
225: dbg(DBG_CFG, level, "%s:%d: %s", file->name, line, msg);
226: }
227: else
228: {
229: dbg(DBG_CFG, level, "%s", msg);
230: }
231: }
232:
233: /**
234: * Described in header
235: */
236: parser_helper_t *parser_helper_create(void *context)
237: {
238: private_parser_helper_t *this;
239: parser_helper_file_t *sentinel;
240:
241: INIT(this,
242: .public = {
243: .context = context,
244: .file_include = _file_include,
245: .file_next = _file_next,
246: .string_init = _string_init,
247: .string_add = _string_add,
248: .string_get = _string_get,
249: .destroy = _destroy,
250: },
251: .files = array_create(0, 0),
252: .writer = bio_writer_create(0),
253: );
254:
255: INIT(sentinel,
256: .name = NULL,
257: );
258: array_insert(this->files, ARRAY_TAIL, sentinel);
259:
260: return &this->public;
261: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>