BSD 4_4 release
[unix-history] / usr / src / usr.sbin / sendmail / src / map.c
index 610fcde..ef53f23 100644 (file)
@@ -1,13 +1,39 @@
 /*
  * Copyright (c) 1992 Eric P. Allman.
 /*
  * Copyright (c) 1992 Eric P. Allman.
- * Copyright (c) 1992 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  *
- * %sccs.include.redist.c%
+ * 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
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)map.c      6.20 (Berkeley) %G%";
+static char sccsid[] = "@(#)map.c      8.1 (Berkeley) 6/7/93";
 #endif /* not lint */
 
 #include "sendmail.h"
 #endif /* not lint */
 
 #include "sendmail.h"
@@ -161,6 +187,14 @@ map_parseargs(map, ap)
 **             none.
 */
 
 **             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;
 char *
 map_rewrite(map, s, slen, av)
        register MAP *map;
@@ -172,12 +206,11 @@ map_rewrite(map, s, slen, av)
        register char c;
        char **avp;
        register char *ap;
        register char c;
        char **avp;
        register char *ap;
+       register struct rwbuf *rwb;
        int i;
        int len;
        int i;
        int len;
-       static int buflen = -1;
-       static char *buf = NULL;
 
 
-       if (tTd(23, 1))
+       if (tTd(39, 1))
        {
                printf("map_rewrite(%.*s), av =", slen, s);
                if (av == NULL)
        {
                printf("map_rewrite(%.*s), av =", slen, s);
                if (av == NULL)
@@ -190,6 +223,10 @@ map_rewrite(map, s, slen, av)
                printf("\n");
        }
 
                printf("\n");
        }
 
+       rwb = RwBufs;
+       if (av == NULL)
+               rwb++;
+
        /* count expected size of output (can safely overestimate) */
        i = len = slen;
        if (av != NULL)
        /* count expected size of output (can safely overestimate) */
        i = len = slen;
        if (av != NULL)
@@ -214,16 +251,16 @@ map_rewrite(map, s, slen, av)
        }
        if (map->map_app != NULL)
                len += strlen(map->map_app);
        }
        if (map->map_app != NULL)
                len += strlen(map->map_app);
-       if (buflen < ++len)
+       if (rwb->rwb_len < ++len)
        {
                /* need to malloc additional space */
        {
                /* need to malloc additional space */
-               buflen = len;
-               if (buf != NULL)
-                       free(buf);
-               buf = xalloc(buflen);
+               rwb->rwb_len = len;
+               if (rwb->rwb_buf != NULL)
+                       free(rwb->rwb_buf);
+               rwb->rwb_buf = xalloc(rwb->rwb_len);
        }
 
        }
 
