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