summaryrefslogtreecommitdiffstats
path: root/src/settings.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/settings.c')
-rw-r--r--src/settings.c176
1 files changed, 176 insertions, 0 deletions
diff --git a/src/settings.c b/src/settings.c
new file mode 100644
index 0000000..f217076
--- /dev/null
+++ b/src/settings.c
@@ -0,0 +1,176 @@
+/* Authors: Martin Nagy <mnagy@redhat.com>
+ *
+ * Copyright (C) 2009 Red Hat
+ * see file 'COPYING' for use and warranty information
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 only
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <isc/util.h>
+#include <isc/mem.h>
+#include <isc/result.h>
+
+#include <ctype.h>
+#include <stdlib.h>
+
+#include "log.h"
+#include "settings.h"
+#include "str.h"
+#include "util.h"
+
+
+/*
+ * Forward declarations.
+ */
+static int args_are_equal(const char *setting_argument,
+ const char *argv_argument);
+static isc_result_t set_value(setting_t *setting, const char *value);
+static isc_result_t set_default_value(setting_t *setting);
+static const char * get_value_str(const char *arg);
+
+isc_result_t
+set_settings(setting_t settings[], const char * const* argv)
+{
+ isc_result_t result;
+ int i, j;
+ const char *value;
+
+ for (i = 0; argv[i] != NULL; i++) {
+ for (j = 0; settings[j].name != NULL; j++) {
+ if (args_are_equal(settings[j].name, argv[i])) {
+ value = get_value_str(argv[i]);
+ CHECK(set_value(&settings[j], value));
+ break;
+ }
+ }
+ }
+
+ /* When all is done, check that all the required settings are set. */
+ for (j = 0; settings[j].name != NULL; j++) {
+ if (settings[j].set != 0)
+ continue;
+ if (!settings[j].has_a_default) {
+ log_error("argument %s must be set", settings[j].name);
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+ CHECK(set_default_value(&settings[j]));
+ }
+
+ return ISC_R_SUCCESS;
+
+cleanup:
+ /* TODO: Free memory in case of error. */
+ return result;
+}
+
+/*
+ * Return 1 if the argument names are equal. The argv_argument also needs to
+ * contain an additional space at the end.
+ */
+static int
+args_are_equal(const char *setting_argument, const char *argv_argument)
+{
+ if (setting_argument == NULL || argv_argument == NULL)
+ return 0;
+
+ for (;;) {
+ if (*setting_argument == '\0')
+ break;
+ if (*argv_argument == '\0')
+ return 0;
+ if (*setting_argument != *argv_argument)
+ return 0;
+ setting_argument++;
+ argv_argument++;
+ }
+
+ /* Now make sure we also found a space at the end of argv_argument. */
+ if (!isspace(*argv_argument) && *argv_argument != '\0')
+ return 0;
+
+ return 1;
+}
+
+static isc_result_t
+set_value(setting_t *setting, const char *value)
+{
+ isc_result_t result;
+ int numeric_value;
+
+ if (setting->type == ST_LD_STRING) {
+ CHECK(str_init_char((ld_string_t *)setting->target, value));
+ } else if (setting->type == ST_SIGNED_INTEGER ||
+ setting->type == ST_UNSIGNED_INTEGER) {
+ if (*value == '\0') {
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+ /* TODO: better type checking. */
+ numeric_value = atoi(value);
+ if (setting->type == ST_SIGNED_INTEGER) {
+ (*(signed *)setting->target) = (signed)numeric_value;
+ } else if (numeric_value < 0) {
+ log_error("argument %s must be an unsigned integer",
+ setting->name);
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ } else {
+ (*(unsigned *)setting->target) = (unsigned)numeric_value;
+ }
+ } else {
+ fatal_error("unknown type in function set_value()");
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+
+ setting->set = 1;
+
+ return ISC_R_SUCCESS;
+
+cleanup:
+ return result;
+}
+
+static isc_result_t
+set_default_value(setting_t *setting)
+{
+ switch (setting->type) {
+ case ST_LD_STRING:
+ return set_value(setting, setting->default_value.value_char);
+ break;
+ case ST_SIGNED_INTEGER:
+ *(signed *)setting->target = setting->default_value.value_sint;
+ break;
+ case ST_UNSIGNED_INTEGER:
+ *(unsigned *)setting->target = setting->default_value.value_uint;
+ break;
+ default:
+ fatal_error("unknown type in function set_default_value()");
+ return ISC_R_FAILURE;
+ }
+
+ return ISC_R_SUCCESS;
+}
+
+static const char *
+get_value_str(const char *arg)
+{
+ while (*arg != '\0' && !isspace(*arg))
+ arg++;
+ while (*arg != '\0' && isspace(*arg))
+ arg++;
+
+ return arg;
+}