diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2010-06-17 13:24:19 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2010-06-17 13:24:19 +0300 |
commit | c81c5df1da0ec4de29a13787b3b116bb71e66ddd (patch) | |
tree | 11f35326cb4dd1a1e9e6bc2f8fa29e88e8f711aa | |
parent | c32cdcbb85fd6ee8d7808957f6312a5ffb3153b0 (diff) | |
download | smap-c81c5df1da0ec4de29a13787b3b116bb71e66ddd.tar.gz smap-c81c5df1da0ec4de29a13787b3b116bb71e66ddd.tar.bz2 |
Further work on the documentation.
* src/query.c (parse_regexp): New function.
(parse_query_map): Regular expressions must be
prefixed with `regexp'.
* doc/smap.texi: Update.
-rw-r--r-- | doc/smap.texi | 115 | ||||
-rw-r--r-- | src/query.c | 116 |
2 files changed, 183 insertions, 48 deletions
diff --git a/doc/smap.texi b/doc/smap.texi index a277238..5bf823c 100644 --- a/doc/smap.texi +++ b/doc/smap.texi @@ -736,6 +736,7 @@ when debugging @command{smapd}. @emph{Never use it in production environment!} @end deffn +@anchor{config-server} @deffn {Config} server name address [block] Configure a server. The @var{name} argument gives its symbolic name, which will be used in logs to identify it. The @var{address} @@ -765,10 +766,12 @@ word @samp{begin} followed by a newline, one or more configuration statements and the word @samp{end} alone on a line. For example: @example +@group server main unix:///var/run/smap.sock begin user smap allgroups yes end +@end group @end example The statements within block apply only to that particular server. @@ -812,17 +815,121 @@ Arguments to the module initialization function. @end table @end deffn -@deffn {Config} database name modname [args...] -Define a database @var{name} and associate it with the module +@anchor{config-database} +@deffn {Config} database dbname modname [args...] +Define a database @var{dbname} and associate it with the module @var{modname}, which must be loaded by a prior @code{module} statement. Optional @var{args} are passed to the database initialization function verbatim. @end deffn @deffn {Config} query cond target -FIXME +Route incoming queries. + +@var{Cond} is a list of conditions that must be satisfied in order to +route this query to @var{target}. Conditions are separated by any +amount of whitespace. They are evaluated from left to right and are +joined using boolean @samp{AND} so that @var{cond} yields @samp{True} +only if all conditions evaluate to @samp{True}. Supported conditions +are: + +@deffn {Condition} from ipaddr +Returns @samp{True} if the IP address of the client equals +@var{ipaddr}. The latter may be given either as an IP address or +as a host name, in which case it will be resolved and the first of +its IP addresses will be used. +@end deffn + +@deffn {Condition} from ipaddr/netmask +Returns @samp{True} if the result of logical @samp{AND} between the +client IP address and @var{netmask} equals to @var{ipaddr}. The +network mask must be specified in ``dotted quad'' form, e.g.: + +@example +from 10.1.10.1/255.255.255.224 +@end example +@end deffn + +@deffn {Condition} from ipaddr/netlen +Returns @samp{True} if first @var{netlen} bits from the client IP +address equal to @var{ipaddr}. The network mask length, @var{netlen} +must be an integer number in the range from 0 to 32. The address +part, @var{ipaddr}, is as described above. For example: + +@example +from 10.1.10.1/27 +@end example +@end deffn + +@deffn {Condition} to name +@samp{True} if this query is being served by the server @var{name} +(@pxref{config-server, name}). +@end deffn + +@deffn {Condition} map op string +@samp{True} if the map name part of the query (@pxref{Protocol,map}) +matches @var{string}. The @var{op} part specifies the comparison +algorithm: + +@table @asis +@item eq +@itemx is +Literal equality. Map name must be exactly the same as @var{string}. + +@item like +@itemx fnmatch +Match using shell wildcard patterns (@pxref{glob,Globbing +patterns,,glob(7), Glob(7) man page}). + +@item regexp +Match using regular expressions. @var{String} must have the following +form: + +@example +/@var{expr}/@var{flags} +@end example + +The slashes may be uniformly replaced with any other punctuation +character. The @var{expr} must constitute a valid regular expression. +The @var{flags} are optional. When given, they allow to control the +type of the regular expression: + +@multitable @columnfractions 0.1 0.9 +@headitem Flag @tab Meaning +@item i @tab Use case-insensitive matching +@item x @tab @var{expr} is an @dfn{extended regular expression}. This +is the default setting. +@item b @tab @var{expr} is a @dfn{basic regular expression}. +@end multitable + +@xref{Extended regexps, Extended regular expressions, Extended +regular expressions, sed, GNU sed}, for a description of Extended +regular expressions. +@end table +@end deffn + +@deffn {Condition} not cond +Reverts the value returned by @var{cond}, which is one of the +conditions described above. For example: + +@example +not map like "local*" +@end example @end deffn +@deffn {Condition} default +Always @samp{True}. This must be the only condition in @var{cond}. +It is useful to declare default query routing. +@end deffn + +The @var{target} instructs the server to direct this query to a +particular database. The syntax is: + +@deffn {Target} uses dbname +@deffnx {Target} database dbname +Pass this query to the database @var{dbname} (@pxref{config-database,dbname}). +@end deffn +@end deffn @node exit codes @section Smapd Exit Codes @@ -830,7 +937,7 @@ FIXME For each code it lists its decimal number, symbolic name from the @file{sysexits.h} header file, and its meaning. -@multitable @columnfractions 0.1 0.2 0.7 +@multitable @columnfractions 0.1 0.4 0.5 @headitem Code @tab Name @tab Meaning @item 0 @tab EX_OK @tab Normal termination. @item 64 @tab EX_USAGE @tab Command line usage error. diff --git a/src/query.c b/src/query.c index 2931b95..61779d7 100644 --- a/src/query.c +++ b/src/query.c @@ -126,6 +126,7 @@ enum query_tok { T_MAP, T_LIKE, T_EQ, + T_REGEXP, T_DB, T_NOT }; @@ -135,6 +136,8 @@ static struct smap_kwtab query_kwtab[] = { { "to", T_TO }, { "map", T_MAP }, { "like", T_LIKE }, + { "fnmatch", T_LIKE }, + { "regexp", T_REGEXP }, { "eq", T_EQ }, { "is", T_EQ }, { "uses", T_DB }, @@ -221,6 +224,67 @@ parse_query_not(struct query_cond **pcond) } static int +parse_regexp(const char *s, struct map_cond *mapcond) +{ + int rc; + char *buf; + size_t len; + int flags = REG_NOSUB | REG_EXTENDED; + char *p; + + if (!ispunct(s[0])) { + smap_error("%s:%lu: regexp does not start with " + "a punctuation character: %s", + cfg_file_name, cfg_line, s); + return 1; + } + + p = strrchr(s, s[0]); + if (p == s) { + smap_error("%s:%lu: unfinished regexp: %s", + cfg_file_name, cfg_line, s); + return 1; + } + if (p[1]) { + char *q; + for (q = p + 1; *q; q++) { + switch (*q) { + case 'i': + flags |= REG_ICASE; + break; + case 'b': + flags &= ~REG_EXTENDED; + break; + case 'x': + flags |= REG_EXTENDED; + break; + default: + smap_error("%s:%lu: uknown regexp " + "flag: %c", + cfg_file_name, cfg_line, + *q); + return 1; + } + } + } + len = p - s - 1; + buf = emalloc(len + 1); + memcpy(buf, s + 1, len); + buf[len] = 0; + rc = regcomp(&mapcond->re, buf, flags); + free(buf); + if (rc) { + char errbuf[512]; + regerror(rc, &mapcond->re, errbuf, sizeof(errbuf)); + smap_error("%s:%lu: regexp error: %s", + cfg_file_name, cfg_line, errbuf); + return 1; + } + mapcond->op = map_re; + return 0; +} + +static int parse_query_map(struct query_cond **pcond) { struct query_cond *cond; @@ -247,53 +311,17 @@ parse_query_map(struct query_cond **pcond) mapcond.op = map_eq; break; + case T_REGEXP: + s = nextarg(); + if (!s) + return 1; + if (parse_regexp(s, &mapcond)) + return 1; + break; + default: mapcond.op = map_eq; } - } else if (ispunct(s[0])) { - int rc; - char *buf; - size_t len; - int flags = REG_NOSUB | REG_EXTENDED; - char *p = strrchr(s, s[0]); - if (p == s) { - smap_error("%s:%lu: unfinished regexp: %s", - cfg_file_name, cfg_line, s); - return 1; - } - if (p[1]) { - char *q; - for (q = p + 1; *q; q++) { - switch (*q) { - case 'i': - flags |= REG_ICASE; - break; - case 'b': - flags &= ~REG_EXTENDED; - break; - default: - smap_error("%s:%lu: uknown regexp " - "flag: %c", - cfg_file_name, cfg_line, - *q); - return 1; - } - } - } - len = p - s - 1; - buf = emalloc(len + 1); - memcpy(buf, s + 1, len); - buf[len] = 0; - rc = regcomp(&mapcond.re, buf, flags); - free(buf); - if (rc) { - char errbuf[512]; - regerror(rc, &mapcond.re, errbuf, sizeof(errbuf)); - smap_error("%s:%lu: regexp error: %s", - cfg_file_name, cfg_line, errbuf); - return 1; - } - mapcond.op = map_re; } else mapcond.op = map_eq; mapcond.str = estrdup(s); |