fixes for user database and new config files
authorEric Allman <eric@ucbvax.Berkeley.EDU>
Sat, 12 Oct 1991 04:46:11 +0000 (20:46 -0800)
committerEric Allman <eric@ucbvax.Berkeley.EDU>
Sat, 12 Oct 1991 04:46:11 +0000 (20:46 -0800)
SCCS-vsn: usr.sbin/sendmail/src/recipient.c 5.22
SCCS-vsn: usr.sbin/sendmail/src/version.c 5.78
SCCS-vsn: usr.sbin/sendmail/src/sendmail.h 5.23
SCCS-vsn: usr.sbin/sendmail/src/readcf.c 5.29
SCCS-vsn: usr.sbin/sendmail/src/deliver.c 5.45
SCCS-vsn: usr.sbin/sendmail/src/udb.c 5.3

usr/src/usr.sbin/sendmail/src/deliver.c
usr/src/usr.sbin/sendmail/src/readcf.c
usr/src/usr.sbin/sendmail/src/recipient.c
usr/src/usr.sbin/sendmail/src/sendmail.h
usr/src/usr.sbin/sendmail/src/udb.c
usr/src/usr.sbin/sendmail/src/version.c

index 03cf7db..c65bacc 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)deliver.c  5.44 (Berkeley) %G%";
+static char sccsid[] = "@(#)deliver.c  5.45 (Berkeley) %G%";
 #endif /* not lint */
 
 #include "sendmail.h"
 #endif /* not lint */
 
 #include "sendmail.h"
@@ -377,7 +377,7 @@ deliver(e, firstto)
 #ifdef NAMED_BIND
                if (host[0] && host[0] != '[')
                {
 #ifdef NAMED_BIND
                if (host[0] && host[0] != '[')
                {
-                       expand("\001w", buf, &buf[sizeof(buf) - 1], e);
+                       expand("\001j", buf, &buf[sizeof(buf) - 1], e);
                        Nmx = getmxrr(host, MxHosts, buf, &rcode);
                }
                else
                        Nmx = getmxrr(host, MxHosts, buf, &rcode);
                }
                else
index be1471b..337081e 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)readcf.c   5.28 (Berkeley) %G%";
+static char sccsid[] = "@(#)readcf.c   5.29 (Berkeley) %G%";
 #endif /* not lint */
 
 # include "sendmail.h"
 #endif /* not lint */
 
 # include "sendmail.h"
@@ -839,7 +839,7 @@ setoption(opt, val, sticky)
                break;
 
          case 'U':             /* location of user database */
                break;
 
          case 'U':             /* location of user database */
-               UdbFileName = newstr(val);
+               UdbSpec = newstr(val);
                break;
 
          case 'u':             /* set default uid */
                break;
 
          case 'u':             /* set default uid */
index c7fa91f..ccbf26e 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)recipient.c        5.21 (Berkeley) %G%";
+static char sccsid[] = "@(#)recipient.c        5.22 (Berkeley) %G%";
 #endif /* not lint */
 
 # include <sys/types.h>
 #endif /* not lint */
 
 # include <sys/types.h>
@@ -326,7 +326,7 @@ recipient(a, sendq)
 
 # ifdef USERDB
                        /* if not  aliased, look it up in the user database */
 
 # ifdef USERDB
                        /* if not  aliased, look it up in the user database */
-                       if (!bitset(QDONTSEND, a->q_flags))
+                       if (!bitset(QDONTSEND|QNOTREMOTE, a->q_flags))
                                udbexpand(a, sendq);
 # endif
                }
                                udbexpand(a, sendq);
 # endif
                }
