+ return buf;
+}
+\f/*
+** NDBM modules
+*/
+
+#ifdef NDBM
+
+/*
+** DBM_MAP_OPEN -- DBM-style map open
+*/
+
+bool
+ndbm_map_open(map, mode)
+ MAP *map;
+ int mode;
+{
+ DBM *dbm;
+
+ if (tTd(27, 2))
+ printf("ndbm_map_open(%s, %d)\n", map->map_file, mode);
+
+ /* open the database */
+ dbm = dbm_open(map->map_file, mode, DBMMODE);
+ if (dbm == NULL)
+ {
+ if (!bitset(MF_OPTIONAL, map->map_flags))
+ syserr("Cannot open DBM database %s", map->map_file);
+ return FALSE;
+ }
+ map->map_db1 = (void *) dbm;
+ 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;
+ char keybuf[MAXNAME + 1];
+
+ if (tTd(27, 20))
+ printf("ndbm_map_lookup(%s)\n", name);
+
+ key.dptr = name;
+ key.dsize = strlen(name);
+ if (!bitset(MF_NOFOLDCASE, map->map_flags))
+ {
+ if (key.dsize > sizeof keybuf - 1)
+ key.dsize = sizeof keybuf - 1;
+ bcopy(key.dptr, keybuf, key.dsize + 1);
+ makelower(keybuf);
+ key.dptr = keybuf;
+ }
+ if (bitset(MF_INCLNULL, map->map_flags))
+ key.dsize++;
+ (void) lockfile(dbm_dirfno((DBM *) map->map_db1), map->map_file, LOCK_SH);
+ val = dbm_fetch((DBM *) map->map_db1, key);
+ (void) lockfile(dbm_dirfno((DBM *) map->map_db1), map->map_file, LOCK_UN);
+ if (val.dptr == NULL)
+ return NULL;
+ if (bitset(MF_MATCHONLY, map->map_flags))
+ av = NULL;
+ 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(27, 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_flags))
+ {
+ 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);
+}
+
+
+/*
+** DBM_MAP_REBUILD -- rebuild DBM database
+*/
+
+void
+ndbm_map_rebuild(map, fp, automatic)
+ register MAP *map;
+ FILE *fp;
+ int automatic;
+{
+ register DBM *db;
+ int i;
+ char buf[MAXNAME];
+
+ if (tTd(27, 2))
+ printf("ndbm_map_rebuild(%s)\n", map->map_file);
+
+ db = dbm_open(map->map_file, O_RDWR|O_CREAT|O_TRUNC, DBMMODE);
+ if (db == NULL)
+ {
+ syserr("ndbm_map_rebuild: cannot create %s", buf);
+ return;
+ }
+ map->map_db1 = (void *) db;
+ map->map_flags |= MF_WRITABLE|MF_VALID;
+}
+
+/*
+** NDBM_ACLOSE -- close the database
+*/
+
+void
+ndbm_map_close(map)
+ register MAP *map;
+{
+ if (bitset(MF_WRITABLE, map->map_flags))
+ {
+#ifdef YPCOMPAT
+ char buf[200];
+
+ (void) sprintf(buf, "%010ld", curtime());
+ ndbm_map_store(map, "YP_LAST_MODIFIED", buf);
+
+ (void) myhostname(buf, sizeof buf);
+ ndbm_map_store(map, "YP_MASTER_NAME", buf);
+#endif
+
+ /* write out the distinguished alias */
+ ndbm_map_store(map, "@", "@");
+ }
+ dbm_close((DBM *) map->map_db1);
+}
+
+#endif
+\f/*
+** HASH (NEWDB) Modules
+*/
+
+#ifdef NEWDB
+
+/*
+** BTREE_MAP_PARSE -- BTREE-style map initialization
+*/
+
+bool
+bt_map_open(map, mode)
+ MAP *map;
+ int mode;
+{
+ DB *db;
+ char buf[MAXNAME];
+
+ if (tTd(27, 2))
+ printf("bt_map_open(%s, %d)\n", map->map_file, mode);
+
+ (void) sprintf(buf, "%s.db", map->map_file);
+ db = dbopen(buf, mode, 0644, DB_BTREE, NULL);
+ if (db == NULL)
+ {
+ if (!bitset(MF_OPTIONAL, map->map_flags))
+ syserr("Cannot open BTREE database %s", map->map_file);
+ return FALSE;
+ }
+ map->map_db2 = (void *) db;
+ return TRUE;
+}
+
+
+/*
+** HASH_MAP_INIT -- HASH-style map initialization
+*/
+
+bool
+hash_map_open(map, mode)
+ MAP *map;
+ int mode;
+{
+ DB *db;
+ char buf[MAXNAME];
+
+ if (tTd(27, 2))
+ printf("hash_map_open(%s, %d)\n", map->map_file, mode);
+
+ (void) sprintf(buf, "%s.db", map->map_file);
+ db = dbopen(buf, mode, 0644, DB_HASH, NULL);
+ if (db == NULL)
+ {
+ if (!bitset(MF_OPTIONAL, map->map_flags))
+ syserr("Cannot open HASH database %s", map->map_file);
+ return FALSE;
+ }
+ map->map_db2 = (void *) db;
+ 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;
+ char keybuf[MAXNAME + 1];
+
+ if (tTd(27, 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_flags))
+ makelower(keybuf);
+ if (bitset(MF_INCLNULL, map->map_flags))
+ key.size++;
+ if (((DB *) map->map_db2)->get((DB *) map->map_db2, &key, &val, 0) != 0)
+ return NULL;
+ if (bitset(MF_MATCHONLY, map->map_flags))
+ av = NULL;
+ 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(27, 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_flags))
+ {
+ 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);
+}
+
+
+/*
+** HASH_MAP_REBUILD -- rebuild hash database
+*/
+
+void
+db_map_rebuild(map, fp, automatic, e)
+ register MAP *map;
+ FILE *fp;
+ int automatic;
+ ENVELOPE *e;
+{
+ register DB *db;
+ char buf[MAXNAME];
+
+ if (tTd(27, 2))
+ printf("hash_map_rebuild(%s)\n", map->map_file);
+
+ (void) strcpy(buf, map->map_file);
+ (void) strcat(buf, ".db");
+ db = dbopen(buf, O_RDWR|O_CREAT|O_TRUNC, DBMMODE, DB_HASH, NULL);
+ if (db == NULL)
+ {
+ syserr("hash_map_rebuild: cannot create %s", buf);
+ return;
+ }
+ map->map_db2 = db;
+ map->map_flags |= MF_WRITABLE|MF_VALID;
+}
+
+
+/*
+** 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(27, 9))
+ printf("db_map_close(%s, %x)\n", map->map_file, map->map_flags);
+
+ if (bitset(MF_WRITABLE, map->map_flags))
+ {
+ /* write out the distinguished alias */
+ db_map_store(map, "@", "@");
+ }
+
+ if (db->close(db) != 0)
+ syserr("readaliases: db close failure");
+}
+
+#endif
+\f/*
+** NIS Modules
+*/
+
+# ifdef NIS
+
+/*
+** NIS_MAP_OPEN -- open DBM map
+*/
+
+bool
+nis_map_open(map, mode)
+ MAP *map;
+ int mode;
+{
+ int yperr;
+ char *master;
+
+ if (tTd(27, 2))
+ printf("nis_map_open(%s)\n", map->map_file);
+
+ if (map->map_domain == NULL)
+ yp_get_default_domain(&map->map_domain);
+
+ /* check to see if this map actually exists */
+ yperr = yp_master(map->map_domain, map->map_file, &master);
+ if (yperr == 0)
+ return TRUE;
+ if (!bitset(MF_OPTIONAL, map->map_flags))
+ syserr("Cannot bind to domain %s: %s", map->map_domain,
+ yperr_string(yperr));
+ return FALSE;
+}
+
+bool
+nis_map_open(map, mode)
+ MAP *map;
+ int mode;
+{
+ register char *p;
+ int yperr;
+ auto char *vp;
+ auto int vsize;
+
+ p = strchr(map->map_file, '@');
+ if (p != NULL)
+ {
+ *p++ = '\0';
+ if (*p != '\0')
+ map->map_domain = p;
+ }
+ if (map->map_domain == NULL)
+ yp_get_default_domain(&map->map_domain);
+
+ if (*map->map_file == '\0')
+ map->map_file = "mail.aliases";
+
+ yperr = yp_match(map->map_domain, map->map_file, "@", 1,
+ &vp, &vsize);
+ if (tTd(27, 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;
+ 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;
+ char keybuf[MAXNAME + 1];
+
+ if (tTd(27, 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_flags))
+ makelower(keybuf);
+ if (bitset(MF_INCLNULL, map->map_flags))
+ buflen++;
+ yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen,
+ &vp, &vsize);
+ if (yperr != 0)
+ {
+ if (yperr != YPERR_KEY && yperr != YPERR_BUSY)
+ map->map_flags &= ~MF_VALID;
+ return NULL;
+ }
+ if (bitset(MF_MATCHONLY, map->map_flags))
+ av = NULL;
+ return map_rewrite(map, val.dptr, val.dsize, av);
+}
+
+
+/*
+** NIS_ASTORE
+*/
+
+void
+nis_map_store(map, lhs, rhs)
+ MAP *map;
+ char *lhs;
+ char *rhs;
+{
+ /* nothing */
+}
+
+/*
+** NIS_AREBUILD
+*/
+
+void
+nis_map_rebuild(map, fp, automatic, e)
+ MAP *map;
+ FILE *fp;
+ int automatic;
+ ENVELOPE *e;
+{
+ if (tTd(27, 2))
+ printf("nis_map_rebuild(%s)\n", map->map_file);
+}
+
+
+/*
+** NIS_ACLOSE
+*/
+
+void
+nis_map_close(map)
+ MAP *map;
+{
+ /* nothing */
+}
+
+#endif /* NIS */
+\f/*
+** STAB (Symbol Table) Modules
+*/
+
+
+/*
+** STAB_ALOOKUP -- look up alias in symbol table
+*/
+
+char *
+stab_map_lookup(map, name)
+ register MAP *map;
+ char *name;
+{
+ register STAB *s;
+
+ if (tTd(27, 20))
+ printf("stab_lookup(%s)\n", name);
+
+ s = stab(name, ST_ALIAS, ST_FIND);
+ if (s != NULL)
+ return (s->s_alias);
+ return (NULL);
+}
+
+
+/*
+** STAB_ASTORE -- 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_AINIT -- initialize (reads data file)
+*/
+
+bool
+stab_map_open(map, mode)
+ register MAP *map;
+ int mode;
+{
+ FILE *af;
+
+ if (tTd(27, 2))
+ printf("stab_map_open(%s)\n", map->map_file);
+
+ if (mode != O_RDONLY)
+ return FALSE;
+
+ af = fopen(map->map_file, "r");
+ if (af == NULL)
+ return FALSE;
+ return TRUE;
+}
+
+
+/*
+** STAB_AREBUILD -- rebuild alias file
+*/
+
+void
+stab_map_rebuild(map, fp, automatic, e)
+ MAP *map;
+ FILE *fp;
+ int automatic;
+ ENVELOPE *e;
+{
+ if (tTd(27, 2))
+ printf("stab_map_rebuild(%s)\n", map->map_file);
+
+ map->map_flags |= MF_WRITABLE|MF_VALID;
+}
+
+
+/*
+** STAB_ACLOSE -- close symbol table (???)
+*/
+
+void
+stab_map_close(map)
+ MAP *map;
+{
+ /* ignore it */
+}
+\f/*
+** Implicit Modules
+**
+** Tries several types. For back compatibility of aliases.
+*/
+
+
+/*
+** IMPL_ALOOKUP -- lookup in best open database
+*/
+
+char *
+impl_map_lookup(map, name, av, pstat)
+ MAP *map;
+ char *name;
+ char **av;
+ int *pstat;
+{
+ if (tTd(27, 20))
+ printf("impl_map_lookup(%s)\n", name);
+
+#ifdef NEWDB
+ if (bitset(MF_IMPL_HASH, map->map_flags))
+ return db_map_lookup(map, name, av, pstat);
+#endif
+#ifdef NDBM
+ if (bitset(MF_IMPL_NDBM, map->map_flags))
+ return ndbm_map_lookup(map, name, av, pstat);
+#endif
+ return stab_map_lookup(map, name, av, pstat);
+}
+
+/*
+** IMPL_ASTORE -- 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_flags))
+ db_map_store(map, lhs, rhs);
+#endif
+#ifdef NDBM
+ if (bitset(MF_IMPL_NDBM, map->map_flags))
+ 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(27, 2))
+ printf("impl_map_open(%s)\n", map->map_file);
+
+ if (stat(map->map_file, &stb) < 0)
+ {
+ /* no alias file at all */
+ return FALSE;
+ }
+
+#ifdef NEWDB
+ if (hash_map_open(map, mode))
+ {
+ map->map_flags |= MF_IMPL_HASH;
+ return TRUE;
+ }
+#endif
+#ifdef NDBM
+ if (ndbm_map_open(map, mode))
+ {
+ map->map_flags |= MF_IMPL_NDBM;
+ return TRUE;
+ }
+#endif
+
+ if (Verbose)
+ message("WARNING: cannot open alias database %s", map->map_file);
+
+ if (stab_map_open(map, mode))
+ {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/*
+** IMPL_AREBUILD -- rebuild alias database
+*/
+
+void
+impl_map_rebuild(map, fp, automatic, e)
+ MAP *map;
+ FILE *fp;
+ int automatic;
+ ENVELOPE *e;
+{
+#ifdef NEWDB
+ DB *ndb;
+ char buf[MAXNAME];
+#endif
+
+ if (tTd(27, 2))
+ printf("impl_map_rebuild(%s)\n", map->map_file);
+
+#ifdef NEWDB
+ (void) strcpy(buf, map->map_file);
+ (void) strcat(buf, ".db");
+ ndb = dbopen(buf, O_RDWR|O_CREAT|O_TRUNC, DBMMODE, DB_HASH, NULL);
+ if (ndb == NULL)
+ {
+ syserr("rebuildaliases: cannot create %s", buf);
+ }
+ else
+ {
+ map->map_db2 = ndb;
+ map->map_flags |= MF_IMPL_HASH;
+#if defined(NDBM) && defined(YPCOMPAT)
+ if (access("/var/yp/Makefile", R_OK) != 0)
+#endif
+ goto readem;
+ }
+#endif
+
+#ifdef NDBM
+ map->map_db1 = (void *) dbm_open(map->map_file, O_RDWR|O_CREAT|O_TRUNC, DBMMODE);
+ if (map->map_db1 == NULL)
+ {
+ syserr("rebuildaliases: cannot create %s.{pag,dir}",
+ map->map_file);
+ }
+ else
+ {
+ map->map_flags |= MF_IMPL_NDBM;
+ }
+#endif
+
+ if (!bitset(MF_IMPL_HASH|MF_IMPL_NDBM, map->map_flags))
+ return;
+
+ readem:
+ map->map_flags |= MF_WRITABLE|MF_VALID;
+}
+
+
+/*
+** IMPL_ACLOSE -- close any open database(s)
+*/
+
+void
+impl_map_close(map, e)
+ MAP *map;
+ ENVELOPE *e;
+{
+#ifdef NEWDB
+ if (bitset(MF_IMPL_HASH, map->map_flags))
+ db_map_close(map, e);
+#endif
+
+#ifdef NDBM
+ if (bitset(MF_IMPL_NDBM, map->map_flags))
+ ndbm_map_close(map, e);
+#endif
+}
+\f/*
+** SETUPALIASES -- set up aliases classes
+*/
+
+extern bool host_map_init __P((MAP *, char *));
+extern char *host_map_lookup __P((MAP *, char *, char **, int *));
+
+extern bool dequote_init __P((MAP *, char *));
+extern char *dequote_map __P((MAP *, char *, char **, int *));
+
+#if 0
+extern bool udb_map_parse __P((MAP *, char *));
+extern char *udb_map_lookup __P((MAP *, char *, char **, int *));
+#endif
+
+static MAPCLASS MapClasses[] =
+{
+#ifdef NEWDB
+ {
+ "hash", ".db", map_parseargs,
+ db_map_lookup, db_map_store,
+ db_map_rebuild, hash_map_open, db_map_close,
+ },
+
+ {
+ "btree", ".db", map_parseargs,
+ db_map_lookup, db_map_store,
+ db_map_rebuild, bt_map_open, db_map_close,
+ },
+#endif
+
+#ifdef NDBM
+ {
+ "dbm", ".dir", map_parseargs,
+ ndbm_map_lookup, ndbm_map_store,
+ ndbm_map_rebuild, ndbm_map_open, ndbm_map_close,
+ },
+#endif
+
+#ifdef NIS
+ {
+ "nis", NULL, map_parseargs,
+ nis_map_lookup, NULL,
+ NULL, nis_map_open, nis_map_close,
+ },
+#endif
+
+ {
+ "stab", NULL, map_parseargs,
+ stab_map_lookup, stab_map_store,
+ NULL, stab_map_open, stab_map_close,
+ },
+
+ {
+ "implicit", NULL, map_parseargs,
+ impl_map_lookup, impl_map_store,
+ impl_map_rebuild, impl_map_open, impl_map_close,
+ },
+
+ /* host DNS lookup */
+ {
+ "host", NULL, host_map_init,
+ host_map_lookup, NULL,
+ NULL, NULL, NULL,
+ },
+
+ /* dequote map */
+ {
+ "dequote", NULL, dequote_init,
+ dequote_map, NULL,
+ NULL, NULL, NULL,
+ },
+
+#if 0
+# ifdef USERDB
+ /* user database */
+ {
+ "udb", ".db", udb_map_parse,
+ udb_map_lookup, NULL,
+ NULL, NULL, NULL,
+ },
+# endif
+#endif
+
+ {
+ NULL
+ }
+};
+
+setupmaps()
+{
+ register MAPCLASS *mc;
+ register STAB *s;
+
+ for (mc = MapClasses; mc->map_cname != NULL; mc++)
+ {
+ s = stab(mc->map_cname, ST_MAPCLASS, ST_ENTER);
+ s->s_mapclass = mc;
+ }