plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

aliasmail.c (5443B)


      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 
     43 	if (chdir(UPASLIB) < 0)
     44 		sysfatal("aliasmail chdir %s: %r", UPASLIB);
     45 
     46 	/* get environmental info */
     47 	names = sysnames_read();
     48 	files = getdbfiles();
     49 	alias = s_new();
     50 
     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 }
     87 
     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;
     95 
     96 	if(from)
     97 		nf = "fromfiles";
     98 	else
     99 		nf = namefiles;
    100 
    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);
    106 	}
    107 
    108 
    109 	DEBUG print("files are %s\n", s_to_c(files));
    110 
    111 	return files;
    112 }
    113 
    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 */
    120 {
    121 	String *file = s_new();
    122 	String **fullnamev;
    123 	int n, rv;
    124 
    125 	rv = -1;
    126 
    127 	DEBUG print("translate(%s, %s, %s)\n", name,
    128 		s_to_c(files), s_to_c(alias));
    129 
    130 	/* create the full name to avoid loops (system!name) */
    131 	for(n = 0; namev[n]; n++)
    132 		;
    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++;
    141 	}
    142 	fullnamev[n] = 0;
    143 
    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;
    150 		}
    151 	}
    152 
    153 out:
    154 	for(n = 0; fullnamev[n]; n++)
    155 		s_free(fullnamev[n]);
    156 	s_free(file);
    157 	free(fullnamev);
    158 	return rv;
    159 }
    160 
    161 /*
    162  *  very dumb conversion to bang format
    163  */
    164 static String*
    165 attobang(String *token)
    166 {
    167 	char *p;
    168 	String *tok;
    169 
    170 	p = strchr(s_to_c(token), '@');
    171 	if(p == 0)
    172 		return token;
    173 
    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);
    178 
    179 	return tok;
    180 }
    181 
    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 */
    190 {
    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;
    197 
    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));
    200 
    201 	s_reset(alias);
    202 	if ((sp = s_allocinstack(s_to_c(file))) == 0)
    203 		return -1;
    204 
    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;
    215 			}
    216 			continue;
    217 		}
    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);
    223 
    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;
    231 				}
    232 
    233 			if(namev[i] == 0)
    234 				s_append(alias, s_to_c(token));
    235 			s_append(alias, "\n");
    236 
    237 			if(bangtoken != token)
    238 				s_free(bangtoken);
    239 		}
    240 		rv = 0;
    241 		break;
    242 	}
    243 	s_free(line);
    244 	s_free(token);
    245 	s_freeinstack(sp);
    246 	return rv;
    247 }
    248 
    249 #define lower(c) ((c)>='A' && (c)<='Z' ? (c)-('A'-'a'):(c))
    250 
    251 /* compare two Strings (case insensitive) */
    252 static int
    253 compare(String *s1,
    254 	char *p2)
    255 {
    256 	char *p1 = s_to_c(s1);
    257 	int rv;
    258 
    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++;
    265 	}
    266 	return rv;
    267 }
    268 
    269 static char*
    270 mklower(char *name)
    271 {
    272 	char *p;
    273 	char c;
    274 
    275 	for(p = name; *p; p++){
    276 		c = *p;
    277 		*p = lower(c);
    278 	}
    279 	return name;
    280 }