122694Sdist /* 235073Sbostic * Copyright (c) 1983 Eric P. Allman 333728Sbostic * Copyright (c) 1988 Regents of the University of California. 433728Sbostic * All rights reserved. 533728Sbostic * 642824Sbostic * %sccs.include.redist.c% 733728Sbostic */ 822694Sdist 950577Seric # include <sys/types.h> 1050577Seric # include <sys/stat.h> 1150577Seric # include <signal.h> 1250577Seric # include "sendmail.h" 1350577Seric # include <sys/file.h> 1450577Seric # include <pwd.h> 1551937Seric # ifdef LOCKF 1651937Seric # include <fcntl.h> 1751937Seric # endif 1850577Seric 1956845Seric # ifdef DBM 2056848Seric ERROR: DBM is no longer supported -- use NDBM instead. 2156845Seric # endif 2256845Seric 2350577Seric # ifdef NEWDB 2450577Seric # include <db.h> 2550577Seric # endif 2650577Seric 2756766Seric # ifdef NDBM 2856845Seric # include <ndbm.h> 2956766Seric # endif 3056766Seric 3133728Sbostic #ifndef lint 3251756Seric #ifdef NEWDB 33*57249Seric static char sccsid[] = "@(#)alias.c 5.44 (Berkeley) 12/21/92 (with NEWDB)"; 3451756Seric #else 3556845Seric #ifdef NDBM 36*57249Seric static char sccsid[] = "@(#)alias.c 5.44 (Berkeley) 12/21/92 (with NDBM)"; 3733728Sbostic #else 38*57249Seric static char sccsid[] = "@(#)alias.c 5.44 (Berkeley) 12/21/92 (without NDBM)"; 3933728Sbostic #endif 4050575Seric #endif 4133728Sbostic #endif /* not lint */ 4251756Seric /* 43292Seric ** ALIAS -- Compute aliases. 44292Seric ** 459368Seric ** Scans the alias file for an alias for the given address. 469368Seric ** If found, it arranges to deliver to the alias list instead. 479368Seric ** Uses libdbm database if -DDBM. 48292Seric ** 49292Seric ** Parameters: 504097Seric ** a -- address to alias. 514999Seric ** sendq -- a pointer to the head of the send queue 524999Seric ** to put the aliases in. 53292Seric ** 54292Seric ** Returns: 55292Seric ** none 56292Seric ** 57292Seric ** Side Effects: 583185Seric ** Aliases found are expanded. 59292Seric ** 60292Seric ** Notes: 61292Seric ** If NoAlias (the "-n" flag) is set, no aliasing is 62292Seric ** done. 63292Seric ** 64292Seric ** Deficiencies: 65292Seric ** It should complain about names that are aliased to 66292Seric ** nothing. 67292Seric */ 68292Seric 69292Seric 7053742Seric /* 7153742Seric ** Sun YP servers read the dbm files directly, so we have to build them 7253742Seric ** even if NEWDB 7353742Seric */ 7453742Seric 7556845Seric #ifdef NDBM 7653742Seric # ifndef NEWDB 7753742Seric # define IF_MAKEDBMFILES 7853742Seric # else 7953742Seric # ifdef YPCOMPAT 8053742Seric # define IF_MAKEDBMFILES if (makedbmfiles) 8153742Seric # endif 8253742Seric # endif 8353742Seric #endif 8453742Seric 8556845Seric typedef union 862966Seric { 8756845Seric #ifdef NDBM 8856845Seric datum dbm; 8951756Seric #endif 9056845Seric #ifdef NEWDB 9156845Seric DBT dbt; 9256845Seric #endif 9356845Seric struct 9456845Seric { 9556845Seric char *data; 9656845Seric int size; 9756845Seric } xx; 9856845Seric } DBdatum; 99292Seric 10050575Seric #ifdef NEWDB 10150575Seric static DB *AliasDBptr; 10250575Seric #endif 10356845Seric #ifdef NDBM 10456845Seric static DBM *AliasDBMptr; 10556845Seric #endif 10650575Seric 10755012Seric alias(a, sendq, e) 1084097Seric register ADDRESS *a; 1094999Seric ADDRESS **sendq; 11055012Seric register ENVELOPE *e; 111292Seric { 1124081Seric register char *p; 1135701Seric extern char *aliaslookup(); 114292Seric 1157671Seric if (tTd(27, 1)) 1164098Seric printf("alias(%s)\n", a->q_paddr); 117292Seric 1184098Seric /* don't realias already aliased names */ 1194098Seric if (bitset(QDONTSEND, a->q_flags)) 1204098Seric return; 1214098Seric 12255012Seric e->e_to = a->q_paddr; 1234098Seric 1244314Seric /* 1254314Seric ** Look up this name 1264314Seric */ 1274314Seric 12824944Seric if (NoAlias) 12924944Seric p = NULL; 13024944Seric else 13124944Seric p = aliaslookup(a->q_user); 1324098Seric if (p == NULL) 1334098Seric return; 134292Seric 135292Seric /* 1364098Seric ** Match on Alias. 1374098Seric ** Deliver to the target list. 1381515Seric */ 1391515Seric 1407671Seric if (tTd(27, 1)) 1414098Seric printf("%s (%s, %s) aliased to %s\n", 1424098Seric a->q_paddr, a->q_host, a->q_user, p); 1437051Seric message(Arpa_Info, "aliased to %s", p); 1444098Seric AliasLevel++; 14555012Seric sendtolist(p, a, sendq, e); 1464098Seric AliasLevel--; 1474098Seric } 1484098Seric /* 1495701Seric ** ALIASLOOKUP -- look up a name in the alias file. 1505701Seric ** 1515701Seric ** Parameters: 1525701Seric ** name -- the name to look up. 1535701Seric ** 1545701Seric ** Returns: 1555701Seric ** the value of name. 1565701Seric ** NULL if unknown. 1575701Seric ** 1585701Seric ** Side Effects: 1595701Seric ** none. 1605701Seric ** 1615701Seric ** Warnings: 1625701Seric ** The return value will be trashed across calls. 1635701Seric */ 1645701Seric 1655701Seric char * 1665701Seric aliaslookup(name) 1675701Seric char *name; 1685701Seric { 16956845Seric # if defined(NEWDB) || defined(NDBM) 17056845Seric DBdatum rhs, lhs; 17150575Seric int s; 1725701Seric 1735701Seric /* create a key for fetch */ 17456845Seric lhs.xx.data = name; 17556845Seric lhs.xx.size = strlen(name) + 1; 17650575Seric # ifdef NEWDB 17751756Seric if (AliasDBptr != NULL) 17851756Seric { 17956845Seric s = AliasDBptr->get(AliasDBptr, &lhs.dbt, &rhs.dbt, 0); 18051756Seric if (s == 0) 18156845Seric return (rhs.dbt.data); 18251756Seric } 18356845Seric # ifdef NDBM 184*57249Seric else if (AliasDBMptr != NULL) 18551756Seric { 18656845Seric rhs.dbm = dbm_fetch(AliasDBMptr, lhs.dbm); 18756845Seric return (rhs.dbm.dptr); 18851756Seric } 18956845Seric # endif /* NDBM */ 19056845Seric # else /* not NEWDB */ 19156845Seric rhs.dbm = dbm_fetch(AliasDBMptr, lhs.dbm); 19256845Seric return (rhs.dbm.dptr); 19356845Seric # endif /* NEWDB */ 19456845Seric # else /* neither NEWDB nor NDBM */ 1955701Seric register STAB *s; 1965701Seric 1975701Seric s = stab(name, ST_ALIAS, ST_FIND); 19851756Seric if (s != NULL) 19951756Seric return (s->s_alias); 20051756Seric # endif 20151756Seric return (NULL); 2025701Seric } 2035701Seric /* 2044098Seric ** INITALIASES -- initialize for aliasing 2054098Seric ** 20656845Seric ** Very different depending on whether we are running NDBM or not. 2074098Seric ** 2084098Seric ** Parameters: 2094098Seric ** aliasfile -- location of aliases. 21056845Seric ** init -- if set and if NDBM, initialize the NDBM files. 2114098Seric ** 2124098Seric ** Returns: 2134098Seric ** none. 2144098Seric ** 2154098Seric ** Side Effects: 2164098Seric ** initializes aliases: 21756845Seric ** if NDBM: opens the database. 21856845Seric ** if ~NDBM: reads the aliases into the symbol table. 2194098Seric */ 2204098Seric 22140559Sbostic # define DBMMODE 0644 2224157Seric 22355012Seric initaliases(aliasfile, init, e) 2244098Seric char *aliasfile; 2254157Seric bool init; 22655012Seric register ENVELOPE *e; 2274098Seric { 22856845Seric #if defined(NDBM) || defined(NEWDB) 2298437Seric int atcnt; 23025522Seric time_t modtime; 23125522Seric bool automatic = FALSE; 2324322Seric char buf[MAXNAME]; 23350575Seric #endif 2349368Seric struct stat stb; 23527176Seric static bool initialized = FALSE; 23646928Sbostic static int readaliases(); 2374322Seric 23827176Seric if (initialized) 23927176Seric return; 24027176Seric initialized = TRUE; 24127176Seric 24217984Seric if (aliasfile == NULL || stat(aliasfile, &stb) < 0) 2438437Seric { 24425522Seric if (aliasfile != NULL && init) 24525522Seric syserr("Cannot open %s", aliasfile); 2468437Seric NoAlias = TRUE; 24711937Seric errno = 0; 2488437Seric return; 2498437Seric } 2508437Seric 25156845Seric # if defined(NDBM) || defined(NEWDB) 2524322Seric /* 2538437Seric ** Check to see that the alias file is complete. 2548437Seric ** If not, we will assume that someone died, and it is up 2558437Seric ** to us to rebuild it. 2568437Seric */ 2578437Seric 25825689Seric if (!init) 25950575Seric { 26050575Seric # ifdef NEWDB 26150575Seric (void) strcpy(buf, aliasfile); 26250575Seric (void) strcat(buf, ".db"); 26351171Sbostic AliasDBptr = dbopen(buf, O_RDONLY, DBMMODE, DB_HASH, NULL); 26450576Seric if (AliasDBptr == NULL) 26550576Seric { 26656845Seric # ifdef NDBM 26756845Seric AliasDBMptr = dbm_open(aliasfile, O_RDONLY, DBMMODE); 268*57249Seric if (AliasDBMptr == NULL) 269*57249Seric { 270*57249Seric syserr("initaliases: cannot open %s", buf); 271*57249Seric NoAlias = TRUE; 272*57249Seric return; 273*57249Seric } 27451756Seric # else 27550576Seric syserr("initaliases: cannot open %s", buf); 27650576Seric NoAlias = TRUE; 27750576Seric return; 27851756Seric # endif 27950576Seric } 28050575Seric # else 28156845Seric AliasDBMptr = dbm_open(aliasfile, O_RDONLY, DBMMODE); 282*57249Seric if (AliasDBMptr == NULL) 283*57249Seric { 284*57249Seric syserr("initaliases: cannot open %s", buf); 285*57249Seric NoAlias = TRUE; 286*57249Seric return; 287*57249Seric } 28850575Seric # endif 28950575Seric } 29017471Seric atcnt = SafeAlias * 2; 29117471Seric if (atcnt > 0) 29217471Seric { 29317471Seric while (!init && atcnt-- >= 0 && aliaslookup("@") == NULL) 29425689Seric { 29525689Seric /* 29625689Seric ** Reinitialize alias file in case the new 29725689Seric ** one is mv'ed in instead of cp'ed in. 29825689Seric ** 29925689Seric ** Only works with new DBM -- old one will 30025689Seric ** just consume file descriptors forever. 30125689Seric ** If you have a dbmclose() it can be 30225689Seric ** added before the sleep(30). 30325689Seric */ 30425689Seric 30550575Seric # ifdef NEWDB 30651756Seric if (AliasDBptr != NULL) 30751756Seric AliasDBptr->close(AliasDBptr); 30850575Seric # endif 30956845Seric # ifdef NDBM 31056845Seric if (AliasDBMptr != NULL) 31156845Seric dbm_close(AliasDBMptr); 31256845Seric # endif 31350575Seric 31417471Seric sleep(30); 31550575Seric # ifdef NEWDB 31650575Seric (void) strcpy(buf, aliasfile); 31750575Seric (void) strcat(buf, ".db"); 31851171Sbostic AliasDBptr = 31951171Sbostic dbopen(buf, O_RDONLY, DBMMODE, DB_HASH, NULL); 32050576Seric if (AliasDBptr == NULL) 32150576Seric { 32251756Seric # ifdef NDBM 32356845Seric AliasDBMptr = dbm_open(aliasfile, O_RDONLY, DBMMODE); 32451756Seric # else 32550576Seric syserr("initaliases: cannot open %s", buf); 32650576Seric NoAlias = TRUE; 32750576Seric return; 32851756Seric # endif 32950576Seric } 33050575Seric # else 33125689Seric # ifdef NDBM 33256845Seric AliasDBMptr = dbm_open(aliasfile, O_RDONLY, DBMMODE); 333*57249Seric if (AliasDBMptr == NULL) 334*57249Seric { 335*57249Seric syserr("initaliases: cannot open %s", buf); 336*57249Seric NoAlias = TRUE; 337*57249Seric return; 338*57249Seric } 33950575Seric # endif 34050575Seric # endif 34125689Seric } 34217471Seric } 34317471Seric else 34417471Seric atcnt = 1; 3458437Seric 3468437Seric /* 34756845Seric ** See if the NDBM version of the file is out of date with 3484322Seric ** the text version. If so, go into 'init' mode automatically. 34940559Sbostic ** This only happens if our effective userid owns the DBM. 35040559Sbostic ** Note the unpalatable hack to see if the stat succeeded. 3514322Seric */ 3524322Seric 3534322Seric modtime = stb.st_mtime; 3544322Seric (void) strcpy(buf, aliasfile); 35550575Seric # ifdef NEWDB 35650575Seric (void) strcat(buf, ".db"); 35750575Seric # else 3584322Seric (void) strcat(buf, ".pag"); 35950575Seric # endif 3604322Seric stb.st_ino = 0; 36119039Seric if (!init && (stat(buf, &stb) < 0 || stb.st_mtime < modtime || atcnt < 0)) 3624322Seric { 36311937Seric errno = 0; 36440559Sbostic if (AutoRebuild && stb.st_ino != 0 && stb.st_uid == geteuid()) 3654322Seric { 3664322Seric init = TRUE; 36725522Seric automatic = TRUE; 3687051Seric message(Arpa_Info, "rebuilding alias database"); 36924944Seric #ifdef LOG 37024944Seric if (LogLevel >= 7) 37124944Seric syslog(LOG_INFO, "rebuilding alias database"); 37256795Seric #endif /* LOG */ 3734322Seric } 3744322Seric else 3754322Seric { 37619039Seric #ifdef LOG 37724944Seric if (LogLevel >= 7) 37824944Seric syslog(LOG_INFO, "alias database out of date"); 37956795Seric #endif /* LOG */ 3804322Seric message(Arpa_Info, "Warning: alias database out of date"); 3814322Seric } 3824322Seric } 3834322Seric 3844322Seric 3854322Seric /* 38656845Seric ** If necessary, load the NDBM file. 38756845Seric ** If running without NDBM, load the symbol table. 3884322Seric */ 3894322Seric 3904157Seric if (init) 3918437Seric { 39225522Seric #ifdef LOG 39325522Seric if (LogLevel >= 6) 39425522Seric { 39525522Seric extern char *username(); 39625522Seric 39725522Seric syslog(LOG_NOTICE, "alias database %srebuilt by %s", 39825522Seric automatic ? "auto" : "", username()); 39925522Seric } 40056795Seric #endif /* LOG */ 40155012Seric readaliases(aliasfile, TRUE, e); 4028437Seric } 40356845Seric # else /* NDBM */ 40455012Seric readaliases(aliasfile, init, e); 40556845Seric # endif /* NDBM */ 4064157Seric } 4074157Seric /* 4084157Seric ** READALIASES -- read and process the alias file. 4094157Seric ** 4104157Seric ** This routine implements the part of initaliases that occurs 4114157Seric ** when we are not going to use the DBM stuff. 4124157Seric ** 4134157Seric ** Parameters: 4144157Seric ** aliasfile -- the pathname of the alias file master. 41556845Seric ** init -- if set, initialize the NDBM stuff. 4164157Seric ** 4174157Seric ** Returns: 4184157Seric ** none. 4194157Seric ** 4204157Seric ** Side Effects: 4214157Seric ** Reads aliasfile into the symbol table. 4224157Seric ** Optionally, builds the .dir & .pag files. 4234157Seric */ 4244157Seric 4254157Seric static 42655012Seric readaliases(aliasfile, init, e) 4274157Seric char *aliasfile; 4284157Seric bool init; 42955012Seric register ENVELOPE *e; 4304157Seric { 4314098Seric register char *p; 4324098Seric char *rhs; 4334098Seric bool skipping; 4349368Seric int naliases, bytes, longest; 4359368Seric FILE *af; 43653742Seric bool makedbmfiles; 43740970Sbostic void (*oldsigint)(); 4384098Seric ADDRESS al, bl; 4394106Seric register STAB *s; 44050575Seric # ifdef NEWDB 44150575Seric DB *dbp; 44250575Seric # endif 44356845Seric # ifdef NDBM 44456845Seric DBM *dbmp; 44556845Seric # endif 44651937Seric # ifdef LOCKF 44751937Seric struct flock fld; 44851937Seric # endif 4499368Seric char line[BUFSIZ]; 4504098Seric 45151937Seric if ((af = fopen(aliasfile, "r+")) == NULL) 4521515Seric { 453*57249Seric if (init) 454*57249Seric syserr("Can't open %s", aliasfile); 455*57249Seric else if (tTd(27, 1)) 4564106Seric printf("Can't open %s\n", aliasfile); 4574098Seric errno = 0; 4584098Seric NoAlias++; 4594098Seric return; 4604098Seric } 4614314Seric 46256845Seric # if defined(NDBM) || defined(NEWDB) 46319784Seric /* see if someone else is rebuilding the alias file already */ 46451835Seric # ifdef LOCKF 46551937Seric fld.l_type = F_WRLCK; 46651937Seric fld.l_whence = fld.l_start = fld.l_len = 0; 46751937Seric if (fcntl(fileno(af), F_SETLK, &fld) < 0) 46851835Seric # else 46919784Seric if (flock(fileno(af), LOCK_EX | LOCK_NB) < 0 && errno == EWOULDBLOCK) 47051835Seric # endif 47119784Seric { 47219784Seric /* yes, they are -- wait until done and then return */ 47319784Seric message(Arpa_Info, "Alias file is already being rebuilt"); 47419784Seric if (OpMode != MD_INITALIAS) 47519784Seric { 47619784Seric /* wait for other rebuild to complete */ 47751835Seric # ifdef LOCKF 47851937Seric (void) fcntl(fileno(af), F_SETLKW, &fld); 47951835Seric # else 48019784Seric (void) flock(fileno(af), LOCK_EX); 48151835Seric # endif 48219784Seric } 48323108Seric (void) fclose(af); 48419784Seric errno = 0; 48519784Seric return; 48619784Seric } 48756845Seric # endif /* NDBM */ 48819784Seric 4894314Seric /* 49019784Seric ** If initializing, create the new DBM files. 49119784Seric */ 49219784Seric 49319784Seric if (init) 49419784Seric { 49519784Seric oldsigint = signal(SIGINT, SIG_IGN); 49651756Seric # ifdef NEWDB 49751756Seric (void) strcpy(line, aliasfile); 49851756Seric (void) strcat(line, ".db"); 49951756Seric dbp = dbopen(line, 50051756Seric O_RDWR|O_CREAT|O_TRUNC, DBMMODE, DB_HASH, NULL); 50151756Seric if (dbp == NULL) 50251756Seric { 50351756Seric syserr("readaliases: cannot create %s", line); 50451756Seric (void) signal(SIGINT, oldsigint); 50551756Seric return; 50651756Seric } 50753742Seric # endif 50853742Seric # ifdef IF_MAKEDBMFILES 50953742Seric # ifdef NEWDB 51053742Seric makedbmfiles = access("/var/yp/Makefile", R_OK) == 0; 51153742Seric # endif 51253742Seric IF_MAKEDBMFILES 51319784Seric { 51456845Seric dbmp = dbm_open(aliasfile, 51556845Seric O_RDWR|O_CREAT|O_TRUNC, DBMMODE); 51656845Seric if (dbmp == NULL) 51753742Seric { 51856845Seric syserr("readaliases: cannot create %s.{dir,pag}", 51956845Seric aliasfile); 52053742Seric (void) signal(SIGINT, oldsigint); 52153742Seric return; 52253742Seric } 52319784Seric } 52450575Seric # endif 52519784Seric } 52619784Seric 52719784Seric /* 5284314Seric ** Read and interpret lines 5294314Seric */ 5304314Seric 5319368Seric FileName = aliasfile; 5329368Seric LineNumber = 0; 5334322Seric naliases = bytes = longest = 0; 5344098Seric skipping = FALSE; 5354098Seric while (fgets(line, sizeof (line), af) != NULL) 5364098Seric { 5374322Seric int lhssize, rhssize; 5384322Seric 5399368Seric LineNumber++; 54056795Seric p = strchr(line, '\n'); 54125278Seric if (p != NULL) 54225278Seric *p = '\0'; 5434098Seric switch (line[0]) 5444098Seric { 5454098Seric case '#': 5464098Seric case '\0': 5474098Seric skipping = FALSE; 5484098Seric continue; 5494065Seric 5504098Seric case ' ': 5514098Seric case '\t': 5524098Seric if (!skipping) 5539368Seric syserr("Non-continuation line starts with space"); 5544098Seric skipping = TRUE; 5554097Seric continue; 5564098Seric } 5574098Seric skipping = FALSE; 5581874Seric 5594314Seric /* 5604314Seric ** Process the LHS 5614314Seric ** Find the final colon, and parse the address. 56216898Seric ** It should resolve to a local name -- this will 56316898Seric ** be checked later (we want to optionally do 56416898Seric ** parsing of the RHS first to maximize error 56516898Seric ** detection). 5664314Seric */ 5674314Seric 5684098Seric for (p = line; *p != '\0' && *p != ':' && *p != '\n'; p++) 5694097Seric continue; 57016898Seric if (*p++ != ':') 5714098Seric { 5729368Seric syserr("missing colon"); 5734097Seric continue; 5744098Seric } 57555012Seric if (parseaddr(line, &al, 1, ':', e) == NULL) 5764098Seric { 57716898Seric syserr("illegal alias name"); 57816898Seric continue; 5794098Seric } 58016898Seric loweraddr(&al); 5814314Seric 5824314Seric /* 5834314Seric ** Process the RHS. 5844314Seric ** 'al' is the internal form of the LHS address. 5854314Seric ** 'p' points to the text of the RHS. 5864314Seric */ 5874314Seric 5884098Seric rhs = p; 5894098Seric for (;;) 5904098Seric { 5914098Seric register char c; 5921515Seric 59325821Seric if (init && CheckAliases) 5944098Seric { 5954157Seric /* do parsing & compression of addresses */ 59625278Seric while (*p != '\0') 5974098Seric { 59825278Seric extern char *DelimChar; 59925278Seric 60025278Seric while (isspace(*p) || *p == ',') 6014157Seric p++; 60225278Seric if (*p == '\0') 60325278Seric break; 60455012Seric if (parseaddr(p, &bl, -1, ',', e) == NULL) 60525278Seric usrerr("%s... bad address", p); 60625278Seric p = DelimChar; 6074098Seric } 6084098Seric } 6094157Seric else 61015769Seric { 61116898Seric p = &p[strlen(p)]; 61216898Seric if (p[-1] == '\n') 61316898Seric *--p = '\0'; 61415769Seric } 6151515Seric 6164098Seric /* see if there should be a continuation line */ 6174106Seric c = fgetc(af); 6184106Seric if (!feof(af)) 6194314Seric (void) ungetc(c, af); 6204106Seric if (c != ' ' && c != '\t') 6214098Seric break; 6224098Seric 6234098Seric /* read continuation line */ 6244098Seric if (fgets(p, sizeof line - (p - line), af) == NULL) 6254098Seric break; 6269368Seric LineNumber++; 62757135Seric 62857135Seric /* check for line overflow */ 62957135Seric if (strchr(p, '\n') == NULL) 63057135Seric { 63157135Seric usrerr("alias too long"); 63257135Seric break; 63357135Seric } 6344098Seric } 63516898Seric if (al.q_mailer != LocalMailer) 63616898Seric { 63716898Seric syserr("cannot alias non-local names"); 63816898Seric continue; 63916898Seric } 6404314Seric 6414314Seric /* 6424314Seric ** Insert alias into symbol table or DBM file 6434314Seric */ 6444314Seric 64516898Seric lhssize = strlen(al.q_user) + 1; 6464322Seric rhssize = strlen(rhs) + 1; 6474322Seric 64856845Seric # if defined(NDBM) || defined(NEWDB) 6494157Seric if (init) 6504157Seric { 65156845Seric DBdatum key, content; 6524157Seric 65356845Seric key.xx.size = lhssize; 65456845Seric key.xx.data = al.q_user; 65556845Seric content.xx.size = rhssize; 65656845Seric content.xx.data = rhs; 65751756Seric # ifdef NEWDB 65856845Seric if (dbp->put(dbp, &key.dbt, &content.dbt, 0) != 0) 65950576Seric syserr("readaliases: db put (%s)", al.q_user); 66050575Seric # endif 66153742Seric # ifdef IF_MAKEDBMFILES 66253742Seric IF_MAKEDBMFILES 66356845Seric if (dbm_store(dbmp, key.dbm, content.dbm, DBM_REPLACE) != 0) 66456845Seric syserr("readaliases: dbm store (%s)", 66556845Seric al.q_user); 66653742Seric # endif 6674157Seric } 6684157Seric else 66956845Seric # endif /* NDBM */ 6704157Seric { 6714157Seric s = stab(al.q_user, ST_ALIAS, ST_ENTER); 6724157Seric s->s_alias = newstr(rhs); 6734157Seric } 6744322Seric 6754322Seric /* statistics */ 6764322Seric naliases++; 6774322Seric bytes += lhssize + rhssize; 6784322Seric if (rhssize > longest) 6794322Seric longest = rhssize; 6801515Seric } 68119784Seric 68256845Seric # if defined(NDBM) || defined(NEWDB) 68319784Seric if (init) 68419784Seric { 68519784Seric /* add the distinquished alias "@" */ 68656845Seric DBdatum key; 68719784Seric 68856845Seric key.xx.size = 2; 68956845Seric key.xx.data = "@"; 69050575Seric # ifdef NEWDB 69150576Seric if (dbp->sync(dbp) != 0 || 69256845Seric dbp->put(dbp, &key.dbt, &key.dbt, 0) != 0 || 69350576Seric dbp->close(dbp) != 0) 69450576Seric syserr("readaliases: db close failure"); 69553742Seric # endif 69656789Seric # ifdef IF_MAKEDBMFILES 69756793Seric IF_MAKEDBMFILES 69856845Seric { 69956845Seric if (dbm_store(dbmp, key.dbm, key.dbm, DBM_REPLACE) != 0 || 70056845Seric dbm_error(dbmp)) 70156845Seric syserr("readaliases: dbm close failure"); 70256845Seric dbm_close(dbmp); 70356845Seric } 70450575Seric # endif 70519784Seric 70619784Seric /* restore the old signal */ 70719784Seric (void) signal(SIGINT, oldsigint); 70819784Seric } 70956845Seric # endif /* NDBM */ 71019784Seric 71119784Seric /* closing the alias file drops the lock */ 7124098Seric (void) fclose(af); 71355012Seric e->e_to = NULL; 7149368Seric FileName = NULL; 7157051Seric message(Arpa_Info, "%d aliases, longest %d bytes, %d bytes total", 7164322Seric naliases, longest, bytes); 71724944Seric # ifdef LOG 71824944Seric if (LogLevel >= 8) 71924944Seric syslog(LOG_INFO, "%d aliases, longest %d bytes, %d bytes total", 72024944Seric naliases, longest, bytes); 72156795Seric # endif /* LOG */ 722292Seric } 723292Seric /* 724292Seric ** FORWARD -- Try to forward mail 725292Seric ** 726292Seric ** This is similar but not identical to aliasing. 727292Seric ** 728292Seric ** Parameters: 7294314Seric ** user -- the name of the user who's mail we would like 7304314Seric ** to forward to. It must have been verified -- 7314314Seric ** i.e., the q_home field must have been filled 7324314Seric ** in. 7334999Seric ** sendq -- a pointer to the head of the send queue to 7344999Seric ** put this user's aliases in. 735292Seric ** 736292Seric ** Returns: 7374098Seric ** none. 738292Seric ** 739292Seric ** Side Effects: 7403185Seric ** New names are added to send queues. 741292Seric */ 742292Seric 74355012Seric forward(user, sendq, e) 7442966Seric ADDRESS *user; 7454999Seric ADDRESS **sendq; 74655012Seric register ENVELOPE *e; 747292Seric { 74857136Seric char *pp; 74957136Seric char *ep; 7504536Seric extern bool safefile(); 7514069Seric 7527671Seric if (tTd(27, 1)) 7534098Seric printf("forward(%s)\n", user->q_paddr); 7544098Seric 7554594Seric if (user->q_mailer != LocalMailer || bitset(QBADADDR, user->q_flags)) 7564098Seric return; 7574314Seric if (user->q_home == NULL) 7584314Seric syserr("forward: no home"); 7594069Seric 7604069Seric /* good address -- look for .forward file in home */ 76155012Seric define('z', user->q_home, e); 76257136Seric define('u', user->q_user, e); 76357136Seric define('h', user->q_host, e); 76457136Seric if (ForwardPath == NULL) 76557136Seric ForwardPath = newstr("\001z/.forward"); 76657136Seric 76757136Seric for (pp = ForwardPath; pp != NULL; pp = ep) 76857136Seric { 76957232Seric char buf[MAXPATHLEN+1]; 77057136Seric 77157136Seric ep = strchr(pp, ':'); 77257136Seric if (ep != NULL) 77357136Seric *ep = '\0'; 77457136Seric expand(pp, buf, &buf[sizeof buf - 1], e); 77557136Seric if (ep != NULL) 77657136Seric *ep++ = ':'; 77757136Seric if (tTd(27, 3)) 77857136Seric printf("forward: trying %s\n", buf); 77957136Seric if (include(buf, TRUE, user, sendq, e) == 0) 78057136Seric break; 78157136Seric } 782292Seric } 783