1292Seric # include <stdio.h> 2292Seric # include <ctype.h> 3292Seric # include <pwd.h> 43309Seric # include "sendmail.h" 5292Seric 64106Seric # ifdef DBM 7*4165Seric static char SccsId[] = "@(#)alias.c 3.14 08/18/81 (with DBM)"; 84106Seric # else DBM 9*4165Seric static char SccsId[] = "@(#)alias.c 3.14 08/18/81 (without DBM)"; 104106Seric # endif DBM 11402Seric 12292Seric /* 13292Seric ** ALIAS -- Compute aliases. 14292Seric ** 154098Seric ** Scans the file /usr/lib/aliases for a set of aliases. 163185Seric ** If found, it arranges to deliver to them. Uses libdbm 173185Seric ** database if -DDBM. 18292Seric ** 19292Seric ** Parameters: 204097Seric ** a -- address to alias. 21292Seric ** 22292Seric ** Returns: 23292Seric ** none 24292Seric ** 25292Seric ** Side Effects: 263185Seric ** Aliases found are expanded. 27292Seric ** 28292Seric ** Files: 294098Seric ** /usr/lib/aliases -- the mail aliases. The format is 30569Seric ** a series of lines of the form: 31569Seric ** alias:name1,name2,name3,... 32569Seric ** where 'alias' expands to all of 33569Seric ** 'name[i]'. Continuations begin with 34569Seric ** space or tab. 354098Seric ** /usr/lib/aliases.pag, /usr/lib/aliases.dir: libdbm version 361503Smark ** of alias file. Keys are aliases, datums 371503Smark ** (data?) are name1,name2, ... 38292Seric ** 39292Seric ** Notes: 40292Seric ** If NoAlias (the "-n" flag) is set, no aliasing is 41292Seric ** done. 42292Seric ** 43292Seric ** Deficiencies: 44292Seric ** It should complain about names that are aliased to 45292Seric ** nothing. 46292Seric ** It is unsophisticated about line overflows. 47292Seric */ 48292Seric 49292Seric 501503Smark #ifdef DBM 512966Seric typedef struct 522966Seric { 532966Seric char *dptr; 544157Seric int dsize; 554157Seric } DATUM; 564157Seric DATUM lhs, rhs; 574157Seric extern DATUM fetch(); 581503Smark #endif DBM 59292Seric 604097Seric alias(a) 614097Seric register ADDRESS *a; 62292Seric { 634081Seric register char *p; 644081Seric # ifndef DBM 654098Seric register STAB *s; 664081Seric # endif DBM 67292Seric 68292Seric if (NoAlias) 69292Seric return; 70292Seric # ifdef DEBUG 71292Seric if (Debug) 724098Seric printf("alias(%s)\n", a->q_paddr); 73292Seric # endif 74292Seric 754098Seric /* don't realias already aliased names */ 764098Seric if (bitset(QDONTSEND, a->q_flags)) 774098Seric return; 784098Seric 794098Seric To = a->q_paddr; 804098Seric 814097Seric # ifdef DBM 824098Seric /* create a key for fetch */ 834098Seric lhs.dptr = a->q_user; 844098Seric lhs.dsize = strlen(a->q_user) + 1; 854098Seric rhs = fetch(lhs); 864098Seric 874098Seric /* find this alias? */ 884098Seric p = rhs.dptr; 894098Seric if (p == NULL) 904098Seric return; 914098Seric # else DBM 924098Seric s = stab(a->q_user, ST_ALIAS, ST_FIND); 934098Seric if (s == NULL) 944098Seric return; 954098Seric p = s->s_alias; 964097Seric # endif DBM 97292Seric 98292Seric /* 994098Seric ** Match on Alias. 1004098Seric ** Deliver to the target list. 1011515Seric */ 1021515Seric 1034098Seric # ifdef DEBUG 1044098Seric if (Debug) 1054098Seric printf("%s (%s, %s) aliased to %s\n", 1064098Seric a->q_paddr, a->q_host, a->q_user, p); 1074098Seric # endif 1084098Seric if (Verbose) 109*4165Seric message(Arpa_Info, "aliased to %s", p); 1104098Seric a->q_flags |= QDONTSEND; 1114098Seric AliasLevel++; 1124098Seric sendto(p, 1); 1134098Seric AliasLevel--; 1144098Seric } 1154098Seric /* 1164098Seric ** INITALIASES -- initialize for aliasing 1174098Seric ** 1184098Seric ** Very different depending on whether we are running DBM or not. 1194098Seric ** 1204098Seric ** Parameters: 1214098Seric ** aliasfile -- location of aliases. 1224157Seric ** init -- if set and if DBM, initialize the DBM files. 1234098Seric ** 1244098Seric ** Returns: 1254098Seric ** none. 1264098Seric ** 1274098Seric ** Side Effects: 1284098Seric ** initializes aliases: 1294098Seric ** if DBM: opens the database. 1304098Seric ** if ~DBM: reads the aliases into the symbol table. 1314098Seric */ 1324098Seric 1334157Seric # define DBMMODE 0666 1344157Seric 1354157Seric initaliases(aliasfile, init) 1364098Seric char *aliasfile; 1374157Seric bool init; 1384098Seric { 1394098Seric # ifdef DBM 1404157Seric if (init) 1414157Seric { 1424157Seric char buf[MAXNAME]; 1434157Seric 1444157Seric (void) strcpy(buf, aliasfile); 1454157Seric (void) strcat(buf, ".dir"); 1464157Seric if (close(creat(buf, DBMMODE)) < 0) 1474157Seric { 1484157Seric syserr("cannot make %s", buf); 1494157Seric return; 1504157Seric } 1514157Seric (void) strcpy(buf, aliasfile); 1524157Seric (void) strcat(buf, ".pag"); 1534157Seric if (close(creat(buf, DBMMODE)) < 0) 1544157Seric { 1554157Seric syserr("cannot make %s", buf); 1564157Seric return; 1574157Seric } 1584157Seric } 1594098Seric dbminit(aliasfile); 1604157Seric if (init) 1614157Seric readaliases(aliasfile, TRUE); 1624098Seric # else DBM 1634157Seric readaliases(aliasfile, init); 1644157Seric # endif DBM 1654157Seric } 1664157Seric /* 1674157Seric ** READALIASES -- read and process the alias file. 1684157Seric ** 1694157Seric ** This routine implements the part of initaliases that occurs 1704157Seric ** when we are not going to use the DBM stuff. 1714157Seric ** 1724157Seric ** Parameters: 1734157Seric ** aliasfile -- the pathname of the alias file master. 1744157Seric ** init -- if set, initialize the DBM stuff. 1754157Seric ** 1764157Seric ** Returns: 1774157Seric ** none. 1784157Seric ** 1794157Seric ** Side Effects: 1804157Seric ** Reads aliasfile into the symbol table. 1814157Seric ** Optionally, builds the .dir & .pag files. 1824157Seric */ 1834157Seric 1844157Seric static 1854157Seric readaliases(aliasfile, init) 1864157Seric char *aliasfile; 1874157Seric bool init; 1884157Seric { 1894098Seric char line[BUFSIZ]; 1904098Seric register char *p; 1914098Seric char *p2; 1924098Seric char *rhs; 1934098Seric bool skipping; 1944098Seric ADDRESS al, bl; 1954106Seric FILE *af; 1964106Seric int lineno; 1974106Seric register STAB *s; 1984098Seric 1994098Seric if ((af = fopen(aliasfile, "r")) == NULL) 2001515Seric { 2014098Seric # ifdef DEBUG 2024098Seric if (Debug) 2034106Seric printf("Can't open %s\n", aliasfile); 2044098Seric # endif 2054098Seric errno = 0; 2064098Seric NoAlias++; 2074098Seric return; 2084098Seric } 2094098Seric /* read and interpret lines */ 2104098Seric lineno = 0; 2114098Seric skipping = FALSE; 2124098Seric while (fgets(line, sizeof (line), af) != NULL) 2134098Seric { 2144098Seric lineno++; 2154098Seric switch (line[0]) 2164098Seric { 2174098Seric case '#': 2184098Seric case '\n': 2194098Seric case '\0': 2204098Seric skipping = FALSE; 2214098Seric continue; 2224065Seric 2234098Seric case ' ': 2244098Seric case '\t': 2254098Seric if (!skipping) 2264098Seric syserr("aliases: %d: Non-continuation line starts with space", lineno); 2274098Seric skipping = TRUE; 2284097Seric continue; 2294098Seric } 2304098Seric skipping = FALSE; 2311874Seric 2324098Seric /* process the LHS */ 2334098Seric for (p = line; *p != '\0' && *p != ':' && *p != '\n'; p++) 2344097Seric continue; 2354098Seric if (*p == '\0' || *p == '\n') 2364098Seric { 2374098Seric syntaxerr: 2384098Seric syserr("aliases: %d: missing colon", lineno); 2394097Seric continue; 2404098Seric } 2414098Seric *p++ = '\0'; 2424098Seric if (parse(line, &al, 1) == NULL) 2434098Seric { 2444098Seric *--p = ':'; 2454098Seric goto syntaxerr; 2464098Seric } 2474098Seric rhs = p; 2484098Seric for (;;) 2494098Seric { 2504098Seric register char c; 2511515Seric 2524157Seric if (init) 2534098Seric { 2544157Seric /* do parsing & compression of addresses */ 2554098Seric c = *p; 2564157Seric while (c != '\0') 2574098Seric { 2584157Seric p2 = p; 2594157Seric while (*p != '\n' && *p != ',' && *p != '\0') 2604157Seric p++; 2614157Seric c = *p; 2624157Seric *p++ = '\0'; 2634157Seric if (*p2 == '\0') 2644157Seric { 2654157Seric p[-1] = c; 2664157Seric continue; 2674157Seric } 2684157Seric parse(p2, &bl, -1); 2694098Seric p[-1] = c; 2704157Seric while (isspace(*p)) 2714157Seric p++; 2724098Seric } 2734098Seric } 2744157Seric else 2754157Seric p = &p[strlen(p)]; 2761515Seric 2774098Seric /* see if there should be a continuation line */ 2784106Seric c = fgetc(af); 2794106Seric if (!feof(af)) 2804106Seric ungetc(c, af); 2814106Seric if (c != ' ' && c != '\t') 2824098Seric break; 2834098Seric 2844098Seric /* read continuation line */ 2854098Seric p--; 2864098Seric if (fgets(p, sizeof line - (p - line), af) == NULL) 2874098Seric break; 2884098Seric lineno++; 2894098Seric } 2904098Seric if (al.q_mailer != M_LOCAL) 2914098Seric { 2924098Seric syserr("aliases: %d: cannot alias non-local names", lineno); 2934098Seric continue; 2944098Seric } 2954157Seric # ifdef DBM 2964157Seric if (init) 2974157Seric { 2984157Seric DATUM key, content; 2994157Seric 3004157Seric key.dsize = strlen(al.q_user) + 1; 3014157Seric key.dptr = al.q_user; 3024157Seric content.dsize = strlen(rhs) + 1; 3034157Seric content.dptr = rhs; 3044157Seric store(key, content); 3054157Seric } 3064157Seric else 3074157Seric # endif DBM 3084157Seric { 3094157Seric s = stab(al.q_user, ST_ALIAS, ST_ENTER); 3104157Seric s->s_alias = newstr(rhs); 3114157Seric } 3121515Seric } 3134098Seric (void) fclose(af); 314292Seric } 315292Seric /* 316292Seric ** FORWARD -- Try to forward mail 317292Seric ** 318292Seric ** This is similar but not identical to aliasing. 319292Seric ** 320292Seric ** Parameters: 321292Seric ** user -- the name of the user who's mail we 322292Seric ** would like to forward to. 323292Seric ** 324292Seric ** Returns: 3254098Seric ** none. 326292Seric ** 327292Seric ** Side Effects: 3283185Seric ** New names are added to send queues. 3294098Seric ** Sets the QDONTSEND bit in addresses that are forwarded. 330292Seric */ 331292Seric 332292Seric forward(user) 3332966Seric ADDRESS *user; 334292Seric { 3354078Seric char buf[60]; 3364069Seric register FILE *fp; 3374069Seric register char *p; 3384069Seric 3394098Seric # ifdef DEBUG 3404098Seric if (Debug) 3414098Seric printf("forward(%s)\n", user->q_paddr); 3424098Seric # endif DEBUG 3434098Seric 3444078Seric if (user->q_mailer != M_LOCAL || bitset(QBADADDR, user->q_flags)) 3454098Seric return; 3464069Seric 3474069Seric /* good address -- look for .forward file in home */ 3484104Seric define('z', user->q_home); 3494081Seric (void) expand("$z/.forward", buf, &buf[sizeof buf - 1]); 3504069Seric fp = fopen(buf, "r"); 3514069Seric if (fp == NULL) 3524098Seric return; 3534069Seric 3544069Seric /* we do have an address to forward to -- do it */ 3554098Seric user->q_flags |= QDONTSEND; 3564081Seric (void) fgets(buf, sizeof buf, fp); 3574069Seric if ((p = index(buf, '\n')) != NULL) 3584069Seric *p = '\0'; 3594081Seric (void) fclose(fp); 3604069Seric if (buf[0] == '\0') 3614098Seric return; 3624069Seric if (Verbose) 363*4165Seric message(Arpa_Info, "forwarded to %s", buf); 3644098Seric AliasLevel++; 3654069Seric sendto(buf, 1); 3664098Seric AliasLevel--; 3674098Seric return; 368292Seric } 369