2 * Copyright (c) 1998-2003 Sendmail, Inc. and its suppliers.
4 * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
5 * Copyright (c) 1988, 1993
6 * The Regents of the University of California. All rights reserved.
8 * By using this file, you agree to the terms and conditions set
9 * forth in the LICENSE file which can be found at the top level of
10 * the sendmail distribution.
17 SM_RCSID("@(#)$Id: udb.c,v 8.161 2005/08/31 21:34:20 ca Exp $ (with USERDB)")
19 SM_RCSID("@(#)$Id: udb.c,v 8.161 2005/08/31 21:34:20 ca Exp $ (without USERDB)")
27 # define DBT struct _data_base_thang_
30 void *data; /* pointer to data */
31 size_t size; /* length of data */
36 ** UDB.C -- interface between sendmail and Berkeley User Data Base.
38 ** This depends on the 4.4BSD db package.
44 char *udb_spec; /* string version of spec */
45 int udb_type; /* type of entry */
46 pid_t udb_pid; /* PID of process which opened db */
47 char *udb_default; /* default host for outgoing mail */
50 # if NETINET || NETINET6
51 /* type UE_REMOTE -- do remote call for lookup */
54 SOCKADDR _udb_addr; /* address */
55 int _udb_timeout; /* timeout */
57 # define udb_addr udb_u.udb_remote._udb_addr
58 # define udb_timeout udb_u.udb_remote._udb_timeout
59 # endif /* NETINET || NETINET6 */
61 /* type UE_FORWARD -- forward message to remote */
64 char *_udb_fwdhost; /* name of forward host */
66 # define udb_fwdhost udb_u.udb_forward._udb_fwdhost
69 /* type UE_FETCH -- lookup in local database */
72 char *_udb_dbname; /* pathname of database */
73 DB *_udb_dbp; /* open database ptr */
75 # define udb_dbname udb_u.udb_lookup._udb_dbname
76 # define udb_dbp udb_u.udb_lookup._udb_dbp
81 # define UDB_EOLIST 0 /* end of list */
82 # define UDB_SKIP 1 /* skip this entry */
83 # define UDB_REMOTE 2 /* look up in remote database */
84 # define UDB_DBFETCH 3 /* look up in local database */
85 # define UDB_FORWARD 4 /* forward to remote host */
86 # define UDB_HESIOD 5 /* look up via hesiod */
88 # define MAXUDBENT 10 /* maximum number of UDB entries */
98 static int hes_udb_get __P((DBT *, DBT *));
100 static char *udbmatch __P((char *, char *, SM_RPOOL_T *));
101 static int _udbx_init __P((ENVELOPE *));
102 static int _udb_parsespec __P((char *, struct udb_option [], int));
105 ** UDBEXPAND -- look up user in database and expand
108 ** a -- address to expand.
109 ** sendq -- pointer to head of sendq to put the expansions in.
110 ** aliaslevel -- the current alias nesting depth.
111 ** e -- the current envelope.
114 ** EX_TEMPFAIL -- if something "odd" happened -- probably due
115 ** to accessing a file on an NFS server that is down.
116 ** EX_OK -- otherwise.
122 static struct udbent UdbEnts[MAXUDBENT + 1];
123 static bool UdbInitialized = false;
126 udbexpand(a, sendq, aliaslevel, e)
130 register ENVELOPE *e;
136 register struct udbent *up;
140 char keybuf[MAXUDBKEY];
142 memset(&key, '\0', sizeof key);
143 memset(&info, '\0', sizeof info);
146 sm_dprintf("udbexpand(%s)\n", a->q_paddr);
148 /* make certain we are supposed to send to this address */
149 if (!QS_IS_SENDABLE(a->q_state))
151 e->e_to = a->q_paddr;
153 /* on first call, locate the database */
156 if (_udbx_init(e) == EX_TEMPFAIL)
160 /* short circuit the process if no chance of a match */
161 if (UdbSpec == NULL || UdbSpec[0] == '\0')
164 /* extract user to do userdb matching on */
167 /* short circuit name begins with '\\' since it can't possibly match */
168 /* (might want to treat this as unquoted instead) */
172 /* if name begins with a colon, it indicates our metadata */
176 keylen = sm_strlcpyn(keybuf, sizeof keybuf, 2, user, ":maildrop");
178 /* if name is too long, assume it won't match */
179 if (keylen >= sizeof keybuf)
182 /* build actual database key */
185 for (up = UdbEnts; !breakout; up++)
189 char userbuf[MEMCHUNKSIZE];
190 # if HESIOD && HES_GETMAILHOST
192 # endif /* HESIOD && HES_GETMAILHOST */
193 # if defined(NEWDB) && DB_VERSION_MAJOR > 1
195 # endif /* defined(NEWDB) && DB_VERSION_MAJOR > 1 */
199 usersize = sizeof userbuf;
200 userleft = sizeof userbuf - 1;
203 ** Select action based on entry type.
205 ** On dropping out of this switch, "class" should
206 ** explain the type of the data, and "user" should
207 ** contain the user information.
210 switch (up->udb_type)
217 sm_dprintf("udbexpand: trying %s (%d) via db\n",
219 # if DB_VERSION_MAJOR < 2
220 i = (*up->udb_dbp->seq)(up->udb_dbp, &key, &info, R_CURSOR);
221 # else /* DB_VERSION_MAJOR < 2 */
224 # if DB_VERSION_MAJOR > 2 || DB_VERSION_MINOR >= 6
225 (errno = (*up->udb_dbp->cursor)(up->udb_dbp,
226 NULL, &dbc, 0)) != 0)
227 # else /* DB_VERSION_MAJOR > 2 || DB_VERSION_MINOR >= 6 */
228 (errno = (*up->udb_dbp->cursor)(up->udb_dbp,
230 # endif /* DB_VERSION_MAJOR > 2 || DB_VERSION_MINOR >= 6 */
232 if (i != 0 || dbc == NULL ||
233 (errno = dbc->c_get(dbc, &key,
234 &info, DB_SET)) != 0)
236 # endif /* DB_VERSION_MAJOR < 2 */
237 if (i > 0 || info.size <= 0)
240 sm_dprintf("udbexpand: no match on %s (%d)\n",
242 # if DB_VERSION_MAJOR > 1
245 (void) dbc->c_close(dbc);
248 # endif /* DB_VERSION_MAJOR > 1 */
252 sm_dprintf("udbexpand: match %.*s: %.*s\n",
253 (int) key.size, (char *) key.data,
254 (int) info.size, (char *) info.data);
256 a->q_flags &= ~QSELFREF;
257 while (i == 0 && key.size == keylen &&
258 memcmp(key.data, keybuf, keylen) == 0)
262 if (bitset(EF_VRFYONLY, e->e_flags))
264 a->q_state = QS_VERIFIED;
265 # if DB_VERSION_MAJOR > 1
268 (void) dbc->c_close(dbc);
271 # endif /* DB_VERSION_MAJOR > 1 */
276 if (info.size >= userleft - 1)
279 int size = MEMCHUNKSIZE;
281 if (info.size > MEMCHUNKSIZE)
283 nuser = sm_malloc_x(usersize + size);
285 memmove(nuser, user, usersize);
287 sm_free(user); /* XXX */
292 p = &user[strlen(user)];
298 memmove(p, info.data, info.size);
300 userleft -= info.size;
302 /* get the next record */
303 # if DB_VERSION_MAJOR < 2
304 i = (*up->udb_dbp->seq)(up->udb_dbp, &key, &info, R_NEXT);
305 # else /* DB_VERSION_MAJOR < 2 */
307 if ((errno = dbc->c_get(dbc, &key,
308 &info, DB_NEXT)) != 0)
310 # endif /* DB_VERSION_MAJOR < 2 */
313 # if DB_VERSION_MAJOR > 1
316 (void) dbc->c_close(dbc);
319 # endif /* DB_VERSION_MAJOR > 1 */
321 /* if nothing ever matched, try next database */
325 message("expanded to %s", user);
327 sm_syslog(LOG_INFO, e->e_id,
328 "expand %.100s => %s",
330 shortenstring(user, MAXSHORTSTR));
331 naddrs = sendtolist(user, a, sendq, aliaslevel + 1, e);
332 if (naddrs > 0 && !bitset(QSELFREF, a->q_flags))
336 sm_dprintf("udbexpand: QS_EXPANDED ");
337 printaddr(sm_debug_file(), a, false);
339 a->q_state = QS_EXPANDED;
343 syserr("udbexpand: db-get %.*s stat %d",
344 (int) key.size, (char *) key.data, i);
349 ** If this address has a -request address, reflect
350 ** it into the envelope.
353 memset(&key, '\0', sizeof key);
354 memset(&info, '\0', sizeof info);
355 (void) sm_strlcpyn(keybuf, sizeof keybuf, 2, a->q_user,
357 keylen = strlen(keybuf);
361 # if DB_VERSION_MAJOR < 2
362 i = (*up->udb_dbp->get)(up->udb_dbp, &key, &info, 0);
363 # else /* DB_VERSION_MAJOR < 2 */
364 i = errno = (*up->udb_dbp->get)(up->udb_dbp, NULL,
366 # endif /* DB_VERSION_MAJOR < 2 */
367 if (i != 0 || info.size <= 0)
369 a->q_owner = sm_rpool_malloc_x(e->e_rpool,
371 memmove(a->q_owner, info.data, info.size);
372 a->q_owner[info.size] = '\0';
374 /* announce delivery; NORECEIPT bit set later */
375 if (e->e_xfp != NULL)
377 (void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT,
378 "Message delivered to mailing list %s\n",
381 e->e_flags |= EF_SENDRECEIPT;
382 a->q_flags |= QDELIVERED|QEXPANDED;
391 sm_dprintf("udbexpand: trying %s (%d) via hesiod\n",
393 /* look up the key via hesiod */
394 i = hes_udb_get(&key, &info);
397 syserr("udbexpand: hesiod-get %.*s stat %d",
398 (int) key.size, (char *) key.data, i);
401 else if (i > 0 || info.size <= 0)
404 struct hes_postoffice *hp;
405 # endif /* HES_GETMAILHOST */
408 sm_dprintf("udbexpand: no match on %s (%d)\n",
409 (char *) keybuf, (int) keylen);
412 sm_dprintf(" ... trying hes_getmailhost(%s)\n",
414 hp = hes_getmailhost(a->q_user);
417 if (hes_error() == HES_ER_NET)
419 syserr("udbexpand: hesiod-getmail %s stat %d",
420 a->q_user, hes_error());
424 sm_dprintf("hes_getmailhost(%s): %d\n",
425 a->q_user, hes_error());
428 if (strlen(hp->po_name) + strlen(hp->po_host) >
432 sm_dprintf("hes_getmailhost(%s): expansion too long: %.30s@%.30s\n",
439 (void) sm_snprintf(pobuf, sizeof pobuf,
440 "%s@%s", hp->po_name, hp->po_host);
441 info.size = strlen(info.data);
442 # else /* HES_GETMAILHOST */
444 # endif /* HES_GETMAILHOST */
447 sm_dprintf("udbexpand: match %.*s: %.*s\n",
448 (int) key.size, (char *) key.data,
449 (int) info.size, (char *) info.data);
450 a->q_flags &= ~QSELFREF;
452 if (bitset(EF_VRFYONLY, e->e_flags))
454 a->q_state = QS_VERIFIED;
459 if (info.size >= usersize)
460 user = sm_malloc_x(info.size + 1);
461 memmove(user, info.data, info.size);
462 user[info.size] = '\0';
464 message("hesioded to %s", user);
466 sm_syslog(LOG_INFO, e->e_id,
467 "hesiod %.100s => %s",
469 shortenstring(user, MAXSHORTSTR));
470 naddrs = sendtolist(user, a, sendq, aliaslevel + 1, e);
472 if (naddrs > 0 && !bitset(QSELFREF, a->q_flags))
476 sm_dprintf("udbexpand: QS_EXPANDED ");
477 printaddr(sm_debug_file(), a, false);
479 a->q_state = QS_EXPANDED;
483 ** If this address has a -request address, reflect
484 ** it into the envelope.
487 (void) sm_strlcpyn(keybuf, sizeof keybuf, 2, a->q_user,
489 keylen = strlen(keybuf);
492 i = hes_udb_get(&key, &info);
493 if (i != 0 || info.size <= 0)
495 a->q_owner = sm_rpool_malloc_x(e->e_rpool,
497 memmove(a->q_owner, info.data, info.size);
498 a->q_owner[info.size] = '\0';
503 /* not yet implemented */
507 if (bitset(EF_VRFYONLY, e->e_flags))
509 a->q_state = QS_VERIFIED;
512 i = strlen(up->udb_fwdhost) + strlen(a->q_user) + 1;
516 user = sm_malloc_x(usersize);
518 (void) sm_strlcpyn(user, usersize, 3,
519 a->q_user, "@", up->udb_fwdhost);
520 message("expanded to %s", user);
521 a->q_flags &= ~QSELFREF;
522 naddrs = sendtolist(user, a, sendq, aliaslevel + 1, e);
523 if (naddrs > 0 && !bitset(QSELFREF, a->q_flags))
527 sm_dprintf("udbexpand: QS_EXPANDED ");
528 printaddr(sm_debug_file(), a, false);
530 a->q_state = QS_EXPANDED;
540 /* unknown entry type */
543 /* XXX if an exception occurs, there is a storage leak */
545 sm_free(user); /* XXX */
550 ** UDBSENDER -- return canonical external name of sender, given local name
553 ** sender -- the name of the sender on the local machine.
554 ** rpool -- resource pool from which to allocate result
557 ** The external name for this sender, if derivable from the
558 ** database. Storage allocated from rpool.
559 ** NULL -- if nothing is changed from the database.
566 udbsender(sender, rpool)
570 return udbmatch(sender, "mailname", rpool);
573 ** UDBMATCH -- match user in field, return result of lookup.
576 ** user -- the name of the user.
577 ** field -- the field to lookup.
578 ** rpool -- resource pool from which to allocate result
581 ** The external name for this sender, if derivable from the
582 ** database. Storage allocated from rpool.
583 ** NULL -- if nothing is changed from the database.
590 udbmatch(user, field, rpool)
596 register struct udbent *up;
600 char keybuf[MAXUDBKEY];
603 sm_dprintf("udbmatch(%s, %s)\n", user, field);
607 if (_udbx_init(CurEnv) == EX_TEMPFAIL)
611 /* short circuit if no spec */
612 if (UdbSpec == NULL || UdbSpec[0] == '\0')
615 /* short circuit name begins with '\\' since it can't possibly match */
619 /* long names can never match and are a pain to deal with */
621 if (i < sizeof "maildrop")
622 i = sizeof "maildrop";
623 if ((strlen(user) + i) > sizeof keybuf - 4)
626 /* names beginning with colons indicate metadata */
630 /* build database key */
631 (void) sm_strlcpyn(keybuf, sizeof keybuf, 3, user, ":", field);
632 keylen = strlen(keybuf);
634 for (up = UdbEnts; up->udb_type != UDB_EOLIST; up++)
637 ** Select action based on entry type.
640 switch (up->udb_type)
644 memset(&key, '\0', sizeof key);
645 memset(&info, '\0', sizeof info);
648 # if DB_VERSION_MAJOR < 2
649 i = (*up->udb_dbp->get)(up->udb_dbp, &key, &info, 0);
650 # else /* DB_VERSION_MAJOR < 2 */
651 i = errno = (*up->udb_dbp->get)(up->udb_dbp, NULL,
653 # endif /* DB_VERSION_MAJOR < 2 */
654 if (i != 0 || info.size <= 0)
657 sm_dprintf("udbmatch: no match on %s (%d) via db\n",
662 p = sm_rpool_malloc_x(rpool, info.size + 1);
663 memmove(p, info.data, info.size);
666 sm_dprintf("udbmatch ==> %s\n", p);
674 i = hes_udb_get(&key, &info);
675 if (i != 0 || info.size <= 0)
678 sm_dprintf("udbmatch: no match on %s (%d) via hesiod\n",
683 p = sm_rpool_malloc_x(rpool, info.size + 1);
684 memmove(p, info.data, info.size);
687 sm_dprintf("udbmatch ==> %s\n", p);
693 if (strcmp(field, "mailname") != 0)
697 ** Nothing yet. Search again for a default case. But only
698 ** use it if we also have a forward (:maildrop) pointer already
702 /* build database key */
703 (void) sm_strlcpyn(keybuf, sizeof keybuf, 2, user, ":maildrop");
704 keylen = strlen(keybuf);
706 for (up = UdbEnts; up->udb_type != UDB_EOLIST; up++)
708 switch (up->udb_type)
712 /* get the default case for this database */
713 if (up->udb_default == NULL)
715 memset(&key, '\0', sizeof key);
716 memset(&info, '\0', sizeof info);
717 key.data = ":default:mailname";
718 key.size = strlen(key.data);
719 # if DB_VERSION_MAJOR < 2
720 i = (*up->udb_dbp->get)(up->udb_dbp,
722 # else /* DB_VERSION_MAJOR < 2 */
723 i = errno = (*up->udb_dbp->get)(up->udb_dbp,
726 # endif /* DB_VERSION_MAJOR < 2 */
727 if (i != 0 || info.size <= 0)
729 /* no default case */
730 up->udb_default = "";
734 /* save the default case */
735 up->udb_default = sm_pmalloc_x(info.size + 1);
736 memmove(up->udb_default, info.data, info.size);
737 up->udb_default[info.size] = '\0';
739 else if (up->udb_default[0] == '\0')
742 /* we have a default case -- verify user:maildrop */
743 memset(&key, '\0', sizeof key);
744 memset(&info, '\0', sizeof info);
747 # if DB_VERSION_MAJOR < 2
748 i = (*up->udb_dbp->get)(up->udb_dbp, &key, &info, 0);
749 # else /* DB_VERSION_MAJOR < 2 */
750 i = errno = (*up->udb_dbp->get)(up->udb_dbp, NULL,
752 # endif /* DB_VERSION_MAJOR < 2 */
753 if (i != 0 || info.size <= 0)
755 /* nope -- no aliasing for this user */
759 /* they exist -- build the actual address */
760 i = strlen(user) + strlen(up->udb_default) + 2;
761 p = sm_rpool_malloc_x(rpool, i);
762 (void) sm_strlcpyn(p, i, 3, user, "@", up->udb_default);
764 sm_dprintf("udbmatch ==> %s\n", p);
770 /* get the default case for this database */
771 if (up->udb_default == NULL)
773 key.data = ":default:mailname";
774 key.size = strlen(key.data);
775 i = hes_udb_get(&key, &info);
777 if (i != 0 || info.size <= 0)
779 /* no default case */
780 up->udb_default = "";
784 /* save the default case */
785 up->udb_default = sm_pmalloc_x(info.size + 1);
786 memmove(up->udb_default, info.data, info.size);
787 up->udb_default[info.size] = '\0';
789 else if (up->udb_default[0] == '\0')
792 /* we have a default case -- verify user:maildrop */
795 i = hes_udb_get(&key, &info);
796 if (i != 0 || info.size <= 0)
798 /* nope -- no aliasing for this user */
802 /* they exist -- build the actual address */
803 i = strlen(user) + strlen(up->udb_default) + 2;
804 p = sm_rpool_malloc_x(rpool, i);
805 (void) sm_strlcpyn(p, i, 3, user, "@", up->udb_default);
807 sm_dprintf("udbmatch ==> %s\n", p);
814 /* still nothing.... too bad */
818 ** UDB_MAP_LOOKUP -- look up arbitrary entry in user database map
821 ** map -- the map being queried.
822 ** name -- the name to look up.
823 ** av -- arguments to the map lookup.
824 ** statp -- to get any error status.
827 ** NULL if name not found in map.
828 ** The rewritten name otherwise.
833 udb_map_lookup(map, name, av, statp)
841 char *SM_NONVOLATILE result = NULL;
842 char keybuf[MAXNAME + 1];
844 if (tTd(28, 20) || tTd(38, 20))
845 sm_dprintf("udb_map_lookup(%s, %s)\n", map->map_mname, name);
847 if (bitset(MF_NOFOLDCASE, map->map_mflags))
853 int keysize = strlen(name);
855 if (keysize > sizeof keybuf - 1)
856 keysize = sizeof keybuf - 1;
857 memmove(keybuf, name, keysize);
858 keybuf[keysize] = '\0';
862 val = udbmatch(key, map->map_file, NULL);
866 if (bitset(MF_MATCHONLY, map->map_mflags))
867 result = map_rewrite(map, name, strlen(name), NULL);
869 result = map_rewrite(map, val, strlen(val), av);
876 ** _UDBX_INIT -- parse the UDB specification, opening any valid entries.
879 ** e -- the current envelope.
882 ** EX_TEMPFAIL -- if it appeared it couldn't get hold of a
883 ** database due to a host being down or some similar
884 ** (recoverable) situation.
885 ** EX_OK -- otherwise.
888 ** Fills in the UdbEnts structure from UdbSpec.
891 # define MAXUDBOPTS 27
899 register struct udbent *up;
904 # ifdef UDB_DEFAULT_SPEC
906 UdbSpec = UDB_DEFAULT_SPEC;
907 # endif /* UDB_DEFAULT_SPEC */
915 struct udb_option opts[MAXUDBOPTS + 1];
917 while (*p == ' ' || *p == '\t' || *p == ',')
926 if (ents >= MAXUDBENT)
928 syserr("Maximum number of UDB entries exceeded");
932 /* extract options */
933 (void) _udb_parsespec(spec, opts, MAXUDBOPTS);
936 ** Decode database specification.
938 ** In the sendmail tradition, the leading character
939 ** defines the semantics of the rest of the entry.
941 ** @hostname -- forward email to the indicated host.
942 ** This should be the last in the list,
943 ** since it always matches the input.
944 ** /dbname -- search the named database on the local
945 ** host using the Berkeley db package.
946 ** Hesiod -- search the named database with BIND
947 ** using the MIT Hesiod package.
952 case '@': /* forward to remote host */
953 up->udb_type = UDB_FORWARD;
954 up->udb_pid = CurrentPid;
955 up->udb_fwdhost = spec + 1;
961 case 'h': /* use hesiod */
963 if (sm_strcasecmp(spec, "hesiod") != 0)
965 up->udb_type = UDB_HESIOD;
966 up->udb_pid = CurrentPid;
973 case '/': /* look up remote name */
975 if (l > 3 && strcmp(&spec[l - 3], ".db") == 0)
977 up->udb_dbname = spec;
981 up->udb_dbname = sm_pmalloc_x(l + 4);
982 (void) sm_strlcpyn(up->udb_dbname, l + 4, 2,
986 # if DB_VERSION_MAJOR < 2
987 up->udb_dbp = dbopen(up->udb_dbname, O_RDONLY,
988 0644, DB_BTREE, NULL);
989 # else /* DB_VERSION_MAJOR < 2 */
991 int flags = DB_RDONLY;
992 # if DB_VERSION_MAJOR > 2
994 # endif /* DB_VERSION_MAJOR > 2 */
996 SM_DB_FLAG_ADD(flags);
998 # if DB_VERSION_MAJOR > 2
999 ret = db_create(&up->udb_dbp, NULL, 0);
1002 (void) up->udb_dbp->close(up->udb_dbp,
1008 ret = up->udb_dbp->open(up->udb_dbp,
1017 #ifdef DB_OLD_VERSION
1018 if (ret == DB_OLD_VERSION)
1020 #endif /* DB_OLD_VERSION */
1021 (void) up->udb_dbp->close(up->udb_dbp, 0);
1026 # else /* DB_VERSION_MAJOR > 2 */
1027 errno = db_open(up->udb_dbname, DB_BTREE,
1029 NULL, &up->udb_dbp);
1030 # endif /* DB_VERSION_MAJOR > 2 */
1032 # endif /* DB_VERSION_MAJOR < 2 */
1033 if (up->udb_dbp == NULL)
1037 int save_errno = errno;
1039 # if DB_VERSION_MAJOR < 2
1040 sm_dprintf("dbopen(%s): %s\n",
1041 # else /* DB_VERSION_MAJOR < 2 */
1042 sm_dprintf("db_open(%s): %s\n",
1043 # endif /* DB_VERSION_MAJOR < 2 */
1045 sm_errstring(errno));
1048 if (errno != ENOENT && errno != EACCES)
1051 sm_syslog(LOG_ERR, e->e_id,
1052 # if DB_VERSION_MAJOR < 2
1054 # else /* DB_VERSION_MAJOR < 2 */
1056 # endif /* DB_VERSION_MAJOR < 2 */
1058 sm_errstring(errno));
1059 up->udb_type = UDB_EOLIST;
1060 if (up->udb_dbname != spec)
1061 sm_free(up->udb_dbname); /* XXX */
1064 if (up->udb_dbname != spec)
1065 sm_free(up->udb_dbname); /* XXX */
1070 # if DB_VERSION_MAJOR < 2
1071 sm_dprintf("_udbx_init: dbopen(%s)\n",
1072 # else /* DB_VERSION_MAJOR < 2 */
1073 sm_dprintf("_udbx_init: db_open(%s)\n",
1074 # endif /* DB_VERSION_MAJOR < 2 */
1077 up->udb_type = UDB_DBFETCH;
1078 up->udb_pid = CurrentPid;
1087 # endif /* HESIOD */
1088 syserr("Unknown UDB spec %s", spec);
1092 up->udb_type = UDB_EOLIST;
1096 for (up = UdbEnts; up->udb_type != UDB_EOLIST; up++)
1098 switch (up->udb_type)
1101 sm_dprintf("REMOTE: addr %s, timeo %d\n",
1102 anynet_ntoa((SOCKADDR *) &up->udb_addr),
1108 sm_dprintf("FETCH: file %s\n",
1111 sm_dprintf("FETCH\n");
1116 sm_dprintf("FORWARD: host %s\n",
1121 sm_dprintf("HESIOD\n");
1125 sm_dprintf("UNKNOWN\n");
1131 UdbInitialized = true;
1136 ** On temporary failure, back out anything we've already done
1141 for (up = UdbEnts; up->udb_type != UDB_EOLIST; up++)
1143 if (up->udb_type == UDB_DBFETCH)
1145 # if DB_VERSION_MAJOR < 2
1146 (*up->udb_dbp->close)(up->udb_dbp);
1147 # else /* DB_VERSION_MAJOR < 2 */
1148 errno = (*up->udb_dbp->close)(up->udb_dbp, 0);
1149 # endif /* DB_VERSION_MAJOR < 2 */
1151 sm_dprintf("_udbx_init: db->close(%s)\n",
1160 _udb_parsespec(udbspec, opt, maxopts)
1162 struct udb_option opt[];
1165 register char *spec;
1166 register char *spec_end;
1167 register int optnum;
1169 spec_end = strchr(udbspec, ':');
1170 for (optnum = 0; optnum < maxopts && (spec = spec_end) != NULL; optnum++)
1174 while (isascii(*spec) && isspace(*spec))
1176 spec_end = strchr(spec, ':');
1177 if (spec_end != NULL)
1180 opt[optnum].udbo_name = spec;
1181 opt[optnum].udbo_val = NULL;
1182 p = strchr(spec, '=');
1184 opt[optnum].udbo_val = ++p;
1189 ** _UDBX_CLOSE -- close all file based UDB entries.
1202 if (!UdbInitialized)
1205 for (up = UdbEnts; up->udb_type != UDB_EOLIST; up++)
1207 if (up->udb_pid != CurrentPid)
1211 if (up->udb_type == UDB_DBFETCH)
1213 # if DB_VERSION_MAJOR < 2
1214 (*up->udb_dbp->close)(up->udb_dbp);
1215 # else /* DB_VERSION_MAJOR < 2 */
1216 errno = (*up->udb_dbp->close)(up->udb_dbp, 0);
1217 # endif /* DB_VERSION_MAJOR < 2 */
1220 sm_dprintf("_udbx_init: db->close(%s)\n",
1229 hes_udb_get(key, info)
1235 char kbuf[MAXUDBKEY + 1];
1237 if (sm_strlcpy(kbuf, key->data, sizeof kbuf) >= sizeof kbuf)
1240 type = strrchr(name, ':');
1244 if (strchr(name, '@') != NULL)
1248 sm_dprintf("hes_udb_get(%s, %s)\n", name, type);
1250 /* make the hesiod query */
1252 if (HesiodContext == NULL && hesiod_init(&HesiodContext) != 0)
1254 hp = hesiod_resolve(HesiodContext, name, type);
1255 # else /* HESIOD_INIT */
1256 hp = hes_resolve(name, type);
1257 # endif /* HESIOD_INIT */
1264 hesiod_free_list(HesiodContext, hp);
1265 if (errno == ECONNREFUSED || errno == EMSGSIZE)
1269 # else /* HESIOD_INIT */
1270 if (hp == NULL || hp[0] == NULL)
1272 /* network problem or timeout */
1273 if (hes_error() == HES_ER_NET)
1278 # endif /* HESIOD_INIT */
1282 ** If there are multiple matches, just return the
1285 ** XXX These should really be returned; for example,
1286 ** XXX it is legal for :maildrop to be multi-valued.
1290 info->size = (size_t) strlen(info->data);
1294 sm_dprintf("hes_udb_get => %s\n", *hp);
1298 # endif /* HESIOD */
1303 udbexpand(a, sendq, aliaslevel, e)