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

📄 udb.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
	/* names beginning with colons indicate metadata */	if (user[0] == ':')		return NULL;	/* build database key */	(void) strcpy(keybuf, user);	(void) strcat(keybuf, ":");	(void) strcat(keybuf, field);	keylen = strlen(keybuf);	for (up = UdbEnts; up->udb_type != UDB_EOLIST; up++)	{		/*		**  Select action based on entry type.		*/		switch (up->udb_type)		{		  case UDB_DBFETCH:			key.data = keybuf;			key.size = keylen;			i = (*up->udb_dbp->get)(up->udb_dbp, &key, &info, 0);			if (i != 0 || info.size <= 0)			{				if (tTd(28, 2))					printf("udbmatch: no match on %s (%d) via db\n",							keybuf, keylen);				continue;			}			p = xalloc(info.size + 1);			bcopy(info.data, p, info.size);			p[info.size] = '\0';			if (tTd(28, 1))				printf("udbmatch ==> %s\n", p);			return p;			break;#ifdef HESIOD		  case UDB_HESIOD:			key.data = keybuf;			key.size = keylen;			i = hes_udb_get(&key, &info); 			if (i != 0 || info.size <= 0)			{				if (tTd(28, 2))					printf("udbmatch: no match on %s (%d) via hesiod\n",							keybuf, keylen);				continue;			}			p = xalloc(info.size + 1);			bcopy(info.data, p, info.size);			p[info.size] = '\0';			free(info.data);			if (tTd(28, 1))				printf("udbmatch ==> %s\n", p);			return p;			break;#endif /* HESIOD */		}	}	if (strcmp(field, "mailname") != 0)		return NULL;	/*	**  Nothing yet.  Search again for a default case.  But only	**  use it if we also have a forward (:maildrop) pointer already	**  in the database.	*/	/* build database key */	(void) strcpy(keybuf, user);	(void) strcat(keybuf, ":maildrop");	keylen = strlen(keybuf);	for (up = UdbEnts; up->udb_type != UDB_EOLIST; up++)	{		switch (up->udb_type)		{		  case UDB_DBFETCH:			/* get the default case for this database */			if (up->udb_default == NULL)			{				key.data = ":default:mailname";				key.size = strlen(key.data);				i = (*up->udb_dbp->get)(up->udb_dbp, &key, &info, 0);				if (i != 0 || info.size <= 0)				{					/* no default case */					up->udb_default = "";					continue;				}				/* save the default case */				up->udb_default = xalloc(info.size + 1);				bcopy(info.data, up->udb_default, info.size);				up->udb_default[info.size] = '\0';			}			else if (up->udb_default[0] == '\0')				continue;			/* we have a default case -- verify user:maildrop */			key.data = keybuf;			key.size = keylen;			i = (*up->udb_dbp->get)(up->udb_dbp, &key, &info, 0);			if (i != 0 || info.size <= 0)			{				/* nope -- no aliasing for this user */				continue;			}			/* they exist -- build the actual address */			p = xalloc(strlen(user) + strlen(up->udb_default) + 2);			(void) strcpy(p, user);			(void) strcat(p, "@");			(void) strcat(p, up->udb_default);			if (tTd(28, 1))				printf("udbmatch ==> %s\n", p);			return p;			break;#ifdef HESIOD		  case UDB_HESIOD:			/* get the default case for this database */			if (up->udb_default == NULL)			{				key.data = ":default:mailname";				key.size = strlen(key.data);				i = hes_udb_get(&key, &info); 				if (i != 0 || info.size <= 0)				{					/* no default case */					up->udb_default = "";					continue;				}				/* save the default case */				up->udb_default = xalloc(info.size + 1);				bcopy(info.data, up->udb_default, info.size);				up->udb_default[info.size] = '\0';				free(info.data);			}			else if (up->udb_default[0] == '\0')				continue;			/* we have a default case -- verify user:maildrop */			key.data = keybuf;			key.size = keylen;			i = hes_udb_get(&key, &info);			if (i != 0 || info.size <= 0)			{				/* nope -- no aliasing for this user */				continue;			}			free(info.data);			/* they exist -- build the actual address */			p = xalloc(strlen(user) + strlen(up->udb_default) + 2);			(void) strcpy(p, user);			(void) strcat(p, "@");			(void) strcat(p, up->udb_default);			if (tTd(28, 1))				printf("udbmatch ==> %s\n", p);			return p;			break;#endif /* HESIOD */		}	}	/* still nothing....  too bad */	return NULL;}/***  _UDBX_INIT -- parse the UDB specification, opening any valid entries.****	Parameters:**		none.****	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	27int_udbx_init(){	register char *p;	int i;	register struct udbent *up;	char buf[BUFSIZ];	if (UdbInitialized)		return EX_OK;# ifdef UDB_DEFAULT_SPEC	if (UdbSpec == NULL)		UdbSpec = UDB_DEFAULT_SPEC;# endif	p = UdbSpec;	up = UdbEnts;	while (p != NULL)	{		char *spec;		auto int rcode;		int nopts;		int nmx;		register struct hostent *h;		char *mxhosts[MAXMXHOSTS + 1];		struct option opts[MAXUDBOPTS + 1];		while (*p == ' ' || *p == '\t' || *p == ',')			p++;		if (*p == '\0')			break;		spec = p;		p = strchr(p, ',');		if (p != NULL)			*p++ = '\0';		/* extract options */		nopts = _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 --	send a datagram to the udb server		**			on host "hostname" asking for the		**			home mail server for this user.		**	*hostname --	similar to +hostname, except that the		**			hostname is searched as an MX record;		**			resulting hosts are searched as for		**			+mxhostname.  If no MX host is found,		**			this is the same as +hostname.		**	@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.		*/		switch (*spec)		{		  case '+':	/* search remote database */		  case '*':	/* search remote database (expand MX) */			if (*spec == '*')			{#if NAMED_BIND				nmx = getmxrr(spec + 1, mxhosts, FALSE, &rcode);#else				mxhosts[0] = spec + 1;				nmx = 1;				rcode = 0;#endif				if (tTd(28, 16))				{					int i;					printf("getmxrr(%s): %d", spec + 1, nmx);					for (i = 0; i <= nmx; i++)						printf(" %s", mxhosts[i]);					printf("\n");				}			}			else			{				nmx = 1;				mxhosts[0] = spec + 1;			}			for (i = 0; i < nmx; i++)			{				h = gethostbyname(mxhosts[i]);				if (h == NULL)					continue;				up->udb_type = UDB_REMOTE;				up->udb_addr.sin_family = h->h_addrtype;				bcopy(h->h_addr_list[0],				      (char *) &up->udb_addr.sin_addr,				      sizeof up->udb_addr.sin_addr);				up->udb_addr.sin_port = UdbPort;				up->udb_timeout = UdbTimeout;				up++;			}			/* set up a datagram socket */			if (UdbSock < 0)			{				UdbSock = socket(AF_INET, SOCK_DGRAM, 0);				(void) fcntl(UdbSock, F_SETFD, 1);			}			break;		  case '@':	/* forward to remote host */			up->udb_type = UDB_FORWARD;			up->udb_fwdhost = spec + 1;			up++;			break;		  case 'h':	/* use hesiod */		  case 'H':#ifdef HESIOD			if (strcasecmp(spec, "hesiod") != 0)				break;			up->udb_type = UDB_HESIOD;			up++;#endif /* HESIOD */			break;		  case '/':	/* look up remote name */			up->udb_dbname = spec;			errno = 0;			up->udb_dbp = dbopen(spec, O_RDONLY, 0644, DB_BTREE, NULL);			if (up->udb_dbp == NULL)			{				if (errno != ENOENT && errno != EACCES)				{#ifdef LOG					if (LogLevel > 2)						syslog(LOG_ERR, "dbopen(%s): %s",							spec, errstring(errno));#endif					up->udb_type = UDB_EOLIST;					goto tempfail;				}				break;			}			up->udb_type = UDB_DBFETCH;			up++;			break;		}	}	up->udb_type = UDB_EOLIST;	if (tTd(28, 4))	{		for (up = UdbEnts; up->udb_type != UDB_EOLIST; up++)		{			switch (up->udb_type)			{			  case UDB_REMOTE:				printf("REMOTE: addr %s, timeo %d\n",					anynet_ntoa((SOCKADDR *) &up->udb_addr),					up->udb_timeout);				break;			  case UDB_DBFETCH:				printf("FETCH: file %s\n",					up->udb_dbname);				break;			  case UDB_FORWARD:				printf("FORWARD: host %s\n",					up->udb_fwdhost);				break;			  case UDB_HESIOD:				printf("HESIOD\n");				break;			  default:				printf("UNKNOWN\n");				break;			}		}	}	UdbInitialized = TRUE;	errno = 0;	return EX_OK;	/*	**  On temporary failure, back out anything we've already done	*/  tempfail:	for (up = UdbEnts; up->udb_type != UDB_EOLIST; up++)	{		if (up->udb_type == UDB_DBFETCH)		{			(*up->udb_dbp->close)(up->udb_dbp);		}	}	return EX_TEMPFAIL;}int_udb_parsespec(udbspec, opt, maxopts)	char *udbspec;	struct 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].name = spec;		opt[optnum].val = NULL;		p = strchr(spec, '=');		if (p != NULL)			opt[optnum].val = ++p;	}	return optnum;}#ifdef HESIODinthes_udb_get(key, info)	DBT *key;	DBT *info;{	char *name, *type;	char *p, **hp;	name = key->data;	type = strchr(name, ':');	if (type == NULL)		return 1;	*type++ = '\0';	if (tTd(28, 1))		printf("hes_udb_get(%s, %s)\n", name, type);	/* make the hesiod query */	hp = hes_resolve(name, type);	if (hp == NULL)	{		/* network problem or timeout */		if (hes_error() == HES_ER_NET)			return -1;		return 1;	}	else	{		/*		**  If there are multiple matches, just return the		**  first one and free the others.		**		**  XXX These should really be returned; for example,		**  XXX it is legal for :maildrop to be multi-valued.		*/		for (p = hp[1]; p; p++)			free(p);		info->data = hp[0];		info->size = (size_t) strlen(info->data);	}	return 0;}#endif /* HESIOD */#else /* not USERDB */intudbexpand(a, sendq, e)	ADDRESS *a;	ADDRESS **sendq;	ENVELOPE *e;{	return EX_OK;}#endif /* USERDB */

⌨️ 快捷键说明

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