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>