diff options
author | rgrimes <rgrimes@FreeBSD.org> | 1994-05-26 05:23:31 +0000 |
---|---|---|
committer | rgrimes <rgrimes@FreeBSD.org> | 1994-05-26 05:23:31 +0000 |
commit | babe0fd0e29aedfa2e1d473fbb3dcec915a3b575 (patch) | |
tree | eb9362e7430d1e6cacffec272ea11deacccddd68 /usr.sbin/sendmail/src/map.c | |
download | FreeBSD-src-babe0fd0e29aedfa2e1d473fbb3dcec915a3b575.zip FreeBSD-src-babe0fd0e29aedfa2e1d473fbb3dcec915a3b575.tar.gz |
BSD 4.4 Lite usr.sbin Sources
Diffstat (limited to 'usr.sbin/sendmail/src/map.c')
-rw-r--r-- | usr.sbin/sendmail/src/map.c | 1339 |
1 files changed, 1339 insertions, 0 deletions
diff --git a/usr.sbin/sendmail/src/map.c b/usr.sbin/sendmail/src/map.c new file mode 100644 index 0000000..01ba411 --- /dev/null +++ b/usr.sbin/sendmail/src/map.c @@ -0,0 +1,1339 @@ +/* + * Copyright (c) 1992 Eric P. Allman. + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)map.c 8.25 (Berkeley) 4/17/94"; +#endif /* not lint */ + +#include "sendmail.h" + +#ifdef NDBM +#include <ndbm.h> +#endif +#ifdef NEWDB +#include <db.h> +#endif +#ifdef NIS +#include <rpcsvc/ypclnt.h> +#endif + +/* +** MAP.C -- implementations for various map classes. +** +** Each map class implements a series of functions: +** +** bool map_parse(MAP *map, char *args) +** Parse the arguments from the config file. Return TRUE +** if they were ok, FALSE otherwise. Fill in map with the +** values. +** +** char *map_lookup(MAP *map, char *key, char **args, int *pstat) +** Look up the key in the given map. If found, do any +** rewriting the map wants (including "args" if desired) +** and return the value. Set *pstat to the appropriate status +** on error and return NULL. Args will be NULL if called +** from the alias routines, although this should probably +** not be relied upon. It is suggested you call map_rewrite +** to return the results -- it takes care of null termination +** and uses a dynamically expanded buffer as needed. +** +** void map_store(MAP *map, char *key, char *value) +** Store the key:value pair in the map. +** +** bool map_open(MAP *map, int mode) +** Open the map for the indicated mode. Mode should +** be either O_RDONLY or O_RDWR. Return TRUE if it +** was opened successfully, FALSE otherwise. If the open +** failed an the MF_OPTIONAL flag is not set, it should +** also print an error. If the MF_ALIAS bit is set +** and this map class understands the @:@ convention, it +** should call aliaswait() before returning. +** +** void map_close(MAP *map) +** Close the map. +*/ + +#define DBMMODE 0644 + +extern bool aliaswait __P((MAP *, char *, int)); +/* +** MAP_PARSEARGS -- parse config line arguments for database lookup +** +** This is a generic version of the map_parse method. +** +** Parameters: +** map -- the map being initialized. +** ap -- a pointer to the args on the config line. +** +** Returns: +** TRUE -- if everything parsed OK. +** FALSE -- otherwise. +** +** Side Effects: +** null terminates the filename; stores it in map +*/ + +bool +map_parseargs(map, ap) + MAP *map; + char *ap; +{ + register char *p = ap; + + map->map_mflags |= MF_TRY0NULL | MF_TRY1NULL; + for (;;) + { + while (isascii(*p) && isspace(*p)) + p++; + if (*p != '-') + break; + switch (*++p) + { + case 'N': + map->map_mflags |= MF_INCLNULL; + map->map_mflags &= ~MF_TRY0NULL; + break; + + case 'O': + map->map_mflags &= ~MF_TRY1NULL; + break; + + case 'o': + map->map_mflags |= MF_OPTIONAL; + break; + + case 'f': + map->map_mflags |= MF_NOFOLDCASE; + break; + + case 'm': + map->map_mflags |= MF_MATCHONLY; + break; + + case 'a': + map->map_app = ++p; + break; + } + while (*p != '\0' && !(isascii(*p) && isspace(*p))) + p++; + if (*p != '\0') + *p++ = '\0'; + } + if (map->map_app != NULL) + map->map_app = newstr(map->map_app); + + if (*p != '\0') + { + map->map_file = p; + while (*p != '\0' && !(isascii(*p) && isspace(*p))) + p++; + if (*p != '\0') + *p++ = '\0'; + map->map_file = newstr(map->map_file); + } + + while (*p != '\0' && isascii(*p) && isspace(*p)) + p++; + if (*p != '\0') + map->map_rebuild = newstr(p); + + if (map->map_file == NULL) + { + syserr("No file name for %s map %s", + map->map_class->map_cname, map->map_mname); + return FALSE; + } + return TRUE; +} +/* +** MAP_REWRITE -- rewrite a database key, interpolating %n indications. +** +** It also adds the map_app string. It can be used as a utility +** in the map_lookup method. +** +** Parameters: +** map -- the map that causes this. +** s -- the string to rewrite, NOT necessarily null terminated. +** slen -- the length of s. +** av -- arguments to interpolate into buf. +** +** Returns: +** Pointer to rewritten result. +** +** Side Effects: +** none. +*/ + +struct rwbuf +{ + int rwb_len; /* size of buffer */ + char *rwb_buf; /* ptr to buffer */ +}; + +struct rwbuf RwBufs[2]; /* buffers for rewriting output */ + +char * +map_rewrite(map, s, slen, av) + register MAP *map; + register char *s; + int slen; + char **av; +{ + register char *bp; + register char c; + char **avp; + register char *ap; + register struct rwbuf *rwb; + int i; + int len; + + if (tTd(39, 1)) + { + printf("map_rewrite(%.*s), av =", slen, s); + if (av == NULL) + printf(" (nullv)"); + else + { + for (avp = av; *avp != NULL; avp++) + printf("\n\t%s", *avp); + } + printf("\n"); + } + + rwb = RwBufs; + if (av == NULL) + rwb++; + + /* count expected size of output (can safely overestimate) */ + i = len = slen; + if (av != NULL) + { + bp = s; + for (i = slen; --i >= 0 && (c = *bp++) != 0; ) + { + if (c != '%') + continue; + if (--i < 0) + break; + c = *bp++; + if (!(isascii(c) && isdigit(c))) + continue; + for (avp = av; --c >= '0' && *avp != NULL; avp++) + continue; + if (*avp == NULL) + continue; + len += strlen(*avp); + } + } + if (map->map_app != NULL) + len += strlen(map->map_app); + if (rwb->rwb_len < ++len) + { + /* need to malloc additional space */ + rwb->rwb_len = len; + if (rwb->rwb_buf != NULL) + free(rwb->rwb_buf); + rwb->rwb_buf = xalloc(rwb->rwb_len); + } + + bp = rwb->rwb_buf; + if (av == NULL) + { + bcopy(s, bp, slen); + bp += slen; + } + else + { + while (--slen >= 0 && (c = *s++) != '\0') + { + if (c != '%') + { + pushc: + *bp++ = c; + continue; + } + if (--slen < 0 || (c = *s++) == '\0') + c = '%'; + if (c == '%') + goto pushc; + if (!(isascii(c) && isdigit(c))) + { + *bp++ = '%'; + goto pushc; + } + for (avp = av; --c >= '0' && *avp != NULL; avp++) + continue; + if (*avp == NULL) + continue; + + /* transliterate argument into output string */ + for (ap = *avp; (c = *ap++) != '\0'; ) + *bp++ = c; + } + } + if (map->map_app != NULL) + strcpy(bp, map->map_app); + else + *bp = '\0'; + if (tTd(39, 1)) + printf("map_rewrite => %s\n", rwb->rwb_buf); + return rwb->rwb_buf; +} +/* +** INITMAPS -- initialize for aliasing +** +** Parameters: +** rebuild -- if TRUE, this rebuilds the cached versions. +** e -- current envelope. +** +** Returns: +** none. +** +** Side Effects: +** initializes aliases: +** if NDBM: opens the database. +** if ~NDBM: reads the aliases into the symbol table. +*/ + +initmaps(rebuild, e) + bool rebuild; + register ENVELOPE *e; +{ + extern void map_init(); + +#ifdef XDEBUG + checkfd012("entering initmaps"); +#endif + CurEnv = e; + if (rebuild) + { + stabapply(map_init, 1); + stabapply(map_init, 2); + } + else + { + stabapply(map_init, 0); + } +#ifdef XDEBUG + checkfd012("exiting initmaps"); +#endif +} + +void +map_init(s, rebuild) + register STAB *s; + int rebuild; +{ + register MAP *map; + + /* has to be a map */ + if (s->s_type != ST_MAP) + return; + + map = &s->s_map; + if (!bitset(MF_VALID, map->map_mflags)) + return; + + if (tTd(38, 2)) + printf("map_init(%s:%s, %d)\n", + map->map_class->map_cname == NULL ? "NULL" : + map->map_class->map_cname, + map->map_file == NULL ? "NULL" : map->map_file, + rebuild); + + if (rebuild == (bitset(MF_ALIAS, map->map_mflags) && + bitset(MCF_REBUILDABLE, map->map_class->map_cflags) ? 1 : 2)) + { + if (tTd(38, 3)) + printf("\twrong pass\n"); + return; + } + + /* if already open, close it (for nested open) */ + if (bitset(MF_OPEN, map->map_mflags)) + { + map->map_class->map_close(map); + map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); + } + + if (rebuild == 2) + { + rebuildaliases(map, FALSE); + } + else + { + if (map->map_class->map_open(map, O_RDONLY)) + { + if (tTd(38, 4)) + printf("\t%s:%s: valid\n", + map->map_class->map_cname == NULL ? "NULL" : + map->map_class->map_cname, + map->map_file == NULL ? "NULL" : + map->map_file); + map->map_mflags |= MF_OPEN; + } + else if (tTd(38, 4)) + printf("\t%s:%s: invalid: %s\n", + map->map_class->map_cname == NULL ? "NULL" : + map->map_class->map_cname, + map->map_file == NULL ? "NULL" : + map->map_file, + errstring(errno)); + } +} +/* +** NDBM modules +*/ + +#ifdef NDBM + +/* +** DBM_MAP_OPEN -- DBM-style map open +*/ + +bool +ndbm_map_open(map, mode) + MAP *map; + int mode; +{ + register DBM *dbm; + struct stat st; + + if (tTd(38, 2)) + printf("ndbm_map_open(%s, %d)\n", map->map_file, mode); + + if (mode == O_RDWR) + mode |= O_CREAT|O_TRUNC; + + /* open the database */ + dbm = dbm_open(map->map_file, mode, DBMMODE); + if (dbm == NULL) + { +#ifdef MAYBENEXTRELEASE + if (aliaswait(map, ".pag", FALSE)) + return TRUE; +#endif + if (!bitset(MF_OPTIONAL, map->map_mflags)) + syserr("Cannot open DBM database %s", map->map_file); + return FALSE; + } + map->map_db1 = (void *) dbm; + if (mode == O_RDONLY) + { + if (bitset(MF_ALIAS, map->map_mflags) && + !aliaswait(map, ".pag", TRUE)) + return FALSE; + } + else + { + int fd; + + /* exclusive lock for duration of rebuild */ + fd = dbm_dirfno((DBM *) map->map_db1); + if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags) && + lockfile(fd, map->map_file, ".dir", LOCK_EX)) + map->map_mflags |= MF_LOCKED; + } + if (fstat(dbm_dirfno((DBM *) map->map_db1), &st) >= 0) + map->map_mtime = st.st_mtime; + return TRUE; +} + + +/* +** DBM_MAP_LOOKUP -- look up a datum in a DBM-type map +*/ + +char * +ndbm_map_lookup(map, name, av, statp) + MAP *map; + char *name; + char **av; + int *statp; +{ + datum key, val; + int fd; + char keybuf[MAXNAME + 1]; + + if (tTd(38, 20)) + printf("ndbm_map_lookup(%s)\n", name); + + key.dptr = name; + key.dsize = strlen(name); + if (!bitset(MF_NOFOLDCASE, map->map_mflags)) + { + if (key.dsize > sizeof keybuf - 1) + key.dsize = sizeof keybuf - 1; + bcopy(key.dptr, keybuf, key.dsize + 1); + makelower(keybuf); + key.dptr = keybuf; + } + fd = dbm_dirfno((DBM *) map->map_db1); + if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) + (void) lockfile(fd, map->map_file, ".dir", LOCK_SH); + val.dptr = NULL; + if (bitset(MF_TRY0NULL, map->map_mflags)) + { + val = dbm_fetch((DBM *) map->map_db1, key); + if (val.dptr != NULL) + map->map_mflags &= ~MF_TRY1NULL; + } + if (val.dptr == NULL && bitset(MF_TRY1NULL, map->map_mflags)) + { + key.dsize++; + val = dbm_fetch((DBM *) map->map_db1, key); + if (val.dptr != NULL) + map->map_mflags &= ~MF_TRY0NULL; + } + if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) + (void) lockfile(fd, map->map_file, ".dir", LOCK_UN); + if (val.dptr == NULL) + return NULL; + if (bitset(MF_MATCHONLY, map->map_mflags)) + return map_rewrite(map, name, strlen(name), NULL); + else + return map_rewrite(map, val.dptr, val.dsize, av); +} + + +/* +** DBM_MAP_STORE -- store a datum in the database +*/ + +void +ndbm_map_store(map, lhs, rhs) + register MAP *map; + char *lhs; + char *rhs; +{ + datum key; + datum data; + int stat; + + if (tTd(38, 12)) + printf("ndbm_map_store(%s, %s)\n", lhs, rhs); + + key.dsize = strlen(lhs); + key.dptr = lhs; + + data.dsize = strlen(rhs); + data.dptr = rhs; + + if (bitset(MF_INCLNULL, map->map_mflags)) + { + key.dsize++; + data.dsize++; + } + + stat = dbm_store((DBM *) map->map_db1, key, data, DBM_INSERT); + if (stat > 0) + { + usrerr("050 Warning: duplicate alias name %s", lhs); + stat = dbm_store((DBM *) map->map_db1, key, data, DBM_REPLACE); + } + if (stat != 0) + syserr("readaliases: dbm put (%s)", lhs); +} + + +/* +** NDBM_MAP_CLOSE -- close the database +*/ + +void +ndbm_map_close(map) + register MAP *map; +{ + if (tTd(38, 9)) + printf("ndbm_map_close(%s, %x)\n", map->map_file, map->map_mflags); + + if (bitset(MF_WRITABLE, map->map_mflags)) + { +#ifdef NIS + bool inclnull; + char buf[200]; + + inclnull = bitset(MF_INCLNULL, map->map_mflags); + map->map_mflags &= ~MF_INCLNULL; + + (void) sprintf(buf, "%010ld", curtime()); + ndbm_map_store(map, "YP_LAST_MODIFIED", buf); + + (void) gethostname(buf, sizeof buf); + ndbm_map_store(map, "YP_MASTER_NAME", buf); + + if (inclnull) + map->map_mflags |= MF_INCLNULL; +#endif + + /* write out the distinguished alias */ + ndbm_map_store(map, "@", "@"); + } + dbm_close((DBM *) map->map_db1); +} + +#endif +/* +** NEWDB (Hash and BTree) Modules +*/ + +#ifdef NEWDB + +/* +** BT_MAP_OPEN, HASH_MAP_OPEN -- database open primitives. +** +** These do rather bizarre locking. If you can lock on open, +** do that to avoid the condition of opening a database that +** is being rebuilt. If you don't, we'll try to fake it, but +** there will be a race condition. If opening for read-only, +** we immediately release the lock to avoid freezing things up. +** We really ought to hold the lock, but guarantee that we won't +** be pokey about it. That's hard to do. +*/ + +bool +bt_map_open(map, mode) + MAP *map; + int mode; +{ + DB *db; + int i; + int omode; + int fd; + struct stat st; + char buf[MAXNAME]; + + if (tTd(38, 2)) + printf("bt_map_open(%s, %d)\n", map->map_file, mode); + + omode = mode; + if (omode == O_RDWR) + { + omode |= O_CREAT|O_TRUNC; +#if defined(O_EXLOCK) && HASFLOCK + omode |= O_EXLOCK; +# if !OLD_NEWDB + } + else + { + omode |= O_SHLOCK; +# endif +#endif + } + + (void) strcpy(buf, map->map_file); + i = strlen(buf); + if (i < 3 || strcmp(&buf[i - 3], ".db") != 0) + (void) strcat(buf, ".db"); + db = dbopen(buf, omode, DBMMODE, DB_BTREE, NULL); + if (db == NULL) + { +#ifdef MAYBENEXTRELEASE + if (aliaswait(map, ".db", FALSE)) + return TRUE; +#endif + if (!bitset(MF_OPTIONAL, map->map_mflags)) + syserr("Cannot open BTREE database %s", map->map_file); + return FALSE; + } +#if !OLD_NEWDB && HASFLOCK + fd = db->fd(db); +# if !defined(O_EXLOCK) + if (mode == O_RDWR && fd >= 0) + { + if (lockfile(fd, map->map_file, ".db", LOCK_EX)) + map->map_mflags |= MF_LOCKED; + } +# else + if (mode == O_RDONLY && fd >= 0) + (void) lockfile(fd, map->map_file, ".db", LOCK_UN); + else + map->map_mflags |= MF_LOCKED; +# endif +#endif + + /* try to make sure that at least the database header is on disk */ + if (mode == O_RDWR) +#if OLD_NEWDB + (void) db->sync(db); +#else + (void) db->sync(db, 0); + + if (fd >= 0 && fstat(fd, &st) >= 0) + map->map_mtime = st.st_mtime; +#endif + + map->map_db2 = (void *) db; + if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags)) + if (!aliaswait(map, ".db", TRUE)) + return FALSE; + return TRUE; +} + + +/* +** HASH_MAP_INIT -- HASH-style map initialization +*/ + +bool +hash_map_open(map, mode) + MAP *map; + int mode; +{ + DB *db; + int i; + int omode; + int fd; + struct stat st; + char buf[MAXNAME]; + + if (tTd(38, 2)) + printf("hash_map_open(%s, %d)\n", map->map_file, mode); + + omode = mode; + if (omode == O_RDWR) + { + omode |= O_CREAT|O_TRUNC; +#if defined(O_EXLOCK) && HASFLOCK + omode |= O_EXLOCK; +# if !OLD_NEWDB + } + else + { + omode |= O_SHLOCK; +# endif +#endif + } + + (void) strcpy(buf, map->map_file); + i = strlen(buf); + if (i < 3 || strcmp(&buf[i - 3], ".db") != 0) + (void) strcat(buf, ".db"); + db = dbopen(buf, omode, DBMMODE, DB_HASH, NULL); + if (db == NULL) + { +#ifdef MAYBENEXTRELEASE + if (aliaswait(map, ".db", FALSE)) + return TRUE; +#endif + if (!bitset(MF_OPTIONAL, map->map_mflags)) + syserr("Cannot open HASH database %s", map->map_file); + return FALSE; + } +#if !OLD_NEWDB && HASFLOCK + fd = db->fd(db); +# if !defined(O_EXLOCK) + if (mode == O_RDWR && fd >= 0) + { + if (lockfile(fd, map->map_file, ".db", LOCK_EX)) + map->map_mflags |= MF_LOCKED; + } +# else + if (mode == O_RDONLY && fd >= 0) + (void) lockfile(fd, map->map_file, ".db", LOCK_UN); + else + map->map_mflags |= MF_LOCKED; +# endif +#endif + + /* try to make sure that at least the database header is on disk */ + if (mode == O_RDWR) +#if OLD_NEWDB + (void) db->sync(db); +#else + (void) db->sync(db, 0); + + if (fd >= 0 && fstat(fd, &st) >= 0) + map->map_mtime = st.st_mtime; +#endif + + map->map_db2 = (void *) db; + if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags)) + if (!aliaswait(map, ".db", TRUE)) + return FALSE; + return TRUE; +} + + +/* +** DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map +*/ + +char * +db_map_lookup(map, name, av, statp) + MAP *map; + char *name; + char **av; + int *statp; +{ + DBT key, val; + register DB *db = (DB *) map->map_db2; + int st; + int saveerrno; + int fd; + char keybuf[MAXNAME + 1]; + + if (tTd(38, 20)) + printf("db_map_lookup(%s)\n", name); + + key.size = strlen(name); + if (key.size > sizeof keybuf - 1) + key.size = sizeof keybuf - 1; + key.data = keybuf; + bcopy(name, keybuf, key.size + 1); + if (!bitset(MF_NOFOLDCASE, map->map_mflags)) + makelower(keybuf); +#if !OLD_NEWDB + fd = db->fd(db); + if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) + (void) lockfile(db->fd(db), map->map_file, ".db", LOCK_SH); +#endif + st = 1; + if (bitset(MF_TRY0NULL, map->map_mflags)) + { + st = db->get(db, &key, &val, 0); + if (st == 0) + map->map_mflags &= ~MF_TRY1NULL; + } + if (st != 0 && bitset(MF_TRY1NULL, map->map_mflags)) + { + key.size++; + st = db->get(db, &key, &val, 0); + if (st == 0) + map->map_mflags &= ~MF_TRY0NULL; + } + saveerrno = errno; +#if !OLD_NEWDB + if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) + (void) lockfile(fd, map->map_file, ".db", LOCK_UN); +#endif + if (st != 0) + { + errno = saveerrno; + if (st < 0) + syserr("db_map_lookup: get (%s)", name); + return NULL; + } + if (bitset(MF_MATCHONLY, map->map_mflags)) + return map_rewrite(map, name, strlen(name), NULL); + else + return map_rewrite(map, val.data, val.size, av); +} + + +/* +** DB_MAP_STORE -- store a datum in the NEWDB database +*/ + +void +db_map_store(map, lhs, rhs) + register MAP *map; + char *lhs; + char *rhs; +{ + int stat; + DBT key; + DBT data; + register DB *db = map->map_db2; + + if (tTd(38, 20)) + printf("db_map_store(%s, %s)\n", lhs, rhs); + + key.size = strlen(lhs); + key.data = lhs; + + data.size = strlen(rhs); + data.data = rhs; + + if (bitset(MF_INCLNULL, map->map_mflags)) + { + key.size++; + data.size++; + } + + stat = db->put(db, &key, &data, R_NOOVERWRITE); + if (stat > 0) + { + usrerr("050 Warning: duplicate alias name %s", lhs); + stat = db->put(db, &key, &data, 0); + } + if (stat != 0) + syserr("readaliases: db put (%s)", lhs); +} + + +/* +** DB_MAP_CLOSE -- add distinguished entries and close the database +*/ + +void +db_map_close(map) + MAP *map; +{ + register DB *db = map->map_db2; + + if (tTd(38, 9)) + printf("db_map_close(%s, %x)\n", map->map_file, map->map_mflags); + + if (bitset(MF_WRITABLE, map->map_mflags)) + { + /* write out the distinguished alias */ + db_map_store(map, "@", "@"); + } + + if (db->close(db) != 0) + syserr("readaliases: db close failure"); +} + +#endif +/* +** NIS Modules +*/ + +# ifdef NIS + +# ifndef YPERR_BUSY +# define YPERR_BUSY 16 +# endif + +/* +** NIS_MAP_OPEN -- open DBM map +*/ + +bool +nis_map_open(map, mode) + MAP *map; + int mode; +{ + int yperr; + register char *p; + auto char *vp; + auto int vsize; + char *master; + + if (tTd(38, 2)) + printf("nis_map_open(%s)\n", map->map_file); + + if (mode != O_RDONLY) + { + /* issue a pseudo-error message */ +#ifdef ENOSYS + errno = ENOSYS; +#else +# ifdef EFTYPE + errno = EFTYPE; +# else + errno = ENXIO; +# endif +#endif + return FALSE; + } + + p = strchr(map->map_file, '@'); + if (p != NULL) + { + *p++ = '\0'; + if (*p != '\0') + map->map_domain = p; + } + + if (*map->map_file == '\0') + map->map_file = "mail.aliases"; + + if (map->map_domain == NULL) + { + yperr = yp_get_default_domain(&map->map_domain); + if (yperr != 0) + { + if (!bitset(MF_OPTIONAL, map->map_mflags)) + syserr("NIS map %s specified, but NIS not running\n", + map->map_file); + return FALSE; + } + } + + /* check to see if this map actually exists */ + yperr = yp_match(map->map_domain, map->map_file, "@", 1, + &vp, &vsize); + if (tTd(38, 10)) + printf("nis_map_open: yp_match(%s, %s) => %s\n", + map->map_domain, map->map_file, yperr_string(yperr)); + if (yperr == 0 || yperr == YPERR_KEY || yperr == YPERR_BUSY) + return TRUE; + + if (!bitset(MF_OPTIONAL, map->map_mflags)) + syserr("Cannot bind to domain %s: %s", map->map_domain, + yperr_string(yperr)); + + return FALSE; +} + + +/* +** NIS_MAP_LOOKUP -- look up a datum in a NIS map +*/ + +char * +nis_map_lookup(map, name, av, statp) + MAP *map; + char *name; + char **av; + int *statp; +{ + char *vp; + auto int vsize; + int buflen; + int yperr; + char keybuf[MAXNAME + 1]; + + if (tTd(38, 20)) + printf("nis_map_lookup(%s)\n", name); + + buflen = strlen(name); + if (buflen > sizeof keybuf - 1) + buflen = sizeof keybuf - 1; + bcopy(name, keybuf, buflen + 1); + if (!bitset(MF_NOFOLDCASE, map->map_mflags)) + makelower(keybuf); + yperr = YPERR_KEY; + if (bitset(MF_TRY0NULL, map->map_mflags)) + { + yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen, + &vp, &vsize); + if (yperr == 0) + map->map_mflags &= ~MF_TRY1NULL; + } + if (yperr == YPERR_KEY && bitset(MF_TRY1NULL, map->map_mflags)) + { + buflen++; + yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen, + &vp, &vsize); + if (yperr == 0) + map->map_mflags &= ~MF_TRY0NULL; + } + if (yperr != 0) + { + if (yperr != YPERR_KEY && yperr != YPERR_BUSY) + map->map_mflags &= ~(MF_VALID|MF_OPEN); + return NULL; + } + if (bitset(MF_MATCHONLY, map->map_mflags)) + return map_rewrite(map, name, strlen(name), NULL); + else + return map_rewrite(map, vp, vsize, av); +} + + +/* +** NIS_MAP_STORE +*/ + +void +nis_map_store(map, lhs, rhs) + MAP *map; + char *lhs; + char *rhs; +{ + /* nothing */ +} + + +/* +** NIS_MAP_CLOSE +*/ + +void +nis_map_close(map) + MAP *map; +{ + /* nothing */ +} + +#endif /* NIS */ +/* +** STAB (Symbol Table) Modules +*/ + + +/* +** STAB_MAP_LOOKUP -- look up alias in symbol table +*/ + +char * +stab_map_lookup(map, name, av, pstat) + register MAP *map; + char *name; + char **av; + int *pstat; +{ + register STAB *s; + + if (tTd(38, 20)) + printf("stab_lookup(%s)\n", name); + + s = stab(name, ST_ALIAS, ST_FIND); + if (s != NULL) + return (s->s_alias); + return (NULL); +} + + +/* +** STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild) +*/ + +void +stab_map_store(map, lhs, rhs) + register MAP *map; + char *lhs; + char *rhs; +{ + register STAB *s; + + s = stab(lhs, ST_ALIAS, ST_ENTER); + s->s_alias = newstr(rhs); +} + + +/* +** STAB_MAP_OPEN -- initialize (reads data file) +** +** This is a wierd case -- it is only intended as a fallback for +** aliases. For this reason, opens for write (only during a +** "newaliases") always fails, and opens for read open the +** actual underlying text file instead of the database. +*/ + +bool +stab_map_open(map, mode) + register MAP *map; + int mode; +{ + FILE *af; + struct stat st; + + if (tTd(38, 2)) + printf("stab_map_open(%s)\n", map->map_file); + + if (mode != O_RDONLY) + { + errno = ENODEV; + return FALSE; + } + + af = fopen(map->map_file, "r"); + if (af == NULL) + return FALSE; + readaliases(map, af, TRUE); + + if (fstat(fileno(af), &st) >= 0) + map->map_mtime = st.st_mtime; + fclose(af); + + return TRUE; +} + + +/* +** STAB_MAP_CLOSE -- close symbol table. +** +** Since this is in memory, there is nothing to do. +*/ + +void +stab_map_close(map) + MAP *map; +{ + /* ignore it */ +} +/* +** Implicit Modules +** +** Tries several types. For back compatibility of aliases. +*/ + + +/* +** IMPL_MAP_LOOKUP -- lookup in best open database +*/ + +char * +impl_map_lookup(map, name, av, pstat) + MAP *map; + char *name; + char **av; + int *pstat; +{ + if (tTd(38, 20)) + printf("impl_map_lookup(%s)\n", name); + +#ifdef NEWDB + if (bitset(MF_IMPL_HASH, map->map_mflags)) + return db_map_lookup(map, name, av, pstat); +#endif +#ifdef NDBM + if (bitset(MF_IMPL_NDBM, map->map_mflags)) + return ndbm_map_lookup(map, name, av, pstat); +#endif + return stab_map_lookup(map, name, av, pstat); +} + +/* +** IMPL_MAP_STORE -- store in open databases +*/ + +void +impl_map_store(map, lhs, rhs) + MAP *map; + char *lhs; + char *rhs; +{ +#ifdef NEWDB + if (bitset(MF_IMPL_HASH, map->map_mflags)) + db_map_store(map, lhs, rhs); +#endif +#ifdef NDBM + if (bitset(MF_IMPL_NDBM, map->map_mflags)) + ndbm_map_store(map, lhs, rhs); +#endif + stab_map_store(map, lhs, rhs); +} + +/* +** IMPL_MAP_OPEN -- implicit database open +*/ + +bool +impl_map_open(map, mode) + MAP *map; + int mode; +{ + struct stat stb; + + if (tTd(38, 2)) + printf("impl_map_open(%s, %d)\n", map->map_file, mode); + + if (stat(map->map_file, &stb) < 0) + { + /* no alias file at all */ + if (tTd(38, 3)) + printf("no map file\n"); + return FALSE; + } + +#ifdef NEWDB + map->map_mflags |= MF_IMPL_HASH; + if (hash_map_open(map, mode)) + { +#if defined(NDBM) && defined(NIS) + if (mode == O_RDONLY || access("/var/yp/Makefile", R_OK) != 0) +#endif + return TRUE; + } + else + map->map_mflags &= ~MF_IMPL_HASH; +#endif +#ifdef NDBM + map->map_mflags |= MF_IMPL_NDBM; + if (ndbm_map_open(map, mode)) + { + return TRUE; + } + else + map->map_mflags &= ~MF_IMPL_NDBM; +#endif + +#if defined(NEWDB) || defined(NDBM) + if (Verbose) + message("WARNING: cannot open alias database %s", map->map_file); +#else + if (mode != O_RDONLY) + usrerr("Cannot rebuild aliases: no database format defined"); +#endif + + return stab_map_open(map, mode); +} + + +/* +** IMPL_MAP_CLOSE -- close any open database(s) +*/ + +void +impl_map_close(map) + MAP *map; +{ +#ifdef NEWDB + if (bitset(MF_IMPL_HASH, map->map_mflags)) + { + db_map_close(map); + map->map_mflags &= ~MF_IMPL_HASH; + } +#endif + +#ifdef NDBM + if (bitset(MF_IMPL_NDBM, map->map_mflags)) + { + ndbm_map_close(map); + map->map_mflags &= ~MF_IMPL_NDBM; + } +#endif +} +/* +** NULL stubs +*/ + +bool +null_map_open(map, mode) + MAP *map; + int mode; +{ + return TRUE; +} + +void +null_map_close(map) + MAP *map; +{ + return; +} + +void +null_map_store(map, key, val) + MAP *map; + char *key; + char *val; +{ + return; +} |