1292Seric # include <stdio.h> 2292Seric # include <ctype.h> 3292Seric # include <pwd.h> 43309Seric # include "sendmail.h" 5292Seric 64106Seric # ifdef DBM 7*4157Seric static char SccsId[] = "@(#)alias.c 3.13 08/18/81 (with DBM)"; 84106Seric # else DBM 9*4157Seric static char SccsId[] = "@(#)alias.c 3.13 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; 54*4157Seric int dsize; 55*4157Seric } DATUM; 56*4157Seric DATUM lhs, rhs; 57*4157Seric 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. 122*4157Seric ** 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 133*4157Seric # define DBMMODE 0666 134*4157Seric 135*4157Seric initaliases(aliasfile, init) 1364098Seric char *aliasfile; 137*4157Seric bool init; 1384098Seric { 1394098Seric # ifdef DBM 140*4157Seric if (init) 141*4157Seric { 142*4157Seric char buf[MAXNAME]; 143*4157Seric 144*4157Seric (void) strcpy(buf, aliasfile); 145*4157Seric (void) strcat(buf, ".dir"); 146*4157Seric if (close(creat(buf, DBMMODE)) < 0) 147*4157Seric { 148*4157Seric syserr("cannot make %s", buf); 149*4157Seric return; 150*4157Seric } 151*4157Seric (void) strcpy(buf, aliasfile); 152*4157Seric (void) strcat(buf, ".pag"); 153*4157Seric if (close(creat(buf, DBMMODE)) < 0) 154*4157Seric { 155*4157Seric syserr("cannot make %s", buf); 156*4157Seric return; 157*4157Seric } 158*4157Seric } 1594098Seric dbminit(aliasfile); 160*4157Seric if (init) 161*4157Seric readaliases(aliasfile, TRUE); 1624098Seric # else DBM 163*4157Seric readaliases(aliasfile, init); 164*4157Seric # endif DBM 165*4157Seric } 166*4157Seric /* 167*4157Seric ** READALIASES -- read and process the alias file. 168*4157Seric ** 169*4157Seric ** This routine implements the part of initaliases that occurs 170*4157Seric ** when we are not going to use the DBM stuff. 171*4157Seric ** 172*4157Seric ** Parameters: 173*4157Seric ** aliasfile -- the pathname of the alias file master. 174*4157Seric ** init -- if set, initialize the DBM stuff. 175*4157Seric ** 176*4157Seric ** Returns: 177*4157Seric ** none. 178*4157Seric ** 179*4157Seric ** Side Effects: 180*4157Seric ** Reads aliasfile into the symbol table. 181*4157Seric ** Optionally, builds the .dir & .pag files. 182*4157Seric */ 183*4157Seric 184*4157Seric static 185*4157Seric readaliases(aliasfile, init) 186*4157Seric char *aliasfile; 187*4157Seric bool init; 188*4157Seric { 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 252*4157Seric if (init) 2534098Seric { 254*4157Seric /* do parsing & compression of addresses */ 2554098Seric c = *p; 256*4157Seric while (c != '\0') 2574098Seric { 258*4157Seric p2 = p; 259*4157Seric while (*p != '\n' && *p != ',' && *p != '\0') 260*4157Seric p++; 261*4157Seric c = *p; 262*4157Seric *p++ = '\0'; 263*4157Seric if (*p2 == '\0') 264*4157Seric { 265*4157Seric p[-1] = c; 266*4157Seric continue; 267*4157Seric } 268*4157Seric parse(p2, &bl, -1); 2694098Seric p[-1] = c; 270*4157Seric while (isspace(*p)) 271*4157Seric p++; 2724098Seric } 2734098Seric } 274*4157Seric else 275*4157Seric 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 } 295*4157Seric # ifdef DBM 296*4157Seric if (init) 297*4157Seric { 298*4157Seric DATUM key, content; 299*4157Seric 300*4157Seric key.dsize = strlen(al.q_user) + 1; 301*4157Seric key.dptr = al.q_user; 302*4157Seric content.dsize = strlen(rhs) + 1; 303*4157Seric content.dptr = rhs; 304*4157Seric store(key, content); 305*4157Seric } 306*4157Seric else 307*4157Seric # endif DBM 308*4157Seric { 309*4157Seric s = stab(al.q_user, ST_ALIAS, ST_ENTER); 310*4157Seric s->s_alias = newstr(rhs); 311*4157Seric } 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) 3634069Seric message("050", "forwarded to %s", buf); 3644098Seric AliasLevel++; 3654069Seric sendto(buf, 1); 3664098Seric AliasLevel--; 3674098Seric return; 368292Seric } 369