aboutsummaryrefslogtreecommitdiff
path: root/src/builtin.c
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2009-02-18 00:04:51 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2009-02-18 00:04:51 +0200
commit8c4ab07dbf003ba07bec6e77fd803b9c54b91e52 (patch)
tree9f4e1b0dcd3f10e78c815d6c5baecc8da8ad1c47 /src/builtin.c
parent317095181674a01651602ddf6817e888d0ad5280 (diff)
downloadwydawca-8c4ab07dbf003ba07bec6e77fd803b9c54b91e52.tar.gz
wydawca-8c4ab07dbf003ba07bec6e77fd803b9c54b91e52.tar.bz2
Various fixes
Diffstat (limited to 'src/builtin.c')
-rw-r--r--src/builtin.c224
1 files changed, 218 insertions, 6 deletions
diff --git a/src/builtin.c b/src/builtin.c
index 9786383..711694f 100644
--- a/src/builtin.c
+++ b/src/builtin.c
@@ -16,6 +16,11 @@
#include "wydawca.h"
#include "builtin.h"
+#include "fnmatch.h"
+#include "regex.h"
+#define obstack_chunk_alloc malloc
+#define obstack_chunk_free free
+#include "obstack.h"
int
builtin_init (struct access_method *meth)
@@ -35,11 +40,219 @@ builtin_open (struct access_method *meth)
return meth;
}
+#define CMP_EXACT 0
+#define CMP_FNMATCH 1
+#define CMP_REGEX 2
+
+#define RF_ICASE 0x1
+#define RF_BASIC 0x2
+
+#define STRMATCH(s, p, len) \
+ (len == sizeof(s) - 1 && memcmp (s, p, sizeof(s) - 1) == 0)
+
+typedef int (*strcmp_fn) (const char *, const char *, int flags);
+
+static int
+cmp_exact (const char *pat, const char *str, int flags)
+{
+ return strcmp (pat, str) == 0;
+}
+
+static int
+cmp_exact_ci (const char *pat, const char *str, int flags)
+{
+ return strcmp (pat, str) == 0;
+}
+
+static int
+cmp_fnmatch (const char *pat, const char *str, int flags)
+{
+ return fnmatch (pat, str, flags) == 0;
+}
+
+static int
+cmp_regex (const char *pat, const char *str, int flags)
+{
+ int rc;
+ regex_t regex;
+
+ rc = regcomp (&regex, pat, flags);
+ if (rc)
+ {
+ char errbuf[512];
+
+ regerror (rc, &regex, errbuf, sizeof (errbuf));
+ logmsg (LOG_ERR, "%s: cannot compile regexp: %s", pat, errbuf);
+ return 0;
+ }
+
+ rc = regexec (&regex, str, 0, NULL, 0);
+ regfree (&regex);
+ return rc == 0;
+}
+
+int
+parse_cmp_type (const char *pat, strcmp_fn *cmpfn, int *rf)
+{
+ size_t len = strcspn (pat, ",");
+ int flags = 0;
+ int cmp;
+
+ if (STRMATCH ("exact", pat, len))
+ cmp = CMP_EXACT;
+ else if (STRMATCH ("fnmatch", pat, len))
+ cmp = CMP_FNMATCH;
+ else if (STRMATCH ("regex", pat, len))
+ cmp = CMP_REGEX;
+ else
+ return 1;
+
+ pat += len;
+ if (*pat)
+ {
+ while (*++pat)
+ {
+ switch (*pat)
+ {
+ case 'i':
+ flags |= RF_ICASE;
+ break;
+
+ case 'b':
+ flags |= RF_BASIC;
+ break;
+
+ default:
+ logmsg (LOG_NOTICE, "unrecognized comparison flag: %c", *pat);
+ }
+ }
+ }
+
+ switch (cmp)
+ {
+ case CMP_EXACT:
+ *cmpfn = (flags & RF_ICASE) ? cmp_exact_ci : cmp_exact;
+ break;
+
+ case CMP_FNMATCH:
+ *cmpfn = cmp_fnmatch;
+ *rf = FNM_NOESCAPE | FNM_PERIOD |
+ ((flags & RF_ICASE) ? FNM_CASEFOLD : 0);
+ break;
+
+ case CMP_REGEX:
+ *cmpfn = cmp_regex;
+ *rf = ((flags & RF_BASIC) ? 0 : REG_EXTENDED) | REG_NOSUB;
+ if (flags & RF_ICASE)
+ *rf |= REG_ICASE;
+ break;
+ }
+ return 0;
+}
+
+struct builtin_data_storage
+{
+ struct obstack stk;
+ char **wp;
+};
+
+static int default_ncol[] = {
+ 1, /* verify-user: arbitrary return, usually user name */
+ 1, /* gpg-key: key */
+ 2, /* project-owner: email, realname */
+ 2, /* user-data: email, realname */
+};
+
int
builtin_run (struct access_method *meth, void *handle, const char *req)
{
- meth->nrow = meth->parmc;
- meth->ncol = 1;
+ int i;
+ size_t count = 0;
+ struct obstack stk;
+ int flags = 0;
+ strcmp_fn cmpfn = cmp_exact;
+ struct builtin_data_storage *bds;
+ int ncol = default_ncol[meth->id];
+
+ if (meth->parmc == 0)
+ {
+ meth->nrow = meth->ncol = 0;
+ return 0;
+ }
+
+ obstack_init (&stk);
+
+ for (i = 0; i < meth->parmc; i++)
+ {
+ char *pat = meth->parmv[i];
+ char *val;
+
+ if (pat[0] == '/')
+ {
+ pat++;
+ if (*pat != '/' && parse_cmp_type (pat, &cmpfn, &flags) == 0)
+ continue;
+ }
+
+ if (i + ncol >= meth->parmc)
+ break;
+
+ if (cmpfn (pat, req, flags))
+ {
+ size_t j;
+ for (j = 1; j <= ncol; j++)
+ {
+ char *val = meth->parmv[i + j];
+ obstack_grow (&stk, val, strlen (val) + 1);
+ }
+ count++;
+ }
+
+ i += ncol;
+ }
+
+ meth->nrow = count;
+ meth->ncol = ncol;
+
+ if (count == 0)
+ {
+ obstack_free (&stk, NULL);
+ bds = NULL;
+ }
+ else
+ {
+ size_t i;
+ char *p;
+
+ bds = xmalloc (sizeof (*bds));
+ count *= ncol;
+ bds->wp = xcalloc (count, sizeof (bds->wp[0]));
+ bds->stk = stk;
+ p = obstack_finish (&stk);
+
+ for (i = 0; i < count; i++)
+ {
+ bds->wp[i] = p;
+ p += strlen (p) + 1;
+ }
+ }
+
+ meth->storage = bds;
+
+ return 0;
+}
+
+int
+builtin_free_result (struct access_method *method, void *handle)
+{
+ if (method->storage)
+ {
+ struct builtin_data_storage *bds = method->storage;
+ obstack_free (&bds->stk, NULL);
+ free (bds->wp);
+ free (bds);
+ method->storage = NULL;
+ }
return 0;
}
@@ -47,10 +260,9 @@ int
builtin_get (struct access_method *method, void *handle,
unsigned nrow, unsigned ncol)
{
- if (nrow >= method->parmc)
- return 1;
- method_copy_result (method, method->parmv[nrow],
- strlen (method->parmv[nrow]));
+ struct builtin_data_storage *bds = method->storage;
+ char *str = bds->wp[nrow * method->ncol + ncol];
+ method_copy_result (method, str, strlen (str));
return 0;
}

Return to:

Send suggestions and report system problems to the System administrator.