aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/upas/send/rewrite.c
diff options
context:
space:
mode:
authorrsc <devnull@localhost>2005-10-29 16:26:44 +0000
committerrsc <devnull@localhost>2005-10-29 16:26:44 +0000
commit5cdb17983ae6e6367ad7a940cb219eab247a9304 (patch)
tree8ca1ef49af2a96e7daebe624d91fdf679814a057 /src/cmd/upas/send/rewrite.c
parentcd3745196389579fb78b9b01ef1daefb5a57aa71 (diff)
downloadplan9port-5cdb17983ae6e6367ad7a940cb219eab247a9304.tar.gz
plan9port-5cdb17983ae6e6367ad7a940cb219eab247a9304.tar.bz2
plan9port-5cdb17983ae6e6367ad7a940cb219eab247a9304.zip
Thanks to John Cummings.
Diffstat (limited to 'src/cmd/upas/send/rewrite.c')
-rw-r--r--src/cmd/upas/send/rewrite.c315
1 files changed, 315 insertions, 0 deletions
diff --git a/src/cmd/upas/send/rewrite.c b/src/cmd/upas/send/rewrite.c
new file mode 100644
index 00000000..4f40b293
--- /dev/null
+++ b/src/cmd/upas/send/rewrite.c
@@ -0,0 +1,315 @@
+#include "common.h"
+#include "send.h"
+
+extern int debug;
+
+/*
+ * Routines for dealing with the rewrite rules.
+ */
+
+/* globals */
+typedef struct rule rule;
+
+#define NSUBEXP 10
+struct rule {
+ String *matchre; /* address match */
+ String *repl1; /* first replacement String */
+ String *repl2; /* second replacement String */
+ d_status type; /* type of rule */
+ Reprog *program;
+ Resub subexp[NSUBEXP];
+ rule *next;
+};
+static rule *rulep;
+static rule *rlastp;
+
+/* predeclared */
+static String *substitute(String *, Resub *, message *);
+static rule *findrule(String *, int);
+
+
+/*
+ * Get the next token from `line'. The symbol `\l' is replaced by
+ * the name of the local system.
+ */
+extern String *
+rule_parse(String *line, char *system, int *backl)
+{
+ String *token;
+ String *expanded;
+ char *cp;
+
+ token = s_parse(line, 0);
+ if(token == 0)
+ return(token);
+ if(strchr(s_to_c(token), '\\')==0)
+ return(token);
+ expanded = s_new();
+ for(cp = s_to_c(token); *cp; cp++) {
+ if(*cp == '\\') switch(*++cp) {
+ case 'l':
+ s_append(expanded, system);
+ *backl = 1;
+ break;
+ case '\\':
+ s_putc(expanded, '\\');
+ break;
+ default:
+ s_putc(expanded, '\\');
+ s_putc(expanded, *cp);
+ break;
+ } else
+ s_putc(expanded, *cp);
+ }
+ s_free(token);
+ s_terminate(expanded);
+ return(expanded);
+}
+
+static int
+getrule(String *line, String *type, char *system)
+{
+ rule *rp;
+ String *re;
+ int backl;
+
+ backl = 0;
+
+ /* get a rule */
+ re = rule_parse(s_restart(line), system, &backl);
+ if(re == 0)
+ return 0;
+ rp = (rule *)malloc(sizeof(rule));
+ if(rp == 0) {
+ perror("getrules:");
+ exit(1);
+ }
+ rp->next = 0;
+ s_tolower(re);
+ rp->matchre = s_new();
+ s_append(rp->matchre, s_to_c(re));
+ s_restart(rp->matchre);
+ s_free(re);
+ s_parse(line, s_restart(type));
+ rp->repl1 = rule_parse(line, system, &backl);
+ rp->repl2 = rule_parse(line, system, &backl);
+ rp->program = 0;
+ if(strcmp(s_to_c(type), "|") == 0)
+ rp->type = d_pipe;
+ else if(strcmp(s_to_c(type), ">>") == 0)
+ rp->type = d_cat;
+ else if(strcmp(s_to_c(type), "alias") == 0)
+ rp->type = d_alias;
+ else if(strcmp(s_to_c(type), "translate") == 0)
+ rp->type = d_translate;
+ else if(strcmp(s_to_c(type), "auth") == 0)
+ rp->type = d_auth;
+ else {
+ s_free(rp->matchre);
+ s_free(rp->repl1);
+ s_free(rp->repl2);
+ free((char *)rp);
+ fprint(2,"illegal rewrite rule: %s\n", s_to_c(line));
+ return 0;
+ }
+ if(rulep == 0)
+ rulep = rlastp = rp;
+ else
+ rlastp = rlastp->next = rp;
+ return backl;
+}
+
+/*
+ * rules are of the form:
+ * <reg exp> <String> <repl exp> [<repl exp>]
+ */
+extern int
+getrules(void)
+{
+ Biobuf *rfp;
+ String *line;
+ String *type;
+ String *file;
+
+ file = abspath("rewrite", unsharp(UPASLIB), (String *)0);
+ rfp = sysopen(s_to_c(file), "r", 0);
+ if(rfp == 0) {
+ rulep = 0;
+ return -1;
+ }
+ rlastp = 0;
+ line = s_new();
+ type = s_new();
+ while(s_getline(rfp, s_restart(line)))
+ if(getrule(line, type, thissys) && altthissys)
+ getrule(s_restart(line), type, altthissys);
+ s_free(type);
+ s_free(line);
+ s_free(file);
+ sysclose(rfp);
+ return 0;
+}
+
+/* look up a matching rule */
+static rule *
+findrule(String *addrp, int authorized)
+{
+ rule *rp;
+ static rule defaultrule;
+
+ if(rulep == 0)
+ return &defaultrule;
+ for (rp = rulep; rp != 0; rp = rp->next) {
+ if(rp->type==d_auth && authorized)
+ continue;
+ if(rp->program == 0)
+ rp->program = regcomp(rp->matchre->base);
+ if(rp->program == 0)
+ continue;
+ memset(rp->subexp, 0, sizeof(rp->subexp));
+ if(debug)
+ print("matching %s aginst %s\n", s_to_c(addrp), rp->matchre->base);
+ if(regexec(rp->program, s_to_c(addrp), rp->subexp, NSUBEXP))
+ if(s_to_c(addrp) == rp->subexp[0].s.sp)
+ if((s_to_c(addrp) + strlen(s_to_c(addrp))) == rp->subexp[0].e.ep)
+ return rp;
+ }
+ return 0;
+}
+
+/* Transforms the address into a command.
+ * Returns: -1 ifaddress not matched by reules
+ * 0 ifaddress matched and ok to forward
+ * 1 ifaddress matched and not ok to forward
+ */
+extern int
+rewrite(dest *dp, message *mp)
+{
+ rule *rp; /* rewriting rule */
+ String *lower; /* lower case version of destination */
+
+ /*
+ * Rewrite the address. Matching is case insensitive.
+ */
+ lower = s_clone(dp->addr);
+ s_tolower(s_restart(lower));
+ rp = findrule(lower, dp->authorized);
+ if(rp == 0){
+ s_free(lower);
+ return -1;
+ }
+ strcpy(s_to_c(lower), s_to_c(dp->addr));
+ dp->repl1 = substitute(rp->repl1, rp->subexp, mp);
+ dp->repl2 = substitute(rp->repl2, rp->subexp, mp);
+ dp->status = rp->type;
+ if(debug){
+ print("\t->");
+ if(dp->repl1)
+ print("%s", s_to_c(dp->repl1));
+ if(dp->repl2)
+ print("%s", s_to_c(dp->repl2));
+ print("\n");
+ }
+ s_free(lower);
+ return 0;
+}
+
+static String *
+substitute(String *source, Resub *subexp, message *mp)
+{
+ int i;
+ char *s;
+ char *sp;
+ String *stp;
+
+ if(source == 0)
+ return 0;
+ sp = s_to_c(source);
+
+ /* someplace to put it */
+ stp = s_new();
+
+ /* do the substitution */
+ while (*sp != '\0') {
+ if(*sp == '\\') {
+ switch (*++sp) {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ i = *sp-'0';
+ if(subexp[i].s.sp != 0)
+ for (s = subexp[i].s.sp;
+ s < subexp[i].e.ep;
+ s++)
+ s_putc(stp, *s);
+ break;
+ case '\\':
+ s_putc(stp, '\\');
+ break;
+ case '\0':
+ sp--;
+ break;
+ case 's':
+ for(s = s_to_c(mp->replyaddr); *s; s++)
+ s_putc(stp, *s);
+ break;
+ case 'p':
+ if(mp->bulk)
+ s = "bulk";
+ else
+ s = "normal";
+ for(;*s; s++)
+ s_putc(stp, *s);
+ break;
+ default:
+ s_putc(stp, *sp);
+ break;
+ }
+ } else if(*sp == '&') {
+ if(subexp[0].s.sp != 0)
+ for (s = subexp[0].s.sp;
+ s < subexp[0].e.ep; s++)
+ s_putc(stp, *s);
+ } else
+ s_putc(stp, *sp);
+ sp++;
+ }
+ s_terminate(stp);
+
+ return s_restart(stp);
+}
+
+extern void
+regerror(char* s)
+{
+ fprint(2, "rewrite: %s\n", s);
+}
+
+extern void
+dumprules(void)
+{
+ rule *rp;
+
+ for (rp = rulep; rp != 0; rp = rp->next) {
+ fprint(2, "'%s'", rp->matchre->base);
+ switch (rp->type) {
+ case d_pipe:
+ fprint(2, " |");
+ break;
+ case d_cat:
+ fprint(2, " >>");
+ break;
+ case d_alias:
+ fprint(2, " alias");
+ break;
+ case d_translate:
+ fprint(2, " translate");
+ break;
+ default:
+ fprint(2, " UNKNOWN");
+ break;
+ }
+ fprint(2, " '%s'", rp->repl1 ? rp->repl1->base:"...");
+ fprint(2, " '%s'\n", rp->repl2 ? rp->repl2->base:"...");
+ }
+}
+