Annotation of coherent/a/tmp/smail/alias.c, revision 1.1

1.1     ! root        1: #ifndef lint
        !             2: static char *sccsid = "@(#)alias.c     2.5 (smail) 9/15/87";
        !             3: #endif
        !             4: 
        !             5: #include <stdio.h>
        !             6: #include <sys/types.h>
        !             7: #include <sys/stat.h>
        !             8: #include <pwd.h>
        !             9: #include "defs.h"
        !            10: #include <ctype.h>
        !            11: 
        !            12: extern enum edebug debug;      /* verbose and debug modes              */
        !            13: extern char hostdomain[];
        !            14: extern char hostname[];
        !            15: extern char *aliasfile;
        !            16: #ifdef HOMEALIASES
        !            17: extern char *homealias;
        !            18: #endif /* HOMEALIASES */
        !            19: 
        !            20: /*
        !            21: **
        !            22: ** Picture of the alias graph structure
        !            23: **
        !            24: **     head
        !            25: **       |
        !            26: **       v
        !            27: **     maps -> mark -> gjm -> mel -> NNULL
        !            28: **       |
        !            29: **       v
        !            30: **     sys ->  root -> ron -> NNULL
        !            31: **       |
        !            32: **       v
        !            33: **     root -> mark -> chris -> lda -> NNULL
        !            34: **       |
        !            35: **       v
        !            36: **      NNULL
        !            37: */
        !            38: 
        !            39: typedef struct alias_node node;
        !            40: 
        !            41: static struct alias_node {
        !            42:        char *string;
        !            43:        node *horz;
        !            44:        node *vert;
        !            45: };
        !            46: 
        !            47: #ifndef SENDMAIL
        !            48: static node aliases = {"", 0, 0}; /* this is the 'dummy header' */
        !            49: #endif /* not SENDMAIL */
        !            50: 
        !            51: /*
        !            52: ** lint free forms of NULL
        !            53: */
        !            54: 
        !            55: #define NNULL  ((node   *) 0)
        !            56: #define CNULL  ('\0')
        !            57: 
        !            58: #define TRUE ((int) (1==1))
        !            59: #define FALSE ((int) (1==2))
        !            60: /*
        !            61: ** string parsing macros
        !            62: */
        !            63: #define SKIPWORD(Z)  while(*Z!=' ' && *Z!='\t' && *Z!='\n' && *Z!=',') Z++;
        !            64: #define SKIPSPACE(Z) while(*Z==' ' || *Z=='\t' || *Z=='\n' || *Z==',') Z++;
        !            65: 
        !            66: static int nargc = 0;
        !            67: static char *nargv[MAXARGS];
        !            68: static int no_backslash = TRUE;
        !            69: static int last_no_backslash = TRUE;
        !            70: 
        !            71: void   add_horz();
        !            72: void   load_alias(), strip_comments();
        !            73: int    recipients();
        !            74: node   *pop();
        !            75: #ifndef SENDMAIL
        !            76: node   *v_search(), *h_search();
        !            77: char   *tilde();
        !            78: #endif /* not SENDMAIL */
        !            79: 
        !            80: /* our horizontal linked list looks like a stack */
        !            81: #define push           add_horz
        !            82: 
        !            83: #define escape(s)      ((*s != '\\') ? (s) : (s+1))
        !            84: 
        !            85: char **
        !            86: alias(pargc, argv)
        !            87: int *pargc;
        !            88: char **argv;
        !            89: {
        !            90: /*
        !            91: **  alias the addresses
        !            92: */
        !            93:        int     i;
        !            94:        char    domain[SMLBUF], ubuf[SMLBUF], *user;
        !            95:        node    *addr, addrstk;
        !            96:        node    *flist,  fliststk, *u;
        !            97: 
        !            98: #ifndef SENDMAIL
        !            99:        FILE    *fp;
        !           100:        node    *a;
        !           101:        char    *home, buf[SMLBUF];
        !           102:        int     aliased;
        !           103:        struct  stat st;
        !           104: #endif /* not SENDMAIL */
        !           105: 
        !           106: #ifdef FULLNAME
        !           107:        char *res_fname();      /* Does fullname processing */
        !           108: #endif
        !           109: 
        !           110:        addr  = &addrstk;
        !           111:        flist = &fliststk;
        !           112:        user  = ubuf;
        !           113: 
        !           114:        addr->horz = NNULL;
        !           115:        flist->horz  = NNULL;
        !           116: 
        !           117:        /*
        !           118:        ** push all of the addresses onto a stack
        !           119:        */
        !           120:        for(i=0; i < *pargc; i++) {
        !           121:                push(addr, argv[i]);
        !           122:        }
        !           123: 
        !           124:        /*
        !           125:        ** for each adress, check for included files, aliases,
        !           126:        ** full name mapping, and .forward files
        !           127:        */
        !           128: 
        !           129:        while((nargc < MAXARGS) && ((u = pop(addr)) != NNULL)) {
        !           130: #ifndef SENDMAIL
        !           131:                if(strncmpic(u->string, ":include:", 9) == 0) {
        !           132:                        /*
        !           133:                        ** make sure it's a full path name
        !           134:                        ** don't allow multiple sourcing
        !           135:                        ** of a given include file
        !           136:                        */
        !           137:                        char *p = u->string + 9;
        !           138: 
        !           139:                        if((*p == '/')
        !           140:                        && (h_search(flist, p) == NULL)) {
        !           141:                                push(flist, p);
        !           142:                                if((stat(p, &st) >= 0)
        !           143:                                &&((st.st_mode & S_IFMT) == S_IFREG)
        !           144:                                &&((fp = fopen(p, "r")) != NULL)) {
        !           145:                                        while(fgets(buf, sizeof buf, fp)) {
        !           146:                                                (void) recipients(addr, buf);
        !           147:                                        }
        !           148:                                        (void) fclose(fp);
        !           149:                                }
        !           150:                        }
        !           151:                        continue;
        !           152:                }
        !           153: #endif /* not SENDMAIL */
        !           154:                /*
        !           155:                ** parse the arg to see if it's to be aliased
        !           156:                */
        !           157: 
        !           158:                if(islocal(u->string, domain, ubuf) == 0) {
        !           159:                        goto aliasing_complete;
        !           160:                }
        !           161: 
        !           162:                /*
        !           163:                ** local form - try to alias user
        !           164:                ** aliases file takes precedence over ~user/.forward
        !           165:                ** since that's the way that sendmail does it.
        !           166:                */
        !           167: 
        !           168: #ifdef LOWERLOGNAME
        !           169:                /* squish 'user' into lower case */
        !           170:                for(user = ubuf; *user ; user++) {
        !           171:                        *user = lower(*user);
        !           172:                }
        !           173: #endif
        !           174:                user = escape(ubuf);
        !           175: 
        !           176:                (void) strcpy(u->string, user); /* local => elide domain */
        !           177: #ifndef SENDMAIL
        !           178:                /*
        !           179:                ** check for alias - all this complication is necessary
        !           180:                ** to handle perverted aliases like these:
        !           181:                ** # mail to 's' resolves to 't' 'm' and 'rmt!j'
        !           182:                ** s    t,g,j,m
        !           183:                ** g    j,m
        !           184:                ** j    rmt!j
        !           185:                ** # mail to 'a' resolves to 'rmt!d'
        !           186:                ** a    b c
        !           187:                ** b    c
        !           188:                ** c    rmt!d
        !           189:                ** # mail to x resolves to 'x'
        !           190:                ** x    local!x
        !           191:                ** # mail to 'y' resolves to 'y' and 'z'
        !           192:                ** y    \y z
        !           193:                */
        !           194:                if(((a = v_search(user)) != NNULL)) {
        !           195:                        char dtmpb[SMLBUF], utmpb[SMLBUF], *ut;
        !           196:                        int user_inalias = 0;
        !           197:                        node *t = a;
        !           198: 
        !           199:                        for(a = a->horz; a != NNULL; a=a->horz) {
        !           200:                                if(islocal(a->string, dtmpb, utmpb)) {
        !           201: #ifdef LOWERLOGNAME
        !           202:                                        /* squish 'utmpb' into lower case */
        !           203:                                        for(ut = utmpb; *ut ; ut++) {
        !           204:                                                *ut = lower(*ut);
        !           205:                                        }
        !           206: #endif
        !           207: 
        !           208:                                        ut = escape(utmpb);
        !           209: #ifdef CASEALIAS
        !           210:                                        if(strcmp(ut, user) == 0)
        !           211: #else
        !           212:                                        if(strcmpic(ut, user) == 0)
        !           213: #endif
        !           214:                                        {
        !           215:                                                user_inalias = 1;
        !           216:                                        } else {
        !           217:                                                push(addr, a->string);
        !           218:                                        }
        !           219:                                } else {
        !           220:                                        push(addr, a->string);
        !           221:                                }
        !           222:                        }
        !           223:                        t->horz = NNULL; /* truncate horz list of aliases */
        !           224:                        if(user_inalias == 0) {
        !           225:                                continue;
        !           226:                        }
        !           227:                }
        !           228: 
        !           229:                if((home = tilde(user)) != NULL) {
        !           230:                        /* don't allow multiple sourcing
        !           231:                        ** of a given .forward file
        !           232:                        */
        !           233: 
        !           234:                        if((h_search(flist, home) != NULL)) {
        !           235:                                continue;
        !           236:                        }
        !           237:                        push(flist, home);
        !           238: 
        !           239:                        /*
        !           240:                        ** check for ~user/.forward file
        !           241:                        ** must be a regular, readable file
        !           242:                        */
        !           243: 
        !           244:                        (void) sprintf(buf, "%s/%s", home, ".forward");
        !           245:                        if((stat(buf, &st) >= 0)
        !           246:                        &&((st.st_mode & S_IFMT) == S_IFREG)
        !           247:                        &&((st.st_mode & 0444)   == 0444)
        !           248:                        &&((fp = fopen(buf, "r")) != NULL)) {
        !           249:                                aliased = 0;
        !           250:                                while(fgets(buf, sizeof buf, fp)) {
        !           251:                                        aliased |= recipients(addr, buf);
        !           252:                                }
        !           253:                                (void) fclose(fp);
        !           254:                                if(aliased) {
        !           255:                                        continue;
        !           256:                                }
        !           257:                        }
        !           258:                }
        !           259: #endif /* not SENDMAIL */
        !           260: 
        !           261: #ifdef FULLNAME
        !           262:                /*
        !           263:                ** Do possible fullname substitution.
        !           264:                */
        !           265: #ifdef DOT_REQD
        !           266:                if (index(user, '.') != NULL)
        !           267: #endif
        !           268:                {
        !           269:                        static char t_dom[SMLBUF], t_unam[SMLBUF];
        !           270:                        char *t_user = res_fname(user);
        !           271:                        if (t_user != NULL) {
        !           272:                                if(islocal(t_user, t_dom, t_unam) == 0) {
        !           273:                                        /* aliased to non-local address */
        !           274:                                        push(addr, t_user);
        !           275:                                        continue;
        !           276:                                }
        !           277:                                if(strcmp(t_unam, user) != 0) {
        !           278:                                        /* aliased to different local address */
        !           279:                                        push(addr, t_unam);
        !           280:                                        continue;
        !           281:                                }
        !           282:                        }
        !           283:                }
        !           284: #endif
        !           285: 
        !           286: aliasing_complete:
        !           287:                user = escape(u->string);
        !           288:                for(i=0; i < nargc; i++) {
        !           289: #ifdef CASEALIAS
        !           290:                        if(strcmp(nargv[i], user) == 0) {
        !           291: #else
        !           292:                        if(strcmpic(nargv[i], user) == 0) {
        !           293: #endif
        !           294:                                break;
        !           295:                        }
        !           296:                }
        !           297: 
        !           298:                if(i == nargc) {
        !           299:                        nargv[nargc++] = user;
        !           300:                }
        !           301:        }
        !           302:        *pargc     = nargc;
        !           303:        return(nargv);
        !           304: }
        !           305: 
        !           306: #ifndef SENDMAIL
        !           307: /*
        !           308: ** v_search
        !           309: **     given an string, look for its alias in
        !           310: **     the 'vertical' linked list of aliases.
        !           311: */
        !           312: node *
        !           313: v_search(user)
        !           314: char *user;
        !           315: {
        !           316:        node *head;
        !           317:        node *a;
        !           318:        static int loaded = 0;
        !           319: 
        !           320:        head = &aliases;
        !           321:        if(loaded == 0) {
        !           322:                load_alias(head, aliasfile);
        !           323: #ifdef HOMEALIASES
        !           324:                /* Load $HOME/.aliases if there is one.  */
        !           325:                /* NB:  Security problem if aliases can pipe to programs.  */
        !           326:                if (( homealias = getenv("HOME") ) != NULL ) {
        !           327:                        FILE *fp;
        !           328: 
        !           329:                        strcat(homealias, HOMEALIASES);
        !           330:                        /* This fopen is just an existence and perm check.  */
        !           331:                        if((fp = fopen(homealias,"r")) != NULL) {
        !           332:                                fclose(fp);
        !           333:                                load_alias(head, homealias);
        !           334:                        } else {
        !           335:                                fclose(fp);
        !           336:                        }
        !           337:                }
        !           338: #endif
        !           339:                loaded = 1;
        !           340:        }
        !           341: 
        !           342:        for(a = head->vert; a != NNULL; a = a->vert) {
        !           343: #ifdef CASEALIAS
        !           344:                if(strcmp(a->string, user) == 0)
        !           345: #else
        !           346:                if(strcmpic(a->string, user) == 0)
        !           347: #endif
        !           348:                {
        !           349:                        break;
        !           350:                }
        !           351:        }
        !           352:        if(a == NNULL) {                /* not in graph */
        !           353:                return(NNULL);
        !           354:        }
        !           355:        return(a);
        !           356: }
        !           357: 
        !           358: /*
        !           359: ** h_search
        !           360: **     given an string, look for it in
        !           361: **     a 'horizontal' linked list of strings.
        !           362: */
        !           363: node *
        !           364: h_search(head, str)
        !           365: node *head;
        !           366: char *str;
        !           367: {
        !           368:        node *a;
        !           369:        for(a = head->horz; a != NNULL; a = a->horz) {
        !           370: #ifdef CASEALIAS
        !           371:                if(strcmp(a->string, str) == 0)
        !           372: #else
        !           373:                if(strcmpic(a->string, str) == 0)
        !           374: #endif
        !           375:                {
        !           376:                        break;
        !           377:                }
        !           378:        }
        !           379:        return(a);
        !           380: }
        !           381: #endif /* not SENDMAIL */
        !           382: 
        !           383: /*
        !           384: ** load_alias
        !           385: **     parse an 'aliases' file and add the aliases to the alias graph.
        !           386: **     Handle inclusion of other 'aliases' files.
        !           387: */
        !           388: 
        !           389: void
        !           390: load_alias(head, filename)
        !           391: node *head;
        !           392: char *filename;
        !           393: {
        !           394:        FILE *fp;
        !           395:        node *v, *h, *add_vert();
        !           396:        char domain[SMLBUF], user[SMLBUF];
        !           397:        char *p, *b, buf[SMLBUF];
        !           398: 
        !           399:        if((fp = fopen(filename,"r")) == NULL) {
        !           400: DEBUG("load_alias open('%s') failed\n", filename);
        !           401:                return;
        !           402:        }
        !           403: 
        !           404:        while(fgets(buf, sizeof buf, fp) != NULL) {
        !           405:                p = buf;
        !           406: 
        !           407:                /* Check for trailing \, mark for later.  */
        !           408:                no_backslash = last_no_backslash;
        !           409:                if(strlen(p) > 0) {
        !           410:                        if(p[strlen(p) - 2 ] == '\\') {
        !           411:                                last_no_backslash = FALSE;
        !           412:                        } else {
        !           413:                                last_no_backslash = TRUE;
        !           414:                        }
        !           415:                } else {
        !           416:                        last_no_backslash = TRUE;
        !           417:                } /* check for trailing \ */
        !           418: 
        !           419:                if((*p == '#') || (*p == '\n')) {
        !           420:                        continue;
        !           421:                }
        !           422: 
        !           423:                /*
        !           424:                ** include another file of aliases
        !           425:                */
        !           426: 
        !           427:                if(strncmp(p, ":include:", 9) == 0) {
        !           428:                        char *nl;
        !           429:                        p += 9;
        !           430:                        if((nl = index(p, '\n')) != NULL) {
        !           431:                                *nl = CNULL;
        !           432:                        }
        !           433: DEBUG("load_alias '%s' includes file '%s'\n", filename, p);
        !           434:                        load_alias(head, p);
        !           435:                        continue; /* bug? line truncated after :include: */
        !           436:                }
        !           437: 
        !           438:                /*
        !           439:                **  if the first char on the line is a space or tab
        !           440:                **  or the last character of the last line was a '\'
        !           441:                **  then it's a continuation line.  Otherwise,
        !           442:                **  we start a new alias.
        !           443:                */
        !           444:                if(*p != ' ' && *p != '\t' && no_backslash) {
        !           445:                        b = p;
        !           446:                        SKIPWORD(p);
        !           447:                        *p++ = CNULL;
        !           448:                        /*
        !           449:                        ** be sure that the alias is in local form
        !           450:                        */
        !           451:                        if(islocal(b, domain, user) == 0) {
        !           452:                                /*
        !           453:                                ** non-local alias format - skip it
        !           454:                                */
        !           455:                                continue;
        !           456:                        }
        !           457:                        /*
        !           458:                        ** add the alias to the (vertical) list of aliases
        !           459:                        */
        !           460:                        if((h = add_vert(head, user)) == NNULL) {
        !           461: DEBUG("load_alias for '%s' failed\n", b);
        !           462:                                fclose(fp);
        !           463:                                return;
        !           464:                        }
        !           465:                }
        !           466:                /*
        !           467:                **  Next on the line is the list of recipents.
        !           468:                **  Strip out each word and add it to the
        !           469:                **  horizontal linked list.
        !           470:                */
        !           471:                (void) recipients(h, p);
        !           472: 
        !           473:        } /* while (fgets(buf, sizeof buf, fp) != NULL) */
        !           474:        (void) fclose(fp);
        !           475:        /*
        !           476:        ** strip out aliases which have no members
        !           477:        */
        !           478:        for(v = head; v->vert != NNULL; ) {
        !           479:                if(v->vert->horz == NNULL) {
        !           480:                        v->vert = v->vert->vert;
        !           481:                } else {
        !           482:                        v = v->vert;
        !           483:                }
        !           484:        }
        !           485: }
        !           486: 
        !           487: /*
        !           488: ** add each word in a string (*p) of recipients
        !           489: ** to the (horizontal) linked list associated with 'h'
        !           490: */
        !           491: 
        !           492: recipients(h, p)
        !           493: node *h;
        !           494: char *p;
        !           495: {
        !           496: 
        !           497:        char *b, d[SMLBUF], u[SMLBUF];
        !           498:        int ret = 0;
        !           499: 
        !           500:        strip_comments(p);      /* strip out stuff in ()'s */
        !           501: 
        !           502:        SKIPSPACE(p);           /* skip leading whitespace on line */
        !           503: 
        !           504:        while((*p != NULL) && (*p != '#')) {
        !           505:                b = p;
        !           506:                if(*b == '"') {
        !           507:                        if((p = index(++b, '"')) == NULL) {
        !           508:                                /* syntax error - no matching quote */
        !           509:                                /* skip the rest of the line */
        !           510:                                return(ret);
        !           511:                        }
        !           512:                } else {
        !           513:                        SKIPWORD(p);
        !           514:                }
        !           515: 
        !           516:                if(*p != CNULL) {
        !           517:                        *p++ = CNULL;
        !           518:                }
        !           519: 
        !           520:                /* don't allow aliases of the form
        !           521:                ** a    a
        !           522:                */
        !           523:                if((islocal(b, d, u) == 0)
        !           524: #ifdef CASEALIAS
        !           525:                || (strcmp(h->string, u) != 0)) {
        !           526: #else
        !           527:                || (strcmpic(h->string, u) != 0)) {
        !           528: #endif
        !           529:                        add_horz(h, b);
        !           530:                        ret = 1;
        !           531:                }
        !           532:                SKIPSPACE(p);
        !           533:        }
        !           534:        return(ret);
        !           535: }
        !           536: 
        !           537: /*
        !           538: ** some aliases may have comments on the line like:
        !           539: **
        !           540: ** moderators  [email protected]       (Moderator's Name)
        !           541: **             [email protected]    (Another Moderator's Name)
        !           542: **
        !           543: ** strip out the stuff in ()'s
        !           544: **
        !           545: */
        !           546: 
        !           547: void
        !           548: strip_comments(p)
        !           549: char *p;
        !           550: {
        !           551:        char *b;
        !           552:        while((p = index(p, '(')) != NULL) {
        !           553:                b = p++;        /*
        !           554:                                ** save pointer to open parenthesis
        !           555:                                */
        !           556:                if((p = index(p, ')')) != NULL) {/* look for close paren */
        !           557:                        (void) strcpy(b, ++p);   /* slide string left    */
        !           558:                } else {
        !           559:                        *b = CNULL;     /* no paren, skip rest of line  */
        !           560:                        break;
        !           561:                }
        !           562:        }
        !           563: }
        !           564: 
        !           565: /*
        !           566: ** add_vert - add a (vertical) link to the chain of aliases.
        !           567: */
        !           568: 
        !           569: node *
        !           570: add_vert(head, str)
        !           571: node *head;
        !           572: char *str;
        !           573: {
        !           574:        char *p, *malloc();
        !           575:        void free();
        !           576:        node *new;
        !           577: 
        !           578:        /*
        !           579:        ** strip colons off the end of alias names
        !           580:        */
        !           581:        if((p = index(str, ':')) != NULL) {
        !           582:                *p = CNULL;
        !           583:        }
        !           584:        if((new = (node *) malloc(sizeof(node))) != NNULL) {
        !           585:                if((new->string = malloc((unsigned) strlen(str)+1)) == NULL) {
        !           586:                        free(new);
        !           587:                        new = NNULL;
        !           588:                } else {
        !           589:                        (void) strcpy(new->string, str);
        !           590:                        new->vert   = head->vert;
        !           591:                        new->horz   = NNULL;
        !           592:                        head->vert  = new;
        !           593: /*DEBUG("add_vert %s->%s\n", head->string, new->string);/* */
        !           594:                }
        !           595:        }
        !           596:        return(new);
        !           597: }
        !           598: 
        !           599: /*
        !           600: ** add_horz - add a (horizontal) link to the chain of recipients.
        !           601: */
        !           602: 
        !           603: void
        !           604: add_horz(head, str)
        !           605: node *head;
        !           606: char *str;
        !           607: {
        !           608:        char *malloc();
        !           609:        node *new;
        !           610: 
        !           611:        if((new = (node *) malloc(sizeof(node))) != NNULL) {
        !           612:                if((new->string = malloc((unsigned) strlen(str)+1)) == NULL) {
        !           613:                        free(new);
        !           614:                        new = NNULL;
        !           615:                } else {
        !           616:                        (void) strcpy(new->string, str);
        !           617:                        new->horz  = head->horz;
        !           618:                        new->vert  = NNULL;
        !           619:                        head->horz = new;
        !           620:                }
        !           621: /*DEBUG("add_horz %s->%s\n", head->string, new->string);/* */
        !           622:        }
        !           623: }
        !           624: 
        !           625: node *
        !           626: pop(head)
        !           627: node *head;
        !           628: {
        !           629:        node *ret = NNULL;
        !           630: 
        !           631: 
        !           632:        if(head != NNULL) {
        !           633:                ret = head->horz;
        !           634:                if(ret != NNULL) {
        !           635:                        head->horz = ret->horz;
        !           636:                }
        !           637:        }
        !           638:        return(ret);
        !           639: }

unix.superglobalmegacorp.com

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