MINOR: args: implement a new arg type for regex : ARGT_REG

This one will be used when a regex is expected. It is automatically
resolved after the parsing and compiled into a regex. Some optional
flags are supported in the type-specific flags that should be set by
the optional arg checker. One is used during the regex compilation :
ARGF_REG_ICASE to ignore case.
This commit is contained in:
Willy Tarreau 2015-01-19 19:00:58 +01:00
parent 085dafac5f
commit 469477879c
4 changed files with 59 additions and 1 deletions

View File

@ -57,6 +57,7 @@ enum {
ARGT_SRV, /* a pointer to a server */
ARGT_USR, /* a pointer to a user list */
ARGT_MAP, /* a pointer to a map descriptor */
ARGT_REG, /* a pointer to a regex */
};
/* context where arguments are used, in order to help error reporting */
@ -72,10 +73,15 @@ enum {
ARGC_CAP, /* capture rule */
};
/* flags used when compiling and executing regex */
#define ARGF_REG_ICASE 1
#define ARGF_REG_GLOB 2
/* some types that are externally defined */
struct proxy;
struct server;
struct userlist;
struct my_regex;
union arg_data {
unsigned int uint; /* used for uint, time, size */
@ -87,6 +93,7 @@ union arg_data {
struct server *srv;
struct userlist *usr;
struct map_descriptor *map;
struct my_regex *reg;
};
struct arg {

View File

@ -34,6 +34,7 @@ static const char *arg_type_names[ARGT_NBTYPES] = {
[ARGT_SRV] = "server",
[ARGT_USR] = "user list",
[ARGT_MAP] = "map",
[ARGT_REG] = "regex",
/* Unassigned types must never happen. Better crash during parsing if they do. */
};
@ -173,6 +174,7 @@ int make_arg_list(const char *in, int len, unsigned int mask, struct arg **argp,
case ARGT_TAB:
case ARGT_SRV:
case ARGT_USR:
case ARGT_REG:
/* These argument types need to be stored as strings during
* parsing then resolved later.
*/

View File

@ -1086,6 +1086,13 @@ static void deinit_sample_arg(struct arg *p)
p->data.str.str = NULL;
p->unresolved = 0;
}
else if (p->type == ARGT_REG) {
if (p->data.reg) {
regex_free(p->data.reg);
free(p->data.reg);
p->data.reg = NULL;
}
}
p++;
}

View File

@ -983,13 +983,16 @@ int smp_resolve_args(struct proxy *p)
const char *ctx, *where;
const char *conv_ctx, *conv_pre, *conv_pos;
struct userlist *ul;
struct my_regex *reg;
struct arg *arg;
int cfgerr = 0;
int rflags;
list_for_each_entry_safe(cur, bak, &p->conf.args.list, list) {
struct proxy *px;
struct server *srv;
char *pname, *sname;
char *err;
arg = cur->arg;
@ -1004,7 +1007,7 @@ int smp_resolve_args(struct proxy *p)
where = "in";
ctx = "sample fetch keyword";
switch (cur->ctx) {
case ARGC_STK:where = "in stick rule in"; break;
case ARGC_STK: where = "in stick rule in"; break;
case ARGC_TRK: where = "in tracking rule in"; break;
case ARGC_LOG: where = "in log-format string in"; break;
case ARGC_HRQ: where = "in http-request header format string in"; break;
@ -1175,6 +1178,45 @@ int smp_resolve_args(struct proxy *p)
arg->unresolved = 0;
arg->data.usr = ul;
break;
case ARGT_REG:
if (!arg->data.str.len) {
Alert("parsing [%s:%d] : missing regex in arg %d of %s%s%s%s '%s' %s proxy '%s'.\n",
cur->file, cur->line,
cur->arg_pos + 1, conv_pre, conv_ctx, conv_pos, ctx, cur->kw, where, p->id);
cfgerr++;
continue;
}
reg = calloc(1, sizeof(*reg));
if (!reg) {
Alert("parsing [%s:%d] : not enough memory to build regex in arg %d of %s%s%s%s '%s' %s proxy '%s'.\n",
cur->file, cur->line,
cur->arg_pos + 1, conv_pre, conv_ctx, conv_pos, ctx, cur->kw, where, p->id);
cfgerr++;
continue;
}
rflags = 0;
rflags |= (arg->type_flags & ARGF_REG_ICASE) ? REG_ICASE : 0;
err = NULL;
if (!regex_comp(arg->data.str.str, reg, rflags, 1 /* capture substr */, &err)) {
Alert("parsing [%s:%d] : error in regex '%s' in arg %d of %s%s%s%s '%s' %s proxy '%s' : %s.\n",
cur->file, cur->line,
arg->data.str.str,
cur->arg_pos + 1, conv_pre, conv_ctx, conv_pos, ctx, cur->kw, where, p->id, err);
cfgerr++;
continue;
}
free(arg->data.str.str);
arg->data.str.str = NULL;
arg->unresolved = 0;
arg->data.reg = reg;
break;
}
LIST_DEL(&cur->list);