blob: d017ccd519c9a9b4a7a99fb07ceafb7e27362f0c [file] [log] [blame]
/*
* config_parser.c
*
* Configuration file parser for userland suspend tools
*
* Copyright (C) 2006 Rafael J. Wysocki <rjw@sisk.pl>
*
* This file is released under the GPLv2.
*
*/
#include "config.h"
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <ctype.h>
#include <getopt.h>
#include "config_parser.h"
#include "encrypt.h"
int parse_line(char *str, struct config_par *parv)
{
char *fmt, *end;
int error = 0;
int i, k;
/* Skip white space */
while (isspace(*str))
str++;
/* Skip the lines containing white space only */
if (!*str)
goto cleanup;
/* Ignore comments */
if (*str == '#')
goto cleanup;
/* Compare with parameter names */
for (i=0; parv[i].name; i++) {
k = strlen(parv[i].name);
if (!strncmp(parv[i].name, str, k)) {
if (!parv[i].ptr)
break;
str += k;
while (isblank(*str))
str++;
if (*str != ':' && *str != '=') {
error = -EINVAL;
break;
}
str++;
while (isblank(*str))
str++;
end = str + strlen(str);
while (end > str && isspace(*--end))
*end = '\0';
if (*str) {
fmt = parv[i].fmt;
if (!strncmp(fmt, "%s", 2))
strncpy(parv[i].ptr, str,
parv[i].len - 1);
else {
if (sscanf(str, fmt, parv[i].ptr) <= 0)
error = -EINVAL;
}
break;
}
}
}
if (!parv[i].name) {
error = -EINVAL;
}
cleanup:
return error;
}
/**
* parse - read and parse the configuration file
*/
int parse(char *my_name, char *file_name, struct config_par *parv)
{
char buf[MAX_STR_LEN];
char *str;
FILE *file;
int error, i;
file = fopen(file_name, "r");
if (!file) {
fprintf(stderr, "%s: Could not open configuration file\n",
my_name);
return -errno;
}
error = 0;
i = 0;
do {
str = fgets(buf, MAX_STR_LEN, file);
if (!str)
break;
i++;
error = parse_line(str, parv);
} while (!error);
fclose(file);
if (error)
fprintf(stderr, "%s: Error in configuration file, line %d\n",
my_name, i);
return error;
}
/* We're abusing struct option a bit. usage() expects an \0 in the
* name string, and after that a comment.
*/
void usage(char *my_name, struct option *options, const char *short_options)
{
struct option *opt;
printf("Usage: %s [options]", my_name);
for (opt = options; opt->name; opt++)
{
const char *descr = opt->name + strlen(opt->name) + 1;
if (strchr(short_options,opt->val))
printf("\n -%c, --%s", opt->val, opt->name);
else
printf("\n --%s", opt->name);
if (opt->has_arg)
printf(" <%s>", opt->name);
if (strlen(descr))
printf("\t%s",descr);
}
printf("\n");
}
void version(char *my_name, char *extra_version)
{
printf(
(
"%s (%s) %s %s\n"
"\n"
"FEATURES: %s\n"
"\n"
"This is free software. You may redistribute copies of it under the terms of\n"
"the GNU General Public License <http://www.gnu.org/licenses/gpl.html>.\n"
"There is NO WARRANTY, to the extent permitted by law.\n"
),
my_name,
PACKAGE_NAME,
PACKAGE_VERSION,
extra_version ? extra_version : "",
CONFIG_FEATURES
);
}