summaryrefslogtreecommitdiff
path: root/src/libstrongswan/utils/optionsfrom.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstrongswan/utils/optionsfrom.c')
-rw-r--r--src/libstrongswan/utils/optionsfrom.c143
1 files changed, 110 insertions, 33 deletions
diff --git a/src/libstrongswan/utils/optionsfrom.c b/src/libstrongswan/utils/optionsfrom.c
index ffa571b05..39e38cc58 100644
--- a/src/libstrongswan/utils/optionsfrom.c
+++ b/src/libstrongswan/utils/optionsfrom.c
@@ -6,8 +6,10 @@
*/
/*
- * Copyright (C) 1998, 1999 Henry Spencer.
- *
+ * Copyright (C) 2007-2008 Andreas Steffen
+ *
+ * Hochschule fuer Technik Rapperswil
+ *
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Library General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at your
@@ -18,6 +20,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
* License for more details.
*
+ * RCSID $Id$
*/
#include <stdio.h>
@@ -30,29 +33,64 @@
#include "optionsfrom.h"
#define MAX_USES 20 /* loop-detection limit */
-#define SOME_ARGS 10 /* first guess at how many arguments we'll need */
+#define MORE_ARGS 10 /* first guess at how many arguments we'll need */
/*
* Defined in header.
*/
-bool optionsfrom(const char *filename, int *argcp, char **argvp[], int optind)
-{
- static int nuses = 0;
+
+typedef struct private_options_t private_options_t;
+
+/**
+ * Private data of a options_t object.
+ */
+struct private_options_t {
+ /**
+ * Public interface
+ */
+ options_t public;
+
+ /**
+ * reallocated argv array
+ */
char **newargv;
+
+ /**
+ * number of free arguments in newargv
+ */
+ int room;
+
+ /**
+ * number of included option files
+ */
+ int nuses;
+
+ /**
+ * allocated space for option files
+ */
+ char *buffers[MAX_USES];
+};
+
+/**
+ * Defined in header
+ */
+bool from(private_options_t *this, char *filename, int *argcp, char **argvp[],
+ int optind)
+{
int newargc;
int next; /* place for next argument */
- int room; /* how many more new arguments we can hold */
+ char **newargv;
size_t bytes;
- chunk_t chunk, src, line, token;
+ chunk_t src, line, token;
bool good = TRUE;
int linepos = 0;
FILE *fd;
/* avoid endless loops with recursive --optionsfrom arguments */
- nuses++;
- if (nuses >= MAX_USES)
+ this->nuses++;
+ if (this->nuses >= MAX_USES)
{
- DBG1("optionsfrom called %d times - looping?", (*argvp)[0], nuses);
+ DBG1("optionsfrom called %d times by \"%s\" - looping?", this->nuses + 1, (*argvp)[0]);
return FALSE;
}
@@ -66,26 +104,31 @@ bool optionsfrom(const char *filename, int *argcp, char **argvp[], int optind)
/* determine the file size */
fseek(fd, 0, SEEK_END);
- chunk.len = ftell(fd);
+ src.len = ftell(fd);
rewind(fd);
/* allocate one byte more just in case of a missing final newline */
- chunk.ptr = malloc(chunk.len + 1);
+ src.ptr = this->buffers[this->nuses] = malloc(src.len + 1);
/* read the whole file into a chunk */
- bytes = fread(chunk.ptr, 1, chunk.len, fd);
+ bytes = fread(src.ptr, 1, src.len, fd);
fclose(fd);
- newargc = *argcp + SOME_ARGS;
- newargv = malloc((newargc + 1) * sizeof(char *));
+ if (this->room)
+ {
+ newargc = *argcp;
+ newargv = malloc((newargc + 1 + this->room) * sizeof(char *));
+ }
+ else
+ {
+ newargc = *argcp + MORE_ARGS;
+ this->room = MORE_ARGS;
+ newargv = malloc((newargc + 1) * sizeof(char *));
+ }
memcpy(newargv, *argvp, optind * sizeof(char *));
- room = SOME_ARGS;
next = optind;
newargv[next] = NULL;
- /* we keep the chunk pointer so that we can still free it */
- src = chunk;
-
while (fetchline(&src, &line) && good)
{
linepos++;
@@ -116,11 +159,11 @@ bool optionsfrom(const char *filename, int *argcp, char **argvp[], int optind)
}
/* do we have to allocate more memory for additional arguments? */
- if (room == 0)
+ if (this->room == 0)
{
- newargc += SOME_ARGS;
- newargv = realloc(newargv, (newargc+1) * sizeof(char *));
- room = SOME_ARGS;
+ newargc += MORE_ARGS;
+ newargv = realloc(newargv, (newargc + 1) * sizeof(char *));
+ this->room = MORE_ARGS;
}
/* terminate the token by replacing the delimiter with a null character */
@@ -129,20 +172,54 @@ bool optionsfrom(const char *filename, int *argcp, char **argvp[], int optind)
/* assign the token to the next argument */
newargv[next] = token.ptr;
next++;
- room--;
+ this->room--;
}
}
- if (!good) /* error of some kind */
+ /* assign newargv to argv */
+ if (good)
{
- free(chunk.ptr);
- free(newargv);
- return FALSE;
+ memcpy(newargv + next, *argvp + optind, (*argcp + 1 - optind) * sizeof(char *));
+ *argcp += next - optind;
+ *argvp = newargv;
}
- memcpy(newargv + next, *argvp + optind, (*argcp + 1 - optind) * sizeof(char *));
- *argcp += next - optind;
- *argvp = newargv;
- return TRUE;
+ /* keep a pointer to the latest newargv and free any earlier version */
+ free(this->newargv);
+ this->newargv = newargv;
+
+ return good;
+}
+
+/**
+ * Defined in header
+ */
+void destroy(private_options_t *this)
+{
+ while (this->nuses >= 0)
+ {
+ free(this->buffers[this->nuses--]);
+ }
+ free(this->newargv);
+ free(this);
}
+/*
+ * Defined in header
+ */
+options_t *options_create(void)
+{
+ private_options_t *this = malloc_thing(private_options_t);
+
+ /* initialize */
+ this->newargv = NULL;
+ this->room = 0;
+ this->nuses = -1;
+ memset(this->buffers, '\0', MAX_USES);
+
+ /* public functions */
+ this->public.from = (bool (*) (options_t*,char*,int*,char***,int))from;
+ this->public.destroy = (void (*) (options_t*))destroy;
+
+ return &this->public;
+}