more libstrongswan-like error handling in optionsfrom

This commit is contained in:
Martin Willi
2007-10-03 15:02:29 +00:00
parent 8bcdf1562c
commit 6a8e7381d0
3 changed files with 36 additions and 53 deletions
+29 -47
View File
@@ -21,35 +21,47 @@
*/ */
#include <stdio.h> #include <stdio.h>
#include <errno.h>
#include <library.h> #include <library.h>
#include <debug.h>
#include <utils/lexparser.h> #include <utils/lexparser.h>
#include "optionsfrom.h" #include "optionsfrom.h"
#define MAX_USES 100 /* loop-detection limit */ #define MAX_USES 20 /* loop-detection limit */
#define SOME_ARGS 10 /* first guess at how many arguments we'll need */ #define SOME_ARGS 10 /* first guess at how many arguments we'll need */
/** /*
* parse the options from a file * Defined in header.
* does not alter the existing arguments, but does relocate and alter
* the argv pointer vector.
*/ */
static err_t parse_options_file(const char *filename, int *argcp, char **argvp[], int optind) bool optionsfrom(const char *filename, int *argcp, char **argvp[], int optind)
{ {
static int nuses = 0;
char **newargv; char **newargv;
int newargc; int newargc;
int next; /* place for next argument */ int next; /* place for next argument */
int room; /* how many more new arguments we can hold */ int room; /* how many more new arguments we can hold */
size_t bytes; size_t bytes;
chunk_t chunk, src, line, token; chunk_t chunk, src, line, token;
err_t ugh = NULL; bool good = TRUE;
int linepos = 0;
FILE *fd;
FILE *fd = fopen(filename, "r"); /* avoid endless loops with recursive --optionsfrom arguments */
nuses++;
if (nuses >= MAX_USES)
{
DBG1("optionsfrom called %d times - looping?", (*argvp)[0], nuses);
return FALSE;
}
fd = fopen(filename, "r");
if (fd == NULL) if (fd == NULL)
{ {
return "unable to open file"; DBG1("optionsfrom: unable to open file '%s': %s",
filename, strerror(errno));
return FALSE;
} }
/* determine the file size */ /* determine the file size */
@@ -74,8 +86,9 @@ static err_t parse_options_file(const char *filename, int *argcp, char **argvp[]
/* we keep the chunk pointer so that we can still free it */ /* we keep the chunk pointer so that we can still free it */
src = chunk; src = chunk;
while (fetchline(&src, &line) && ugh == NULL) while (fetchline(&src, &line) && good)
{ {
linepos++;
while (eat_whitespace(&line)) while (eat_whitespace(&line))
{ {
if (*line.ptr == '"'|| *line.ptr == '\'') if (*line.ptr == '"'|| *line.ptr == '\'')
@@ -86,7 +99,9 @@ static err_t parse_options_file(const char *filename, int *argcp, char **argvp[]
line.len--; line.len--;
if (!extract_token(&token, delimiter, &line)) if (!extract_token(&token, delimiter, &line))
{ {
ugh = "missing terminating delimiter"; DBG1("optionsfrom: missing terminator at %s:%d",
filename, linepos);
good = FALSE;
break; break;
} }
} }
@@ -118,49 +133,16 @@ static err_t parse_options_file(const char *filename, int *argcp, char **argvp[]
} }
} }
if (ugh) /* error of some kind */ if (!good) /* error of some kind */
{ {
free(chunk.ptr); free(chunk.ptr);
free(newargv); free(newargv);
return ugh; return FALSE;
} }
memcpy(newargv + next, *argvp + optind, (*argcp + 1 - optind) * sizeof(char *)); memcpy(newargv + next, *argvp + optind, (*argcp + 1 - optind) * sizeof(char *));
*argcp += next - optind; *argcp += next - optind;
*argvp = newargv; *argvp = newargv;
return NULL; return TRUE;
} }
/*
* Defined in header.
*/
err_t optionsfrom(const char *filename, int *argcp, char **argvp[], int optind, FILE *errfile)
{
static int nuses = 0;
err_t ugh = NULL;
/* avoid endless loops with recursive --optionsfrom arguments */
if (errfile != NULL)
{
nuses++;
if (nuses >= MAX_USES)
{
fprintf(errfile, "%s: optionsfrom called %d times - looping?\n",
(*argvp)[0], nuses);
exit(2);
}
}
else
{
nuses = 0;
}
ugh = parse_options_file(filename, argcp, argvp, optind);
if (ugh != NULL && errfile != NULL)
{
fprintf(errfile, "%s: optionsfrom failed: %s\n", (*argvp)[0], ugh);
exit(2);
}
return ugh;
}
+2 -3
View File
@@ -30,9 +30,8 @@
* @param argcp pointer to argc * @param argcp pointer to argc
* @param argvp pointer to argv[] * @param argvp pointer to argv[]
* @param optind current optind, number of next argument * @param optind current optind, number of next argument
* @param errfile where to report errors (NULL means return) * @return TRUE if optionsfrom parsing successful
* @return NULL if successful, error string otherwise
*/ */
err_t optionsfrom(const char *filename, int *argcp, char **argvp[], int optind, FILE *errfile); bool optionsfrom(const char *filename, int *argcp, char **argvp[], int optind);
#endif /*OPTIONSFROM_H_*/ #endif /*OPTIONSFROM_H_*/
+4 -2
View File
@@ -291,8 +291,10 @@ int main(int argc, char **argv)
{ {
snprintf(path, BUF_LEN, "%s/%s", OPENAC_PATH, optarg); snprintf(path, BUF_LEN, "%s/%s", OPENAC_PATH, optarg);
} }
optionsfrom(path, &argc, &argv, optind, stderr); if (!optionsfrom(path, &argc, &argv, optind))
/* does not return on error */ {
exit(1);
}
} }
continue; continue;