Annotation of 42BSD/usr.lib/sendmail/src/alias.c, revision 1.1.1.1

1.1       root        1: # include <pwd.h>
                      2: # include <sys/types.h>
                      3: # include <sys/stat.h>
                      4: # include <signal.h>
                      5: # include "sendmail.h"
                      6: 
                      7: # ifdef DBM
                      8: SCCSID(@(#)alias.c     4.1             7/25/83 (with DBM));
                      9: # else DBM
                     10: SCCSID(@(#)alias.c     4.1             7/25/83 (without DBM));
                     11: # endif DBM
                     12: 
                     13: /*
                     14: **  ALIAS -- Compute aliases.
                     15: **
                     16: **     Scans the alias file for an alias for the given address.
                     17: **     If found, it arranges to deliver to the alias list instead.
                     18: **     Uses libdbm database if -DDBM.
                     19: **
                     20: **     Parameters:
                     21: **             a -- address to alias.
                     22: **             sendq -- a pointer to the head of the send queue
                     23: **                     to put the aliases in.
                     24: **
                     25: **     Returns:
                     26: **             none
                     27: **
                     28: **     Side Effects:
                     29: **             Aliases found are expanded.
                     30: **
                     31: **     Notes:
                     32: **             If NoAlias (the "-n" flag) is set, no aliasing is
                     33: **                     done.
                     34: **
                     35: **     Deficiencies:
                     36: **             It should complain about names that are aliased to
                     37: **                     nothing.
                     38: */
                     39: 
                     40: 
                     41: #ifdef DBM
                     42: typedef struct
                     43: {
                     44:        char    *dptr;
                     45:        int     dsize;
                     46: } DATUM;
                     47: extern DATUM fetch();
                     48: #endif DBM
                     49: 
                     50: alias(a, sendq)
                     51:        register ADDRESS *a;
                     52:        ADDRESS **sendq;
                     53: {
                     54:        register char *p;
                     55:        extern char *aliaslookup();
                     56: 
                     57:        if (NoAlias)
                     58:                return;
                     59: # ifdef DEBUG
                     60:        if (tTd(27, 1))
                     61:                printf("alias(%s)\n", a->q_paddr);
                     62: # endif
                     63: 
                     64:        /* don't realias already aliased names */
                     65:        if (bitset(QDONTSEND, a->q_flags))
                     66:                return;
                     67: 
                     68:        CurEnv->e_to = a->q_paddr;
                     69: 
                     70:        /*
                     71:        **  Look up this name
                     72:        */
                     73: 
                     74:        p = aliaslookup(a->q_user);
                     75:        if (p == NULL)
                     76:                return;
                     77: 
                     78:        /*
                     79:        **  Match on Alias.
                     80:        **      Deliver to the target list.
                     81:        */
                     82: 
                     83: # ifdef DEBUG
                     84:        if (tTd(27, 1))
                     85:                printf("%s (%s, %s) aliased to %s\n",
                     86:                    a->q_paddr, a->q_host, a->q_user, p);
                     87: # endif
                     88:        message(Arpa_Info, "aliased to %s", p);
                     89:        AliasLevel++;
                     90:        sendtolist(p, a, sendq);
                     91:        AliasLevel--;
                     92: }
                     93: /*
                     94: **  ALIASLOOKUP -- look up a name in the alias file.
                     95: **
                     96: **     Parameters:
                     97: **             name -- the name to look up.
                     98: **
                     99: **     Returns:
                    100: **             the value of name.
                    101: **             NULL if unknown.
                    102: **
                    103: **     Side Effects:
                    104: **             none.
                    105: **
                    106: **     Warnings:
                    107: **             The return value will be trashed across calls.
                    108: */
                    109: 
                    110: char *
                    111: aliaslookup(name)
                    112:        char *name;
                    113: {
                    114: # ifdef DBM
                    115:        DATUM rhs, lhs;
                    116: 
                    117:        /* create a key for fetch */
                    118:        lhs.dptr = name;
                    119:        lhs.dsize = strlen(name) + 1;
                    120:        rhs = fetch(lhs);
                    121:        return (rhs.dptr);
                    122: # else DBM
                    123:        register STAB *s;
                    124: 
                    125:        s = stab(name, ST_ALIAS, ST_FIND);
                    126:        if (s == NULL)
                    127:                return (NULL);
                    128:        return (s->s_alias);
                    129: # endif DBM
                    130: }
                    131: /*
                    132: **  INITALIASES -- initialize for aliasing
                    133: **
                    134: **     Very different depending on whether we are running DBM or not.
                    135: **
                    136: **     Parameters:
                    137: **             aliasfile -- location of aliases.
                    138: **             init -- if set and if DBM, initialize the DBM files.
                    139: **
                    140: **     Returns:
                    141: **             none.
                    142: **
                    143: **     Side Effects:
                    144: **             initializes aliases:
                    145: **             if DBM:  opens the database.
                    146: **             if ~DBM: reads the aliases into the symbol table.
                    147: */
                    148: 
                    149: # define DBMMODE       0666
                    150: 
                    151: initaliases(aliasfile, init)
                    152:        char *aliasfile;
                    153:        bool init;
                    154: {
                    155: #ifdef DBM
                    156:        int atcnt;
                    157:        char buf[MAXNAME];
                    158:        time_t modtime;
                    159:        int (*oldsigint)();
                    160: #endif DBM
                    161:        struct stat stb;
                    162: 
                    163:        if (stat(aliasfile, &stb) < 0)
                    164:        {
                    165:                NoAlias = TRUE;
                    166:                errno = 0;
                    167:                return;
                    168:        }
                    169: 
                    170: # ifdef DBM
                    171:        /*
                    172:        **  Check to see that the alias file is complete.
                    173:        **      If not, we will assume that someone died, and it is up
                    174:        **      to us to rebuild it.
                    175:        */
                    176: 
                    177:        dbminit(aliasfile);
                    178:        atcnt = 10;
                    179:        while (SafeAlias && !init && atcnt-- >= 0 && aliaslookup("@") == NULL)
                    180:                sleep(30);
                    181: 
                    182:        /*
                    183:        **  See if the DBM version of the file is out of date with
                    184:        **  the text version.  If so, go into 'init' mode automatically.
                    185:        **      This only happens if our effective userid owns the DBM
                    186:        **      version or if the mode of the database is 666 -- this
                    187:        **      is an attempt to avoid protection problems.  Note the
                    188:        **      unpalatable hack to see if the stat succeeded.
                    189:        */
                    190: 
                    191:        modtime = stb.st_mtime;
                    192:        (void) strcpy(buf, aliasfile);
                    193:        (void) strcat(buf, ".pag");
                    194:        stb.st_ino = 0;
                    195:        if (!init && (atcnt < 0 || stat(buf, &stb) < 0 || stb.st_mtime < modtime))
                    196:        {
                    197:                errno = 0;
                    198:                if (AutoRebuild && stb.st_ino != 0 &&
                    199:                    ((stb.st_mode & 0777) == 0666 || stb.st_uid == geteuid()))
                    200:                {
                    201:                        init = TRUE;
                    202:                        message(Arpa_Info, "rebuilding alias database");
                    203:                }
                    204:                else
                    205:                {
                    206:                        bool oldverb = Verbose;
                    207: 
                    208:                        Verbose = TRUE;
                    209:                        message(Arpa_Info, "Warning: alias database out of date");
                    210:                        Verbose = oldverb;
                    211:                }
                    212:        }
                    213: 
                    214:        /*
                    215:        **  If initializing, create the new files.
                    216:        **      We should lock the alias file here to prevent other
                    217:        **      instantiations of sendmail from reading an incomplete
                    218:        **      file -- or worse yet, doing a concurrent initialize.
                    219:        */
                    220: 
                    221:        if (init)
                    222:        {
                    223:                oldsigint = signal(SIGINT, SIG_IGN);
                    224:                (void) strcpy(buf, aliasfile);
                    225:                (void) strcat(buf, ".dir");
                    226:                if (close(creat(buf, DBMMODE)) < 0)
                    227:                {
                    228:                        syserr("cannot make %s", buf);
                    229:                        (void) signal(SIGINT, oldsigint);
                    230:                        return;
                    231:                }
                    232:                (void) strcpy(buf, aliasfile);
                    233:                (void) strcat(buf, ".pag");
                    234:                if (close(creat(buf, DBMMODE)) < 0)
                    235:                {
                    236:                        syserr("cannot make %s", buf);
                    237:                        (void) signal(SIGINT, oldsigint);
                    238:                        return;
                    239:                }
                    240:        }
                    241: 
                    242:        /*
                    243:        **  If necessary, load the DBM file.
                    244:        **      If running without DBM, load the symbol table.
                    245:        **      After loading the DBM file, add the distinquished alias "@".
                    246:        */
                    247: 
                    248:        if (init)
                    249:        {
                    250:                DATUM key;
                    251: 
                    252:                readaliases(aliasfile, TRUE);
                    253:                key.dsize = 2;
                    254:                key.dptr = "@";
                    255:                store(key, key);
                    256:                (void) signal(SIGINT, oldsigint);
                    257:        }
                    258: # else DBM
                    259:        readaliases(aliasfile, init);
                    260: # endif DBM
                    261: }
                    262: /*
                    263: **  READALIASES -- read and process the alias file.
                    264: **
                    265: **     This routine implements the part of initaliases that occurs
                    266: **     when we are not going to use the DBM stuff.
                    267: **
                    268: **     Parameters:
                    269: **             aliasfile -- the pathname of the alias file master.
                    270: **             init -- if set, initialize the DBM stuff.
                    271: **
                    272: **     Returns:
                    273: **             none.
                    274: **
                    275: **     Side Effects:
                    276: **             Reads aliasfile into the symbol table.
                    277: **             Optionally, builds the .dir & .pag files.
                    278: */
                    279: 
                    280: static
                    281: readaliases(aliasfile, init)
                    282:        char *aliasfile;
                    283:        bool init;
                    284: {
                    285:        register char *p;
                    286:        char *p2;
                    287:        char *rhs;
                    288:        bool skipping;
                    289:        int naliases, bytes, longest;
                    290:        FILE *af;
                    291:        ADDRESS al, bl;
                    292:        register STAB *s;
                    293:        char line[BUFSIZ];
                    294: 
                    295:        if ((af = fopen(aliasfile, "r")) == NULL)
                    296:        {
                    297: # ifdef DEBUG
                    298:                if (tTd(27, 1))
                    299:                        printf("Can't open %s\n", aliasfile);
                    300: # endif
                    301:                errno = 0;
                    302:                NoAlias++;
                    303:                return;
                    304:        }
                    305: 
                    306:        /*
                    307:        **  Read and interpret lines
                    308:        */
                    309: 
                    310:        FileName = aliasfile;
                    311:        LineNumber = 0;
                    312:        naliases = bytes = longest = 0;
                    313:        skipping = FALSE;
                    314:        while (fgets(line, sizeof (line), af) != NULL)
                    315:        {
                    316:                int lhssize, rhssize;
                    317: 
                    318:                LineNumber++;
                    319:                switch (line[0])
                    320:                {
                    321:                  case '#':
                    322:                  case '\n':
                    323:                  case '\0':
                    324:                        skipping = FALSE;
                    325:                        continue;
                    326: 
                    327:                  case ' ':
                    328:                  case '\t':
                    329:                        if (!skipping)
                    330:                                syserr("Non-continuation line starts with space");
                    331:                        skipping = TRUE;
                    332:                        continue;
                    333:                }
                    334:                skipping = FALSE;
                    335: 
                    336:                /*
                    337:                **  Process the LHS
                    338:                **      Find the final colon, and parse the address.
                    339:                **      It should resolve to a local name -- this will
                    340:                **      be checked later (we want to optionally do
                    341:                **      parsing of the RHS first to maximize error
                    342:                **      detection).
                    343:                */
                    344: 
                    345:                for (p = line; *p != '\0' && *p != ':' && *p != '\n'; p++)
                    346:                        continue;
                    347:                if (*p++ != ':')
                    348:                {
                    349:                        syserr("missing colon");
                    350:                        continue;
                    351:                }
                    352:                if (parseaddr(line, &al, 1, ':') == NULL)
                    353:                {
                    354:                        syserr("illegal alias name");
                    355:                        continue;
                    356:                }
                    357: 
                    358:                /*
                    359:                **  Process the RHS.
                    360:                **      'al' is the internal form of the LHS address.
                    361:                **      'p' points to the text of the RHS.
                    362:                */
                    363: 
                    364:                rhs = p;
                    365:                for (;;)
                    366:                {
                    367:                        register char c;
                    368: 
                    369:                        if (init)
                    370:                        {
                    371:                                /* do parsing & compression of addresses */
                    372:                                c = *p;
                    373:                                while (c != '\0')
                    374:                                {
                    375:                                        p2 = p;
                    376:                                        while (*p != '\n' && *p != ',' && *p != '\0')
                    377:                                                p++;
                    378:                                        c = *p;
                    379:                                        *p++ = '\0';
                    380:                                        if (c == '\n')
                    381:                                                c = '\0';
                    382:                                        if (*p2 == '\0')
                    383:                                        {
                    384:                                                p[-1] = c;
                    385:                                                continue;
                    386:                                        }
                    387:                                        (void) parseaddr(p2, &bl, -1, ',');
                    388:                                        p[-1] = c;
                    389:                                        while (isspace(*p))
                    390:                                                p++;
                    391:                                }
                    392:                        }
                    393:                        else
                    394:                                p = &p[strlen(p)];
                    395: 
                    396:                        /* see if there should be a continuation line */
                    397:                        c = fgetc(af);
                    398:                        if (!feof(af))
                    399:                                (void) ungetc(c, af);
                    400:                        if (c != ' ' && c != '\t')
                    401:                                break;
                    402: 
                    403:                        /* read continuation line */
                    404:                        p--;
                    405:                        if (fgets(p, sizeof line - (p - line), af) == NULL)
                    406:                                break;
                    407:                        LineNumber++;
                    408:                }
                    409:                if (al.q_mailer != LocalMailer)
                    410:                {
                    411:                        syserr("cannot alias non-local names");
                    412:                        continue;
                    413:                }
                    414: 
                    415:                /*
                    416:                **  Insert alias into symbol table or DBM file
                    417:                */
                    418: 
                    419:                lhssize = strlen(al.q_user) + 1;
                    420:                rhssize = strlen(rhs) + 1;
                    421: 
                    422: # ifdef DBM
                    423:                if (init)
                    424:                {
                    425:                        DATUM key, content;
                    426: 
                    427:                        key.dsize = lhssize;
                    428:                        key.dptr = al.q_user;
                    429:                        content.dsize = rhssize;
                    430:                        content.dptr = rhs;
                    431:                        store(key, content);
                    432:                }
                    433:                else
                    434: # endif DBM
                    435:                {
                    436:                        s = stab(al.q_user, ST_ALIAS, ST_ENTER);
                    437:                        s->s_alias = newstr(rhs);
                    438:                }
                    439: 
                    440:                /* statistics */
                    441:                naliases++;
                    442:                bytes += lhssize + rhssize;
                    443:                if (rhssize > longest)
                    444:                        longest = rhssize;
                    445:        }
                    446:        (void) fclose(af);
                    447:        CurEnv->e_to = NULL;
                    448:        FileName = NULL;
                    449:        message(Arpa_Info, "%d aliases, longest %d bytes, %d bytes total",
                    450:                        naliases, longest, bytes);
                    451: }
                    452: /*
                    453: **  FORWARD -- Try to forward mail
                    454: **
                    455: **     This is similar but not identical to aliasing.
                    456: **
                    457: **     Parameters:
                    458: **             user -- the name of the user who's mail we would like
                    459: **                     to forward to.  It must have been verified --
                    460: **                     i.e., the q_home field must have been filled
                    461: **                     in.
                    462: **             sendq -- a pointer to the head of the send queue to
                    463: **                     put this user's aliases in.
                    464: **
                    465: **     Returns:
                    466: **             none.
                    467: **
                    468: **     Side Effects:
                    469: **             New names are added to send queues.
                    470: */
                    471: 
                    472: forward(user, sendq)
                    473:        ADDRESS *user;
                    474:        ADDRESS **sendq;
                    475: {
                    476:        char buf[60];
                    477:        extern bool safefile();
                    478: 
                    479: # ifdef DEBUG
                    480:        if (tTd(27, 1))
                    481:                printf("forward(%s)\n", user->q_paddr);
                    482: # endif DEBUG
                    483: 
                    484:        if (user->q_mailer != LocalMailer || bitset(QBADADDR, user->q_flags))
                    485:                return;
                    486: # ifdef DEBUG
                    487:        if (user->q_home == NULL)
                    488:                syserr("forward: no home");
                    489: # endif DEBUG
                    490: 
                    491:        /* good address -- look for .forward file in home */
                    492:        define('z', user->q_home, CurEnv);
                    493:        expand("$z/.forward", buf, &buf[sizeof buf - 1], CurEnv);
                    494:        if (!safefile(buf, user->q_uid, S_IREAD))
                    495:                return;
                    496: 
                    497:        /* we do have an address to forward to -- do it */
                    498:        include(buf, "forwarding", user, sendq);
                    499: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.