xref: /plan9-contrib/sys/src/cmd/upas/alias/aliasmail.c (revision d46c239f8612929b7dbade67d0d071633df3a15d)
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 	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 *
91 getdbfiles(void)
92 {
93 	Biobuf *fp;
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 ((fp = sysopen(nf, "r", 0)) != 0){
104 		while(s_getline(fp, files))
105 			s_append(files, " ");
106 		sysclose(fp);
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
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*
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
187 lookup(
188 	String **namev,
189 	String *file,
190 	String *alias)	/* returned String */
191 {
192 	Biobuf *fp;
193 	String *line = s_new();
194 	String *token = s_new();
195 	String *bangtoken;
196 	int i, rv = -1;
197 	char *name =  s_to_c(namev[0]);
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 ((fp = sysopen(s_to_c(file), "r", 0)) == 0)
204 		return -1;
205 
206 	/* look for a match */
207 	while (s_getline(fp, 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, name)!=0)
213 			continue;
214 		/* match found, get the alias */
215 		while(s_parse(line, s_restart(token))!=0) {
216 			bangtoken = attobang(token);
217 
218 			/* avoid definition loops */
219 			for(i = 0; namev[i]; i++)
220 				if(compare(bangtoken, s_to_c(namev[i]))==0) {
221 					s_append(alias, "local");
222 					s_append(alias, "!");
223 					s_append(alias, name);
224 					break;
225 				}
226 
227 			if(namev[i] == 0)
228 				s_append(alias, s_to_c(token));
229 			s_append(alias, "\n");
230 
231 			if(bangtoken != token)
232 				s_free(bangtoken);
233 		}
234 		rv = 0;
235 		break;
236 	}
237 	s_free(line);
238 	s_free(token);
239 	sysclose(fp);
240 	return rv;
241 }
242 
243 #define lower(c) ((c)>='A' && (c)<='Z' ? (c)-('A'-'a'):(c))
244 
245 /* compare two Strings (case insensitive) */
246 static int
247 compare(String *s1,
248 	char *p2)
249 {
250 	char *p1 = s_to_c(s1);
251 	int rv;
252 
253 	DEBUG print("comparing %s to %s\n", p1, p2);
254 	while((rv = lower(*p1) - lower(*p2)) == 0) {
255 		if (*p1 == '\0')
256 			break;
257 		p1++;
258 		p2++;
259 	}
260 	return rv;
261 }
262 
263 static char*
264 mklower(char *name)
265 {
266 	char *p;
267 	char c;
268 
269 	for(p = name; *p; p++){
270 		c = *p;
271 		*p = lower(c);
272 	}
273 	return name;
274 }
275