#include "common.h" /* * WARNING! This turns all upper case names into lower case * local ones. */ static String *getdbfiles(void); static int translate(char*, char**, String*, String*); static int lookup(String**, String*, String*); static char *mklower(char*); static int debug; static int from; static char *namefiles = "namefiles"; #define dprint(...) if(debug)fprint(2, __VA_ARGS__); else {} void usage(void) { fprint(2, "usage: aliasmail [-df] [-n namefile] [names ...]\n"); exits("usage"); } void main(int argc, char *argv[]) { char *alias, **names, *p; /* names of this system */ int i, rv; String *s, *salias, *files; ARGBEGIN { case 'd': debug = 1; break; case 'f': from = 1; break; case 'n': namefiles = EARGF(usage()); break; default: usage(); } ARGEND if (chdir(UPASLIB) < 0) sysfatal("chdir: %r"); names = sysnames_read(); files = getdbfiles(); salias = s_new(); /* loop through the names to be translated (from standard input) */ for(i=0; i= 0 && *alias != '\0'){ if(p = strchr(alias, '\n')) *p = 0; if(p = strchr(alias, '!')) { *p = 0; print("%s", alias); } else { if(p = strchr(alias, '@')) print("%s", p+1); else print("%s", alias); } } } else { if (rv < 0 || *alias == '\0') print("local!%s\n", s_to_c(s)); else /* this must be a write, not a print */ write(1, alias, strlen(alias)); } s_free(s); } exits(0); } /* get the list of dbfiles to search */ static String * getdbfiles(void) { char *nf; Sinstack *sp; String *files; if(from) nf = "fromfiles"; else nf = namefiles; /* system wide aliases */ files = s_new(); if ((sp = s_allocinstack(nf)) != 0){ while(s_rdinstack(sp, files)) s_append(files, " "); s_freeinstack(sp); } dprint("files are %s\n", s_to_c(files)); return files; } /* loop through the translation files */ static int translate(char *name, char **namev, String *files, String *alias) { int n, rv; String *file, **fullnamev; rv = -1; file = s_new(); dprint("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. */ #define compare(a, b) cistrcmp(s_to_c(a), b) static int lookup(String **namev, String *file, String *alias) { char *name; int i, rv; String *line, *token, *bangtoken; Sinstack *sp; dprint("lookup(%s, %s, %s, %s)\n", s_to_c(namev[0]), s_to_c(namev[1]), s_to_c(file), s_to_c(alias)); rv = -1; name = s_to_c(namev[0]); line = s_new(); token = s_new(); 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) { dprint("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; } static char* mklower(char *name) { char c, *p; for(p = name; c = *p; p++) if(c >= 'A' && c <= 'Z') *p = c + 0x20; return name; }