1292Seric # include <stdio.h> 2292Seric # include <ctype.h> 3292Seric # include <pwd.h> 43309Seric # include "sendmail.h" 5292Seric 6*4106Seric # ifdef DBM 7*4106Seric static char SccsId[] = "@(#)alias.c 3.12 08/10/81 (with DBM)"; 8*4106Seric # else DBM 9*4106Seric static char SccsId[] = "@(#)alias.c 3.12 08/10/81 (without DBM)"; 10*4106Seric # 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; 542966Seric int dsize; 552966Seric } datum; 561503Smark datum lhs, rhs; 571515Seric 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) 1094098Seric message("050", "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. 1224098Seric ** 1234098Seric ** Returns: 1244098Seric ** none. 1254098Seric ** 1264098Seric ** Side Effects: 1274098Seric ** initializes aliases: 1284098Seric ** if DBM: opens the database. 1294098Seric ** if ~DBM: reads the aliases into the symbol table. 1304098Seric */ 1314098Seric 1324098Seric initaliases(aliasfile) 1334098Seric char *aliasfile; 1344098Seric { 1354098Seric # ifdef DBM 1364098Seric dbminit(aliasfile); 1374098Seric # else DBM 1384098Seric char line[BUFSIZ]; 1394098Seric register char *p; 1404098Seric char *p2; 1414098Seric char *rhs; 1424098Seric bool skipping; 1434098Seric ADDRESS al, bl; 144*4106Seric FILE *af; 145*4106Seric int lineno; 146*4106Seric register STAB *s; 1474098Seric 1484098Seric if ((af = fopen(aliasfile, "r")) == NULL) 1491515Seric { 1504098Seric # ifdef DEBUG 1514098Seric if (Debug) 152*4106Seric printf("Can't open %s\n", aliasfile); 1534098Seric # endif 1544098Seric errno = 0; 1554098Seric NoAlias++; 1564098Seric return; 1574098Seric } 1584098Seric /* read and interpret lines */ 1594098Seric lineno = 0; 1604098Seric skipping = FALSE; 1614098Seric while (fgets(line, sizeof (line), af) != NULL) 1624098Seric { 1634098Seric lineno++; 1644098Seric switch (line[0]) 1654098Seric { 1664098Seric case '#': 1674098Seric case '\n': 1684098Seric case '\0': 1694098Seric skipping = FALSE; 1704098Seric continue; 1714065Seric 1724098Seric case ' ': 1734098Seric case '\t': 1744098Seric if (!skipping) 1754098Seric syserr("aliases: %d: Non-continuation line starts with space", lineno); 1764098Seric skipping = TRUE; 1774097Seric continue; 1784098Seric } 1794098Seric skipping = FALSE; 1801874Seric 1814098Seric /* process the LHS */ 1824098Seric for (p = line; *p != '\0' && *p != ':' && *p != '\n'; p++) 1834097Seric continue; 1844098Seric if (*p == '\0' || *p == '\n') 1854098Seric { 1864098Seric syntaxerr: 1874098Seric syserr("aliases: %d: missing colon", lineno); 1884097Seric continue; 1894098Seric } 1904098Seric *p++ = '\0'; 1914098Seric if (parse(line, &al, 1) == NULL) 1924098Seric { 1934098Seric *--p = ':'; 1944098Seric goto syntaxerr; 1954098Seric } 1964098Seric rhs = p; 1974098Seric for (;;) 1984098Seric { 1994098Seric register char c; 2001515Seric 201*4106Seric # ifdef SECURE 2024098Seric /* do parsing & compression of addresses */ 2034098Seric c = *p; 2044098Seric while (c != '\0') 2054098Seric { 2064098Seric p2 = p; 2074098Seric while (*p != '\n' && *p != ',' && *p != '\0') 2084098Seric p++; 2094098Seric c = *p; 2104098Seric *p++ = '\0'; 2114098Seric if (*p2 == '\0') 2124098Seric { 2134098Seric p[-1] = c; 2144098Seric continue; 2154098Seric } 2164098Seric parse(p2, &bl, -1); 2174098Seric p[-1] = c; 2184098Seric while (isspace(*p)) 2194098Seric p++; 2204098Seric } 221*4106Seric # else SECURE 222*4106Seric p = &p[strlen(p)]; 223*4106Seric # endif SECURE 2241515Seric 2254098Seric /* see if there should be a continuation line */ 226*4106Seric c = fgetc(af); 227*4106Seric if (!feof(af)) 228*4106Seric ungetc(c, af); 229*4106Seric if (c != ' ' && c != '\t') 2304098Seric break; 2314098Seric 2324098Seric /* read continuation line */ 2334098Seric p--; 2344098Seric if (fgets(p, sizeof line - (p - line), af) == NULL) 2354098Seric break; 2364098Seric lineno++; 2374098Seric } 2384098Seric if (al.q_mailer != M_LOCAL) 2394098Seric { 2404098Seric syserr("aliases: %d: cannot alias non-local names", lineno); 2414098Seric continue; 2424098Seric } 243*4106Seric s = stab(al.q_user, ST_ALIAS, ST_ENTER); 244*4106Seric s->s_alias = newstr(rhs); 2451515Seric } 2464098Seric (void) fclose(af); 2474098Seric # endif DBM 248292Seric } 249292Seric /* 250292Seric ** FORWARD -- Try to forward mail 251292Seric ** 252292Seric ** This is similar but not identical to aliasing. 253292Seric ** 254292Seric ** Parameters: 255292Seric ** user -- the name of the user who's mail we 256292Seric ** would like to forward to. 257292Seric ** 258292Seric ** Returns: 2594098Seric ** none. 260292Seric ** 261292Seric ** Side Effects: 2623185Seric ** New names are added to send queues. 2634098Seric ** Sets the QDONTSEND bit in addresses that are forwarded. 264292Seric */ 265292Seric 266292Seric forward(user) 2672966Seric ADDRESS *user; 268292Seric { 2694078Seric char buf[60]; 2704069Seric register FILE *fp; 2714069Seric register char *p; 2724069Seric 2734098Seric # ifdef DEBUG 2744098Seric if (Debug) 2754098Seric printf("forward(%s)\n", user->q_paddr); 2764098Seric # endif DEBUG 2774098Seric 2784078Seric if (user->q_mailer != M_LOCAL || bitset(QBADADDR, user->q_flags)) 2794098Seric return; 2804069Seric 2814069Seric /* good address -- look for .forward file in home */ 2824104Seric define('z', user->q_home); 2834081Seric (void) expand("$z/.forward", buf, &buf[sizeof buf - 1]); 2844069Seric fp = fopen(buf, "r"); 2854069Seric if (fp == NULL) 2864098Seric return; 2874069Seric 2884069Seric /* we do have an address to forward to -- do it */ 2894098Seric user->q_flags |= QDONTSEND; 2904081Seric (void) fgets(buf, sizeof buf, fp); 2914069Seric if ((p = index(buf, '\n')) != NULL) 2924069Seric *p = '\0'; 2934081Seric (void) fclose(fp); 2944069Seric if (buf[0] == '\0') 2954098Seric return; 2964069Seric if (Verbose) 2974069Seric message("050", "forwarded to %s", buf); 2984098Seric AliasLevel++; 2994069Seric sendto(buf, 1); 3004098Seric AliasLevel--; 3014098Seric return; 302292Seric } 303