⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 map.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1992 Eric P. Allman. * Copyright (c) 1992, 1993 *	The Regents of the University of California.  All rights reserved. * * 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 lintstatic char sccsid[] = "@(#)map.c	8.25 (Berkeley) 4/17/94";#endif /* not lint */#include "sendmail.h"#ifdef NDBM#include <ndbm.h>#endif#ifdef NEWDB#include <db.h>#endif#ifdef NIS#include <rpcsvc/ypclnt.h>#endif/***  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**		values.****	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)**		Close the map.*/#define DBMMODE		0644extern bool	aliaswait __P((MAP *, char *, int));/***  MAP_PARSEARGS -- parse config line arguments for database lookup****	This is a generic version of the map_parse method.****	Parameters:**		map -- the map being initialized.**		ap -- a pointer to the args on the config line.****	Returns:**		TRUE -- if everything parsed OK.**		FALSE -- otherwise.****	Side Effects:**		null terminates the filename; stores it in map*/boolmap_parseargs(map, ap)	MAP *map;	char *ap;{	register char *p = ap;	map->map_mflags |= MF_TRY0NULL | MF_TRY1NULL;	for (;;)	{		while (isascii(*p) && isspace(*p))			p++;		if (*p != '-')			break;		switch (*++p)		{		  case 'N':			map->map_mflags |= MF_INCLNULL;			map->map_mflags &= ~MF_TRY0NULL;			break;		  case 'O':			map->map_mflags &= ~MF_TRY1NULL;			break;		  case 'o':			map->map_mflags |= MF_OPTIONAL;			break;		  case 'f':			map->map_mflags |= MF_NOFOLDCASE;			break;		  case 'm':			map->map_mflags |= MF_MATCHONLY;			break;		  case 'a':			map->map_app = ++p;			break;		}		while (*p != '\0' && !(isascii(*p) && isspace(*p)))			p++;		if (*p != '\0')			*p++ = '\0';	}	if (map->map_app != NULL)		map->map_app = newstr(map->map_app);	if (*p != '\0')	{		map->map_file = p;		while (*p != '\0' && !(isascii(*p) && isspace(*p)))			p++;		if (*p != '\0')			*p++ = '\0';		map->map_file = newstr(map->map_file);	}	while (*p != '\0' && isascii(*p) && isspace(*p))		p++;	if (*p != '\0')		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);		return FALSE;	}	return TRUE;}/***  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.****	Parameters:**		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.****	Returns:**		Pointer to rewritten result.****	Side Effects:**		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;	register char *s;	int slen;	char **av;{	register char *bp;	register char c;	char **avp;	register char *ap;	register struct rwbuf *rwb;	int i;	int len;	if (tTd(39, 1))	{		printf("map_rewrite(%.*s), av =", slen, s);		if (av == NULL)			printf(" (nullv)");		else		{			for (avp = av; *avp != NULL; avp++)				printf("\n\t%s", *avp);		}		printf("\n");	}	rwb = RwBufs;	if (av == NULL)		rwb++;	/* count expected size of output (can safely overestimate) */	i = len = slen;	if (av != NULL)	{		bp = s;		for (i = slen; --i >= 0 && (c = *bp++) != 0; )		{			if (c != '%')				continue;			if (--i < 0)				break;			c = *bp++;			if (!(isascii(c) && isdigit(c)))				continue;			for (avp = av; --c >= '0' && *avp != NULL; avp++)				continue;			if (*avp == NULL)				continue;			len += strlen(*avp);		}	}	if (map->map_app != NULL)		len += strlen(map->map_app);	if (rwb->rwb_len < ++len)	{		/* need to malloc additional space */		rwb->rwb_len = len;		if (rwb->rwb_buf != NULL)			free(rwb->rwb_buf);		rwb->rwb_buf = xalloc(rwb->rwb_len);	}	bp = rwb->rwb_buf;	if (av == NULL)	{		bcopy(s, bp, slen);		bp += slen;	}	else	{		while (--slen >= 0 && (c = *s++) != '\0')		{			if (c != '%')			{  pushc:				*bp++ = c;				continue;			}			if (--slen < 0 || (c = *s++) == '\0')				c = '%';			if (c == '%')				goto pushc;			if (!(isascii(c) && isdigit(c)))			{				*bp++ = '%';				goto pushc;			}			for (avp = av; --c >= '0' && *avp != NULL; avp++)				continue;			if (*avp == NULL)				continue;			/* transliterate argument into output string */			for (ap = *avp; (c = *ap++) != '\0'; )				*bp++ = c;		}	}	if (map->map_app != NULL)		strcpy(bp, map->map_app);	else		*bp = '\0';	if (tTd(39, 1))		printf("map_rewrite => %s\n", rwb->rwb_buf);	return rwb->rwb_buf;}/***  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();#ifdef XDEBUG	checkfd012("entering initmaps");#endif	CurEnv = e;	if (rebuild)	{		stabapply(map_init, 1);		stabapply(map_init, 2);	}	else	{		stabapply(map_init, 0);	}#ifdef XDEBUG	checkfd012("exiting initmaps");#endif}voidmap_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, %d)\n",			map->map_class->map_cname == NULL ? "NULL" :				map->map_class->map_cname,			map->map_file == NULL ? "NULL" : map->map_file,			rebuild);	if (rebuild == (bitset(MF_ALIAS, map->map_mflags) &&		    bitset(MCF_REBUILDABLE, map->map_class->map_cflags) ? 1 : 2))	{		if (tTd(38, 3))			printf("\twrong pass\n");		return;	}	/* 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 == 2)	{		rebuildaliases(map, FALSE);	}	else	{		if (map->map_class->map_open(map, O_RDONLY))		{			if (tTd(38, 4))				printf("\t%s:%s: valid\n",					map->map_class->map_cname == NULL ? "NULL" :						map->map_class->map_cname,					map->map_file == NULL ? "NULL" :						map->map_file);			map->map_mflags |= MF_OPEN;		}		else if (tTd(38, 4))			printf("\t%s:%s: invalid: %s\n",				map->map_class->map_cname == NULL ? "NULL" :					map->map_class->map_cname,				map->map_file == NULL ? "NULL" :					map->map_file,				errstring(errno));	}}/***  NDBM modules*/#ifdef NDBM/***  DBM_MAP_OPEN -- DBM-style map open*/boolndbm_map_open(map, mode)	MAP *map;	int mode;{	register DBM *dbm;	struct stat st;	if (tTd(38, 2))		printf("ndbm_map_open(%s, %d)\n", map->map_file, mode);	if (mode == O_RDWR)		mode |= O_CREAT|O_TRUNC;	/* open the database */	dbm = dbm_open(map->map_file, mode, DBMMODE);	if (dbm == NULL)	{#ifdef MAYBENEXTRELEASE		if (aliaswait(map, ".pag", FALSE))			return TRUE;#endif		if (!bitset(MF_OPTIONAL, map->map_mflags))			syserr("Cannot open DBM database %s", map->map_file);		return FALSE;	}	map->map_db1 = (void *) dbm;	if (mode == O_RDONLY)	{		if (bitset(MF_ALIAS, map->map_mflags) &&		    !aliaswait(map, ".pag", TRUE))			return FALSE;	}	else	{		int fd;		/* exclusive lock for duration of rebuild */		fd = dbm_dirfno((DBM *) map->map_db1);		if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags) &&		    lockfile(fd, map->map_file, ".dir", LOCK_EX))			map->map_mflags |= MF_LOCKED;	}	if (fstat(dbm_dirfno((DBM *) map->map_db1), &st) >= 0)		map->map_mtime = st.st_mtime;	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;	int fd;	char keybuf[MAXNAME + 1];	if (tTd(38, 20))		printf("ndbm_map_lookup(%s)\n", name);	key.dptr = 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);		makelower(keybuf);		key.dptr = keybuf;	}	fd = dbm_dirfno((DBM *) map->map_db1);	if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))		(void) lockfile(fd, map->map_file, ".dir", LOCK_SH);	val.dptr = NULL;	if (bitset(MF_TRY0NULL, map->map_mflags))	{		val = dbm_fetch((DBM *) map->map_db1, key);		if (val.dptr != NULL)			map->map_mflags &= ~MF_TRY1NULL;	}	if (val.dptr == NULL && bitset(MF_TRY1NULL, map->map_mflags))	{		key.dsize++;		val = dbm_fetch((DBM *) map->map_db1, key);		if (val.dptr != NULL)			map->map_mflags &= ~MF_TRY0NULL;	}	if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))		(void) lockfile(fd, map->map_file, ".dir", LOCK_UN);	if (val.dptr == NULL)		return NULL;	if (bitset(MF_MATCHONLY, map->map_mflags))		return map_rewrite(map, name, strlen(name), NULL);	else		return map_rewrite(map, val.dptr, val.dsize, av);}/***  DBM_MAP_STORE -- store a datum in the database*/voidndbm_map_store(map, lhs, rhs)	register MAP *map;	char *lhs;	char *rhs;{	datum key;	datum data;	int stat;	if (tTd(38, 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_mflags))	{		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);}/***  NDBM_MAP_CLOSE -- close the database*/voidndbm_map_close(map)	register MAP  *map;{	if (tTd(38, 9))		printf("ndbm_map_close(%s, %x)\n", map->map_file, map->map_mflags);	if (bitset(MF_WRITABLE, map->map_mflags))	{#ifdef NIS		bool inclnull;		char buf[200];		inclnull = bitset(MF_INCLNULL, map->map_mflags);		map->map_mflags &= ~MF_INCLNULL;		(void) sprintf(buf, "%010ld", curtime());		ndbm_map_store(map, "YP_LAST_MODIFIED", buf);		(void) gethostname(buf, sizeof buf);		ndbm_map_store(map, "YP_MASTER_NAME", buf);		if (inclnull)			map->map_mflags |= MF_INCLNULL;#endif		/* write out the distinguished alias */		ndbm_map_store(map, "@", "@");	}	dbm_close((DBM *) map->map_db1);}#endif/***  NEWDB (Hash and BTree) Modules*/#ifdef NEWDB/***  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.*/boolbt_map_open(map, mode)	MAP *map;	int mode;{	DB *db;	int i;	int omode;	int fd;	struct stat st;	char buf[MAXNAME];	if (tTd(38, 2))		printf("bt_map_open(%s, %d)\n", map->map_file, mode);	omode = mode;	if (omode == O_RDWR)	{		omode |= O_CREAT|O_TRUNC;#if defined(O_EXLOCK) && HASFLOCK		omode |= O_EXLOCK;# if !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");	db = dbopen(buf, omode, DBMMODE, DB_BTREE, NULL);	if (db == NULL)	{#ifdef MAYBENEXTRELEASE		if (aliaswait(map, ".db", FALSE))			return TRUE;#endif		if (!bitset(MF_OPTIONAL, map->map_mflags))			syserr("Cannot open BTREE database %s", map->map_file);		return FALSE;	}#if !OLD_NEWDB && HASFLOCK

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -