Blob


1 #include "common.h"
3 /*
4 * WARNING! This turns all upper case names into lower case
5 * local ones.
6 */
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*);
15 static int debug;
16 static int from;
17 static char *namefiles = "namefiles";
18 #define DEBUG if(debug)
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;
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
43 if (chdir(UPASLIB) < 0)
44 sysfatal("aliasmail chdir %s: %r", UPASLIB);
46 /* get environmental info */
47 names = sysnames_read();
48 files = getdbfiles();
49 alias = s_new();
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 }
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;
96 if(from)
97 nf = "fromfiles";
98 else
99 nf = namefiles;
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);
109 DEBUG print("files are %s\n", s_to_c(files));
111 return files;
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 */
121 String *file = s_new();
122 String **fullnamev;
123 int n, rv;
125 rv = -1;
127 DEBUG print("translate(%s, %s, %s)\n", name,
128 s_to_c(files), s_to_c(alias));
130 /* create the full name to avoid loops (system!name) */
131 for(n = 0; namev[n]; n++)
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++;
142 fullnamev[n] = 0;
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;
153 out:
154 for(n = 0; fullnamev[n]; n++)
155 s_free(fullnamev[n]);
156 s_free(file);
157 free(fullnamev);
158 return rv;
161 /*
162 * very dumb conversion to bang format
163 */
164 static String*
165 attobang(String *token)
167 char *p;
168 String *tok;
170 p = strchr(s_to_c(token), '@');
171 if(p == 0)
172 return token;
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);
179 return tok;
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 */
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;
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));
201 s_reset(alias);
202 if ((sp = s_allocinstack(s_to_c(file))) == 0)
203 return -1;
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;
216 continue;
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);
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;
233 if(namev[i] == 0)
234 s_append(alias, s_to_c(token));
235 s_append(alias, "\n");
237 if(bangtoken != token)
238 s_free(bangtoken);
240 rv = 0;
241 break;
243 s_free(line);
244 s_free(token);
245 s_freeinstack(sp);
246 return rv;
249 #define lower(c) ((c)>='A' && (c)<='Z' ? (c)-('A'-'a'):(c))
251 /* compare two Strings (case insensitive) */
252 static int
253 compare(String *s1,
254 char *p2)
256 char *p1 = s_to_c(s1);
257 int rv;
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++;
266 return rv;
269 static char*
270 mklower(char *name)
272 char *p;
273 char c;
275 for(p = name; *p; p++){
276 c = *p;
277 *p = lower(c);
279 return name;