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>