Annotation of embedaddon/strongswan/src/libstrongswan/utils/parser_helper.c, revision 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>