156822Seric /* 256822Seric * Copyright (c) 1992 Eric P. Allman. 356822Seric * Copyright (c) 1992 Regents of the University of California. 456822Seric * All rights reserved. 556822Seric * 656822Seric * %sccs.include.redist.c% 756822Seric */ 856822Seric 956822Seric #ifndef lint 10*59274Seric static char sccsid[] = "@(#)map.c 6.10 (Berkeley) 04/26/93"; 1156822Seric #endif /* not lint */ 1256822Seric 1356822Seric #include "sendmail.h" 1456822Seric 1556822Seric #ifdef DBM_MAP 1656822Seric #include <ndbm.h> 1756822Seric #endif 1856822Seric #if defined(HASH_MAP) || defined(BTREE_MAP) 1956822Seric #include <db.h> 2056822Seric #endif 2157208Seric #ifdef NIS_MAP 2257208Seric #include <rpcsvc/ypclnt.h> 2357208Seric #endif 2456822Seric 2556822Seric 2656822Seric #ifdef DBM_MAP 2756822Seric 2856822Seric /* 2956822Seric ** DBM_MAP_INIT -- DBM-style map initialization 3056822Seric ** 3156822Seric ** Parameters: 3256822Seric ** map -- the pointer to the actual map 3356822Seric ** mapname -- the name of the map (for error messages) 3456822Seric ** args -- a pointer to the config file line arguments 3556822Seric ** 3656822Seric ** Returns: 3756822Seric ** TRUE -- if it could successfully open the map. 3856822Seric ** FALSE -- otherwise. 3956822Seric ** 4056822Seric ** Side Effects: 4156822Seric ** Gives an error if it can't open the map. 4256822Seric */ 4356822Seric 4456822Seric bool 4556822Seric dbm_map_init(map, mapname, args) 4656822Seric MAP *map; 4756822Seric char *mapname; 4856822Seric char *args; 4956822Seric { 5056822Seric DBM *dbm; 5156822Seric 5257208Seric map_parseargs(map, &args); 5356822Seric if (map->map_file == NULL) 5457208Seric { 5557208Seric syserr("No file name for DBM map %s", mapname); 5656822Seric return FALSE; 5757208Seric } 5856822Seric dbm = dbm_open(map->map_file, O_RDONLY, 0644); 5956822Seric if (dbm == NULL) 6056822Seric { 6156836Seric if (!bitset(MF_OPTIONAL, map->map_flags)) 6256836Seric syserr("Cannot open DBM database %s", map->map_file); 6356822Seric return FALSE; 6456822Seric } 6556822Seric map->map_db = (void *) dbm; 6656822Seric return TRUE; 6756822Seric } 6856822Seric /* 6956822Seric ** DBM_MAP_LOOKUP -- look up a datum in a DBM-type map 7056822Seric ** 7156822Seric ** Parameters: 7256822Seric ** map -- the map to look up in. 7356822Seric ** buf -- a pointer to to the buffer containing the key. 7456822Seric ** This is a null terminated string. 7556822Seric ** bufsiz -- the size of buf -- note that this is in general 7656822Seric ** larger that strlen(buf), and buf can be changed 7756822Seric ** in place if desired. 7856822Seric ** av -- arguments from the config file (can be interpolated 7956822Seric ** into the final result). 8059084Seric ** statp -- pointer to status word (out-parameter). 8156822Seric ** 8256822Seric ** Returns: 8356822Seric ** A pointer to the rewritten result. 8456822Seric ** NULL if not found in the map. 8556822Seric */ 8656822Seric 8756822Seric char * 8859084Seric dbm_map_lookup(map, buf, bufsiz, av, statp) 8956822Seric MAP *map; 9056822Seric char buf[]; 9156822Seric int bufsiz; 9256822Seric char **av; 9359084Seric int *statp; 9456822Seric { 9556822Seric datum key, val; 9656822Seric 9756822Seric key.dptr = buf; 9856822Seric key.dsize = strlen(buf); 9957033Seric if (!bitset(MF_NOFOLDCASE, map->map_flags)) 10057014Seric { 10157014Seric register char *p; 10257014Seric 10357014Seric for (p = buf; *p != '\0'; p++) 10458050Seric if (isascii(*p) && isupper(*p)) 10557014Seric *p = tolower(*p); 10657014Seric } 10756822Seric if (bitset(MF_INCLNULL, map->map_flags)) 10856822Seric key.dsize++; 10956822Seric val = dbm_fetch(map->map_db, key); 11056822Seric if (val.dptr == NULL) 11156822Seric return NULL; 11257208Seric if (!bitset(MF_MATCHONLY, map->map_flags)) 11357208Seric map_rewrite(val.dptr, val.dsize, buf, bufsiz, av); 11456822Seric return buf; 11556822Seric } 11656822Seric 11756822Seric #endif /* DBM_MAP */ 11856822Seric 11956822Seric #ifdef BTREE_MAP 12056822Seric 12156822Seric /* 12256822Seric ** BTREE_MAP_INIT -- BTREE-style map initialization 12356822Seric ** 12456822Seric ** Parameters: 12556822Seric ** map -- the pointer to the actual map 12656822Seric ** mapname -- the name of the map (for error messages) 12756822Seric ** args -- a pointer to the config file line arguments 12856822Seric ** 12956822Seric ** Returns: 13056822Seric ** TRUE -- if it could successfully open the map. 13156822Seric ** FALSE -- otherwise. 13256822Seric ** 13356822Seric ** Side Effects: 13456822Seric ** Gives an error if it can't open the map. 13556822Seric */ 13656822Seric 13756822Seric bool 13856822Seric bt_map_init(map, mapname, args) 13956822Seric MAP *map; 14056822Seric char *mapname; 14156822Seric char *args; 14256822Seric { 14356822Seric DB *db; 14456822Seric 14557208Seric map_parseargs(map, &args); 14656822Seric if (map->map_file == NULL) 14757208Seric { 14857208Seric syserr("No file name for BTREE map %s", mapname); 14956822Seric return FALSE; 15057208Seric } 15156822Seric db = dbopen(map->map_file, O_RDONLY, 0644, DB_BTREE, NULL); 15256822Seric if (db == NULL) 15356822Seric { 15456836Seric if (!bitset(MF_OPTIONAL, map->map_flags)) 15556836Seric syserr("Cannot open BTREE database %s", map->map_file); 15656822Seric return FALSE; 15756822Seric } 15856822Seric map->map_db = (void *) db; 15956822Seric return TRUE; 16056822Seric } 16156822Seric 16256822Seric #endif /* BTREE_MAP */ 16356822Seric 16456822Seric #ifdef HASH_MAP 16556822Seric 16656822Seric /* 16756822Seric ** HASH_MAP_INIT -- HASH-style map initialization 16856822Seric ** 16956822Seric ** Parameters: 17056822Seric ** map -- the pointer to the actual map 17156822Seric ** mapname -- the name of the map (for error messages) 17256822Seric ** args -- a pointer to the config file line arguments 17356822Seric ** 17456822Seric ** Returns: 17556822Seric ** TRUE -- if it could successfully open the map. 17656822Seric ** FALSE -- otherwise. 17756822Seric ** 17856822Seric ** Side Effects: 17956822Seric ** Gives an error if it can't open the map. 18056822Seric */ 18156822Seric 18256822Seric bool 18356822Seric hash_map_init(map, mapname, args) 18456822Seric MAP *map; 18556822Seric char *mapname; 18656822Seric char *args; 18756822Seric { 18856822Seric DB *db; 18956822Seric 19057208Seric map_parseargs(map, &args); 19156822Seric if (map->map_file == NULL) 19257208Seric { 19357208Seric syserr("No file name for HASH map %s", mapname); 19456822Seric return FALSE; 19557208Seric } 19656822Seric db = dbopen(map->map_file, O_RDONLY, 0644, DB_HASH, NULL); 19756822Seric if (db == NULL) 19856822Seric { 19956836Seric if (!bitset(MF_OPTIONAL, map->map_flags)) 20056836Seric syserr("Cannot open HASH database %s", map->map_file); 20156822Seric return FALSE; 20256822Seric } 20356822Seric map->map_db = (void *) db; 20456822Seric return TRUE; 20556822Seric } 20656822Seric 20756822Seric #endif /* HASH_MAP */ 20856822Seric 20956822Seric #if defined(BTREE_MAP) || defined(HASH_MAP) 21056822Seric 21156822Seric /* 21256822Seric ** DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map 21356822Seric ** 21456822Seric ** Parameters: 21556822Seric ** map -- the map to look up in. 21656822Seric ** buf -- a pointer to to the buffer containing the key. 21756822Seric ** This is a null terminated string. 21856822Seric ** bufsiz -- the size of buf -- note that this is in general 21956822Seric ** larger that strlen(buf), and buf can be changed 22056822Seric ** in place if desired. 22156822Seric ** av -- arguments from the config file (can be interpolated 22256822Seric ** into the final result). 22359084Seric ** statp -- pointer to status word (out-parameter). 22456822Seric ** 22556822Seric ** Returns: 22656822Seric ** A pointer to the rewritten result. 22756822Seric ** NULL if not found in the map. 22856822Seric */ 22956822Seric 23056822Seric char * 23159084Seric db_map_lookup(map, buf, bufsiz, av, statp) 23256822Seric MAP *map; 23356822Seric char buf[]; 23456822Seric int bufsiz; 23556822Seric char **av; 23659084Seric int *statp; 23756822Seric { 23856822Seric DBT key, val; 23956822Seric 24056822Seric key.data = buf; 24156822Seric key.size = strlen(buf); 24257033Seric if (!bitset(MF_NOFOLDCASE, map->map_flags)) 24356847Seric { 24456847Seric register char *p; 24556847Seric 24656847Seric for (p = buf; *p != '\0'; p++) 24758050Seric if (isascii(*p) && isupper(*p)) 24856847Seric *p = tolower(*p); 24956847Seric } 25056822Seric if (bitset(MF_INCLNULL, map->map_flags)) 25156822Seric key.size++; 25256836Seric if (((DB *) map->map_db)->get((DB *) map->map_db, &key, &val, 0) != 0) 25356822Seric return NULL; 25457208Seric if (!bitset(MF_MATCHONLY, map->map_flags)) 25557208Seric map_rewrite(val.data, val.size, buf, bufsiz, av); 25656822Seric return buf; 25756822Seric } 25856822Seric 25956822Seric #endif /* BTREE_MAP || HASH_MAP */ 26056822Seric /* 26156822Seric ** MAP_PARSEARGS -- parse config line arguments for database lookup 26256822Seric ** 26356822Seric ** Parameters: 26456822Seric ** map -- the map being initialized. 26556822Seric ** pp -- an indirect pointer to the config line. It will 26656822Seric ** be replaced with a pointer to the next field 26756822Seric ** on the line. 26856822Seric ** 26956822Seric ** Returns: 27056822Seric ** none 27156822Seric ** 27256822Seric ** Side Effects: 27356822Seric ** null terminates the filename; stores it in map 27456822Seric */ 27556822Seric 27657208Seric map_parseargs(map, pp) 27756822Seric MAP *map; 27856822Seric char **pp; 27956822Seric { 28056822Seric register char *p = *pp; 28156822Seric 28256822Seric for (;;) 28356822Seric { 28458050Seric while (isascii(*p) && isspace(*p)) 28556822Seric p++; 28656822Seric if (*p != '-') 28756822Seric break; 28856822Seric switch (*++p) 28956822Seric { 29056822Seric case 'N': 29156822Seric map->map_flags |= MF_INCLNULL; 29256822Seric break; 29356836Seric 29456836Seric case 'o': 29556836Seric map->map_flags |= MF_OPTIONAL; 29656836Seric break; 29756836Seric 29856847Seric case 'f': 29957033Seric map->map_flags |= MF_NOFOLDCASE; 30056847Seric break; 30156847Seric 30257208Seric case 'm': 30357208Seric map->map_flags |= MF_MATCHONLY; 30457208Seric break; 30557208Seric 30656836Seric case 'a': 30756836Seric map->map_app = ++p; 30856836Seric break; 30957208Seric 31057208Seric case 'd': 31157208Seric map->map_domain = ++p; 31257208Seric break; 31356822Seric } 31458050Seric while (*p != '\0' && !(isascii(*p) && isspace(*p))) 31556822Seric p++; 31656836Seric if (*p != '\0') 31758804Seric *p++ = '\0'; 31856822Seric } 31956836Seric if (map->map_app != NULL) 32056836Seric map->map_app = newstr(map->map_app); 32157208Seric if (map->map_domain != NULL) 32257208Seric map->map_domain = newstr(map->map_domain); 32356822Seric 32456822Seric if (*p != '\0') 32558804Seric { 32658804Seric map->map_file = p; 32758804Seric while (*p != '\0' && !(isascii(*p) && isspace(*p))) 32858804Seric p++; 32958804Seric if (*p != '\0') 33058804Seric *p++ = '\0'; 33158804Seric map->map_file = newstr(map->map_file); 33258804Seric } 33358963Seric 33458963Seric while (*p != '\0' && isascii(*p) && isspace(*p)) 33558963Seric p++; 33656822Seric *pp = p; 33758963Seric if (*p != '\0') 33858963Seric map->map_rebuild = newstr(p); 33956822Seric } 34057208Seric 34157208Seric # ifdef NIS_MAP 34257208Seric 34357208Seric /* 34457208Seric ** NIS_MAP_INIT -- initialize DBM map 34557208Seric ** 34657208Seric ** Parameters: 34757208Seric ** map -- the pointer to the actual map. 34857208Seric ** mapname -- the name of the map (for error messages). 34957208Seric ** args -- a pointer to the config file line arguments. 35057208Seric ** 35157208Seric ** Returns: 35257208Seric ** TRUE -- if it could successfully open the map. 35357208Seric ** FALSE -- otherwise. 35457208Seric ** 35557208Seric ** Side Effects: 35657208Seric ** Prints an error if it can't open the map. 35757208Seric */ 35857208Seric 35957208Seric bool 36057208Seric nis_map_init(map, mapname, args) 36157208Seric MAP *map; 36257208Seric char *mapname; 36357208Seric char *args; 36457208Seric { 36557216Seric int yperr; 36657216Seric char *master; 36757216Seric 36857208Seric /* parse arguments */ 36957208Seric map_parseargs(map, &args); 37057208Seric if (map->map_file == NULL) 37157208Seric { 37257208Seric syserr("No NIS map name for map %s", mapname); 37357208Seric return FALSE; 37457208Seric } 37557208Seric if (map->map_domain == NULL) 37657208Seric yp_get_default_domain(&map->map_domain); 37757216Seric 37857216Seric /* check to see if this map actually exists */ 37957216Seric yperr = yp_master(map->map_domain, map->map_file, &master); 38057216Seric if (yperr == 0) 38157216Seric return TRUE; 38257216Seric if (!bitset(MF_OPTIONAL, map->map_flags)) 38357216Seric syserr("Cannot bind to domain %s: %s", map->map_domain, 38457216Seric yperr_string(yperr)); 38557216Seric return FALSE; 38657208Seric } 38756822Seric /* 38857208Seric ** NIS_MAP_LOOKUP -- look up a datum in a NIS map 38957208Seric ** 39057208Seric ** Parameters: 39157208Seric ** map -- the map to look up in. 39257208Seric ** buf -- a pointer to to the buffer containing the key. 39357208Seric ** This is a null terminated string. 39457208Seric ** bufsiz -- the size of buf -- note that this is in general 39557208Seric ** larger that strlen(buf), and buf can be changed 39657208Seric ** in place if desired. 39757208Seric ** av -- arguments from the config file (can be interpolated 39857208Seric ** into the final result). 39959084Seric ** statp -- pointer to status word (out-parameter). 40057208Seric ** 40157208Seric ** Returns: 40257208Seric ** A pointer to the rewritten result. 40357208Seric ** NULL if not found in the map. 40457208Seric */ 40557208Seric 40657208Seric char * 40759084Seric nis_map_lookup(map, buf, bufsiz, av, statp) 40857208Seric MAP *map; 40957208Seric char buf[]; 41057208Seric int bufsiz; 41157208Seric char **av; 41259084Seric int *statp; 41357208Seric { 41457208Seric char *vp; 41557642Seric auto int vsize; 416*59274Seric int buflen; 41757208Seric 41857208Seric if (!bitset(MF_NOFOLDCASE, map->map_flags)) 41957208Seric { 42057208Seric register char *p; 42157208Seric 42257208Seric for (p = buf; *p != '\0'; p++) 42358050Seric if (isascii(*p) && isupper(*p)) 42457208Seric *p = tolower(*p); 42557208Seric } 426*59274Seric buflen = strlen(buf); 427*59274Seric if (bitset(MF_INCLNULL, map->map_flags)) 428*59274Seric buflen++; 429*59274Seric if (yp_match(map->map_domain, map->map_file, buf, buflen, 43057642Seric &vp, &vsize) != 0) 43157208Seric return NULL; 43257208Seric if (!bitset(MF_MATCHONLY, map->map_flags)) 43357208Seric map_rewrite(vp, vsize, buf, bufsiz, av); 43457208Seric return buf; 43557208Seric } 43657208Seric 43757208Seric #endif /* NIS_MAP */ 43857208Seric /* 43956822Seric ** MAP_REWRITE -- rewrite a database key, interpolating %n indications. 44056822Seric ** 44156822Seric ** Parameters: 44256822Seric ** s -- the string to rewrite, NOT necessarily null terminated. 44356822Seric ** slen -- the length of s. 44456822Seric ** buf -- the place to write it. 44556822Seric ** buflen -- the length of buf. 44656822Seric ** av -- arguments to interpolate into buf. 44756822Seric ** 44856822Seric ** Returns: 44956822Seric ** none. 45056822Seric ** 45156822Seric ** Side Effects: 45256822Seric ** none. 45356822Seric */ 45456822Seric 45556822Seric map_rewrite(s, slen, buf, buflen, av) 45656822Seric register char *s; 45756822Seric int slen; 45856822Seric char buf[]; 45956822Seric int buflen; 46056822Seric char **av; 46156822Seric { 46256822Seric register char *bp; 46356822Seric char *buflim; 46456822Seric register char c; 46556822Seric char **avp; 46656822Seric register char *ap; 46756822Seric 46856822Seric if (tTd(23, 1)) 46956822Seric { 47056822Seric printf("map_rewrite(%.*s), av =\n", slen, s); 47156822Seric for (avp = av; *avp != NULL; avp++) 47256822Seric printf("\t%s\n", *avp); 47356822Seric } 47456822Seric 47556822Seric bp = buf; 47656822Seric buflim = &buf[buflen - 2]; 47756822Seric while (--slen >= 0 && (c = *s++) != '\0') 47856822Seric { 47956822Seric if (c != '%') 48056822Seric { 48156822Seric pushc: 48256822Seric if (bp < buflim) 48356822Seric *bp++ = c; 48456822Seric continue; 48556822Seric } 48656822Seric if (--slen < 0 || (c = *s++) == '\0') 48756822Seric c = '%'; 48856822Seric if (c == '%') 48956822Seric goto pushc; 49058050Seric if (!(isascii(c) && isdigit(c))) 49156822Seric { 49256822Seric *bp++ = '%'; 49356822Seric goto pushc; 49456822Seric } 49556822Seric c -= '0'; 49656822Seric for (avp = av; --c >= 0 && *avp != NULL; avp++) 49756822Seric continue; 49856822Seric if (*avp == NULL) 49956822Seric continue; 50056822Seric 50156822Seric /* transliterate argument into output string */ 50256822Seric for (ap = *avp; (c = *ap++) != '\0'; ) 50356822Seric { 50456822Seric if (bp < buflim) 50556822Seric *bp++ = c; 50656822Seric } 50756822Seric } 50856822Seric *bp++ = '\0'; 50956822Seric if (tTd(23, 1)) 51056822Seric printf("map_rewrite => %s\n", buf); 51156822Seric } 512