-       bp = buf;
+       bp = rwb->rwb_buf;
        if (av == NULL)
        {
                bcopy(s, bp, slen);
        if (av == NULL)
        {
                bcopy(s, bp, slen);
@@ -263,9 +300,84 @@ map_rewrite(map, s, slen, av)
                strcpy(bp, map->map_app);
        else
                *bp = '\0';
                strcpy(bp, map->map_app);
        else
                *bp = '\0';
-       if (tTd(23, 1))
-               printf("map_rewrite => %s\n", buf);
-       return buf;
+       if (tTd(39, 1))
+               printf("map_rewrite => %s\n", rwb->rwb_buf);
+       return rwb->rwb_buf;
+}
+\f/*
+**  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();
+
+       CurEnv = e;
+       stabapply(map_init, rebuild);
+}
+
+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)\n",
+                       map->map_class->map_cname, map->map_file);
+
+       /* 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)
+       {
+               if (bitset(MF_ALIAS, map->map_mflags) &&
+                   bitset(MCF_REBUILDABLE, map->map_class->map_cflags))
+                       rebuildaliases(map, FALSE);
+       }
+       else
+       {
+               if (map->map_class->map_open(map, O_RDONLY))
+               {
+                       if (tTd(38, 4))
+                               printf("%s:%s: valid\n",
+                                       map->map_class->map_cname,
+                                       map->map_file);
+                       map->map_mflags |= MF_OPEN;
+               }
+               else if (tTd(38, 4))
+                       printf("%s:%s: invalid: %s\n",
+                               map->map_class->map_cname,
+                               map->map_file,
+                               errstring(errno));
+       }
 }
 \f/*
 **  NDBM modules
 }
 \f/*
 **  NDBM modules
@@ -284,7 +396,7 @@ ndbm_map_open(map, mode)
 {
        DBM *dbm;
 
 {
        DBM *dbm;
 
-       if (tTd(27, 2))
+       if (tTd(38, 2))
                printf("ndbm_map_open(%s, %d)\n", map->map_file, mode);
 
        if (mode == O_RDWR)
                printf("ndbm_map_open(%s, %d)\n", map->map_file, mode);
 
        if (mode == O_RDWR)
@@ -300,7 +412,7 @@ ndbm_map_open(map, mode)
        }
        map->map_db1 = (void *) dbm;
        if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags))
        }
        map->map_db1 = (void *) dbm;
        if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags))
-               aliaswait(map, ".dir");
+               aliaswait(map, ".pag");
        return TRUE;
 }
 
        return TRUE;
 }
 
@@ -319,7 +431,7 @@ ndbm_map_lookup(map, name, av, statp)
        datum key, val;
        char keybuf[MAXNAME + 1];
 
        datum key, val;
        char keybuf[MAXNAME + 1];
 
-       if (tTd(27, 20))
+       if (tTd(38, 20))
                printf("ndbm_map_lookup(%s)\n", name);
 
        key.dptr = name;
                printf("ndbm_map_lookup(%s)\n", name);
 
        key.dptr = name;
@@ -359,7 +471,7 @@ ndbm_map_store(map, lhs, rhs)
        datum data;
        int stat;
 
        datum data;
        int stat;
 
-       if (tTd(27, 12))
+       if (tTd(38, 12))
                printf("ndbm_map_store(%s, %s)\n", lhs, rhs);
 
        key.dsize = strlen(lhs);
                printf("ndbm_map_store(%s, %s)\n", lhs, rhs);
 
        key.dsize = strlen(lhs);
@@ -413,13 +525,21 @@ ndbm_map_close(map)
 
 #endif
 \f/*
 
 #endif
 \f/*
-**  HASH (NEWDB) Modules
+**  NEWDB (Hash and BTree) Modules
 */
 
 #ifdef NEWDB
 
 /*
 */
 
 #ifdef NEWDB
 
 /*
-**  BTREE_MAP_PARSE -- BTREE-style map initialization
+**  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
 */
 
 bool
@@ -429,25 +549,52 @@ bt_map_open(map, mode)
 {
        DB *db;
        int i;
 {
        DB *db;
        int i;
+       int omode;
        char buf[MAXNAME];
 
        char buf[MAXNAME];
 
-       if (tTd(27, 2))
+       if (tTd(38, 2))
                printf("bt_map_open(%s, %d)\n", map->map_file, mode);
 
                printf("bt_map_open(%s, %d)\n", map->map_file, mode);
 
-       if (mode == O_RDWR)
-               mode |= O_CREAT|O_TRUNC;
+       omode = mode;
+       if (omode == O_RDWR)
+       {
+               omode |= O_CREAT|O_TRUNC;
+#if defined(O_EXLOCK) && !defined(LOCKF)
+               omode |= O_EXLOCK;
+# if !defined(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");
 
        (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, mode, DBMMODE, DB_BTREE, NULL);
+       db = dbopen(buf, omode, DBMMODE, DB_BTREE, NULL);
        if (db == NULL)
        {
                if (!bitset(MF_OPTIONAL, map->map_mflags))
                        syserr("Cannot open BTREE database %s", map->map_file);
                return FALSE;
        }
        if (db == NULL)
        {
                if (!bitset(MF_OPTIONAL, map->map_mflags))
                        syserr("Cannot open BTREE database %s", map->map_file);
                return FALSE;
        }
+#if !defined(OLD_NEWDB) && !defined(LOCKF)
+# if !defined(O_EXLOCK)
+       if (mode == O_RDWR)
+               (void) lockfile(db->fd(db), map->map_file, LOCK_EX);
+# else
+       if (mode == O_RDONLY)
+               (void) lockfile(db->fd(db), map->map_file, LOCK_UN);
+# endif
+#endif
+
+       /* try to make sure that at least the database header is on disk */
+       if (mode == O_RDWR)
+               (void) db->sync(db, 0);
+
        map->map_db2 = (void *) db;
        if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags))
                aliaswait(map, ".db");
        map->map_db2 = (void *) db;
        if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags))
                aliaswait(map, ".db");
