* Copyright (c) 1992 Eric P. Allman.
* Copyright (c) 1992 Regents of the University of California.
* %sccs.include.redist.c%
static char sccsid
[] = "@(#)map.c 6.14 (Berkeley) %G%";
#include <rpcsvc/ypclnt.h>
** 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
** char *map_lookup(MAP *map, char buf[], int bufsize,
** char **args, int *pstat)
** Look up the key given in buf 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.
** void map_store(MAP *map, char *key, char *value)
** Store the key:value pair in the map.
** void map_rebuild(MAP *map, FILE *fp, int automatic)
** Rebuild the map. If automatic is set, this is an
** bool map_open(MAP *map, int mode)
** Open the map for the indicated mode. Return TRUE if it
** was opened successfully, FALSE otherwise.
** void map_close(MAP *map)
** MAP_PARSEARGS -- parse config line arguments for database lookup
** This is a generic version of the map_parse method.
** map -- the map being initialized.
** ap -- a pointer to the args on the config line.
** TRUE -- if everything parsed OK.
** null terminates the filename; stores it in map
while (isascii(*p
) && isspace(*p
))
map
->map_flags
|= MF_INCLNULL
;
map
->map_flags
|= MF_OPTIONAL
;
map
->map_flags
|= MF_NOFOLDCASE
;
map
->map_flags
|= MF_MATCHONLY
;
while (*p
!= '\0' && !(isascii(*p
) && isspace(*p
)))
if (map
->map_app
!= NULL
)
map
->map_app
= newstr(map
->map_app
);
if (map
->map_domain
!= NULL
)
map
->map_domain
= newstr(map
->map_domain
);
while (*p
!= '\0' && !(isascii(*p
) && isspace(*p
)))
map
->map_file
= newstr(map
->map_file
);
while (*p
!= '\0' && isascii(*p
) && isspace(*p
))
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
);
** 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.
** 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.
** Pointer to rewritten result.
map_rewrite(map
, s
, slen
, av
)
printf("map_rewrite(%.*s), av =\n", slen
, s
);
for (avp
= av
; *avp
!= NULL
; avp
++)
/* count expected size of output (can safely overestimate) */
for (i
= slen
; --i
>= 0 && (c
= *bp
++) != 0; )
if (!(isascii(c
) && isdigit(c
)))
for (avp
= av
; --c
>= 0 && *avp
!= NULL
; avp
++)
if (map
->map_app
!= NULL
)
len
+= strlen(map
->map_app
);
/* need to malloc additional space */
while (--slen
>= 0 && (c
= *s
++) != '\0')
if (--slen
< 0 || (c
= *s
++) == '\0')
if (!(isascii(c
) && isdigit(c
)))
for (avp
= av
; --c
>= 0 && *avp
!= NULL
; avp
++)
/* transliterate argument into output string */
for (ap
= *avp
; (c
= *ap
++) != '\0'; )
if (map
->map_app
!= NULL
)
strcpy(bp
, map
->map_app
);
printf("map_rewrite => %s\n", buf
);
** DBM_MAP_OPEN -- DBM-style map open
printf("ndbm_map_open(%s, %d)\n", map
->map_file
, mode
);
dbm
= dbm_open(map
->map_file
, mode
, DBMMODE
);
if (!bitset(MF_OPTIONAL
, map
->map_flags
))
syserr("Cannot open DBM database %s", map
->map_file
);
map
->map_db1
= (void *) dbm
;
** DBM_MAP_LOOKUP -- look up a datum in a DBM-type map
ndbm_map_lookup(map
, name
, av
, statp
)
char keybuf
[MAXNAME
+ 1];
printf("ndbm_map_lookup(%s)\n", 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);
if (bitset(MF_INCLNULL
, map
->map_flags
))
(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 (bitset(MF_MATCHONLY
, map
->map_flags
))
return map_rewrite(map
, val
.dptr
, val
.dsize
, av
);
** DBM_MAP_STORE -- store a datum in the database
ndbm_map_store(map
, lhs
, rhs
)
printf("ndbm_map_store(%s, %s)\n", lhs
, rhs
);
data
.dsize
= strlen(rhs
);
if (bitset(MF_INCLNULL
, map
->map_flags
))
stat
= dbm_store((DBM
*) map
->map_db1
, key
, data
, DBM_INSERT
);
usrerr("050 Warning: duplicate alias name %s", lhs
);
stat
= dbm_store((DBM
*) map
->map_db1
, key
, data
, DBM_REPLACE
);
syserr("readaliases: dbm put (%s)", lhs
);
** DBM_MAP_REBUILD -- rebuild DBM database
ndbm_map_rebuild(map
, fp
, automatic
)
printf("ndbm_map_rebuild(%s)\n", map
->map_file
);
db
= dbm_open(map
->map_file
, O_RDWR
|O_CREAT
|O_TRUNC
, DBMMODE
);
syserr("ndbm_map_rebuild: cannot create %s", buf
);
map
->map_db1
= (void *) db
;
map
->map_flags
|= MF_WRITABLE
|MF_VALID
;
** NDBM_ACLOSE -- close the database
if (bitset(MF_WRITABLE
, map
->map_flags
))
(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
);
/* write out the distinguished alias */
ndbm_map_store(map
, "@", "@");
dbm_close((DBM
*) map
->map_db1
);
** BTREE_MAP_PARSE -- BTREE-style map initialization
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 (!bitset(MF_OPTIONAL
, map
->map_flags
))
syserr("Cannot open BTREE database %s", map
->map_file
);
map
->map_db2
= (void *) db
;
** HASH_MAP_INIT -- HASH-style map initialization
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 (!bitset(MF_OPTIONAL
, map
->map_flags
))
syserr("Cannot open HASH database %s", map
->map_file
);
map
->map_db2
= (void *) db
;
** DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map
db_map_lookup(map
, name
, av
, statp
)
char keybuf
[MAXNAME
+ 1];
printf("db_map_lookup(%s)\n", name
);
if (key
.size
> sizeof keybuf
- 1)
key
.size
= sizeof keybuf
- 1;
bcopy(name
, keybuf
, key
.size
+ 1);
if (!bitset(MF_NOFOLDCASE
, map
->map_flags
))
if (bitset(MF_INCLNULL
, map
->map_flags
))
if (((DB
*) map
->map_db2
)->get((DB
*) map
->map_db2
, &key
, &val
, 0) != 0)
if (bitset(MF_MATCHONLY
, map
->map_flags
))
return map_rewrite(map
, val
.data
, val
.size
, av
);
** DB_MAP_STORE -- store a datum in the NEWDB database
db_map_store(map
, lhs
, rhs
)
register DB
*db
= map
->map_db2
;
printf("db_map_store(%s, %s)\n", lhs
, rhs
);
if (bitset(MF_INCLNULL
, map
->map_flags
))
stat
= db
->put(db
, &key
, &data
, R_NOOVERWRITE
);
usrerr("050 Warning: duplicate alias name %s", lhs
);
stat
= db
->put(db
, &key
, &data
, 0);
syserr("readaliases: db put (%s)", lhs
);
** HASH_MAP_REBUILD -- rebuild hash database
db_map_rebuild(map
, fp
, automatic
, e
)
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
);
syserr("hash_map_rebuild: cannot create %s", buf
);
map
->map_flags
|= MF_WRITABLE
|MF_VALID
;
** DB_MAP_CLOSE -- add distinguished entries and close the database
register DB
*db
= map
->map_db2
;
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
, "@", "@");
syserr("readaliases: db close failure");
** NIS_MAP_OPEN -- open DBM map
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 (!bitset(MF_OPTIONAL
, map
->map_flags
))
syserr("Cannot bind to domain %s: %s", map
->map_domain
,
p
= strchr(map
->map_file
, '@');
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,
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
)
** NIS_MAP_LOOKUP -- look up a datum in a NIS map
nis_map_lookup(map
, name
, av
, statp
)
char keybuf
[MAXNAME
+ 1];
printf("nis_map_lookup(%s)\n", name
);
if (buflen
> sizeof keybuf
- 1)
buflen
= sizeof keybuf
- 1;
bcopy(name
, keybuf
, buflen
+ 1);
if (!bitset(MF_NOFOLDCASE
, map
->map_flags
))
if (bitset(MF_INCLNULL
, map
->map_flags
))
yperr
= yp_match(map
->map_domain
, map
->map_file
, keybuf
, buflen
,
if (yperr
!= YPERR_KEY
&& yperr
!= YPERR_BUSY
)
map
->map_flags
&= ~MF_VALID
;
if (bitset(MF_MATCHONLY
, map
->map_flags
))
return map_rewrite(map
, val
.dptr
, val
.dsize
, av
);
nis_map_store(map
, lhs
, rhs
)
nis_map_rebuild(map
, fp
, automatic
, e
)
printf("nis_map_rebuild(%s)\n", map
->map_file
);
** STAB (Symbol Table) Modules
** STAB_ALOOKUP -- look up alias in symbol table
stab_map_lookup(map
, name
)
printf("stab_lookup(%s)\n", name
);
s
= stab(name
, ST_ALIAS
, ST_FIND
);
** STAB_ASTORE -- store in symtab (actually using during init, not rebuild)
stab_map_store(map
, lhs
, rhs
)
s
= stab(lhs
, ST_ALIAS
, ST_ENTER
);
s
->s_alias
= newstr(rhs
);
** STAB_AINIT -- initialize (reads data file)
printf("stab_map_open(%s)\n", map
->map_file
);
af
= fopen(map
->map_file
, "r");
** STAB_AREBUILD -- rebuild alias file
stab_map_rebuild(map
, fp
, automatic
, e
)
printf("stab_map_rebuild(%s)\n", map
->map_file
);
map
->map_flags
|= MF_WRITABLE
|MF_VALID
;
** STAB_ACLOSE -- close symbol table (???)
** Tries several types. For back compatibility of aliases.
** IMPL_ALOOKUP -- lookup in best open database
impl_map_lookup(map
, name
, av
, pstat
)
printf("impl_map_lookup(%s)\n", name
);
if (bitset(MF_IMPL_HASH
, map
->map_flags
))
return db_map_lookup(map
, name
, av
, pstat
);
if (bitset(MF_IMPL_NDBM
, map
->map_flags
))
return ndbm_map_lookup(map
, name
, av
, pstat
);
return stab_map_lookup(map
, name
, av
, pstat
);
** IMPL_ASTORE -- store in open databases
impl_map_store(map
, lhs
, rhs
)
if (bitset(MF_IMPL_HASH
, map
->map_flags
))
db_map_store(map
, lhs
, rhs
);
if (bitset(MF_IMPL_NDBM
, map
->map_flags
))
ndbm_map_store(map
, lhs
, rhs
);
stab_map_store(map
, lhs
, rhs
);
** IMPL_MAP_OPEN -- implicit database open
printf("impl_map_open(%s)\n", map
->map_file
);
if (stat(map
->map_file
, &stb
) < 0)
/* no alias file at all */
if (hash_map_open(map
, mode
))
map
->map_flags
|= MF_IMPL_HASH
;
if (ndbm_map_open(map
, mode
))
map
->map_flags
|= MF_IMPL_NDBM
;
message("WARNING: cannot open alias database %s", map
->map_file
);
if (stab_map_open(map
, mode
))
** IMPL_AREBUILD -- rebuild alias database
impl_map_rebuild(map
, fp
, automatic
, e
)
printf("impl_map_rebuild(%s)\n", map
->map_file
);
(void) strcpy(buf
, map
->map_file
);
(void) strcat(buf
, ".db");
ndb
= dbopen(buf
, O_RDWR
|O_CREAT
|O_TRUNC
, DBMMODE
, DB_HASH
, NULL
);
syserr("rebuildaliases: cannot create %s", buf
);
map
->map_flags
|= MF_IMPL_HASH
;
#if defined(NDBM) && defined(YPCOMPAT)
if (access("/var/yp/Makefile", R_OK
) != 0)
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_flags
|= MF_IMPL_NDBM
;
if (!bitset(MF_IMPL_HASH
|MF_IMPL_NDBM
, map
->map_flags
))
map
->map_flags
|= MF_WRITABLE
|MF_VALID
;
** IMPL_ACLOSE -- close any open database(s)
if (bitset(MF_IMPL_HASH
, map
->map_flags
))
if (bitset(MF_IMPL_NDBM
, map
->map_flags
))
** 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 *));
extern bool udb_map_parse
__P((MAP
*, char *));
extern char *udb_map_lookup
__P((MAP
*, char *, char **, int *));
static MAPCLASS MapClasses
[] =
"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
,
"dbm", ".dir", map_parseargs
,
ndbm_map_lookup
, ndbm_map_store
,
ndbm_map_rebuild
, ndbm_map_open
, ndbm_map_close
,
"nis", NULL
, map_parseargs
,
NULL
, nis_map_open
, nis_map_close
,
"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", NULL
, host_map_init
,
"dequote", NULL
, dequote_init
,
"udb", ".db", udb_map_parse
,
for (mc
= MapClasses
; mc
->map_cname
!= NULL
; mc
++)
s
= stab(mc
->map_cname
, ST_MAPCLASS
, ST_ENTER
);