* Copyright (c) 1983 Eric P. Allman
* Copyright (c) 1988 Regents of the University of California.
* %sccs.include.redist.c%
static char sccsid
[] = "@(#)udb.c 5.10 (Berkeley) %G% (with USERDB)";
static char sccsid
[] = "@(#)udb.c 5.10 (Berkeley) %G% (without USERDB)";
** UDBEXPAND.C -- interface between sendmail and Berkeley User Data Base.
** This depends on the 4.4BSD db package.
char *udb_spec
; /* string version of spec */
int udb_type
; /* type of entry */
/* type UE_REMOTE -- do remote call for lookup */
struct sockaddr_in _udb_addr
; /* address */
int _udb_timeout
; /* timeout */
#define udb_addr udb_u.udb_remote._udb_addr
#define udb_timeout udb_u.udb_remote._udb_timeout
/* type UE_FORWARD -- forward message to remote */
char *_udb_fwdhost
; /* name of forward host */
#define udb_fwdhost udb_u.udb_forward._udb_fwdhost
/* type UE_LOOKUP -- lookup in local database */
char *_udb_dbname
; /* pathname of database */
DB
*_udb_dbp
; /* open database ptr */
#define udb_dbname udb_u.udb_lookup._udb_dbname
#define udb_dbp udb_u.udb_lookup._udb_dbp
#define UDB_EOLIST 0 /* end of list */
#define UDB_SKIP 1 /* skip this entry */
#define UDB_REMOTE 2 /* look up in remote database */
#define UDB_LOOKUP 3 /* look up in local database */
#define UDB_FORWARD 4 /* forward to remote host */
#define MAXUDBENT 10 /* maximum number of UDB entries */
** UDBEXPAND -- look up user in database and expand
** a -- address to expand.
** sendq -- pointer to head of sendq to put the expansions in.
struct udbent UdbEnts
[MAXUDBENT
+ 1];
static bool firstcall
= TRUE
;
register struct udbent
*up
;
printf("expand(%s)\n", a
->q_paddr
);
/* make certain we are supposed to send to this address */
if (bitset(QDONTSEND
, a
->q_flags
) ||
UdbSpec
== NULL
|| UdbSpec
[0] == '\0')
CurEnv
->e_to
= a
->q_paddr
;
/* on first call, locate the database */
extern void _udbx_init();
/* if name is too long, assume it won't match */
if (strlen(a
->q_user
) > sizeof keybuf
- 12)
/* if name begins with a colon, it indicates our metadata */
/* build actual database key */
(void) strcpy(keybuf
, a
->q_user
);
(void) strcat(keybuf
, ":maildrop");
for (up
= UdbEnts
; !breakout
; up
++)
** Select action based on entry type.
** On dropping out of this switch, "class" should
** explain the type of the data, and "user" should
** contain the user information.
i
= (*up
->udb_dbp
->seq
)(up
->udb_dbp
, &key
, &info
, R_CURSOR
);
if (i
!= 0 || info
.size
<= 0)
syserr("udbexpand: db-get stat %s");
printf("expand: no match on %s\n", keybuf
);
while (i
== 0 && key
.size
== keylen
&&
bcmp(key
.data
, keybuf
, keylen
) == 0)
if (info
.size
< sizeof buf
)
user
= xalloc(info
.size
+ 1);
bcopy(info
.data
, user
, info
.size
);
message(Arpa_Info
, "expanded to %s", user
);
sendtolist(user
, a
, sendq
);
/* get the next record */
i
= (*up
->udb_dbp
->seq
)(up
->udb_dbp
, &key
, &info
, R_NEXT
);
/* not yet implemented */
i
= strlen(up
->udb_fwdhost
) + strlen(a
->q_user
) + 1;
(void) sprintf(user
, "%s@%s", a
->q_user
, up
->udb_fwdhost
);
message(Arpa_Info
, "expanded to %s", user
);
sendtolist(user
, a
, sendq
);
register struct udbent
*up
;
register struct hostent
*h
;
char *mxhosts
[MAXMXHOSTS
+ 1];
struct option opts
[MAXUDBOPTS
+ 1];
while (*p
== ' ' || *p
== '\t' || *p
== ',')
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.
case '+': /* search remote database */
case '*': /* search remote database (expand MX) */
nmx
= getmxrr(spec
+ 1, mxhosts
, "", &rcode
);
printf("getmxrr(%s): %d", spec
+ 1, nmx
);
for (i
= 0; i
<= nmx
; i
++)
printf(" %s", mxhosts
[i
]);
for (i
= 0; i
< nmx
; i
++)
h
= gethostbyname(mxhosts
[i
]);
up
->udb_type
= UDB_REMOTE
;
up
->udb_addr
.sin_family
= h
->h_addrtype
;
(char *) &up
->udb_addr
.sin_addr
,
up
->udb_addr
.sin_port
= UdbPort
;
up
->udb_timeout
= UdbTimeout
;
/* set up a datagram socket */
UdbSock
= socket(AF_INET
, SOCK_DGRAM
, 0);
(void) fcntl(UdbSock
, F_SETFD
, 1);
case '@': /* forward to remote host */
up
->udb_type
= UDB_FORWARD
;
up
->udb_fwdhost
= spec
+ 1;
case '/': /* look up remote name */
up
->udb_dbp
= dbopen(spec
, O_RDONLY
, 0644, DB_BTREE
, NULL
);
up
->udb_type
= UDB_LOOKUP
;
up
->udb_type
= UDB_EOLIST
;
for (up
= UdbEnts
; ; up
++)
printf("REMOTE: addr %s, timeo %d\n",
inet_ntoa(up
->udb_addr
.sin_addr
),
printf("LOOKUP: file %s\n",
printf("FORWARD: host %s\n",
_udb_parsespec(udbspec
, opt
, maxopts
)
spec_end
= index(udbspec
, ':');
for (optnum
= 0; optnum
< maxopts
&& (spec
= spec_end
) != NULL
; optnum
++)
spec_end
= index(spec
, ':');