@@ -466,25 +613,52 @@ hash_map_open(map, mode)
 {
        DB *db;
        int i;
 {
        DB *db;
        int i;
+       int omode;
        char buf[MAXNAME];
 
        char buf[MAXNAME];
 
-       if (tTd(27, 2))
+       if (tTd(38, 2))
                printf("hash_map_open(%s, %d)\n", map->map_file, mode);
 
                printf("hash_map_open(%s, %d)\n", map->map_file, mode);
 
-       if (mode == O_RDWR)
-               mode |= O_CREAT|O_TRUNC;
+       omode = mode;
+       if (omode == O_RDWR)
+       {
+               omode |= O_CREAT|O_TRUNC;
+#if defined(O_EXLOCK) && !defined(LOCKF)
+               omode |= O_EXLOCK;
+# if !defined(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");
 
        (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, mode, DBMMODE, DB_HASH, NULL);
+       db = dbopen(buf, omode, DBMMODE, DB_HASH, NULL);
        if (db == NULL)
        {
                if (!bitset(MF_OPTIONAL, map->map_mflags))
                        syserr("Cannot open HASH database %s", map->map_file);
                return FALSE;
        }
        if (db == NULL)
        {
                if (!bitset(MF_OPTIONAL, map->map_mflags))
                        syserr("Cannot open HASH database %s", map->map_file);
                return FALSE;
        }
+#if !defined(OLD_NEWDB) && !defined(LOCKF)
+# if !defined(O_EXLOCK)
+       if (mode == O_RDWR)
+               (void) lockfile(db->fd(db), map->map_file, LOCK_EX);
+# else
+       if (mode == O_RDONLY)
+               (void) lockfile(db->fd(db), map->map_file, LOCK_UN);
+# endif
+#endif
+
+       /* try to make sure that at least the database header is on disk */
+       if (mode == O_RDWR)
+               (void) db->sync(db, 0);
+
        map->map_db2 = (void *) db;
        if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags))
                aliaswait(map, ".db");
        map->map_db2 = (void *) db;
        if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags))
                aliaswait(map, ".db");
@@ -509,7 +683,7 @@ db_map_lookup(map, name, av, statp)
        int saveerrno;
        char keybuf[MAXNAME + 1];
 
        int saveerrno;
        char keybuf[MAXNAME + 1];
 
-       if (tTd(27, 20))
+       if (tTd(38, 20))
                printf("db_map_lookup(%s)\n", name);
 
        key.size = strlen(name);
                printf("db_map_lookup(%s)\n", name);
 
        key.size = strlen(name);
@@ -557,7 +731,7 @@ db_map_store(map, lhs, rhs)
        DBT data;
        register DB *db = map->map_db2;
 
        DBT data;
        register DB *db = map->map_db2;
 
-       if (tTd(27, 20))
+       if (tTd(38, 20))
                printf("db_map_store(%s, %s)\n", lhs, rhs);
 
        key.size = strlen(lhs);
                printf("db_map_store(%s, %s)\n", lhs, rhs);
 
        key.size = strlen(lhs);
