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*58170Seric static char sccsid[] = "@(#)alias.c 6.18 (Berkeley) 02/24/93 (with NEWDB and NDBM)"; 3351756Seric #else 34*58170Seric static char sccsid[] = "@(#)alias.c 6.18 (Berkeley) 02/24/93 (with NEWDB)"; 3557736Seric #endif 3657736Seric #else 3756845Seric #ifdef NDBM 38*58170Seric static char sccsid[] = "@(#)alias.c 6.18 (Berkeley) 02/24/93 (with NDBM)"; 3933728Sbostic #else 40*58170Seric static char sccsid[] = "@(#)alias.c 6.18 (Berkeley) 02/24/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. 5558092Seric ** e -- the current envelope. 56292Seric ** 57292Seric ** Returns: 58292Seric ** none 59292Seric ** 60292Seric ** Side Effects: 613185Seric ** Aliases found are expanded. 62292Seric ** 63292Seric ** Notes: 64292Seric ** If NoAlias (the "-n" flag) is set, no aliasing is 65292Seric ** done. 66292Seric ** 67292Seric ** Deficiencies: 68292Seric ** It should complain about names that are aliased to 69292Seric ** nothing. 70292Seric */ 71292Seric 72292Seric 7353742Seric /* 7453742Seric ** Sun YP servers read the dbm files directly, so we have to build them 7553742Seric ** even if NEWDB 7653742Seric */ 7753742Seric 7856845Seric #ifdef NDBM 7953742Seric # ifndef NEWDB 8053742Seric # define IF_MAKEDBMFILES 8153742Seric # else 8253742Seric # ifdef YPCOMPAT 8353742Seric # define IF_MAKEDBMFILES if (makedbmfiles) 8453742Seric # endif 8553742Seric # endif 8653742Seric #endif 8753742Seric 8856845Seric typedef union 892966Seric { 9056845Seric #ifdef NDBM 9156845Seric datum dbm; 9251756Seric #endif 9356845Seric #ifdef NEWDB 9456845Seric DBT dbt; 9556845Seric #endif 9656845Seric struct 9756845Seric { 9856845Seric char *data; 9956845Seric int size; 10056845Seric } xx; 10156845Seric } DBdatum; 102292Seric 10350575Seric #ifdef NEWDB 10450575Seric static DB *AliasDBptr; 10550575Seric #endif 10656845Seric #ifdef NDBM 10756845Seric static DBM *AliasDBMptr; 10856845Seric #endif 10950575Seric 11055012Seric alias(a, sendq, e) 1114097Seric register ADDRESS *a; 1124999Seric ADDRESS **sendq; 11355012Seric register ENVELOPE *e; 114292Seric { 1154081Seric register char *p; 11658082Seric int naliases; 117*58170Seric char *owner; 118*58170Seric char obuf[MAXNAME + 6]; 1195701Seric extern char *aliaslookup(); 120292Seric 1217671Seric if (tTd(27, 1)) 1224098Seric printf("alias(%s)\n", a->q_paddr); 123292Seric 1244098Seric /* don't realias already aliased names */ 12558154Seric if (bitset(QDONTSEND|QVERIFIED, a->q_flags)) 1264098Seric return; 1274098Seric 12855012Seric e->e_to = a->q_paddr; 1294098Seric 1304314Seric /* 1314314Seric ** Look up this name 1324314Seric */ 1334314Seric 13424944Seric if (NoAlias) 13524944Seric p = NULL; 13624944Seric else 13724944Seric p = aliaslookup(a->q_user); 1384098Seric if (p == NULL) 1394098Seric return; 140292Seric 141292Seric /* 1424098Seric ** Match on Alias. 1434098Seric ** Deliver to the target list. 1441515Seric */ 1451515Seric 1467671Seric if (tTd(27, 1)) 1474098Seric printf("%s (%s, %s) aliased to %s\n", 1484098Seric a->q_paddr, a->q_host, a->q_user, p); 14958092Seric if (bitset(EF_VRFYONLY, e->e_flags)) 15058154Seric { 15158154Seric a->q_flags |= QVERIFIED; 15258092Seric return; 15358154Seric } 15458154Seric message("aliased to %s", p); 15557977Seric #ifdef LOG 15658020Seric if (LogLevel > 9) 15757977Seric syslog(LOG_INFO, "%s: alias %s => %s", e->e_id, a->q_paddr, p); 15857977Seric #endif 15958082Seric a->q_flags &= ~QSELFREF; 1604098Seric AliasLevel++; 16158082Seric naliases = sendtolist(p, a, sendq, e); 1624098Seric AliasLevel--; 16358082Seric if (naliases > 0 && !bitset(QSELFREF, a->q_flags)) 16458065Seric { 16558065Seric if (tTd(27, 5)) 16658065Seric { 16758065Seric printf("alias: QDONTSEND "); 16858065Seric printaddr(a, FALSE); 16958065Seric } 17058065Seric a->q_flags |= QDONTSEND; 17158065Seric } 172*58170Seric 173*58170Seric /* 174*58170Seric ** Look for owner of alias 175*58170Seric */ 176*58170Seric 177*58170Seric (void) strcpy(obuf, "owner-"); 178*58170Seric if (strncmp(a->q_user, "owner-", 6) == 0) 179*58170Seric (void) strcat(obuf, "owner"); 180*58170Seric else 181*58170Seric (void) strcat(obuf, a->q_user); 182*58170Seric if (!bitnset(M_USR_UPPER, a->q_mailer->m_flags)) 183*58170Seric makelower(obuf); 184*58170Seric owner = aliaslookup(obuf); 185*58170Seric if (owner != NULL) 186*58170Seric { 187*58170Seric if (strchr(owner, ',') != NULL) 188*58170Seric owner = obuf; 189*58170Seric a->q_owner = newstr(owner); 190*58170Seric } 1914098Seric } 1924098Seric /* 1935701Seric ** ALIASLOOKUP -- look up a name in the alias file. 1945701Seric ** 1955701Seric ** Parameters: 1965701Seric ** name -- the name to look up. 1975701Seric ** 1985701Seric ** Returns: 1995701Seric ** the value of name. 2005701Seric ** NULL if unknown. 2015701Seric ** 2025701Seric ** Side Effects: 2035701Seric ** none. 2045701Seric ** 2055701Seric ** Warnings: 2065701Seric ** The return value will be trashed across calls. 2075701Seric */ 2085701Seric 2095701Seric char * 2105701Seric aliaslookup(name) 2115701Seric char *name; 2125701Seric { 21357381Seric int i; 21457381Seric char keybuf[MAXNAME + 1]; 21556845Seric # if defined(NEWDB) || defined(NDBM) 21656845Seric DBdatum rhs, lhs; 21750575Seric int s; 21857381Seric # else /* neither NEWDB nor NDBM */ 21957381Seric register STAB *s; 22057381Seric # endif 2215701Seric 2225701Seric /* create a key for fetch */ 22357381Seric i = strlen(name) + 1; 22457381Seric if (i > sizeof keybuf) 22557381Seric i = sizeof keybuf; 22657381Seric bcopy(name, keybuf, i); 22757381Seric if (!bitnset(M_USR_UPPER, LocalMailer->m_flags)) 22857381Seric makelower(keybuf); 22957381Seric 23057381Seric # if defined(NEWDB) || defined(NDBM) 23157381Seric lhs.xx.size = i; 23257381Seric lhs.xx.data = keybuf; 23350575Seric # ifdef NEWDB 23451756Seric if (AliasDBptr != NULL) 23551756Seric { 23657381Seric i = AliasDBptr->get(AliasDBptr, &lhs.dbt, &rhs.dbt, 0); 23757381Seric if (i == 0) 23856845Seric return (rhs.dbt.data); 23951756Seric } 24056845Seric # ifdef NDBM 24157249Seric else if (AliasDBMptr != NULL) 24251756Seric { 24356845Seric rhs.dbm = dbm_fetch(AliasDBMptr, lhs.dbm); 24456845Seric return (rhs.dbm.dptr); 24551756Seric } 24656845Seric # endif /* NDBM */ 24757530Seric return (NULL); 24856845Seric # else /* not NEWDB */ 24956845Seric rhs.dbm = dbm_fetch(AliasDBMptr, lhs.dbm); 25056845Seric return (rhs.dbm.dptr); 25156845Seric # endif /* NEWDB */ 25256845Seric # else /* neither NEWDB nor NDBM */ 25357381Seric s = stab(keybuf, ST_ALIAS, ST_FIND); 25451756Seric if (s != NULL) 25551756Seric return (s->s_alias); 25657530Seric return (NULL); 25751756Seric # endif 2585701Seric } 2595701Seric /* 2604098Seric ** INITALIASES -- initialize for aliasing 2614098Seric ** 26256845Seric ** Very different depending on whether we are running NDBM or not. 2634098Seric ** 2644098Seric ** Parameters: 2654098Seric ** aliasfile -- location of aliases. 26656845Seric ** init -- if set and if NDBM, initialize the NDBM files. 2674098Seric ** 2684098Seric ** Returns: 2694098Seric ** none. 2704098Seric ** 2714098Seric ** Side Effects: 2724098Seric ** initializes aliases: 27356845Seric ** if NDBM: opens the database. 27456845Seric ** if ~NDBM: reads the aliases into the symbol table. 2754098Seric */ 2764098Seric 27740559Sbostic # define DBMMODE 0644 2784157Seric 27955012Seric initaliases(aliasfile, init, e) 2804098Seric char *aliasfile; 2814157Seric bool init; 28255012Seric register ENVELOPE *e; 2834098Seric { 28456845Seric #if defined(NDBM) || defined(NEWDB) 2858437Seric int atcnt; 28625522Seric time_t modtime; 28725522Seric bool automatic = FALSE; 2884322Seric char buf[MAXNAME]; 28950575Seric #endif 2909368Seric struct stat stb; 29127176Seric static bool initialized = FALSE; 29246928Sbostic static int readaliases(); 2934322Seric 29427176Seric if (initialized) 29527176Seric return; 29627176Seric initialized = TRUE; 29727176Seric 29817984Seric if (aliasfile == NULL || stat(aliasfile, &stb) < 0) 2998437Seric { 30025522Seric if (aliasfile != NULL && init) 30158151Seric syserr("554 Cannot open %s", aliasfile); 3028437Seric NoAlias = TRUE; 30311937Seric errno = 0; 3048437Seric return; 3058437Seric } 3068437Seric 30756845Seric # if defined(NDBM) || defined(NEWDB) 3084322Seric /* 3098437Seric ** Check to see that the alias file is complete. 3108437Seric ** If not, we will assume that someone died, and it is up 3118437Seric ** to us to rebuild it. 3128437Seric */ 3138437Seric 31425689Seric if (!init) 31550575Seric { 31650575Seric # ifdef NEWDB 31750575Seric (void) strcpy(buf, aliasfile); 31850575Seric (void) strcat(buf, ".db"); 31951171Sbostic AliasDBptr = dbopen(buf, O_RDONLY, DBMMODE, DB_HASH, NULL); 32050576Seric if (AliasDBptr == NULL) 32150576Seric { 32256845Seric # ifdef NDBM 32356845Seric AliasDBMptr = dbm_open(aliasfile, O_RDONLY, DBMMODE); 32457249Seric if (AliasDBMptr == NULL) 32557249Seric { 32657249Seric syserr("initaliases: cannot open %s", buf); 32757249Seric NoAlias = TRUE; 32857249Seric return; 32957249Seric } 33051756Seric # else 33150576Seric syserr("initaliases: cannot open %s", buf); 33250576Seric NoAlias = TRUE; 33350576Seric return; 33451756Seric # endif 33550576Seric } 33650575Seric # else 33756845Seric AliasDBMptr = dbm_open(aliasfile, O_RDONLY, DBMMODE); 33857249Seric if (AliasDBMptr == NULL) 33957249Seric { 34057977Seric syserr("initaliases: cannot open DBM database %s.{pag,dir}", 34157977Seric aliasfile); 34257249Seric NoAlias = TRUE; 34357249Seric return; 34457249Seric } 34550575Seric # endif 34650575Seric } 34717471Seric atcnt = SafeAlias * 2; 34817471Seric if (atcnt > 0) 34917471Seric { 35017471Seric while (!init && atcnt-- >= 0 && aliaslookup("@") == NULL) 35125689Seric { 35225689Seric /* 35325689Seric ** Reinitialize alias file in case the new 35425689Seric ** one is mv'ed in instead of cp'ed in. 35525689Seric ** 35625689Seric ** Only works with new DBM -- old one will 35725689Seric ** just consume file descriptors forever. 35825689Seric ** If you have a dbmclose() it can be 35925689Seric ** added before the sleep(30). 36025689Seric */ 36125689Seric 36250575Seric # ifdef NEWDB 36351756Seric if (AliasDBptr != NULL) 36451756Seric AliasDBptr->close(AliasDBptr); 36550575Seric # endif 36656845Seric # ifdef NDBM 36756845Seric if (AliasDBMptr != NULL) 36856845Seric dbm_close(AliasDBMptr); 36956845Seric # endif 37050575Seric 37117471Seric sleep(30); 37250575Seric # ifdef NEWDB 37350575Seric (void) strcpy(buf, aliasfile); 37450575Seric (void) strcat(buf, ".db"); 37551171Sbostic AliasDBptr = 37651171Sbostic dbopen(buf, O_RDONLY, DBMMODE, DB_HASH, NULL); 37750576Seric if (AliasDBptr == NULL) 37850576Seric { 37951756Seric # ifdef NDBM 38056845Seric AliasDBMptr = dbm_open(aliasfile, O_RDONLY, DBMMODE); 38151756Seric # else 38250576Seric syserr("initaliases: cannot open %s", buf); 38350576Seric NoAlias = TRUE; 38450576Seric return; 38551756Seric # endif 38650576Seric } 38750575Seric # else 38825689Seric # ifdef NDBM 38956845Seric AliasDBMptr = dbm_open(aliasfile, O_RDONLY, DBMMODE); 39057249Seric if (AliasDBMptr == NULL) 39157249Seric { 39258008Seric syserr("initaliases: cannot open DBM database %s.{pag,dir}", 39358008Seric aliasfile); 39457249Seric NoAlias = TRUE; 39557249Seric return; 39657249Seric } 39750575Seric # endif 39850575Seric # endif 39925689Seric } 40017471Seric } 40117471Seric else 40217471Seric atcnt = 1; 4038437Seric 4048437Seric /* 40556845Seric ** See if the NDBM version of the file is out of date with 4064322Seric ** the text version. If so, go into 'init' mode automatically. 40740559Sbostic ** This only happens if our effective userid owns the DBM. 40840559Sbostic ** Note the unpalatable hack to see if the stat succeeded. 4094322Seric */ 4104322Seric 4114322Seric modtime = stb.st_mtime; 4124322Seric (void) strcpy(buf, aliasfile); 41350575Seric # ifdef NEWDB 41450575Seric (void) strcat(buf, ".db"); 41550575Seric # else 4164322Seric (void) strcat(buf, ".pag"); 41750575Seric # endif 4184322Seric stb.st_ino = 0; 41919039Seric if (!init && (stat(buf, &stb) < 0 || stb.st_mtime < modtime || atcnt < 0)) 4204322Seric { 42111937Seric errno = 0; 42240559Sbostic if (AutoRebuild && stb.st_ino != 0 && stb.st_uid == geteuid()) 4234322Seric { 4244322Seric init = TRUE; 42525522Seric automatic = TRUE; 42658151Seric message("rebuilding alias database"); 42724944Seric #ifdef LOG 42858020Seric if (LogLevel > 14) 42924944Seric syslog(LOG_INFO, "rebuilding alias database"); 43056795Seric #endif /* LOG */ 4314322Seric } 4324322Seric else 4334322Seric { 43419039Seric #ifdef LOG 43558020Seric if (LogLevel > 3) 43624944Seric syslog(LOG_INFO, "alias database out of date"); 43756795Seric #endif /* LOG */ 43858151Seric message("Warning: alias database out of date"); 4394322Seric } 4404322Seric } 4414322Seric 4424322Seric 4434322Seric /* 44456845Seric ** If necessary, load the NDBM file. 44556845Seric ** If running without NDBM, load the symbol table. 4464322Seric */ 4474322Seric 4484157Seric if (init) 4498437Seric { 45025522Seric #ifdef LOG 45158020Seric if (LogLevel > 7) 45225522Seric { 45325522Seric extern char *username(); 45425522Seric 45525522Seric syslog(LOG_NOTICE, "alias database %srebuilt by %s", 45625522Seric automatic ? "auto" : "", username()); 45725522Seric } 45856795Seric #endif /* LOG */ 45955012Seric readaliases(aliasfile, TRUE, e); 4608437Seric } 46156845Seric # else /* NDBM */ 46255012Seric readaliases(aliasfile, init, e); 46356845Seric # endif /* NDBM */ 4644157Seric } 4654157Seric /* 4664157Seric ** READALIASES -- read and process the alias file. 4674157Seric ** 4684157Seric ** This routine implements the part of initaliases that occurs 4694157Seric ** when we are not going to use the DBM stuff. 4704157Seric ** 4714157Seric ** Parameters: 4724157Seric ** aliasfile -- the pathname of the alias file master. 47356845Seric ** init -- if set, initialize the NDBM stuff. 4744157Seric ** 4754157Seric ** Returns: 4764157Seric ** none. 4774157Seric ** 4784157Seric ** Side Effects: 4794157Seric ** Reads aliasfile into the symbol table. 4804157Seric ** Optionally, builds the .dir & .pag files. 4814157Seric */ 4824157Seric 4834157Seric static 48455012Seric readaliases(aliasfile, init, e) 4854157Seric char *aliasfile; 4864157Seric bool init; 48755012Seric register ENVELOPE *e; 4884157Seric { 4894098Seric register char *p; 4904098Seric char *rhs; 4914098Seric bool skipping; 4929368Seric int naliases, bytes, longest; 4939368Seric FILE *af; 49453742Seric bool makedbmfiles; 49540970Sbostic void (*oldsigint)(); 4964098Seric ADDRESS al, bl; 4974106Seric register STAB *s; 49850575Seric # ifdef NEWDB 49950575Seric DB *dbp; 50050575Seric # endif 50156845Seric # ifdef NDBM 50256845Seric DBM *dbmp; 50356845Seric # endif 50451937Seric # ifdef LOCKF 50551937Seric struct flock fld; 50651937Seric # endif 5079368Seric char line[BUFSIZ]; 5084098Seric 50951937Seric if ((af = fopen(aliasfile, "r+")) == NULL) 5101515Seric { 51157249Seric if (init) 51258151Seric syserr("554 Can't open %s", aliasfile); 51357249Seric else if (tTd(27, 1)) 5144106Seric printf("Can't open %s\n", aliasfile); 5154098Seric errno = 0; 5164098Seric NoAlias++; 5174098Seric return; 5184098Seric } 5194314Seric 52056845Seric # if defined(NDBM) || defined(NEWDB) 52119784Seric /* see if someone else is rebuilding the alias file already */ 52251835Seric # ifdef LOCKF 52351937Seric fld.l_type = F_WRLCK; 52451937Seric fld.l_whence = fld.l_start = fld.l_len = 0; 52551937Seric if (fcntl(fileno(af), F_SETLK, &fld) < 0) 52651835Seric # else 52719784Seric if (flock(fileno(af), LOCK_EX | LOCK_NB) < 0 && errno == EWOULDBLOCK) 52851835Seric # endif 52919784Seric { 53019784Seric /* yes, they are -- wait until done and then return */ 53158151Seric message("Alias file is already being rebuilt"); 53219784Seric if (OpMode != MD_INITALIAS) 53319784Seric { 53419784Seric /* wait for other rebuild to complete */ 53551835Seric # ifdef LOCKF 53651937Seric (void) fcntl(fileno(af), F_SETLKW, &fld); 53751835Seric # else 53819784Seric (void) flock(fileno(af), LOCK_EX); 53951835Seric # endif 54019784Seric } 54123108Seric (void) fclose(af); 54219784Seric errno = 0; 54319784Seric return; 54419784Seric } 54556845Seric # endif /* NDBM */ 54619784Seric 5474314Seric /* 54819784Seric ** If initializing, create the new DBM files. 54919784Seric */ 55019784Seric 55119784Seric if (init) 55219784Seric { 55319784Seric oldsigint = signal(SIGINT, SIG_IGN); 55451756Seric # ifdef NEWDB 55551756Seric (void) strcpy(line, aliasfile); 55651756Seric (void) strcat(line, ".db"); 55751756Seric dbp = dbopen(line, 55851756Seric O_RDWR|O_CREAT|O_TRUNC, DBMMODE, DB_HASH, NULL); 55951756Seric if (dbp == NULL) 56051756Seric { 56151756Seric syserr("readaliases: cannot create %s", line); 56251756Seric (void) signal(SIGINT, oldsigint); 56351756Seric return; 56451756Seric } 56553742Seric # endif 56653742Seric # ifdef IF_MAKEDBMFILES 56753742Seric # ifdef NEWDB 56853742Seric makedbmfiles = access("/var/yp/Makefile", R_OK) == 0; 56953742Seric # endif 57053742Seric IF_MAKEDBMFILES 57119784Seric { 57256845Seric dbmp = dbm_open(aliasfile, 57356845Seric O_RDWR|O_CREAT|O_TRUNC, DBMMODE); 57456845Seric if (dbmp == NULL) 57553742Seric { 57656845Seric syserr("readaliases: cannot create %s.{dir,pag}", 57756845Seric aliasfile); 57853742Seric (void) signal(SIGINT, oldsigint); 57953742Seric return; 58053742Seric } 58119784Seric } 58250575Seric # endif 58319784Seric } 58419784Seric 58519784Seric /* 5864314Seric ** Read and interpret lines 5874314Seric */ 5884314Seric 5899368Seric FileName = aliasfile; 5909368Seric LineNumber = 0; 5914322Seric naliases = bytes = longest = 0; 5924098Seric skipping = FALSE; 5934098Seric while (fgets(line, sizeof (line), af) != NULL) 5944098Seric { 5954322Seric int lhssize, rhssize; 5964322Seric 5979368Seric LineNumber++; 59856795Seric p = strchr(line, '\n'); 59925278Seric if (p != NULL) 60025278Seric *p = '\0'; 6014098Seric switch (line[0]) 6024098Seric { 6034098Seric case '#': 6044098Seric case '\0': 6054098Seric skipping = FALSE; 6064098Seric continue; 6074065Seric 6084098Seric case ' ': 6094098Seric case '\t': 6104098Seric if (!skipping) 61158151Seric syserr("554 Non-continuation line starts with space"); 6124098Seric skipping = TRUE; 6134097Seric continue; 6144098Seric } 6154098Seric skipping = FALSE; 6161874Seric 6174314Seric /* 6184314Seric ** Process the LHS 61957736Seric ** Find the colon separator, and parse the address. 62016898Seric ** It should resolve to a local name -- this will 62116898Seric ** be checked later (we want to optionally do 62216898Seric ** parsing of the RHS first to maximize error 62316898Seric ** detection). 6244314Seric */ 6254314Seric 6264098Seric for (p = line; *p != '\0' && *p != ':' && *p != '\n'; p++) 6274097Seric continue; 62816898Seric if (*p++ != ':') 6294098Seric { 63058151Seric syserr("554 missing colon"); 6314097Seric continue; 6324098Seric } 63355012Seric if (parseaddr(line, &al, 1, ':', e) == NULL) 6344098Seric { 63558151Seric syserr("554 illegal alias name"); 63616898Seric continue; 6374098Seric } 63816898Seric loweraddr(&al); 6394314Seric 6404314Seric /* 6414314Seric ** Process the RHS. 6424314Seric ** 'al' is the internal form of the LHS address. 6434314Seric ** 'p' points to the text of the RHS. 6444314Seric */ 6454314Seric 6464098Seric rhs = p; 6474098Seric for (;;) 6484098Seric { 6494098Seric register char c; 6501515Seric 65125821Seric if (init && CheckAliases) 6524098Seric { 6534157Seric /* do parsing & compression of addresses */ 65425278Seric while (*p != '\0') 6554098Seric { 65625278Seric extern char *DelimChar; 65725278Seric 65858050Seric while ((isascii(*p) && isspace(*p)) || 65958050Seric *p == ',') 6604157Seric p++; 66125278Seric if (*p == '\0') 66225278Seric break; 66355012Seric if (parseaddr(p, &bl, -1, ',', e) == NULL) 66458151Seric usrerr("553 %s... bad address", p); 66525278Seric p = DelimChar; 6664098Seric } 6674098Seric } 6684157Seric else 66915769Seric { 67016898Seric p = &p[strlen(p)]; 67116898Seric if (p[-1] == '\n') 67216898Seric *--p = '\0'; 67315769Seric } 6741515Seric 6754098Seric /* see if there should be a continuation line */ 6764106Seric c = fgetc(af); 6774106Seric if (!feof(af)) 6784314Seric (void) ungetc(c, af); 6794106Seric if (c != ' ' && c != '\t') 6804098Seric break; 6814098Seric 6824098Seric /* read continuation line */ 6834098Seric if (fgets(p, sizeof line - (p - line), af) == NULL) 6844098Seric break; 6859368Seric LineNumber++; 68657135Seric 68757135Seric /* check for line overflow */ 68857135Seric if (strchr(p, '\n') == NULL) 68957135Seric { 69058151Seric usrerr("554 alias too long"); 69157135Seric break; 69257135Seric } 6934098Seric } 69416898Seric if (al.q_mailer != LocalMailer) 69516898Seric { 69658151Seric syserr("554 cannot alias non-local names"); 69716898Seric continue; 69816898Seric } 6994314Seric 7004314Seric /* 7014314Seric ** Insert alias into symbol table or DBM file 7024314Seric */ 7034314Seric 70416898Seric lhssize = strlen(al.q_user) + 1; 70557381Seric if (!bitnset(M_USR_UPPER, al.q_mailer->m_flags)) 70657381Seric makelower(al.q_user); 7074322Seric rhssize = strlen(rhs) + 1; 7084322Seric 70956845Seric # if defined(NDBM) || defined(NEWDB) 7104157Seric if (init) 7114157Seric { 71256845Seric DBdatum key, content; 71357381Seric int putstat; 7144157Seric 71556845Seric key.xx.size = lhssize; 71656845Seric key.xx.data = al.q_user; 71756845Seric content.xx.size = rhssize; 71856845Seric content.xx.data = rhs; 71951756Seric # ifdef NEWDB 72057381Seric putstat = dbp->put(dbp, &key.dbt, &content.dbt, 72157381Seric R_NOOVERWRITE); 72257381Seric if (putstat > 0) 72357381Seric { 72457977Seric usrerr("050 Warning: duplicate alias name %s", 72557381Seric al.q_user); 72657381Seric putstat = dbp->put(dbp, &key.dbt, 72757381Seric &content.dbt, 0); 72857381Seric } 72957381Seric if (putstat != 0) 73050576Seric syserr("readaliases: db put (%s)", al.q_user); 73150575Seric # endif 73253742Seric # ifdef IF_MAKEDBMFILES 73353742Seric IF_MAKEDBMFILES 73457381Seric { 73557381Seric putstat = dbm_store(dbmp, key.dbm, content.dbm, 73657381Seric DBM_INSERT); 73757381Seric if (putstat > 0) 73857381Seric { 73957977Seric usrerr("050 Warning: duplicate alias name %s", 74057381Seric al.q_user); 74157381Seric putstat = dbm_store(dbmp, key.dbm, 74257381Seric content.dbm, DBM_REPLACE); 74357381Seric } 74457381Seric if (putstat != 0) 74556845Seric syserr("readaliases: dbm store (%s)", 74656845Seric al.q_user); 74757381Seric } 74853742Seric # endif 74957381Seric if (al.q_paddr != NULL) 75057381Seric free(al.q_paddr); 75157381Seric if (al.q_host != NULL) 75257381Seric free(al.q_host); 75357381Seric if (al.q_user != NULL) 75457381Seric free(al.q_user); 7554157Seric } 7564157Seric else 75756845Seric # endif /* NDBM */ 7584157Seric { 7594157Seric s = stab(al.q_user, ST_ALIAS, ST_ENTER); 7604157Seric s->s_alias = newstr(rhs); 7614157Seric } 7624322Seric 7634322Seric /* statistics */ 7644322Seric naliases++; 7654322Seric bytes += lhssize + rhssize; 7664322Seric if (rhssize > longest) 7674322Seric longest = rhssize; 7681515Seric } 76919784Seric 77056845Seric # if defined(NDBM) || defined(NEWDB) 77119784Seric if (init) 77219784Seric { 77319784Seric /* add the distinquished alias "@" */ 77456845Seric DBdatum key; 77519784Seric 77656845Seric key.xx.size = 2; 77756845Seric key.xx.data = "@"; 77850575Seric # ifdef NEWDB 77950576Seric if (dbp->sync(dbp) != 0 || 78056845Seric dbp->put(dbp, &key.dbt, &key.dbt, 0) != 0 || 78150576Seric dbp->close(dbp) != 0) 78250576Seric syserr("readaliases: db close failure"); 78353742Seric # endif 78456789Seric # ifdef IF_MAKEDBMFILES 78556793Seric IF_MAKEDBMFILES 78656845Seric { 78758059Seric #ifdef YPCOMPAT 78858059Seric nis_magic(dbmp); 78958059Seric #endif 79056845Seric if (dbm_store(dbmp, key.dbm, key.dbm, DBM_REPLACE) != 0 || 79156845Seric dbm_error(dbmp)) 79256845Seric syserr("readaliases: dbm close failure"); 79356845Seric dbm_close(dbmp); 79456845Seric } 79550575Seric # endif 79619784Seric 79719784Seric /* restore the old signal */ 79819784Seric (void) signal(SIGINT, oldsigint); 79919784Seric } 80056845Seric # endif /* NDBM */ 80119784Seric 80219784Seric /* closing the alias file drops the lock */ 8034098Seric (void) fclose(af); 80455012Seric e->e_to = NULL; 8059368Seric FileName = NULL; 80658151Seric message("%d aliases, longest %d bytes, %d bytes total", 8074322Seric naliases, longest, bytes); 80824944Seric # ifdef LOG 80958020Seric if (LogLevel > 7) 81024944Seric syslog(LOG_INFO, "%d aliases, longest %d bytes, %d bytes total", 81124944Seric naliases, longest, bytes); 81256795Seric # endif /* LOG */ 813292Seric } 814292Seric /* 81558059Seric ** NIS_MAGIC -- Add NIS magic dbm data 81658059Seric ** 81758059Seric ** This adds the magic entries needed by SunOS to make this a valid 81858059Seric ** NIS map. 81958059Seric ** 82058059Seric ** Parameters: 82158059Seric ** dbmp -- a pointer to the DBM structure. 82258059Seric ** 82358059Seric ** Returns: 82458059Seric ** none. 82558059Seric */ 82658059Seric 82758059Seric # ifdef YPCOMPAT 82858059Seric 82958059Seric static void 83058059Seric nis_magic(dbmp) 83158059Seric DBM *dbmp; 83258059Seric { 83358059Seric int i; 83458059Seric static datum key[2] = 83558059Seric { 83658059Seric { "YP_LAST_MODIFIED", sizeof "YP_LAST_MODIFIED" - 1 }, 83758059Seric { "YP_MASTER_NAME", sizeof "YP_MASTER_NAME" - 1 }, 83858059Seric }; 83958059Seric datum contents[2]; 84058059Seric char tbuf[12]; 84158059Seric char hbuf[MAXHOSTNAMELEN]; 84258059Seric 84358059Seric (void) sprintf(tbuf, "%010ld", curtime()); 84458059Seric contents[0].dptr = tbuf; 84558059Seric contents[0].dsize = strlen(tbuf); 84658059Seric 84758059Seric (void) myhostname(hbuf, sizeof hbuf); 84858059Seric contents[1].dptr = hbuf; 84958059Seric contents[1].dptr = strlen(hbuf); 85058059Seric 85158059Seric for (i = 0; i < sizeof key / sizeof *key; i++) 85258059Seric { 85358059Seric if (dbm_store(dbmp, key[i], contents[i], DBM_REPLACE) != 0 || 85458059Seric dbm_error(dbmp)) 85558059Seric syserr("nis_magic: dbm_store failure"); 85658059Seric } 85758059Seric } 85858059Seric 85958059Seric # endif 86058059Seric /* 861292Seric ** FORWARD -- Try to forward mail 862292Seric ** 863292Seric ** This is similar but not identical to aliasing. 864292Seric ** 865292Seric ** Parameters: 8664314Seric ** user -- the name of the user who's mail we would like 8674314Seric ** to forward to. It must have been verified -- 8684314Seric ** i.e., the q_home field must have been filled 8694314Seric ** in. 8704999Seric ** sendq -- a pointer to the head of the send queue to 8714999Seric ** put this user's aliases in. 872292Seric ** 873292Seric ** Returns: 8744098Seric ** none. 875292Seric ** 876292Seric ** Side Effects: 8773185Seric ** New names are added to send queues. 878292Seric */ 879292Seric 88055012Seric forward(user, sendq, e) 8812966Seric ADDRESS *user; 8824999Seric ADDRESS **sendq; 88355012Seric register ENVELOPE *e; 884292Seric { 88557136Seric char *pp; 88657136Seric char *ep; 8874536Seric extern bool safefile(); 8884069Seric 8897671Seric if (tTd(27, 1)) 8904098Seric printf("forward(%s)\n", user->q_paddr); 8914098Seric 8924594Seric if (user->q_mailer != LocalMailer || bitset(QBADADDR, user->q_flags)) 8934098Seric return; 8944314Seric if (user->q_home == NULL) 89558059Seric { 89658151Seric syserr("554 forward: no home"); 89758059Seric user->q_home = "/nosuchdirectory"; 89858059Seric } 8994069Seric 9004069Seric /* good address -- look for .forward file in home */ 90155012Seric define('z', user->q_home, e); 90257136Seric define('u', user->q_user, e); 90357136Seric define('h', user->q_host, e); 90457136Seric if (ForwardPath == NULL) 90558050Seric ForwardPath = newstr("\201z/.forward"); 90657136Seric 90757136Seric for (pp = ForwardPath; pp != NULL; pp = ep) 90857136Seric { 90957232Seric char buf[MAXPATHLEN+1]; 91057136Seric 91157136Seric ep = strchr(pp, ':'); 91257136Seric if (ep != NULL) 91357136Seric *ep = '\0'; 91457136Seric expand(pp, buf, &buf[sizeof buf - 1], e); 91557136Seric if (ep != NULL) 91657136Seric *ep++ = ':'; 91757136Seric if (tTd(27, 3)) 91857136Seric printf("forward: trying %s\n", buf); 91957136Seric if (include(buf, TRUE, user, sendq, e) == 0) 92057136Seric break; 92157136Seric } 922292Seric } 923