Revision: 14752
Author: adrian.chadd
Date: Mon Aug  9 23:24:11 2010
Log: Begin fleshing out a regex external ACL helper for use in Issue #120 .

This helper is absolutely not yet finished; don't even think about
using it.


http://code.google.com/p/lusca-cache/source/detail?r=14752

Added:
 /branches/LUSCA_HEAD/helpers/external_acl/regex
 /branches/LUSCA_HEAD/helpers/external_acl/regex/regex.c

=======================================
--- /dev/null
+++ /branches/LUSCA_HEAD/helpers/external_acl/regex/regex.c Mon Aug 9 23:24:11 2010
@@ -0,0 +1,231 @@
+/*
+ * #insert GPLv2 licence here.
+ */
+
+/*
+ * This is a hackish, not-quite-finished regex external ACL helper.
+ * Don't even try to use it in production yet.
+ * -adrian
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <strings.h>
+#include <string.h>
+#include <regex.h>
+
+#define        HELPERBUFSZ     16384
+#define        MAXLINE         8192
+#define        RELOAD_TIME     5
+
+struct _regex_entry {
+       int linenum;
+       const char *entry;
+       regex_t re;
+       int re_flags;
+};
+typedef struct _regex_entry regex_entry_t;
+
+struct {
+       regex_entry_t *r;
+       int count;
+       int alloc;
+} re_list = { NULL, 0, 0 };
+
+regex_entry_t *
+re_list_get(void)
+{
+       regex_entry_t *r;
+
+       if (re_list.count <= re_list.alloc) {
+               r = realloc(re_list.r,
+                   sizeof(regex_entry_t) * (re_list.alloc + 16));
+               if (r == NULL) {
+                       perror("re_list_get: realloc");
+                       return NULL;
+               }
+               re_list.r = r;
+               re_list.alloc += 16;
+       }
+
+       /* Reuse r */
+       r = &re_list.r[re_list.count];
+       bzero(r, sizeof(regex_entry_t));
+       /* The caller needs to bump re_list.count if they're using it */
+       return r;
+}
+
+void
+re_list_free(void)
+{
+       int i;
+       for (i = 0; i < re_list.count; i++) {
+               fprintf(stderr, "[%d]: free\n", i);
+               regfree(&re_list.r[i].re);
+               bzero(&re_list.r[i], sizeof(regex_entry_t));
+       }
+       re_list.count = 0;
+}
+
+int
+regex_init(regex_entry_t *r, const char *entry, int linenum, int re_flags)
+{
+       int i;
+
+       bzero(r, sizeof(*r));
+       r->entry = strdup(entry);
+       r->linenum = linenum;
+       r->re_flags = re_flags;
+
+       i = regcomp(&r->re, entry, re_flags);
+       if (i) {        /* error condition */
+               perror("regcomp");    /* XXX should output i instead */
+               /* XXX should regfree be called here? */
+               return 0;
+       }
+
+       return 1;
+}
+
+int
+regex_parse_line(const char *line, int linenum)
+{
+       int i;
+       regex_entry_t *r;
+
+       /* Comment? skip */
+       if (line[0] == '#')
+               return 0;
+       if (line[0] == '\r' || line[0] == '\n' || line[0] == '\0')
+               return 0;
+
+       /* Get the latest unallocated entry */
+       r = re_list_get();
+       if (r == NULL)
+               return -1;
+
+       /* For now, just bump the thing entirely to the line parser */
+       i = regex_init(r, line, linenum, REG_EXTENDED | REG_NOSUB);
+       if (i <= 0)
+               return -1;
+
+       /* success - use */
+       re_list.count++;
+
+       return 1;
+
+}
+
+static void
+trim_trailing_crlf(char *buf)
+{
+       int n;
+
+       for (n = strlen(buf) - 1;
+           n >= 0 && (buf[n] == '\r' || buf[n] == '\n');
+           n --)
+               buf[n] = '\0';
+}
+
+
+void
+load_regex_file(const char *file)
+{
+       FILE *fp;
+       char buf[MAXLINE];
+       int linenum;
+       int n;
+
+       fp = fopen(file, "r");
+       if (! fp) {
+               perror("fopen");
+               exit(127);
+       }
+
+       linenum = 0;
+       while (!feof(fp)) {
+               linenum++;
+               if (! fgets(buf, MAXLINE, fp))
+                       break;  /* XXX should check for error or EOF */
+
+               /* Trim trailing \r\n's */
+               trim_trailing_crlf(buf);
+               n = regex_parse_line(buf, linenum);
+               if (n > 0) {
+                       printf("[%d]: %s\n", linenum, buf);
+               }
+       }
+
+       fclose(fp);
+}
+
+static void
+check_file_update(const char *fn, struct timeval *m)
+{
+       /* For now, always reload */
+       re_list_free();
+       load_regex_file(fn);
+}
+
+static int
+re_lookup(const char *url)
+{
+       int r, i;
+
+       for (i = 0; i < re_list.count; i++) {
+               r = regexec(&re_list.r[i].re, url, 0, NULL, 0);
+               if (r == 0) {   /* Success */
+                       return r;
+               }
+       }
+       return 0;
+}
+
+
+int
+main(int argc, const char *argv[])
+{
+       const char *fn;
+       char buf[HELPERBUFSZ];
+       time_t ts;
+       int r;
+
+       if (argc < 2) {
+               printf("%s: <config file>\n", argv[0]);
+               exit(127);
+       }
+       fn = argv[1];
+
+       /* set stdout/stderr unbuffered */
+       (void) setvbuf(stdout, NULL, _IONBF, 0);
+       (void) setvbuf(stderr, NULL, _IONBF, 0);
+
+       /* initial load */
+       load_regex_file(fn);
+       ts = time(NULL);
+
+       while (!feof(stdin)) {
+               if (time(NULL) - ts > RELOAD_TIME) {
+                       ts = time(NULL);
+                       check_file_update(fn, NULL);
+               }
+
+               if (! fgets(buf, HELPERBUFSZ, stdin))
+                       break;
+               trim_trailing_crlf(buf);
+               fprintf(stderr, "read: %s\n", buf);
+               /* XXX should break out JUST the URL here! */
+               r = re_lookup(buf);
+               if (r > 0) {
+                       fprintf(stderr, "HIT: line %d; rule %s\n",
+                           re_list.r[r].linenum, re_list.r[r].entry);
+                       printf("YES\n");
+               } else {
+                       printf("NO\n");
+               }
+       }
+       re_list_free();
+       exit(0);
+}

--
You received this message because you are subscribed to the Google Groups 
"lusca-commit" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/lusca-commit?hl=en.

Reply via email to