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 958332Seric # include "sendmail.h" 1050577Seric # include <signal.h> 1150577Seric # include <pwd.h> 1250577Seric 1356845Seric # ifdef DBM 1456848Seric ERROR: DBM is no longer supported -- use NDBM instead. 1556845Seric # endif 1656845Seric 1750577Seric # ifdef NEWDB 1850577Seric # include <db.h> 1950577Seric # endif 2050577Seric 2156766Seric # ifdef NDBM 2256845Seric # include <ndbm.h> 2356766Seric # endif 2456766Seric 2533728Sbostic #ifndef lint 2651756Seric #ifdef NEWDB 2757736Seric #ifdef NDBM 28*59611Seric static char sccsid[] = "@(#)alias.c 6.35 (Berkeley) 05/01/93 (with NEWDB and NDBM)"; 2951756Seric #else 30*59611Seric static char sccsid[] = "@(#)alias.c 6.35 (Berkeley) 05/01/93 (with NEWDB)"; 3157736Seric #endif 3257736Seric #else 3356845Seric #ifdef NDBM 34*59611Seric static char sccsid[] = "@(#)alias.c 6.35 (Berkeley) 05/01/93 (with NDBM)"; 3533728Sbostic #else 36*59611Seric static char sccsid[] = "@(#)alias.c 6.35 (Berkeley) 05/01/93 (without NEWDB or NDBM)"; 3733728Sbostic #endif 3850575Seric #endif 3933728Sbostic #endif /* not lint */ 4051756Seric /* 41292Seric ** ALIAS -- Compute aliases. 42292Seric ** 439368Seric ** Scans the alias file for an alias for the given address. 449368Seric ** If found, it arranges to deliver to the alias list instead. 459368Seric ** Uses libdbm database if -DDBM. 46292Seric ** 47292Seric ** Parameters: 484097Seric ** a -- address to alias. 494999Seric ** sendq -- a pointer to the head of the send queue 504999Seric ** to put the aliases in. 5158092Seric ** e -- the current envelope. 52292Seric ** 53292Seric ** Returns: 54292Seric ** none 55292Seric ** 56292Seric ** Side Effects: 573185Seric ** Aliases found are expanded. 58292Seric ** 59292Seric ** Notes: 60292Seric ** If NoAlias (the "-n" flag) is set, no aliasing is 61292Seric ** done. 62292Seric ** 63292Seric ** Deficiencies: 64292Seric ** It should complain about names that are aliased to 65292Seric ** nothing. 66292Seric */ 67292Seric 68292Seric 6953742Seric /* 7053742Seric ** Sun YP servers read the dbm files directly, so we have to build them 7153742Seric ** even if NEWDB 7253742Seric */ 7353742Seric 7456845Seric #ifdef NDBM 7553742Seric # ifndef NEWDB 7653742Seric # define IF_MAKEDBMFILES 7753742Seric # else 7853742Seric # ifdef YPCOMPAT 7953742Seric # define IF_MAKEDBMFILES if (makedbmfiles) 8053742Seric # endif 8153742Seric # endif 8253742Seric #endif 8353742Seric 8456845Seric typedef union 852966Seric { 8656845Seric #ifdef NDBM 8756845Seric datum dbm; 8851756Seric #endif 8956845Seric #ifdef NEWDB 9056845Seric DBT dbt; 9156845Seric #endif 9256845Seric struct 9356845Seric { 9456845Seric char *data; 9556845Seric int size; 9656845Seric } xx; 9756845Seric } DBdatum; 98292Seric 9950575Seric #ifdef NEWDB 10050575Seric static DB *AliasDBptr; 10150575Seric #endif 10256845Seric #ifdef NDBM 10356845Seric static DBM *AliasDBMptr; 10456845Seric #endif 10550575Seric 10655012Seric alias(a, sendq, e) 1074097Seric register ADDRESS *a; 1084999Seric ADDRESS **sendq; 10955012Seric register ENVELOPE *e; 110292Seric { 1114081Seric register char *p; 11258082Seric int naliases; 11358170Seric char *owner; 11458170Seric char obuf[MAXNAME + 6]; 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 */ 12158680Seric if (bitset(QDONTSEND|QBADADDR|QVERIFIED, 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); 14558092Seric if (bitset(EF_VRFYONLY, e->e_flags)) 14658154Seric { 14758154Seric a->q_flags |= QVERIFIED; 14858884Seric e->e_nrcpts++; 14958092Seric return; 15058154Seric } 15158154Seric message("aliased to %s", p); 15257977Seric #ifdef LOG 15358020Seric if (LogLevel > 9) 15457977Seric syslog(LOG_INFO, "%s: alias %s => %s", e->e_id, a->q_paddr, p); 15557977Seric #endif 15658082Seric a->q_flags &= ~QSELFREF; 1574098Seric AliasLevel++; 15858082Seric naliases = sendtolist(p, a, sendq, e); 1594098Seric AliasLevel--; 16058082Seric if (naliases > 0 && !bitset(QSELFREF, a->q_flags)) 16158065Seric { 16258065Seric if (tTd(27, 5)) 16358065Seric { 16458065Seric printf("alias: QDONTSEND "); 16558065Seric printaddr(a, FALSE); 16658065Seric } 16758065Seric a->q_flags |= QDONTSEND; 16858065Seric } 16958170Seric 17058170Seric /* 17158170Seric ** Look for owner of alias 17258170Seric */ 17358170Seric 17458170Seric (void) strcpy(obuf, "owner-"); 17558170Seric if (strncmp(a->q_user, "owner-", 6) == 0) 17658170Seric (void) strcat(obuf, "owner"); 17758170Seric else 17858170Seric (void) strcat(obuf, a->q_user); 17958170Seric if (!bitnset(M_USR_UPPER, a->q_mailer->m_flags)) 18058170Seric makelower(obuf); 18158170Seric owner = aliaslookup(obuf); 18258170Seric if (owner != NULL) 18358170Seric { 18458170Seric if (strchr(owner, ',') != NULL) 18558170Seric owner = obuf; 18658170Seric a->q_owner = newstr(owner); 18758170Seric } 1884098Seric } 1894098Seric /* 1905701Seric ** ALIASLOOKUP -- look up a name in the alias file. 1915701Seric ** 1925701Seric ** Parameters: 1935701Seric ** name -- the name to look up. 1945701Seric ** 1955701Seric ** Returns: 1965701Seric ** the value of name. 1975701Seric ** NULL if unknown. 1985701Seric ** 1995701Seric ** Side Effects: 2005701Seric ** none. 2015701Seric ** 2025701Seric ** Warnings: 2035701Seric ** The return value will be trashed across calls. 2045701Seric */ 2055701Seric 2065701Seric char * 2075701Seric aliaslookup(name) 2085701Seric char *name; 2095701Seric { 21057381Seric int i; 21157381Seric char keybuf[MAXNAME + 1]; 21256845Seric # if defined(NEWDB) || defined(NDBM) 21356845Seric DBdatum rhs, lhs; 21450575Seric int s; 21557381Seric # else /* neither NEWDB nor NDBM */ 21657381Seric register STAB *s; 21757381Seric # endif 2185701Seric 2195701Seric /* create a key for fetch */ 22057381Seric i = strlen(name) + 1; 22157381Seric if (i > sizeof keybuf) 22257381Seric i = sizeof keybuf; 22357381Seric bcopy(name, keybuf, i); 22457381Seric if (!bitnset(M_USR_UPPER, LocalMailer->m_flags)) 22557381Seric makelower(keybuf); 22657381Seric 22757381Seric # if defined(NEWDB) || defined(NDBM) 22857381Seric lhs.xx.size = i; 22957381Seric lhs.xx.data = keybuf; 23050575Seric # ifdef NEWDB 23151756Seric if (AliasDBptr != NULL) 23251756Seric { 23357381Seric i = AliasDBptr->get(AliasDBptr, &lhs.dbt, &rhs.dbt, 0); 23457381Seric if (i == 0) 23556845Seric return (rhs.dbt.data); 23651756Seric } 23756845Seric # ifdef NDBM 23857249Seric else if (AliasDBMptr != NULL) 23951756Seric { 24056845Seric rhs.dbm = dbm_fetch(AliasDBMptr, lhs.dbm); 24156845Seric return (rhs.dbm.dptr); 24251756Seric } 24356845Seric # endif /* NDBM */ 24457530Seric return (NULL); 24556845Seric # else /* not NEWDB */ 24656845Seric rhs.dbm = dbm_fetch(AliasDBMptr, lhs.dbm); 24756845Seric return (rhs.dbm.dptr); 24856845Seric # endif /* NEWDB */ 24956845Seric # else /* neither NEWDB nor NDBM */ 25057381Seric s = stab(keybuf, ST_ALIAS, ST_FIND); 25151756Seric if (s != NULL) 25251756Seric return (s->s_alias); 25357530Seric return (NULL); 25451756Seric # endif 2555701Seric } 2565701Seric /* 2574098Seric ** INITALIASES -- initialize for aliasing 2584098Seric ** 25956845Seric ** Very different depending on whether we are running NDBM or not. 2604098Seric ** 2614098Seric ** Parameters: 2624098Seric ** aliasfile -- location of aliases. 26356845Seric ** init -- if set and if NDBM, initialize the NDBM files. 2644098Seric ** 2654098Seric ** Returns: 2664098Seric ** none. 2674098Seric ** 2684098Seric ** Side Effects: 2694098Seric ** initializes aliases: 27056845Seric ** if NDBM: opens the database. 27156845Seric ** if ~NDBM: reads the aliases into the symbol table. 2724098Seric */ 2734098Seric 27440559Sbostic # define DBMMODE 0644 2754157Seric 27655012Seric initaliases(aliasfile, init, e) 2774098Seric char *aliasfile; 2784157Seric bool init; 27955012Seric register ENVELOPE *e; 2804098Seric { 28156845Seric #if defined(NDBM) || defined(NEWDB) 2828437Seric int atcnt; 28325522Seric time_t modtime; 28425522Seric bool automatic = FALSE; 2854322Seric char buf[MAXNAME]; 28650575Seric #endif 2879368Seric struct stat stb; 28827176Seric static bool initialized = FALSE; 28946928Sbostic static int readaliases(); 2904322Seric 29127176Seric if (initialized) 29227176Seric return; 29327176Seric initialized = TRUE; 29427176Seric 29517984Seric if (aliasfile == NULL || stat(aliasfile, &stb) < 0) 2968437Seric { 29725522Seric if (aliasfile != NULL && init) 29858151Seric syserr("554 Cannot open %s", aliasfile); 2998437Seric NoAlias = TRUE; 30011937Seric errno = 0; 3018437Seric return; 3028437Seric } 3038437Seric 30456845Seric # if defined(NDBM) || defined(NEWDB) 3054322Seric /* 3068437Seric ** Check to see that the alias file is complete. 3078437Seric ** If not, we will assume that someone died, and it is up 3088437Seric ** to us to rebuild it. 3098437Seric */ 3108437Seric 31125689Seric if (!init) 31250575Seric { 31350575Seric # ifdef NEWDB 31450575Seric (void) strcpy(buf, aliasfile); 31550575Seric (void) strcat(buf, ".db"); 31651171Sbostic AliasDBptr = dbopen(buf, O_RDONLY, DBMMODE, DB_HASH, NULL); 31750576Seric if (AliasDBptr == NULL) 31850576Seric { 31956845Seric # ifdef NDBM 32056845Seric AliasDBMptr = dbm_open(aliasfile, O_RDONLY, DBMMODE); 32157249Seric if (AliasDBMptr == NULL) 32257249Seric { 32359025Seric syserr("WARNING: initaliases: cannot open %s", buf); 32457249Seric NoAlias = TRUE; 32557249Seric return; 32657249Seric } 32751756Seric # else 32859025Seric syserr("WARNING: initaliases: cannot open %s", buf); 32950576Seric NoAlias = TRUE; 33050576Seric return; 33151756Seric # endif 33250576Seric } 33350575Seric # else 33456845Seric AliasDBMptr = dbm_open(aliasfile, O_RDONLY, DBMMODE); 33557249Seric if (AliasDBMptr == NULL) 33657249Seric { 33759025Seric syserr("WARNING: initaliases: cannot open DBM database %s.{pag,dir}", 33857977Seric aliasfile); 33957249Seric NoAlias = TRUE; 34057249Seric return; 34157249Seric } 34250575Seric # endif 34350575Seric } 34417471Seric atcnt = SafeAlias * 2; 34517471Seric if (atcnt > 0) 34617471Seric { 34717471Seric while (!init && atcnt-- >= 0 && aliaslookup("@") == NULL) 34825689Seric { 34925689Seric /* 35025689Seric ** Reinitialize alias file in case the new 35125689Seric ** one is mv'ed in instead of cp'ed in. 35225689Seric ** 35325689Seric ** Only works with new DBM -- old one will 35425689Seric ** just consume file descriptors forever. 35525689Seric ** If you have a dbmclose() it can be 35625689Seric ** added before the sleep(30). 35725689Seric */ 35825689Seric 35950575Seric # ifdef NEWDB 36051756Seric if (AliasDBptr != NULL) 36151756Seric AliasDBptr->close(AliasDBptr); 36250575Seric # endif 36356845Seric # ifdef NDBM 36456845Seric if (AliasDBMptr != NULL) 36556845Seric dbm_close(AliasDBMptr); 36656845Seric # endif 36750575Seric 36817471Seric sleep(30); 36950575Seric # ifdef NEWDB 37050575Seric (void) strcpy(buf, aliasfile); 37150575Seric (void) strcat(buf, ".db"); 37251171Sbostic AliasDBptr = 37351171Sbostic dbopen(buf, O_RDONLY, DBMMODE, DB_HASH, NULL); 37450576Seric if (AliasDBptr == NULL) 37550576Seric { 37651756Seric # ifdef NDBM 37756845Seric AliasDBMptr = dbm_open(aliasfile, O_RDONLY, DBMMODE); 37851756Seric # else 37959025Seric syserr("WARNING: initaliases: cannot open %s", buf); 38050576Seric NoAlias = TRUE; 38150576Seric return; 38251756Seric # endif 38350576Seric } 38450575Seric # else 38525689Seric # ifdef NDBM 38656845Seric AliasDBMptr = dbm_open(aliasfile, O_RDONLY, DBMMODE); 38757249Seric if (AliasDBMptr == NULL) 38857249Seric { 38959025Seric syserr("WARNING: initaliases: cannot open DBM database %s.{pag,dir}", 39058008Seric aliasfile); 39157249Seric NoAlias = TRUE; 39257249Seric return; 39357249Seric } 39450575Seric # endif 39550575Seric # endif 39625689Seric } 39717471Seric } 39817471Seric else 39917471Seric atcnt = 1; 4008437Seric 4018437Seric /* 40256845Seric ** See if the NDBM version of the file is out of date with 4034322Seric ** the text version. If so, go into 'init' mode automatically. 40440559Sbostic ** This only happens if our effective userid owns the DBM. 40540559Sbostic ** Note the unpalatable hack to see if the stat succeeded. 4064322Seric */ 4074322Seric 4084322Seric modtime = stb.st_mtime; 4094322Seric (void) strcpy(buf, aliasfile); 41050575Seric # ifdef NEWDB 41150575Seric (void) strcat(buf, ".db"); 41250575Seric # else 4134322Seric (void) strcat(buf, ".pag"); 41450575Seric # endif 4154322Seric stb.st_ino = 0; 41619039Seric if (!init && (stat(buf, &stb) < 0 || stb.st_mtime < modtime || atcnt < 0)) 4174322Seric { 41811937Seric errno = 0; 41940559Sbostic if (AutoRebuild && stb.st_ino != 0 && stb.st_uid == geteuid()) 4204322Seric { 4214322Seric init = TRUE; 42225522Seric automatic = TRUE; 42358151Seric message("rebuilding alias database"); 42424944Seric #ifdef LOG 42558020Seric if (LogLevel > 14) 42624944Seric syslog(LOG_INFO, "rebuilding alias database"); 42756795Seric #endif /* LOG */ 4284322Seric } 4294322Seric else 4304322Seric { 43119039Seric #ifdef LOG 43258020Seric if (LogLevel > 3) 43324944Seric syslog(LOG_INFO, "alias database out of date"); 43456795Seric #endif /* LOG */ 43558151Seric message("Warning: alias database out of date"); 4364322Seric } 4374322Seric } 4384322Seric 4394322Seric 4404322Seric /* 44156845Seric ** If necessary, load the NDBM file. 44256845Seric ** If running without NDBM, load the symbol table. 4434322Seric */ 4444322Seric 4454157Seric if (init) 4468437Seric { 44725522Seric #ifdef LOG 44858020Seric if (LogLevel > 7) 44925522Seric { 45025522Seric extern char *username(); 45125522Seric 45225522Seric syslog(LOG_NOTICE, "alias database %srebuilt by %s", 45325522Seric automatic ? "auto" : "", username()); 45425522Seric } 45556795Seric #endif /* LOG */ 45655012Seric readaliases(aliasfile, TRUE, e); 4578437Seric } 45856845Seric # else /* NDBM */ 45955012Seric readaliases(aliasfile, init, e); 46056845Seric # endif /* NDBM */ 4614157Seric } 4624157Seric /* 4634157Seric ** READALIASES -- read and process the alias file. 4644157Seric ** 4654157Seric ** This routine implements the part of initaliases that occurs 4664157Seric ** when we are not going to use the DBM stuff. 4674157Seric ** 4684157Seric ** Parameters: 4694157Seric ** aliasfile -- the pathname of the alias file master. 47056845Seric ** init -- if set, initialize the NDBM stuff. 4714157Seric ** 4724157Seric ** Returns: 4734157Seric ** none. 4744157Seric ** 4754157Seric ** Side Effects: 4764157Seric ** Reads aliasfile into the symbol table. 4774157Seric ** Optionally, builds the .dir & .pag files. 4784157Seric */ 4794157Seric 4804157Seric static 48155012Seric readaliases(aliasfile, init, e) 4824157Seric char *aliasfile; 4834157Seric bool init; 48455012Seric register ENVELOPE *e; 4854157Seric { 4864098Seric register char *p; 4874098Seric char *rhs; 4884098Seric bool skipping; 4899368Seric int naliases, bytes, longest; 4909368Seric FILE *af; 49153742Seric bool makedbmfiles; 49240970Sbostic void (*oldsigint)(); 4934098Seric ADDRESS al, bl; 4944106Seric register STAB *s; 49550575Seric # ifdef NEWDB 49650575Seric DB *dbp; 49750575Seric # endif 49856845Seric # ifdef NDBM 49956845Seric DBM *dbmp; 50056845Seric # endif 5019368Seric char line[BUFSIZ]; 50258689Seric extern bool lockfile(); 5034098Seric 50451937Seric if ((af = fopen(aliasfile, "r+")) == NULL) 5051515Seric { 50657249Seric if (init) 50758151Seric syserr("554 Can't open %s", aliasfile); 50857249Seric else if (tTd(27, 1)) 5094106Seric printf("Can't open %s\n", aliasfile); 5104098Seric errno = 0; 5114098Seric NoAlias++; 5124098Seric return; 5134098Seric } 5144314Seric 51556845Seric # if defined(NDBM) || defined(NEWDB) 51619784Seric /* see if someone else is rebuilding the alias file already */ 51758689Seric if (!lockfile(fileno(af), aliasfile, LOCK_EX|LOCK_NB)) 51819784Seric { 51919784Seric /* yes, they are -- wait until done and then return */ 52058151Seric message("Alias file is already being rebuilt"); 52119784Seric if (OpMode != MD_INITALIAS) 52219784Seric { 52319784Seric /* wait for other rebuild to complete */ 52458689Seric (void) lockfile(fileno(af), aliasfile, LOCK_EX); 52519784Seric } 52623108Seric (void) fclose(af); 52719784Seric errno = 0; 52819784Seric return; 52919784Seric } 53056845Seric # endif /* NDBM */ 53119784Seric 5324314Seric /* 53319784Seric ** If initializing, create the new DBM files. 53419784Seric */ 53519784Seric 53619784Seric if (init) 53719784Seric { 53819784Seric oldsigint = signal(SIGINT, SIG_IGN); 53951756Seric # ifdef NEWDB 54051756Seric (void) strcpy(line, aliasfile); 54151756Seric (void) strcat(line, ".db"); 54251756Seric dbp = dbopen(line, 54351756Seric O_RDWR|O_CREAT|O_TRUNC, DBMMODE, DB_HASH, NULL); 54451756Seric if (dbp == NULL) 54551756Seric { 54651756Seric syserr("readaliases: cannot create %s", line); 54751756Seric (void) signal(SIGINT, oldsigint); 54851756Seric return; 54951756Seric } 55053742Seric # endif 55153742Seric # ifdef IF_MAKEDBMFILES 55253742Seric # ifdef NEWDB 55353742Seric makedbmfiles = access("/var/yp/Makefile", R_OK) == 0; 55453742Seric # endif 55553742Seric IF_MAKEDBMFILES 55619784Seric { 55756845Seric dbmp = dbm_open(aliasfile, 55856845Seric O_RDWR|O_CREAT|O_TRUNC, DBMMODE); 55956845Seric if (dbmp == NULL) 56053742Seric { 56156845Seric syserr("readaliases: cannot create %s.{dir,pag}", 56256845Seric aliasfile); 56353742Seric (void) signal(SIGINT, oldsigint); 56453742Seric return; 56553742Seric } 56619784Seric } 56750575Seric # endif 56819784Seric } 56919784Seric 57019784Seric /* 5714314Seric ** Read and interpret lines 5724314Seric */ 5734314Seric 5749368Seric FileName = aliasfile; 5759368Seric LineNumber = 0; 5764322Seric naliases = bytes = longest = 0; 5774098Seric skipping = FALSE; 5784098Seric while (fgets(line, sizeof (line), af) != NULL) 5794098Seric { 5804322Seric int lhssize, rhssize; 5814322Seric 5829368Seric LineNumber++; 58356795Seric p = strchr(line, '\n'); 58425278Seric if (p != NULL) 58525278Seric *p = '\0'; 5864098Seric switch (line[0]) 5874098Seric { 5884098Seric case '#': 5894098Seric case '\0': 5904098Seric skipping = FALSE; 5914098Seric continue; 5924065Seric 5934098Seric case ' ': 5944098Seric case '\t': 5954098Seric if (!skipping) 59658151Seric syserr("554 Non-continuation line starts with space"); 5974098Seric skipping = TRUE; 5984097Seric continue; 5994098Seric } 6004098Seric skipping = FALSE; 6011874Seric 6024314Seric /* 6034314Seric ** Process the LHS 60457736Seric ** Find the colon separator, and parse the address. 60516898Seric ** It should resolve to a local name -- this will 60616898Seric ** be checked later (we want to optionally do 60716898Seric ** parsing of the RHS first to maximize error 60816898Seric ** detection). 6094314Seric */ 6104314Seric 6114098Seric for (p = line; *p != '\0' && *p != ':' && *p != '\n'; p++) 6124097Seric continue; 61316898Seric if (*p++ != ':') 6144098Seric { 61558151Seric syserr("554 missing colon"); 6164097Seric continue; 6174098Seric } 61858333Seric if (parseaddr(line, &al, 1, ':', NULL, e) == NULL) 6194098Seric { 62058151Seric syserr("554 illegal alias name"); 62116898Seric continue; 6224098Seric } 6234314Seric 6244314Seric /* 6254314Seric ** Process the RHS. 6264314Seric ** 'al' is the internal form of the LHS address. 6274314Seric ** 'p' points to the text of the RHS. 6284314Seric */ 6294314Seric 63058914Seric while (isascii(*p) && isspace(*p)) 63158914Seric p++; 6324098Seric rhs = p; 6334098Seric for (;;) 6344098Seric { 6354098Seric register char c; 63658662Seric register char *nlp; 6371515Seric 63858662Seric nlp = &p[strlen(p)]; 63958662Seric if (nlp[-1] == '\n') 64058662Seric *--nlp = '\0'; 64158662Seric 64225821Seric if (init && CheckAliases) 6434098Seric { 6444157Seric /* do parsing & compression of addresses */ 64525278Seric while (*p != '\0') 6464098Seric { 64758333Seric auto char *delimptr; 64825278Seric 64958050Seric while ((isascii(*p) && isspace(*p)) || 65058050Seric *p == ',') 6514157Seric p++; 65225278Seric if (*p == '\0') 65325278Seric break; 65458333Seric if (parseaddr(p, &bl, -1, ',', &delimptr, e) == NULL) 65558151Seric usrerr("553 %s... bad address", p); 65658333Seric p = delimptr; 6574098Seric } 6584098Seric } 6594157Seric else 66015769Seric { 66158662Seric p = nlp; 66215769Seric } 6631515Seric 6644098Seric /* see if there should be a continuation line */ 6654106Seric c = fgetc(af); 6664106Seric if (!feof(af)) 6674314Seric (void) ungetc(c, af); 6684106Seric if (c != ' ' && c != '\t') 6694098Seric break; 6704098Seric 6714098Seric /* read continuation line */ 6724098Seric if (fgets(p, sizeof line - (p - line), af) == NULL) 6734098Seric break; 6749368Seric LineNumber++; 67557135Seric 67657135Seric /* check for line overflow */ 67757135Seric if (strchr(p, '\n') == NULL) 67857135Seric { 67958151Seric usrerr("554 alias too long"); 68057135Seric break; 68157135Seric } 6824098Seric } 68316898Seric if (al.q_mailer != LocalMailer) 68416898Seric { 68558151Seric syserr("554 cannot alias non-local names"); 68616898Seric continue; 68716898Seric } 6884314Seric 6894314Seric /* 6904314Seric ** Insert alias into symbol table or DBM file 6914314Seric */ 6924314Seric 69316898Seric lhssize = strlen(al.q_user) + 1; 69457381Seric if (!bitnset(M_USR_UPPER, al.q_mailer->m_flags)) 69557381Seric makelower(al.q_user); 6964322Seric rhssize = strlen(rhs) + 1; 6974322Seric 69856845Seric # if defined(NDBM) || defined(NEWDB) 6994157Seric if (init) 7004157Seric { 70156845Seric DBdatum key, content; 70257381Seric int putstat; 7034157Seric 70456845Seric key.xx.size = lhssize; 70556845Seric key.xx.data = al.q_user; 70656845Seric content.xx.size = rhssize; 70756845Seric content.xx.data = rhs; 70851756Seric # ifdef NEWDB 70957381Seric putstat = dbp->put(dbp, &key.dbt, &content.dbt, 71057381Seric R_NOOVERWRITE); 71157381Seric if (putstat > 0) 71257381Seric { 71357977Seric usrerr("050 Warning: duplicate alias name %s", 71457381Seric al.q_user); 71557381Seric putstat = dbp->put(dbp, &key.dbt, 71657381Seric &content.dbt, 0); 71757381Seric } 71857381Seric if (putstat != 0) 71950576Seric syserr("readaliases: db put (%s)", al.q_user); 72050575Seric # endif 72153742Seric # ifdef IF_MAKEDBMFILES 72253742Seric IF_MAKEDBMFILES 72357381Seric { 72457381Seric putstat = dbm_store(dbmp, key.dbm, content.dbm, 72557381Seric DBM_INSERT); 72657381Seric if (putstat > 0) 72757381Seric { 72857977Seric usrerr("050 Warning: duplicate alias name %s", 72957381Seric al.q_user); 73057381Seric putstat = dbm_store(dbmp, key.dbm, 73157381Seric content.dbm, DBM_REPLACE); 73257381Seric } 73357381Seric if (putstat != 0) 73456845Seric syserr("readaliases: dbm store (%s)", 73556845Seric al.q_user); 73657381Seric } 73753742Seric # endif 73857381Seric if (al.q_paddr != NULL) 73957381Seric free(al.q_paddr); 74057381Seric if (al.q_host != NULL) 74157381Seric free(al.q_host); 74257381Seric if (al.q_user != NULL) 74357381Seric free(al.q_user); 7444157Seric } 7454157Seric else 74656845Seric # endif /* NDBM */ 7474157Seric { 7484157Seric s = stab(al.q_user, ST_ALIAS, ST_ENTER); 7494157Seric s->s_alias = newstr(rhs); 7504157Seric } 7514322Seric 7524322Seric /* statistics */ 7534322Seric naliases++; 7544322Seric bytes += lhssize + rhssize; 7554322Seric if (rhssize > longest) 7564322Seric longest = rhssize; 7571515Seric } 75819784Seric 75956845Seric # if defined(NDBM) || defined(NEWDB) 76019784Seric if (init) 76119784Seric { 76219784Seric /* add the distinquished alias "@" */ 76356845Seric DBdatum key; 76419784Seric 76556845Seric key.xx.size = 2; 76656845Seric key.xx.data = "@"; 76750575Seric # ifdef NEWDB 76850576Seric if (dbp->sync(dbp) != 0 || 76956845Seric dbp->put(dbp, &key.dbt, &key.dbt, 0) != 0 || 77050576Seric dbp->close(dbp) != 0) 77150576Seric syserr("readaliases: db close failure"); 77253742Seric # endif 77356789Seric # ifdef IF_MAKEDBMFILES 77456793Seric IF_MAKEDBMFILES 77556845Seric { 77658059Seric #ifdef YPCOMPAT 77759152Seric static void nis_magic __P((DBM *dbmp)); 77858846Seric 77958059Seric nis_magic(dbmp); 78058059Seric #endif 78156845Seric if (dbm_store(dbmp, key.dbm, key.dbm, DBM_REPLACE) != 0 || 78256845Seric dbm_error(dbmp)) 78356845Seric syserr("readaliases: dbm close failure"); 78456845Seric dbm_close(dbmp); 78556845Seric } 78650575Seric # endif 78719784Seric 78819784Seric /* restore the old signal */ 78919784Seric (void) signal(SIGINT, oldsigint); 79019784Seric } 79156845Seric # endif /* NDBM */ 79219784Seric 79319784Seric /* closing the alias file drops the lock */ 7944098Seric (void) fclose(af); 79555012Seric e->e_to = NULL; 7969368Seric FileName = NULL; 79758151Seric message("%d aliases, longest %d bytes, %d bytes total", 7984322Seric naliases, longest, bytes); 79924944Seric # ifdef LOG 80058020Seric if (LogLevel > 7) 80124944Seric syslog(LOG_INFO, "%d aliases, longest %d bytes, %d bytes total", 80224944Seric naliases, longest, bytes); 80356795Seric # endif /* LOG */ 804292Seric } 805292Seric /* 80658059Seric ** NIS_MAGIC -- Add NIS magic dbm data 80758059Seric ** 80858059Seric ** This adds the magic entries needed by SunOS to make this a valid 80958059Seric ** NIS map. 81058059Seric ** 81158059Seric ** Parameters: 81258059Seric ** dbmp -- a pointer to the DBM structure. 81358059Seric ** 81458059Seric ** Returns: 81558059Seric ** none. 81658059Seric */ 81758059Seric 81858059Seric # ifdef YPCOMPAT 81958059Seric 82058059Seric static void 82158059Seric nis_magic(dbmp) 82258059Seric DBM *dbmp; 82358059Seric { 82458059Seric int i; 82558059Seric static datum key[2] = 82658059Seric { 82758059Seric { "YP_LAST_MODIFIED", sizeof "YP_LAST_MODIFIED" - 1 }, 82858059Seric { "YP_MASTER_NAME", sizeof "YP_MASTER_NAME" - 1 }, 82958059Seric }; 83058059Seric datum contents[2]; 83158059Seric char tbuf[12]; 83258059Seric char hbuf[MAXHOSTNAMELEN]; 83358059Seric 83458059Seric (void) sprintf(tbuf, "%010ld", curtime()); 83558059Seric contents[0].dptr = tbuf; 83658059Seric contents[0].dsize = strlen(tbuf); 83758059Seric 83858059Seric (void) myhostname(hbuf, sizeof hbuf); 83958059Seric contents[1].dptr = hbuf; 84058846Seric contents[1].dsize = strlen(hbuf); 84158059Seric 84258059Seric for (i = 0; i < sizeof key / sizeof *key; i++) 84358059Seric { 84458059Seric if (dbm_store(dbmp, key[i], contents[i], DBM_REPLACE) != 0 || 84558059Seric dbm_error(dbmp)) 84658059Seric syserr("nis_magic: dbm_store failure"); 84758059Seric } 84858059Seric } 84958059Seric 85058059Seric # endif 85158059Seric /* 852292Seric ** FORWARD -- Try to forward mail 853292Seric ** 854292Seric ** This is similar but not identical to aliasing. 855292Seric ** 856292Seric ** Parameters: 8574314Seric ** user -- the name of the user who's mail we would like 8584314Seric ** to forward to. It must have been verified -- 8594314Seric ** i.e., the q_home field must have been filled 8604314Seric ** in. 8614999Seric ** sendq -- a pointer to the head of the send queue to 8624999Seric ** put this user's aliases in. 863292Seric ** 864292Seric ** Returns: 8654098Seric ** none. 866292Seric ** 867292Seric ** Side Effects: 8683185Seric ** New names are added to send queues. 869292Seric */ 870292Seric 87155012Seric forward(user, sendq, e) 8722966Seric ADDRESS *user; 8734999Seric ADDRESS **sendq; 87455012Seric register ENVELOPE *e; 875292Seric { 87657136Seric char *pp; 87757136Seric char *ep; 8784069Seric 8797671Seric if (tTd(27, 1)) 8804098Seric printf("forward(%s)\n", user->q_paddr); 8814098Seric 8824594Seric if (user->q_mailer != LocalMailer || bitset(QBADADDR, user->q_flags)) 8834098Seric return; 8844314Seric if (user->q_home == NULL) 88558059Seric { 88658151Seric syserr("554 forward: no home"); 88758059Seric user->q_home = "/nosuchdirectory"; 88858059Seric } 8894069Seric 8904069Seric /* good address -- look for .forward file in home */ 89155012Seric define('z', user->q_home, e); 89257136Seric define('u', user->q_user, e); 89357136Seric define('h', user->q_host, e); 89457136Seric if (ForwardPath == NULL) 89558050Seric ForwardPath = newstr("\201z/.forward"); 89657136Seric 89757136Seric for (pp = ForwardPath; pp != NULL; pp = ep) 89857136Seric { 89958247Seric int err; 90057232Seric char buf[MAXPATHLEN+1]; 90157136Seric 90257136Seric ep = strchr(pp, ':'); 90357136Seric if (ep != NULL) 90457136Seric *ep = '\0'; 90557136Seric expand(pp, buf, &buf[sizeof buf - 1], e); 90657136Seric if (ep != NULL) 90757136Seric *ep++ = ':'; 90857136Seric if (tTd(27, 3)) 90957136Seric printf("forward: trying %s\n", buf); 91058247Seric err = include(buf, TRUE, user, sendq, e); 91158247Seric if (err == 0) 91257136Seric break; 91358247Seric if (transienterror(err)) 91458247Seric { 91558247Seric /* we have to suspend this message */ 91659563Seric if (tTd(27, 2)) 91759563Seric printf("forward: transient error on %s\n", buf); 91859563Seric #ifdef LOG 91959563Seric if (LogLevel > 2) 92059563Seric syslog(LOG_NOTICE, "%s: forward %s: transient error: %e", 92159563Seric e->e_id, buf); 92259563Seric #endif 923*59611Seric message("%s: %s: message queued", buf, errstring(err)); 92458247Seric user->q_flags |= QQUEUEUP|QDONTSEND; 92558247Seric return; 92658247Seric } 92757136Seric } 928292Seric } 929