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>