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*58154Seric static char sccsid[] = "@(#)alias.c 6.17 (Berkeley) 02/23/93 (with NEWDB and NDBM)"; 3351756Seric #else 34*58154Seric static char sccsid[] = "@(#)alias.c 6.17 (Berkeley) 02/23/93 (with NEWDB)"; 3557736Seric #endif 3657736Seric #else 3756845Seric #ifdef NDBM 38*58154Seric static char sccsid[] = "@(#)alias.c 6.17 (Berkeley) 02/23/93 (with NDBM)"; 3933728Sbostic #else 40*58154Seric static char sccsid[] = "@(#)alias.c 6.17 (Berkeley) 02/23/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; 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 */ 123*58154Seric if (bitset(QDONTSEND|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)) 148*58154Seric { 149*58154Seric a->q_flags |= QVERIFIED; 15058092Seric return; 151*58154Seric } 152*58154Seric 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 } 1704098Seric } 1714098Seric /* 1725701Seric ** ALIASLOOKUP -- look up a name in the alias file. 1735701Seric ** 1745701Seric ** Parameters: 1755701Seric ** name -- the name to look up. 1765701Seric ** 1775701Seric ** Returns: 1785701Seric ** the value of name. 1795701Seric ** NULL if unknown. 1805701Seric ** 1815701Seric ** Side Effects: 1825701Seric ** none. 1835701Seric ** 1845701Seric ** Warnings: 1855701Seric ** The return value will be trashed across calls. 1865701Seric */ 1875701Seric 1885701Seric char * 1895701Seric aliaslookup(name) 1905701Seric char *name; 1915701Seric { 19257381Seric int i; 19357381Seric char keybuf[MAXNAME + 1]; 19456845Seric # if defined(NEWDB) || defined(NDBM) 19556845Seric DBdatum rhs, lhs; 19650575Seric int s; 19757381Seric # else /* neither NEWDB nor NDBM */ 19857381Seric register STAB *s; 19957381Seric # endif 2005701Seric 2015701Seric /* create a key for fetch */ 20257381Seric i = strlen(name) + 1; 20357381Seric if (i > sizeof keybuf) 20457381Seric i = sizeof keybuf; 20557381Seric bcopy(name, keybuf, i); 20657381Seric if (!bitnset(M_USR_UPPER, LocalMailer->m_flags)) 20757381Seric makelower(keybuf); 20857381Seric 20957381Seric # if defined(NEWDB) || defined(NDBM) 21057381Seric lhs.xx.size = i; 21157381Seric lhs.xx.data = keybuf; 21250575Seric # ifdef NEWDB 21351756Seric if (AliasDBptr != NULL) 21451756Seric { 21557381Seric i = AliasDBptr->get(AliasDBptr, &lhs.dbt, &rhs.dbt, 0); 21657381Seric if (i == 0) 21756845Seric return (rhs.dbt.data); 21851756Seric } 21956845Seric # ifdef NDBM 22057249Seric else if (AliasDBMptr != NULL) 22151756Seric { 22256845Seric rhs.dbm = dbm_fetch(AliasDBMptr, lhs.dbm); 22356845Seric return (rhs.dbm.dptr); 22451756Seric } 22556845Seric # endif /* NDBM */ 22657530Seric return (NULL); 22756845Seric # else /* not NEWDB */ 22856845Seric rhs.dbm = dbm_fetch(AliasDBMptr, lhs.dbm); 22956845Seric return (rhs.dbm.dptr); 23056845Seric # endif /* NEWDB */ 23156845Seric # else /* neither NEWDB nor NDBM */ 23257381Seric s = stab(keybuf, ST_ALIAS, ST_FIND); 23351756Seric if (s != NULL) 23451756Seric return (s->s_alias); 23557530Seric return (NULL); 23651756Seric # endif 2375701Seric } 2385701Seric /* 2394098Seric ** INITALIASES -- initialize for aliasing 2404098Seric ** 24156845Seric ** Very different depending on whether we are running NDBM or not. 2424098Seric ** 2434098Seric ** Parameters: 2444098Seric ** aliasfile -- location of aliases. 24556845Seric ** init -- if set and if NDBM, initialize the NDBM files. 2464098Seric ** 2474098Seric ** Returns: 2484098Seric ** none. 2494098Seric ** 2504098Seric ** Side Effects: 2514098Seric ** initializes aliases: 25256845Seric ** if NDBM: opens the database. 25356845Seric ** if ~NDBM: reads the aliases into the symbol table. 2544098Seric */ 2554098Seric 25640559Sbostic # define DBMMODE 0644 2574157Seric 25855012Seric initaliases(aliasfile, init, e) 2594098Seric char *aliasfile; 2604157Seric bool init; 26155012Seric register ENVELOPE *e; 2624098Seric { 26356845Seric #if defined(NDBM) || defined(NEWDB) 2648437Seric int atcnt; 26525522Seric time_t modtime; 26625522Seric bool automatic = FALSE; 2674322Seric char buf[MAXNAME]; 26850575Seric #endif 2699368Seric struct stat stb; 27027176Seric static bool initialized = FALSE; 27146928Sbostic static int readaliases(); 2724322Seric 27327176Seric if (initialized) 27427176Seric return; 27527176Seric initialized = TRUE; 27627176Seric 27717984Seric if (aliasfile == NULL || stat(aliasfile, &stb) < 0) 2788437Seric { 27925522Seric if (aliasfile != NULL && init) 28058151Seric syserr("554 Cannot open %s", aliasfile); 2818437Seric NoAlias = TRUE; 28211937Seric errno = 0; 2838437Seric return; 2848437Seric } 2858437Seric 28656845Seric # if defined(NDBM) || defined(NEWDB) 2874322Seric /* 2888437Seric ** Check to see that the alias file is complete. 2898437Seric ** If not, we will assume that someone died, and it is up 2908437Seric ** to us to rebuild it. 2918437Seric */ 2928437Seric 29325689Seric if (!init) 29450575Seric { 29550575Seric # ifdef NEWDB 29650575Seric (void) strcpy(buf, aliasfile); 29750575Seric (void) strcat(buf, ".db"); 29851171Sbostic AliasDBptr = dbopen(buf, O_RDONLY, DBMMODE, DB_HASH, NULL); 29950576Seric if (AliasDBptr == NULL) 30050576Seric { 30156845Seric # ifdef NDBM 30256845Seric AliasDBMptr = dbm_open(aliasfile, O_RDONLY, DBMMODE); 30357249Seric if (AliasDBMptr == NULL) 30457249Seric { 30557249Seric syserr("initaliases: cannot open %s", buf); 30657249Seric NoAlias = TRUE; 30757249Seric return; 30857249Seric } 30951756Seric # else 31050576Seric syserr("initaliases: cannot open %s", buf); 31150576Seric NoAlias = TRUE; 31250576Seric return; 31351756Seric # endif 31450576Seric } 31550575Seric # else 31656845Seric AliasDBMptr = dbm_open(aliasfile, O_RDONLY, DBMMODE); 31757249Seric if (AliasDBMptr == NULL) 31857249Seric { 31957977Seric syserr("initaliases: cannot open DBM database %s.{pag,dir}", 32057977Seric aliasfile); 32157249Seric NoAlias = TRUE; 32257249Seric return; 32357249Seric } 32450575Seric # endif 32550575Seric } 32617471Seric atcnt = SafeAlias * 2; 32717471Seric if (atcnt > 0) 32817471Seric { 32917471Seric while (!init && atcnt-- >= 0 && aliaslookup("@") == NULL) 33025689Seric { 33125689Seric /* 33225689Seric ** Reinitialize alias file in case the new 33325689Seric ** one is mv'ed in instead of cp'ed in. 33425689Seric ** 33525689Seric ** Only works with new DBM -- old one will 33625689Seric ** just consume file descriptors forever. 33725689Seric ** If you have a dbmclose() it can be 33825689Seric ** added before the sleep(30). 33925689Seric */ 34025689Seric 34150575Seric # ifdef NEWDB 34251756Seric if (AliasDBptr != NULL) 34351756Seric AliasDBptr->close(AliasDBptr); 34450575Seric # endif 34556845Seric # ifdef NDBM 34656845Seric if (AliasDBMptr != NULL) 34756845Seric dbm_close(AliasDBMptr); 34856845Seric # endif 34950575Seric 35017471Seric sleep(30); 35150575Seric # ifdef NEWDB 35250575Seric (void) strcpy(buf, aliasfile); 35350575Seric (void) strcat(buf, ".db"); 35451171Sbostic AliasDBptr = 35551171Sbostic dbopen(buf, O_RDONLY, DBMMODE, DB_HASH, NULL); 35650576Seric if (AliasDBptr == NULL) 35750576Seric { 35851756Seric # ifdef NDBM 35956845Seric AliasDBMptr = dbm_open(aliasfile, O_RDONLY, DBMMODE); 36051756Seric # else 36150576Seric syserr("initaliases: cannot open %s", buf); 36250576Seric NoAlias = TRUE; 36350576Seric return; 36451756Seric # endif 36550576Seric } 36650575Seric # else 36725689Seric # ifdef NDBM 36856845Seric AliasDBMptr = dbm_open(aliasfile, O_RDONLY, DBMMODE); 36957249Seric if (AliasDBMptr == NULL) 37057249Seric { 37158008Seric syserr("initaliases: cannot open DBM database %s.{pag,dir}", 37258008Seric aliasfile); 37357249Seric NoAlias = TRUE; 37457249Seric return; 37557249Seric } 37650575Seric # endif 37750575Seric # endif 37825689Seric } 37917471Seric } 38017471Seric else 38117471Seric atcnt = 1; 3828437Seric 3838437Seric /* 38456845Seric ** See if the NDBM version of the file is out of date with 3854322Seric ** the text version. If so, go into 'init' mode automatically. 38640559Sbostic ** This only happens if our effective userid owns the DBM. 38740559Sbostic ** Note the unpalatable hack to see if the stat succeeded. 3884322Seric */ 3894322Seric 3904322Seric modtime = stb.st_mtime; 3914322Seric (void) strcpy(buf, aliasfile); 39250575Seric # ifdef NEWDB 39350575Seric (void) strcat(buf, ".db"); 39450575Seric # else 3954322Seric (void) strcat(buf, ".pag"); 39650575Seric # endif 3974322Seric stb.st_ino = 0; 39819039Seric if (!init && (stat(buf, &stb) < 0 || stb.st_mtime < modtime || atcnt < 0)) 3994322Seric { 40011937Seric errno = 0; 40140559Sbostic if (AutoRebuild && stb.st_ino != 0 && stb.st_uid == geteuid()) 4024322Seric { 4034322Seric init = TRUE; 40425522Seric automatic = TRUE; 40558151Seric message("rebuilding alias database"); 40624944Seric #ifdef LOG 40758020Seric if (LogLevel > 14) 40824944Seric syslog(LOG_INFO, "rebuilding alias database"); 40956795Seric #endif /* LOG */ 4104322Seric } 4114322Seric else 4124322Seric { 41319039Seric #ifdef LOG 41458020Seric if (LogLevel > 3) 41524944Seric syslog(LOG_INFO, "alias database out of date"); 41656795Seric #endif /* LOG */ 41758151Seric message("Warning: alias database out of date"); 4184322Seric } 4194322Seric } 4204322Seric 4214322Seric 4224322Seric /* 42356845Seric ** If necessary, load the NDBM file. 42456845Seric ** If running without NDBM, load the symbol table. 4254322Seric */ 4264322Seric 4274157Seric if (init) 4288437Seric { 42925522Seric #ifdef LOG 43058020Seric if (LogLevel > 7) 43125522Seric { 43225522Seric extern char *username(); 43325522Seric 43425522Seric syslog(LOG_NOTICE, "alias database %srebuilt by %s", 43525522Seric automatic ? "auto" : "", username()); 43625522Seric } 43756795Seric #endif /* LOG */ 43855012Seric readaliases(aliasfile, TRUE, e); 4398437Seric } 44056845Seric # else /* NDBM */ 44155012Seric readaliases(aliasfile, init, e); 44256845Seric # endif /* NDBM */ 4434157Seric } 4444157Seric /* 4454157Seric ** READALIASES -- read and process the alias file. 4464157Seric ** 4474157Seric ** This routine implements the part of initaliases that occurs 4484157Seric ** when we are not going to use the DBM stuff. 4494157Seric ** 4504157Seric ** Parameters: 4514157Seric ** aliasfile -- the pathname of the alias file master. 45256845Seric ** init -- if set, initialize the NDBM stuff. 4534157Seric ** 4544157Seric ** Returns: 4554157Seric ** none. 4564157Seric ** 4574157Seric ** Side Effects: 4584157Seric ** Reads aliasfile into the symbol table. 4594157Seric ** Optionally, builds the .dir & .pag files. 4604157Seric */ 4614157Seric 4624157Seric static 46355012Seric readaliases(aliasfile, init, e) 4644157Seric char *aliasfile; 4654157Seric bool init; 46655012Seric register ENVELOPE *e; 4674157Seric { 4684098Seric register char *p; 4694098Seric char *rhs; 4704098Seric bool skipping; 4719368Seric int naliases, bytes, longest; 4729368Seric FILE *af; 47353742Seric bool makedbmfiles; 47440970Sbostic void (*oldsigint)(); 4754098Seric ADDRESS al, bl; 4764106Seric register STAB *s; 47750575Seric # ifdef NEWDB 47850575Seric DB *dbp; 47950575Seric # endif 48056845Seric # ifdef NDBM 48156845Seric DBM *dbmp; 48256845Seric # endif 48351937Seric # ifdef LOCKF 48451937Seric struct flock fld; 48551937Seric # endif 4869368Seric char line[BUFSIZ]; 4874098Seric 48851937Seric if ((af = fopen(aliasfile, "r+")) == NULL) 4891515Seric { 49057249Seric if (init) 49158151Seric syserr("554 Can't open %s", aliasfile); 49257249Seric else if (tTd(27, 1)) 4934106Seric printf("Can't open %s\n", aliasfile); 4944098Seric errno = 0; 4954098Seric NoAlias++; 4964098Seric return; 4974098Seric } 4984314Seric 49956845Seric # if defined(NDBM) || defined(NEWDB) 50019784Seric /* see if someone else is rebuilding the alias file already */ 50151835Seric # ifdef LOCKF 50251937Seric fld.l_type = F_WRLCK; 50351937Seric fld.l_whence = fld.l_start = fld.l_len = 0; 50451937Seric if (fcntl(fileno(af), F_SETLK, &fld) < 0) 50551835Seric # else 50619784Seric if (flock(fileno(af), LOCK_EX | LOCK_NB) < 0 && errno == EWOULDBLOCK) 50751835Seric # endif 50819784Seric { 50919784Seric /* yes, they are -- wait until done and then return */ 51058151Seric message("Alias file is already being rebuilt"); 51119784Seric if (OpMode != MD_INITALIAS) 51219784Seric { 51319784Seric /* wait for other rebuild to complete */ 51451835Seric # ifdef LOCKF 51551937Seric (void) fcntl(fileno(af), F_SETLKW, &fld); 51651835Seric # else 51719784Seric (void) flock(fileno(af), LOCK_EX); 51851835Seric # endif 51919784Seric } 52023108Seric (void) fclose(af); 52119784Seric errno = 0; 52219784Seric return; 52319784Seric } 52456845Seric # endif /* NDBM */ 52519784Seric 5264314Seric /* 52719784Seric ** If initializing, create the new DBM files. 52819784Seric */ 52919784Seric 53019784Seric if (init) 53119784Seric { 53219784Seric oldsigint = signal(SIGINT, SIG_IGN); 53351756Seric # ifdef NEWDB 53451756Seric (void) strcpy(line, aliasfile); 53551756Seric (void) strcat(line, ".db"); 53651756Seric dbp = dbopen(line, 53751756Seric O_RDWR|O_CREAT|O_TRUNC, DBMMODE, DB_HASH, NULL); 53851756Seric if (dbp == NULL) 53951756Seric { 54051756Seric syserr("readaliases: cannot create %s", line); 54151756Seric (void) signal(SIGINT, oldsigint); 54251756Seric return; 54351756Seric } 54453742Seric # endif 54553742Seric # ifdef IF_MAKEDBMFILES 54653742Seric # ifdef NEWDB 54753742Seric makedbmfiles = access("/var/yp/Makefile", R_OK) == 0; 54853742Seric # endif 54953742Seric IF_MAKEDBMFILES 55019784Seric { 55156845Seric dbmp = dbm_open(aliasfile, 55256845Seric O_RDWR|O_CREAT|O_TRUNC, DBMMODE); 55356845Seric if (dbmp == NULL) 55453742Seric { 55556845Seric syserr("readaliases: cannot create %s.{dir,pag}", 55656845Seric aliasfile); 55753742Seric (void) signal(SIGINT, oldsigint); 55853742Seric return; 55953742Seric } 56019784Seric } 56150575Seric # endif 56219784Seric } 56319784Seric 56419784Seric /* 5654314Seric ** Read and interpret lines 5664314Seric */ 5674314Seric 5689368Seric FileName = aliasfile; 5699368Seric LineNumber = 0; 5704322Seric naliases = bytes = longest = 0; 5714098Seric skipping = FALSE; 5724098Seric while (fgets(line, sizeof (line), af) != NULL) 5734098Seric { 5744322Seric int lhssize, rhssize; 5754322Seric 5769368Seric LineNumber++; 57756795Seric p = strchr(line, '\n'); 57825278Seric if (p != NULL) 57925278Seric *p = '\0'; 5804098Seric switch (line[0]) 5814098Seric { 5824098Seric case '#': 5834098Seric case '\0': 5844098Seric skipping = FALSE; 5854098Seric continue; 5864065Seric 5874098Seric case ' ': 5884098Seric case '\t': 5894098Seric if (!skipping) 59058151Seric syserr("554 Non-continuation line starts with space"); 5914098Seric skipping = TRUE; 5924097Seric continue; 5934098Seric } 5944098Seric skipping = FALSE; 5951874Seric 5964314Seric /* 5974314Seric ** Process the LHS 59857736Seric ** Find the colon separator, and parse the address. 59916898Seric ** It should resolve to a local name -- this will 60016898Seric ** be checked later (we want to optionally do 60116898Seric ** parsing of the RHS first to maximize error 60216898Seric ** detection). 6034314Seric */ 6044314Seric 6054098Seric for (p = line; *p != '\0' && *p != ':' && *p != '\n'; p++) 6064097Seric continue; 60716898Seric if (*p++ != ':') 6084098Seric { 60958151Seric syserr("554 missing colon"); 6104097Seric continue; 6114098Seric } 61255012Seric if (parseaddr(line, &al, 1, ':', e) == NULL) 6134098Seric { 61458151Seric syserr("554 illegal alias name"); 61516898Seric continue; 6164098Seric } 61716898Seric loweraddr(&al); 6184314Seric 6194314Seric /* 6204314Seric ** Process the RHS. 6214314Seric ** 'al' is the internal form of the LHS address. 6224314Seric ** 'p' points to the text of the RHS. 6234314Seric */ 6244314Seric 6254098Seric rhs = p; 6264098Seric for (;;) 6274098Seric { 6284098Seric register char c; 6291515Seric 63025821Seric if (init && CheckAliases) 6314098Seric { 6324157Seric /* do parsing & compression of addresses */ 63325278Seric while (*p != '\0') 6344098Seric { 63525278Seric extern char *DelimChar; 63625278Seric 63758050Seric while ((isascii(*p) && isspace(*p)) || 63858050Seric *p == ',') 6394157Seric p++; 64025278Seric if (*p == '\0') 64125278Seric break; 64255012Seric if (parseaddr(p, &bl, -1, ',', e) == NULL) 64358151Seric usrerr("553 %s... bad address", p); 64425278Seric p = DelimChar; 6454098Seric } 6464098Seric } 6474157Seric else 64815769Seric { 64916898Seric p = &p[strlen(p)]; 65016898Seric if (p[-1] == '\n') 65116898Seric *--p = '\0'; 65215769Seric } 6531515Seric 6544098Seric /* see if there should be a continuation line */ 6554106Seric c = fgetc(af); 6564106Seric if (!feof(af)) 6574314Seric (void) ungetc(c, af); 6584106Seric if (c != ' ' && c != '\t') 6594098Seric break; 6604098Seric 6614098Seric /* read continuation line */ 6624098Seric if (fgets(p, sizeof line - (p - line), af) == NULL) 6634098Seric break; 6649368Seric LineNumber++; 66557135Seric 66657135Seric /* check for line overflow */ 66757135Seric if (strchr(p, '\n') == NULL) 66857135Seric { 66958151Seric usrerr("554 alias too long"); 67057135Seric break; 67157135Seric } 6724098Seric } 67316898Seric if (al.q_mailer != LocalMailer) 67416898Seric { 67558151Seric syserr("554 cannot alias non-local names"); 67616898Seric continue; 67716898Seric } 6784314Seric 6794314Seric /* 6804314Seric ** Insert alias into symbol table or DBM file 6814314Seric */ 6824314Seric 68316898Seric lhssize = strlen(al.q_user) + 1; 68457381Seric if (!bitnset(M_USR_UPPER, al.q_mailer->m_flags)) 68557381Seric makelower(al.q_user); 6864322Seric rhssize = strlen(rhs) + 1; 6874322Seric 68856845Seric # if defined(NDBM) || defined(NEWDB) 6894157Seric if (init) 6904157Seric { 69156845Seric DBdatum key, content; 69257381Seric int putstat; 6934157Seric 69456845Seric key.xx.size = lhssize; 69556845Seric key.xx.data = al.q_user; 69656845Seric content.xx.size = rhssize; 69756845Seric content.xx.data = rhs; 69851756Seric # ifdef NEWDB 69957381Seric putstat = dbp->put(dbp, &key.dbt, &content.dbt, 70057381Seric R_NOOVERWRITE); 70157381Seric if (putstat > 0) 70257381Seric { 70357977Seric usrerr("050 Warning: duplicate alias name %s", 70457381Seric al.q_user); 70557381Seric putstat = dbp->put(dbp, &key.dbt, 70657381Seric &content.dbt, 0); 70757381Seric } 70857381Seric if (putstat != 0) 70950576Seric syserr("readaliases: db put (%s)", al.q_user); 71050575Seric # endif 71153742Seric # ifdef IF_MAKEDBMFILES 71253742Seric IF_MAKEDBMFILES 71357381Seric { 71457381Seric putstat = dbm_store(dbmp, key.dbm, content.dbm, 71557381Seric DBM_INSERT); 71657381Seric if (putstat > 0) 71757381Seric { 71857977Seric usrerr("050 Warning: duplicate alias name %s", 71957381Seric al.q_user); 72057381Seric putstat = dbm_store(dbmp, key.dbm, 72157381Seric content.dbm, DBM_REPLACE); 72257381Seric } 72357381Seric if (putstat != 0) 72456845Seric syserr("readaliases: dbm store (%s)", 72556845Seric al.q_user); 72657381Seric } 72753742Seric # endif 72857381Seric if (al.q_paddr != NULL) 72957381Seric free(al.q_paddr); 73057381Seric if (al.q_host != NULL) 73157381Seric free(al.q_host); 73257381Seric if (al.q_user != NULL) 73357381Seric free(al.q_user); 7344157Seric } 7354157Seric else 73656845Seric # endif /* NDBM */ 7374157Seric { 7384157Seric s = stab(al.q_user, ST_ALIAS, ST_ENTER); 7394157Seric s->s_alias = newstr(rhs); 7404157Seric } 7414322Seric 7424322Seric /* statistics */ 7434322Seric naliases++; 7444322Seric bytes += lhssize + rhssize; 7454322Seric if (rhssize > longest) 7464322Seric longest = rhssize; 7471515Seric } 74819784Seric 74956845Seric # if defined(NDBM) || defined(NEWDB) 75019784Seric if (init) 75119784Seric { 75219784Seric /* add the distinquished alias "@" */ 75356845Seric DBdatum key; 75419784Seric 75556845Seric key.xx.size = 2; 75656845Seric key.xx.data = "@"; 75750575Seric # ifdef NEWDB 75850576Seric if (dbp->sync(dbp) != 0 || 75956845Seric dbp->put(dbp, &key.dbt, &key.dbt, 0) != 0 || 76050576Seric dbp->close(dbp) != 0) 76150576Seric syserr("readaliases: db close failure"); 76253742Seric # endif 76356789Seric # ifdef IF_MAKEDBMFILES 76456793Seric IF_MAKEDBMFILES 76556845Seric { 76658059Seric #ifdef YPCOMPAT 76758059Seric nis_magic(dbmp); 76858059Seric #endif 76956845Seric if (dbm_store(dbmp, key.dbm, key.dbm, DBM_REPLACE) != 0 || 77056845Seric dbm_error(dbmp)) 77156845Seric syserr("readaliases: dbm close failure"); 77256845Seric dbm_close(dbmp); 77356845Seric } 77450575Seric # endif 77519784Seric 77619784Seric /* restore the old signal */ 77719784Seric (void) signal(SIGINT, oldsigint); 77819784Seric } 77956845Seric # endif /* NDBM */ 78019784Seric 78119784Seric /* closing the alias file drops the lock */ 7824098Seric (void) fclose(af); 78355012Seric e->e_to = NULL; 7849368Seric FileName = NULL; 78558151Seric message("%d aliases, longest %d bytes, %d bytes total", 7864322Seric naliases, longest, bytes); 78724944Seric # ifdef LOG 78858020Seric if (LogLevel > 7) 78924944Seric syslog(LOG_INFO, "%d aliases, longest %d bytes, %d bytes total", 79024944Seric naliases, longest, bytes); 79156795Seric # endif /* LOG */ 792292Seric } 793292Seric /* 79458059Seric ** NIS_MAGIC -- Add NIS magic dbm data 79558059Seric ** 79658059Seric ** This adds the magic entries needed by SunOS to make this a valid 79758059Seric ** NIS map. 79858059Seric ** 79958059Seric ** Parameters: 80058059Seric ** dbmp -- a pointer to the DBM structure. 80158059Seric ** 80258059Seric ** Returns: 80358059Seric ** none. 80458059Seric */ 80558059Seric 80658059Seric # ifdef YPCOMPAT 80758059Seric 80858059Seric static void 80958059Seric nis_magic(dbmp) 81058059Seric DBM *dbmp; 81158059Seric { 81258059Seric int i; 81358059Seric static datum key[2] = 81458059Seric { 81558059Seric { "YP_LAST_MODIFIED", sizeof "YP_LAST_MODIFIED" - 1 }, 81658059Seric { "YP_MASTER_NAME", sizeof "YP_MASTER_NAME" - 1 }, 81758059Seric }; 81858059Seric datum contents[2]; 81958059Seric char tbuf[12]; 82058059Seric char hbuf[MAXHOSTNAMELEN]; 82158059Seric 82258059Seric (void) sprintf(tbuf, "%010ld", curtime()); 82358059Seric contents[0].dptr = tbuf; 82458059Seric contents[0].dsize = strlen(tbuf); 82558059Seric 82658059Seric (void) myhostname(hbuf, sizeof hbuf); 82758059Seric contents[1].dptr = hbuf; 82858059Seric contents[1].dptr = strlen(hbuf); 82958059Seric 83058059Seric for (i = 0; i < sizeof key / sizeof *key; i++) 83158059Seric { 83258059Seric if (dbm_store(dbmp, key[i], contents[i], DBM_REPLACE) != 0 || 83358059Seric dbm_error(dbmp)) 83458059Seric syserr("nis_magic: dbm_store failure"); 83558059Seric } 83658059Seric } 83758059Seric 83858059Seric # endif 83958059Seric /* 840292Seric ** FORWARD -- Try to forward mail 841292Seric ** 842292Seric ** This is similar but not identical to aliasing. 843292Seric ** 844292Seric ** Parameters: 8454314Seric ** user -- the name of the user who's mail we would like 8464314Seric ** to forward to. It must have been verified -- 8474314Seric ** i.e., the q_home field must have been filled 8484314Seric ** in. 8494999Seric ** sendq -- a pointer to the head of the send queue to 8504999Seric ** put this user's aliases in. 851292Seric ** 852292Seric ** Returns: 8534098Seric ** none. 854292Seric ** 855292Seric ** Side Effects: 8563185Seric ** New names are added to send queues. 857292Seric */ 858292Seric 85955012Seric forward(user, sendq, e) 8602966Seric ADDRESS *user; 8614999Seric ADDRESS **sendq; 86255012Seric register ENVELOPE *e; 863292Seric { 86457136Seric char *pp; 86557136Seric char *ep; 8664536Seric extern bool safefile(); 8674069Seric 8687671Seric if (tTd(27, 1)) 8694098Seric printf("forward(%s)\n", user->q_paddr); 8704098Seric 8714594Seric if (user->q_mailer != LocalMailer || bitset(QBADADDR, user->q_flags)) 8724098Seric return; 8734314Seric if (user->q_home == NULL) 87458059Seric { 87558151Seric syserr("554 forward: no home"); 87658059Seric user->q_home = "/nosuchdirectory"; 87758059Seric } 8784069Seric 8794069Seric /* good address -- look for .forward file in home */ 88055012Seric define('z', user->q_home, e); 88157136Seric define('u', user->q_user, e); 88257136Seric define('h', user->q_host, e); 88357136Seric if (ForwardPath == NULL) 88458050Seric ForwardPath = newstr("\201z/.forward"); 88557136Seric 88657136Seric for (pp = ForwardPath; pp != NULL; pp = ep) 88757136Seric { 88857232Seric char buf[MAXPATHLEN+1]; 88957136Seric 89057136Seric ep = strchr(pp, ':'); 89157136Seric if (ep != NULL) 89257136Seric *ep = '\0'; 89357136Seric expand(pp, buf, &buf[sizeof buf - 1], e); 89457136Seric if (ep != NULL) 89557136Seric *ep++ = ':'; 89657136Seric if (tTd(27, 3)) 89757136Seric printf("forward: trying %s\n", buf); 89857136Seric if (include(buf, TRUE, user, sendq, e) == 0) 89957136Seric break; 90057136Seric } 901292Seric } 902