@@ -593,7 +767,7 @@ db_map_close(map)
 {
        register DB *db = map->map_db2;
 
 {
        register DB *db = map->map_db2;
 
-       if (tTd(27, 9))
+       if (tTd(38, 9))
                printf("db_map_close(%s, %x)\n", map->map_file, map->map_mflags);
 
        if (bitset(MF_WRITABLE, map->map_mflags))
                printf("db_map_close(%s, %x)\n", map->map_file, map->map_mflags);
 
        if (bitset(MF_WRITABLE, map->map_mflags))
@@ -628,7 +802,7 @@ nis_map_open(map, mode)
        auto int vsize;
        char *master;
 
        auto int vsize;
        char *master;
 
-       if (tTd(27, 2))
+       if (tTd(38, 2))
                printf("nis_map_open(%s)\n", map->map_file);
 
        if (mode != O_RDONLY)
                printf("nis_map_open(%s)\n", map->map_file);
 
        if (mode != O_RDONLY)
@@ -654,7 +828,7 @@ nis_map_open(map, mode)
        /* check to see if this map actually exists */
        yperr = yp_match(map->map_domain, map->map_file, "@", 1,
                        &vp, &vsize);
        /* check to see if this map actually exists */
        yperr = yp_match(map->map_domain, map->map_file, "@", 1,
                        &vp, &vsize);
-       if (tTd(27, 10))
+       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)
                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)
@@ -685,7 +859,7 @@ nis_map_lookup(map, name, av, statp)
        int yperr;
        char keybuf[MAXNAME + 1];
 
        int yperr;
        char keybuf[MAXNAME + 1];
 
-       if (tTd(27, 20))
+       if (tTd(38, 20))
                printf("nis_map_lookup(%s)\n", name);
 
        buflen = strlen(name);
                printf("nis_map_lookup(%s)\n", name);
 
        buflen = strlen(name);
@@ -746,13 +920,15 @@ nis_map_close(map)
 */
 
 char *
 */
 
 char *
-stab_map_lookup(map, name)
+stab_map_lookup(map, name, av, pstat)
        register MAP *map;
        char *name;
        register MAP *map;
        char *name;
+       char **av;
+       int *pstat;
 {
        register STAB *s;
 
 {
        register STAB *s;
 
-       if (tTd(27, 20))
+       if (tTd(38, 20))
                printf("stab_lookup(%s)\n", name);
 
        s = stab(name, ST_ALIAS, ST_FIND);
                printf("stab_lookup(%s)\n", name);
 
        s = stab(name, ST_ALIAS, ST_FIND);
@@ -793,9 +969,7 @@ stab_map_open(map, mode)
        register MAP *map;
        int mode;
 {
        register MAP *map;
        int mode;
 {
-       FILE *af;
-
-       if (tTd(27, 2))
+       if (tTd(38, 2))
                printf("stab_map_open(%s)\n", map->map_file);
 
        if (mode != O_RDONLY)
                printf("stab_map_open(%s)\n", map->map_file);
 
        if (mode != O_RDONLY)
@@ -836,7 +1010,7 @@ impl_map_lookup(map, name, av, pstat)
        char **av;
        int *pstat;
 {
        char **av;
        int *pstat;
 {
-       if (tTd(27, 20))
+       if (tTd(38, 20))
                printf("impl_map_lookup(%s)\n", name);
 
 #ifdef NEWDB
                printf("impl_map_lookup(%s)\n", name);
 
 #ifdef NEWDB
@@ -882,7 +1056,7 @@ impl_map_open(map, mode)
 {
        struct stat stb;
 
 {
        struct stat stb;
 
-       if (tTd(27, 2))
+       if (tTd(38, 2))
                printf("impl_map_open(%s)\n", map->map_file);
 
        if (stat(map->map_file, &stb) < 0)
                printf("impl_map_open(%s)\n", map->map_file);
 
        if (stat(map->map_file, &stb) < 0)
@@ -896,7 +1070,7 @@ impl_map_open(map, mode)
        if (hash_map_open(map, mode))
        {
 #if defined(NDBM) && defined(YPCOMPAT)
        if (hash_map_open(map, mode))
        {
 #if defined(NDBM) && defined(YPCOMPAT)
-               if (mode == O_RDONLY || access("/var/yp/Makefile", R_OK) == 0)
+               if (mode == O_RDONLY || access("/var/yp/Makefile", R_OK) != 0)
 #endif
                        return TRUE;
        }
 #endif
                        return TRUE;
        }