aboutsummaryrefslogtreecommitdiff
path: root/src/config.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/config.c')
-rw-r--r--src/config.c156
1 files changed, 112 insertions, 44 deletions
diff --git a/src/config.c b/src/config.c
index 93683f0..76ca179 100644
--- a/src/config.c
+++ b/src/config.c
@@ -417,8 +417,8 @@ find_asrtop(char *s)
return NULL;
}
-static int
-parse_assertion(char **argv, struct grecs_symtab *at, grecs_locus_t *locus)
+static struct slb_assertion *
+parse_assert_argv(char **argv, struct grecs_symtab *at, grecs_locus_t *locus)
{
struct slb_assertion *ap;
int install;
@@ -439,7 +439,7 @@ parse_assertion(char **argv, struct grecs_symtab *at, grecs_locus_t *locus)
op = find_asrtop(s);
if (!op) {
grecs_error(locus, 0, _("invalid operation: %s"), s);
- return 1;
+ return NULL;
}
opcode = op->opcode;
flags ^= op->flags;
@@ -447,7 +447,7 @@ parse_assertion(char **argv, struct grecs_symtab *at, grecs_locus_t *locus)
oidlen = MAX_OID_LEN;
if (!read_objid(argv[0], oid, &oidlen)) {
grecs_error(locus, 0, _("cannot parse oid"));
- return 1;
+ return NULL;
}
install = 1;
@@ -457,8 +457,16 @@ parse_assertion(char **argv, struct grecs_symtab *at, grecs_locus_t *locus)
ap->opcode = opcode;
ap->flags = flags;
- ap->value = grecs_strdup(argv[2]);
- ap->vallen = strlen(ap->value);
+ if (strcmp(argv[2], "-prev") == 0) {
+ ap->value = NULL;
+ ap->flags |= SLB_ASSERT_PREV;
+ } else if (argv[2][0] == '-') {
+ ap->value = grecs_strdup(argv[2] + 1);
+ ap->vallen = strlen(ap->value);
+ } else {
+ ap->value = grecs_strdup(argv[2]);
+ ap->vallen = strlen(ap->value);
+ }
clone_locus(&ap->locus, locus);
len = strlen(argv[0]) + 1 +
@@ -470,56 +478,115 @@ parse_assertion(char **argv, struct grecs_symtab *at, grecs_locus_t *locus)
strcat(ap->text, argv[1]);
strcat(ap->text, " ");
strcat(ap->text, argv[2]);
- return 0;
+ return ap;
}
-int
+static struct slb_assertion *
+parse_assert_string(char *str, struct grecs_symtab *at, grecs_locus_t *locus)
+{
+ struct slb_assertion *ap;
+ struct wordsplit ws;
+
+ if (wordsplit(str, &ws, WRDSF_DEFFLAGS)) {
+ grecs_error(locus, 0, "can't split argument: %s",
+ wordsplit_strerror(&ws));
+ return NULL;
+ }
+ if (ws.ws_wordc > 3) {
+ grecs_error(locus, 0, "too many arguments to assertion");
+ wordsplit_free(&ws);
+ return NULL;
+ } else if (ws.ws_wordc < 3) {
+ grecs_error(locus, 0, "too few arguments to assertion");
+ wordsplit_free(&ws);
+ return NULL;
+ }
+ ap = parse_assert_argv(ws.ws_wordv, at, locus);
+ wordsplit_free(&ws);
+ return ap;
+}
+
+static int
cb_server_assert(enum grecs_callback_command cmd,
grecs_locus_t *locus,
void *varptr,
grecs_value_t *value,
void *cb_data)
{
- struct grecs_symtab *at = *(struct grecs_symtab **)varptr;
- int rc;
+ struct slb_server *srv = varptr;
+ void **pdata = cb_data;
+ struct slb_assertion *ap;
- if (assert_n_strings(locus, cmd, value, 1, 3))
- return 1;
+ switch (cmd) {
+ case grecs_callback_section_begin:
+ ap = parse_assert_string(value->v.string, srv->assertions,
+ locus);
+ if (!ap)
+ return 1;
+ *pdata = ap;
+ break;
- if (value->type == GRECS_TYPE_STRING) {
- struct wordsplit ws;
+ case grecs_callback_section_end:
+ /*ap = *pdata;*/
+ break;
- if (wordsplit(value->v.string, &ws, WRDSF_DEFFLAGS)) {
- grecs_error(locus, 0,
- _("can't split argument: %s"),
- wordsplit_strerror(&ws));
- return 1;
- }
- if (ws.ws_wordc > 3) {
- grecs_error(locus, 0,
- _("too many arguments to assertion"));
- wordsplit_free(&ws);
- return 1;
- } else if (ws.ws_wordc < 3) {
- grecs_error(locus, 0,
- _("too few arguments to assertion"));
- wordsplit_free(&ws);
- return 1;
+ case grecs_callback_set_value:
+ if (value->type == GRECS_TYPE_STRING) {
+ if (!parse_assert_string(value->v.string,
+ srv->assertions, locus))
+ return 1;
+ } else {
+ char *argv[4];
+
+ if (assert_n_strings(locus, cmd, value, 3, 3))
+ return 1;
+
+ argv[0] = value->v.arg.v[0]->v.string;
+ argv[1] = value->v.arg.v[1]->v.string;
+ argv[2] = value->v.arg.v[2]->v.string;
+ argv[3] = NULL;
+ if (!parse_assert_argv(argv, srv->assertions, locus))
+ return 1;
}
- rc = parse_assertion(ws.ws_wordv, at, locus);
- wordsplit_free(&ws);
- } else {
- char *argv[4];
- argv[0] = value->v.arg.v[0]->v.string;
- argv[1] = value->v.arg.v[1]->v.string;
- argv[2] = value->v.arg.v[2]->v.string;
- argv[3] = NULL;
- rc = parse_assertion(argv, at, locus);
}
+ return 0;
+}
- return rc;
+static int
+cb_assertion_action(enum grecs_callback_command cmd,
+ grecs_locus_t *locus,
+ void *varptr,
+ grecs_value_t *value,
+ void *cb_data)
+{
+ struct slb_assertion *asrt = varptr;
+ if (assert_string_value(locus, cmd, value))
+ return 1;
+ if (strcmp(value->v.string, "abort") == 0)
+ asrt->action = SLB_ASSERT_ABORT;
+ else if (strcmp(value->v.string, "warn") == 0)
+ asrt->action = SLB_ASSERT_WARN;
+ else if (strcmp(value->v.string, "reinit") == 0)
+ asrt->action = SLB_ASSERT_REINIT;
+ else {
+ grecs_error(locus, 0, "unknown action");
+ return 1;
+ }
+ return 0;
}
+static struct grecs_keyword server_assert_kw[] = {
+ { "action", N_("{abort|warn|reinit}"),
+ N_("Action to take when the assertion fails"),
+ grecs_type_string, GRECS_DFLT,
+ NULL, 0,
+ cb_assertion_action },
+ { "message", NULL, N_("Message to issue when the assertion fails"),
+ grecs_type_string, GRECS_DFLT,
+ NULL, offsetof(struct slb_assertion, text) },
+ { NULL }
+};
+
int
cb_server_macro(enum grecs_callback_command cmd,
grecs_locus_t *locus,
@@ -866,10 +933,11 @@ static struct grecs_keyword server_kw[] = {
"Each of these can be suffixed with \"/i\" to request case-insensitive\n"
"comparison.\n"
"\n"
- "A \"!\" in front of opcode reverts its meaning."),
- grecs_type_string, GRECS_MULT,
- NULL, offsetof(struct slb_server, assertions),
- cb_server_assert },
+ "A \"!\" in front of opcode reverts its meaning.\n\n"
+ "The block part is optional. If omitted, the default action is \"abort\""),
+ grecs_type_section, GRECS_MULT,
+ NULL, 0,
+ cb_server_assert, NULL, server_assert_kw },
{ NULL }
};

Return to:

Send suggestions and report system problems to the System administrator.