1292Seric # include <pwd.h> 23309Seric # include "sendmail.h" 3292Seric 44106Seric # ifdef DBM 5*4193Seric static char SccsId[] = "@(#)alias.c 3.17 08/21/81 (with DBM)"; 64106Seric # else DBM 7*4193Seric static char SccsId[] = "@(#)alias.c 3.17 08/21/81 (without DBM)"; 84106Seric # endif DBM 9402Seric 10292Seric /* 11292Seric ** ALIAS -- Compute aliases. 12292Seric ** 134098Seric ** Scans the file /usr/lib/aliases for a set of aliases. 143185Seric ** If found, it arranges to deliver to them. Uses libdbm 153185Seric ** database if -DDBM. 16292Seric ** 17292Seric ** Parameters: 184097Seric ** a -- address to alias. 19292Seric ** 20292Seric ** Returns: 21292Seric ** none 22292Seric ** 23292Seric ** Side Effects: 243185Seric ** Aliases found are expanded. 25292Seric ** 26292Seric ** Files: 274098Seric ** /usr/lib/aliases -- the mail aliases. The format is 28569Seric ** a series of lines of the form: 29569Seric ** alias:name1,name2,name3,... 30569Seric ** where 'alias' expands to all of 31569Seric ** 'name[i]'. Continuations begin with 32569Seric ** space or tab. 334098Seric ** /usr/lib/aliases.pag, /usr/lib/aliases.dir: libdbm version 341503Smark ** of alias file. Keys are aliases, datums 351503Smark ** (data?) are name1,name2, ... 36292Seric ** 37292Seric ** Notes: 38292Seric ** If NoAlias (the "-n" flag) is set, no aliasing is 39292Seric ** done. 40292Seric ** 41292Seric ** Deficiencies: 42292Seric ** It should complain about names that are aliased to 43292Seric ** nothing. 44292Seric ** It is unsophisticated about line overflows. 45292Seric */ 46292Seric 47292Seric 481503Smark #ifdef DBM 492966Seric typedef struct 502966Seric { 512966Seric char *dptr; 524157Seric int dsize; 534157Seric } DATUM; 544157Seric DATUM lhs, rhs; 554157Seric extern DATUM fetch(); 561503Smark #endif DBM 57292Seric 584097Seric alias(a) 594097Seric register ADDRESS *a; 60292Seric { 614081Seric register char *p; 624081Seric # ifndef DBM 634098Seric register STAB *s; 644081Seric # endif DBM 65292Seric 66292Seric if (NoAlias) 67292Seric return; 68292Seric # ifdef DEBUG 69292Seric if (Debug) 704098Seric printf("alias(%s)\n", a->q_paddr); 71292Seric # endif 72292Seric 734098Seric /* don't realias already aliased names */ 744098Seric if (bitset(QDONTSEND, a->q_flags)) 754098Seric return; 764098Seric 774098Seric To = a->q_paddr; 784098Seric 794097Seric # ifdef DBM 804098Seric /* create a key for fetch */ 814098Seric lhs.dptr = a->q_user; 824098Seric lhs.dsize = strlen(a->q_user) + 1; 834098Seric rhs = fetch(lhs); 844098Seric 854098Seric /* find this alias? */ 864098Seric p = rhs.dptr; 874098Seric if (p == NULL) 884098Seric return; 894098Seric # else DBM 904098Seric s = stab(a->q_user, ST_ALIAS, ST_FIND); 914098Seric if (s == NULL) 924098Seric return; 934098Seric p = s->s_alias; 944097Seric # endif DBM 95292Seric 96292Seric /* 974098Seric ** Match on Alias. 984098Seric ** Deliver to the target list. 991515Seric */ 1001515Seric 1014098Seric # ifdef DEBUG 1024098Seric if (Debug) 1034098Seric printf("%s (%s, %s) aliased to %s\n", 1044098Seric a->q_paddr, a->q_host, a->q_user, p); 1054098Seric # endif 1064098Seric if (Verbose) 1074165Seric message(Arpa_Info, "aliased to %s", p); 1084098Seric a->q_flags |= QDONTSEND; 1094098Seric AliasLevel++; 1104098Seric sendto(p, 1); 1114098Seric AliasLevel--; 1124098Seric } 1134098Seric /* 1144098Seric ** INITALIASES -- initialize for aliasing 1154098Seric ** 1164098Seric ** Very different depending on whether we are running DBM or not. 1174098Seric ** 1184098Seric ** Parameters: 1194098Seric ** aliasfile -- location of aliases. 1204157Seric ** init -- if set and if DBM, initialize the DBM files. 1214098Seric ** 1224098Seric ** Returns: 1234098Seric ** none. 1244098Seric ** 1254098Seric ** Side Effects: 1264098Seric ** initializes aliases: 1274098Seric ** if DBM: opens the database. 1284098Seric ** if ~DBM: reads the aliases into the symbol table. 1294098Seric */ 1304098Seric 1314157Seric # define DBMMODE 0666 1324157Seric 1334157Seric initaliases(aliasfile, init) 1344098Seric char *aliasfile; 1354157Seric bool init; 1364098Seric { 1374098Seric # ifdef DBM 1384157Seric if (init) 1394157Seric { 1404157Seric char buf[MAXNAME]; 1414157Seric 1424157Seric (void) strcpy(buf, aliasfile); 1434157Seric (void) strcat(buf, ".dir"); 1444157Seric if (close(creat(buf, DBMMODE)) < 0) 1454157Seric { 1464157Seric syserr("cannot make %s", buf); 1474157Seric return; 1484157Seric } 1494157Seric (void) strcpy(buf, aliasfile); 1504157Seric (void) strcat(buf, ".pag"); 1514157Seric if (close(creat(buf, DBMMODE)) < 0) 1524157Seric { 1534157Seric syserr("cannot make %s", buf); 1544157Seric return; 1554157Seric } 1564157Seric } 1574098Seric dbminit(aliasfile); 1584157Seric if (init) 1594157Seric readaliases(aliasfile, TRUE); 1604098Seric # else DBM 1614157Seric readaliases(aliasfile, init); 1624157Seric # endif DBM 1634157Seric } 1644157Seric /* 1654157Seric ** READALIASES -- read and process the alias file. 1664157Seric ** 1674157Seric ** This routine implements the part of initaliases that occurs 1684157Seric ** when we are not going to use the DBM stuff. 1694157Seric ** 1704157Seric ** Parameters: 1714157Seric ** aliasfile -- the pathname of the alias file master. 1724157Seric ** init -- if set, initialize the DBM stuff. 1734157Seric ** 1744157Seric ** Returns: 1754157Seric ** none. 1764157Seric ** 1774157Seric ** Side Effects: 1784157Seric ** Reads aliasfile into the symbol table. 1794157Seric ** Optionally, builds the .dir & .pag files. 1804157Seric */ 1814157Seric 1824157Seric static 1834157Seric readaliases(aliasfile, init) 1844157Seric char *aliasfile; 1854157Seric bool init; 1864157Seric { 1874098Seric char line[BUFSIZ]; 1884098Seric register char *p; 1894098Seric char *p2; 1904098Seric char *rhs; 1914098Seric bool skipping; 1924098Seric ADDRESS al, bl; 1934106Seric FILE *af; 1944106Seric int lineno; 1954106Seric register STAB *s; 1964098Seric 1974098Seric if ((af = fopen(aliasfile, "r")) == NULL) 1981515Seric { 1994098Seric # ifdef DEBUG 2004098Seric if (Debug) 2014106Seric printf("Can't open %s\n", aliasfile); 2024098Seric # endif 2034098Seric errno = 0; 2044098Seric NoAlias++; 2054098Seric return; 2064098Seric } 2074098Seric /* read and interpret lines */ 2084098Seric lineno = 0; 2094098Seric skipping = FALSE; 2104098Seric while (fgets(line, sizeof (line), af) != NULL) 2114098Seric { 2124098Seric lineno++; 2134098Seric switch (line[0]) 2144098Seric { 2154098Seric case '#': 2164098Seric case '\n': 2174098Seric case '\0': 2184098Seric skipping = FALSE; 2194098Seric continue; 2204065Seric 2214098Seric case ' ': 2224098Seric case '\t': 2234098Seric if (!skipping) 2244098Seric syserr("aliases: %d: Non-continuation line starts with space", lineno); 2254098Seric skipping = TRUE; 2264097Seric continue; 2274098Seric } 2284098Seric skipping = FALSE; 2291874Seric 2304098Seric /* process the LHS */ 2314098Seric for (p = line; *p != '\0' && *p != ':' && *p != '\n'; p++) 2324097Seric continue; 2334098Seric if (*p == '\0' || *p == '\n') 2344098Seric { 2354098Seric syntaxerr: 2364098Seric syserr("aliases: %d: missing colon", lineno); 2374097Seric continue; 2384098Seric } 2394098Seric *p++ = '\0'; 2404098Seric if (parse(line, &al, 1) == NULL) 2414098Seric { 2424098Seric *--p = ':'; 2434098Seric goto syntaxerr; 2444098Seric } 2454098Seric rhs = p; 2464098Seric for (;;) 2474098Seric { 2484098Seric register char c; 2491515Seric 2504157Seric if (init) 2514098Seric { 2524157Seric /* do parsing & compression of addresses */ 2534098Seric c = *p; 2544157Seric while (c != '\0') 2554098Seric { 2564157Seric p2 = p; 2574157Seric while (*p != '\n' && *p != ',' && *p != '\0') 2584157Seric p++; 2594157Seric c = *p; 2604157Seric *p++ = '\0'; 2614157Seric if (*p2 == '\0') 2624157Seric { 2634157Seric p[-1] = c; 2644157Seric continue; 2654157Seric } 2664157Seric parse(p2, &bl, -1); 2674098Seric p[-1] = c; 2684157Seric while (isspace(*p)) 2694157Seric p++; 2704098Seric } 2714098Seric } 2724157Seric else 2734157Seric p = &p[strlen(p)]; 2741515Seric 2754098Seric /* see if there should be a continuation line */ 2764106Seric c = fgetc(af); 2774106Seric if (!feof(af)) 2784106Seric ungetc(c, af); 2794106Seric if (c != ' ' && c != '\t') 2804098Seric break; 2814098Seric 2824098Seric /* read continuation line */ 2834098Seric p--; 2844098Seric if (fgets(p, sizeof line - (p - line), af) == NULL) 2854098Seric break; 2864098Seric lineno++; 2874098Seric } 288*4193Seric if (al.q_mailer != MN_LOCAL) 2894098Seric { 2904098Seric syserr("aliases: %d: cannot alias non-local names", lineno); 2914098Seric continue; 2924098Seric } 2934157Seric # ifdef DBM 2944157Seric if (init) 2954157Seric { 2964157Seric DATUM key, content; 2974157Seric 2984157Seric key.dsize = strlen(al.q_user) + 1; 2994157Seric key.dptr = al.q_user; 3004157Seric content.dsize = strlen(rhs) + 1; 3014157Seric content.dptr = rhs; 3024157Seric store(key, content); 3034157Seric } 3044157Seric else 3054157Seric # endif DBM 3064157Seric { 3074157Seric s = stab(al.q_user, ST_ALIAS, ST_ENTER); 3084157Seric s->s_alias = newstr(rhs); 3094157Seric } 3101515Seric } 3114098Seric (void) fclose(af); 312292Seric } 313292Seric /* 314292Seric ** FORWARD -- Try to forward mail 315292Seric ** 316292Seric ** This is similar but not identical to aliasing. 317292Seric ** 318292Seric ** Parameters: 319292Seric ** user -- the name of the user who's mail we 320292Seric ** would like to forward to. 321292Seric ** 322292Seric ** Returns: 3234098Seric ** none. 324292Seric ** 325292Seric ** Side Effects: 3263185Seric ** New names are added to send queues. 3274098Seric ** Sets the QDONTSEND bit in addresses that are forwarded. 328292Seric */ 329292Seric 330292Seric forward(user) 3312966Seric ADDRESS *user; 332292Seric { 3334078Seric char buf[60]; 3344069Seric register FILE *fp; 3354069Seric register char *p; 3364069Seric 3374098Seric # ifdef DEBUG 3384098Seric if (Debug) 3394098Seric printf("forward(%s)\n", user->q_paddr); 3404098Seric # endif DEBUG 3414098Seric 342*4193Seric if (user->q_mailer != MN_LOCAL || bitset(QBADADDR, user->q_flags)) 3434098Seric return; 3444069Seric 3454069Seric /* good address -- look for .forward file in home */ 3464104Seric define('z', user->q_home); 3474081Seric (void) expand("$z/.forward", buf, &buf[sizeof buf - 1]); 3484177Seric if (access(buf, 4) < 0) 3494098Seric return; 3504069Seric 3514069Seric /* we do have an address to forward to -- do it */ 3524098Seric user->q_flags |= QDONTSEND; 3534177Seric include(buf, "forwarding"); 354292Seric } 355