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