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> 11*57948Seric # include <sys/file.h> 1250577Seric # include <signal.h> 1350577Seric # include "sendmail.h" 1457737Seric # include <fcntl.h> 1550577Seric # include <pwd.h> 1650577Seric 1756845Seric # ifdef DBM 1856848Seric ERROR: DBM is no longer supported -- use NDBM instead. 1956845Seric # endif 2056845Seric 2150577Seric # ifdef NEWDB 2250577Seric # include <db.h> 2350577Seric # endif 2450577Seric 2556766Seric # ifdef NDBM 2656845Seric # include <ndbm.h> 2756766Seric # endif 2856766Seric 2933728Sbostic #ifndef lint 3051756Seric #ifdef NEWDB 3157736Seric #ifdef NDBM 32*57948Seric static char sccsid[] = "@(#)alias.c 6.7 (Berkeley) 02/12/93 (with NEWDB and NDBM)"; 3351756Seric #else 34*57948Seric static char sccsid[] = "@(#)alias.c 6.7 (Berkeley) 02/12/93 (with NEWDB)"; 3557736Seric #endif 3657736Seric #else 3756845Seric #ifdef NDBM 38*57948Seric static char sccsid[] = "@(#)alias.c 6.7 (Berkeley) 02/12/93 (with NDBM)"; 3933728Sbostic #else 40*57948Seric static char sccsid[] = "@(#)alias.c 6.7 (Berkeley) 02/12/93 (without NEWDB or NDBM)"; 4133728Sbostic #endif 4250575Seric #endif 4333728Sbostic #endif /* not lint */ 4451756Seric /* 45292Seric ** ALIAS -- Compute aliases. 46292Seric ** 479368Seric ** Scans the alias file for an alias for the given address. 489368Seric ** If found, it arranges to deliver to the alias list instead. 499368Seric ** Uses libdbm database if -DDBM. 50292Seric ** 51292Seric ** Parameters: 524097Seric ** a -- address to alias. 534999Seric ** sendq -- a pointer to the head of the send queue 544999Seric ** to put the aliases in. 55292Seric ** 56292Seric ** Returns: 57292Seric ** none 58292Seric ** 59292Seric ** Side Effects: 603185Seric ** Aliases found are expanded. 61292Seric ** 62292Seric ** Notes: 63292Seric ** If NoAlias (the "-n" flag) is set, no aliasing is 64292Seric ** done. 65292Seric ** 66292Seric ** Deficiencies: 67292Seric ** It should complain about names that are aliased to 68292Seric ** nothing. 69292Seric */ 70292Seric 71292Seric 7253742Seric /* 7353742Seric ** Sun YP servers read the dbm files directly, so we have to build them 7453742Seric ** even if NEWDB 7553742Seric */ 7653742Seric 7756845Seric #ifdef NDBM 7853742Seric # ifndef NEWDB 7953742Seric # define IF_MAKEDBMFILES 8053742Seric # else 8153742Seric # ifdef YPCOMPAT 8253742Seric # define IF_MAKEDBMFILES if (makedbmfiles) 8353742Seric # endif 8453742Seric # endif 8553742Seric #endif 8653742Seric 8756845Seric typedef union 882966Seric { 8956845Seric #ifdef NDBM 9056845Seric datum dbm; 9151756Seric #endif 9256845Seric #ifdef NEWDB 9356845Seric DBT dbt; 9456845Seric #endif 9556845Seric struct 9656845Seric { 9756845Seric char *data; 9856845Seric int size; 9956845Seric } xx; 10056845Seric } DBdatum; 101292Seric 10250575Seric #ifdef NEWDB 10350575Seric static DB *AliasDBptr; 10450575Seric #endif 10556845Seric #ifdef NDBM 10656845Seric static DBM *AliasDBMptr; 10756845Seric #endif 10850575Seric 10955012Seric alias(a, sendq, e) 1104097Seric register ADDRESS *a; 1114999Seric ADDRESS **sendq; 11255012Seric register ENVELOPE *e; 113292Seric { 1144081Seric register char *p; 1155701Seric extern char *aliaslookup(); 116292Seric 1177671Seric if (tTd(27, 1)) 1184098Seric printf("alias(%s)\n", a->q_paddr); 119292Seric 1204098Seric /* don't realias already aliased names */ 1214098Seric if (bitset(QDONTSEND, a->q_flags)) 1224098Seric return; 1234098Seric 12455012Seric e->e_to = a->q_paddr; 1254098Seric 1264314Seric /* 1274314Seric ** Look up this name 1284314Seric */ 1294314Seric 13024944Seric if (NoAlias) 13124944Seric p = NULL; 13224944Seric else 13324944Seric p = aliaslookup(a->q_user); 1344098Seric if (p == NULL) 1354098Seric return; 136292Seric 137292Seric /* 1384098Seric ** Match on Alias. 1394098Seric ** Deliver to the target list. 1401515Seric */ 1411515Seric 1427671Seric if (tTd(27, 1)) 1434098Seric printf("%s (%s, %s) aliased to %s\n", 1444098Seric a->q_paddr, a->q_host, a->q_user, p); 1457051Seric message(Arpa_Info, "aliased to %s", p); 1464098Seric AliasLevel++; 14755012Seric sendtolist(p, a, sendq, e); 1484098Seric AliasLevel--; 1494098Seric } 1504098Seric /* 1515701Seric ** ALIASLOOKUP -- look up a name in the alias file. 1525701Seric ** 1535701Seric ** Parameters: 1545701Seric ** name -- the name to look up. 1555701Seric ** 1565701Seric ** Returns: 1575701Seric ** the value of name. 1585701Seric ** NULL if unknown. 1595701Seric ** 1605701Seric ** Side Effects: 1615701Seric ** none. 1625701Seric ** 1635701Seric ** Warnings: 1645701Seric ** The return value will be trashed across calls. 1655701Seric */ 1665701Seric 1675701Seric char * 1685701Seric aliaslookup(name) 1695701Seric char *name; 1705701Seric { 17157381Seric int i; 17257381Seric char keybuf[MAXNAME + 1]; 17356845Seric # if defined(NEWDB) || defined(NDBM) 17456845Seric DBdatum rhs, lhs; 17550575Seric int s; 17657381Seric # else /* neither NEWDB nor NDBM */ 17757381Seric register STAB *s; 17857381Seric # endif 1795701Seric 1805701Seric /* create a key for fetch */ 18157381Seric i = strlen(name) + 1; 18257381Seric if (i > sizeof keybuf) 18357381Seric i = sizeof keybuf; 18457381Seric bcopy(name, keybuf, i); 18557381Seric if (!bitnset(M_USR_UPPER, LocalMailer->m_flags)) 18657381Seric makelower(keybuf); 18757381Seric 18857381Seric # if defined(NEWDB) || defined(NDBM) 18957381Seric lhs.xx.size = i; 19057381Seric lhs.xx.data = keybuf; 19150575Seric # ifdef NEWDB 19251756Seric if (AliasDBptr != NULL) 19351756Seric { 19457381Seric i = AliasDBptr->get(AliasDBptr, &lhs.dbt, &rhs.dbt, 0); 19557381Seric if (i == 0) 19656845Seric return (rhs.dbt.data); 19751756Seric } 19856845Seric # ifdef NDBM 19957249Seric else if (AliasDBMptr != NULL) 20051756Seric { 20156845Seric rhs.dbm = dbm_fetch(AliasDBMptr, lhs.dbm); 20256845Seric return (rhs.dbm.dptr); 20351756Seric } 20456845Seric # endif /* NDBM */ 20557530Seric return (NULL); 20656845Seric # else /* not NEWDB */ 20756845Seric rhs.dbm = dbm_fetch(AliasDBMptr, lhs.dbm); 20856845Seric return (rhs.dbm.dptr); 20956845Seric # endif /* NEWDB */ 21056845Seric # else /* neither NEWDB nor NDBM */ 21157381Seric s = stab(keybuf, ST_ALIAS, ST_FIND); 21251756Seric if (s != NULL) 21351756Seric return (s->s_alias); 21457530Seric return (NULL); 21551756Seric # endif 2165701Seric } 2175701Seric /* 2184098Seric ** INITALIASES -- initialize for aliasing 2194098Seric ** 22056845Seric ** Very different depending on whether we are running NDBM or not. 2214098Seric ** 2224098Seric ** Parameters: 2234098Seric ** aliasfile -- location of aliases. 22456845Seric ** init -- if set and if NDBM, initialize the NDBM files. 2254098Seric ** 2264098Seric ** Returns: 2274098Seric ** none. 2284098Seric ** 2294098Seric ** Side Effects: 2304098Seric ** initializes aliases: 23156845Seric ** if NDBM: opens the database. 23256845Seric ** if ~NDBM: reads the aliases into the symbol table. 2334098Seric */ 2344098Seric 23540559Sbostic # define DBMMODE 0644 2364157Seric 23755012Seric initaliases(aliasfile, init, e) 2384098Seric char *aliasfile; 2394157Seric bool init; 24055012Seric register ENVELOPE *e; 2414098Seric { 24256845Seric #if defined(NDBM) || defined(NEWDB) 2438437Seric int atcnt; 24425522Seric time_t modtime; 24525522Seric bool automatic = FALSE; 2464322Seric char buf[MAXNAME]; 24750575Seric #endif 2489368Seric struct stat stb; 24927176Seric static bool initialized = FALSE; 25046928Sbostic static int readaliases(); 2514322Seric 25227176Seric if (initialized) 25327176Seric return; 25427176Seric initialized = TRUE; 25527176Seric 25617984Seric if (aliasfile == NULL || stat(aliasfile, &stb) < 0) 2578437Seric { 25825522Seric if (aliasfile != NULL && init) 25925522Seric syserr("Cannot open %s", aliasfile); 2608437Seric NoAlias = TRUE; 26111937Seric errno = 0; 2628437Seric return; 2638437Seric } 2648437Seric 26556845Seric # if defined(NDBM) || defined(NEWDB) 2664322Seric /* 2678437Seric ** Check to see that the alias file is complete. 2688437Seric ** If not, we will assume that someone died, and it is up 2698437Seric ** to us to rebuild it. 2708437Seric */ 2718437Seric 27225689Seric if (!init) 27350575Seric { 27450575Seric # ifdef NEWDB 27550575Seric (void) strcpy(buf, aliasfile); 27650575Seric (void) strcat(buf, ".db"); 27751171Sbostic AliasDBptr = dbopen(buf, O_RDONLY, DBMMODE, DB_HASH, NULL); 27850576Seric if (AliasDBptr == NULL) 27950576Seric { 28056845Seric # ifdef NDBM 28156845Seric AliasDBMptr = dbm_open(aliasfile, O_RDONLY, DBMMODE); 28257249Seric if (AliasDBMptr == NULL) 28357249Seric { 28457249Seric syserr("initaliases: cannot open %s", buf); 28557249Seric NoAlias = TRUE; 28657249Seric return; 28757249Seric } 28851756Seric # else 28950576Seric syserr("initaliases: cannot open %s", buf); 29050576Seric NoAlias = TRUE; 29150576Seric return; 29251756Seric # endif 29350576Seric } 29450575Seric # else 29556845Seric AliasDBMptr = dbm_open(aliasfile, O_RDONLY, DBMMODE); 29657249Seric if (AliasDBMptr == NULL) 29757249Seric { 29857249Seric syserr("initaliases: cannot open %s", buf); 29957249Seric NoAlias = TRUE; 30057249Seric return; 30157249Seric } 30250575Seric # endif 30350575Seric } 30417471Seric atcnt = SafeAlias * 2; 30517471Seric if (atcnt > 0) 30617471Seric { 30717471Seric while (!init && atcnt-- >= 0 && aliaslookup("@") == NULL) 30825689Seric { 30925689Seric /* 31025689Seric ** Reinitialize alias file in case the new 31125689Seric ** one is mv'ed in instead of cp'ed in. 31225689Seric ** 31325689Seric ** Only works with new DBM -- old one will 31425689Seric ** just consume file descriptors forever. 31525689Seric ** If you have a dbmclose() it can be 31625689Seric ** added before the sleep(30). 31725689Seric */ 31825689Seric 31950575Seric # ifdef NEWDB 32051756Seric if (AliasDBptr != NULL) 32151756Seric AliasDBptr->close(AliasDBptr); 32250575Seric # endif 32356845Seric # ifdef NDBM 32456845Seric if (AliasDBMptr != NULL) 32556845Seric dbm_close(AliasDBMptr); 32656845Seric # endif 32750575Seric 32817471Seric sleep(30); 32950575Seric # ifdef NEWDB 33050575Seric (void) strcpy(buf, aliasfile); 33150575Seric (void) strcat(buf, ".db"); 33251171Sbostic AliasDBptr = 33351171Sbostic dbopen(buf, O_RDONLY, DBMMODE, DB_HASH, NULL); 33450576Seric if (AliasDBptr == NULL) 33550576Seric { 33651756Seric # ifdef NDBM 33756845Seric AliasDBMptr = dbm_open(aliasfile, O_RDONLY, DBMMODE); 33851756Seric # else 33950576Seric syserr("initaliases: cannot open %s", buf); 34050576Seric NoAlias = TRUE; 34150576Seric return; 34251756Seric # endif 34350576Seric } 34450575Seric # else 34525689Seric # ifdef NDBM 34656845Seric AliasDBMptr = dbm_open(aliasfile, O_RDONLY, DBMMODE); 34757249Seric if (AliasDBMptr == NULL) 34857249Seric { 34957249Seric syserr("initaliases: cannot open %s", buf); 35057249Seric NoAlias = TRUE; 35157249Seric return; 35257249Seric } 35350575Seric # endif 35450575Seric # endif 35525689Seric } 35617471Seric } 35717471Seric else 35817471Seric atcnt = 1; 3598437Seric 3608437Seric /* 36156845Seric ** See if the NDBM version of the file is out of date with 3624322Seric ** the text version. If so, go into 'init' mode automatically. 36340559Sbostic ** This only happens if our effective userid owns the DBM. 36440559Sbostic ** Note the unpalatable hack to see if the stat succeeded. 3654322Seric */ 3664322Seric 3674322Seric modtime = stb.st_mtime; 3684322Seric (void) strcpy(buf, aliasfile); 36950575Seric # ifdef NEWDB 37050575Seric (void) strcat(buf, ".db"); 37150575Seric # else 3724322Seric (void) strcat(buf, ".pag"); 37350575Seric # endif 3744322Seric stb.st_ino = 0; 37519039Seric if (!init && (stat(buf, &stb) < 0 || stb.st_mtime < modtime || atcnt < 0)) 3764322Seric { 37711937Seric errno = 0; 37840559Sbostic if (AutoRebuild && stb.st_ino != 0 && stb.st_uid == geteuid()) 3794322Seric { 3804322Seric init = TRUE; 38125522Seric automatic = TRUE; 3827051Seric message(Arpa_Info, "rebuilding alias database"); 38324944Seric #ifdef LOG 38424944Seric if (LogLevel >= 7) 38524944Seric syslog(LOG_INFO, "rebuilding alias database"); 38656795Seric #endif /* LOG */ 3874322Seric } 3884322Seric else 3894322Seric { 39019039Seric #ifdef LOG 39124944Seric if (LogLevel >= 7) 39224944Seric syslog(LOG_INFO, "alias database out of date"); 39356795Seric #endif /* LOG */ 3944322Seric message(Arpa_Info, "Warning: alias database out of date"); 3954322Seric } 3964322Seric } 3974322Seric 3984322Seric 3994322Seric /* 40056845Seric ** If necessary, load the NDBM file. 40156845Seric ** If running without NDBM, load the symbol table. 4024322Seric */ 4034322Seric 4044157Seric if (init) 4058437Seric { 40625522Seric #ifdef LOG 40725522Seric if (LogLevel >= 6) 40825522Seric { 40925522Seric extern char *username(); 41025522Seric 41125522Seric syslog(LOG_NOTICE, "alias database %srebuilt by %s", 41225522Seric automatic ? "auto" : "", username()); 41325522Seric } 41456795Seric #endif /* LOG */ 41555012Seric readaliases(aliasfile, TRUE, e); 4168437Seric } 41756845Seric # else /* NDBM */ 41855012Seric readaliases(aliasfile, init, e); 41956845Seric # endif /* NDBM */ 4204157Seric } 4214157Seric /* 4224157Seric ** READALIASES -- read and process the alias file. 4234157Seric ** 4244157Seric ** This routine implements the part of initaliases that occurs 4254157Seric ** when we are not going to use the DBM stuff. 4264157Seric ** 4274157Seric ** Parameters: 4284157Seric ** aliasfile -- the pathname of the alias file master. 42956845Seric ** init -- if set, initialize the NDBM stuff. 4304157Seric ** 4314157Seric ** Returns: 4324157Seric ** none. 4334157Seric ** 4344157Seric ** Side Effects: 4354157Seric ** Reads aliasfile into the symbol table. 4364157Seric ** Optionally, builds the .dir & .pag files. 4374157Seric */ 4384157Seric 4394157Seric static 44055012Seric readaliases(aliasfile, init, e) 4414157Seric char *aliasfile; 4424157Seric bool init; 44355012Seric register ENVELOPE *e; 4444157Seric { 4454098Seric register char *p; 4464098Seric char *rhs; 4474098Seric bool skipping; 4489368Seric int naliases, bytes, longest; 4499368Seric FILE *af; 45053742Seric bool makedbmfiles; 45140970Sbostic void (*oldsigint)(); 4524098Seric ADDRESS al, bl; 4534106Seric register STAB *s; 45450575Seric # ifdef NEWDB 45550575Seric DB *dbp; 45650575Seric # endif 45756845Seric # ifdef NDBM 45856845Seric DBM *dbmp; 45956845Seric # endif 46051937Seric # ifdef LOCKF 46151937Seric struct flock fld; 46251937Seric # endif 4639368Seric char line[BUFSIZ]; 4644098Seric 46551937Seric if ((af = fopen(aliasfile, "r+")) == NULL) 4661515Seric { 46757249Seric if (init) 46857249Seric syserr("Can't open %s", aliasfile); 46957249Seric else if (tTd(27, 1)) 4704106Seric printf("Can't open %s\n", aliasfile); 4714098Seric errno = 0; 4724098Seric NoAlias++; 4734098Seric return; 4744098Seric } 4754314Seric 47656845Seric # if defined(NDBM) || defined(NEWDB) 47719784Seric /* see if someone else is rebuilding the alias file already */ 47851835Seric # ifdef LOCKF 47951937Seric fld.l_type = F_WRLCK; 48051937Seric fld.l_whence = fld.l_start = fld.l_len = 0; 48151937Seric if (fcntl(fileno(af), F_SETLK, &fld) < 0) 48251835Seric # else 48319784Seric if (flock(fileno(af), LOCK_EX | LOCK_NB) < 0 && errno == EWOULDBLOCK) 48451835Seric # endif 48519784Seric { 48619784Seric /* yes, they are -- wait until done and then return */ 48719784Seric message(Arpa_Info, "Alias file is already being rebuilt"); 48819784Seric if (OpMode != MD_INITALIAS) 48919784Seric { 49019784Seric /* wait for other rebuild to complete */ 49151835Seric # ifdef LOCKF 49251937Seric (void) fcntl(fileno(af), F_SETLKW, &fld); 49351835Seric # else 49419784Seric (void) flock(fileno(af), LOCK_EX); 49551835Seric # endif 49619784Seric } 49723108Seric (void) fclose(af); 49819784Seric errno = 0; 49919784Seric return; 50019784Seric } 50156845Seric # endif /* NDBM */ 50219784Seric 5034314Seric /* 50419784Seric ** If initializing, create the new DBM files. 50519784Seric */ 50619784Seric 50719784Seric if (init) 50819784Seric { 50919784Seric oldsigint = signal(SIGINT, SIG_IGN); 51051756Seric # ifdef NEWDB 51151756Seric (void) strcpy(line, aliasfile); 51251756Seric (void) strcat(line, ".db"); 51351756Seric dbp = dbopen(line, 51451756Seric O_RDWR|O_CREAT|O_TRUNC, DBMMODE, DB_HASH, NULL); 51551756Seric if (dbp == NULL) 51651756Seric { 51751756Seric syserr("readaliases: cannot create %s", line); 51851756Seric (void) signal(SIGINT, oldsigint); 51951756Seric return; 52051756Seric } 52153742Seric # endif 52253742Seric # ifdef IF_MAKEDBMFILES 52353742Seric # ifdef NEWDB 52453742Seric makedbmfiles = access("/var/yp/Makefile", R_OK) == 0; 52553742Seric # endif 52653742Seric IF_MAKEDBMFILES 52719784Seric { 52856845Seric dbmp = dbm_open(aliasfile, 52956845Seric O_RDWR|O_CREAT|O_TRUNC, DBMMODE); 53056845Seric if (dbmp == NULL) 53153742Seric { 53256845Seric syserr("readaliases: cannot create %s.{dir,pag}", 53356845Seric aliasfile); 53453742Seric (void) signal(SIGINT, oldsigint); 53553742Seric return; 53653742Seric } 53719784Seric } 53850575Seric # endif 53919784Seric } 54019784Seric 54119784Seric /* 5424314Seric ** Read and interpret lines 5434314Seric */ 5444314Seric 5459368Seric FileName = aliasfile; 5469368Seric LineNumber = 0; 5474322Seric naliases = bytes = longest = 0; 5484098Seric skipping = FALSE; 5494098Seric while (fgets(line, sizeof (line), af) != NULL) 5504098Seric { 5514322Seric int lhssize, rhssize; 5524322Seric 5539368Seric LineNumber++; 55456795Seric p = strchr(line, '\n'); 55525278Seric if (p != NULL) 55625278Seric *p = '\0'; 5574098Seric switch (line[0]) 5584098Seric { 5594098Seric case '#': 5604098Seric case '\0': 5614098Seric skipping = FALSE; 5624098Seric continue; 5634065Seric 5644098Seric case ' ': 5654098Seric case '\t': 5664098Seric if (!skipping) 5679368Seric syserr("Non-continuation line starts with space"); 5684098Seric skipping = TRUE; 5694097Seric continue; 5704098Seric } 5714098Seric skipping = FALSE; 5721874Seric 5734314Seric /* 5744314Seric ** Process the LHS 57557736Seric ** Find the colon separator, and parse the address. 57616898Seric ** It should resolve to a local name -- this will 57716898Seric ** be checked later (we want to optionally do 57816898Seric ** parsing of the RHS first to maximize error 57916898Seric ** detection). 5804314Seric */ 5814314Seric 5824098Seric for (p = line; *p != '\0' && *p != ':' && *p != '\n'; p++) 5834097Seric continue; 58416898Seric if (*p++ != ':') 5854098Seric { 5869368Seric syserr("missing colon"); 5874097Seric continue; 5884098Seric } 58955012Seric if (parseaddr(line, &al, 1, ':', e) == NULL) 5904098Seric { 59116898Seric syserr("illegal alias name"); 59216898Seric continue; 5934098Seric } 59416898Seric loweraddr(&al); 5954314Seric 5964314Seric /* 5974314Seric ** Process the RHS. 5984314Seric ** 'al' is the internal form of the LHS address. 5994314Seric ** 'p' points to the text of the RHS. 6004314Seric */ 6014314Seric 6024098Seric rhs = p; 6034098Seric for (;;) 6044098Seric { 6054098Seric register char c; 6061515Seric 60725821Seric if (init && CheckAliases) 6084098Seric { 6094157Seric /* do parsing & compression of addresses */ 61025278Seric while (*p != '\0') 6114098Seric { 61225278Seric extern char *DelimChar; 61325278Seric 61425278Seric while (isspace(*p) || *p == ',') 6154157Seric p++; 61625278Seric if (*p == '\0') 61725278Seric break; 61855012Seric if (parseaddr(p, &bl, -1, ',', e) == NULL) 61925278Seric usrerr("%s... bad address", p); 62025278Seric p = DelimChar; 6214098Seric } 6224098Seric } 6234157Seric else 62415769Seric { 62516898Seric p = &p[strlen(p)]; 62616898Seric if (p[-1] == '\n') 62716898Seric *--p = '\0'; 62815769Seric } 6291515Seric 6304098Seric /* see if there should be a continuation line */ 6314106Seric c = fgetc(af); 6324106Seric if (!feof(af)) 6334314Seric (void) ungetc(c, af); 6344106Seric if (c != ' ' && c != '\t') 6354098Seric break; 6364098Seric 6374098Seric /* read continuation line */ 6384098Seric if (fgets(p, sizeof line - (p - line), af) == NULL) 6394098Seric break; 6409368Seric LineNumber++; 64157135Seric 64257135Seric /* check for line overflow */ 64357135Seric if (strchr(p, '\n') == NULL) 64457135Seric { 64557135Seric usrerr("alias too long"); 64657135Seric break; 64757135Seric } 6484098Seric } 64916898Seric if (al.q_mailer != LocalMailer) 65016898Seric { 65116898Seric syserr("cannot alias non-local names"); 65216898Seric continue; 65316898Seric } 6544314Seric 6554314Seric /* 6564314Seric ** Insert alias into symbol table or DBM file 6574314Seric */ 6584314Seric 65916898Seric lhssize = strlen(al.q_user) + 1; 66057381Seric if (!bitnset(M_USR_UPPER, al.q_mailer->m_flags)) 66157381Seric makelower(al.q_user); 6624322Seric rhssize = strlen(rhs) + 1; 6634322Seric 66456845Seric # if defined(NDBM) || defined(NEWDB) 6654157Seric if (init) 6664157Seric { 66756845Seric DBdatum key, content; 66857381Seric int putstat; 6694157Seric 67056845Seric key.xx.size = lhssize; 67156845Seric key.xx.data = al.q_user; 67256845Seric content.xx.size = rhssize; 67356845Seric content.xx.data = rhs; 67451756Seric # ifdef NEWDB 67557381Seric putstat = dbp->put(dbp, &key.dbt, &content.dbt, 67657381Seric R_NOOVERWRITE); 67757381Seric if (putstat > 0) 67857381Seric { 67957381Seric usrerr("Warning: duplicate alias name %s", 68057381Seric al.q_user); 68157381Seric putstat = dbp->put(dbp, &key.dbt, 68257381Seric &content.dbt, 0); 68357381Seric } 68457381Seric if (putstat != 0) 68550576Seric syserr("readaliases: db put (%s)", al.q_user); 68650575Seric # endif 68753742Seric # ifdef IF_MAKEDBMFILES 68853742Seric IF_MAKEDBMFILES 68957381Seric { 69057381Seric putstat = dbm_store(dbmp, key.dbm, content.dbm, 69157381Seric DBM_INSERT); 69257381Seric if (putstat > 0) 69357381Seric { 69457381Seric usrerr("Warning: duplicate alias name %s", 69557381Seric al.q_user); 69657381Seric putstat = dbm_store(dbmp, key.dbm, 69757381Seric content.dbm, DBM_REPLACE); 69857381Seric } 69957381Seric if (putstat != 0) 70056845Seric syserr("readaliases: dbm store (%s)", 70156845Seric al.q_user); 70257381Seric } 70353742Seric # endif 70457381Seric if (al.q_paddr != NULL) 70557381Seric free(al.q_paddr); 70657381Seric if (al.q_host != NULL) 70757381Seric free(al.q_host); 70857381Seric if (al.q_user != NULL) 70957381Seric free(al.q_user); 7104157Seric } 7114157Seric else 71256845Seric # endif /* NDBM */ 7134157Seric { 7144157Seric s = stab(al.q_user, ST_ALIAS, ST_ENTER); 7154157Seric s->s_alias = newstr(rhs); 7164157Seric } 7174322Seric 7184322Seric /* statistics */ 7194322Seric naliases++; 7204322Seric bytes += lhssize + rhssize; 7214322Seric if (rhssize > longest) 7224322Seric longest = rhssize; 7231515Seric } 72419784Seric 72556845Seric # if defined(NDBM) || defined(NEWDB) 72619784Seric if (init) 72719784Seric { 72819784Seric /* add the distinquished alias "@" */ 72956845Seric DBdatum key; 73019784Seric 73156845Seric key.xx.size = 2; 73256845Seric key.xx.data = "@"; 73350575Seric # ifdef NEWDB 73450576Seric if (dbp->sync(dbp) != 0 || 73556845Seric dbp->put(dbp, &key.dbt, &key.dbt, 0) != 0 || 73650576Seric dbp->close(dbp) != 0) 73750576Seric syserr("readaliases: db close failure"); 73853742Seric # endif 73956789Seric # ifdef IF_MAKEDBMFILES 74056793Seric IF_MAKEDBMFILES 74156845Seric { 74256845Seric if (dbm_store(dbmp, key.dbm, key.dbm, DBM_REPLACE) != 0 || 74356845Seric dbm_error(dbmp)) 74456845Seric syserr("readaliases: dbm close failure"); 74556845Seric dbm_close(dbmp); 74656845Seric } 74750575Seric # endif 74819784Seric 74919784Seric /* restore the old signal */ 75019784Seric (void) signal(SIGINT, oldsigint); 75119784Seric } 75256845Seric # endif /* NDBM */ 75319784Seric 75419784Seric /* closing the alias file drops the lock */ 7554098Seric (void) fclose(af); 75655012Seric e->e_to = NULL; 7579368Seric FileName = NULL; 7587051Seric message(Arpa_Info, "%d aliases, longest %d bytes, %d bytes total", 7594322Seric naliases, longest, bytes); 76024944Seric # ifdef LOG 76124944Seric if (LogLevel >= 8) 76224944Seric syslog(LOG_INFO, "%d aliases, longest %d bytes, %d bytes total", 76324944Seric naliases, longest, bytes); 76456795Seric # endif /* LOG */ 765292Seric } 766292Seric /* 767292Seric ** FORWARD -- Try to forward mail 768292Seric ** 769292Seric ** This is similar but not identical to aliasing. 770292Seric ** 771292Seric ** Parameters: 7724314Seric ** user -- the name of the user who's mail we would like 7734314Seric ** to forward to. It must have been verified -- 7744314Seric ** i.e., the q_home field must have been filled 7754314Seric ** in. 7764999Seric ** sendq -- a pointer to the head of the send queue to 7774999Seric ** put this user's aliases in. 778292Seric ** 779292Seric ** Returns: 7804098Seric ** none. 781292Seric ** 782292Seric ** Side Effects: 7833185Seric ** New names are added to send queues. 784292Seric */ 785292Seric 78655012Seric forward(user, sendq, e) 7872966Seric ADDRESS *user; 7884999Seric ADDRESS **sendq; 78955012Seric register ENVELOPE *e; 790292Seric { 79157136Seric char *pp; 79257136Seric char *ep; 7934536Seric extern bool safefile(); 7944069Seric 7957671Seric if (tTd(27, 1)) 7964098Seric printf("forward(%s)\n", user->q_paddr); 7974098Seric 7984594Seric if (user->q_mailer != LocalMailer || bitset(QBADADDR, user->q_flags)) 7994098Seric return; 8004314Seric if (user->q_home == NULL) 8014314Seric syserr("forward: no home"); 8024069Seric 8034069Seric /* good address -- look for .forward file in home */ 80455012Seric define('z', user->q_home, e); 80557136Seric define('u', user->q_user, e); 80657136Seric define('h', user->q_host, e); 80757136Seric if (ForwardPath == NULL) 80857136Seric ForwardPath = newstr("\001z/.forward"); 80957136Seric 81057136Seric for (pp = ForwardPath; pp != NULL; pp = ep) 81157136Seric { 81257232Seric char buf[MAXPATHLEN+1]; 81357136Seric 81457136Seric ep = strchr(pp, ':'); 81557136Seric if (ep != NULL) 81657136Seric *ep = '\0'; 81757136Seric expand(pp, buf, &buf[sizeof buf - 1], e); 81857136Seric if (ep != NULL) 81957136Seric *ep++ = ':'; 82057136Seric if (tTd(27, 3)) 82157136Seric printf("forward: trying %s\n", buf); 82257136Seric if (include(buf, TRUE, user, sendq, e) == 0) 82357136Seric break; 82457136Seric } 825292Seric } 826