aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/upas/alias
diff options
context:
space:
mode:
authorrsc <devnull@localhost>2005-10-29 16:26:32 +0000
committerrsc <devnull@localhost>2005-10-29 16:26:32 +0000
commitd1f529f46f957c78a3db73b42c2fcd2d3c9f8a34 (patch)
treea4d6f28106cca984926b9dd5ecddd6053b654617 /src/cmd/upas/alias
parent9f1fdc128738b2ed76258ac22a8574c681f3df3a (diff)
downloadplan9port-d1f529f46f957c78a3db73b42c2fcd2d3c9f8a34.tar.gz
plan9port-d1f529f46f957c78a3db73b42c2fcd2d3c9f8a34.tar.bz2
plan9port-d1f529f46f957c78a3db73b42c2fcd2d3c9f8a34.zip
Thanks to John Cummings.
Diffstat (limited to 'src/cmd/upas/alias')
-rw-r--r--src/cmd/upas/alias/aliasmail.c281
-rw-r--r--src/cmd/upas/alias/mkfile21
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