* 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.20 (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 *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)
** 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_mflags
|= MF_INCLNULL
;
map
->map_mflags
|= MF_OPTIONAL
;
map
->map_mflags
|= MF_NOFOLDCASE
;
map
->map_mflags
|= MF_MATCHONLY
;
while (*p
!= '\0' && !(isascii(*p
) && isspace(*p
)))
if (map
->map_app
!= NULL
)
map
->map_app
= newstr(map
->map_app
);
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 =", 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_mflags
))
syserr("Cannot open DBM database %s", map
->map_file
);
map
->map_db1
= (void *) dbm
;
if (mode
== O_RDONLY
&& bitset(MF_ALIAS
, map
->map_mflags
))
** 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_mflags
))
if (key
.dsize
> sizeof keybuf
- 1)
key
.dsize
= sizeof keybuf
- 1;
bcopy(key
.dptr
, keybuf
, key
.dsize
+ 1);
if (bitset(MF_INCLNULL
, map
->map_mflags
))
(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_mflags
))
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_mflags
))
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
);
** NDBM_MAP_CLOSE -- close the database
if (bitset(MF_WRITABLE
, map
->map_mflags
))
(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) strcpy(buf
, map
->map_file
);
if (i
< 3 || strcmp(&buf
[i
- 3], ".db") != 0)
(void) strcat(buf
, ".db");
db
= dbopen(buf
, mode
, DBMMODE
, DB_BTREE
, NULL
);
if (!bitset(MF_OPTIONAL
, map
->map_mflags
))
syserr("Cannot open BTREE database %s", map
->map_file
);
map
->map_db2
= (void *) db
;
if (mode
== O_RDONLY
&& bitset(MF_ALIAS
, map
->map_mflags
))
** HASH_MAP_INIT -- HASH-style map initialization
printf("hash_map_open(%s, %d)\n", map
->map_file
, mode
);
(void) strcpy(buf
, map
->map_file
);
if (i
< 3 || strcmp(&buf
[i
- 3], ".db") != 0)
(void) strcat(buf
, ".db");
db
= dbopen(buf
, mode
, DBMMODE
, DB_HASH
, NULL
);
if (!bitset(MF_OPTIONAL
, map
->map_mflags
))
syserr("Cannot open HASH database %s", map
->map_file
);
map
->map_db2
= (void *) db
;
if (mode
== O_RDONLY
&& bitset(MF_ALIAS
, map
->map_mflags
))
** DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map
db_map_lookup(map
, name
, av
, statp
)
register DB
*db
= (DB
*) map
->map_db2
;
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_mflags
))
if (bitset(MF_INCLNULL
, map
->map_mflags
))
(void) lockfile(db
->fd(db
), map
->map_file
, LOCK_SH
);
st
= db
->get(db
, &key
, &val
, 0);
(void) lockfile(db
->fd(db
), map
->map_file
, LOCK_UN
);
syserr("db_map_lookup: get (%s)", name
);
if (bitset(MF_MATCHONLY
, map
->map_mflags
))
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_mflags
))
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
);
** 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_mflags
);
if (bitset(MF_WRITABLE
, map
->map_mflags
))
/* 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
);
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";
/* check to see if this map actually exists */
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
)
if (!bitset(MF_OPTIONAL
, map
->map_mflags
))
syserr("Cannot bind to domain %s: %s", map
->map_domain
,
** 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_mflags
))
if (bitset(MF_INCLNULL
, map
->map_mflags
))
yperr
= yp_match(map
->map_domain
, map
->map_file
, keybuf
, buflen
,
if (yperr
!= YPERR_KEY
&& yperr
!= YPERR_BUSY
)
map
->map_mflags
&= ~(MF_VALID
|MF_OPEN
);
if (bitset(MF_MATCHONLY
, map
->map_mflags
))
return map_rewrite(map
, vp
, vsize
, av
);
nis_map_store(map
, lhs
, rhs
)
** STAB (Symbol Table) Modules
** STAB_MAP_LOOKUP -- 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_MAP_STORE -- 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_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.
printf("stab_map_open(%s)\n", map
->map_file
);
** STAB_MAP_CLOSE -- close symbol table (???)
** Tries several types. For back compatibility of aliases.
** IMPL_MAP_LOOKUP -- 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_mflags
))
return db_map_lookup(map
, name
, av
, pstat
);
if (bitset(MF_IMPL_NDBM
, map
->map_mflags
))
return ndbm_map_lookup(map
, name
, av
, pstat
);
return stab_map_lookup(map
, name
, av
, pstat
);
** IMPL_MAP_STORE -- store in open databases
impl_map_store(map
, lhs
, rhs
)
if (bitset(MF_IMPL_HASH
, map
->map_mflags
))
db_map_store(map
, lhs
, rhs
);
if (bitset(MF_IMPL_NDBM
, map
->map_mflags
))
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 */
map
->map_mflags
|= MF_IMPL_HASH
;
if (hash_map_open(map
, mode
))
#if defined(NDBM) && defined(YPCOMPAT)
if (mode
== O_RDONLY
|| access("/var/yp/Makefile", R_OK
) == 0)
map
->map_mflags
&= ~MF_IMPL_HASH
;
map
->map_mflags
|= MF_IMPL_NDBM
;
if (ndbm_map_open(map
, mode
))
map
->map_mflags
&= ~MF_IMPL_NDBM
;
#if !defined(NEWDB) && !defined(NDBM)
message("WARNING: cannot open alias database %s", map
->map_file
);
return stab_map_open(map
, mode
);
** IMPL_MAP_CLOSE -- close any open database(s)
if (bitset(MF_IMPL_HASH
, map
->map_mflags
))
map
->map_mflags
&= ~MF_IMPL_HASH
;
if (bitset(MF_IMPL_NDBM
, map
->map_mflags
))
map
->map_mflags
&= ~MF_IMPL_NDBM
;
null_map_store(map
, key
, val
)