aliasmail.c (5443B)
1 #include "common.h" 2 3 /* 4 * WARNING! This turns all upper case names into lower case 5 * local ones. 6 */ 7 8 /* predeclared */ 9 static String *getdbfiles(void); 10 static int translate(char*, char**, String*, String*); 11 static int lookup(String**, String*, String*); 12 static int compare(String*, char*); 13 static char* mklower(char*); 14 15 static int debug; 16 static int from; 17 static char *namefiles = "namefiles"; 18 #define DEBUG if(debug) 19 20 /* loop through the names to be translated */ 21 void 22 main(int argc, char *argv[]) 23 { 24 String *s; 25 String *alias; /* the alias for the name */ 26 char **names; /* names of this system */ 27 String *files; /* list of files to search */ 28 int i, rv; 29 char *p; 30 31 ARGBEGIN { 32 case 'd': 33 debug = 1; 34 break; 35 case 'f': 36 from = 1; 37 break; 38 case 'n': 39 namefiles = ARGF(); 40 break; 41 } ARGEND 42 43 if (chdir(UPASLIB) < 0) 44 sysfatal("aliasmail chdir %s: %r", UPASLIB); 45 46 /* get environmental info */ 47 names = sysnames_read(); 48 files = getdbfiles(); 49 alias = s_new(); 50 51 /* loop through the names to be translated (from standard input) */ 52 for(i=0; i<argc; i++) { 53 s = unescapespecial(s_copy(mklower(argv[i]))); 54 if(strchr(s_to_c(s), '!') == 0) 55 rv = translate(s_to_c(s), names, files, alias); 56 else 57 rv = -1; 58 if(from){ 59 if (rv >= 0 && *s_to_c(alias) != '\0'){ 60 p = strchr(s_to_c(alias), '\n'); 61 if(p) 62 *p = 0; 63 p = strchr(s_to_c(alias), '!'); 64 if(p) { 65 *p = 0; 66 print("%s", s_to_c(alias)); 67 } else { 68 p = strchr(s_to_c(alias), '@'); 69 if(p) 70 print("%s", p+1); 71 else 72 print("%s", s_to_c(alias)); 73 } 74 } 75 } else { 76 if (rv < 0 || *s_to_c(alias) == '\0') 77 print("local!%s\n", s_to_c(s)); 78 else { 79 /* this must be a write, not a print */ 80 write(1, s_to_c(alias), strlen(s_to_c(alias))); 81 } 82 } 83 s_free(s); 84 } 85 exits(0); 86 } 87 88 /* get the list of dbfiles to search */ 89 static String * 90 getdbfiles(void) 91 { 92 Sinstack *sp; 93 String *files = s_new(); 94 char *nf; 95 96 if(from) 97 nf = "fromfiles"; 98 else 99 nf = namefiles; 100 101 /* system wide aliases */ 102 if ((sp = s_allocinstack(nf)) != 0){ 103 while(s_rdinstack(sp, files)) 104 s_append(files, " "); 105 s_freeinstack(sp); 106 } 107 108 109 DEBUG print("files are %s\n", s_to_c(files)); 110 111 return files; 112 } 113 114 /* loop through the translation files */ 115 static int 116 translate(char *name, /* name to translate */ 117 char **namev, /* names of this system */ 118 String *files, /* names of system alias files */ 119 String *alias) /* where to put the alias */ 120 { 121 String *file = s_new(); 122 String **fullnamev; 123 int n, rv; 124 125 rv = -1; 126 127 DEBUG print("translate(%s, %s, %s)\n", name, 128 s_to_c(files), s_to_c(alias)); 129 130 /* create the full name to avoid loops (system!name) */ 131 for(n = 0; namev[n]; n++) 132 ; 133 fullnamev = (String**)malloc(sizeof(String*)*(n+2)); 134 n = 0; 135 fullnamev[n++] = s_copy(name); 136 for(; *namev; namev++){ 137 fullnamev[n] = s_copy(*namev); 138 s_append(fullnamev[n], "!"); 139 s_append(fullnamev[n], name); 140 n++; 141 } 142 fullnamev[n] = 0; 143 144 /* look at system-wide names */ 145 s_restart(files); 146 while (s_parse(files, s_restart(file)) != 0) { 147 if (lookup(fullnamev, file, alias)==0) { 148 rv = 0; 149 goto out; 150 } 151 } 152 153 out: 154 for(n = 0; fullnamev[n]; n++) 155 s_free(fullnamev[n]); 156 s_free(file); 157 free(fullnamev); 158 return rv; 159 } 160 161 /* 162 * very dumb conversion to bang format 163 */ 164 static String* 165 attobang(String *token) 166 { 167 char *p; 168 String *tok; 169 170 p = strchr(s_to_c(token), '@'); 171 if(p == 0) 172 return token; 173 174 p++; 175 tok = s_copy(p); 176 s_append(tok, "!"); 177 s_nappend(tok, s_to_c(token), p - s_to_c(token) - 1); 178 179 return tok; 180 } 181 182 /* Loop through the entries in a translation file looking for a match. 183 * Return 0 if found, -1 otherwise. 184 */ 185 static int 186 lookup( 187 String **namev, 188 String *file, 189 String *alias) /* returned String */ 190 { 191 String *line = s_new(); 192 String *token = s_new(); 193 String *bangtoken; 194 int i, rv = -1; 195 char *name = s_to_c(namev[0]); 196 Sinstack *sp; 197 198 DEBUG print("lookup(%s, %s, %s, %s)\n", s_to_c(namev[0]), s_to_c(namev[1]), 199 s_to_c(file), s_to_c(alias)); 200 201 s_reset(alias); 202 if ((sp = s_allocinstack(s_to_c(file))) == 0) 203 return -1; 204 205 /* look for a match */ 206 while (s_rdinstack(sp, s_restart(line))!=0) { 207 DEBUG print("line is %s\n", s_to_c(line)); 208 s_restart(token); 209 if (s_parse(s_restart(line), token)==0) 210 continue; 211 if (compare(token, "#include")==0){ 212 if(s_parse(line, s_restart(token))!=0) { 213 if(lookup(namev, line, alias) == 0) 214 break; 215 } 216 continue; 217 } 218 if (compare(token, name)!=0) 219 continue; 220 /* match found, get the alias */ 221 while(s_parse(line, s_restart(token))!=0) { 222 bangtoken = attobang(token); 223 224 /* avoid definition loops */ 225 for(i = 0; namev[i]; i++) 226 if(compare(bangtoken, s_to_c(namev[i]))==0) { 227 s_append(alias, "local"); 228 s_append(alias, "!"); 229 s_append(alias, name); 230 break; 231 } 232 233 if(namev[i] == 0) 234 s_append(alias, s_to_c(token)); 235 s_append(alias, "\n"); 236 237 if(bangtoken != token) 238 s_free(bangtoken); 239 } 240 rv = 0; 241 break; 242 } 243 s_free(line); 244 s_free(token); 245 s_freeinstack(sp); 246 return rv; 247 } 248 249 #define lower(c) ((c)>='A' && (c)<='Z' ? (c)-('A'-'a'):(c)) 250 251 /* compare two Strings (case insensitive) */ 252 static int 253 compare(String *s1, 254 char *p2) 255 { 256 char *p1 = s_to_c(s1); 257 int rv; 258 259 DEBUG print("comparing %s to %s\n", p1, p2); 260 while((rv = lower(*p1) - lower(*p2)) == 0) { 261 if (*p1 == '\0') 262 break; 263 p1++; 264 p2++; 265 } 266 return rv; 267 } 268 269 static char* 270 mklower(char *name) 271 { 272 char *p; 273 char c; 274 275 for(p = name; *p; p++){ 276 c = *p; 277 *p = lower(c); 278 } 279 return name; 280 }