Annotation of embedaddon/strongswan/src/libstrongswan/utils/optionsfrom.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2007-2008 Andreas Steffen
                      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 <stdio.h>
                     17: #include <errno.h>
                     18: 
                     19: #include <library.h>
                     20: #include <utils/debug.h>
                     21: #include <utils/lexparser.h>
                     22: 
                     23: #include "optionsfrom.h"
                     24: 
                     25: #define        MAX_USES         20             /* loop-detection limit */
                     26: #define        MORE_ARGS        10             /* first guess at how many arguments we'll need */
                     27: 
                     28: /*
                     29:  * Defined in header.
                     30:  */
                     31: 
                     32: typedef struct private_options_t private_options_t;
                     33: 
                     34: /**
                     35:  * Private data of a options_t object.
                     36:  */
                     37: struct private_options_t {
                     38:        /**
                     39:         * Public interface
                     40:         */
                     41:        options_t public;
                     42: 
                     43:        /**
                     44:         * reallocated argv array
                     45:         */
                     46:        char **newargv;
                     47: 
                     48:        /**
                     49:         * number of free arguments in newargv
                     50:         */
                     51:        int room;
                     52: 
                     53:        /**
                     54:         * number of included option files
                     55:        */
                     56:        int nuses;
                     57: 
                     58:        /**
                     59:         * allocated space for option files
                     60:         */
                     61:        char *buffers[MAX_USES];
                     62: };
                     63: 
                     64: METHOD(options_t, from, bool,
                     65:        private_options_t *this, char *filename, int *argcp, char **argvp[], int optind)
                     66: {
                     67:        int newargc;
                     68:        int next;                       /* place for next argument */
                     69:        char **newargv;
                     70:        chunk_t src, line, token;
                     71:        bool good = TRUE;
                     72:        int linepos = 0;
                     73:        FILE *fd;
                     74: 
                     75:        /* avoid endless loops with recursive --optionsfrom arguments */
                     76:        this->nuses++;
                     77:        if (this->nuses >= MAX_USES)
                     78:        {
                     79:                DBG1(DBG_LIB, "optionsfrom called %d times by \"%s\" - looping?",
                     80:                         this->nuses + 1, (*argvp)[0]);
                     81:                return FALSE;
                     82:        }
                     83: 
                     84:        fd = fopen(filename, "r");
                     85:        if (fd == NULL)
                     86:        {
                     87:                DBG1(DBG_LIB, "optionsfrom: unable to open file '%s': %s",
                     88:                         filename, strerror(errno));
                     89:                return FALSE;
                     90:        }
                     91: 
                     92:        /* determine the file size */
                     93:        if (fseek(fd, 0, SEEK_END) == -1 || (src.len = ftell(fd)) == -1)
                     94:        {
                     95:                DBG1(DBG_LIB, "optionsfrom: unable to determine size of '%s': %s",
                     96:                         filename, strerror(errno));
                     97:                fclose(fd);
                     98:                return FALSE;
                     99:        }
                    100:        rewind(fd);
                    101: 
                    102:        /* allocate one byte more just in case of a missing final newline */
                    103:        src.ptr = this->buffers[this->nuses] = malloc(src.len + 1);
                    104: 
                    105:        /* read the whole file into a chunk */
                    106:        if (fread(src.ptr, 1, src.len, fd) != src.len)
                    107:        {
                    108:                DBG1(DBG_LIB, "optionsfrom: unable to read file '%s': %s",
                    109:                         filename, strerror(errno));
                    110:                free(src.ptr);
                    111:                fclose(fd);
                    112:                return FALSE;
                    113:        }
                    114:        fclose(fd);
                    115: 
                    116:        if (this->room)
                    117:        {
                    118:                newargc = *argcp;
                    119:                newargv = malloc((newargc + 1 + this->room) * sizeof(char *));
                    120:        }
                    121:        else
                    122:        {
                    123:                newargc = *argcp + MORE_ARGS;
                    124:                this->room = MORE_ARGS;
                    125:                newargv = malloc((newargc + 1) * sizeof(char *));
                    126:        }
                    127:        memcpy(newargv, *argvp, optind * sizeof(char *));
                    128:        next = optind;
                    129:        newargv[next] = NULL;
                    130: 
                    131:        while (fetchline(&src, &line) && good)
                    132:        {
                    133:                linepos++;
                    134:                while (eat_whitespace(&line))
                    135:                {
                    136:                        if (*line.ptr == '"'|| *line.ptr == '\'')
                    137:                        {
                    138:                                char delimiter = *line.ptr;
                    139: 
                    140:                                line.ptr++;
                    141:                                line.len--;
                    142:                                if (!extract_token(&token, delimiter, &line))
                    143:                                {
                    144:                                        DBG1(DBG_LIB, "optionsfrom: missing terminator at %s:%d",
                    145:                                                 filename, linepos);
                    146:                                        good = FALSE;
                    147:                                        break;
                    148:                                }
                    149:                        }
                    150:                        else
                    151:                        {
                    152:                                if (!extract_token(&token, ' ', &line))
                    153:                                {
                    154:                                        /* last token in a line */
                    155:                                        token = line;
                    156:                                        line.len = 0;
                    157:                                }
                    158:                        }
                    159: 
                    160:                        /* do we have to allocate more memory for additional arguments? */
                    161:                        if (this->room == 0)
                    162:                        {
                    163:                                newargc += MORE_ARGS;
                    164:                                newargv = realloc(newargv, (newargc + 1) * sizeof(char *));
                    165:                                this->room = MORE_ARGS;
                    166:                        }
                    167: 
                    168:                        /* terminate the token by replacing the delimiter with a null character */
                    169:                        *(token.ptr + token.len) = '\0';
                    170: 
                    171:                        /* assign the token to the next argument */
                    172:                        newargv[next] = token.ptr;
                    173:                        next++;
                    174:                        this->room--;
                    175:                }
                    176:        }
                    177: 
                    178:        /* assign newargv to argv */
                    179:        if (good)
                    180:        {
                    181:                memcpy(newargv + next, *argvp + optind, (*argcp + 1 - optind) * sizeof(char *));
                    182:                *argcp += next - optind;
                    183:                *argvp = newargv;
                    184:        }
                    185: 
                    186:        /* keep a pointer to the latest newargv and free any earlier version */
                    187:        free(this->newargv);
                    188:        this->newargv = newargv;
                    189: 
                    190:        return good;
                    191: }
                    192: 
                    193: METHOD(options_t, destroy, void,
                    194:        private_options_t *this)
                    195: {
                    196:        while (this->nuses >= 0)
                    197:        {
                    198:                free(this->buffers[this->nuses--]);
                    199:        }
                    200:        free(this->newargv);
                    201:        free(this);
                    202: }
                    203: 
                    204: /*
                    205:  * Defined in header
                    206:  */
                    207: options_t *options_create(void)
                    208: {
                    209:        private_options_t *this;
                    210: 
                    211:        INIT(this,
                    212:                .public = {
                    213:                        .from = _from,
                    214:                        .destroy = _destroy,
                    215: 
                    216:                },
                    217:                .nuses = -1,
                    218:        );
                    219: 
                    220:        return &this->public;
                    221: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>