ref: eed13a5c22662fe4c77b8587e7a53c9b1ae96acb
dir: /sys/src/cmd/upas/alias/aliasmail.c/
#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(UPASLIB) < 0) { perror("translate(chdir):"); exit(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; }