diff options
Diffstat (limited to 'src/cmd/upas/alias')
-rw-r--r-- | src/cmd/upas/alias/aliasmail.c | 281 | ||||
-rw-r--r-- | src/cmd/upas/alias/mkfile | 21 |
2 files changed, 302 insertions, 0 deletions
diff --git a/src/cmd/upas/alias/aliasmail.c b/src/cmd/upas/alias/aliasmail.c new file mode 100644 index 00000000..f50c348a --- /dev/null +++ b/src/cmd/upas/alias/aliasmail.c @@ -0,0 +1,281 @@ +#include "common.h" + +/* + * WARNING! This turns all upper case names into lower case + * local ones. + */ + +/* predeclared */ +static String *getdbfiles(void); +static int translate(char*, char**, String*, String*); +static int lookup(String**, String*, String*); +static int compare(String*, char*); +static char* mklower(char*); + +static int debug; +static int from; +static char *namefiles = "namefiles"; +#define DEBUG if(debug) + +/* loop through the names to be translated */ +void +main(int argc, char *argv[]) +{ + String *s; + String *alias; /* the alias for the name */ + char **names; /* names of this system */ + String *files; /* list of files to search */ + int i, rv; + char *p; + + ARGBEGIN { + case 'd': + debug = 1; + break; + case 'f': + from = 1; + break; + case 'n': + namefiles = ARGF(); + break; + } ARGEND + if (chdir(unsharp(UPASLIB)) < 0) { + perror("translate(chdir):"); + exit9(1); + } + + /* get environmental info */ + names = sysnames_read(); + files = getdbfiles(); + alias = s_new(); + + /* loop through the names to be translated (from standard input) */ + for(i=0; i<argc; i++) { + s = unescapespecial(s_copy(mklower(argv[i]))); + if(strchr(s_to_c(s), '!') == 0) + rv = translate(s_to_c(s), names, files, alias); + else + rv = -1; + if(from){ + if (rv >= 0 && *s_to_c(alias) != '\0'){ + p = strchr(s_to_c(alias), '\n'); + if(p) + *p = 0; + p = strchr(s_to_c(alias), '!'); + if(p) { + *p = 0; + print("%s", s_to_c(alias)); + } else { + p = strchr(s_to_c(alias), '@'); + if(p) + print("%s", p+1); + else + print("%s", s_to_c(alias)); + } + } + } else { + if (rv < 0 || *s_to_c(alias) == '\0') + print("local!%s\n", s_to_c(s)); + else { + /* this must be a write, not a print */ + write(1, s_to_c(alias), strlen(s_to_c(alias))); + } + } + s_free(s); + } + exits(0); +} + +/* get the list of dbfiles to search */ +static String * +getdbfiles(void) +{ + Sinstack *sp; + String *files = s_new(); + char *nf; + + if(from) + nf = "fromfiles"; + else + nf = namefiles; + + /* system wide aliases */ + if ((sp = s_allocinstack(nf)) != 0){ + while(s_rdinstack(sp, files)) + s_append(files, " "); + s_freeinstack(sp); + } + + + DEBUG print("files are %s\n", s_to_c(files)); + + return files; +} + +/* loop through the translation files */ +static int +translate(char *name, /* name to translate */ + char **namev, /* names of this system */ + String *files, /* names of system alias files */ + String *alias) /* where to put the alias */ +{ + String *file = s_new(); + String **fullnamev; + int n, rv; + + rv = -1; + + DEBUG print("translate(%s, %s, %s)\n", name, + s_to_c(files), s_to_c(alias)); + + /* create the full name to avoid loops (system!name) */ + for(n = 0; namev[n]; n++) + ; + fullnamev = (String**)malloc(sizeof(String*)*(n+2)); + n = 0; + fullnamev[n++] = s_copy(name); + for(; *namev; namev++){ + fullnamev[n] = s_copy(*namev); + s_append(fullnamev[n], "!"); + s_append(fullnamev[n], name); + n++; + } + fullnamev[n] = 0; + + /* look at system-wide names */ + s_restart(files); + while (s_parse(files, s_restart(file)) != 0) { + if (lookup(fullnamev, file, alias)==0) { + rv = 0; + goto out; + } + } + +out: + for(n = 0; fullnamev[n]; n++) + s_free(fullnamev[n]); + s_free(file); + free(fullnamev); + return rv; +} + +/* + * very dumb conversion to bang format + */ +static String* +attobang(String *token) +{ + char *p; + String *tok; + + p = strchr(s_to_c(token), '@'); + if(p == 0) + return token; + + p++; + tok = s_copy(p); + s_append(tok, "!"); + s_nappend(tok, s_to_c(token), p - s_to_c(token) - 1); + + return tok; +} + +/* Loop through the entries in a translation file looking for a match. + * Return 0 if found, -1 otherwise. + */ +static int +lookup( + String **namev, + String *file, + String *alias) /* returned String */ +{ + String *line = s_new(); + String *token = s_new(); + String *bangtoken; + int i, rv = -1; + char *name = s_to_c(namev[0]); + Sinstack *sp; + + DEBUG print("lookup(%s, %s, %s, %s)\n", s_to_c(namev[0]), s_to_c(namev[1]), + s_to_c(file), s_to_c(alias)); + + s_reset(alias); + if ((sp = s_allocinstack(s_to_c(file))) == 0) + return -1; + + /* look for a match */ + while (s_rdinstack(sp, s_restart(line))!=0) { + DEBUG print("line is %s\n", s_to_c(line)); + s_restart(token); + if (s_parse(s_restart(line), token)==0) + continue; + if (compare(token, "#include")==0){ + if(s_parse(line, s_restart(token))!=0) { + if(lookup(namev, line, alias) == 0) + break; + } + continue; + } + if (compare(token, name)!=0) + continue; + /* match found, get the alias */ + while(s_parse(line, s_restart(token))!=0) { + bangtoken = attobang(token); + + /* avoid definition loops */ + for(i = 0; namev[i]; i++) + if(compare(bangtoken, s_to_c(namev[i]))==0) { + s_append(alias, "local"); + s_append(alias, "!"); + s_append(alias, name); + break; + } + + if(namev[i] == 0) + s_append(alias, s_to_c(token)); + s_append(alias, "\n"); + + if(bangtoken != token) + s_free(bangtoken); + } + rv = 0; + break; + } + s_free(line); + s_free(token); + s_freeinstack(sp); + return rv; +} + +#define lower(c) ((c)>='A' && (c)<='Z' ? (c)-('A'-'a'):(c)) + +/* compare two Strings (case insensitive) */ +static int +compare(String *s1, + char *p2) +{ + char *p1 = s_to_c(s1); + int rv; + + DEBUG print("comparing %s to %s\n", p1, p2); + while((rv = lower(*p1) - lower(*p2)) == 0) { + if (*p1 == '\0') + break; + p1++; + p2++; + } + return rv; +} + +static char* +mklower(char *name) +{ + char *p; + char c; + + for(p = name; *p; p++){ + c = *p; + *p = lower(c); + } + return name; +} diff --git a/src/cmd/upas/alias/mkfile b/src/cmd/upas/alias/mkfile new file mode 100644 index 00000000..d7f8f91c --- /dev/null +++ b/src/cmd/upas/alias/mkfile @@ -0,0 +1,21 @@ +<$PLAN9/src/mkhdr + +TARG=aliasmail + +OFILES=aliasmail.$O\ + +LIB=../common/libcommon.a\ + +HFILES=../common/common.h\ + ../common/sys.h\ + + +BIN=$PLAN9/bin/upas + +UPDATE=\ + mkfile\ + $HFILES\ + ${OFILES:%.$O=%.c}\ + +<$PLAN9/src/mkone +CFLAGS=$CFLAGS -I../common |