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 <sys/stat.h> 1157948Seric # include <sys/file.h> 1250577Seric # include <signal.h> 1350577Seric # include <pwd.h> 1450577Seric 1556845Seric # ifdef DBM 1656848Seric ERROR: DBM is no longer supported -- use NDBM instead. 1756845Seric # endif 1856845Seric 1950577Seric # ifdef NEWDB 2050577Seric # include <db.h> 2150577Seric # endif 2250577Seric 2356766Seric # ifdef NDBM 2456845Seric # include <ndbm.h> 2556766Seric # endif 2656766Seric 2733728Sbostic #ifndef lint 2851756Seric #ifdef NEWDB 2957736Seric #ifdef NDBM 30*58689Seric static char sccsid[] = "@(#)alias.c 6.26 (Berkeley) 03/17/93 (with NEWDB and NDBM)"; 3151756Seric #else 32*58689Seric static char sccsid[] = "@(#)alias.c 6.26 (Berkeley) 03/17/93 (with NEWDB)"; 3357736Seric #endif 3457736Seric #else 3556845Seric #ifdef NDBM 36*58689Seric static char sccsid[] = "@(#)alias.c 6.26 (Berkeley) 03/17/93 (with NDBM)"; 3733728Sbostic #else 38*58689Seric static char sccsid[] = "@(#)alias.c 6.26 (Berkeley) 03/17/93 (without NEWDB or NDBM)"; 3933728Sbostic #endif 4050575Seric #endif 4133728Sbostic #endif /* not lint */ 4251756Seric /* 43292Seric ** ALIAS -- Compute aliases. 44292Seric ** 459368Seric ** Scans the alias file for an alias for the given address. 469368Seric ** If found, it arranges to deliver to the alias list instead. 479368Seric ** Uses libdbm database if -DDBM. 48292Seric ** 49292Seric ** Parameters: 504097Seric ** a -- address to alias. 514999Seric ** sendq -- a pointer to the head of the send queue 524999Seric ** to put the aliases in. 5358092Seric ** e -- the current envelope. 54292Seric ** 55292Seric ** Returns: 56292Seric ** none 57292Seric ** 58292Seric ** Side Effects: 593185Seric ** Aliases found are expanded. 60292Seric ** 61292Seric ** Notes: 62292Seric ** If NoAlias (the "-n" flag) is set, no aliasing is 63292Seric ** done. 64292Seric ** 65292Seric ** Deficiencies: 66292Seric ** It should complain about names that are aliased to 67292Seric ** nothing. 68292Seric */ 69292Seric 70292Seric 7153742Seric /* 7253742Seric ** Sun YP servers read the dbm files directly, so we have to build them 7353742Seric ** even if NEWDB 7453742Seric */ 7553742Seric 7656845Seric #ifdef NDBM 7753742Seric # ifndef NEWDB 7853742Seric # define IF_MAKEDBMFILES 7953742Seric # else 8053742Seric # ifdef YPCOMPAT 8153742Seric # define IF_MAKEDBMFILES if (makedbmfiles) 8253742Seric # endif 8353742Seric # endif 8453742Seric #endif 8553742Seric 8656845Seric typedef union 872966Seric { 8856845Seric #ifdef NDBM 8956845Seric datum dbm; 9051756Seric #endif 9156845Seric #ifdef NEWDB 9256845Seric DBT dbt; 9356845Seric #endif 9456845Seric struct 9556845Seric { 9656845Seric char *data; 9756845Seric int size; 9856845Seric } xx; 9956845Seric } DBdatum; 100292Seric 10150575Seric #ifdef NEWDB 10250575Seric static DB *AliasDBptr; 10350575Seric #endif 10456845Seric #ifdef NDBM 10556845Seric static DBM *AliasDBMptr; 10656845Seric #endif 10750575Seric 10855012Seric alias(a, sendq, e) 1094097Seric register ADDRESS *a; 1104999Seric ADDRESS **sendq; 11155012Seric register ENVELOPE *e; 112292Seric { 1134081Seric register char *p; 11458082Seric int naliases; 11558170Seric char *owner; 11658170Seric char obuf[MAXNAME + 6]; 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 */ 12358680Seric if (bitset(QDONTSEND|QBADADDR|QVERIFIED, 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); 14758092Seric if (bitset(EF_VRFYONLY, e->e_flags)) 14858154Seric { 14958154Seric a->q_flags |= QVERIFIED; 15058092Seric return; 15158154Seric } 15258154Seric message("aliased to %s", p); 15357977Seric #ifdef LOG 15458020Seric if (LogLevel > 9) 15557977Seric syslog(LOG_INFO, "%s: alias %s => %s", e->e_id, a->q_paddr, p); 15657977Seric #endif 15758082Seric a->q_flags &= ~QSELFREF; 1584098Seric AliasLevel++; 15958082Seric naliases = sendtolist(p, a, sendq, e); 1604098Seric AliasLevel--; 16158082Seric if (naliases > 0 && !bitset(QSELFREF, a->q_flags)) 16258065Seric { 16358065Seric if (tTd(27, 5)) 16458065Seric { 16558065Seric printf("alias: QDONTSEND "); 16658065Seric printaddr(a, FALSE); 16758065Seric } 16858065Seric a->q_flags |= QDONTSEND; 16958065Seric } 17058170Seric 17158170Seric /* 17258170Seric ** Look for owner of alias 17358170Seric */ 17458170Seric 17558170Seric (void) strcpy(obuf, "owner-"); 17658170Seric if (strncmp(a->q_user, "owner-", 6) == 0) 17758170Seric (void) strcat(obuf, "owner"); 17858170Seric else 17958170Seric (void) strcat(obuf, a->q_user); 18058170Seric if (!bitnset(M_USR_UPPER, a->q_mailer->m_flags)) 18158170Seric makelower(obuf); 18258170Seric owner = aliaslookup(obuf); 18358170Seric if (owner != NULL) 18458170Seric { 18558170Seric if (strchr(owner, ',') != NULL) 18658170Seric owner = obuf; 18758170Seric a->q_owner = newstr(owner); 18858170Seric } 1894098Seric } 1904098Seric /* 1915701Seric ** ALIASLOOKUP -- look up a name in the alias file. 1925701Seric ** 1935701Seric ** Parameters: 1945701Seric ** name -- the name to look up. 1955701Seric ** 1965701Seric ** Returns: 1975701Seric ** the value of name. 1985701Seric ** NULL if unknown. 1995701Seric ** 2005701Seric ** Side Effects: 2015701Seric ** none. 2025701Seric ** 2035701Seric ** Warnings: 2045701Seric ** The return value will be trashed across calls. 2055701Seric */ 2065701Seric 2075701Seric char * 2085701Seric aliaslookup(name) 2095701Seric char *name; 2105701Seric { 21157381Seric int i; 21257381Seric char keybuf[MAXNAME + 1]; 21356845Seric # if defined(NEWDB) || defined(NDBM) 21456845Seric DBdatum rhs, lhs; 21550575Seric int s; 21657381Seric # else /* neither NEWDB nor NDBM */ 21757381Seric register STAB *s; 21857381Seric # endif 2195701Seric 2205701Seric /* create a key for fetch */ 22157381Seric i = strlen(name) + 1; 22257381Seric if (i > sizeof keybuf) 22357381Seric i = sizeof keybuf; 22457381Seric bcopy(name, keybuf, i); 22557381Seric if (!bitnset(M_USR_UPPER, LocalMailer->m_flags)) 22657381Seric makelower(keybuf); 22757381Seric 22857381Seric # if defined(NEWDB) || defined(NDBM) 22957381Seric lhs.xx.size = i; 23057381Seric lhs.xx.data = keybuf; 23150575Seric # ifdef NEWDB 23251756Seric if (AliasDBptr != NULL) 23351756Seric { 23457381Seric i = AliasDBptr->get(AliasDBptr, &lhs.dbt, &rhs.dbt, 0); 23557381Seric if (i == 0) 23656845Seric return (rhs.dbt.data); 23751756Seric } 23856845Seric # ifdef NDBM 23957249Seric else if (AliasDBMptr != NULL) 24051756Seric { 24156845Seric rhs.dbm = dbm_fetch(AliasDBMptr, lhs.dbm); 24256845Seric return (rhs.dbm.dptr); 24351756Seric } 24456845Seric # endif /* NDBM */ 24557530Seric return (NULL); 24656845Seric # else /* not NEWDB */ 24756845Seric rhs.dbm = dbm_fetch(AliasDBMptr, lhs.dbm); 24856845Seric return (rhs.dbm.dptr); 24956845Seric # endif /* NEWDB */ 25056845Seric # else /* neither NEWDB nor NDBM */ 25157381Seric s = stab(keybuf, ST_ALIAS, ST_FIND); 25251756Seric if (s != NULL) 25351756Seric return (s->s_alias); 25457530Seric return (NULL); 25551756Seric # endif 2565701Seric } 2575701Seric /* 2584098Seric ** INITALIASES -- initialize for aliasing 2594098Seric ** 26056845Seric ** Very different depending on whether we are running NDBM or not. 2614098Seric ** 2624098Seric ** Parameters: 2634098Seric ** aliasfile -- location of aliases. 26456845Seric ** init -- if set and if NDBM, initialize the NDBM files. 2654098Seric ** 2664098Seric ** Returns: 2674098Seric ** none. 2684098Seric ** 2694098Seric ** Side Effects: 2704098Seric ** initializes aliases: 27156845Seric ** if NDBM: opens the database. 27256845Seric ** if ~NDBM: reads the aliases into the symbol table. 2734098Seric */ 2744098Seric 27540559Sbostic # define DBMMODE 0644 2764157Seric 27755012Seric initaliases(aliasfile, init, e) 2784098Seric char *aliasfile; 2794157Seric bool init; 28055012Seric register ENVELOPE *e; 2814098Seric { 28256845Seric #if defined(NDBM) || defined(NEWDB) 2838437Seric int atcnt; 28425522Seric time_t modtime; 28525522Seric bool automatic = FALSE; 2864322Seric char buf[MAXNAME]; 28750575Seric #endif 2889368Seric struct stat stb; 28927176Seric static bool initialized = FALSE; 29046928Sbostic static int readaliases(); 2914322Seric 29227176Seric if (initialized) 29327176Seric return; 29427176Seric initialized = TRUE; 29527176Seric 29617984Seric if (aliasfile == NULL || stat(aliasfile, &stb) < 0) 2978437Seric { 29825522Seric if (aliasfile != NULL && init) 29958151Seric syserr("554 Cannot open %s", aliasfile); 3008437Seric NoAlias = TRUE; 30111937Seric errno = 0; 3028437Seric return; 3038437Seric } 3048437Seric 30556845Seric # if defined(NDBM) || defined(NEWDB) 3064322Seric /* 3078437Seric ** Check to see that the alias file is complete. 3088437Seric ** If not, we will assume that someone died, and it is up 3098437Seric ** to us to rebuild it. 3108437Seric */ 3118437Seric 31225689Seric if (!init) 31350575Seric { 31450575Seric # ifdef NEWDB 31550575Seric (void) strcpy(buf, aliasfile); 31650575Seric (void) strcat(buf, ".db"); 31751171Sbostic AliasDBptr = dbopen(buf, O_RDONLY, DBMMODE, DB_HASH, NULL); 31850576Seric if (AliasDBptr == NULL) 31950576Seric { 32056845Seric # ifdef NDBM 32156845Seric AliasDBMptr = dbm_open(aliasfile, O_RDONLY, DBMMODE); 32257249Seric if (AliasDBMptr == NULL) 32357249Seric { 32457249Seric syserr("initaliases: cannot open %s", buf); 32557249Seric NoAlias = TRUE; 32657249Seric return; 32757249Seric } 32851756Seric # else 32950576Seric syserr("initaliases: cannot open %s", buf); 33050576Seric NoAlias = TRUE; 33150576Seric return; 33251756Seric # endif 33350576Seric } 33450575Seric # else 33556845Seric AliasDBMptr = dbm_open(aliasfile, O_RDONLY, DBMMODE); 33657249Seric if (AliasDBMptr == NULL) 33757249Seric { 33857977Seric syserr("initaliases: cannot open DBM database %s.{pag,dir}", 33957977Seric aliasfile); 34057249Seric NoAlias = TRUE; 34157249Seric return; 34257249Seric } 34350575Seric # endif 34450575Seric } 34517471Seric atcnt = SafeAlias * 2; 34617471Seric if (atcnt > 0) 34717471Seric { 34817471Seric while (!init && atcnt-- >= 0 && aliaslookup("@") == NULL) 34925689Seric { 35025689Seric /* 35125689Seric ** Reinitialize alias file in case the new 35225689Seric ** one is mv'ed in instead of cp'ed in. 35325689Seric ** 35425689Seric ** Only works with new DBM -- old one will 35525689Seric ** just consume file descriptors forever. 35625689Seric ** If you have a dbmclose() it can be 35725689Seric ** added before the sleep(30). 35825689Seric */ 35925689Seric 36050575Seric # ifdef NEWDB 36151756Seric if (AliasDBptr != NULL) 36251756Seric AliasDBptr->close(AliasDBptr); 36350575Seric # endif 36456845Seric # ifdef NDBM 36556845Seric if (AliasDBMptr != NULL) 36656845Seric dbm_close(AliasDBMptr); 36756845Seric # endif 36850575Seric 36917471Seric sleep(30); 37050575Seric # ifdef NEWDB 37150575Seric (void) strcpy(buf, aliasfile); 37250575Seric (void) strcat(buf, ".db"); 37351171Sbostic AliasDBptr = 37451171Sbostic dbopen(buf, O_RDONLY, DBMMODE, DB_HASH, NULL); 37550576Seric if (AliasDBptr == NULL) 37650576Seric { 37751756Seric # ifdef NDBM 37856845Seric AliasDBMptr = dbm_open(aliasfile, O_RDONLY, DBMMODE); 37951756Seric # else 38050576Seric syserr("initaliases: cannot open %s", buf); 38150576Seric NoAlias = TRUE; 38250576Seric return; 38351756Seric # endif 38450576Seric } 38550575Seric # else 38625689Seric # ifdef NDBM 38756845Seric AliasDBMptr = dbm_open(aliasfile, O_RDONLY, DBMMODE); 38857249Seric if (AliasDBMptr == NULL) 38957249Seric { 39058008Seric syserr("initaliases: cannot open DBM database %s.{pag,dir}", 39158008Seric aliasfile); 39257249Seric NoAlias = TRUE; 39357249Seric return; 39457249Seric } 39550575Seric # endif 39650575Seric # endif 39725689Seric } 39817471Seric } 39917471Seric else 40017471Seric atcnt = 1; 4018437Seric 4028437Seric /* 40356845Seric ** See if the NDBM version of the file is out of date with 4044322Seric ** the text version. If so, go into 'init' mode automatically. 40540559Sbostic ** This only happens if our effective userid owns the DBM. 40640559Sbostic ** Note the unpalatable hack to see if the stat succeeded. 4074322Seric */ 4084322Seric 4094322Seric modtime = stb.st_mtime; 4104322Seric (void) strcpy(buf, aliasfile); 41150575Seric # ifdef NEWDB 41250575Seric (void) strcat(buf, ".db"); 41350575Seric # else 4144322Seric (void) strcat(buf, ".pag"); 41550575Seric # endif 4164322Seric stb.st_ino = 0; 41719039Seric if (!init && (stat(buf, &stb) < 0 || stb.st_mtime < modtime || atcnt < 0)) 4184322Seric { 41911937Seric errno = 0; 42040559Sbostic if (AutoRebuild && stb.st_ino != 0 && stb.st_uid == geteuid()) 4214322Seric { 4224322Seric init = TRUE; 42325522Seric automatic = TRUE; 42458151Seric message("rebuilding alias database"); 42524944Seric #ifdef LOG 42658020Seric if (LogLevel > 14) 42724944Seric syslog(LOG_INFO, "rebuilding alias database"); 42856795Seric #endif /* LOG */ 4294322Seric } 4304322Seric else 4314322Seric { 43219039Seric #ifdef LOG 43358020Seric if (LogLevel > 3) 43424944Seric syslog(LOG_INFO, "alias database out of date"); 43556795Seric #endif /* LOG */ 43658151Seric message("Warning: alias database out of date"); 4374322Seric } 4384322Seric } 4394322Seric 4404322Seric 4414322Seric /* 44256845Seric ** If necessary, load the NDBM file. 44356845Seric ** If running without NDBM, load the symbol table. 4444322Seric */ 4454322Seric 4464157Seric if (init) 4478437Seric { 44825522Seric #ifdef LOG 44958020Seric if (LogLevel > 7) 45025522Seric { 45125522Seric extern char *username(); 45225522Seric 45325522Seric syslog(LOG_NOTICE, "alias database %srebuilt by %s", 45425522Seric automatic ? "auto" : "", username()); 45525522Seric } 45656795Seric #endif /* LOG */ 45755012Seric readaliases(aliasfile, TRUE, e); 4588437Seric } 45956845Seric # else /* NDBM */ 46055012Seric readaliases(aliasfile, init, e); 46156845Seric # endif /* NDBM */ 4624157Seric } 4634157Seric /* 4644157Seric ** READALIASES -- read and process the alias file. 4654157Seric ** 4664157Seric ** This routine implements the part of initaliases that occurs 4674157Seric ** when we are not going to use the DBM stuff. 4684157Seric ** 4694157Seric ** Parameters: 4704157Seric ** aliasfile -- the pathname of the alias file master. 47156845Seric ** init -- if set, initialize the NDBM stuff. 4724157Seric ** 4734157Seric ** Returns: 4744157Seric ** none. 4754157Seric ** 4764157Seric ** Side Effects: 4774157Seric ** Reads aliasfile into the symbol table. 4784157Seric ** Optionally, builds the .dir & .pag files. 4794157Seric */ 4804157Seric 4814157Seric static 48255012Seric readaliases(aliasfile, init, e) 4834157Seric char *aliasfile; 4844157Seric bool init; 48555012Seric register ENVELOPE *e; 4864157Seric { 4874098Seric register char *p; 4884098Seric char *rhs; 4894098Seric bool skipping; 4909368Seric int naliases, bytes, longest; 4919368Seric FILE *af; 49253742Seric bool makedbmfiles; 49340970Sbostic void (*oldsigint)(); 4944098Seric ADDRESS al, bl; 4954106Seric register STAB *s; 49650575Seric # ifdef NEWDB 49750575Seric DB *dbp; 49850575Seric # endif 49956845Seric # ifdef NDBM 50056845Seric DBM *dbmp; 50156845Seric # endif 5029368Seric char line[BUFSIZ]; 503*58689Seric extern bool lockfile(); 5044098Seric 50551937Seric if ((af = fopen(aliasfile, "r+")) == NULL) 5061515Seric { 50757249Seric if (init) 50858151Seric syserr("554 Can't open %s", aliasfile); 50957249Seric else if (tTd(27, 1)) 5104106Seric printf("Can't open %s\n", aliasfile); 5114098Seric errno = 0; 5124098Seric NoAlias++; 5134098Seric return; 5144098Seric } 5154314Seric 51656845Seric # if defined(NDBM) || defined(NEWDB) 51719784Seric /* see if someone else is rebuilding the alias file already */ 518*58689Seric if (!lockfile(fileno(af), aliasfile, LOCK_EX|LOCK_NB)) 51919784Seric { 52019784Seric /* yes, they are -- wait until done and then return */ 52158151Seric message("Alias file is already being rebuilt"); 52219784Seric if (OpMode != MD_INITALIAS) 52319784Seric { 52419784Seric /* wait for other rebuild to complete */ 525*58689Seric (void) lockfile(fileno(af), aliasfile, LOCK_EX); 52619784Seric } 52723108Seric (void) fclose(af); 52819784Seric errno = 0; 52919784Seric return; 53019784Seric } 53156845Seric # endif /* NDBM */ 53219784Seric 5334314Seric /* 53419784Seric ** If initializing, create the new DBM files. 53519784Seric */ 53619784Seric 53719784Seric if (init) 53819784Seric { 53919784Seric oldsigint = signal(SIGINT, SIG_IGN); 54051756Seric # ifdef NEWDB 54151756Seric (void) strcpy(line, aliasfile); 54251756Seric (void) strcat(line, ".db"); 54351756Seric dbp = dbopen(line, 54451756Seric O_RDWR|O_CREAT|O_TRUNC, DBMMODE, DB_HASH, NULL); 54551756Seric if (dbp == NULL) 54651756Seric { 54751756Seric syserr("readaliases: cannot create %s", line); 54851756Seric (void) signal(SIGINT, oldsigint); 54951756Seric return; 55051756Seric } 55153742Seric # endif 55253742Seric # ifdef IF_MAKEDBMFILES 55353742Seric # ifdef NEWDB 55453742Seric makedbmfiles = access("/var/yp/Makefile", R_OK) == 0; 55553742Seric # endif 55653742Seric IF_MAKEDBMFILES 55719784Seric { 55856845Seric dbmp = dbm_open(aliasfile, 55956845Seric O_RDWR|O_CREAT|O_TRUNC, DBMMODE); 56056845Seric if (dbmp == NULL) 56153742Seric { 56256845Seric syserr("readaliases: cannot create %s.{dir,pag}", 56356845Seric aliasfile); 56453742Seric (void) signal(SIGINT, oldsigint); 56553742Seric return; 56653742Seric } 56719784Seric } 56850575Seric # endif 56919784Seric } 57019784Seric 57119784Seric /* 5724314Seric ** Read and interpret lines 5734314Seric */ 5744314Seric 5759368Seric FileName = aliasfile; 5769368Seric LineNumber = 0; 5774322Seric naliases = bytes = longest = 0; 5784098Seric skipping = FALSE; 5794098Seric while (fgets(line, sizeof (line), af) != NULL) 5804098Seric { 5814322Seric int lhssize, rhssize; 5824322Seric 5839368Seric LineNumber++; 58456795Seric p = strchr(line, '\n'); 58525278Seric if (p != NULL) 58625278Seric *p = '\0'; 5874098Seric switch (line[0]) 5884098Seric { 5894098Seric case '#': 5904098Seric case '\0': 5914098Seric skipping = FALSE; 5924098Seric continue; 5934065Seric 5944098Seric case ' ': 5954098Seric case '\t': 5964098Seric if (!skipping) 59758151Seric syserr("554 Non-continuation line starts with space"); 5984098Seric skipping = TRUE; 5994097Seric continue; 6004098Seric } 6014098Seric skipping = FALSE; 6021874Seric 6034314Seric /* 6044314Seric ** Process the LHS 60557736Seric ** Find the colon separator, and parse the address. 60616898Seric ** It should resolve to a local name -- this will 60716898Seric ** be checked later (we want to optionally do 60816898Seric ** parsing of the RHS first to maximize error 60916898Seric ** detection). 6104314Seric */ 6114314Seric 6124098Seric for (p = line; *p != '\0' && *p != ':' && *p != '\n'; p++) 6134097Seric continue; 61416898Seric if (*p++ != ':') 6154098Seric { 61658151Seric syserr("554 missing colon"); 6174097Seric continue; 6184098Seric } 61958333Seric if (parseaddr(line, &al, 1, ':', NULL, e) == NULL) 6204098Seric { 62158151Seric syserr("554 illegal alias name"); 62216898Seric continue; 6234098Seric } 6244314Seric 6254314Seric /* 6264314Seric ** Process the RHS. 6274314Seric ** 'al' is the internal form of the LHS address. 6284314Seric ** 'p' points to the text of the RHS. 6294314Seric */ 6304314Seric 6314098Seric rhs = p; 6324098Seric for (;;) 6334098Seric { 6344098Seric register char c; 63558662Seric register char *nlp; 6361515Seric 63758662Seric nlp = &p[strlen(p)]; 63858662Seric if (nlp[-1] == '\n') 63958662Seric *--nlp = '\0'; 64058662Seric 64125821Seric if (init && CheckAliases) 6424098Seric { 6434157Seric /* do parsing & compression of addresses */ 64425278Seric while (*p != '\0') 6454098Seric { 64658333Seric auto char *delimptr; 64725278Seric 64858050Seric while ((isascii(*p) && isspace(*p)) || 64958050Seric *p == ',') 6504157Seric p++; 65125278Seric if (*p == '\0') 65225278Seric break; 65358333Seric if (parseaddr(p, &bl, -1, ',', &delimptr, e) == NULL) 65458151Seric usrerr("553 %s... bad address", p); 65558333Seric p = delimptr; 6564098Seric } 6574098Seric } 6584157Seric else 65915769Seric { 66058662Seric p = nlp; 66115769Seric } 6621515Seric 6634098Seric /* see if there should be a continuation line */ 6644106Seric c = fgetc(af); 6654106Seric if (!feof(af)) 6664314Seric (void) ungetc(c, af); 6674106Seric if (c != ' ' && c != '\t') 6684098Seric break; 6694098Seric 6704098Seric /* read continuation line */ 6714098Seric if (fgets(p, sizeof line - (p - line), af) == NULL) 6724098Seric break; 6739368Seric LineNumber++; 67457135Seric 67557135Seric /* check for line overflow */ 67657135Seric if (strchr(p, '\n') == NULL) 67757135Seric { 67858151Seric usrerr("554 alias too long"); 67957135Seric break; 68057135Seric } 6814098Seric } 68216898Seric if (al.q_mailer != LocalMailer) 68316898Seric { 68458151Seric syserr("554 cannot alias non-local names"); 68516898Seric continue; 68616898Seric } 6874314Seric 6884314Seric /* 6894314Seric ** Insert alias into symbol table or DBM file 6904314Seric */ 6914314Seric 69216898Seric lhssize = strlen(al.q_user) + 1; 69357381Seric if (!bitnset(M_USR_UPPER, al.q_mailer->m_flags)) 69457381Seric makelower(al.q_user); 6954322Seric rhssize = strlen(rhs) + 1; 6964322Seric 69756845Seric # if defined(NDBM) || defined(NEWDB) 6984157Seric if (init) 6994157Seric { 70056845Seric DBdatum key, content; 70157381Seric int putstat; 7024157Seric 70356845Seric key.xx.size = lhssize; 70456845Seric key.xx.data = al.q_user; 70556845Seric content.xx.size = rhssize; 70656845Seric content.xx.data = rhs; 70751756Seric # ifdef NEWDB 70857381Seric putstat = dbp->put(dbp, &key.dbt, &content.dbt, 70957381Seric R_NOOVERWRITE); 71057381Seric if (putstat > 0) 71157381Seric { 71257977Seric usrerr("050 Warning: duplicate alias name %s", 71357381Seric al.q_user); 71457381Seric putstat = dbp->put(dbp, &key.dbt, 71557381Seric &content.dbt, 0); 71657381Seric } 71757381Seric if (putstat != 0) 71850576Seric syserr("readaliases: db put (%s)", al.q_user); 71950575Seric # endif 72053742Seric # ifdef IF_MAKEDBMFILES 72153742Seric IF_MAKEDBMFILES 72257381Seric { 72357381Seric putstat = dbm_store(dbmp, key.dbm, content.dbm, 72457381Seric DBM_INSERT); 72557381Seric if (putstat > 0) 72657381Seric { 72757977Seric usrerr("050 Warning: duplicate alias name %s", 72857381Seric al.q_user); 72957381Seric putstat = dbm_store(dbmp, key.dbm, 73057381Seric content.dbm, DBM_REPLACE); 73157381Seric } 73257381Seric if (putstat != 0) 73356845Seric syserr("readaliases: dbm store (%s)", 73456845Seric al.q_user); 73557381Seric } 73653742Seric # endif 73757381Seric if (al.q_paddr != NULL) 73857381Seric free(al.q_paddr); 73957381Seric if (al.q_host != NULL) 74057381Seric free(al.q_host); 74157381Seric if (al.q_user != NULL) 74257381Seric free(al.q_user); 7434157Seric } 7444157Seric else 74556845Seric # endif /* NDBM */ 7464157Seric { 7474157Seric s = stab(al.q_user, ST_ALIAS, ST_ENTER); 7484157Seric s->s_alias = newstr(rhs); 7494157Seric } 7504322Seric 7514322Seric /* statistics */ 7524322Seric naliases++; 7534322Seric bytes += lhssize + rhssize; 7544322Seric if (rhssize > longest) 7554322Seric longest = rhssize; 7561515Seric } 75719784Seric 75856845Seric # if defined(NDBM) || defined(NEWDB) 75919784Seric if (init) 76019784Seric { 76119784Seric /* add the distinquished alias "@" */ 76256845Seric DBdatum key; 76319784Seric 76456845Seric key.xx.size = 2; 76556845Seric key.xx.data = "@"; 76650575Seric # ifdef NEWDB 76750576Seric if (dbp->sync(dbp) != 0 || 76856845Seric dbp->put(dbp, &key.dbt, &key.dbt, 0) != 0 || 76950576Seric dbp->close(dbp) != 0) 77050576Seric syserr("readaliases: db close failure"); 77153742Seric # endif 77256789Seric # ifdef IF_MAKEDBMFILES 77356793Seric IF_MAKEDBMFILES 77456845Seric { 77558059Seric #ifdef YPCOMPAT 77658059Seric nis_magic(dbmp); 77758059Seric #endif 77856845Seric if (dbm_store(dbmp, key.dbm, key.dbm, DBM_REPLACE) != 0 || 77956845Seric dbm_error(dbmp)) 78056845Seric syserr("readaliases: dbm close failure"); 78156845Seric dbm_close(dbmp); 78256845Seric } 78350575Seric # endif 78419784Seric 78519784Seric /* restore the old signal */ 78619784Seric (void) signal(SIGINT, oldsigint); 78719784Seric } 78856845Seric # endif /* NDBM */ 78919784Seric 79019784Seric /* closing the alias file drops the lock */ 7914098Seric (void) fclose(af); 79255012Seric e->e_to = NULL; 7939368Seric FileName = NULL; 79458151Seric message("%d aliases, longest %d bytes, %d bytes total", 7954322Seric naliases, longest, bytes); 79624944Seric # ifdef LOG 79758020Seric if (LogLevel > 7) 79824944Seric syslog(LOG_INFO, "%d aliases, longest %d bytes, %d bytes total", 79924944Seric naliases, longest, bytes); 80056795Seric # endif /* LOG */ 801292Seric } 802292Seric /* 80358059Seric ** NIS_MAGIC -- Add NIS magic dbm data 80458059Seric ** 80558059Seric ** This adds the magic entries needed by SunOS to make this a valid 80658059Seric ** NIS map. 80758059Seric ** 80858059Seric ** Parameters: 80958059Seric ** dbmp -- a pointer to the DBM structure. 81058059Seric ** 81158059Seric ** Returns: 81258059Seric ** none. 81358059Seric */ 81458059Seric 81558059Seric # ifdef YPCOMPAT 81658059Seric 81758059Seric static void 81858059Seric nis_magic(dbmp) 81958059Seric DBM *dbmp; 82058059Seric { 82158059Seric int i; 82258059Seric static datum key[2] = 82358059Seric { 82458059Seric { "YP_LAST_MODIFIED", sizeof "YP_LAST_MODIFIED" - 1 }, 82558059Seric { "YP_MASTER_NAME", sizeof "YP_MASTER_NAME" - 1 }, 82658059Seric }; 82758059Seric datum contents[2]; 82858059Seric char tbuf[12]; 82958059Seric char hbuf[MAXHOSTNAMELEN]; 83058059Seric 83158059Seric (void) sprintf(tbuf, "%010ld", curtime()); 83258059Seric contents[0].dptr = tbuf; 83358059Seric contents[0].dsize = strlen(tbuf); 83458059Seric 83558059Seric (void) myhostname(hbuf, sizeof hbuf); 83658059Seric contents[1].dptr = hbuf; 83758059Seric contents[1].dptr = strlen(hbuf); 83858059Seric 83958059Seric for (i = 0; i < sizeof key / sizeof *key; i++) 84058059Seric { 84158059Seric if (dbm_store(dbmp, key[i], contents[i], DBM_REPLACE) != 0 || 84258059Seric dbm_error(dbmp)) 84358059Seric syserr("nis_magic: dbm_store failure"); 84458059Seric } 84558059Seric } 84658059Seric 84758059Seric # endif 84858059Seric /* 849292Seric ** FORWARD -- Try to forward mail 850292Seric ** 851292Seric ** This is similar but not identical to aliasing. 852292Seric ** 853292Seric ** Parameters: 8544314Seric ** user -- the name of the user who's mail we would like 8554314Seric ** to forward to. It must have been verified -- 8564314Seric ** i.e., the q_home field must have been filled 8574314Seric ** in. 8584999Seric ** sendq -- a pointer to the head of the send queue to 8594999Seric ** put this user's aliases in. 860292Seric ** 861292Seric ** Returns: 8624098Seric ** none. 863292Seric ** 864292Seric ** Side Effects: 8653185Seric ** New names are added to send queues. 866292Seric */ 867292Seric 86855012Seric forward(user, sendq, e) 8692966Seric ADDRESS *user; 8704999Seric ADDRESS **sendq; 87155012Seric register ENVELOPE *e; 872292Seric { 87357136Seric char *pp; 87457136Seric char *ep; 8754069Seric 8767671Seric if (tTd(27, 1)) 8774098Seric printf("forward(%s)\n", user->q_paddr); 8784098Seric 8794594Seric if (user->q_mailer != LocalMailer || bitset(QBADADDR, user->q_flags)) 8804098Seric return; 8814314Seric if (user->q_home == NULL) 88258059Seric { 88358151Seric syserr("554 forward: no home"); 88458059Seric user->q_home = "/nosuchdirectory"; 88558059Seric } 8864069Seric 8874069Seric /* good address -- look for .forward file in home */ 88855012Seric define('z', user->q_home, e); 88957136Seric define('u', user->q_user, e); 89057136Seric define('h', user->q_host, e); 89157136Seric if (ForwardPath == NULL) 89258050Seric ForwardPath = newstr("\201z/.forward"); 89357136Seric 89457136Seric for (pp = ForwardPath; pp != NULL; pp = ep) 89557136Seric { 89658247Seric int err; 89757232Seric char buf[MAXPATHLEN+1]; 89857136Seric 89957136Seric ep = strchr(pp, ':'); 90057136Seric if (ep != NULL) 90157136Seric *ep = '\0'; 90257136Seric expand(pp, buf, &buf[sizeof buf - 1], e); 90357136Seric if (ep != NULL) 90457136Seric *ep++ = ':'; 90557136Seric if (tTd(27, 3)) 90657136Seric printf("forward: trying %s\n", buf); 90758247Seric err = include(buf, TRUE, user, sendq, e); 90858247Seric if (err == 0) 90957136Seric break; 91058247Seric if (transienterror(err)) 91158247Seric { 91258247Seric /* we have to suspend this message */ 91358247Seric user->q_flags |= QQUEUEUP|QDONTSEND; 91458247Seric return; 91558247Seric } 91657136Seric } 917292Seric } 918