index 669b968..3c25f2b 100644 (file)
@@ -5,7 +5,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)sendmail.h  5.22 (Berkeley) %G%
+ *     @(#)sendmail.h  5.23 (Berkeley) %G%
  */
 
 /*
  */
 
 /*
@@ -15,7 +15,7 @@
 # ifdef _DEFINE
 # define EXTERN
 # ifndef lint
 # ifdef _DEFINE
 # define EXTERN
 # ifndef lint
-static char SmailSccsId[] =    "@(#)sendmail.h 5.22            %G%";
+static char SmailSccsId[] =    "@(#)sendmail.h 5.23            %G%";
 # endif lint
 # else  _DEFINE
 # define EXTERN extern
 # endif lint
 # else  _DEFINE
 # define EXTERN extern
@@ -555,7 +555,7 @@ EXTERN char *TrustedUsers[MAXTRUST+1];      /* list of trusted users */
 EXTERN char    *UserEnviron[MAXUSERENVIRON+1]; /* saved user environment */
 EXTERN int     CheckpointInterval;     /* queue file checkpoint interval */
 EXTERN bool    NoWildcardMX;   /* we don't have wildcard MX records */
 EXTERN char    *UserEnviron[MAXUSERENVIRON+1]; /* saved user environment */
 EXTERN int     CheckpointInterval;     /* queue file checkpoint interval */
 EXTERN bool    NoWildcardMX;   /* we don't have wildcard MX records */
-EXTERN char    *UdbFileName;   /* user database file name [udbexpand.c] */
+EXTERN char    *UdbSpec;       /* user database source spec [udbexpand.c] */
 EXTERN int     MaxHopCount;    /* number of hops until we give an error */
 EXTERN int     ConfigLevel;    /* config file level -- what does .cf expect? */
 \f/*
 EXTERN int     MaxHopCount;    /* number of hops until we give an error */
 EXTERN int     ConfigLevel;    /* config file level -- what does .cf expect? */
 \f/*
index b12b6c3..667597b 100644 (file)
@@ -7,7 +7,11 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid [] = "@(#)udb.c     5.2 (Berkeley) %G%";
+#ifdef USERDB
+static char sccsid [] = "@(#)udb.c     5.3 (Berkeley) %G% (with USERDB)";
+#else
+static char sccsid [] = "@(#)udb.c     5.3 (Berkeley) %G% (without USERDB)";
+#endif
 #endif
 
 #include "sendmail.h"
 #endif
 
 #include "sendmail.h"
@@ -15,6 +19,9 @@ static char sccsid [] = "@(#)udb.c    5.2 (Berkeley) %G%";
 #ifdef USERDB
 
 #include <sys/file.h>
 #ifdef USERDB
 
 #include <sys/file.h>
+#include <sys/time.h>
+#include <fcntl.h>
+#include <netdb.h>
 #include <db.h>
 
 /*
 #include <db.h>
 
 /*
@@ -31,6 +38,50 @@ static char sccsid [] = "@(#)udb.c   5.2 (Berkeley) %G%";
 **             Modifies sendq.
 */
 
 **             Modifies sendq.
 */
 
+struct udbent
+{
+       char    *udb_spec;              /* string version of spec */
+       int     udb_type;               /* type of entry */
+       union
+       {
+               /* type UE_REMOTE -- do remote call for lookup */
+               struct
+               {
+                       int             _udb_addrlen;   /* length of addr */
+                       struct sockaddr_in _udb_addr;   /* address */
+                       int             _udb_timeout;   /* timeout */
+               } udb_remote;
+#define udb_addrlen    udb_u.udb_remote._udb_addrlen
+#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 */
+               struct
+               {
+                       char    *_udb_fwdhost;  /* name of forward host */
+               } udb_forward;
+#define udb_fwdhost    udb_u.udb_forward._udb_fwdhost
+
+               /* type UE_LOOKUP -- lookup in local database */
+               struct
+               {
+                       char    *_udb_dbname;   /* pathname of database */
+                       DB      *_udb_dbp;      /* open database ptr */
+               } udb_lookup;
+#define udb_dbname     udb_u.udb_lookup._udb_dbname
+#define udb_dbp                udb_u.udb_lookup._udb_dbp
+       } udb_u;
+};
+
+#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 */
+
+
 void
 udbexpand(a, sendq)
        register ADDRESS *a;
 void
 udbexpand(a, sendq)
        register ADDRESS *a;
@@ -42,78 +93,210 @@ udbexpand(a, sendq)
        auto char *list;
        DBT key;
        DBT info;
        auto char *list;
        DBT key;
        DBT info;
-       static DB *dbp = NULL;
        register char *bp;
        register char *bp;
+       static bool firstcall = TRUE;
+       static int udbsock = -1;
+       bool breakout;
+       register struct udbent *up;
+       struct udbent udbents[MAXUDBENT + 1];
        char buf[8192];
 
        if (tTd(28, 1))
                printf("expand(%s)\n", a->q_paddr);
 
        /* make certain we are supposed to send to this address */
        char buf[8192];
 
        if (tTd(28, 1))
                printf("expand(%s)\n", a->q_paddr);
 
        /* make certain we are supposed to send to this address */
-       if (bitset(QDONTSEND, a->q_flags))
+       if (bitset(QDONTSEND, a->q_flags) ||
+           UdbSpec == NULL || UdbSpec[0] == '\0')
                return;
        CurEnv->e_to = a->q_paddr;
 
                return;
        CurEnv->e_to = a->q_paddr;
 
-       /* if necessary, open the database */
-       if (dbp == NULL)
+       /* on first call, locate the database */
+       if (firstcall)
        {
        {
-               if (UdbFileName == NULL || UdbFileName[0] == '\0')
+               firstcall = FALSE;
+               p = UdbSpec;
+               up = udbents;
+               for (;;)
                {
                {
-                       if (tTd(28, 4))
-                               printf("no userdb specified\n");
-                       return;
-               }
-               dbp = dbopen(UdbFileName, O_RDONLY, 0644, DB_HASH, NULL);
-               if (dbp == NULL)
-               {
-                       extern int errno;
+                       char *spec;
+                       auto int rcode;
+                       int nmx;
+                       char *mxhosts[MAXMXHOSTS + 1];
+
+                       while (*p == ' ' || *p == '\t' || *p == ',')
+                               p++;
+                       if (*p == '\0')
+                               break;
+                       spec = p;
+                       p = index(p, ',');
+                       if (*p != '\0')
+                               *p++ = '\0';
+                       switch (*spec)
+                       {
+                         case '*':     /* search remote database */
+                               expand("\001j", buf, &buf[sizeof(buf) - 1], CurEnv);
+                               nmx = getmxrr(spec + 1, mxhosts, buf, &rcode);
+                               for (i = 0; i < nmx; i++)
+                               {
+                                       register struct hostent *h;
 
 
-                       if (tTd(28, 2))
-                               printf("cannot open %s: %d\n", UdbFileName, errno);
-                       return;
+                                       h = gethostbyname(mxhosts[i]);
+                                       if (h == NULL)
+                                               continue;
+                                       up->udb_type = UDB_REMOTE;
+                                       up->udb_addr.sin_family = h->h_addrtype;
+                                       up->udb_addrlen = h->h_length;
+                                       bcopy(h->h_addr_list[0],
+                                             (char *) &up->udb_addr.sin_addr,
+                                             h->h_length);
+                                       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 '/':     /* look up remote name */
+                               up->udb_dbp = dbopen(spec, O_RDONLY, 0644, DB_BTREE, NULL);
+                               if (up->udb_dbp == NULL)
+                                       break;
+                               up->udb_type = UDB_LOOKUP;
+                               up++;
+                               break;
+                       }
                }
                }
+               up->udb_type = UDB_EOLIST;
        }
 
        }
 
-       key.data = a->q_user;
-       key.size = strlen(key.data);
-       i = dbp->get(dbp, &key, &info, R_NOOVERWRITE);
-       if (i != 0 || info.size <= 0)
+       breakout = FALSE;
+       for (up = udbents; !breakout; up++)
        {
        {
-               if (i < 0)
-                       syserr("udbexpand: db-get stat %s");
-               if (tTd(28, 2))
-                       printf("expand: no match on %s\n", key.data);
-               return;
-       }
+               char *user;
+               struct timeval timeout;
+               fd_set fdset;
 
 
-       /* extract the class (first string) and data (second string) */
-       i = strlen((char *) info.data) + 1;
-       p = (char *) info.data + i;
-       i = info.size - i;
+               /*
+               **  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.
+               */
 
 
-       /* use internal buffer if it will fit; otherwise malloc */
-       if (i < sizeof buf)
-               bp = buf;
-       else
-               bp = xalloc(i + 1);
-       bcopy(p, bp, i);
-       bp[i] = '\0';
+               switch (up->udb_type)
+               {
+                 case UDB_LOOKUP:
+                       key.data = a->q_user;
+                       key.size = strlen(key.data);
+                       i = (*up->udb_dbp->get)(up->udb_dbp, &key, &info, 0);
+                       if (i != 0 || info.size <= 0)
+                       {
+                               if (i < 0)
+                                       syserr("udbexpand: db-get stat %s");
+                               if (tTd(28, 2))
+                                       printf("expand: no match on %s\n", key.data);
+                               continue;
+                       }
 
 
-       if (tTd(28, 1))
-               printf("Class %s: %s\n", info.data, bp);
+                       /* extract the class (first string) and data (second string) */
+                       class = info.data;
+                       i = strlen((char *) info.data) + 1;
+                       p = (char *) info.data + i;
+                       i = info.size - i;
 
 
-       /* do special processing based on class */
-       if (strcmp((char *) info.data, "user") == 0)
-       {
-               message(Arpa_Info, "expanded to (%s) %s", info.data, bp);
-               AliasLevel++;
-               sendtolist(bp, a, sendq);
-               AliasLevel--;
+                       /* use internal buffer if it will fit; otherwise malloc */
+                       if (i < sizeof buf)
+                               user = buf;
+                       else
+                               user = xalloc(i + 1);
+                       bcopy(p, user, i);
+                       user[i] = '\0';
+                       break;
+
+                 case UDB_REMOTE:
+                       if (sendto(udbsock, a->q_user, strlen(a->q_user), 0,
+                                  (struct sockaddr *) &up->udb_addr,
+                                  up->udb_addrlen) < 0)
+                       {
+                               continue;
+                       }
+                       timeout.tv_sec = up->udb_timeout / 10;
+                       timeout.tv_usec = (up->udb_timeout % 10) * 100000;
+                       do
+                       {
+                               FD_ZERO(&fdset);
+                               FD_SET(udbsock, &fdset);
+                               i = select(FD_SETSIZE, &fdset, NULL, NULL, &timeout);
+                       } while (i > 0 && !FD_ISSET(udbsock, &fdset));
+                       if (i <= 0)
+                               continue;
+                       i = recvfrom(udbsock, buf, sizeof buf - 1, 0, NULL, NULL);
+                       if (i < 0)
+                               continue;
+                       class = buf;
+                       user = &buf[strlen(buf)];
+                       buf[i] = '\0';
+                       break;
+
+                 case UDB_FORWARD:
+                       class = "forward";
+                       i = strlen(up->udb_fwdhost) + strlen(a->q_user) + 1;
+                       if (i < sizeof buf)
+                               user = buf;
+                       else
+                               user = xalloc(i + 1);
+                       (void) sprintf(user, "%s@%s", a->q_user, up->udb_fwdhost);
+                       break;
+
+                 case UDB_EOLIST:
+                       breakout = TRUE;
+                       continue;
+
+                 default:
+                       /* unknown entry type */
+                       continue;
+               }
+
+               if (tTd(28, 1))
+                       printf("Class %s: %s\n", class, user);
+
+               /* do special processing based on class */
+               if (strcmp(class, "user") == 0 || strcmp(class, "forward") == 0)
+               {
+                       message(Arpa_Info, "expanded to (%s) %s", class, user);
+                       AliasLevel++;
+                       sendtolist(user, a, sendq);
+                       AliasLevel--;
+                       breakout = TRUE;
+               }
+
+               /* free memory if we allocated it */
+               if (up->udb_type == UDB_FORWARD || up->udb_type == UDB_LOOKUP)
+               {
+                       if (user != buf)
+                               free(user);
+               }
        }
        }
+}
 
 
-       /* free memory if we allocated it */
-       if (bp != buf)
-               free(bp);
+#else /* not USERDB */
+
+void
+udbexpand(a, sendq)
+       ADDRESS *a;
+       ADDRESS **sendq;
+{
+       return;
 }
 
 #endif /* USERDB */
 }
 
 #endif /* USERDB */
index 715f3f0..68f096d 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)version.c  5.77 (Berkeley) %G%";
+static char sccsid[] = "@(#)version.c  5.78 (Berkeley) %G%";
 #endif /* not lint */
 
 #endif /* not lint */
 
-char   Version[] = "5.77";
+char   Version[] = "5.78";