📄 map.c
字号:
if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags) &&
!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 i;
int st;
int save_errno;
int fd;
struct stat stbuf;
char keybuf[MAXNAME + 1];
char buf[MAXNAME + 1];
memset(&key, '\0', sizeof key);
memset(&val, '\0', sizeof val);
if (tTd(38, 20))
dprintf("db_map_lookup(%s, %s)\n",
map->map_mname, name);
i = strlen(map->map_file);
if (i > MAXNAME)
i = MAXNAME;
(void) strlcpy(buf, map->map_file, i + 1);
if (i > 3 && strcmp(&buf[i - 3], ".db") == 0)
buf[i - 3] = '\0';
key.size = strlen(name);
if (key.size > sizeof keybuf - 1)
key.size = sizeof keybuf - 1;
key.data = keybuf;
memmove(keybuf, name, key.size);
keybuf[key.size] = '\0';
if (!bitset(MF_NOFOLDCASE, map->map_mflags))
makelower(keybuf);
lockdb:
# if DB_VERSION_MAJOR < 2
fd = db->fd(db);
# else /* DB_VERSION_MAJOR < 2 */
fd = -1;
errno = db->fd(db, &fd);
# endif /* DB_VERSION_MAJOR < 2 */
if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
(void) lockfile(fd, buf, ".db", LOCK_SH);
if (fd < 0 || fstat(fd, &stbuf) < 0 || stbuf.st_mtime > map->map_mtime)
{
/* Reopen the database to sync the cache */
int omode = bitset(map->map_mflags, MF_WRITABLE) ? O_RDWR
: O_RDONLY;
if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
(void) lockfile(fd, buf, ".db", LOCK_UN);
map->map_class->map_close(map);
map->map_mflags &= ~(MF_OPEN|MF_WRITABLE);
if (map->map_class->map_open(map, omode))
{
map->map_mflags |= MF_OPEN;
map->map_pid = getpid();
if ((omode && O_ACCMODE) == O_RDWR)
map->map_mflags |= MF_WRITABLE;
db = (DB *) map->map_db2;
goto lockdb;
}
else
{
if (!bitset(MF_OPTIONAL, map->map_mflags))
{
extern MAPCLASS BogusMapClass;
*statp = EX_TEMPFAIL;
map->map_class = &BogusMapClass;
map->map_mflags |= MF_OPEN;
map->map_pid = getpid();
syserr("Cannot reopen DB database %s",
map->map_file);
}
return NULL;
}
}
st = 1;
if (bitset(MF_TRY0NULL, map->map_mflags))
{
# if DB_VERSION_MAJOR < 2
st = db->get(db, &key, &val, 0);
# else /* DB_VERSION_MAJOR < 2 */
errno = db->get(db, NULL, &key, &val, 0);
switch (errno)
{
case DB_NOTFOUND:
case DB_KEYEMPTY:
st = 1;
break;
case 0:
st = 0;
break;
default:
st = -1;
break;
}
# endif /* DB_VERSION_MAJOR < 2 */
if (st == 0)
map->map_mflags &= ~MF_TRY1NULL;
}
if (st != 0 && bitset(MF_TRY1NULL, map->map_mflags))
{
key.size++;
# if DB_VERSION_MAJOR < 2
st = db->get(db, &key, &val, 0);
# else /* DB_VERSION_MAJOR < 2 */
errno = db->get(db, NULL, &key, &val, 0);
switch (errno)
{
case DB_NOTFOUND:
case DB_KEYEMPTY:
st = 1;
break;
case 0:
st = 0;
break;
default:
st = -1;
break;
}
# endif /* DB_VERSION_MAJOR < 2 */
if (st == 0)
map->map_mflags &= ~MF_TRY0NULL;
}
save_errno = errno;
if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
(void) lockfile(fd, buf, ".db", LOCK_UN);
if (st != 0)
{
errno = save_errno;
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 status;
DBT key;
DBT data;
register DB *db = map->map_db2;
char keybuf[MAXNAME + 1];
memset(&key, '\0', sizeof key);
memset(&data, '\0', sizeof data);
if (tTd(38, 12))
dprintf("db_map_store(%s, %s, %s)\n",
map->map_mname, lhs, rhs);
key.size = strlen(lhs);
key.data = lhs;
if (!bitset(MF_NOFOLDCASE, map->map_mflags))
{
if (key.size > sizeof keybuf - 1)
key.size = sizeof keybuf - 1;
memmove(keybuf, key.data, key.size);
keybuf[key.size] = '\0';
makelower(keybuf);
key.data = keybuf;
}
data.size = strlen(rhs);
data.data = rhs;
if (bitset(MF_INCLNULL, map->map_mflags))
{
key.size++;
data.size++;
}
# if DB_VERSION_MAJOR < 2
status = db->put(db, &key, &data, R_NOOVERWRITE);
# else /* DB_VERSION_MAJOR < 2 */
errno = db->put(db, NULL, &key, &data, DB_NOOVERWRITE);
switch (errno)
{
case DB_KEYEXIST:
status = 1;
break;
case 0:
status = 0;
break;
default:
status = -1;
break;
}
# endif /* DB_VERSION_MAJOR < 2 */
if (status > 0)
{
if (!bitset(MF_APPEND, map->map_mflags))
message("050 Warning: duplicate alias name %s", lhs);
else
{
static char *buf = NULL;
static int bufsiz = 0;
DBT old;
memset(&old, '\0', sizeof old);
old.data = db_map_lookup(map, key.data,
(char **)NULL, &status);
if (old.data != NULL)
{
old.size = strlen(old.data);
if (data.size + old.size + 2 > (size_t)bufsiz)
{
if (buf != NULL)
(void) free(buf);
bufsiz = data.size + old.size + 2;
buf = xalloc(bufsiz);
}
snprintf(buf, bufsiz, "%s,%s",
(char *) data.data, (char *) old.data);
data.size = data.size + old.size + 1;
data.data = buf;
if (tTd(38, 9))
dprintf("db_map_store append=%s\n",
(char *) data.data);
}
}
# if DB_VERSION_MAJOR < 2
status = db->put(db, &key, &data, 0);
# else /* DB_VERSION_MAJOR < 2 */
status = errno = db->put(db, NULL, &key, &data, 0);
# endif /* DB_VERSION_MAJOR < 2 */
}
if (status != 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))
dprintf("db_map_close(%s, %s, %lx)\n",
map->map_mname, map->map_file, map->map_mflags);
if (bitset(MF_WRITABLE, map->map_mflags))
{
/* write out the distinguished alias */
db_map_store(map, "@", "@");
}
(void) db->sync(db, 0);
# if !LOCK_ON_OPEN
if (map->map_lockfd >= 0)
(void) close(map->map_lockfd);
# endif /* !LOCK_ON_OPEN */
# if DB_VERSION_MAJOR < 2
if (db->close(db) != 0)
# else /* DB_VERSION_MAJOR < 2 */
/*
** Berkeley DB can use internal shared memory
** locking for its memory pool. Closing a map
** opened by another process will interfere
** with the shared memory and locks of the parent
** process leaving things in a bad state.
*/
/*
** If this map was not opened by the current
** process, do not close the map but recover
** the file descriptor.
*/
if (map->map_pid != getpid())
{
int fd = -1;
errno = db->fd(db, &fd);
if (fd >= 0)
(void) close(fd);
return;
}
if ((errno = db->close(db, 0)) != 0)
# endif /* DB_VERSION_MAJOR < 2 */
syserr("db_map_close(%s, %s, %lx): db close failure",
map->map_mname, map->map_file, map->map_mflags);
}
#endif /* NEWDB */
/*
** NIS Modules
*/
#ifdef NIS
# ifndef YPERR_BUSY
# define YPERR_BUSY 16
# endif /* ! YPERR_BUSY */
/*
** 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;
if (tTd(38, 2))
dprintf("nis_map_open(%s, %s, %d)\n",
map->map_mname, map->map_file, mode);
mode &= O_ACCMODE;
if (mode != O_RDONLY)
{
/* issue a pseudo-error message */
# ifdef ENOSYS
errno = ENOSYS;
# else /* ENOSYS */
# ifdef EFTYPE
errno = EFTYPE;
# else /* EFTYPE */
errno = ENXIO;
# endif /* EFTYPE */
# endif /* ENOSYS */
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("421 4.3.5 NIS map %s specified, but NIS not running",
map->map_file);
return FALSE;
}
}
/* check to see if this map actually exists */
vp = NULL;
yperr = yp_match(map->map_domain, map->map_file, "@", 1,
&vp, &vsize);
if (tTd(38, 10))
dprintf("nis_map_open: yp_match(@, %s, %s) => %s\n",
map->map_domain, map->map_file, yperr_string(yperr));
if (vp != NULL)
free(vp);
if (yperr == 0 || yperr == YPERR_KEY || yperr == YPERR_BUSY)
{
/*
** We ought to be calling aliaswait() here if this is an
** alias file, but powerful HP-UX NIS servers apparently
** don't insert the @:@ token into the alias map when it
** is rebuilt, so aliaswait() just hangs. I hate HP-UX.
*/
# if 0
if (!bitset(MF_ALIAS, map->map_mflags) ||
aliaswait(map, NULL, TRUE))
# endif /* 0 */
return TRUE;
}
if (!bitset(MF_OPTIONAL, map->map_mflags))
{
syserr("421 4.0.0 Cannot bind to map %s in domain %s: %s",
map->map_file, map->map_domain, yperr_string(yperr));
}
return FALSE;
}
/*
** NIS_MAP_LOOKUP -- look up a datum in a NIS map
*/
/* ARGSUSED3 */
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))
dprintf("nis_map_lookup(%s, %s)\n",
map->map_mname, name);
buflen = strlen(name);
if (buflen > sizeof keybuf - 1)
buflen = sizeof keybuf - 1;
memmove(keybuf, name, buflen);
keybuf[buflen] = '\0';
if (!bitset(MF_NOFOLDCASE, map->map_mflags))
makelower(keybuf);
yperr = YPERR_KEY;
vp = NULL;
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))
{
if (vp != NULL)
{
free(vp);
vp = NULL;
}
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);
if (vp != NULL)
free(vp);
return NULL;
}
if (bitset(MF_MATCHONLY, map->map_mflags))
return map_rewrite(map, name, strlen(name), NULL);
else
{
char *ret;
ret = map_rewrite(map, vp, vsize, av);
if (vp != NULL)
free(vp);
return ret;
}
}
/*
** NIS_GETCANONNAME -- look up canonical name in NIS
*/
static bool
nis_getcanonname(name, hbsize, statp)
char *name;
int hbsize;
int *statp;
{
char *vp;
auto int vsize;
int keylen;
int yperr;
static bool try0null = TRUE;
static bool try1null = TRUE;
static char *yp_domain = NULL;
char host_record[MAXLINE];
char cbuf[MAXNAME];
char nbuf[MAXNAME + 1];
if (tTd(38, 20))
dprintf("nis_getcanonname(%s)\n", name);
if (strlcpy(nbuf, name, sizeof nbuf) >= sizeof nbuf)
{
*statp = EX_UNAVAILABLE;
return FALSE;
}
shorten_hostname(nbuf);
keylen = strlen(nbuf);
if (yp_domain == NULL)
(void) yp_get_default_domain(&yp_domain);
makelower(nbuf);
yperr = YPERR_KEY;
vp = NULL;
if (try0null)
{
yperr = yp_match(yp_domain, "hosts.byname", nbuf, keylen,
&vp, &vsize);
if (yperr == 0)
try1null = FALSE;
}
if (yperr == YPERR_KEY && try1null)
{
if (vp != NULL)
{
free(vp);
vp = NULL;
}
keylen++;
yperr = yp_match(yp_domain, "hosts.byname", nbuf, keylen,
&vp, &vsize);
if (yperr == 0)
try0null = FALSE;
}
if (yperr != 0)
{
if (yperr == YPERR_KEY)
*statp = EX_NOHOST;
else if (yperr == YPERR_BUSY)
*statp = EX_TEMPFAIL;
else
*statp = EX_UNAVAILABLE;
if (vp != NULL)
free(vp);
return FALSE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -