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> 1157948Seric # 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*58059Seric static char sccsid[] = "@(#)alias.c 6.12 (Berkeley) 02/19/93 (with NEWDB and NDBM)"; 3351756Seric #else 34*58059Seric static char sccsid[] = "@(#)alias.c 6.12 (Berkeley) 02/19/93 (with NEWDB)"; 3557736Seric #endif 3657736Seric #else 3756845Seric #ifdef NDBM 38*58059Seric static char sccsid[] = "@(#)alias.c 6.12 (Berkeley) 02/19/93 (with NDBM)"; 3933728Sbostic #else 40*58059Seric static char sccsid[] = "@(#)alias.c 6.12 (Berkeley) 02/19/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); 14657977Seric #ifdef LOG 14758020Seric if (LogLevel > 9) 14857977Seric syslog(LOG_INFO, "%s: alias %s => %s", e->e_id, a->q_paddr, p); 14957977Seric #endif 1504098Seric AliasLevel++; 15155012Seric sendtolist(p, a, sendq, e); 1524098Seric AliasLevel--; 1534098Seric } 1544098Seric /* 1555701Seric ** ALIASLOOKUP -- look up a name in the alias file. 1565701Seric ** 1575701Seric ** Parameters: 1585701Seric ** name -- the name to look up. 1595701Seric ** 1605701Seric ** Returns: 1615701Seric ** the value of name. 1625701Seric ** NULL if unknown. 1635701Seric ** 1645701Seric ** Side Effects: 1655701Seric ** none. 1665701Seric ** 1675701Seric ** Warnings: 1685701Seric ** The return value will be trashed across calls. 1695701Seric */ 1705701Seric 1715701Seric char * 1725701Seric aliaslookup(name) 1735701Seric char *name; 1745701Seric { 17557381Seric int i; 17657381Seric char keybuf[MAXNAME + 1]; 17756845Seric # if defined(NEWDB) || defined(NDBM) 17856845Seric DBdatum rhs, lhs; 17950575Seric int s; 18057381Seric # else /* neither NEWDB nor NDBM */ 18157381Seric register STAB *s; 18257381Seric # endif 1835701Seric 1845701Seric /* create a key for fetch */ 18557381Seric i = strlen(name) + 1; 18657381Seric if (i > sizeof keybuf) 18757381Seric i = sizeof keybuf; 18857381Seric bcopy(name, keybuf, i); 18957381Seric if (!bitnset(M_USR_UPPER, LocalMailer->m_flags)) 19057381Seric makelower(keybuf); 19157381Seric 19257381Seric # if defined(NEWDB) || defined(NDBM) 19357381Seric lhs.xx.size = i; 19457381Seric lhs.xx.data = keybuf; 19550575Seric # ifdef NEWDB 19651756Seric if (AliasDBptr != NULL) 19751756Seric { 19857381Seric i = AliasDBptr->get(AliasDBptr, &lhs.dbt, &rhs.dbt, 0); 19957381Seric if (i == 0) 20056845Seric return (rhs.dbt.data); 20151756Seric } 20256845Seric # ifdef NDBM 20357249Seric else if (AliasDBMptr != NULL) 20451756Seric { 20556845Seric rhs.dbm = dbm_fetch(AliasDBMptr, lhs.dbm); 20656845Seric return (rhs.dbm.dptr); 20751756Seric } 20856845Seric # endif /* NDBM */ 20957530Seric return (NULL); 21056845Seric # else /* not NEWDB */ 21156845Seric rhs.dbm = dbm_fetch(AliasDBMptr, lhs.dbm); 21256845Seric return (rhs.dbm.dptr); 21356845Seric # endif /* NEWDB */ 21456845Seric # else /* neither NEWDB nor NDBM */ 21557381Seric s = stab(keybuf, ST_ALIAS, ST_FIND); 21651756Seric if (s != NULL) 21751756Seric return (s->s_alias); 21857530Seric return (NULL); 21951756Seric # endif 2205701Seric } 2215701Seric /* 2224098Seric ** INITALIASES -- initialize for aliasing 2234098Seric ** 22456845Seric ** Very different depending on whether we are running NDBM or not. 2254098Seric ** 2264098Seric ** Parameters: 2274098Seric ** aliasfile -- location of aliases. 22856845Seric ** init -- if set and if NDBM, initialize the NDBM files. 2294098Seric ** 2304098Seric ** Returns: 2314098Seric ** none. 2324098Seric ** 2334098Seric ** Side Effects: 2344098Seric ** initializes aliases: 23556845Seric ** if NDBM: opens the database. 23656845Seric ** if ~NDBM: reads the aliases into the symbol table. 2374098Seric */ 2384098Seric 23940559Sbostic # define DBMMODE 0644 2404157Seric 24155012Seric initaliases(aliasfile, init, e) 2424098Seric char *aliasfile; 2434157Seric bool init; 24455012Seric register ENVELOPE *e; 2454098Seric { 24656845Seric #if defined(NDBM) || defined(NEWDB) 2478437Seric int atcnt; 24825522Seric time_t modtime; 24925522Seric bool automatic = FALSE; 2504322Seric char buf[MAXNAME]; 25150575Seric #endif 2529368Seric struct stat stb; 25327176Seric static bool initialized = FALSE; 25446928Sbostic static int readaliases(); 2554322Seric 25627176Seric if (initialized) 25727176Seric return; 25827176Seric initialized = TRUE; 25927176Seric 26017984Seric if (aliasfile == NULL || stat(aliasfile, &stb) < 0) 2618437Seric { 26225522Seric if (aliasfile != NULL && init) 26325522Seric syserr("Cannot open %s", aliasfile); 2648437Seric NoAlias = TRUE; 26511937Seric errno = 0; 2668437Seric return; 2678437Seric } 2688437Seric 26956845Seric # if defined(NDBM) || defined(NEWDB) 2704322Seric /* 2718437Seric ** Check to see that the alias file is complete. 2728437Seric ** If not, we will assume that someone died, and it is up 2738437Seric ** to us to rebuild it. 2748437Seric */ 2758437Seric 27625689Seric if (!init) 27750575Seric { 27850575Seric # ifdef NEWDB 27950575Seric (void) strcpy(buf, aliasfile); 28050575Seric (void) strcat(buf, ".db"); 28151171Sbostic AliasDBptr = dbopen(buf, O_RDONLY, DBMMODE, DB_HASH, NULL); 28250576Seric if (AliasDBptr == NULL) 28350576Seric { 28456845Seric # ifdef NDBM 28556845Seric AliasDBMptr = dbm_open(aliasfile, O_RDONLY, DBMMODE); 28657249Seric if (AliasDBMptr == NULL) 28757249Seric { 28857249Seric syserr("initaliases: cannot open %s", buf); 28957249Seric NoAlias = TRUE; 29057249Seric return; 29157249Seric } 29251756Seric # else 29350576Seric syserr("initaliases: cannot open %s", buf); 29450576Seric NoAlias = TRUE; 29550576Seric return; 29651756Seric # endif 29750576Seric } 29850575Seric # else 29956845Seric AliasDBMptr = dbm_open(aliasfile, O_RDONLY, DBMMODE); 30057249Seric if (AliasDBMptr == NULL) 30157249Seric { 30257977Seric syserr("initaliases: cannot open DBM database %s.{pag,dir}", 30357977Seric aliasfile); 30457249Seric NoAlias = TRUE; 30557249Seric return; 30657249Seric } 30750575Seric # endif 30850575Seric } 30917471Seric atcnt = SafeAlias * 2; 31017471Seric if (atcnt > 0) 31117471Seric { 31217471Seric while (!init && atcnt-- >= 0 && aliaslookup("@") == NULL) 31325689Seric { 31425689Seric /* 31525689Seric ** Reinitialize alias file in case the new 31625689Seric ** one is mv'ed in instead of cp'ed in. 31725689Seric ** 31825689Seric ** Only works with new DBM -- old one will 31925689Seric ** just consume file descriptors forever. 32025689Seric ** If you have a dbmclose() it can be 32125689Seric ** added before the sleep(30). 32225689Seric */ 32325689Seric 32450575Seric # ifdef NEWDB 32551756Seric if (AliasDBptr != NULL) 32651756Seric AliasDBptr->close(AliasDBptr); 32750575Seric # endif 32856845Seric # ifdef NDBM 32956845Seric if (AliasDBMptr != NULL) 33056845Seric dbm_close(AliasDBMptr); 33156845Seric # endif 33250575Seric 33317471Seric sleep(30); 33450575Seric # ifdef NEWDB 33550575Seric (void) strcpy(buf, aliasfile); 33650575Seric (void) strcat(buf, ".db"); 33751171Sbostic AliasDBptr = 33851171Sbostic dbopen(buf, O_RDONLY, DBMMODE, DB_HASH, NULL); 33950576Seric if (AliasDBptr == NULL) 34050576Seric { 34151756Seric # ifdef NDBM 34256845Seric AliasDBMptr = dbm_open(aliasfile, O_RDONLY, DBMMODE); 34351756Seric # else 34450576Seric syserr("initaliases: cannot open %s", buf); 34550576Seric NoAlias = TRUE; 34650576Seric return; 34751756Seric # endif 34850576Seric } 34950575Seric # else 35025689Seric # ifdef NDBM 35156845Seric AliasDBMptr = dbm_open(aliasfile, O_RDONLY, DBMMODE); 35257249Seric if (AliasDBMptr == NULL) 35357249Seric { 35458008Seric syserr("initaliases: cannot open DBM database %s.{pag,dir}", 35558008Seric aliasfile); 35657249Seric NoAlias = TRUE; 35757249Seric return; 35857249Seric } 35950575Seric # endif 36050575Seric # endif 36125689Seric } 36217471Seric } 36317471Seric else 36417471Seric atcnt = 1; 3658437Seric 3668437Seric /* 36756845Seric ** See if the NDBM version of the file is out of date with 3684322Seric ** the text version. If so, go into 'init' mode automatically. 36940559Sbostic ** This only happens if our effective userid owns the DBM. 37040559Sbostic ** Note the unpalatable hack to see if the stat succeeded. 3714322Seric */ 3724322Seric 3734322Seric modtime = stb.st_mtime; 3744322Seric (void) strcpy(buf, aliasfile); 37550575Seric # ifdef NEWDB 37650575Seric (void) strcat(buf, ".db"); 37750575Seric # else 3784322Seric (void) strcat(buf, ".pag"); 37950575Seric # endif 3804322Seric stb.st_ino = 0; 38119039Seric if (!init && (stat(buf, &stb) < 0 || stb.st_mtime < modtime || atcnt < 0)) 3824322Seric { 38311937Seric errno = 0; 38440559Sbostic if (AutoRebuild && stb.st_ino != 0 && stb.st_uid == geteuid()) 3854322Seric { 3864322Seric init = TRUE; 38725522Seric automatic = TRUE; 3887051Seric message(Arpa_Info, "rebuilding alias database"); 38924944Seric #ifdef LOG 39058020Seric if (LogLevel > 14) 39124944Seric syslog(LOG_INFO, "rebuilding alias database"); 39256795Seric #endif /* LOG */ 3934322Seric } 3944322Seric else 3954322Seric { 39619039Seric #ifdef LOG 39758020Seric if (LogLevel > 3) 39824944Seric syslog(LOG_INFO, "alias database out of date"); 39956795Seric #endif /* LOG */ 4004322Seric message(Arpa_Info, "Warning: alias database out of date"); 4014322Seric } 4024322Seric } 4034322Seric 4044322Seric 4054322Seric /* 40656845Seric ** If necessary, load the NDBM file. 40756845Seric ** If running without NDBM, load the symbol table. 4084322Seric */ 4094322Seric 4104157Seric if (init) 4118437Seric { 41225522Seric #ifdef LOG 41358020Seric if (LogLevel > 7) 41425522Seric { 41525522Seric extern char *username(); 41625522Seric 41725522Seric syslog(LOG_NOTICE, "alias database %srebuilt by %s", 41825522Seric automatic ? "auto" : "", username()); 41925522Seric } 42056795Seric #endif /* LOG */ 42155012Seric readaliases(aliasfile, TRUE, e); 4228437Seric } 42356845Seric # else /* NDBM */ 42455012Seric readaliases(aliasfile, init, e); 42556845Seric # endif /* NDBM */ 4264157Seric } 4274157Seric /* 4284157Seric ** READALIASES -- read and process the alias file. 4294157Seric ** 4304157Seric ** This routine implements the part of initaliases that occurs 4314157Seric ** when we are not going to use the DBM stuff. 4324157Seric ** 4334157Seric ** Parameters: 4344157Seric ** aliasfile -- the pathname of the alias file master. 43556845Seric ** init -- if set, initialize the NDBM stuff. 4364157Seric ** 4374157Seric ** Returns: 4384157Seric ** none. 4394157Seric ** 4404157Seric ** Side Effects: 4414157Seric ** Reads aliasfile into the symbol table. 4424157Seric ** Optionally, builds the .dir & .pag files. 4434157Seric */ 4444157Seric 4454157Seric static 44655012Seric readaliases(aliasfile, init, e) 4474157Seric char *aliasfile; 4484157Seric bool init; 44955012Seric register ENVELOPE *e; 4504157Seric { 4514098Seric register char *p; 4524098Seric char *rhs; 4534098Seric bool skipping; 4549368Seric int naliases, bytes, longest; 4559368Seric FILE *af; 45653742Seric bool makedbmfiles; 45740970Sbostic void (*oldsigint)(); 4584098Seric ADDRESS al, bl; 4594106Seric register STAB *s; 46050575Seric # ifdef NEWDB 46150575Seric DB *dbp; 46250575Seric # endif 46356845Seric # ifdef NDBM 46456845Seric DBM *dbmp; 46556845Seric # endif 46651937Seric # ifdef LOCKF 46751937Seric struct flock fld; 46851937Seric # endif 4699368Seric char line[BUFSIZ]; 4704098Seric 47151937Seric if ((af = fopen(aliasfile, "r+")) == NULL) 4721515Seric { 47357249Seric if (init) 47457249Seric syserr("Can't open %s", aliasfile); 47557249Seric else if (tTd(27, 1)) 4764106Seric printf("Can't open %s\n", aliasfile); 4774098Seric errno = 0; 4784098Seric NoAlias++; 4794098Seric return; 4804098Seric } 4814314Seric 48256845Seric # if defined(NDBM) || defined(NEWDB) 48319784Seric /* see if someone else is rebuilding the alias file already */ 48451835Seric # ifdef LOCKF 48551937Seric fld.l_type = F_WRLCK; 48651937Seric fld.l_whence = fld.l_start = fld.l_len = 0; 48751937Seric if (fcntl(fileno(af), F_SETLK, &fld) < 0) 48851835Seric # else 48919784Seric if (flock(fileno(af), LOCK_EX | LOCK_NB) < 0 && errno == EWOULDBLOCK) 49051835Seric # endif 49119784Seric { 49219784Seric /* yes, they are -- wait until done and then return */ 49319784Seric message(Arpa_Info, "Alias file is already being rebuilt"); 49419784Seric if (OpMode != MD_INITALIAS) 49519784Seric { 49619784Seric /* wait for other rebuild to complete */ 49751835Seric # ifdef LOCKF 49851937Seric (void) fcntl(fileno(af), F_SETLKW, &fld); 49951835Seric # else 50019784Seric (void) flock(fileno(af), LOCK_EX); 50151835Seric # endif 50219784Seric } 50323108Seric (void) fclose(af); 50419784Seric errno = 0; 50519784Seric return; 50619784Seric } 50756845Seric # endif /* NDBM */ 50819784Seric 5094314Seric /* 51019784Seric ** If initializing, create the new DBM files. 51119784Seric */ 51219784Seric 51319784Seric if (init) 51419784Seric { 51519784Seric oldsigint = signal(SIGINT, SIG_IGN); 51651756Seric # ifdef NEWDB 51751756Seric (void) strcpy(line, aliasfile); 51851756Seric (void) strcat(line, ".db"); 51951756Seric dbp = dbopen(line, 52051756Seric O_RDWR|O_CREAT|O_TRUNC, DBMMODE, DB_HASH, NULL); 52151756Seric if (dbp == NULL) 52251756Seric { 52351756Seric syserr("readaliases: cannot create %s", line); 52451756Seric (void) signal(SIGINT, oldsigint); 52551756Seric return; 52651756Seric } 52753742Seric # endif 52853742Seric # ifdef IF_MAKEDBMFILES 52953742Seric # ifdef NEWDB 53053742Seric makedbmfiles = access("/var/yp/Makefile", R_OK) == 0; 53153742Seric # endif 53253742Seric IF_MAKEDBMFILES 53319784Seric { 53456845Seric dbmp = dbm_open(aliasfile, 53556845Seric O_RDWR|O_CREAT|O_TRUNC, DBMMODE); 53656845Seric if (dbmp == NULL) 53753742Seric { 53856845Seric syserr("readaliases: cannot create %s.{dir,pag}", 53956845Seric aliasfile); 54053742Seric (void) signal(SIGINT, oldsigint); 54153742Seric return; 54253742Seric } 54319784Seric } 54450575Seric # endif 54519784Seric } 54619784Seric 54719784Seric /* 5484314Seric ** Read and interpret lines 5494314Seric */ 5504314Seric 5519368Seric FileName = aliasfile; 5529368Seric LineNumber = 0; 5534322Seric naliases = bytes = longest = 0; 5544098Seric skipping = FALSE; 5554098Seric while (fgets(line, sizeof (line), af) != NULL) 5564098Seric { 5574322Seric int lhssize, rhssize; 5584322Seric 5599368Seric LineNumber++; 56056795Seric p = strchr(line, '\n'); 56125278Seric if (p != NULL) 56225278Seric *p = '\0'; 5634098Seric switch (line[0]) 5644098Seric { 5654098Seric case '#': 5664098Seric case '\0': 5674098Seric skipping = FALSE; 5684098Seric continue; 5694065Seric 5704098Seric case ' ': 5714098Seric case '\t': 5724098Seric if (!skipping) 5739368Seric syserr("Non-continuation line starts with space"); 5744098Seric skipping = TRUE; 5754097Seric continue; 5764098Seric } 5774098Seric skipping = FALSE; 5781874Seric 5794314Seric /* 5804314Seric ** Process the LHS 58157736Seric ** Find the colon separator, and parse the address. 58216898Seric ** It should resolve to a local name -- this will 58316898Seric ** be checked later (we want to optionally do 58416898Seric ** parsing of the RHS first to maximize error 58516898Seric ** detection). 5864314Seric */ 5874314Seric 5884098Seric for (p = line; *p != '\0' && *p != ':' && *p != '\n'; p++) 5894097Seric continue; 59016898Seric if (*p++ != ':') 5914098Seric { 5929368Seric syserr("missing colon"); 5934097Seric continue; 5944098Seric } 59555012Seric if (parseaddr(line, &al, 1, ':', e) == NULL) 5964098Seric { 59716898Seric syserr("illegal alias name"); 59816898Seric continue; 5994098Seric } 60016898Seric loweraddr(&al); 6014314Seric 6024314Seric /* 6034314Seric ** Process the RHS. 6044314Seric ** 'al' is the internal form of the LHS address. 6054314Seric ** 'p' points to the text of the RHS. 6064314Seric */ 6074314Seric 6084098Seric rhs = p; 6094098Seric for (;;) 6104098Seric { 6114098Seric register char c; 6121515Seric 61325821Seric if (init && CheckAliases) 6144098Seric { 6154157Seric /* do parsing & compression of addresses */ 61625278Seric while (*p != '\0') 6174098Seric { 61825278Seric extern char *DelimChar; 61925278Seric 62058050Seric while ((isascii(*p) && isspace(*p)) || 62158050Seric *p == ',') 6224157Seric p++; 62325278Seric if (*p == '\0') 62425278Seric break; 62555012Seric if (parseaddr(p, &bl, -1, ',', e) == NULL) 62625278Seric usrerr("%s... bad address", p); 62725278Seric p = DelimChar; 6284098Seric } 6294098Seric } 6304157Seric else 63115769Seric { 63216898Seric p = &p[strlen(p)]; 63316898Seric if (p[-1] == '\n') 63416898Seric *--p = '\0'; 63515769Seric } 6361515Seric 6374098Seric /* see if there should be a continuation line */ 6384106Seric c = fgetc(af); 6394106Seric if (!feof(af)) 6404314Seric (void) ungetc(c, af); 6414106Seric if (c != ' ' && c != '\t') 6424098Seric break; 6434098Seric 6444098Seric /* read continuation line */ 6454098Seric if (fgets(p, sizeof line - (p - line), af) == NULL) 6464098Seric break; 6479368Seric LineNumber++; 64857135Seric 64957135Seric /* check for line overflow */ 65057135Seric if (strchr(p, '\n') == NULL) 65157135Seric { 65257135Seric usrerr("alias too long"); 65357135Seric break; 65457135Seric } 6554098Seric } 65616898Seric if (al.q_mailer != LocalMailer) 65716898Seric { 65816898Seric syserr("cannot alias non-local names"); 65916898Seric continue; 66016898Seric } 6614314Seric 6624314Seric /* 6634314Seric ** Insert alias into symbol table or DBM file 6644314Seric */ 6654314Seric 66616898Seric lhssize = strlen(al.q_user) + 1; 66757381Seric if (!bitnset(M_USR_UPPER, al.q_mailer->m_flags)) 66857381Seric makelower(al.q_user); 6694322Seric rhssize = strlen(rhs) + 1; 6704322Seric 67156845Seric # if defined(NDBM) || defined(NEWDB) 6724157Seric if (init) 6734157Seric { 67456845Seric DBdatum key, content; 67557381Seric int putstat; 6764157Seric 67756845Seric key.xx.size = lhssize; 67856845Seric key.xx.data = al.q_user; 67956845Seric content.xx.size = rhssize; 68056845Seric content.xx.data = rhs; 68151756Seric # ifdef NEWDB 68257381Seric putstat = dbp->put(dbp, &key.dbt, &content.dbt, 68357381Seric R_NOOVERWRITE); 68457381Seric if (putstat > 0) 68557381Seric { 68657977Seric usrerr("050 Warning: duplicate alias name %s", 68757381Seric al.q_user); 68857381Seric putstat = dbp->put(dbp, &key.dbt, 68957381Seric &content.dbt, 0); 69057381Seric } 69157381Seric if (putstat != 0) 69250576Seric syserr("readaliases: db put (%s)", al.q_user); 69350575Seric # endif 69453742Seric # ifdef IF_MAKEDBMFILES 69553742Seric IF_MAKEDBMFILES 69657381Seric { 69757381Seric putstat = dbm_store(dbmp, key.dbm, content.dbm, 69857381Seric DBM_INSERT); 69957381Seric if (putstat > 0) 70057381Seric { 70157977Seric usrerr("050 Warning: duplicate alias name %s", 70257381Seric al.q_user); 70357381Seric putstat = dbm_store(dbmp, key.dbm, 70457381Seric content.dbm, DBM_REPLACE); 70557381Seric } 70657381Seric if (putstat != 0) 70756845Seric syserr("readaliases: dbm store (%s)", 70856845Seric al.q_user); 70957381Seric } 71053742Seric # endif 71157381Seric if (al.q_paddr != NULL) 71257381Seric free(al.q_paddr); 71357381Seric if (al.q_host != NULL) 71457381Seric free(al.q_host); 71557381Seric if (al.q_user != NULL) 71657381Seric free(al.q_user); 7174157Seric } 7184157Seric else 71956845Seric # endif /* NDBM */ 7204157Seric { 7214157Seric s = stab(al.q_user, ST_ALIAS, ST_ENTER); 7224157Seric s->s_alias = newstr(rhs); 7234157Seric } 7244322Seric 7254322Seric /* statistics */ 7264322Seric naliases++; 7274322Seric bytes += lhssize + rhssize; 7284322Seric if (rhssize > longest) 7294322Seric longest = rhssize; 7301515Seric } 73119784Seric 73256845Seric # if defined(NDBM) || defined(NEWDB) 73319784Seric if (init) 73419784Seric { 73519784Seric /* add the distinquished alias "@" */ 73656845Seric DBdatum key; 73719784Seric 73856845Seric key.xx.size = 2; 73956845Seric key.xx.data = "@"; 74050575Seric # ifdef NEWDB 74150576Seric if (dbp->sync(dbp) != 0 || 74256845Seric dbp->put(dbp, &key.dbt, &key.dbt, 0) != 0 || 74350576Seric dbp->close(dbp) != 0) 74450576Seric syserr("readaliases: db close failure"); 74553742Seric # endif 74656789Seric # ifdef IF_MAKEDBMFILES 74756793Seric IF_MAKEDBMFILES 74856845Seric { 749*58059Seric #ifdef YPCOMPAT 750*58059Seric nis_magic(dbmp); 751*58059Seric #endif 75256845Seric if (dbm_store(dbmp, key.dbm, key.dbm, DBM_REPLACE) != 0 || 75356845Seric dbm_error(dbmp)) 75456845Seric syserr("readaliases: dbm close failure"); 75556845Seric dbm_close(dbmp); 75656845Seric } 75750575Seric # endif 75819784Seric 75919784Seric /* restore the old signal */ 76019784Seric (void) signal(SIGINT, oldsigint); 76119784Seric } 76256845Seric # endif /* NDBM */ 76319784Seric 76419784Seric /* closing the alias file drops the lock */ 7654098Seric (void) fclose(af); 76655012Seric e->e_to = NULL; 7679368Seric FileName = NULL; 7687051Seric message(Arpa_Info, "%d aliases, longest %d bytes, %d bytes total", 7694322Seric naliases, longest, bytes); 77024944Seric # ifdef LOG 77158020Seric if (LogLevel > 7) 77224944Seric syslog(LOG_INFO, "%d aliases, longest %d bytes, %d bytes total", 77324944Seric naliases, longest, bytes); 77456795Seric # endif /* LOG */ 775292Seric } 776292Seric /* 777*58059Seric ** NIS_MAGIC -- Add NIS magic dbm data 778*58059Seric ** 779*58059Seric ** This adds the magic entries needed by SunOS to make this a valid 780*58059Seric ** NIS map. 781*58059Seric ** 782*58059Seric ** Parameters: 783*58059Seric ** dbmp -- a pointer to the DBM structure. 784*58059Seric ** 785*58059Seric ** Returns: 786*58059Seric ** none. 787*58059Seric */ 788*58059Seric 789*58059Seric # ifdef YPCOMPAT 790*58059Seric 791*58059Seric static void 792*58059Seric nis_magic(dbmp) 793*58059Seric DBM *dbmp; 794*58059Seric { 795*58059Seric int i; 796*58059Seric static datum key[2] = 797*58059Seric { 798*58059Seric { "YP_LAST_MODIFIED", sizeof "YP_LAST_MODIFIED" - 1 }, 799*58059Seric { "YP_MASTER_NAME", sizeof "YP_MASTER_NAME" - 1 }, 800*58059Seric }; 801*58059Seric datum contents[2]; 802*58059Seric char tbuf[12]; 803*58059Seric char hbuf[MAXHOSTNAMELEN]; 804*58059Seric 805*58059Seric (void) sprintf(tbuf, "%010ld", curtime()); 806*58059Seric contents[0].dptr = tbuf; 807*58059Seric contents[0].dsize = strlen(tbuf); 808*58059Seric 809*58059Seric (void) myhostname(hbuf, sizeof hbuf); 810*58059Seric contents[1].dptr = hbuf; 811*58059Seric contents[1].dptr = strlen(hbuf); 812*58059Seric 813*58059Seric for (i = 0; i < sizeof key / sizeof *key; i++) 814*58059Seric { 815*58059Seric if (dbm_store(dbmp, key[i], contents[i], DBM_REPLACE) != 0 || 816*58059Seric dbm_error(dbmp)) 817*58059Seric syserr("nis_magic: dbm_store failure"); 818*58059Seric } 819*58059Seric } 820*58059Seric 821*58059Seric # endif 822*58059Seric /* 823292Seric ** FORWARD -- Try to forward mail 824292Seric ** 825292Seric ** This is similar but not identical to aliasing. 826292Seric ** 827292Seric ** Parameters: 8284314Seric ** user -- the name of the user who's mail we would like 8294314Seric ** to forward to. It must have been verified -- 8304314Seric ** i.e., the q_home field must have been filled 8314314Seric ** in. 8324999Seric ** sendq -- a pointer to the head of the send queue to 8334999Seric ** put this user's aliases in. 834292Seric ** 835292Seric ** Returns: 8364098Seric ** none. 837292Seric ** 838292Seric ** Side Effects: 8393185Seric ** New names are added to send queues. 840292Seric */ 841292Seric 84255012Seric forward(user, sendq, e) 8432966Seric ADDRESS *user; 8444999Seric ADDRESS **sendq; 84555012Seric register ENVELOPE *e; 846292Seric { 84757136Seric char *pp; 84857136Seric char *ep; 8494536Seric extern bool safefile(); 8504069Seric 8517671Seric if (tTd(27, 1)) 8524098Seric printf("forward(%s)\n", user->q_paddr); 8534098Seric 8544594Seric if (user->q_mailer != LocalMailer || bitset(QBADADDR, user->q_flags)) 8554098Seric return; 8564314Seric if (user->q_home == NULL) 857*58059Seric { 8584314Seric syserr("forward: no home"); 859*58059Seric user->q_home = "/nosuchdirectory"; 860*58059Seric } 8614069Seric 8624069Seric /* good address -- look for .forward file in home */ 86355012Seric define('z', user->q_home, e); 86457136Seric define('u', user->q_user, e); 86557136Seric define('h', user->q_host, e); 86657136Seric if (ForwardPath == NULL) 86758050Seric ForwardPath = newstr("\201z/.forward"); 86857136Seric 86957136Seric for (pp = ForwardPath; pp != NULL; pp = ep) 87057136Seric { 87157232Seric char buf[MAXPATHLEN+1]; 87257136Seric 87357136Seric ep = strchr(pp, ':'); 87457136Seric if (ep != NULL) 87557136Seric *ep = '\0'; 87657136Seric expand(pp, buf, &buf[sizeof buf - 1], e); 87757136Seric if (ep != NULL) 87857136Seric *ep++ = ':'; 87957136Seric if (tTd(27, 3)) 88057136Seric printf("forward: trying %s\n", buf); 88157136Seric if (include(buf, TRUE, user, sendq, e) == 0) 88257136Seric break; 88357136Seric } 884292Seric } 885