1292Seric # include <stdio.h> 2292Seric # include <ctype.h> 3292Seric # include <pwd.h> 43309Seric # include "sendmail.h" 5292Seric 6*4098Seric static char SccsId[] = "@(#)alias.c 3.10 08/10/81"; 7402Seric 8292Seric /* 9292Seric ** ALIAS -- Compute aliases. 10292Seric ** 11*4098Seric ** Scans the file /usr/lib/aliases for a set of aliases. 123185Seric ** If found, it arranges to deliver to them. Uses libdbm 133185Seric ** database if -DDBM. 14292Seric ** 15292Seric ** Parameters: 164097Seric ** a -- address to alias. 17292Seric ** 18292Seric ** Returns: 19292Seric ** none 20292Seric ** 21292Seric ** Side Effects: 223185Seric ** Aliases found are expanded. 23292Seric ** 24292Seric ** Files: 25*4098Seric ** /usr/lib/aliases -- the mail aliases. The format is 26569Seric ** a series of lines of the form: 27569Seric ** alias:name1,name2,name3,... 28569Seric ** where 'alias' expands to all of 29569Seric ** 'name[i]'. Continuations begin with 30569Seric ** space or tab. 31*4098Seric ** /usr/lib/aliases.pag, /usr/lib/aliases.dir: libdbm version 321503Smark ** of alias file. Keys are aliases, datums 331503Smark ** (data?) are name1,name2, ... 34292Seric ** 35292Seric ** Notes: 36292Seric ** If NoAlias (the "-n" flag) is set, no aliasing is 37292Seric ** done. 38292Seric ** 39292Seric ** Deficiencies: 40292Seric ** It should complain about names that are aliased to 41292Seric ** nothing. 42292Seric ** It is unsophisticated about line overflows. 43292Seric */ 44292Seric 45292Seric 461503Smark #ifdef DBM 472966Seric typedef struct 482966Seric { 492966Seric char *dptr; 502966Seric int dsize; 512966Seric } datum; 521503Smark datum lhs, rhs; 531515Seric extern datum fetch(); 541503Smark #endif DBM 55292Seric 564097Seric alias(a) 574097Seric register ADDRESS *a; 58292Seric { 594081Seric register char *p; 604081Seric # ifndef DBM 61*4098Seric register STAB *s; 624081Seric # endif DBM 63292Seric 64292Seric if (NoAlias) 65292Seric return; 66292Seric # ifdef DEBUG 67292Seric if (Debug) 68*4098Seric printf("alias(%s)\n", a->q_paddr); 69292Seric # endif 70292Seric 71*4098Seric /* don't realias already aliased names */ 72*4098Seric if (bitset(QDONTSEND, a->q_flags)) 73*4098Seric return; 74*4098Seric 75*4098Seric To = a->q_paddr; 76*4098Seric 774097Seric # ifdef DBM 78*4098Seric /* create a key for fetch */ 79*4098Seric lhs.dptr = a->q_user; 80*4098Seric lhs.dsize = strlen(a->q_user) + 1; 81*4098Seric rhs = fetch(lhs); 82*4098Seric 83*4098Seric /* find this alias? */ 84*4098Seric p = rhs.dptr; 85*4098Seric if (p == NULL) 86*4098Seric return; 87*4098Seric # else DBM 88*4098Seric s = stab(a->q_user, ST_ALIAS, ST_FIND); 89*4098Seric if (s == NULL) 90*4098Seric return; 91*4098Seric p = s->s_alias; 924097Seric # endif DBM 93292Seric 94292Seric /* 95*4098Seric ** Match on Alias. 96*4098Seric ** Deliver to the target list. 971515Seric */ 981515Seric 99*4098Seric # ifdef DEBUG 100*4098Seric if (Debug) 101*4098Seric printf("%s (%s, %s) aliased to %s\n", 102*4098Seric a->q_paddr, a->q_host, a->q_user, p); 103*4098Seric # endif 104*4098Seric if (Verbose) 105*4098Seric message("050", "aliased to %s", p); 106*4098Seric a->q_flags |= QDONTSEND; 107*4098Seric AliasLevel++; 108*4098Seric sendto(p, 1); 109*4098Seric AliasLevel--; 110*4098Seric } 111*4098Seric /* 112*4098Seric ** INITALIASES -- initialize for aliasing 113*4098Seric ** 114*4098Seric ** Very different depending on whether we are running DBM or not. 115*4098Seric ** 116*4098Seric ** Parameters: 117*4098Seric ** aliasfile -- location of aliases. 118*4098Seric ** 119*4098Seric ** Returns: 120*4098Seric ** none. 121*4098Seric ** 122*4098Seric ** Side Effects: 123*4098Seric ** initializes aliases: 124*4098Seric ** if DBM: opens the database. 125*4098Seric ** if ~DBM: reads the aliases into the symbol table. 126*4098Seric */ 127*4098Seric 128*4098Seric initaliases(aliasfile) 129*4098Seric char *aliasfile; 130*4098Seric { 131*4098Seric # ifdef DBM 132*4098Seric dbminit(aliasfile); 133*4098Seric # else DBM 134*4098Seric char line[BUFSIZ]; 135*4098Seric register char *p; 136*4098Seric char *p2; 137*4098Seric char *rhs; 138*4098Seric bool skipping; 139*4098Seric ADDRESS al, bl; 140*4098Seric extern char *prescan(); 141*4098Seric bool contin; 142*4098Seric 143*4098Seric if ((af = fopen(aliasfile, "r")) == NULL) 1441515Seric { 145*4098Seric # ifdef DEBUG 146*4098Seric if (Debug) 147*4098Seric printf("Can't open %s\n", AliasFile); 148*4098Seric # endif 149*4098Seric errno = 0; 150*4098Seric NoAlias++; 151*4098Seric return; 152*4098Seric } 153*4098Seric /* read and interpret lines */ 154*4098Seric lineno = 0; 155*4098Seric skipping = FALSE; 156*4098Seric while (fgets(line, sizeof (line), af) != NULL) 157*4098Seric { 158*4098Seric lineno++; 159*4098Seric switch (line[0]) 160*4098Seric { 161*4098Seric case '#': 162*4098Seric case '\n': 163*4098Seric case '\0': 164*4098Seric skipping = FALSE; 165*4098Seric continue; 1664065Seric 167*4098Seric case ' ': 168*4098Seric case '\t': 169*4098Seric if (!skipping) 170*4098Seric syserr("aliases: %d: Non-continuation line starts with space", lineno); 171*4098Seric skipping = TRUE; 1724097Seric continue; 173*4098Seric } 174*4098Seric skipping = FALSE; 1751874Seric 176*4098Seric /* process the LHS */ 177*4098Seric for (p = line; *p != '\0' && *p != ':' && *p != '\n'; p++) 1784097Seric continue; 179*4098Seric if (*p == '\0' || *p == '\n') 180*4098Seric { 181*4098Seric syntaxerr: 182*4098Seric syserr("aliases: %d: missing colon", lineno); 1834097Seric continue; 184*4098Seric } 185*4098Seric *p++ = '\0'; 186*4098Seric if (parse(line, &al, 1) == NULL) 187*4098Seric { 188*4098Seric *--p = ':'; 189*4098Seric goto syntaxerr; 190*4098Seric } 191*4098Seric rhs = p; 192*4098Seric contin = FALSE; 193*4098Seric for (;;) 194*4098Seric { 195*4098Seric register char c; 1961515Seric 197*4098Seric /* do parsing & compression of addresses */ 198*4098Seric c = *p; 199*4098Seric while (c != '\0') 200*4098Seric { 201*4098Seric p2 = p; 202*4098Seric while (*p != '\n' && *p != ',' && *p != '\0') 203*4098Seric p++; 204*4098Seric c = *p; 205*4098Seric *p++ = '\0'; 206*4098Seric if (*p2 == '\0') 207*4098Seric { 208*4098Seric p[-1] = c; 209*4098Seric continue; 210*4098Seric } 211*4098Seric parse(p2, &bl, -1); 212*4098Seric contin = (c == ','); 213*4098Seric p[-1] = c; 214*4098Seric while (isspace(*p)) 215*4098Seric p++; 216*4098Seric } 2171515Seric 218*4098Seric /* see if there should be a continuation line */ 219*4098Seric if (!contin) 220*4098Seric break; 221*4098Seric 222*4098Seric /* read continuation line */ 223*4098Seric p--; 224*4098Seric if (fgets(p, sizeof line - (p - line), af) == NULL) 225*4098Seric break; 226*4098Seric lineno++; 227*4098Seric 228*4098Seric if (!isspace(*p)) 229*4098Seric syserr("aliases: %d: continuation line missing", lineno); 230*4098Seric } 231*4098Seric if (al.q_mailer != M_LOCAL) 232*4098Seric { 233*4098Seric syserr("aliases: %d: cannot alias non-local names", lineno); 234*4098Seric continue; 235*4098Seric } 236*4098Seric s = stab(al.q_user, ST_ALIAS, rhs); 2371515Seric } 238*4098Seric (void) fclose(af); 239*4098Seric # endif DBM 240292Seric } 241292Seric /* 242292Seric ** FORWARD -- Try to forward mail 243292Seric ** 244292Seric ** This is similar but not identical to aliasing. 245292Seric ** 246292Seric ** Parameters: 247292Seric ** user -- the name of the user who's mail we 248292Seric ** would like to forward to. 249292Seric ** 250292Seric ** Returns: 251*4098Seric ** none. 252292Seric ** 253292Seric ** Side Effects: 2543185Seric ** New names are added to send queues. 255*4098Seric ** Sets the QDONTSEND bit in addresses that are forwarded. 256292Seric */ 257292Seric 258292Seric forward(user) 2592966Seric ADDRESS *user; 260292Seric { 2614078Seric char buf[60]; 2624069Seric register FILE *fp; 2634069Seric register char *p; 2644069Seric 265*4098Seric # ifdef DEBUG 266*4098Seric if (Debug) 267*4098Seric printf("forward(%s)\n", user->q_paddr); 268*4098Seric # endif DEBUG 269*4098Seric 2704078Seric if (user->q_mailer != M_LOCAL || bitset(QBADADDR, user->q_flags)) 271*4098Seric return; 2724069Seric 2734069Seric /* good address -- look for .forward file in home */ 2744081Seric (void) expand("$z/.forward", buf, &buf[sizeof buf - 1]); 2754069Seric fp = fopen(buf, "r"); 2764069Seric if (fp == NULL) 277*4098Seric return; 2784069Seric 2794069Seric /* we do have an address to forward to -- do it */ 280*4098Seric user->q_flags |= QDONTSEND; 2814081Seric (void) fgets(buf, sizeof buf, fp); 2824069Seric if ((p = index(buf, '\n')) != NULL) 2834069Seric *p = '\0'; 2844081Seric (void) fclose(fp); 2854069Seric if (buf[0] == '\0') 286*4098Seric return; 2874069Seric if (Verbose) 2884069Seric message("050", "forwarded to %s", buf); 289*4098Seric AliasLevel++; 2904069Seric sendto(buf, 1); 291*4098Seric AliasLevel--; 292*4098Seric return; 293292Seric } 294