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

📄 udb.c

📁 < linux网络编程工具>>配套源码
💻 C
📖 第 1 页 / 共 3 页
字号:
**	Returns:
**		EX_TEMPFAIL -- if it appeared it couldn't get hold of a
**			database due to a host being down or some similar
**			(recoverable) situation.
**		EX_OK -- otherwise.
**
**	Side Effects:
**		Fills in the UdbEnts structure from UdbSpec.
*/

# define MAXUDBOPTS	27

static int
_udbx_init(e)
	ENVELOPE *e;
{
	int ents = 0;
	register char *p;
	register struct udbent *up;

	if (UdbInitialized)
		return EX_OK;

# ifdef UDB_DEFAULT_SPEC
	if (UdbSpec == NULL)
		UdbSpec = UDB_DEFAULT_SPEC;
# endif /* UDB_DEFAULT_SPEC */

	p = UdbSpec;
	up = UdbEnts;
	while (p != NULL)
	{
		char *spec;
		int l;
		struct udb_option opts[MAXUDBOPTS + 1];

		while (*p == ' ' || *p == '\t' || *p == ',')
			p++;
		if (*p == '\0')
			break;
		spec = p;
		p = strchr(p, ',');
		if (p != NULL)
			*p++ = '\0';

		if (ents >= MAXUDBENT)
		{
			syserr("Maximum number of UDB entries exceeded");
			break;
		}

		/* extract options */
		(void) _udb_parsespec(spec, opts, MAXUDBOPTS);

		/*
		**  Decode database specification.
		**
		**	In the sendmail tradition, the leading character
		**	defines the semantics of the rest of the entry.
		**
		**	@hostname --	forward email to the indicated host.
		**			This should be the last in the list,
		**			since it always matches the input.
		**	/dbname	 --	search the named database on the local
		**			host using the Berkeley db package.
		**	Hesiod --	search the named database with BIND
		**			using the MIT Hesiod package.
		*/

		switch (*spec)
		{
		  case '@':	/* forward to remote host */
			up->udb_type = UDB_FORWARD;
			up->udb_pid = getpid();
			up->udb_fwdhost = spec + 1;
			ents++;
			up++;
			break;

# ifdef HESIOD
		  case 'h':	/* use hesiod */
		  case 'H':
			if (strcasecmp(spec, "hesiod") != 0)
				goto badspec;
			up->udb_type = UDB_HESIOD;
			up->udb_pid = getpid();
			ents++;
			up++;
			break;
# endif /* HESIOD */

# ifdef NEWDB
		  case '/':	/* look up remote name */
			l = strlen(spec);
			if (l > 3 && strcmp(&spec[l - 3], ".db") == 0)
			{
				up->udb_dbname = spec;
			}
			else
			{
				up->udb_dbname = xalloc(l + 4);
				(void) strlcpy(up->udb_dbname, spec, l + 4);
				(void) strlcat(up->udb_dbname, ".db", l + 4);
			}
			errno = 0;
#  if DB_VERSION_MAJOR < 2
			up->udb_dbp = dbopen(up->udb_dbname, O_RDONLY,
					     0644, DB_BTREE, NULL);
#  else /* DB_VERSION_MAJOR < 2 */
			{
				int flags = DB_RDONLY;
#  if DB_VERSION_MAJOR > 2
				int ret;
#  endif /* DB_VERSION_MAJOR > 2 */

#  if !HASFLOCK && defined(DB_FCNTL_LOCKING)
				flags |= DB_FCNTL_LOCKING;
#  endif /* !HASFLOCK && defined(DB_FCNTL_LOCKING) */

				up->udb_dbp = NULL;

#  if DB_VERSION_MAJOR > 2
				ret = db_create(&up->udb_dbp, NULL, 0);
				if (ret != 0)
				{
					(void) up->udb_dbp->close(up->udb_dbp,
								  0);
					up->udb_dbp = NULL;
				}
				else
				{
					ret = up->udb_dbp->open(up->udb_dbp,
								up->udb_dbname,
								NULL,
								DB_BTREE,
								flags,
								0644);
					if (ret != 0)
					{
						(void) up->udb_dbp->close(up->udb_dbp, 0);
						up->udb_dbp = NULL;
					}
				}
				errno = ret;
#  else /* DB_VERSION_MAJOR > 2 */
				errno = db_open(up->udb_dbname, DB_BTREE,
						flags, 0644, NULL,
						NULL, &up->udb_dbp);
#  endif /* DB_VERSION_MAJOR > 2 */
			}
#  endif /* DB_VERSION_MAJOR < 2 */
			if (up->udb_dbp == NULL)
			{
				if (tTd(28, 1))
				{
					int save_errno = errno;

#  if DB_VERSION_MAJOR < 2
					dprintf("dbopen(%s): %s\n",
#  else /* DB_VERSION_MAJOR < 2 */
					dprintf("db_open(%s): %s\n",
#  endif /* DB_VERSION_MAJOR < 2 */
						up->udb_dbname,
						errstring(errno));
					errno = save_errno;
				}
				if (errno != ENOENT && errno != EACCES)
				{
					if (LogLevel > 2)
						sm_syslog(LOG_ERR, e->e_id,
#  if DB_VERSION_MAJOR < 2
							  "dbopen(%s): %s",
#  else /* DB_VERSION_MAJOR < 2 */
							  "db_open(%s): %s",
#  endif /* DB_VERSION_MAJOR < 2 */
							  up->udb_dbname,
							  errstring(errno));
					up->udb_type = UDB_EOLIST;
					if (up->udb_dbname != spec)
						free(up->udb_dbname);
					goto tempfail;
				}
				if (up->udb_dbname != spec)
					free(up->udb_dbname);
				break;
			}
			if (tTd(28, 1))
			{
#  if DB_VERSION_MAJOR < 2
				dprintf("_udbx_init: dbopen(%s)\n",
#  else /* DB_VERSION_MAJOR < 2 */
				dprintf("_udbx_init: db_open(%s)\n",
#  endif /* DB_VERSION_MAJOR < 2 */
					up->udb_dbname);
			}
			up->udb_type = UDB_DBFETCH;
			up->udb_pid = getpid();
			ents++;
			up++;
			break;
# endif /* NEWDB */

		  default:
# ifdef HESIOD
badspec:
# endif /* HESIOD */
			syserr("Unknown UDB spec %s", spec);
			break;
		}
	}
	up->udb_type = UDB_EOLIST;

	if (tTd(28, 4))
	{
		for (up = UdbEnts; up->udb_type != UDB_EOLIST; up++)
		{
			switch (up->udb_type)
			{
# if DAEMON
			  case UDB_REMOTE:
				dprintf("REMOTE: addr %s, timeo %d\n",
					anynet_ntoa((SOCKADDR *) &up->udb_addr),
					up->udb_timeout);
				break;
# endif /* DAEMON */

			  case UDB_DBFETCH:
# ifdef NEWDB
				dprintf("FETCH: file %s\n",
					up->udb_dbname);
# else /* NEWDB */
				dprintf("FETCH\n");
# endif /* NEWDB */
				break;

			  case UDB_FORWARD:
				dprintf("FORWARD: host %s\n",
					up->udb_fwdhost);
				break;

			  case UDB_HESIOD:
				dprintf("HESIOD\n");
				break;

			  default:
				dprintf("UNKNOWN\n");
				break;
			}
		}
	}

	UdbInitialized = TRUE;
	errno = 0;
	return EX_OK;

	/*
	**  On temporary failure, back out anything we've already done
	*/

  tempfail:
# ifdef NEWDB
	for (up = UdbEnts; up->udb_type != UDB_EOLIST; up++)
	{
		if (up->udb_type == UDB_DBFETCH)
		{
#  if DB_VERSION_MAJOR < 2
			(*up->udb_dbp->close)(up->udb_dbp);
#  else /* DB_VERSION_MAJOR < 2 */
			errno = (*up->udb_dbp->close)(up->udb_dbp, 0);
#  endif /* DB_VERSION_MAJOR < 2 */
			if (tTd(28, 1))
				dprintf("_udbx_init: db->close(%s)\n",
					up->udb_dbname);
		}
	}
# endif /* NEWDB */
	return EX_TEMPFAIL;
}

static int
_udb_parsespec(udbspec, opt, maxopts)
	char *udbspec;
	struct udb_option opt[];
	int maxopts;
{
	register char *spec;
	register char *spec_end;
	register int optnum;

	spec_end = strchr(udbspec, ':');
	for (optnum = 0; optnum < maxopts && (spec = spec_end) != NULL; optnum++)
	{
		register char *p;

		while (isascii(*spec) && isspace(*spec))
			spec++;
		spec_end = strchr(spec, ':');
		if (spec_end != NULL)
			*spec_end++ = '\0';

		opt[optnum].udbo_name = spec;
		opt[optnum].udbo_val = NULL;
		p = strchr(spec, '=');
		if (p != NULL)
			opt[optnum].udbo_val = ++p;
	}
	return optnum;
}
/*
**  _UDBX_CLOSE -- close all file based UDB entries.
**
**	Parameters:
**		none
**
**	Returns:
**		none
*/
void
_udbx_close()
{
	pid_t pid;
	struct udbent *up;

	if (!UdbInitialized)
		return;

	pid = getpid();

	for (up = UdbEnts; up->udb_type != UDB_EOLIST; up++)
	{
		if (up->udb_pid != pid)
			continue;

# ifdef NEWDB
		if (up->udb_type == UDB_DBFETCH)
		{
#  if DB_VERSION_MAJOR < 2
			(*up->udb_dbp->close)(up->udb_dbp);
#  else /* DB_VERSION_MAJOR < 2 */
			errno = (*up->udb_dbp->close)(up->udb_dbp, 0);
#  endif /* DB_VERSION_MAJOR < 2 */
		}
		if (tTd(28, 1))
			dprintf("_udbx_init: db->close(%s)\n",
				up->udb_dbname);
# endif /* NEWDB */
	}
}

# ifdef HESIOD

static int
hes_udb_get(key, info)
	DBT *key;
	DBT *info;
{
	char *name, *type;
	char **hp;
	char kbuf[MAXKEY + 1];

	if (strlcpy(kbuf, key->data, sizeof kbuf) >= (SIZE_T) sizeof kbuf)
		return 0;
	name = kbuf;
	type = strrchr(name, ':');
	if (type == NULL)
		return 1;
	*type++ = '\0';
	if (strchr(name, '@') != NULL)
		return 1;

	if (tTd(28, 1))
		dprintf("hes_udb_get(%s, %s)\n", name, type);

	/* make the hesiod query */
#  ifdef HESIOD_INIT
	if (HesiodContext == NULL && hesiod_init(&HesiodContext) != 0)
		return -1;
	hp = hesiod_resolve(HesiodContext, name, type);
#  else /* HESIOD_INIT */
	hp = hes_resolve(name, type);
#  endif /* HESIOD_INIT */
	*--type = ':';
#  ifdef HESIOD_INIT
	if (hp == NULL)
		return 1;
	if (*hp == NULL)
	{
		hesiod_free_list(HesiodContext, hp);
		if (errno == ECONNREFUSED || errno == EMSGSIZE)
			return -1;
		return 1;
	}
#  else /* HESIOD_INIT */
	if (hp == NULL || hp[0] == NULL)
	{
		/* network problem or timeout */
		if (hes_error() == HES_ER_NET)
			return -1;

		return 1;
	}
#  endif /* HESIOD_INIT */
	else
	{
		/*
		**  If there are multiple matches, just return the
		**  first one.
		**
		**  XXX These should really be returned; for example,
		**  XXX it is legal for :maildrop to be multi-valued.
		*/

		info->data = hp[0];
		info->size = (size_t) strlen(info->data);
	}

	if (tTd(28, 80))
		dprintf("hes_udb_get => %s\n", *hp);

	return 0;
}
# endif /* HESIOD */

#else /* USERDB */

int
udbexpand(a, sendq, aliaslevel, e)
	ADDRESS *a;
	ADDRESS **sendq;
	int aliaslevel;
	ENVELOPE *e;
{
	return EX_OK;
}

#endif /* USERDB */

⌨️ 快捷键说明

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