254 lines · 4.8 KB · C
RawDownload
#include "common.h" /* *  WARNING!  This turns all upper case names into lower case *  local ones. */ static	String	*getdbfiles(void);static	int	translate(char*, char**, String*, String*);static	int	lookup(String**, String*, String*);static	char	*mklower(char*); static	int	debug;static	int	from;static	char	*namefiles = "namefiles"; #define dprint(...) if(debug)fprint(2, __VA_ARGS__); else {} voidusage(void){	fprint(2, "usage: aliasmail [-df] [-n namefile] [names ...]\n");	exits("usage");} voidmain(int argc, char *argv[]){	char *alias, **names, *p;		/* names of this system */	int i, rv;	String *s, *salias, *files; 	ARGBEGIN {	case 'd':		debug = 1;		break;	case 'f':		from = 1;		break;	case 'n':		namefiles = EARGF(usage());		break;	default:		usage();	} ARGEND	if (chdir(UPASLIB) < 0)		sysfatal("chdir: %r"); 	names = sysnames_read();	files = getdbfiles();	salias = s_new(); 	/* loop through the names to be translated (from standard input) */	for(i=0; i<argc; i++) {		s = unescapespecial(s_copy(mklower(argv[i])));		if(strchr(s_to_c(s), '!') == 0)			rv = translate(s_to_c(s), names, files, salias);		else			rv = -1;		alias = s_to_c(salias);		if(from){			if (rv >= 0 && *alias != '\0'){				if(p = strchr(alias, '\n'))					*p = 0;				if(p = strchr(alias, '!')) {					*p = 0;					print("%s", alias);				} else {					if(p = strchr(alias, '@'))						print("%s", p+1);					else						print("%s", alias);				}			}		} else {			if (rv < 0 || *alias == '\0')				print("local!%s\n", s_to_c(s));			else				/* this must be a write, not a print */				write(1, alias, strlen(alias));		}		s_free(s);	}	exits(0);} /* get the list of dbfiles to search */static String *getdbfiles(void){	char *nf;	Sinstack *sp;	String *files; 	if(from)		nf = "fromfiles";	else		nf = namefiles; 	/* system wide aliases */	files = s_new();	if ((sp = s_allocinstack(nf)) != 0){		while(s_rdinstack(sp, files))			s_append(files, " ");		s_freeinstack(sp);	} 	dprint("files are %s\n", s_to_c(files));	return files;} /* loop through the translation files */static inttranslate(char *name, char **namev,	String *files, String *alias){	int n, rv;	String *file, **fullnamev; 	rv = -1;	file = s_new(); 	dprint("translate(%s, %s, %s)\n", name,		s_to_c(files), s_to_c(alias)); 	/* create the full name to avoid loops (system!name) */	for(n = 0; namev[n]; n++)		; 	fullnamev = (String**)malloc(sizeof(String*)*(n+2));	n = 0;	fullnamev[n++] = s_copy(name);	for(; *namev; namev++){		fullnamev[n] = s_copy(*namev);		s_append(fullnamev[n], "!");		s_append(fullnamev[n], name);		n++;	}	fullnamev[n] = 0; 	/* look at system-wide names */	s_restart(files);	while (s_parse(files, s_restart(file)) != 0)		if (lookup(fullnamev, file, alias)==0) {			rv = 0;			goto out;		} out:	for(n = 0; fullnamev[n]; n++)		s_free(fullnamev[n]);	s_free(file);	free(fullnamev);	return rv;} /* *  very dumb conversion to bang format */static String*attobang(String *token){	char *p;	String *tok; 	p = strchr(s_to_c(token), '@');	if(p == 0)		return token; 	p++;	tok = s_copy(p);	s_append(tok, "!");	s_nappend(tok, s_to_c(token), p - s_to_c(token) - 1); 	return tok;} /*  Loop through the entries in a translation file looking for a match. *  Return 0 if found, -1 otherwise. */#define compare(a, b) cistrcmp(s_to_c(a), b) static intlookup(String **namev, String *file, String *alias){	char *name;	int i, rv;	String *line, *token, *bangtoken;	Sinstack *sp; 	dprint("lookup(%s, %s, %s, %s)\n", s_to_c(namev[0]), s_to_c(namev[1]),		s_to_c(file), s_to_c(alias)); 	rv = -1;	name = s_to_c(namev[0]);	line = s_new();	token = s_new();	s_reset(alias);	if ((sp = s_allocinstack(s_to_c(file))) == 0)		return -1; 	/* look for a match */	while (s_rdinstack(sp, s_restart(line))!=0) {		dprint("line is %s\n", s_to_c(line));		s_restart(token);		if (s_parse(s_restart(line), token)==0)			continue;		if (compare(token, "#include")==0){			if(s_parse(line, s_restart(token))!=0) {				if(lookup(namev, line, alias) == 0)					break;			}			continue;		}		if (compare(token, name)!=0)			continue;		/* match found, get the alias */		while(s_parse(line, s_restart(token))!=0) {			bangtoken = attobang(token); 			/* avoid definition loops */			for(i = 0; namev[i]; i++)				if(compare(bangtoken, s_to_c(namev[i]))==0) {					s_append(alias, "local");					s_append(alias, "!");					s_append(alias, name);					break;				} 			if(namev[i] == 0)				s_append(alias, s_to_c(token));			s_append(alias, "\n"); 			if(bangtoken != token)				s_free(bangtoken);		}		rv = 0;		break;	}	s_free(line);	s_free(token);	s_freeinstack(sp);	return rv;} static char*mklower(char *name){	char c, *p; 	for(p = name; c = *p; p++)		if(c >= 'A' && c <= 'Z')			*p = c + 0x20;	return name;}