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*57736Seric #ifdef NDBM 34*57736Seric static char sccsid[] = "@(#)alias.c 6.5 (Berkeley) 01/28/93 (with NEWDB and NDBM)"; 3551756Seric #else 36*57736Seric static char sccsid[] = "@(#)alias.c 6.5 (Berkeley) 01/28/93 (with NEWDB)"; 37*57736Seric #endif 38*57736Seric #else 3956845Seric #ifdef NDBM 40*57736Seric static char sccsid[] = "@(#)alias.c 6.5 (Berkeley) 01/28/93 (with NDBM)"; 4133728Sbostic #else 42*57736Seric static char sccsid[] = "@(#)alias.c 6.5 (Berkeley) 01/28/93 (without NEWDB or NDBM)"; 4333728Sbostic #endif 4450575Seric #endif 4533728Sbostic #endif /* not lint */ 4651756Seric /* 47292Seric ** ALIAS -- Compute aliases. 48292Seric ** 499368Seric ** Scans the alias file for an alias for the given address. 509368Seric ** If found, it arranges to deliver to the alias list instead. 519368Seric ** Uses libdbm database if -DDBM. 52292Seric ** 53292Seric ** Parameters: 544097Seric ** a -- address to alias. 554999Seric ** sendq -- a pointer to the head of the send queue 564999Seric ** to put the aliases in. 57292Seric ** 58292Seric ** Returns: 59292Seric ** none 60292Seric ** 61292Seric ** Side Effects: 623185Seric ** Aliases found are expanded. 63292Seric ** 64292Seric ** Notes: 65292Seric ** If NoAlias (the "-n" flag) is set, no aliasing is 66292Seric ** done. 67292Seric ** 68292Seric ** Deficiencies: 69292Seric ** It should complain about names that are aliased to 70292Seric ** nothing. 71292Seric */ 72292Seric 73292Seric 7453742Seric /* 7553742Seric ** Sun YP servers read the dbm files directly, so we have to build them 7653742Seric ** even if NEWDB 7753742Seric */ 7853742Seric 7956845Seric #ifdef NDBM 8053742Seric # ifndef NEWDB 8153742Seric # define IF_MAKEDBMFILES 8253742Seric # else 8353742Seric # ifdef YPCOMPAT 8453742Seric # define IF_MAKEDBMFILES if (makedbmfiles) 8553742Seric # endif 8653742Seric # endif 8753742Seric #endif 8853742Seric 8956845Seric typedef union 902966Seric { 9156845Seric #ifdef NDBM 9256845Seric datum dbm; 9351756Seric #endif 9456845Seric #ifdef NEWDB 9556845Seric DBT dbt; 9656845Seric #endif 9756845Seric struct 9856845Seric { 9956845Seric char *data; 10056845Seric int size; 10156845Seric } xx; 10256845Seric } DBdatum; 103292Seric 10450575Seric #ifdef NEWDB 10550575Seric static DB *AliasDBptr; 10650575Seric #endif 10756845Seric #ifdef NDBM 10856845Seric static DBM *AliasDBMptr; 10956845Seric #endif 11050575Seric 11155012Seric alias(a, sendq, e) 1124097Seric register ADDRESS *a; 1134999Seric ADDRESS **sendq; 11455012Seric register ENVELOPE *e; 115292Seric { 1164081Seric register char *p; 1175701Seric extern char *aliaslookup(); 118292Seric 1197671Seric if (tTd(27, 1)) 1204098Seric printf("alias(%s)\n", a->q_paddr); 121292Seric 1224098Seric /* don't realias already aliased names */ 1234098Seric if (bitset(QDONTSEND, a->q_flags)) 1244098Seric return; 1254098Seric 12655012Seric e->e_to = a->q_paddr; 1274098Seric 1284314Seric /* 1294314Seric ** Look up this name 1304314Seric */ 1314314Seric 13224944Seric if (NoAlias) 13324944Seric p = NULL; 13424944Seric else 13524944Seric p = aliaslookup(a->q_user); 1364098Seric if (p == NULL) 1374098Seric return; 138292Seric 139292Seric /* 1404098Seric ** Match on Alias. 1414098Seric ** Deliver to the target list. 1421515Seric */ 1431515Seric 1447671Seric if (tTd(27, 1)) 1454098Seric printf("%s (%s, %s) aliased to %s\n", 1464098Seric a->q_paddr, a->q_host, a->q_user, p); 1477051Seric message(Arpa_Info, "aliased to %s", p); 1484098Seric AliasLevel++; 14955012Seric sendtolist(p, a, sendq, e); 1504098Seric AliasLevel--; 1514098Seric } 1524098Seric /* 1535701Seric ** ALIASLOOKUP -- look up a name in the alias file. 1545701Seric ** 1555701Seric ** Parameters: 1565701Seric ** name -- the name to look up. 1575701Seric ** 1585701Seric ** Returns: 1595701Seric ** the value of name. 1605701Seric ** NULL if unknown. 1615701Seric ** 1625701Seric ** Side Effects: 1635701Seric ** none. 1645701Seric ** 1655701Seric ** Warnings: 1665701Seric ** The return value will be trashed across calls. 1675701Seric */ 1685701Seric 1695701Seric char * 1705701Seric aliaslookup(name) 1715701Seric char *name; 1725701Seric { 17357381Seric int i; 17457381Seric char keybuf[MAXNAME + 1]; 17556845Seric # if defined(NEWDB) || defined(NDBM) 17656845Seric DBdatum rhs, lhs; 17750575Seric int s; 17857381Seric # else /* neither NEWDB nor NDBM */ 17957381Seric register STAB *s; 18057381Seric # endif 1815701Seric 1825701Seric /* create a key for fetch */ 18357381Seric i = strlen(name) + 1; 18457381Seric if (i > sizeof keybuf) 18557381Seric i = sizeof keybuf; 18657381Seric bcopy(name, keybuf, i); 18757381Seric if (!bitnset(M_USR_UPPER, LocalMailer->m_flags)) 18857381Seric makelower(keybuf); 18957381Seric 19057381Seric # if defined(NEWDB) || defined(NDBM) 19157381Seric lhs.xx.size = i; 19257381Seric lhs.xx.data = keybuf; 19350575Seric # ifdef NEWDB 19451756Seric if (AliasDBptr != NULL) 19551756Seric { 19657381Seric i = AliasDBptr->get(AliasDBptr, &lhs.dbt, &rhs.dbt, 0); 19757381Seric if (i == 0) 19856845Seric return (rhs.dbt.data); 19951756Seric } 20056845Seric # ifdef NDBM 20157249Seric else if (AliasDBMptr != NULL) 20251756Seric { 20356845Seric rhs.dbm = dbm_fetch(AliasDBMptr, lhs.dbm); 20456845Seric return (rhs.dbm.dptr); 20551756Seric } 20656845Seric # endif /* NDBM */ 20757530Seric return (NULL); 20856845Seric # else /* not NEWDB */ 20956845Seric rhs.dbm = dbm_fetch(AliasDBMptr, lhs.dbm); 21056845Seric return (rhs.dbm.dptr); 21156845Seric # endif /* NEWDB */ 21256845Seric # else /* neither NEWDB nor NDBM */ 21357381Seric s = stab(keybuf, ST_ALIAS, ST_FIND); 21451756Seric if (s != NULL) 21551756Seric return (s->s_alias); 21657530Seric return (NULL); 21751756Seric # endif 2185701Seric } 2195701Seric /* 2204098Seric ** INITALIASES -- initialize for aliasing 2214098Seric ** 22256845Seric ** Very different depending on whether we are running NDBM or not. 2234098Seric ** 2244098Seric ** Parameters: 2254098Seric ** aliasfile -- location of aliases. 22656845Seric ** init -- if set and if NDBM, initialize the NDBM files. 2274098Seric ** 2284098Seric ** Returns: 2294098Seric ** none. 2304098Seric ** 2314098Seric ** Side Effects: 2324098Seric ** initializes aliases: 23356845Seric ** if NDBM: opens the database. 23456845Seric ** if ~NDBM: reads the aliases into the symbol table. 2354098Seric */ 2364098Seric 23740559Sbostic # define DBMMODE 0644 2384157Seric 23955012Seric initaliases(aliasfile, init, e) 2404098Seric char *aliasfile; 2414157Seric bool init; 24255012Seric register ENVELOPE *e; 2434098Seric { 24456845Seric #if defined(NDBM) || defined(NEWDB) 2458437Seric int atcnt; 24625522Seric time_t modtime; 24725522Seric bool automatic = FALSE; 2484322Seric char buf[MAXNAME]; 24950575Seric #endif 2509368Seric struct stat stb; 25127176Seric static bool initialized = FALSE; 25246928Sbostic static int readaliases(); 2534322Seric 25427176Seric if (initialized) 25527176Seric return; 25627176Seric initialized = TRUE; 25727176Seric 25817984Seric if (aliasfile == NULL || stat(aliasfile, &stb) < 0) 2598437Seric { 26025522Seric if (aliasfile != NULL && init) 26125522Seric syserr("Cannot open %s", aliasfile); 2628437Seric NoAlias = TRUE; 26311937Seric errno = 0; 2648437Seric return; 2658437Seric } 2668437Seric 26756845Seric # if defined(NDBM) || defined(NEWDB) 2684322Seric /* 2698437Seric ** Check to see that the alias file is complete. 2708437Seric ** If not, we will assume that someone died, and it is up 2718437Seric ** to us to rebuild it. 2728437Seric */ 2738437Seric 27425689Seric if (!init) 27550575Seric { 27650575Seric # ifdef NEWDB 27750575Seric (void) strcpy(buf, aliasfile); 27850575Seric (void) strcat(buf, ".db"); 27951171Sbostic AliasDBptr = dbopen(buf, O_RDONLY, DBMMODE, DB_HASH, NULL); 28050576Seric if (AliasDBptr == NULL) 28150576Seric { 28256845Seric # ifdef NDBM 28356845Seric AliasDBMptr = dbm_open(aliasfile, O_RDONLY, DBMMODE); 28457249Seric if (AliasDBMptr == NULL) 28557249Seric { 28657249Seric syserr("initaliases: cannot open %s", buf); 28757249Seric NoAlias = TRUE; 28857249Seric return; 28957249Seric } 29051756Seric # else 29150576Seric syserr("initaliases: cannot open %s", buf); 29250576Seric NoAlias = TRUE; 29350576Seric return; 29451756Seric # endif 29550576Seric } 29650575Seric # else 29756845Seric AliasDBMptr = dbm_open(aliasfile, O_RDONLY, DBMMODE); 29857249Seric if (AliasDBMptr == NULL) 29957249Seric { 30057249Seric syserr("initaliases: cannot open %s", buf); 30157249Seric NoAlias = TRUE; 30257249Seric return; 30357249Seric } 30450575Seric # endif 30550575Seric } 30617471Seric atcnt = SafeAlias * 2; 30717471Seric if (atcnt > 0) 30817471Seric { 30917471Seric while (!init && atcnt-- >= 0 && aliaslookup("@") == NULL) 31025689Seric { 31125689Seric /* 31225689Seric ** Reinitialize alias file in case the new 31325689Seric ** one is mv'ed in instead of cp'ed in. 31425689Seric ** 31525689Seric ** Only works with new DBM -- old one will 31625689Seric ** just consume file descriptors forever. 31725689Seric ** If you have a dbmclose() it can be 31825689Seric ** added before the sleep(30). 31925689Seric */ 32025689Seric 32150575Seric # ifdef NEWDB 32251756Seric if (AliasDBptr != NULL) 32351756Seric AliasDBptr->close(AliasDBptr); 32450575Seric # endif 32556845Seric # ifdef NDBM 32656845Seric if (AliasDBMptr != NULL) 32756845Seric dbm_close(AliasDBMptr); 32856845Seric # endif 32950575Seric 33017471Seric sleep(30); 33150575Seric # ifdef NEWDB 33250575Seric (void) strcpy(buf, aliasfile); 33350575Seric (void) strcat(buf, ".db"); 33451171Sbostic AliasDBptr = 33551171Sbostic dbopen(buf, O_RDONLY, DBMMODE, DB_HASH, NULL); 33650576Seric if (AliasDBptr == NULL) 33750576Seric { 33851756Seric # ifdef NDBM 33956845Seric AliasDBMptr = dbm_open(aliasfile, O_RDONLY, DBMMODE); 34051756Seric # else 34150576Seric syserr("initaliases: cannot open %s", buf); 34250576Seric NoAlias = TRUE; 34350576Seric return; 34451756Seric # endif 34550576Seric } 34650575Seric # else 34725689Seric # ifdef NDBM 34856845Seric AliasDBMptr = dbm_open(aliasfile, O_RDONLY, DBMMODE); 34957249Seric if (AliasDBMptr == NULL) 35057249Seric { 35157249Seric syserr("initaliases: cannot open %s", buf); 35257249Seric NoAlias = TRUE; 35357249Seric return; 35457249Seric } 35550575Seric # endif 35650575Seric # endif 35725689Seric } 35817471Seric } 35917471Seric else 36017471Seric atcnt = 1; 3618437Seric 3628437Seric /* 36356845Seric ** See if the NDBM version of the file is out of date with 3644322Seric ** the text version. If so, go into 'init' mode automatically. 36540559Sbostic ** This only happens if our effective userid owns the DBM. 36640559Sbostic ** Note the unpalatable hack to see if the stat succeeded. 3674322Seric */ 3684322Seric 3694322Seric modtime = stb.st_mtime; 3704322Seric (void) strcpy(buf, aliasfile); 37150575Seric # ifdef NEWDB 37250575Seric (void) strcat(buf, ".db"); 37350575Seric # else 3744322Seric (void) strcat(buf, ".pag"); 37550575Seric # endif 3764322Seric stb.st_ino = 0; 37719039Seric if (!init && (stat(buf, &stb) < 0 || stb.st_mtime < modtime || atcnt < 0)) 3784322Seric { 37911937Seric errno = 0; 38040559Sbostic if (AutoRebuild && stb.st_ino != 0 && stb.st_uid == geteuid()) 3814322Seric { 3824322Seric init = TRUE; 38325522Seric automatic = TRUE; 3847051Seric message(Arpa_Info, "rebuilding alias database"); 38524944Seric #ifdef LOG 38624944Seric if (LogLevel >= 7) 38724944Seric syslog(LOG_INFO, "rebuilding alias database"); 38856795Seric #endif /* LOG */ 3894322Seric } 3904322Seric else 3914322Seric { 39219039Seric #ifdef LOG 39324944Seric if (LogLevel >= 7) 39424944Seric syslog(LOG_INFO, "alias database out of date"); 39556795Seric #endif /* LOG */ 3964322Seric message(Arpa_Info, "Warning: alias database out of date"); 3974322Seric } 3984322Seric } 3994322Seric 4004322Seric 4014322Seric /* 40256845Seric ** If necessary, load the NDBM file. 40356845Seric ** If running without NDBM, load the symbol table. 4044322Seric */ 4054322Seric 4064157Seric if (init) 4078437Seric { 40825522Seric #ifdef LOG 40925522Seric if (LogLevel >= 6) 41025522Seric { 41125522Seric extern char *username(); 41225522Seric 41325522Seric syslog(LOG_NOTICE, "alias database %srebuilt by %s", 41425522Seric automatic ? "auto" : "", username()); 41525522Seric } 41656795Seric #endif /* LOG */ 41755012Seric readaliases(aliasfile, TRUE, e); 4188437Seric } 41956845Seric # else /* NDBM */ 42055012Seric readaliases(aliasfile, init, e); 42156845Seric # endif /* NDBM */ 4224157Seric } 4234157Seric /* 4244157Seric ** READALIASES -- read and process the alias file. 4254157Seric ** 4264157Seric ** This routine implements the part of initaliases that occurs 4274157Seric ** when we are not going to use the DBM stuff. 4284157Seric ** 4294157Seric ** Parameters: 4304157Seric ** aliasfile -- the pathname of the alias file master. 43156845Seric ** init -- if set, initialize the NDBM stuff. 4324157Seric ** 4334157Seric ** Returns: 4344157Seric ** none. 4354157Seric ** 4364157Seric ** Side Effects: 4374157Seric ** Reads aliasfile into the symbol table. 4384157Seric ** Optionally, builds the .dir & .pag files. 4394157Seric */ 4404157Seric 4414157Seric static 44255012Seric readaliases(aliasfile, init, e) 4434157Seric char *aliasfile; 4444157Seric bool init; 44555012Seric register ENVELOPE *e; 4464157Seric { 4474098Seric register char *p; 4484098Seric char *rhs; 4494098Seric bool skipping; 4509368Seric int naliases, bytes, longest; 4519368Seric FILE *af; 45253742Seric bool makedbmfiles; 45340970Sbostic void (*oldsigint)(); 4544098Seric ADDRESS al, bl; 4554106Seric register STAB *s; 45650575Seric # ifdef NEWDB 45750575Seric DB *dbp; 45850575Seric # endif 45956845Seric # ifdef NDBM 46056845Seric DBM *dbmp; 46156845Seric # endif 46251937Seric # ifdef LOCKF 46351937Seric struct flock fld; 46451937Seric # endif 4659368Seric char line[BUFSIZ]; 4664098Seric 46751937Seric if ((af = fopen(aliasfile, "r+")) == NULL) 4681515Seric { 46957249Seric if (init) 47057249Seric syserr("Can't open %s", aliasfile); 47157249Seric else if (tTd(27, 1)) 4724106Seric printf("Can't open %s\n", aliasfile); 4734098Seric errno = 0; 4744098Seric NoAlias++; 4754098Seric return; 4764098Seric } 4774314Seric 47856845Seric # if defined(NDBM) || defined(NEWDB) 47919784Seric /* see if someone else is rebuilding the alias file already */ 48051835Seric # ifdef LOCKF 48151937Seric fld.l_type = F_WRLCK; 48251937Seric fld.l_whence = fld.l_start = fld.l_len = 0; 48351937Seric if (fcntl(fileno(af), F_SETLK, &fld) < 0) 48451835Seric # else 48519784Seric if (flock(fileno(af), LOCK_EX | LOCK_NB) < 0 && errno == EWOULDBLOCK) 48651835Seric # endif 48719784Seric { 48819784Seric /* yes, they are -- wait until done and then return */ 48919784Seric message(Arpa_Info, "Alias file is already being rebuilt"); 49019784Seric if (OpMode != MD_INITALIAS) 49119784Seric { 49219784Seric /* wait for other rebuild to complete */ 49351835Seric # ifdef LOCKF 49451937Seric (void) fcntl(fileno(af), F_SETLKW, &fld); 49551835Seric # else 49619784Seric (void) flock(fileno(af), LOCK_EX); 49751835Seric # endif 49819784Seric } 49923108Seric (void) fclose(af); 50019784Seric errno = 0; 50119784Seric return; 50219784Seric } 50356845Seric # endif /* NDBM */ 50419784Seric 5054314Seric /* 50619784Seric ** If initializing, create the new DBM files. 50719784Seric */ 50819784Seric 50919784Seric if (init) 51019784Seric { 51119784Seric oldsigint = signal(SIGINT, SIG_IGN); 51251756Seric # ifdef NEWDB 51351756Seric (void) strcpy(line, aliasfile); 51451756Seric (void) strcat(line, ".db"); 51551756Seric dbp = dbopen(line, 51651756Seric O_RDWR|O_CREAT|O_TRUNC, DBMMODE, DB_HASH, NULL); 51751756Seric if (dbp == NULL) 51851756Seric { 51951756Seric syserr("readaliases: cannot create %s", line); 52051756Seric (void) signal(SIGINT, oldsigint); 52151756Seric return; 52251756Seric } 52353742Seric # endif 52453742Seric # ifdef IF_MAKEDBMFILES 52553742Seric # ifdef NEWDB 52653742Seric makedbmfiles = access("/var/yp/Makefile", R_OK) == 0; 52753742Seric # endif 52853742Seric IF_MAKEDBMFILES 52919784Seric { 53056845Seric dbmp = dbm_open(aliasfile, 53156845Seric O_RDWR|O_CREAT|O_TRUNC, DBMMODE); 53256845Seric if (dbmp == NULL) 53353742Seric { 53456845Seric syserr("readaliases: cannot create %s.{dir,pag}", 53556845Seric aliasfile); 53653742Seric (void) signal(SIGINT, oldsigint); 53753742Seric return; 53853742Seric } 53919784Seric } 54050575Seric # endif 54119784Seric } 54219784Seric 54319784Seric /* 5444314Seric ** Read and interpret lines 5454314Seric */ 5464314Seric 5479368Seric FileName = aliasfile; 5489368Seric LineNumber = 0; 5494322Seric naliases = bytes = longest = 0; 5504098Seric skipping = FALSE; 5514098Seric while (fgets(line, sizeof (line), af) != NULL) 5524098Seric { 5534322Seric int lhssize, rhssize; 5544322Seric 5559368Seric LineNumber++; 55656795Seric p = strchr(line, '\n'); 55725278Seric if (p != NULL) 55825278Seric *p = '\0'; 5594098Seric switch (line[0]) 5604098Seric { 5614098Seric case '#': 5624098Seric case '\0': 5634098Seric skipping = FALSE; 5644098Seric continue; 5654065Seric 5664098Seric case ' ': 5674098Seric case '\t': 5684098Seric if (!skipping) 5699368Seric syserr("Non-continuation line starts with space"); 5704098Seric skipping = TRUE; 5714097Seric continue; 5724098Seric } 5734098Seric skipping = FALSE; 5741874Seric 5754314Seric /* 5764314Seric ** Process the LHS 577*57736Seric ** Find the colon separator, and parse the address. 57816898Seric ** It should resolve to a local name -- this will 57916898Seric ** be checked later (we want to optionally do 58016898Seric ** parsing of the RHS first to maximize error 58116898Seric ** detection). 5824314Seric */ 5834314Seric 5844098Seric for (p = line; *p != '\0' && *p != ':' && *p != '\n'; p++) 5854097Seric continue; 58616898Seric if (*p++ != ':') 5874098Seric { 5889368Seric syserr("missing colon"); 5894097Seric continue; 5904098Seric } 59155012Seric if (parseaddr(line, &al, 1, ':', e) == NULL) 5924098Seric { 59316898Seric syserr("illegal alias name"); 59416898Seric continue; 5954098Seric } 59616898Seric loweraddr(&al); 5974314Seric 5984314Seric /* 5994314Seric ** Process the RHS. 6004314Seric ** 'al' is the internal form of the LHS address. 6014314Seric ** 'p' points to the text of the RHS. 6024314Seric */ 6034314Seric 6044098Seric rhs = p; 6054098Seric for (;;) 6064098Seric { 6074098Seric register char c; 6081515Seric 60925821Seric if (init && CheckAliases) 6104098Seric { 6114157Seric /* do parsing & compression of addresses */ 61225278Seric while (*p != '\0') 6134098Seric { 61425278Seric extern char *DelimChar; 61525278Seric 61625278Seric while (isspace(*p) || *p == ',') 6174157Seric p++; 61825278Seric if (*p == '\0') 61925278Seric break; 62055012Seric if (parseaddr(p, &bl, -1, ',', e) == NULL) 62125278Seric usrerr("%s... bad address", p); 62225278Seric p = DelimChar; 6234098Seric } 6244098Seric } 6254157Seric else 62615769Seric { 62716898Seric p = &p[strlen(p)]; 62816898Seric if (p[-1] == '\n') 62916898Seric *--p = '\0'; 63015769Seric } 6311515Seric 6324098Seric /* see if there should be a continuation line */ 6334106Seric c = fgetc(af); 6344106Seric if (!feof(af)) 6354314Seric (void) ungetc(c, af); 6364106Seric if (c != ' ' && c != '\t') 6374098Seric break; 6384098Seric 6394098Seric /* read continuation line */ 6404098Seric if (fgets(p, sizeof line - (p - line), af) == NULL) 6414098Seric break; 6429368Seric LineNumber++; 64357135Seric 64457135Seric /* check for line overflow */ 64557135Seric if (strchr(p, '\n') == NULL) 64657135Seric { 64757135Seric usrerr("alias too long"); 64857135Seric break; 64957135Seric } 6504098Seric } 65116898Seric if (al.q_mailer != LocalMailer) 65216898Seric { 65316898Seric syserr("cannot alias non-local names"); 65416898Seric continue; 65516898Seric } 6564314Seric 6574314Seric /* 6584314Seric ** Insert alias into symbol table or DBM file 6594314Seric */ 6604314Seric 66116898Seric lhssize = strlen(al.q_user) + 1; 66257381Seric if (!bitnset(M_USR_UPPER, al.q_mailer->m_flags)) 66357381Seric makelower(al.q_user); 6644322Seric rhssize = strlen(rhs) + 1; 6654322Seric 66656845Seric # if defined(NDBM) || defined(NEWDB) 6674157Seric if (init) 6684157Seric { 66956845Seric DBdatum key, content; 67057381Seric int putstat; 6714157Seric 67256845Seric key.xx.size = lhssize; 67356845Seric key.xx.data = al.q_user; 67456845Seric content.xx.size = rhssize; 67556845Seric content.xx.data = rhs; 67651756Seric # ifdef NEWDB 67757381Seric putstat = dbp->put(dbp, &key.dbt, &content.dbt, 67857381Seric R_NOOVERWRITE); 67957381Seric if (putstat > 0) 68057381Seric { 68157381Seric usrerr("Warning: duplicate alias name %s", 68257381Seric al.q_user); 68357381Seric putstat = dbp->put(dbp, &key.dbt, 68457381Seric &content.dbt, 0); 68557381Seric } 68657381Seric if (putstat != 0) 68750576Seric syserr("readaliases: db put (%s)", al.q_user); 68850575Seric # endif 68953742Seric # ifdef IF_MAKEDBMFILES 69053742Seric IF_MAKEDBMFILES 69157381Seric { 69257381Seric putstat = dbm_store(dbmp, key.dbm, content.dbm, 69357381Seric DBM_INSERT); 69457381Seric if (putstat > 0) 69557381Seric { 69657381Seric usrerr("Warning: duplicate alias name %s", 69757381Seric al.q_user); 69857381Seric putstat = dbm_store(dbmp, key.dbm, 69957381Seric content.dbm, DBM_REPLACE); 70057381Seric } 70157381Seric if (putstat != 0) 70256845Seric syserr("readaliases: dbm store (%s)", 70356845Seric al.q_user); 70457381Seric } 70553742Seric # endif 70657381Seric if (al.q_paddr != NULL) 70757381Seric free(al.q_paddr); 70857381Seric if (al.q_host != NULL) 70957381Seric free(al.q_host); 71057381Seric if (al.q_user != NULL) 71157381Seric free(al.q_user); 7124157Seric } 7134157Seric else 71456845Seric # endif /* NDBM */ 7154157Seric { 7164157Seric s = stab(al.q_user, ST_ALIAS, ST_ENTER); 7174157Seric s->s_alias = newstr(rhs); 7184157Seric } 7194322Seric 7204322Seric /* statistics */ 7214322Seric naliases++; 7224322Seric bytes += lhssize + rhssize; 7234322Seric if (rhssize > longest) 7244322Seric longest = rhssize; 7251515Seric } 72619784Seric 72756845Seric # if defined(NDBM) || defined(NEWDB) 72819784Seric if (init) 72919784Seric { 73019784Seric /* add the distinquished alias "@" */ 73156845Seric DBdatum key; 73219784Seric 73356845Seric key.xx.size = 2; 73456845Seric key.xx.data = "@"; 73550575Seric # ifdef NEWDB 73650576Seric if (dbp->sync(dbp) != 0 || 73756845Seric dbp->put(dbp, &key.dbt, &key.dbt, 0) != 0 || 73850576Seric dbp->close(dbp) != 0) 73950576Seric syserr("readaliases: db close failure"); 74053742Seric # endif 74156789Seric # ifdef IF_MAKEDBMFILES 74256793Seric IF_MAKEDBMFILES 74356845Seric { 74456845Seric if (dbm_store(dbmp, key.dbm, key.dbm, DBM_REPLACE) != 0 || 74556845Seric dbm_error(dbmp)) 74656845Seric syserr("readaliases: dbm close failure"); 74756845Seric dbm_close(dbmp); 74856845Seric } 74950575Seric # endif 75019784Seric 75119784Seric /* restore the old signal */ 75219784Seric (void) signal(SIGINT, oldsigint); 75319784Seric } 75456845Seric # endif /* NDBM */ 75519784Seric 75619784Seric /* closing the alias file drops the lock */ 7574098Seric (void) fclose(af); 75855012Seric e->e_to = NULL; 7599368Seric FileName = NULL; 7607051Seric message(Arpa_Info, "%d aliases, longest %d bytes, %d bytes total", 7614322Seric naliases, longest, bytes); 76224944Seric # ifdef LOG 76324944Seric if (LogLevel >= 8) 76424944Seric syslog(LOG_INFO, "%d aliases, longest %d bytes, %d bytes total", 76524944Seric naliases, longest, bytes); 76656795Seric # endif /* LOG */ 767292Seric } 768292Seric /* 769292Seric ** FORWARD -- Try to forward mail 770292Seric ** 771292Seric ** This is similar but not identical to aliasing. 772292Seric ** 773292Seric ** Parameters: 7744314Seric ** user -- the name of the user who's mail we would like 7754314Seric ** to forward to. It must have been verified -- 7764314Seric ** i.e., the q_home field must have been filled 7774314Seric ** in. 7784999Seric ** sendq -- a pointer to the head of the send queue to 7794999Seric ** put this user's aliases in. 780292Seric ** 781292Seric ** Returns: 7824098Seric ** none. 783292Seric ** 784292Seric ** Side Effects: 7853185Seric ** New names are added to send queues. 786292Seric */ 787292Seric 78855012Seric forward(user, sendq, e) 7892966Seric ADDRESS *user; 7904999Seric ADDRESS **sendq; 79155012Seric register ENVELOPE *e; 792292Seric { 79357136Seric char *pp; 79457136Seric char *ep; 7954536Seric extern bool safefile(); 7964069Seric 7977671Seric if (tTd(27, 1)) 7984098Seric printf("forward(%s)\n", user->q_paddr); 7994098Seric 8004594Seric if (user->q_mailer != LocalMailer || bitset(QBADADDR, user->q_flags)) 8014098Seric return; 8024314Seric if (user->q_home == NULL) 8034314Seric syserr("forward: no home"); 8044069Seric 8054069Seric /* good address -- look for .forward file in home */ 80655012Seric define('z', user->q_home, e); 80757136Seric define('u', user->q_user, e); 80857136Seric define('h', user->q_host, e); 80957136Seric if (ForwardPath == NULL) 81057136Seric ForwardPath = newstr("\001z/.forward"); 81157136Seric 81257136Seric for (pp = ForwardPath; pp != NULL; pp = ep) 81357136Seric { 81457232Seric char buf[MAXPATHLEN+1]; 81557136Seric 81657136Seric ep = strchr(pp, ':'); 81757136Seric if (ep != NULL) 81857136Seric *ep = '\0'; 81957136Seric expand(pp, buf, &buf[sizeof buf - 1], e); 82057136Seric if (ep != NULL) 82157136Seric *ep++ = ':'; 82257136Seric if (tTd(27, 3)) 82357136Seric printf("forward: trying %s\n", buf); 82457136Seric if (include(buf, TRUE, user, sendq, e) == 0) 82557136Seric break; 82657136Seric } 827292Seric } 828