xref: /plan9-contrib/sys/src/cmd/upas/alias/aliasmail.c (revision dc5a79c1208f0704eeb474acc990728f8b4854f5)
13e12c5d1SDavid du Colombier #include "common.h"
23e12c5d1SDavid du Colombier 
3219b2ee8SDavid du Colombier /*
4219b2ee8SDavid du Colombier  *  WARNING!  This turns all upper case names into lower case
5219b2ee8SDavid du Colombier  *  local ones.
6219b2ee8SDavid du Colombier  */
7219b2ee8SDavid du Colombier 
83e12c5d1SDavid du Colombier /* predeclared */
93e12c5d1SDavid du Colombier static String	*getdbfiles(void);
107dd7cddfSDavid du Colombier static int	translate(char*, char**, String*, String*);
117dd7cddfSDavid du Colombier static int	lookup(String**, String*, String*);
123e12c5d1SDavid du Colombier static int	compare(String*, char*);
13219b2ee8SDavid du Colombier static char*	mklower(char*);
143e12c5d1SDavid du Colombier 
153e12c5d1SDavid du Colombier static int debug;
167dd7cddfSDavid du Colombier static int from;
177dd7cddfSDavid du Colombier static char *namefiles = "namefiles";
183e12c5d1SDavid du Colombier #define DEBUG if(debug)
193e12c5d1SDavid du Colombier 
203e12c5d1SDavid du Colombier /* loop through the names to be translated */
213e12c5d1SDavid du Colombier void
main(int argc,char * argv[])223e12c5d1SDavid du Colombier main(int argc, char *argv[])
233e12c5d1SDavid du Colombier {
247dd7cddfSDavid du Colombier 	String *s;
253e12c5d1SDavid du Colombier 	String *alias;		/* the alias for the name */
267dd7cddfSDavid du Colombier 	char **names;		/* names of this system */
273e12c5d1SDavid du Colombier 	String *files;		/* list of files to search */
283e12c5d1SDavid du Colombier 	int i, rv;
297dd7cddfSDavid du Colombier 	char *p;
303e12c5d1SDavid du Colombier 
313e12c5d1SDavid du Colombier 	ARGBEGIN {
323e12c5d1SDavid du Colombier 	case 'd':
333e12c5d1SDavid du Colombier 		debug = 1;
343e12c5d1SDavid du Colombier 		break;
357dd7cddfSDavid du Colombier 	case 'f':
367dd7cddfSDavid du Colombier 		from = 1;
377dd7cddfSDavid du Colombier 		break;
387dd7cddfSDavid du Colombier 	case 'n':
397dd7cddfSDavid du Colombier 		namefiles = ARGF();
407dd7cddfSDavid du Colombier 		break;
413e12c5d1SDavid du Colombier 	} ARGEND
427dd7cddfSDavid du Colombier 	if (chdir(UPASLIB) < 0) {
433e12c5d1SDavid du Colombier 		perror("translate(chdir):");
443e12c5d1SDavid du Colombier 		exit(1);
453e12c5d1SDavid du Colombier 	}
463e12c5d1SDavid du Colombier 
473e12c5d1SDavid du Colombier 	/* get environmental info */
487dd7cddfSDavid du Colombier 	names = sysnames_read();
493e12c5d1SDavid du Colombier 	files = getdbfiles();
503e12c5d1SDavid du Colombier 	alias = s_new();
513e12c5d1SDavid du Colombier 
523e12c5d1SDavid du Colombier 	/* loop through the names to be translated (from standard input) */
533e12c5d1SDavid du Colombier 	for(i=0; i<argc; i++) {
547dd7cddfSDavid du Colombier 		s = unescapespecial(s_copy(mklower(argv[i])));
557dd7cddfSDavid du Colombier 		if(strchr(s_to_c(s), '!') == 0)
567dd7cddfSDavid du Colombier 			rv = translate(s_to_c(s), names, files, alias);
573e12c5d1SDavid du Colombier 		else
587dd7cddfSDavid du Colombier 			rv = -1;
597dd7cddfSDavid du Colombier 		if(from){
607dd7cddfSDavid du Colombier 			if (rv >= 0 && *s_to_c(alias) != '\0'){
617dd7cddfSDavid du Colombier 				p = strchr(s_to_c(alias), '\n');
627dd7cddfSDavid du Colombier 				if(p)
637dd7cddfSDavid du Colombier 					*p = 0;
647dd7cddfSDavid du Colombier 				p = strchr(s_to_c(alias), '!');
657dd7cddfSDavid du Colombier 				if(p) {
667dd7cddfSDavid du Colombier 					*p = 0;
677dd7cddfSDavid du Colombier 					print("%s", s_to_c(alias));
687dd7cddfSDavid du Colombier 				} else {
697dd7cddfSDavid du Colombier 					p = strchr(s_to_c(alias), '@');
707dd7cddfSDavid du Colombier 					if(p)
717dd7cddfSDavid du Colombier 						print("%s", p+1);
727dd7cddfSDavid du Colombier 					else
737dd7cddfSDavid du Colombier 						print("%s", s_to_c(alias));
747dd7cddfSDavid du Colombier 				}
757dd7cddfSDavid du Colombier 			}
767dd7cddfSDavid du Colombier 		} else {
777dd7cddfSDavid du Colombier 			if (rv < 0 || *s_to_c(alias) == '\0')
787dd7cddfSDavid du Colombier 				print("local!%s\n", s_to_c(s));
797dd7cddfSDavid du Colombier 			else {
807dd7cddfSDavid du Colombier 				/* this must be a write, not a print */
817dd7cddfSDavid du Colombier 				write(1, s_to_c(alias), strlen(s_to_c(alias)));
827dd7cddfSDavid du Colombier 			}
837dd7cddfSDavid du Colombier 		}
847dd7cddfSDavid du Colombier 		s_free(s);
853e12c5d1SDavid du Colombier 	}
863e12c5d1SDavid du Colombier 	exits(0);
873e12c5d1SDavid du Colombier }
883e12c5d1SDavid du Colombier 
893e12c5d1SDavid du Colombier /* get the list of dbfiles to search */
903e12c5d1SDavid du Colombier static String *
getdbfiles(void)913e12c5d1SDavid du Colombier getdbfiles(void)
923e12c5d1SDavid du Colombier {
93*dc5a79c1SDavid du Colombier 	Sinstack *sp;
943e12c5d1SDavid du Colombier 	String *files = s_new();
957dd7cddfSDavid du Colombier 	char *nf;
967dd7cddfSDavid du Colombier 
977dd7cddfSDavid du Colombier 	if(from)
987dd7cddfSDavid du Colombier 		nf = "fromfiles";
997dd7cddfSDavid du Colombier 	else
1007dd7cddfSDavid du Colombier 		nf = namefiles;
1013e12c5d1SDavid du Colombier 
1023e12c5d1SDavid du Colombier 	/* system wide aliases */
103*dc5a79c1SDavid du Colombier 	if ((sp = s_allocinstack(nf)) != 0){
104*dc5a79c1SDavid du Colombier 		while(s_rdinstack(sp, files))
1053e12c5d1SDavid du Colombier 			s_append(files, " ");
106*dc5a79c1SDavid du Colombier 		s_freeinstack(sp);
1073e12c5d1SDavid du Colombier 	}
1083e12c5d1SDavid du Colombier 
1093e12c5d1SDavid du Colombier 
1103e12c5d1SDavid du Colombier 	DEBUG print("files are %s\n", s_to_c(files));
1113e12c5d1SDavid du Colombier 
1123e12c5d1SDavid du Colombier 	return files;
1133e12c5d1SDavid du Colombier }
1143e12c5d1SDavid du Colombier 
1153e12c5d1SDavid du Colombier /* loop through the translation files */
1163e12c5d1SDavid du Colombier static int
translate(char * name,char ** namev,String * files,String * alias)1173e12c5d1SDavid du Colombier translate(char *name,		/* name to translate */
1187dd7cddfSDavid du Colombier 	char **namev,		/* names of this system */
1197dd7cddfSDavid du Colombier 	String *files,		/* names of system alias files */
1203e12c5d1SDavid du Colombier 	String *alias)		/* where to put the alias */
1213e12c5d1SDavid du Colombier {
1223e12c5d1SDavid du Colombier 	String *file = s_new();
1237dd7cddfSDavid du Colombier 	String **fullnamev;
1247dd7cddfSDavid du Colombier 	int n, rv;
1253e12c5d1SDavid du Colombier 
1267dd7cddfSDavid du Colombier 	rv = -1;
1277dd7cddfSDavid du Colombier 
1287dd7cddfSDavid du Colombier 	DEBUG print("translate(%s, %s, %s)\n", name,
1293e12c5d1SDavid du Colombier 		s_to_c(files), s_to_c(alias));
1303e12c5d1SDavid du Colombier 
1313e12c5d1SDavid du Colombier 	/* create the full name to avoid loops (system!name) */
1327dd7cddfSDavid du Colombier 	for(n = 0; namev[n]; n++)
1337dd7cddfSDavid du Colombier 		;
1347dd7cddfSDavid du Colombier 	fullnamev = (String**)malloc(sizeof(String*)*(n+2));
1357dd7cddfSDavid du Colombier 	n = 0;
1367dd7cddfSDavid du Colombier 	fullnamev[n++] = s_copy(name);
1377dd7cddfSDavid du Colombier 	for(; *namev; namev++){
1387dd7cddfSDavid du Colombier 		fullnamev[n] = s_copy(*namev);
1397dd7cddfSDavid du Colombier 		s_append(fullnamev[n], "!");
1407dd7cddfSDavid du Colombier 		s_append(fullnamev[n], name);
1417dd7cddfSDavid du Colombier 		n++;
1427dd7cddfSDavid du Colombier 	}
1437dd7cddfSDavid du Colombier 	fullnamev[n] = 0;
1443e12c5d1SDavid du Colombier 
1453e12c5d1SDavid du Colombier 	/* look at system-wide names */
1463e12c5d1SDavid du Colombier 	s_restart(files);
1473e12c5d1SDavid du Colombier 	while (s_parse(files, s_restart(file)) != 0) {
1487dd7cddfSDavid du Colombier 		if (lookup(fullnamev, file, alias)==0) {
1497dd7cddfSDavid du Colombier 			rv = 0;
1507dd7cddfSDavid du Colombier 			goto out;
1513e12c5d1SDavid du Colombier 		}
1523e12c5d1SDavid du Colombier 	}
1533e12c5d1SDavid du Colombier 
1547dd7cddfSDavid du Colombier out:
1557dd7cddfSDavid du Colombier 	for(n = 0; fullnamev[n]; n++)
1567dd7cddfSDavid du Colombier 		s_free(fullnamev[n]);
1577dd7cddfSDavid du Colombier 	s_free(file);
1587dd7cddfSDavid du Colombier 	free(fullnamev);
1597dd7cddfSDavid du Colombier 	return rv;
1607dd7cddfSDavid du Colombier }
1617dd7cddfSDavid du Colombier 
1627dd7cddfSDavid du Colombier /*
1637dd7cddfSDavid du Colombier  *  very dumb conversion to bang format
1647dd7cddfSDavid du Colombier  */
1657dd7cddfSDavid du Colombier static String*
attobang(String * token)1667dd7cddfSDavid du Colombier attobang(String *token)
1677dd7cddfSDavid du Colombier {
1687dd7cddfSDavid du Colombier 	char *p;
1697dd7cddfSDavid du Colombier 	String *tok;
1707dd7cddfSDavid du Colombier 
1717dd7cddfSDavid du Colombier 	p = strchr(s_to_c(token), '@');
1727dd7cddfSDavid du Colombier 	if(p == 0)
1737dd7cddfSDavid du Colombier 		return token;
1747dd7cddfSDavid du Colombier 
1757dd7cddfSDavid du Colombier 	p++;
1767dd7cddfSDavid du Colombier 	tok = s_copy(p);
1777dd7cddfSDavid du Colombier 	s_append(tok, "!");
1787dd7cddfSDavid du Colombier 	s_nappend(tok, s_to_c(token), p - s_to_c(token) - 1);
1797dd7cddfSDavid du Colombier 
1807dd7cddfSDavid du Colombier 	return tok;
1813e12c5d1SDavid du Colombier }
1823e12c5d1SDavid du Colombier 
1833e12c5d1SDavid du Colombier /*  Loop through the entries in a translation file looking for a match.
1843e12c5d1SDavid du Colombier  *  Return 0 if found, -1 otherwise.
1853e12c5d1SDavid du Colombier  */
1863e12c5d1SDavid du Colombier static int
lookup(String ** namev,String * file,String * alias)1877dd7cddfSDavid du Colombier lookup(
1887dd7cddfSDavid du Colombier 	String **namev,
1893e12c5d1SDavid du Colombier 	String *file,
1903e12c5d1SDavid du Colombier 	String *alias)	/* returned String */
1913e12c5d1SDavid du Colombier {
1923e12c5d1SDavid du Colombier 	String *line = s_new();
1933e12c5d1SDavid du Colombier 	String *token = s_new();
1947dd7cddfSDavid du Colombier 	String *bangtoken;
1957dd7cddfSDavid du Colombier 	int i, rv = -1;
1967dd7cddfSDavid du Colombier 	char *name =  s_to_c(namev[0]);
197*dc5a79c1SDavid du Colombier 	Sinstack *sp;
1983e12c5d1SDavid du Colombier 
1997dd7cddfSDavid du Colombier 	DEBUG print("lookup(%s, %s, %s, %s)\n", s_to_c(namev[0]), s_to_c(namev[1]),
2003e12c5d1SDavid du Colombier 		s_to_c(file), s_to_c(alias));
2013e12c5d1SDavid du Colombier 
2023e12c5d1SDavid du Colombier 	s_reset(alias);
203*dc5a79c1SDavid du Colombier 	if ((sp = s_allocinstack(s_to_c(file))) == 0)
2043e12c5d1SDavid du Colombier 		return -1;
2053e12c5d1SDavid du Colombier 
2063e12c5d1SDavid du Colombier 	/* look for a match */
207*dc5a79c1SDavid du Colombier 	while (s_rdinstack(sp, s_restart(line))!=0) {
2083e12c5d1SDavid du Colombier 		DEBUG print("line is %s\n", s_to_c(line));
2093e12c5d1SDavid du Colombier 		s_restart(token);
2103e12c5d1SDavid du Colombier 		if (s_parse(s_restart(line), token)==0)
2113e12c5d1SDavid du Colombier 			continue;
212*dc5a79c1SDavid du Colombier 		if (compare(token, "#include")==0){
213*dc5a79c1SDavid du Colombier 			if(s_parse(line, s_restart(token))!=0) {
214*dc5a79c1SDavid du Colombier 				if(lookup(namev, line, alias) == 0)
215*dc5a79c1SDavid du Colombier 					break;
216*dc5a79c1SDavid du Colombier 			}
217*dc5a79c1SDavid du Colombier 			continue;
218*dc5a79c1SDavid du Colombier 		}
2193e12c5d1SDavid du Colombier 		if (compare(token, name)!=0)
2203e12c5d1SDavid du Colombier 			continue;
2213e12c5d1SDavid du Colombier 		/* match found, get the alias */
2223e12c5d1SDavid du Colombier 		while(s_parse(line, s_restart(token))!=0) {
2237dd7cddfSDavid du Colombier 			bangtoken = attobang(token);
2247dd7cddfSDavid du Colombier 
2253e12c5d1SDavid du Colombier 			/* avoid definition loops */
2267dd7cddfSDavid du Colombier 			for(i = 0; namev[i]; i++)
2277dd7cddfSDavid du Colombier 				if(compare(bangtoken, s_to_c(namev[i]))==0) {
2283e12c5d1SDavid du Colombier 					s_append(alias, "local");
2293e12c5d1SDavid du Colombier 					s_append(alias, "!");
2303e12c5d1SDavid du Colombier 					s_append(alias, name);
2317dd7cddfSDavid du Colombier 					break;
2323e12c5d1SDavid du Colombier 				}
2337dd7cddfSDavid du Colombier 
2347dd7cddfSDavid du Colombier 			if(namev[i] == 0)
2357dd7cddfSDavid du Colombier 				s_append(alias, s_to_c(token));
2367dd7cddfSDavid du Colombier 			s_append(alias, "\n");
2377dd7cddfSDavid du Colombier 
2387dd7cddfSDavid du Colombier 			if(bangtoken != token)
2397dd7cddfSDavid du Colombier 				s_free(bangtoken);
2403e12c5d1SDavid du Colombier 		}
2413e12c5d1SDavid du Colombier 		rv = 0;
2423e12c5d1SDavid du Colombier 		break;
2433e12c5d1SDavid du Colombier 	}
2443e12c5d1SDavid du Colombier 	s_free(line);
2453e12c5d1SDavid du Colombier 	s_free(token);
246*dc5a79c1SDavid du Colombier 	s_freeinstack(sp);
2473e12c5d1SDavid du Colombier 	return rv;
2483e12c5d1SDavid du Colombier }
2493e12c5d1SDavid du Colombier 
2503e12c5d1SDavid du Colombier #define lower(c) ((c)>='A' && (c)<='Z' ? (c)-('A'-'a'):(c))
251219b2ee8SDavid du Colombier 
252219b2ee8SDavid du Colombier /* compare two Strings (case insensitive) */
2533e12c5d1SDavid du Colombier static int
compare(String * s1,char * p2)2543e12c5d1SDavid du Colombier compare(String *s1,
2553e12c5d1SDavid du Colombier 	char *p2)
2563e12c5d1SDavid du Colombier {
2573e12c5d1SDavid du Colombier 	char *p1 = s_to_c(s1);
2583e12c5d1SDavid du Colombier 	int rv;
2593e12c5d1SDavid du Colombier 
2603e12c5d1SDavid du Colombier 	DEBUG print("comparing %s to %s\n", p1, p2);
2613e12c5d1SDavid du Colombier 	while((rv = lower(*p1) - lower(*p2)) == 0) {
2623e12c5d1SDavid du Colombier 		if (*p1 == '\0')
2633e12c5d1SDavid du Colombier 			break;
2643e12c5d1SDavid du Colombier 		p1++;
2653e12c5d1SDavid du Colombier 		p2++;
2663e12c5d1SDavid du Colombier 	}
2673e12c5d1SDavid du Colombier 	return rv;
2683e12c5d1SDavid du Colombier }
269219b2ee8SDavid du Colombier 
2707dd7cddfSDavid du Colombier static char*
mklower(char * name)271219b2ee8SDavid du Colombier mklower(char *name)
272219b2ee8SDavid du Colombier {
273219b2ee8SDavid du Colombier 	char *p;
274219b2ee8SDavid du Colombier 	char c;
275219b2ee8SDavid du Colombier 
276219b2ee8SDavid du Colombier 	for(p = name; *p; p++){
277219b2ee8SDavid du Colombier 		c = *p;
278219b2ee8SDavid du Colombier 		*p = lower(c);
279219b2ee8SDavid du Colombier 	}
280219b2ee8SDavid du Colombier 	return name;
281219b2ee8SDavid du Colombier }
282