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*58082Seric static char sccsid[] = "@(#)alias.c 6.14 (Berkeley) 02/20/93 (with NEWDB and NDBM)"; 3351756Seric #else 34*58082Seric static char sccsid[] = "@(#)alias.c 6.14 (Berkeley) 02/20/93 (with NEWDB)"; 3557736Seric #endif 3657736Seric #else 3756845Seric #ifdef NDBM 38*58082Seric static char sccsid[] = "@(#)alias.c 6.14 (Berkeley) 02/20/93 (with NDBM)"; 3933728Sbostic #else 40*58082Seric static char sccsid[] = "@(#)alias.c 6.14 (Berkeley) 02/20/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; 115*58082Seric int naliases; 1165701Seric extern char *aliaslookup(); 117292Seric 1187671Seric if (tTd(27, 1)) 1194098Seric printf("alias(%s)\n", a->q_paddr); 120292Seric 1214098Seric /* don't realias already aliased names */ 1224098Seric if (bitset(QDONTSEND, a->q_flags)) 1234098Seric return; 1244098Seric 12555012Seric e->e_to = a->q_paddr; 1264098Seric 1274314Seric /* 1284314Seric ** Look up this name 1294314Seric */ 1304314Seric 13124944Seric if (NoAlias) 13224944Seric p = NULL; 13324944Seric else 13424944Seric p = aliaslookup(a->q_user); 1354098Seric if (p == NULL) 1364098Seric return; 137292Seric 138292Seric /* 1394098Seric ** Match on Alias. 1404098Seric ** Deliver to the target list. 1411515Seric */ 1421515Seric 1437671Seric if (tTd(27, 1)) 1444098Seric printf("%s (%s, %s) aliased to %s\n", 1454098Seric a->q_paddr, a->q_host, a->q_user, p); 1467051Seric message(Arpa_Info, "aliased to %s", p); 14757977Seric #ifdef LOG 14858020Seric if (LogLevel > 9) 14957977Seric syslog(LOG_INFO, "%s: alias %s => %s", e->e_id, a->q_paddr, p); 15057977Seric #endif 151*58082Seric a->q_flags &= ~QSELFREF; 1524098Seric AliasLevel++; 153*58082Seric naliases = sendtolist(p, a, sendq, e); 1544098Seric AliasLevel--; 155*58082Seric if (naliases > 0 && !bitset(QSELFREF, a->q_flags)) 15658065Seric { 15758065Seric if (tTd(27, 5)) 15858065Seric { 15958065Seric printf("alias: QDONTSEND "); 16058065Seric printaddr(a, FALSE); 16158065Seric } 16258065Seric a->q_flags |= QDONTSEND; 16358065Seric } 1644098Seric } 1654098Seric /* 1665701Seric ** ALIASLOOKUP -- look up a name in the alias file. 1675701Seric ** 1685701Seric ** Parameters: 1695701Seric ** name -- the name to look up. 1705701Seric ** 1715701Seric ** Returns: 1725701Seric ** the value of name. 1735701Seric ** NULL if unknown. 1745701Seric ** 1755701Seric ** Side Effects: 1765701Seric ** none. 1775701Seric ** 1785701Seric ** Warnings: 1795701Seric ** The return value will be trashed across calls. 1805701Seric */ 1815701Seric 1825701Seric char * 1835701Seric aliaslookup(name) 1845701Seric char *name; 1855701Seric { 18657381Seric int i; 18757381Seric char keybuf[MAXNAME + 1]; 18856845Seric # if defined(NEWDB) || defined(NDBM) 18956845Seric DBdatum rhs, lhs; 19050575Seric int s; 19157381Seric # else /* neither NEWDB nor NDBM */ 19257381Seric register STAB *s; 19357381Seric # endif 1945701Seric 1955701Seric /* create a key for fetch */ 19657381Seric i = strlen(name) + 1; 19757381Seric if (i > sizeof keybuf) 19857381Seric i = sizeof keybuf; 19957381Seric bcopy(name, keybuf, i); 20057381Seric if (!bitnset(M_USR_UPPER, LocalMailer->m_flags)) 20157381Seric makelower(keybuf); 20257381Seric 20357381Seric # if defined(NEWDB) || defined(NDBM) 20457381Seric lhs.xx.size = i; 20557381Seric lhs.xx.data = keybuf; 20650575Seric # ifdef NEWDB 20751756Seric if (AliasDBptr != NULL) 20851756Seric { 20957381Seric i = AliasDBptr->get(AliasDBptr, &lhs.dbt, &rhs.dbt, 0); 21057381Seric if (i == 0) 21156845Seric return (rhs.dbt.data); 21251756Seric } 21356845Seric # ifdef NDBM 21457249Seric else if (AliasDBMptr != NULL) 21551756Seric { 21656845Seric rhs.dbm = dbm_fetch(AliasDBMptr, lhs.dbm); 21756845Seric return (rhs.dbm.dptr); 21851756Seric } 21956845Seric # endif /* NDBM */ 22057530Seric return (NULL); 22156845Seric # else /* not NEWDB */ 22256845Seric rhs.dbm = dbm_fetch(AliasDBMptr, lhs.dbm); 22356845Seric return (rhs.dbm.dptr); 22456845Seric # endif /* NEWDB */ 22556845Seric # else /* neither NEWDB nor NDBM */ 22657381Seric s = stab(keybuf, ST_ALIAS, ST_FIND); 22751756Seric if (s != NULL) 22851756Seric return (s->s_alias); 22957530Seric return (NULL); 23051756Seric # endif 2315701Seric } 2325701Seric /* 2334098Seric ** INITALIASES -- initialize for aliasing 2344098Seric ** 23556845Seric ** Very different depending on whether we are running NDBM or not. 2364098Seric ** 2374098Seric ** Parameters: 2384098Seric ** aliasfile -- location of aliases. 23956845Seric ** init -- if set and if NDBM, initialize the NDBM files. 2404098Seric ** 2414098Seric ** Returns: 2424098Seric ** none. 2434098Seric ** 2444098Seric ** Side Effects: 2454098Seric ** initializes aliases: 24656845Seric ** if NDBM: opens the database. 24756845Seric ** if ~NDBM: reads the aliases into the symbol table. 2484098Seric */ 2494098Seric 25040559Sbostic # define DBMMODE 0644 2514157Seric 25255012Seric initaliases(aliasfile, init, e) 2534098Seric char *aliasfile; 2544157Seric bool init; 25555012Seric register ENVELOPE *e; 2564098Seric { 25756845Seric #if defined(NDBM) || defined(NEWDB) 2588437Seric int atcnt; 25925522Seric time_t modtime; 26025522Seric bool automatic = FALSE; 2614322Seric char buf[MAXNAME]; 26250575Seric #endif 2639368Seric struct stat stb; 26427176Seric static bool initialized = FALSE; 26546928Sbostic static int readaliases(); 2664322Seric 26727176Seric if (initialized) 26827176Seric return; 26927176Seric initialized = TRUE; 27027176Seric 27117984Seric if (aliasfile == NULL || stat(aliasfile, &stb) < 0) 2728437Seric { 27325522Seric if (aliasfile != NULL && init) 27425522Seric syserr("Cannot open %s", aliasfile); 2758437Seric NoAlias = TRUE; 27611937Seric errno = 0; 2778437Seric return; 2788437Seric } 2798437Seric 28056845Seric # if defined(NDBM) || defined(NEWDB) 2814322Seric /* 2828437Seric ** Check to see that the alias file is complete. 2838437Seric ** If not, we will assume that someone died, and it is up 2848437Seric ** to us to rebuild it. 2858437Seric */ 2868437Seric 28725689Seric if (!init) 28850575Seric { 28950575Seric # ifdef NEWDB 29050575Seric (void) strcpy(buf, aliasfile); 29150575Seric (void) strcat(buf, ".db"); 29251171Sbostic AliasDBptr = dbopen(buf, O_RDONLY, DBMMODE, DB_HASH, NULL); 29350576Seric if (AliasDBptr == NULL) 29450576Seric { 29556845Seric # ifdef NDBM 29656845Seric AliasDBMptr = dbm_open(aliasfile, O_RDONLY, DBMMODE); 29757249Seric if (AliasDBMptr == NULL) 29857249Seric { 29957249Seric syserr("initaliases: cannot open %s", buf); 30057249Seric NoAlias = TRUE; 30157249Seric return; 30257249Seric } 30351756Seric # else 30450576Seric syserr("initaliases: cannot open %s", buf); 30550576Seric NoAlias = TRUE; 30650576Seric return; 30751756Seric # endif 30850576Seric } 30950575Seric # else 31056845Seric AliasDBMptr = dbm_open(aliasfile, O_RDONLY, DBMMODE); 31157249Seric if (AliasDBMptr == NULL) 31257249Seric { 31357977Seric syserr("initaliases: cannot open DBM database %s.{pag,dir}", 31457977Seric aliasfile); 31557249Seric NoAlias = TRUE; 31657249Seric return; 31757249Seric } 31850575Seric # endif 31950575Seric } 32017471Seric atcnt = SafeAlias * 2; 32117471Seric if (atcnt > 0) 32217471Seric { 32317471Seric while (!init && atcnt-- >= 0 && aliaslookup("@") == NULL) 32425689Seric { 32525689Seric /* 32625689Seric ** Reinitialize alias file in case the new 32725689Seric ** one is mv'ed in instead of cp'ed in. 32825689Seric ** 32925689Seric ** Only works with new DBM -- old one will 33025689Seric ** just consume file descriptors forever. 33125689Seric ** If you have a dbmclose() it can be 33225689Seric ** added before the sleep(30). 33325689Seric */ 33425689Seric 33550575Seric # ifdef NEWDB 33651756Seric if (AliasDBptr != NULL) 33751756Seric AliasDBptr->close(AliasDBptr); 33850575Seric # endif 33956845Seric # ifdef NDBM 34056845Seric if (AliasDBMptr != NULL) 34156845Seric dbm_close(AliasDBMptr); 34256845Seric # endif 34350575Seric 34417471Seric sleep(30); 34550575Seric # ifdef NEWDB 34650575Seric (void) strcpy(buf, aliasfile); 34750575Seric (void) strcat(buf, ".db"); 34851171Sbostic AliasDBptr = 34951171Sbostic dbopen(buf, O_RDONLY, DBMMODE, DB_HASH, NULL); 35050576Seric if (AliasDBptr == NULL) 35150576Seric { 35251756Seric # ifdef NDBM 35356845Seric AliasDBMptr = dbm_open(aliasfile, O_RDONLY, DBMMODE); 35451756Seric # else 35550576Seric syserr("initaliases: cannot open %s", buf); 35650576Seric NoAlias = TRUE; 35750576Seric return; 35851756Seric # endif 35950576Seric } 36050575Seric # else 36125689Seric # ifdef NDBM 36256845Seric AliasDBMptr = dbm_open(aliasfile, O_RDONLY, DBMMODE); 36357249Seric if (AliasDBMptr == NULL) 36457249Seric { 36558008Seric syserr("initaliases: cannot open DBM database %s.{pag,dir}", 36658008Seric aliasfile); 36757249Seric NoAlias = TRUE; 36857249Seric return; 36957249Seric } 37050575Seric # endif 37150575Seric # endif 37225689Seric } 37317471Seric } 37417471Seric else 37517471Seric atcnt = 1; 3768437Seric 3778437Seric /* 37856845Seric ** See if the NDBM version of the file is out of date with 3794322Seric ** the text version. If so, go into 'init' mode automatically. 38040559Sbostic ** This only happens if our effective userid owns the DBM. 38140559Sbostic ** Note the unpalatable hack to see if the stat succeeded. 3824322Seric */ 3834322Seric 3844322Seric modtime = stb.st_mtime; 3854322Seric (void) strcpy(buf, aliasfile); 38650575Seric # ifdef NEWDB 38750575Seric (void) strcat(buf, ".db"); 38850575Seric # else 3894322Seric (void) strcat(buf, ".pag"); 39050575Seric # endif 3914322Seric stb.st_ino = 0; 39219039Seric if (!init && (stat(buf, &stb) < 0 || stb.st_mtime < modtime || atcnt < 0)) 3934322Seric { 39411937Seric errno = 0; 39540559Sbostic if (AutoRebuild && stb.st_ino != 0 && stb.st_uid == geteuid()) 3964322Seric { 3974322Seric init = TRUE; 39825522Seric automatic = TRUE; 3997051Seric message(Arpa_Info, "rebuilding alias database"); 40024944Seric #ifdef LOG 40158020Seric if (LogLevel > 14) 40224944Seric syslog(LOG_INFO, "rebuilding alias database"); 40356795Seric #endif /* LOG */ 4044322Seric } 4054322Seric else 4064322Seric { 40719039Seric #ifdef LOG 40858020Seric if (LogLevel > 3) 40924944Seric syslog(LOG_INFO, "alias database out of date"); 41056795Seric #endif /* LOG */ 4114322Seric message(Arpa_Info, "Warning: alias database out of date"); 4124322Seric } 4134322Seric } 4144322Seric 4154322Seric 4164322Seric /* 41756845Seric ** If necessary, load the NDBM file. 41856845Seric ** If running without NDBM, load the symbol table. 4194322Seric */ 4204322Seric 4214157Seric if (init) 4228437Seric { 42325522Seric #ifdef LOG 42458020Seric if (LogLevel > 7) 42525522Seric { 42625522Seric extern char *username(); 42725522Seric 42825522Seric syslog(LOG_NOTICE, "alias database %srebuilt by %s", 42925522Seric automatic ? "auto" : "", username()); 43025522Seric } 43156795Seric #endif /* LOG */ 43255012Seric readaliases(aliasfile, TRUE, e); 4338437Seric } 43456845Seric # else /* NDBM */ 43555012Seric readaliases(aliasfile, init, e); 43656845Seric # endif /* NDBM */ 4374157Seric } 4384157Seric /* 4394157Seric ** READALIASES -- read and process the alias file. 4404157Seric ** 4414157Seric ** This routine implements the part of initaliases that occurs 4424157Seric ** when we are not going to use the DBM stuff. 4434157Seric ** 4444157Seric ** Parameters: 4454157Seric ** aliasfile -- the pathname of the alias file master. 44656845Seric ** init -- if set, initialize the NDBM stuff. 4474157Seric ** 4484157Seric ** Returns: 4494157Seric ** none. 4504157Seric ** 4514157Seric ** Side Effects: 4524157Seric ** Reads aliasfile into the symbol table. 4534157Seric ** Optionally, builds the .dir & .pag files. 4544157Seric */ 4554157Seric 4564157Seric static 45755012Seric readaliases(aliasfile, init, e) 4584157Seric char *aliasfile; 4594157Seric bool init; 46055012Seric register ENVELOPE *e; 4614157Seric { 4624098Seric register char *p; 4634098Seric char *rhs; 4644098Seric bool skipping; 4659368Seric int naliases, bytes, longest; 4669368Seric FILE *af; 46753742Seric bool makedbmfiles; 46840970Sbostic void (*oldsigint)(); 4694098Seric ADDRESS al, bl; 4704106Seric register STAB *s; 47150575Seric # ifdef NEWDB 47250575Seric DB *dbp; 47350575Seric # endif 47456845Seric # ifdef NDBM 47556845Seric DBM *dbmp; 47656845Seric # endif 47751937Seric # ifdef LOCKF 47851937Seric struct flock fld; 47951937Seric # endif 4809368Seric char line[BUFSIZ]; 4814098Seric 48251937Seric if ((af = fopen(aliasfile, "r+")) == NULL) 4831515Seric { 48457249Seric if (init) 48557249Seric syserr("Can't open %s", aliasfile); 48657249Seric else if (tTd(27, 1)) 4874106Seric printf("Can't open %s\n", aliasfile); 4884098Seric errno = 0; 4894098Seric NoAlias++; 4904098Seric return; 4914098Seric } 4924314Seric 49356845Seric # if defined(NDBM) || defined(NEWDB) 49419784Seric /* see if someone else is rebuilding the alias file already */ 49551835Seric # ifdef LOCKF 49651937Seric fld.l_type = F_WRLCK; 49751937Seric fld.l_whence = fld.l_start = fld.l_len = 0; 49851937Seric if (fcntl(fileno(af), F_SETLK, &fld) < 0) 49951835Seric # else 50019784Seric if (flock(fileno(af), LOCK_EX | LOCK_NB) < 0 && errno == EWOULDBLOCK) 50151835Seric # endif 50219784Seric { 50319784Seric /* yes, they are -- wait until done and then return */ 50419784Seric message(Arpa_Info, "Alias file is already being rebuilt"); 50519784Seric if (OpMode != MD_INITALIAS) 50619784Seric { 50719784Seric /* wait for other rebuild to complete */ 50851835Seric # ifdef LOCKF 50951937Seric (void) fcntl(fileno(af), F_SETLKW, &fld); 51051835Seric # else 51119784Seric (void) flock(fileno(af), LOCK_EX); 51251835Seric # endif 51319784Seric } 51423108Seric (void) fclose(af); 51519784Seric errno = 0; 51619784Seric return; 51719784Seric } 51856845Seric # endif /* NDBM */ 51919784Seric 5204314Seric /* 52119784Seric ** If initializing, create the new DBM files. 52219784Seric */ 52319784Seric 52419784Seric if (init) 52519784Seric { 52619784Seric oldsigint = signal(SIGINT, SIG_IGN); 52751756Seric # ifdef NEWDB 52851756Seric (void) strcpy(line, aliasfile); 52951756Seric (void) strcat(line, ".db"); 53051756Seric dbp = dbopen(line, 53151756Seric O_RDWR|O_CREAT|O_TRUNC, DBMMODE, DB_HASH, NULL); 53251756Seric if (dbp == NULL) 53351756Seric { 53451756Seric syserr("readaliases: cannot create %s", line); 53551756Seric (void) signal(SIGINT, oldsigint); 53651756Seric return; 53751756Seric } 53853742Seric # endif 53953742Seric # ifdef IF_MAKEDBMFILES 54053742Seric # ifdef NEWDB 54153742Seric makedbmfiles = access("/var/yp/Makefile", R_OK) == 0; 54253742Seric # endif 54353742Seric IF_MAKEDBMFILES 54419784Seric { 54556845Seric dbmp = dbm_open(aliasfile, 54656845Seric O_RDWR|O_CREAT|O_TRUNC, DBMMODE); 54756845Seric if (dbmp == NULL) 54853742Seric { 54956845Seric syserr("readaliases: cannot create %s.{dir,pag}", 55056845Seric aliasfile); 55153742Seric (void) signal(SIGINT, oldsigint); 55253742Seric return; 55353742Seric } 55419784Seric } 55550575Seric # endif 55619784Seric } 55719784Seric 55819784Seric /* 5594314Seric ** Read and interpret lines 5604314Seric */ 5614314Seric 5629368Seric FileName = aliasfile; 5639368Seric LineNumber = 0; 5644322Seric naliases = bytes = longest = 0; 5654098Seric skipping = FALSE; 5664098Seric while (fgets(line, sizeof (line), af) != NULL) 5674098Seric { 5684322Seric int lhssize, rhssize; 5694322Seric 5709368Seric LineNumber++; 57156795Seric p = strchr(line, '\n'); 57225278Seric if (p != NULL) 57325278Seric *p = '\0'; 5744098Seric switch (line[0]) 5754098Seric { 5764098Seric case '#': 5774098Seric case '\0': 5784098Seric skipping = FALSE; 5794098Seric continue; 5804065Seric 5814098Seric case ' ': 5824098Seric case '\t': 5834098Seric if (!skipping) 5849368Seric syserr("Non-continuation line starts with space"); 5854098Seric skipping = TRUE; 5864097Seric continue; 5874098Seric } 5884098Seric skipping = FALSE; 5891874Seric 5904314Seric /* 5914314Seric ** Process the LHS 59257736Seric ** Find the colon separator, and parse the address. 59316898Seric ** It should resolve to a local name -- this will 59416898Seric ** be checked later (we want to optionally do 59516898Seric ** parsing of the RHS first to maximize error 59616898Seric ** detection). 5974314Seric */ 5984314Seric 5994098Seric for (p = line; *p != '\0' && *p != ':' && *p != '\n'; p++) 6004097Seric continue; 60116898Seric if (*p++ != ':') 6024098Seric { 6039368Seric syserr("missing colon"); 6044097Seric continue; 6054098Seric } 60655012Seric if (parseaddr(line, &al, 1, ':', e) == NULL) 6074098Seric { 60816898Seric syserr("illegal alias name"); 60916898Seric continue; 6104098Seric } 61116898Seric loweraddr(&al); 6124314Seric 6134314Seric /* 6144314Seric ** Process the RHS. 6154314Seric ** 'al' is the internal form of the LHS address. 6164314Seric ** 'p' points to the text of the RHS. 6174314Seric */ 6184314Seric 6194098Seric rhs = p; 6204098Seric for (;;) 6214098Seric { 6224098Seric register char c; 6231515Seric 62425821Seric if (init && CheckAliases) 6254098Seric { 6264157Seric /* do parsing & compression of addresses */ 62725278Seric while (*p != '\0') 6284098Seric { 62925278Seric extern char *DelimChar; 63025278Seric 63158050Seric while ((isascii(*p) && isspace(*p)) || 63258050Seric *p == ',') 6334157Seric p++; 63425278Seric if (*p == '\0') 63525278Seric break; 63655012Seric if (parseaddr(p, &bl, -1, ',', e) == NULL) 63725278Seric usrerr("%s... bad address", p); 63825278Seric p = DelimChar; 6394098Seric } 6404098Seric } 6414157Seric else 64215769Seric { 64316898Seric p = &p[strlen(p)]; 64416898Seric if (p[-1] == '\n') 64516898Seric *--p = '\0'; 64615769Seric } 6471515Seric 6484098Seric /* see if there should be a continuation line */ 6494106Seric c = fgetc(af); 6504106Seric if (!feof(af)) 6514314Seric (void) ungetc(c, af); 6524106Seric if (c != ' ' && c != '\t') 6534098Seric break; 6544098Seric 6554098Seric /* read continuation line */ 6564098Seric if (fgets(p, sizeof line - (p - line), af) == NULL) 6574098Seric break; 6589368Seric LineNumber++; 65957135Seric 66057135Seric /* check for line overflow */ 66157135Seric if (strchr(p, '\n') == NULL) 66257135Seric { 66357135Seric usrerr("alias too long"); 66457135Seric break; 66557135Seric } 6664098Seric } 66716898Seric if (al.q_mailer != LocalMailer) 66816898Seric { 66916898Seric syserr("cannot alias non-local names"); 67016898Seric continue; 67116898Seric } 6724314Seric 6734314Seric /* 6744314Seric ** Insert alias into symbol table or DBM file 6754314Seric */ 6764314Seric 67716898Seric lhssize = strlen(al.q_user) + 1; 67857381Seric if (!bitnset(M_USR_UPPER, al.q_mailer->m_flags)) 67957381Seric makelower(al.q_user); 6804322Seric rhssize = strlen(rhs) + 1; 6814322Seric 68256845Seric # if defined(NDBM) || defined(NEWDB) 6834157Seric if (init) 6844157Seric { 68556845Seric DBdatum key, content; 68657381Seric int putstat; 6874157Seric 68856845Seric key.xx.size = lhssize; 68956845Seric key.xx.data = al.q_user; 69056845Seric content.xx.size = rhssize; 69156845Seric content.xx.data = rhs; 69251756Seric # ifdef NEWDB 69357381Seric putstat = dbp->put(dbp, &key.dbt, &content.dbt, 69457381Seric R_NOOVERWRITE); 69557381Seric if (putstat > 0) 69657381Seric { 69757977Seric usrerr("050 Warning: duplicate alias name %s", 69857381Seric al.q_user); 69957381Seric putstat = dbp->put(dbp, &key.dbt, 70057381Seric &content.dbt, 0); 70157381Seric } 70257381Seric if (putstat != 0) 70350576Seric syserr("readaliases: db put (%s)", al.q_user); 70450575Seric # endif 70553742Seric # ifdef IF_MAKEDBMFILES 70653742Seric IF_MAKEDBMFILES 70757381Seric { 70857381Seric putstat = dbm_store(dbmp, key.dbm, content.dbm, 70957381Seric DBM_INSERT); 71057381Seric if (putstat > 0) 71157381Seric { 71257977Seric usrerr("050 Warning: duplicate alias name %s", 71357381Seric al.q_user); 71457381Seric putstat = dbm_store(dbmp, key.dbm, 71557381Seric content.dbm, DBM_REPLACE); 71657381Seric } 71757381Seric if (putstat != 0) 71856845Seric syserr("readaliases: dbm store (%s)", 71956845Seric al.q_user); 72057381Seric } 72153742Seric # endif 72257381Seric if (al.q_paddr != NULL) 72357381Seric free(al.q_paddr); 72457381Seric if (al.q_host != NULL) 72557381Seric free(al.q_host); 72657381Seric if (al.q_user != NULL) 72757381Seric free(al.q_user); 7284157Seric } 7294157Seric else 73056845Seric # endif /* NDBM */ 7314157Seric { 7324157Seric s = stab(al.q_user, ST_ALIAS, ST_ENTER); 7334157Seric s->s_alias = newstr(rhs); 7344157Seric } 7354322Seric 7364322Seric /* statistics */ 7374322Seric naliases++; 7384322Seric bytes += lhssize + rhssize; 7394322Seric if (rhssize > longest) 7404322Seric longest = rhssize; 7411515Seric } 74219784Seric 74356845Seric # if defined(NDBM) || defined(NEWDB) 74419784Seric if (init) 74519784Seric { 74619784Seric /* add the distinquished alias "@" */ 74756845Seric DBdatum key; 74819784Seric 74956845Seric key.xx.size = 2; 75056845Seric key.xx.data = "@"; 75150575Seric # ifdef NEWDB 75250576Seric if (dbp->sync(dbp) != 0 || 75356845Seric dbp->put(dbp, &key.dbt, &key.dbt, 0) != 0 || 75450576Seric dbp->close(dbp) != 0) 75550576Seric syserr("readaliases: db close failure"); 75653742Seric # endif 75756789Seric # ifdef IF_MAKEDBMFILES 75856793Seric IF_MAKEDBMFILES 75956845Seric { 76058059Seric #ifdef YPCOMPAT 76158059Seric nis_magic(dbmp); 76258059Seric #endif 76356845Seric if (dbm_store(dbmp, key.dbm, key.dbm, DBM_REPLACE) != 0 || 76456845Seric dbm_error(dbmp)) 76556845Seric syserr("readaliases: dbm close failure"); 76656845Seric dbm_close(dbmp); 76756845Seric } 76850575Seric # endif 76919784Seric 77019784Seric /* restore the old signal */ 77119784Seric (void) signal(SIGINT, oldsigint); 77219784Seric } 77356845Seric # endif /* NDBM */ 77419784Seric 77519784Seric /* closing the alias file drops the lock */ 7764098Seric (void) fclose(af); 77755012Seric e->e_to = NULL; 7789368Seric FileName = NULL; 7797051Seric message(Arpa_Info, "%d aliases, longest %d bytes, %d bytes total", 7804322Seric naliases, longest, bytes); 78124944Seric # ifdef LOG 78258020Seric if (LogLevel > 7) 78324944Seric syslog(LOG_INFO, "%d aliases, longest %d bytes, %d bytes total", 78424944Seric naliases, longest, bytes); 78556795Seric # endif /* LOG */ 786292Seric } 787292Seric /* 78858059Seric ** NIS_MAGIC -- Add NIS magic dbm data 78958059Seric ** 79058059Seric ** This adds the magic entries needed by SunOS to make this a valid 79158059Seric ** NIS map. 79258059Seric ** 79358059Seric ** Parameters: 79458059Seric ** dbmp -- a pointer to the DBM structure. 79558059Seric ** 79658059Seric ** Returns: 79758059Seric ** none. 79858059Seric */ 79958059Seric 80058059Seric # ifdef YPCOMPAT 80158059Seric 80258059Seric static void 80358059Seric nis_magic(dbmp) 80458059Seric DBM *dbmp; 80558059Seric { 80658059Seric int i; 80758059Seric static datum key[2] = 80858059Seric { 80958059Seric { "YP_LAST_MODIFIED", sizeof "YP_LAST_MODIFIED" - 1 }, 81058059Seric { "YP_MASTER_NAME", sizeof "YP_MASTER_NAME" - 1 }, 81158059Seric }; 81258059Seric datum contents[2]; 81358059Seric char tbuf[12]; 81458059Seric char hbuf[MAXHOSTNAMELEN]; 81558059Seric 81658059Seric (void) sprintf(tbuf, "%010ld", curtime()); 81758059Seric contents[0].dptr = tbuf; 81858059Seric contents[0].dsize = strlen(tbuf); 81958059Seric 82058059Seric (void) myhostname(hbuf, sizeof hbuf); 82158059Seric contents[1].dptr = hbuf; 82258059Seric contents[1].dptr = strlen(hbuf); 82358059Seric 82458059Seric for (i = 0; i < sizeof key / sizeof *key; i++) 82558059Seric { 82658059Seric if (dbm_store(dbmp, key[i], contents[i], DBM_REPLACE) != 0 || 82758059Seric dbm_error(dbmp)) 82858059Seric syserr("nis_magic: dbm_store failure"); 82958059Seric } 83058059Seric } 83158059Seric 83258059Seric # endif 83358059Seric /* 834292Seric ** FORWARD -- Try to forward mail 835292Seric ** 836292Seric ** This is similar but not identical to aliasing. 837292Seric ** 838292Seric ** Parameters: 8394314Seric ** user -- the name of the user who's mail we would like 8404314Seric ** to forward to. It must have been verified -- 8414314Seric ** i.e., the q_home field must have been filled 8424314Seric ** in. 8434999Seric ** sendq -- a pointer to the head of the send queue to 8444999Seric ** put this user's aliases in. 845292Seric ** 846292Seric ** Returns: 8474098Seric ** none. 848292Seric ** 849292Seric ** Side Effects: 8503185Seric ** New names are added to send queues. 851292Seric */ 852292Seric 85355012Seric forward(user, sendq, e) 8542966Seric ADDRESS *user; 8554999Seric ADDRESS **sendq; 85655012Seric register ENVELOPE *e; 857292Seric { 85857136Seric char *pp; 85957136Seric char *ep; 8604536Seric extern bool safefile(); 8614069Seric 8627671Seric if (tTd(27, 1)) 8634098Seric printf("forward(%s)\n", user->q_paddr); 8644098Seric 8654594Seric if (user->q_mailer != LocalMailer || bitset(QBADADDR, user->q_flags)) 8664098Seric return; 8674314Seric if (user->q_home == NULL) 86858059Seric { 8694314Seric syserr("forward: no home"); 87058059Seric user->q_home = "/nosuchdirectory"; 87158059Seric } 8724069Seric 8734069Seric /* good address -- look for .forward file in home */ 87455012Seric define('z', user->q_home, e); 87557136Seric define('u', user->q_user, e); 87657136Seric define('h', user->q_host, e); 87757136Seric if (ForwardPath == NULL) 87858050Seric ForwardPath = newstr("\201z/.forward"); 87957136Seric 88057136Seric for (pp = ForwardPath; pp != NULL; pp = ep) 88157136Seric { 88257232Seric char buf[MAXPATHLEN+1]; 88357136Seric 88457136Seric ep = strchr(pp, ':'); 88557136Seric if (ep != NULL) 88657136Seric *ep = '\0'; 88757136Seric expand(pp, buf, &buf[sizeof buf - 1], e); 88857136Seric if (ep != NULL) 88957136Seric *ep++ = ':'; 89057136Seric if (tTd(27, 3)) 89157136Seric printf("forward: trying %s\n", buf); 89257136Seric if (include(buf, TRUE, user, sendq, e) == 0) 89357136Seric break; 89457136Seric } 895292Seric } 896