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*58151Seric static char sccsid[] = "@(#)alias.c 6.16 (Berkeley) 02/23/93 (with NEWDB and NDBM)"; 3351756Seric #else 34*58151Seric static char sccsid[] = "@(#)alias.c 6.16 (Berkeley) 02/23/93 (with NEWDB)"; 3557736Seric #endif 3657736Seric #else 3756845Seric #ifdef NDBM 38*58151Seric static char sccsid[] = "@(#)alias.c 6.16 (Berkeley) 02/23/93 (with NDBM)"; 3933728Sbostic #else 40*58151Seric static char sccsid[] = "@(#)alias.c 6.16 (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 */ 1234098Seric if (bitset(QDONTSEND, 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); 147*58151Seric message("aliased to %s", p); 14858092Seric if (bitset(EF_VRFYONLY, e->e_flags)) 14958092Seric return; 15057977Seric #ifdef LOG 15158020Seric if (LogLevel > 9) 15257977Seric syslog(LOG_INFO, "%s: alias %s => %s", e->e_id, a->q_paddr, p); 15357977Seric #endif 15458082Seric a->q_flags &= ~QSELFREF; 1554098Seric AliasLevel++; 15658082Seric naliases = sendtolist(p, a, sendq, e); 1574098Seric AliasLevel--; 15858082Seric if (naliases > 0 && !bitset(QSELFREF, a->q_flags)) 15958065Seric { 16058065Seric if (tTd(27, 5)) 16158065Seric { 16258065Seric printf("alias: QDONTSEND "); 16358065Seric printaddr(a, FALSE); 16458065Seric } 16558065Seric a->q_flags |= QDONTSEND; 16658065Seric } 1674098Seric } 1684098Seric /* 1695701Seric ** ALIASLOOKUP -- look up a name in the alias file. 1705701Seric ** 1715701Seric ** Parameters: 1725701Seric ** name -- the name to look up. 1735701Seric ** 1745701Seric ** Returns: 1755701Seric ** the value of name. 1765701Seric ** NULL if unknown. 1775701Seric ** 1785701Seric ** Side Effects: 1795701Seric ** none. 1805701Seric ** 1815701Seric ** Warnings: 1825701Seric ** The return value will be trashed across calls. 1835701Seric */ 1845701Seric 1855701Seric char * 1865701Seric aliaslookup(name) 1875701Seric char *name; 1885701Seric { 18957381Seric int i; 19057381Seric char keybuf[MAXNAME + 1]; 19156845Seric # if defined(NEWDB) || defined(NDBM) 19256845Seric DBdatum rhs, lhs; 19350575Seric int s; 19457381Seric # else /* neither NEWDB nor NDBM */ 19557381Seric register STAB *s; 19657381Seric # endif 1975701Seric 1985701Seric /* create a key for fetch */ 19957381Seric i = strlen(name) + 1; 20057381Seric if (i > sizeof keybuf) 20157381Seric i = sizeof keybuf; 20257381Seric bcopy(name, keybuf, i); 20357381Seric if (!bitnset(M_USR_UPPER, LocalMailer->m_flags)) 20457381Seric makelower(keybuf); 20557381Seric 20657381Seric # if defined(NEWDB) || defined(NDBM) 20757381Seric lhs.xx.size = i; 20857381Seric lhs.xx.data = keybuf; 20950575Seric # ifdef NEWDB 21051756Seric if (AliasDBptr != NULL) 21151756Seric { 21257381Seric i = AliasDBptr->get(AliasDBptr, &lhs.dbt, &rhs.dbt, 0); 21357381Seric if (i == 0) 21456845Seric return (rhs.dbt.data); 21551756Seric } 21656845Seric # ifdef NDBM 21757249Seric else if (AliasDBMptr != NULL) 21851756Seric { 21956845Seric rhs.dbm = dbm_fetch(AliasDBMptr, lhs.dbm); 22056845Seric return (rhs.dbm.dptr); 22151756Seric } 22256845Seric # endif /* NDBM */ 22357530Seric return (NULL); 22456845Seric # else /* not NEWDB */ 22556845Seric rhs.dbm = dbm_fetch(AliasDBMptr, lhs.dbm); 22656845Seric return (rhs.dbm.dptr); 22756845Seric # endif /* NEWDB */ 22856845Seric # else /* neither NEWDB nor NDBM */ 22957381Seric s = stab(keybuf, ST_ALIAS, ST_FIND); 23051756Seric if (s != NULL) 23151756Seric return (s->s_alias); 23257530Seric return (NULL); 23351756Seric # endif 2345701Seric } 2355701Seric /* 2364098Seric ** INITALIASES -- initialize for aliasing 2374098Seric ** 23856845Seric ** Very different depending on whether we are running NDBM or not. 2394098Seric ** 2404098Seric ** Parameters: 2414098Seric ** aliasfile -- location of aliases. 24256845Seric ** init -- if set and if NDBM, initialize the NDBM files. 2434098Seric ** 2444098Seric ** Returns: 2454098Seric ** none. 2464098Seric ** 2474098Seric ** Side Effects: 2484098Seric ** initializes aliases: 24956845Seric ** if NDBM: opens the database. 25056845Seric ** if ~NDBM: reads the aliases into the symbol table. 2514098Seric */ 2524098Seric 25340559Sbostic # define DBMMODE 0644 2544157Seric 25555012Seric initaliases(aliasfile, init, e) 2564098Seric char *aliasfile; 2574157Seric bool init; 25855012Seric register ENVELOPE *e; 2594098Seric { 26056845Seric #if defined(NDBM) || defined(NEWDB) 2618437Seric int atcnt; 26225522Seric time_t modtime; 26325522Seric bool automatic = FALSE; 2644322Seric char buf[MAXNAME]; 26550575Seric #endif 2669368Seric struct stat stb; 26727176Seric static bool initialized = FALSE; 26846928Sbostic static int readaliases(); 2694322Seric 27027176Seric if (initialized) 27127176Seric return; 27227176Seric initialized = TRUE; 27327176Seric 27417984Seric if (aliasfile == NULL || stat(aliasfile, &stb) < 0) 2758437Seric { 27625522Seric if (aliasfile != NULL && init) 277*58151Seric syserr("554 Cannot open %s", aliasfile); 2788437Seric NoAlias = TRUE; 27911937Seric errno = 0; 2808437Seric return; 2818437Seric } 2828437Seric 28356845Seric # if defined(NDBM) || defined(NEWDB) 2844322Seric /* 2858437Seric ** Check to see that the alias file is complete. 2868437Seric ** If not, we will assume that someone died, and it is up 2878437Seric ** to us to rebuild it. 2888437Seric */ 2898437Seric 29025689Seric if (!init) 29150575Seric { 29250575Seric # ifdef NEWDB 29350575Seric (void) strcpy(buf, aliasfile); 29450575Seric (void) strcat(buf, ".db"); 29551171Sbostic AliasDBptr = dbopen(buf, O_RDONLY, DBMMODE, DB_HASH, NULL); 29650576Seric if (AliasDBptr == NULL) 29750576Seric { 29856845Seric # ifdef NDBM 29956845Seric AliasDBMptr = dbm_open(aliasfile, O_RDONLY, DBMMODE); 30057249Seric if (AliasDBMptr == NULL) 30157249Seric { 30257249Seric syserr("initaliases: cannot open %s", buf); 30357249Seric NoAlias = TRUE; 30457249Seric return; 30557249Seric } 30651756Seric # else 30750576Seric syserr("initaliases: cannot open %s", buf); 30850576Seric NoAlias = TRUE; 30950576Seric return; 31051756Seric # endif 31150576Seric } 31250575Seric # else 31356845Seric AliasDBMptr = dbm_open(aliasfile, O_RDONLY, DBMMODE); 31457249Seric if (AliasDBMptr == NULL) 31557249Seric { 31657977Seric syserr("initaliases: cannot open DBM database %s.{pag,dir}", 31757977Seric aliasfile); 31857249Seric NoAlias = TRUE; 31957249Seric return; 32057249Seric } 32150575Seric # endif 32250575Seric } 32317471Seric atcnt = SafeAlias * 2; 32417471Seric if (atcnt > 0) 32517471Seric { 32617471Seric while (!init && atcnt-- >= 0 && aliaslookup("@") == NULL) 32725689Seric { 32825689Seric /* 32925689Seric ** Reinitialize alias file in case the new 33025689Seric ** one is mv'ed in instead of cp'ed in. 33125689Seric ** 33225689Seric ** Only works with new DBM -- old one will 33325689Seric ** just consume file descriptors forever. 33425689Seric ** If you have a dbmclose() it can be 33525689Seric ** added before the sleep(30). 33625689Seric */ 33725689Seric 33850575Seric # ifdef NEWDB 33951756Seric if (AliasDBptr != NULL) 34051756Seric AliasDBptr->close(AliasDBptr); 34150575Seric # endif 34256845Seric # ifdef NDBM 34356845Seric if (AliasDBMptr != NULL) 34456845Seric dbm_close(AliasDBMptr); 34556845Seric # endif 34650575Seric 34717471Seric sleep(30); 34850575Seric # ifdef NEWDB 34950575Seric (void) strcpy(buf, aliasfile); 35050575Seric (void) strcat(buf, ".db"); 35151171Sbostic AliasDBptr = 35251171Sbostic dbopen(buf, O_RDONLY, DBMMODE, DB_HASH, NULL); 35350576Seric if (AliasDBptr == NULL) 35450576Seric { 35551756Seric # ifdef NDBM 35656845Seric AliasDBMptr = dbm_open(aliasfile, O_RDONLY, DBMMODE); 35751756Seric # else 35850576Seric syserr("initaliases: cannot open %s", buf); 35950576Seric NoAlias = TRUE; 36050576Seric return; 36151756Seric # endif 36250576Seric } 36350575Seric # else 36425689Seric # ifdef NDBM 36556845Seric AliasDBMptr = dbm_open(aliasfile, O_RDONLY, DBMMODE); 36657249Seric if (AliasDBMptr == NULL) 36757249Seric { 36858008Seric syserr("initaliases: cannot open DBM database %s.{pag,dir}", 36958008Seric aliasfile); 37057249Seric NoAlias = TRUE; 37157249Seric return; 37257249Seric } 37350575Seric # endif 37450575Seric # endif 37525689Seric } 37617471Seric } 37717471Seric else 37817471Seric atcnt = 1; 3798437Seric 3808437Seric /* 38156845Seric ** See if the NDBM version of the file is out of date with 3824322Seric ** the text version. If so, go into 'init' mode automatically. 38340559Sbostic ** This only happens if our effective userid owns the DBM. 38440559Sbostic ** Note the unpalatable hack to see if the stat succeeded. 3854322Seric */ 3864322Seric 3874322Seric modtime = stb.st_mtime; 3884322Seric (void) strcpy(buf, aliasfile); 38950575Seric # ifdef NEWDB 39050575Seric (void) strcat(buf, ".db"); 39150575Seric # else 3924322Seric (void) strcat(buf, ".pag"); 39350575Seric # endif 3944322Seric stb.st_ino = 0; 39519039Seric if (!init && (stat(buf, &stb) < 0 || stb.st_mtime < modtime || atcnt < 0)) 3964322Seric { 39711937Seric errno = 0; 39840559Sbostic if (AutoRebuild && stb.st_ino != 0 && stb.st_uid == geteuid()) 3994322Seric { 4004322Seric init = TRUE; 40125522Seric automatic = TRUE; 402*58151Seric message("rebuilding alias database"); 40324944Seric #ifdef LOG 40458020Seric if (LogLevel > 14) 40524944Seric syslog(LOG_INFO, "rebuilding alias database"); 40656795Seric #endif /* LOG */ 4074322Seric } 4084322Seric else 4094322Seric { 41019039Seric #ifdef LOG 41158020Seric if (LogLevel > 3) 41224944Seric syslog(LOG_INFO, "alias database out of date"); 41356795Seric #endif /* LOG */ 414*58151Seric message("Warning: alias database out of date"); 4154322Seric } 4164322Seric } 4174322Seric 4184322Seric 4194322Seric /* 42056845Seric ** If necessary, load the NDBM file. 42156845Seric ** If running without NDBM, load the symbol table. 4224322Seric */ 4234322Seric 4244157Seric if (init) 4258437Seric { 42625522Seric #ifdef LOG 42758020Seric if (LogLevel > 7) 42825522Seric { 42925522Seric extern char *username(); 43025522Seric 43125522Seric syslog(LOG_NOTICE, "alias database %srebuilt by %s", 43225522Seric automatic ? "auto" : "", username()); 43325522Seric } 43456795Seric #endif /* LOG */ 43555012Seric readaliases(aliasfile, TRUE, e); 4368437Seric } 43756845Seric # else /* NDBM */ 43855012Seric readaliases(aliasfile, init, e); 43956845Seric # endif /* NDBM */ 4404157Seric } 4414157Seric /* 4424157Seric ** READALIASES -- read and process the alias file. 4434157Seric ** 4444157Seric ** This routine implements the part of initaliases that occurs 4454157Seric ** when we are not going to use the DBM stuff. 4464157Seric ** 4474157Seric ** Parameters: 4484157Seric ** aliasfile -- the pathname of the alias file master. 44956845Seric ** init -- if set, initialize the NDBM stuff. 4504157Seric ** 4514157Seric ** Returns: 4524157Seric ** none. 4534157Seric ** 4544157Seric ** Side Effects: 4554157Seric ** Reads aliasfile into the symbol table. 4564157Seric ** Optionally, builds the .dir & .pag files. 4574157Seric */ 4584157Seric 4594157Seric static 46055012Seric readaliases(aliasfile, init, e) 4614157Seric char *aliasfile; 4624157Seric bool init; 46355012Seric register ENVELOPE *e; 4644157Seric { 4654098Seric register char *p; 4664098Seric char *rhs; 4674098Seric bool skipping; 4689368Seric int naliases, bytes, longest; 4699368Seric FILE *af; 47053742Seric bool makedbmfiles; 47140970Sbostic void (*oldsigint)(); 4724098Seric ADDRESS al, bl; 4734106Seric register STAB *s; 47450575Seric # ifdef NEWDB 47550575Seric DB *dbp; 47650575Seric # endif 47756845Seric # ifdef NDBM 47856845Seric DBM *dbmp; 47956845Seric # endif 48051937Seric # ifdef LOCKF 48151937Seric struct flock fld; 48251937Seric # endif 4839368Seric char line[BUFSIZ]; 4844098Seric 48551937Seric if ((af = fopen(aliasfile, "r+")) == NULL) 4861515Seric { 48757249Seric if (init) 488*58151Seric syserr("554 Can't open %s", aliasfile); 48957249Seric else if (tTd(27, 1)) 4904106Seric printf("Can't open %s\n", aliasfile); 4914098Seric errno = 0; 4924098Seric NoAlias++; 4934098Seric return; 4944098Seric } 4954314Seric 49656845Seric # if defined(NDBM) || defined(NEWDB) 49719784Seric /* see if someone else is rebuilding the alias file already */ 49851835Seric # ifdef LOCKF 49951937Seric fld.l_type = F_WRLCK; 50051937Seric fld.l_whence = fld.l_start = fld.l_len = 0; 50151937Seric if (fcntl(fileno(af), F_SETLK, &fld) < 0) 50251835Seric # else 50319784Seric if (flock(fileno(af), LOCK_EX | LOCK_NB) < 0 && errno == EWOULDBLOCK) 50451835Seric # endif 50519784Seric { 50619784Seric /* yes, they are -- wait until done and then return */ 507*58151Seric message("Alias file is already being rebuilt"); 50819784Seric if (OpMode != MD_INITALIAS) 50919784Seric { 51019784Seric /* wait for other rebuild to complete */ 51151835Seric # ifdef LOCKF 51251937Seric (void) fcntl(fileno(af), F_SETLKW, &fld); 51351835Seric # else 51419784Seric (void) flock(fileno(af), LOCK_EX); 51551835Seric # endif 51619784Seric } 51723108Seric (void) fclose(af); 51819784Seric errno = 0; 51919784Seric return; 52019784Seric } 52156845Seric # endif /* NDBM */ 52219784Seric 5234314Seric /* 52419784Seric ** If initializing, create the new DBM files. 52519784Seric */ 52619784Seric 52719784Seric if (init) 52819784Seric { 52919784Seric oldsigint = signal(SIGINT, SIG_IGN); 53051756Seric # ifdef NEWDB 53151756Seric (void) strcpy(line, aliasfile); 53251756Seric (void) strcat(line, ".db"); 53351756Seric dbp = dbopen(line, 53451756Seric O_RDWR|O_CREAT|O_TRUNC, DBMMODE, DB_HASH, NULL); 53551756Seric if (dbp == NULL) 53651756Seric { 53751756Seric syserr("readaliases: cannot create %s", line); 53851756Seric (void) signal(SIGINT, oldsigint); 53951756Seric return; 54051756Seric } 54153742Seric # endif 54253742Seric # ifdef IF_MAKEDBMFILES 54353742Seric # ifdef NEWDB 54453742Seric makedbmfiles = access("/var/yp/Makefile", R_OK) == 0; 54553742Seric # endif 54653742Seric IF_MAKEDBMFILES 54719784Seric { 54856845Seric dbmp = dbm_open(aliasfile, 54956845Seric O_RDWR|O_CREAT|O_TRUNC, DBMMODE); 55056845Seric if (dbmp == NULL) 55153742Seric { 55256845Seric syserr("readaliases: cannot create %s.{dir,pag}", 55356845Seric aliasfile); 55453742Seric (void) signal(SIGINT, oldsigint); 55553742Seric return; 55653742Seric } 55719784Seric } 55850575Seric # endif 55919784Seric } 56019784Seric 56119784Seric /* 5624314Seric ** Read and interpret lines 5634314Seric */ 5644314Seric 5659368Seric FileName = aliasfile; 5669368Seric LineNumber = 0; 5674322Seric naliases = bytes = longest = 0; 5684098Seric skipping = FALSE; 5694098Seric while (fgets(line, sizeof (line), af) != NULL) 5704098Seric { 5714322Seric int lhssize, rhssize; 5724322Seric 5739368Seric LineNumber++; 57456795Seric p = strchr(line, '\n'); 57525278Seric if (p != NULL) 57625278Seric *p = '\0'; 5774098Seric switch (line[0]) 5784098Seric { 5794098Seric case '#': 5804098Seric case '\0': 5814098Seric skipping = FALSE; 5824098Seric continue; 5834065Seric 5844098Seric case ' ': 5854098Seric case '\t': 5864098Seric if (!skipping) 587*58151Seric syserr("554 Non-continuation line starts with space"); 5884098Seric skipping = TRUE; 5894097Seric continue; 5904098Seric } 5914098Seric skipping = FALSE; 5921874Seric 5934314Seric /* 5944314Seric ** Process the LHS 59557736Seric ** Find the colon separator, and parse the address. 59616898Seric ** It should resolve to a local name -- this will 59716898Seric ** be checked later (we want to optionally do 59816898Seric ** parsing of the RHS first to maximize error 59916898Seric ** detection). 6004314Seric */ 6014314Seric 6024098Seric for (p = line; *p != '\0' && *p != ':' && *p != '\n'; p++) 6034097Seric continue; 60416898Seric if (*p++ != ':') 6054098Seric { 606*58151Seric syserr("554 missing colon"); 6074097Seric continue; 6084098Seric } 60955012Seric if (parseaddr(line, &al, 1, ':', e) == NULL) 6104098Seric { 611*58151Seric syserr("554 illegal alias name"); 61216898Seric continue; 6134098Seric } 61416898Seric loweraddr(&al); 6154314Seric 6164314Seric /* 6174314Seric ** Process the RHS. 6184314Seric ** 'al' is the internal form of the LHS address. 6194314Seric ** 'p' points to the text of the RHS. 6204314Seric */ 6214314Seric 6224098Seric rhs = p; 6234098Seric for (;;) 6244098Seric { 6254098Seric register char c; 6261515Seric 62725821Seric if (init && CheckAliases) 6284098Seric { 6294157Seric /* do parsing & compression of addresses */ 63025278Seric while (*p != '\0') 6314098Seric { 63225278Seric extern char *DelimChar; 63325278Seric 63458050Seric while ((isascii(*p) && isspace(*p)) || 63558050Seric *p == ',') 6364157Seric p++; 63725278Seric if (*p == '\0') 63825278Seric break; 63955012Seric if (parseaddr(p, &bl, -1, ',', e) == NULL) 640*58151Seric usrerr("553 %s... bad address", p); 64125278Seric p = DelimChar; 6424098Seric } 6434098Seric } 6444157Seric else 64515769Seric { 64616898Seric p = &p[strlen(p)]; 64716898Seric if (p[-1] == '\n') 64816898Seric *--p = '\0'; 64915769Seric } 6501515Seric 6514098Seric /* see if there should be a continuation line */ 6524106Seric c = fgetc(af); 6534106Seric if (!feof(af)) 6544314Seric (void) ungetc(c, af); 6554106Seric if (c != ' ' && c != '\t') 6564098Seric break; 6574098Seric 6584098Seric /* read continuation line */ 6594098Seric if (fgets(p, sizeof line - (p - line), af) == NULL) 6604098Seric break; 6619368Seric LineNumber++; 66257135Seric 66357135Seric /* check for line overflow */ 66457135Seric if (strchr(p, '\n') == NULL) 66557135Seric { 666*58151Seric usrerr("554 alias too long"); 66757135Seric break; 66857135Seric } 6694098Seric } 67016898Seric if (al.q_mailer != LocalMailer) 67116898Seric { 672*58151Seric syserr("554 cannot alias non-local names"); 67316898Seric continue; 67416898Seric } 6754314Seric 6764314Seric /* 6774314Seric ** Insert alias into symbol table or DBM file 6784314Seric */ 6794314Seric 68016898Seric lhssize = strlen(al.q_user) + 1; 68157381Seric if (!bitnset(M_USR_UPPER, al.q_mailer->m_flags)) 68257381Seric makelower(al.q_user); 6834322Seric rhssize = strlen(rhs) + 1; 6844322Seric 68556845Seric # if defined(NDBM) || defined(NEWDB) 6864157Seric if (init) 6874157Seric { 68856845Seric DBdatum key, content; 68957381Seric int putstat; 6904157Seric 69156845Seric key.xx.size = lhssize; 69256845Seric key.xx.data = al.q_user; 69356845Seric content.xx.size = rhssize; 69456845Seric content.xx.data = rhs; 69551756Seric # ifdef NEWDB 69657381Seric putstat = dbp->put(dbp, &key.dbt, &content.dbt, 69757381Seric R_NOOVERWRITE); 69857381Seric if (putstat > 0) 69957381Seric { 70057977Seric usrerr("050 Warning: duplicate alias name %s", 70157381Seric al.q_user); 70257381Seric putstat = dbp->put(dbp, &key.dbt, 70357381Seric &content.dbt, 0); 70457381Seric } 70557381Seric if (putstat != 0) 70650576Seric syserr("readaliases: db put (%s)", al.q_user); 70750575Seric # endif 70853742Seric # ifdef IF_MAKEDBMFILES 70953742Seric IF_MAKEDBMFILES 71057381Seric { 71157381Seric putstat = dbm_store(dbmp, key.dbm, content.dbm, 71257381Seric DBM_INSERT); 71357381Seric if (putstat > 0) 71457381Seric { 71557977Seric usrerr("050 Warning: duplicate alias name %s", 71657381Seric al.q_user); 71757381Seric putstat = dbm_store(dbmp, key.dbm, 71857381Seric content.dbm, DBM_REPLACE); 71957381Seric } 72057381Seric if (putstat != 0) 72156845Seric syserr("readaliases: dbm store (%s)", 72256845Seric al.q_user); 72357381Seric } 72453742Seric # endif 72557381Seric if (al.q_paddr != NULL) 72657381Seric free(al.q_paddr); 72757381Seric if (al.q_host != NULL) 72857381Seric free(al.q_host); 72957381Seric if (al.q_user != NULL) 73057381Seric free(al.q_user); 7314157Seric } 7324157Seric else 73356845Seric # endif /* NDBM */ 7344157Seric { 7354157Seric s = stab(al.q_user, ST_ALIAS, ST_ENTER); 7364157Seric s->s_alias = newstr(rhs); 7374157Seric } 7384322Seric 7394322Seric /* statistics */ 7404322Seric naliases++; 7414322Seric bytes += lhssize + rhssize; 7424322Seric if (rhssize > longest) 7434322Seric longest = rhssize; 7441515Seric } 74519784Seric 74656845Seric # if defined(NDBM) || defined(NEWDB) 74719784Seric if (init) 74819784Seric { 74919784Seric /* add the distinquished alias "@" */ 75056845Seric DBdatum key; 75119784Seric 75256845Seric key.xx.size = 2; 75356845Seric key.xx.data = "@"; 75450575Seric # ifdef NEWDB 75550576Seric if (dbp->sync(dbp) != 0 || 75656845Seric dbp->put(dbp, &key.dbt, &key.dbt, 0) != 0 || 75750576Seric dbp->close(dbp) != 0) 75850576Seric syserr("readaliases: db close failure"); 75953742Seric # endif 76056789Seric # ifdef IF_MAKEDBMFILES 76156793Seric IF_MAKEDBMFILES 76256845Seric { 76358059Seric #ifdef YPCOMPAT 76458059Seric nis_magic(dbmp); 76558059Seric #endif 76656845Seric if (dbm_store(dbmp, key.dbm, key.dbm, DBM_REPLACE) != 0 || 76756845Seric dbm_error(dbmp)) 76856845Seric syserr("readaliases: dbm close failure"); 76956845Seric dbm_close(dbmp); 77056845Seric } 77150575Seric # endif 77219784Seric 77319784Seric /* restore the old signal */ 77419784Seric (void) signal(SIGINT, oldsigint); 77519784Seric } 77656845Seric # endif /* NDBM */ 77719784Seric 77819784Seric /* closing the alias file drops the lock */ 7794098Seric (void) fclose(af); 78055012Seric e->e_to = NULL; 7819368Seric FileName = NULL; 782*58151Seric message("%d aliases, longest %d bytes, %d bytes total", 7834322Seric naliases, longest, bytes); 78424944Seric # ifdef LOG 78558020Seric if (LogLevel > 7) 78624944Seric syslog(LOG_INFO, "%d aliases, longest %d bytes, %d bytes total", 78724944Seric naliases, longest, bytes); 78856795Seric # endif /* LOG */ 789292Seric } 790292Seric /* 79158059Seric ** NIS_MAGIC -- Add NIS magic dbm data 79258059Seric ** 79358059Seric ** This adds the magic entries needed by SunOS to make this a valid 79458059Seric ** NIS map. 79558059Seric ** 79658059Seric ** Parameters: 79758059Seric ** dbmp -- a pointer to the DBM structure. 79858059Seric ** 79958059Seric ** Returns: 80058059Seric ** none. 80158059Seric */ 80258059Seric 80358059Seric # ifdef YPCOMPAT 80458059Seric 80558059Seric static void 80658059Seric nis_magic(dbmp) 80758059Seric DBM *dbmp; 80858059Seric { 80958059Seric int i; 81058059Seric static datum key[2] = 81158059Seric { 81258059Seric { "YP_LAST_MODIFIED", sizeof "YP_LAST_MODIFIED" - 1 }, 81358059Seric { "YP_MASTER_NAME", sizeof "YP_MASTER_NAME" - 1 }, 81458059Seric }; 81558059Seric datum contents[2]; 81658059Seric char tbuf[12]; 81758059Seric char hbuf[MAXHOSTNAMELEN]; 81858059Seric 81958059Seric (void) sprintf(tbuf, "%010ld", curtime()); 82058059Seric contents[0].dptr = tbuf; 82158059Seric contents[0].dsize = strlen(tbuf); 82258059Seric 82358059Seric (void) myhostname(hbuf, sizeof hbuf); 82458059Seric contents[1].dptr = hbuf; 82558059Seric contents[1].dptr = strlen(hbuf); 82658059Seric 82758059Seric for (i = 0; i < sizeof key / sizeof *key; i++) 82858059Seric { 82958059Seric if (dbm_store(dbmp, key[i], contents[i], DBM_REPLACE) != 0 || 83058059Seric dbm_error(dbmp)) 83158059Seric syserr("nis_magic: dbm_store failure"); 83258059Seric } 83358059Seric } 83458059Seric 83558059Seric # endif 83658059Seric /* 837292Seric ** FORWARD -- Try to forward mail 838292Seric ** 839292Seric ** This is similar but not identical to aliasing. 840292Seric ** 841292Seric ** Parameters: 8424314Seric ** user -- the name of the user who's mail we would like 8434314Seric ** to forward to. It must have been verified -- 8444314Seric ** i.e., the q_home field must have been filled 8454314Seric ** in. 8464999Seric ** sendq -- a pointer to the head of the send queue to 8474999Seric ** put this user's aliases in. 848292Seric ** 849292Seric ** Returns: 8504098Seric ** none. 851292Seric ** 852292Seric ** Side Effects: 8533185Seric ** New names are added to send queues. 854292Seric */ 855292Seric 85655012Seric forward(user, sendq, e) 8572966Seric ADDRESS *user; 8584999Seric ADDRESS **sendq; 85955012Seric register ENVELOPE *e; 860292Seric { 86157136Seric char *pp; 86257136Seric char *ep; 8634536Seric extern bool safefile(); 8644069Seric 8657671Seric if (tTd(27, 1)) 8664098Seric printf("forward(%s)\n", user->q_paddr); 8674098Seric 8684594Seric if (user->q_mailer != LocalMailer || bitset(QBADADDR, user->q_flags)) 8694098Seric return; 8704314Seric if (user->q_home == NULL) 87158059Seric { 872*58151Seric syserr("554 forward: no home"); 87358059Seric user->q_home = "/nosuchdirectory"; 87458059Seric } 8754069Seric 8764069Seric /* good address -- look for .forward file in home */ 87755012Seric define('z', user->q_home, e); 87857136Seric define('u', user->q_user, e); 87957136Seric define('h', user->q_host, e); 88057136Seric if (ForwardPath == NULL) 88158050Seric ForwardPath = newstr("\201z/.forward"); 88257136Seric 88357136Seric for (pp = ForwardPath; pp != NULL; pp = ep) 88457136Seric { 88557232Seric char buf[MAXPATHLEN+1]; 88657136Seric 88757136Seric ep = strchr(pp, ':'); 88857136Seric if (ep != NULL) 88957136Seric *ep = '\0'; 89057136Seric expand(pp, buf, &buf[sizeof buf - 1], e); 89157136Seric if (ep != NULL) 89257136Seric *ep++ = ':'; 89357136Seric if (tTd(27, 3)) 89457136Seric printf("forward: trying %s\n", buf); 89557136Seric if (include(buf, TRUE, user, sendq, e) == 0) 89657136Seric break; 89757136Seric } 898292Seric } 899