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> 1150577Seric # include <signal.h> 1250577Seric # include <errno.h> 1350577Seric # include "sendmail.h" 1450577Seric # include <sys/file.h> 1550577Seric # include <pwd.h> 1651937Seric # ifdef LOCKF 1751937Seric # include <fcntl.h> 1851937Seric # endif 1950577Seric 2050577Seric # ifdef NEWDB 2150577Seric # include <db.h> 2250577Seric # endif 2350577Seric 2456766Seric # ifdef NDBM 2556766Seric # ifndef DBM 2656766Seric # define DBM 2756766Seric # endif 2856766Seric # endif 2956766Seric 3033728Sbostic #ifndef lint 3151756Seric #ifdef NEWDB 32*56795Seric static char sccsid[] = "@(#)alias.c 5.38 (Berkeley) 11/14/92 (with NEWDB)"; 3351756Seric #else 3433728Sbostic #ifdef DBM 35*56795Seric static char sccsid[] = "@(#)alias.c 5.38 (Berkeley) 11/14/92 (with DBM)"; 3633728Sbostic #else 37*56795Seric static char sccsid[] = "@(#)alias.c 5.38 (Berkeley) 11/14/92 (without DBM)"; 3833728Sbostic #endif 3950575Seric #endif 4033728Sbostic #endif /* not lint */ 4151756Seric /* 42292Seric ** ALIAS -- Compute aliases. 43292Seric ** 449368Seric ** Scans the alias file for an alias for the given address. 459368Seric ** If found, it arranges to deliver to the alias list instead. 469368Seric ** Uses libdbm database if -DDBM. 47292Seric ** 48292Seric ** Parameters: 494097Seric ** a -- address to alias. 504999Seric ** sendq -- a pointer to the head of the send queue 514999Seric ** to put the aliases in. 52292Seric ** 53292Seric ** Returns: 54292Seric ** none 55292Seric ** 56292Seric ** Side Effects: 573185Seric ** Aliases found are expanded. 58292Seric ** 59292Seric ** Notes: 60292Seric ** If NoAlias (the "-n" flag) is set, no aliasing is 61292Seric ** done. 62292Seric ** 63292Seric ** Deficiencies: 64292Seric ** It should complain about names that are aliased to 65292Seric ** nothing. 66292Seric */ 67292Seric 68292Seric 6953742Seric /* 7053742Seric ** Sun YP servers read the dbm files directly, so we have to build them 7153742Seric ** even if NEWDB 7253742Seric */ 7353742Seric 741503Smark #ifdef DBM 7553742Seric # ifndef NEWDB 7653742Seric # define IF_MAKEDBMFILES 7753742Seric # else 7853742Seric # ifdef YPCOMPAT 7953742Seric # define IF_MAKEDBMFILES if (makedbmfiles) 8053742Seric # endif 8153742Seric # endif 8253742Seric #endif 8353742Seric 8453742Seric #ifdef DBM 8551756Seric #ifndef NEWDB 862966Seric typedef struct 872966Seric { 8850575Seric char *data; 8950575Seric int size; 9050575Seric } DBT; 9151756Seric #endif 9250575Seric extern DBT fetch(); 9350575Seric #endif /* DBM */ 94292Seric 9550575Seric #ifdef NEWDB 9650575Seric static DB *AliasDBptr; 9750575Seric #endif 9850575Seric 9955012Seric alias(a, sendq, e) 1004097Seric register ADDRESS *a; 1014999Seric ADDRESS **sendq; 10255012Seric register ENVELOPE *e; 103292Seric { 1044081Seric register char *p; 1055701Seric extern char *aliaslookup(); 106292Seric 1077671Seric if (tTd(27, 1)) 1084098Seric printf("alias(%s)\n", a->q_paddr); 109292Seric 1104098Seric /* don't realias already aliased names */ 1114098Seric if (bitset(QDONTSEND, a->q_flags)) 1124098Seric return; 1134098Seric 11455012Seric e->e_to = a->q_paddr; 1154098Seric 1164314Seric /* 1174314Seric ** Look up this name 1184314Seric */ 1194314Seric 12024944Seric if (NoAlias) 12124944Seric p = NULL; 12224944Seric else 12324944Seric p = aliaslookup(a->q_user); 1244098Seric if (p == NULL) 1254098Seric return; 126292Seric 127292Seric /* 1284098Seric ** Match on Alias. 1294098Seric ** Deliver to the target list. 1301515Seric */ 1311515Seric 1327671Seric if (tTd(27, 1)) 1334098Seric printf("%s (%s, %s) aliased to %s\n", 1344098Seric a->q_paddr, a->q_host, a->q_user, p); 1357051Seric message(Arpa_Info, "aliased to %s", p); 1364098Seric AliasLevel++; 13755012Seric sendtolist(p, a, sendq, e); 1384098Seric AliasLevel--; 1394098Seric } 1404098Seric /* 1415701Seric ** ALIASLOOKUP -- look up a name in the alias file. 1425701Seric ** 1435701Seric ** Parameters: 1445701Seric ** name -- the name to look up. 1455701Seric ** 1465701Seric ** Returns: 1475701Seric ** the value of name. 1485701Seric ** NULL if unknown. 1495701Seric ** 1505701Seric ** Side Effects: 1515701Seric ** none. 1525701Seric ** 1535701Seric ** Warnings: 1545701Seric ** The return value will be trashed across calls. 1555701Seric */ 1565701Seric 1575701Seric char * 1585701Seric aliaslookup(name) 1595701Seric char *name; 1605701Seric { 16150575Seric # if defined(NEWDB) || defined(DBM) 16250575Seric DBT rhs, lhs; 16350575Seric int s; 1645701Seric 1655701Seric /* create a key for fetch */ 16650575Seric lhs.data = name; 16750575Seric lhs.size = strlen(name) + 1; 16850575Seric # ifdef NEWDB 16951756Seric if (AliasDBptr != NULL) 17051756Seric { 17151756Seric s = AliasDBptr->get(AliasDBptr, &lhs, &rhs, 0); 17251756Seric if (s == 0) 17351756Seric return (rhs.data); 17451756Seric } 17551756Seric # ifdef DBM 17651756Seric else 17751756Seric { 17851756Seric rhs = fetch(lhs); 17951756Seric return (rhs.data); 18051756Seric } 18151756Seric # endif 18250575Seric # else 1835701Seric rhs = fetch(lhs); 18451756Seric return (rhs.data); 18550575Seric # endif 18651756Seric # else /* neither NEWDB nor DBM */ 1875701Seric register STAB *s; 1885701Seric 1895701Seric s = stab(name, ST_ALIAS, ST_FIND); 19051756Seric if (s != NULL) 19151756Seric return (s->s_alias); 19251756Seric # endif 19351756Seric return (NULL); 1945701Seric } 1955701Seric /* 1964098Seric ** INITALIASES -- initialize for aliasing 1974098Seric ** 1984098Seric ** Very different depending on whether we are running DBM or not. 1994098Seric ** 2004098Seric ** Parameters: 2014098Seric ** aliasfile -- location of aliases. 2024157Seric ** init -- if set and if DBM, initialize the DBM files. 2034098Seric ** 2044098Seric ** Returns: 2054098Seric ** none. 2064098Seric ** 2074098Seric ** Side Effects: 2084098Seric ** initializes aliases: 2094098Seric ** if DBM: opens the database. 2104098Seric ** if ~DBM: reads the aliases into the symbol table. 2114098Seric */ 2124098Seric 21340559Sbostic # define DBMMODE 0644 2144157Seric 21555012Seric initaliases(aliasfile, init, e) 2164098Seric char *aliasfile; 2174157Seric bool init; 21855012Seric register ENVELOPE *e; 2194098Seric { 22050575Seric #if defined(DBM) || defined(NEWDB) 2218437Seric int atcnt; 22225522Seric time_t modtime; 22325522Seric bool automatic = FALSE; 2244322Seric char buf[MAXNAME]; 22550575Seric #endif 2269368Seric struct stat stb; 22727176Seric static bool initialized = FALSE; 22846928Sbostic static int readaliases(); 2294322Seric 23027176Seric if (initialized) 23127176Seric return; 23227176Seric initialized = TRUE; 23327176Seric 23417984Seric if (aliasfile == NULL || stat(aliasfile, &stb) < 0) 2358437Seric { 23625522Seric if (aliasfile != NULL && init) 23725522Seric syserr("Cannot open %s", aliasfile); 2388437Seric NoAlias = TRUE; 23911937Seric errno = 0; 2408437Seric return; 2418437Seric } 2428437Seric 24350575Seric # if defined(DBM) || defined(NEWDB) 2444322Seric /* 2458437Seric ** Check to see that the alias file is complete. 2468437Seric ** If not, we will assume that someone died, and it is up 2478437Seric ** to us to rebuild it. 2488437Seric */ 2498437Seric 25025689Seric if (!init) 25150575Seric { 25250575Seric # ifdef NEWDB 25350575Seric (void) strcpy(buf, aliasfile); 25450575Seric (void) strcat(buf, ".db"); 25551171Sbostic AliasDBptr = dbopen(buf, O_RDONLY, DBMMODE, DB_HASH, NULL); 25650576Seric if (AliasDBptr == NULL) 25750576Seric { 25851756Seric # ifdef DBM 25951756Seric dbminit(aliasfile); 26051756Seric # else 26150576Seric syserr("initaliases: cannot open %s", buf); 26250576Seric NoAlias = TRUE; 26350576Seric return; 26451756Seric # endif 26550576Seric } 26650575Seric # else 26725689Seric dbminit(aliasfile); 26850575Seric # endif 26950575Seric } 27017471Seric atcnt = SafeAlias * 2; 27117471Seric if (atcnt > 0) 27217471Seric { 27317471Seric while (!init && atcnt-- >= 0 && aliaslookup("@") == NULL) 27425689Seric { 27525689Seric /* 27625689Seric ** Reinitialize alias file in case the new 27725689Seric ** one is mv'ed in instead of cp'ed in. 27825689Seric ** 27925689Seric ** Only works with new DBM -- old one will 28025689Seric ** just consume file descriptors forever. 28125689Seric ** If you have a dbmclose() it can be 28225689Seric ** added before the sleep(30). 28325689Seric */ 28425689Seric 28550575Seric # ifdef NEWDB 28651756Seric if (AliasDBptr != NULL) 28751756Seric AliasDBptr->close(AliasDBptr); 28850575Seric # endif 28950575Seric 29017471Seric sleep(30); 29150575Seric # ifdef NEWDB 29250575Seric (void) strcpy(buf, aliasfile); 29350575Seric (void) strcat(buf, ".db"); 29451171Sbostic AliasDBptr = 29551171Sbostic dbopen(buf, O_RDONLY, DBMMODE, DB_HASH, NULL); 29650576Seric if (AliasDBptr == NULL) 29750576Seric { 29851756Seric # ifdef NDBM 29951756Seric dbminit(aliasfile); 30051756Seric # else 30150576Seric syserr("initaliases: cannot open %s", buf); 30250576Seric NoAlias = TRUE; 30350576Seric return; 30451756Seric # endif 30550576Seric } 30650575Seric # else 30725689Seric # ifdef NDBM 30825689Seric dbminit(aliasfile); 30950575Seric # endif 31050575Seric # endif 31125689Seric } 31217471Seric } 31317471Seric else 31417471Seric atcnt = 1; 3158437Seric 3168437Seric /* 3174322Seric ** See if the DBM version of the file is out of date with 3184322Seric ** the text version. If so, go into 'init' mode automatically. 31940559Sbostic ** This only happens if our effective userid owns the DBM. 32040559Sbostic ** Note the unpalatable hack to see if the stat succeeded. 3214322Seric */ 3224322Seric 3234322Seric modtime = stb.st_mtime; 3244322Seric (void) strcpy(buf, aliasfile); 32550575Seric # ifdef NEWDB 32650575Seric (void) strcat(buf, ".db"); 32750575Seric # else 3284322Seric (void) strcat(buf, ".pag"); 32950575Seric # endif 3304322Seric stb.st_ino = 0; 33119039Seric if (!init && (stat(buf, &stb) < 0 || stb.st_mtime < modtime || atcnt < 0)) 3324322Seric { 33311937Seric errno = 0; 33440559Sbostic if (AutoRebuild && stb.st_ino != 0 && stb.st_uid == geteuid()) 3354322Seric { 3364322Seric init = TRUE; 33725522Seric automatic = TRUE; 3387051Seric message(Arpa_Info, "rebuilding alias database"); 33924944Seric #ifdef LOG 34024944Seric if (LogLevel >= 7) 34124944Seric syslog(LOG_INFO, "rebuilding alias database"); 342*56795Seric #endif /* LOG */ 3434322Seric } 3444322Seric else 3454322Seric { 34619039Seric #ifdef LOG 34724944Seric if (LogLevel >= 7) 34824944Seric syslog(LOG_INFO, "alias database out of date"); 349*56795Seric #endif /* LOG */ 3504322Seric message(Arpa_Info, "Warning: alias database out of date"); 3514322Seric } 3524322Seric } 3534322Seric 3544322Seric 3554322Seric /* 3568437Seric ** If necessary, load the DBM file. 3574322Seric ** If running without DBM, load the symbol table. 3584322Seric */ 3594322Seric 3604157Seric if (init) 3618437Seric { 36225522Seric #ifdef LOG 36325522Seric if (LogLevel >= 6) 36425522Seric { 36525522Seric extern char *username(); 36625522Seric 36725522Seric syslog(LOG_NOTICE, "alias database %srebuilt by %s", 36825522Seric automatic ? "auto" : "", username()); 36925522Seric } 370*56795Seric #endif /* LOG */ 37155012Seric readaliases(aliasfile, TRUE, e); 3728437Seric } 373*56795Seric # else /* DBM */ 37455012Seric readaliases(aliasfile, init, e); 375*56795Seric # endif /* DBM */ 3764157Seric } 3774157Seric /* 3784157Seric ** READALIASES -- read and process the alias file. 3794157Seric ** 3804157Seric ** This routine implements the part of initaliases that occurs 3814157Seric ** when we are not going to use the DBM stuff. 3824157Seric ** 3834157Seric ** Parameters: 3844157Seric ** aliasfile -- the pathname of the alias file master. 3854157Seric ** init -- if set, initialize the DBM stuff. 3864157Seric ** 3874157Seric ** Returns: 3884157Seric ** none. 3894157Seric ** 3904157Seric ** Side Effects: 3914157Seric ** Reads aliasfile into the symbol table. 3924157Seric ** Optionally, builds the .dir & .pag files. 3934157Seric */ 3944157Seric 3954157Seric static 39655012Seric readaliases(aliasfile, init, e) 3974157Seric char *aliasfile; 3984157Seric bool init; 39955012Seric register ENVELOPE *e; 4004157Seric { 4014098Seric register char *p; 4024098Seric char *rhs; 4034098Seric bool skipping; 4049368Seric int naliases, bytes, longest; 4059368Seric FILE *af; 40653742Seric bool makedbmfiles; 40740970Sbostic void (*oldsigint)(); 4084098Seric ADDRESS al, bl; 4094106Seric register STAB *s; 41050575Seric # ifdef NEWDB 41150575Seric DB *dbp; 41250575Seric # endif 41351937Seric # ifdef LOCKF 41451937Seric struct flock fld; 41551937Seric # endif 4169368Seric char line[BUFSIZ]; 4174098Seric 41851937Seric if ((af = fopen(aliasfile, "r+")) == NULL) 4191515Seric { 4207671Seric if (tTd(27, 1)) 4214106Seric printf("Can't open %s\n", aliasfile); 4224098Seric errno = 0; 4234098Seric NoAlias++; 4244098Seric return; 4254098Seric } 4264314Seric 42750575Seric # if defined(DBM) || defined(NEWDB) 42819784Seric /* see if someone else is rebuilding the alias file already */ 42951835Seric # ifdef LOCKF 43051937Seric fld.l_type = F_WRLCK; 43151937Seric fld.l_whence = fld.l_start = fld.l_len = 0; 43251937Seric if (fcntl(fileno(af), F_SETLK, &fld) < 0) 43351835Seric # else 43419784Seric if (flock(fileno(af), LOCK_EX | LOCK_NB) < 0 && errno == EWOULDBLOCK) 43551835Seric # endif 43619784Seric { 43719784Seric /* yes, they are -- wait until done and then return */ 43819784Seric message(Arpa_Info, "Alias file is already being rebuilt"); 43919784Seric if (OpMode != MD_INITALIAS) 44019784Seric { 44119784Seric /* wait for other rebuild to complete */ 44251835Seric # ifdef LOCKF 44351937Seric (void) fcntl(fileno(af), F_SETLKW, &fld); 44451835Seric # else 44519784Seric (void) flock(fileno(af), LOCK_EX); 44651835Seric # endif 44719784Seric } 44823108Seric (void) fclose(af); 44919784Seric errno = 0; 45019784Seric return; 45119784Seric } 452*56795Seric # endif /* DBM */ 45319784Seric 4544314Seric /* 45519784Seric ** If initializing, create the new DBM files. 45619784Seric */ 45719784Seric 45819784Seric if (init) 45919784Seric { 46019784Seric oldsigint = signal(SIGINT, SIG_IGN); 46151756Seric # ifdef NEWDB 46251756Seric (void) strcpy(line, aliasfile); 46351756Seric (void) strcat(line, ".db"); 46451756Seric dbp = dbopen(line, 46551756Seric O_RDWR|O_CREAT|O_TRUNC, DBMMODE, DB_HASH, NULL); 46651756Seric if (dbp == NULL) 46751756Seric { 46851756Seric syserr("readaliases: cannot create %s", line); 46951756Seric (void) signal(SIGINT, oldsigint); 47051756Seric return; 47151756Seric } 47253742Seric # endif 47353742Seric # ifdef IF_MAKEDBMFILES 47453742Seric # ifdef NEWDB 47553742Seric makedbmfiles = access("/var/yp/Makefile", R_OK) == 0; 47653742Seric # endif 47753742Seric IF_MAKEDBMFILES 47819784Seric { 47953742Seric (void) strcpy(line, aliasfile); 48053742Seric (void) strcat(line, ".dir"); 48153742Seric if (close(creat(line, DBMMODE)) < 0) 48253742Seric { 48353742Seric syserr("cannot make %s", line); 48453742Seric (void) signal(SIGINT, oldsigint); 48553742Seric return; 48653742Seric } 48753742Seric (void) strcpy(line, aliasfile); 48853742Seric (void) strcat(line, ".pag"); 48953742Seric if (close(creat(line, DBMMODE)) < 0) 49053742Seric { 49153742Seric syserr("cannot make %s", line); 49253742Seric (void) signal(SIGINT, oldsigint); 49353742Seric return; 49453742Seric } 49553742Seric dbminit(aliasfile); 49619784Seric } 49750575Seric # endif 49819784Seric } 49919784Seric 50019784Seric /* 5014314Seric ** Read and interpret lines 5024314Seric */ 5034314Seric 5049368Seric FileName = aliasfile; 5059368Seric LineNumber = 0; 5064322Seric naliases = bytes = longest = 0; 5074098Seric skipping = FALSE; 5084098Seric while (fgets(line, sizeof (line), af) != NULL) 5094098Seric { 5104322Seric int lhssize, rhssize; 5114322Seric 5129368Seric LineNumber++; 513*56795Seric p = strchr(line, '\n'); 51425278Seric if (p != NULL) 51525278Seric *p = '\0'; 5164098Seric switch (line[0]) 5174098Seric { 5184098Seric case '#': 5194098Seric case '\0': 5204098Seric skipping = FALSE; 5214098Seric continue; 5224065Seric 5234098Seric case ' ': 5244098Seric case '\t': 5254098Seric if (!skipping) 5269368Seric syserr("Non-continuation line starts with space"); 5274098Seric skipping = TRUE; 5284097Seric continue; 5294098Seric } 5304098Seric skipping = FALSE; 5311874Seric 5324314Seric /* 5334314Seric ** Process the LHS 5344314Seric ** Find the final colon, and parse the address. 53516898Seric ** It should resolve to a local name -- this will 53616898Seric ** be checked later (we want to optionally do 53716898Seric ** parsing of the RHS first to maximize error 53816898Seric ** detection). 5394314Seric */ 5404314Seric 5414098Seric for (p = line; *p != '\0' && *p != ':' && *p != '\n'; p++) 5424097Seric continue; 54316898Seric if (*p++ != ':') 5444098Seric { 5459368Seric syserr("missing colon"); 5464097Seric continue; 5474098Seric } 54855012Seric if (parseaddr(line, &al, 1, ':', e) == NULL) 5494098Seric { 55016898Seric syserr("illegal alias name"); 55116898Seric continue; 5524098Seric } 55316898Seric loweraddr(&al); 5544314Seric 5554314Seric /* 5564314Seric ** Process the RHS. 5574314Seric ** 'al' is the internal form of the LHS address. 5584314Seric ** 'p' points to the text of the RHS. 5594314Seric */ 5604314Seric 5614098Seric rhs = p; 5624098Seric for (;;) 5634098Seric { 5644098Seric register char c; 5651515Seric 56625821Seric if (init && CheckAliases) 5674098Seric { 5684157Seric /* do parsing & compression of addresses */ 56925278Seric while (*p != '\0') 5704098Seric { 57125278Seric extern char *DelimChar; 57225278Seric 57325278Seric while (isspace(*p) || *p == ',') 5744157Seric p++; 57525278Seric if (*p == '\0') 57625278Seric break; 57755012Seric if (parseaddr(p, &bl, -1, ',', e) == NULL) 57825278Seric usrerr("%s... bad address", p); 57925278Seric p = DelimChar; 5804098Seric } 5814098Seric } 5824157Seric else 58315769Seric { 58416898Seric p = &p[strlen(p)]; 58516898Seric if (p[-1] == '\n') 58616898Seric *--p = '\0'; 58715769Seric } 5881515Seric 5894098Seric /* see if there should be a continuation line */ 5904106Seric c = fgetc(af); 5914106Seric if (!feof(af)) 5924314Seric (void) ungetc(c, af); 5934106Seric if (c != ' ' && c != '\t') 5944098Seric break; 5954098Seric 5964098Seric /* read continuation line */ 5974098Seric if (fgets(p, sizeof line - (p - line), af) == NULL) 5984098Seric break; 5999368Seric LineNumber++; 6004098Seric } 60116898Seric if (al.q_mailer != LocalMailer) 60216898Seric { 60316898Seric syserr("cannot alias non-local names"); 60416898Seric continue; 60516898Seric } 6064314Seric 6074314Seric /* 6084314Seric ** Insert alias into symbol table or DBM file 6094314Seric */ 6104314Seric 61116898Seric lhssize = strlen(al.q_user) + 1; 6124322Seric rhssize = strlen(rhs) + 1; 6134322Seric 61450575Seric # if defined(DBM) || defined(NEWDB) 6154157Seric if (init) 6164157Seric { 61750575Seric DBT key, content; 6184157Seric 61950575Seric key.size = lhssize; 62050575Seric key.data = al.q_user; 62150575Seric content.size = rhssize; 62250575Seric content.data = rhs; 62351756Seric # ifdef NEWDB 62451171Sbostic if (dbp->put(dbp, &key, &content, 0) != 0) 62550576Seric syserr("readaliases: db put (%s)", al.q_user); 62650575Seric # endif 62753742Seric # ifdef IF_MAKEDBMFILES 62853742Seric IF_MAKEDBMFILES 62953742Seric store(key, content); 63053742Seric # endif 6314157Seric } 6324157Seric else 633*56795Seric # endif /* DBM */ 6344157Seric { 6354157Seric s = stab(al.q_user, ST_ALIAS, ST_ENTER); 6364157Seric s->s_alias = newstr(rhs); 6374157Seric } 6384322Seric 6394322Seric /* statistics */ 6404322Seric naliases++; 6414322Seric bytes += lhssize + rhssize; 6424322Seric if (rhssize > longest) 6434322Seric longest = rhssize; 6441515Seric } 64519784Seric 64650575Seric # if defined(DBM) || defined(NEWDB) 64719784Seric if (init) 64819784Seric { 64919784Seric /* add the distinquished alias "@" */ 65050575Seric DBT key; 65119784Seric 65250575Seric key.size = 2; 65350575Seric key.data = "@"; 65450575Seric # ifdef NEWDB 65550576Seric if (dbp->sync(dbp) != 0 || 65651171Sbostic dbp->put(dbp, &key, &key, 0) != 0 || 65750576Seric dbp->close(dbp) != 0) 65850576Seric syserr("readaliases: db close failure"); 65953742Seric # endif 66056789Seric # ifdef IF_MAKEDBMFILES 66156793Seric IF_MAKEDBMFILES 66256793Seric store(key, key); 66350575Seric # endif 66419784Seric 66519784Seric /* restore the old signal */ 66619784Seric (void) signal(SIGINT, oldsigint); 66719784Seric } 668*56795Seric # endif /* DBM */ 66919784Seric 67019784Seric /* closing the alias file drops the lock */ 6714098Seric (void) fclose(af); 67255012Seric e->e_to = NULL; 6739368Seric FileName = NULL; 6747051Seric message(Arpa_Info, "%d aliases, longest %d bytes, %d bytes total", 6754322Seric naliases, longest, bytes); 67624944Seric # ifdef LOG 67724944Seric if (LogLevel >= 8) 67824944Seric syslog(LOG_INFO, "%d aliases, longest %d bytes, %d bytes total", 67924944Seric naliases, longest, bytes); 680*56795Seric # endif /* LOG */ 681292Seric } 682292Seric /* 683292Seric ** FORWARD -- Try to forward mail 684292Seric ** 685292Seric ** This is similar but not identical to aliasing. 686292Seric ** 687292Seric ** Parameters: 6884314Seric ** user -- the name of the user who's mail we would like 6894314Seric ** to forward to. It must have been verified -- 6904314Seric ** i.e., the q_home field must have been filled 6914314Seric ** in. 6924999Seric ** sendq -- a pointer to the head of the send queue to 6934999Seric ** put this user's aliases in. 694292Seric ** 695292Seric ** Returns: 6964098Seric ** none. 697292Seric ** 698292Seric ** Side Effects: 6993185Seric ** New names are added to send queues. 700292Seric */ 701292Seric 70255012Seric forward(user, sendq, e) 7032966Seric ADDRESS *user; 7044999Seric ADDRESS **sendq; 70555012Seric register ENVELOPE *e; 706292Seric { 7074078Seric char buf[60]; 7084536Seric extern bool safefile(); 7094069Seric 7107671Seric if (tTd(27, 1)) 7114098Seric printf("forward(%s)\n", user->q_paddr); 7124098Seric 7134594Seric if (user->q_mailer != LocalMailer || bitset(QBADADDR, user->q_flags)) 7144098Seric return; 7154314Seric if (user->q_home == NULL) 7164314Seric syserr("forward: no home"); 7174069Seric 7184069Seric /* good address -- look for .forward file in home */ 71955012Seric define('z', user->q_home, e); 72055012Seric expand("\001z/.forward", buf, &buf[sizeof buf - 1], e); 72155012Seric include(buf, TRUE, user, sendq, e); 722292Seric } 723