home *** CD-ROM | disk | FTP | other *** search
/ Gold Fish 2 / goldfish_vol2_cd1.bin / files / comm / mail / smail / src / rcs / alias.c,v next >
Text File  |  1993-12-21  |  14KB  |  758 lines

  1. head    1.5;
  2. access;
  3. symbols
  4.     C_1:1.5;
  5. locks; strict;
  6. comment    @ * @;
  7.  
  8.  
  9. 1.5
  10. date    93.10.31.21.11.29;    author Aussem;    state Exp;
  11. branches;
  12. next    1.4;
  13.  
  14. 1.4
  15. date    93.10.11.22.13.24;    author Aussem;    state Exp;
  16. branches;
  17. next    1.3;
  18.  
  19. 1.3
  20. date    93.10.10.19.30.47;    author Aussem;    state Exp;
  21. branches;
  22. next    1.2;
  23.  
  24. 1.2
  25. date    93.09.18.16.47.47;    author Aussem;    state Exp;
  26. branches;
  27. next    1.1;
  28.  
  29. 1.1
  30. date    93.09.08.16.27.13;    author Aussem;    state Exp;
  31. branches;
  32. next    ;
  33.  
  34.  
  35. desc
  36. @alias routines
  37. @
  38.  
  39.  
  40. 1.5
  41. log
  42. @no forwarding and fullname resolution on pipe commands
  43. @
  44. text
  45. @/*
  46.  *  Aliasparsing for smail/rmail
  47.  *
  48.  * This program is free software; you can redistribute it and/or
  49.  * modify it under the terms of the GNU General Public License as
  50.  * published by the Free Software Foundation; either version 2 of
  51.  * the License, or (at your option) any later version.
  52.  *
  53.  * This program is distributed in the hope that it will be useful,
  54.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  55.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  56.  * General Public License for more details.
  57.  *
  58.  * You should have received a copy of the GNU General Public License
  59.  * along with this program; if not, write to the Free Software
  60.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  61.  *
  62.  *
  63.  * $Log: alias.c,v $
  64.  * Revision 1.4  1993/10/11  22:13:24  Aussem
  65.  * forwarding with uumail:user only if the file starts
  66.  * with Forward:
  67.  *
  68.  * Revision 1.3  1993/10/10  19:30:47  Aussem
  69.  * uumail:<user> for forwarding supported
  70.  *
  71.  * Revision 1.2  1993/09/18  16:47:47  Aussem
  72.  * insert GNU license text in the header
  73.  *
  74.  * Revision 1.1  1993/09/08  16:27:13  Aussem
  75.  * Initial revision
  76.  *
  77.  *
  78.  */
  79.  
  80. static char     *rcsid="$Id: alias.c,v 1.4 1993/10/11 22:13:24 Aussem Exp Aussem $";
  81.  
  82. #include <stdio.h>
  83. #include <stdlib.h>
  84. #include <sys/types.h>
  85. #include <sys/stat.h>
  86. #include "defs.h"
  87. #include <ctype.h>
  88.  
  89. extern enum edebug debug;    /* verbose and debug modes        */
  90. extern char hostdomain[];
  91. extern char hostname[];
  92. extern char *aliasfile;
  93. /*
  94. **
  95. ** Picture of the alias graph structure
  96. **
  97. **    head
  98. **       |
  99. **       v
  100. **    maps -> mark -> gjm -> mel -> NNULL
  101. **       |
  102. **       v
  103. **    sys ->  root -> ron -> NNULL
  104. **       |
  105. **       v
  106. **    root -> mark -> chris -> lda -> NNULL
  107. **       |
  108. **       v
  109. **      NNULL
  110. */
  111.  
  112.  
  113. static struct alias_node {
  114.     char *string;
  115.     node *horz;
  116.     node *vert;
  117. };
  118.  
  119. static node aliases = {"", 0, 0}; /* this is the 'dummy header' */
  120.  
  121. /*
  122. ** lint free forms of NULL
  123. */
  124.  
  125. #define NNULL    ((node   *) 0)
  126. #define CNULL    ('\0')
  127.  
  128. /*
  129. ** string parsing macros
  130. */
  131. #define SKIPWORD(Z)  while(*Z!=' ' && *Z!='\t' && *Z!='\n' && *Z!=',') Z++;
  132. #define SKIPSPACE(Z) while(*Z==' ' || *Z=='\t' || *Z=='\n' || *Z==',') Z++;
  133.  
  134. static int nargc = 0;
  135. static char *nargv[MAXARGS];
  136.  
  137. /* our horizontal linked list looks like a stack */
  138. #define push        add_horz
  139.  
  140. #define escape(s)    ((*s != '\\') ? (s) : (s+1))
  141.  
  142. char **
  143. alias(pargc, argv)
  144. int *pargc;
  145. char **argv;
  146. {
  147. /*
  148. **  alias the addresses
  149. */
  150.     int    i;
  151.     char    domain[SMLBUF], ubuf[SMLBUF], *user;
  152.     node    *addr, addrstk;
  153.     node    *flist,  fliststk, *u;
  154.  
  155.     FILE    *fp;
  156.     node    *a;
  157.     char    *home, buf[SMLBUF];
  158.     int    aliased;
  159.    short flag;
  160.  
  161.     addr  = &addrstk;
  162.     flist = &fliststk;
  163.     user  = ubuf;
  164.  
  165.     addr->horz = NNULL;
  166.     flist->horz  = NNULL;
  167.  
  168.     /*
  169.     ** push all of the addresses onto a stack
  170.     */
  171.     for(i=0; i < *pargc; i++) {
  172.         push(addr, argv[i]);
  173.     }
  174.  
  175.     /*
  176.     ** for each adress, check for included files, aliases,
  177.     ** full name mapping, and .forward files
  178.     */
  179.  
  180.     while((nargc < MAXARGS) && ((u = pop(addr)) != NNULL)) {
  181.         if(strncmpic(u->string, ":include:", 9) == 0) {
  182.             /*
  183.             ** make sure it's a full path name
  184.             ** don't allow multiple sourcing
  185.             ** of a given include file
  186.             */
  187.             char *p = u->string + 9;
  188.  
  189.             if((h_search(flist, p) == NULL)) {
  190.                 push(flist, p);
  191.                 if((fp = fopen(p, "r")) != NULL) {
  192.                 ADVISE("alias include ('%s')\n", p);
  193.                     while(fgets(buf, sizeof buf, fp)) {
  194.                         (void) recipients(addr, buf);
  195.                     }
  196.                     (void) fclose(fp);
  197.                 }
  198.             }
  199.             continue;
  200.         }
  201.         /*
  202.         ** parse the arg to see if it's to be aliased
  203.         */
  204.  
  205.         if(islocal(u->string, domain, ubuf) == 0) {
  206.             goto aliasing_complete;
  207.         }
  208.  
  209.         /*
  210.         ** local form - try to alias user
  211.         ** aliases file takes precedence over ~user/.forward
  212.         ** since that's the way that sendmail does it.
  213.         */
  214.  
  215. #ifdef LOWERLOGNAME
  216.         /* squish 'user' into lower case */
  217.         for(user = ubuf; *user ; user++) {
  218.             *user = lower(*user);
  219.         }
  220. #endif
  221.         user = escape(ubuf);
  222.  
  223.         (void) strcpy(u->string, user);    /* local => elide domain */
  224.         /*
  225.         ** check for alias - all this complication is necessary
  226.         ** to handle perverted aliases like these:
  227.         ** # mail to 's' resolves to 't' 'm' and 'rmt!j'
  228.         ** s    t,g,j,m
  229.         ** g    j,m
  230.         ** j    rmt!j
  231.         ** # mail to 'a' resolves to 'rmt!d'
  232.         ** a    b c
  233.         ** b    c
  234.         ** c    rmt!d
  235.         ** # mail to x resolves to 'x'
  236.         ** x    local!x
  237.         ** # mail to 'y' resolves to 'y' and 'z'
  238.         ** y    \y z
  239.         */
  240.         if(((a = v_search(user)) != NNULL)) {
  241.             char dtmpb[SMLBUF], utmpb[SMLBUF], *ut;
  242.             int user_inalias = 0;
  243.             node *t = a;
  244.  
  245.             for(a = a->horz; a != NNULL; a=a->horz) {
  246.                 if(islocal(a->string, dtmpb, utmpb)) {
  247. #ifdef LOWERLOGNAME
  248.                     /* squish 'utmpb' into lower case */
  249.                     for(ut = utmpb; *ut ; ut++) {
  250.                         *ut = lower(*ut);
  251.                     }
  252. #endif
  253.  
  254.                     ut = escape(utmpb);
  255. #ifdef CASEALIAS
  256.                     if(strcmp(ut, user) == 0)
  257. #else
  258.                     if(strcmpic(ut, user) == 0)
  259. #endif
  260.                     {
  261.                         user_inalias = 1;
  262.                     } else {
  263.                         push(addr, a->string);
  264.                     }
  265.                 } else {
  266.                     push(addr, a->string);
  267.                 }
  268.             }
  269.             t->horz = NNULL; /* truncate horz list of aliases */
  270.             if(user_inalias == 0) {
  271.                 continue;
  272.             }
  273.         }
  274.  
  275.       /* if the alias is not a piping command */
  276.       if(user[0]!='|')
  277.       {
  278.         if((home = tilde(user)) != NULL) {
  279.             /* don't allow multiple sourcing
  280.             ** of a given .forward file
  281.             */
  282.  
  283.             if((h_search(flist, home) != NULL)) {
  284.                 continue;
  285.             }
  286.             push(flist, home);
  287.  
  288.             /*
  289.             ** check for ~user/.forward file
  290.             ** must be a regular, readable file
  291.             */
  292.             strcpy(buf,mkfilename(home,".forward"));
  293.             if((fp = fopen(buf, "r")) != NULL) {
  294.              ADVISE("alias: ~/.forward include ('%s')\n", buf);
  295.                 aliased = 0;
  296.                 while(fgets(buf, sizeof buf, fp)) {
  297.                     if(buf[0]=='\0' || buf[0]=='#')
  298.                          continue;
  299.                     aliased |= recipients(addr, buf);
  300.                 }
  301.                 (void) fclose(fp);
  302.                 if(aliased) {
  303.                     continue;
  304.                 }
  305.             }
  306.         }
  307.         /*
  308.         ** check for uumail:user file
  309.         ** must be a regular, readable file
  310.         */
  311.         strcpy(buf,mkfilename(UUMAIL,user));
  312.         if((fp = fopen(buf, "r")) != NULL) {
  313.           ADVISE("alias: uumail:<user> include ('%s')\n", buf);
  314.             aliased = 0;
  315.             flag=1;
  316.             while(fgets(buf, sizeof buf, fp)) {
  317.             /* if the first line is not equal Forward: break */
  318.                 if(flag && strncmp(buf,"Forward:",8)!=0)
  319.                      break;
  320.             /* remove the Forward: */
  321.                 if(flag)
  322.                 strcpy(buf,&buf[8]);
  323.  
  324.                 if(flag)flag=0;
  325.                 if(buf[0]=='\0' || buf[0]=='#')
  326.                      continue;
  327.                 aliased |= recipients(addr, buf);
  328.             }
  329.             (void) fclose(fp);
  330.             if(aliased) {
  331.                 continue;
  332.             }
  333.         }
  334. #ifdef FULLNAME
  335.         /*
  336.         ** Do possible fullname substitution.
  337.         */
  338. #ifdef DOT_REQD
  339.         if (index(user, '.') != NULL)
  340. #endif
  341.         {
  342.             static char t_dom[SMLBUF], t_unam[SMLBUF];
  343.             char *t_user = res_fname(user);
  344.             if (t_user != NULL) {
  345.                 if(islocal(t_user, t_dom, t_unam) == 0) {
  346.                     /* aliased to non-local address */
  347.                     push(addr, t_user);
  348.                     continue;
  349.                 }
  350.                 if(strcmp(t_unam, user) != 0) {
  351.                     /* aliased to different local address */
  352.                     push(addr, t_unam);
  353.                     continue;
  354.                 }
  355.             }
  356.         }
  357. #endif
  358.      }
  359. aliasing_complete:
  360.         user = escape(u->string);
  361.         for(i=0; i < nargc; i++) {
  362.             if(strcmpic(nargv[i], user) == 0) {
  363.                 break;
  364.             }
  365.         }
  366.  
  367.         if(i == nargc) {
  368.             nargv[nargc++] = user;
  369.         }
  370.     }
  371.     *pargc     = nargc;
  372.     return(nargv);
  373. }
  374.  
  375. /*
  376. ** v_search
  377. **    given an string, look for its alias in
  378. **    the 'vertical' linked list of aliases.
  379. */
  380. node *
  381. v_search(user)
  382. char *user;
  383. {
  384.     node *head;
  385.     node *a;
  386.     static int loaded = 0;
  387.  
  388.     head = &aliases;
  389.     if(loaded == 0) {
  390.         load_alias(head, aliasfile);
  391.         loaded = 1;
  392.     }
  393.  
  394.     for(a = head->vert; a != NNULL; a = a->vert) {
  395. #ifdef CASEALIAS
  396.         if(strcmp(a->string, user) == 0)
  397. #else
  398.         if(strcmpic(a->string, user) == 0)
  399. #endif
  400.         {
  401.             break;
  402.         }
  403.     }
  404.     if(a == NNULL) {        /* not in graph */
  405.         return(NNULL);
  406.     }
  407.     return(a);
  408. }
  409.  
  410. /*
  411. ** h_search
  412. **    given an string, look for it in
  413. **    a 'horizontal' linked list of strings.
  414. */
  415. node *
  416. h_search(head, str)
  417. node *head;
  418. char *str;
  419. {
  420.     node *a;
  421.     for(a = head->horz; a != NNULL; a = a->horz) {
  422. #ifdef CASEALIAS
  423.         if(strcmp(a->string, str) == 0)
  424. #else
  425.         if(strcmpic(a->string, str) == 0)
  426. #endif
  427.         {
  428.             break;
  429.         }
  430.     }
  431.     return(a);
  432. }
  433.  
  434. /*
  435. ** load_alias
  436. **    parse an 'aliases' file and add the aliases to the alias graph.
  437. **    Handle inclusion of other 'aliases' files.
  438. */
  439.  
  440. void
  441. load_alias(head, filename)
  442. node *head;
  443. char *filename;
  444. {
  445.     FILE *fp;
  446.     node *v, *h;
  447.     char domain[SMLBUF], user[SMLBUF];
  448.     char *p, *b, buf[SMLBUF];
  449.  
  450.     if((fp = fopen(filename,"r")) == NULL) {
  451. DEBUG("load_alias open('%s') failed\n", filename);
  452.         return;
  453.     }
  454.  
  455.     while(fgets(buf, sizeof buf, fp) != NULL) {
  456.         p = buf;
  457.         if((*p == '#') || (*p == '\n')) {
  458.             continue;
  459.         }
  460.  
  461.         /*
  462.         ** include another file of aliases
  463.         */
  464.  
  465.         if(strncmp(p, ":include:", 9) == 0) {
  466.             char *nl;
  467.             p += 9;
  468.             if((nl = index(p, '\n')) != NULL) {
  469.                 *nl = CNULL;
  470.             }
  471. DEBUG("load_alias '%s' includes file '%s'\n", filename, p);
  472.             load_alias(head, p);
  473.             continue;
  474.         }
  475.  
  476.         /*
  477.         **  if the first char on the line is a space or tab
  478.         **  then it's a continuation line.  Otherwise,
  479.         **  we start a new alias.
  480.         */
  481.         if(*p != ' ' && *p != '\t') {
  482.             b = p;
  483.             SKIPWORD(p);
  484.             *p++ = CNULL;
  485.             /*
  486.             ** be sure that the alias is in local form
  487.             */
  488.             if(islocal(b, domain, user) == 0) {
  489.                 /*
  490.                 ** non-local alias format - skip it
  491.                 */
  492.                 continue;
  493.             }
  494.             /*
  495.             ** add the alias to the (vertical) list of aliases
  496.             */
  497.             if((h = add_vert(head, user)) == NNULL) {
  498. DEBUG("load_alias for '%s' failed\n", b);
  499.                 return;
  500.             }
  501.         }
  502.         /*
  503.         **  Next on the line is the list of recipents.
  504.         **  Strip out each word and add it to the
  505.         **  horizontal linked list.
  506.         */
  507.         (void) recipients(h, p);
  508.     }
  509.     (void) fclose(fp);
  510.     /*
  511.     ** strip out aliases which have no members
  512.     */
  513.     for(v = head; v->vert != NNULL; ) {
  514.         if(v->vert->horz == NNULL) {
  515.             v->vert = v->vert->vert;
  516.         } else {
  517.             v = v->vert;
  518.         }
  519.     }
  520. }
  521.  
  522. /*
  523. ** add each word in a string (*p) of recipients
  524. ** to the (horizontal) linked list associated with 'h'
  525. */
  526.  
  527. recipients(h, p)
  528. node *h;
  529. char *p;
  530. {
  531.  
  532.     char *b, d[SMLBUF], u[SMLBUF];
  533.     int ret = 0;
  534.  
  535.     strip_comments(p);    /* strip out stuff in ()'s */
  536.  
  537.     SKIPSPACE(p);        /* skip leading whitespace on line */
  538.  
  539.     while((*p != '\0') && (*p != '#')) {
  540.         b = p;
  541.         if(*b == '"') {
  542.             if((p = index(++b, '"')) == NULL) {
  543.                 /* syntax error - no matching quote */
  544.                 /* skip the rest of the line */
  545.                 return(ret);
  546.             }
  547.         } else {
  548.             SKIPWORD(p);
  549.         }
  550.  
  551.         if(*p != CNULL) {
  552.             *p++ = CNULL;
  553.         }
  554.  
  555.         /* don't allow aliases of the form
  556.         ** a    a
  557.         */
  558.         if((islocal(b, d, u) == 0)
  559.         || !h->string
  560.       || (strcmpic(h->string, u) != 0)) {
  561.             add_horz(h, b);
  562.             ret = 1;
  563.         }
  564.         SKIPSPACE(p);
  565.     }
  566.     return(ret);
  567. }
  568.  
  569. /*
  570. ** some aliases may have comments on the line like:
  571. **
  572. ** moderators    moderator@@somehost.domain    (Moderator's Name)
  573. **        moderator@@anotherhost.domain    (Another Moderator's Name)
  574. **
  575. ** strip out the stuff in ()'s
  576. **
  577. */
  578.  
  579. void
  580. strip_comments(p)
  581. char *p;
  582. {
  583.     char *b;
  584.     while((p = index(p, '(')) != NULL) {
  585.         b = p++;    /*
  586.                 ** save pointer to open parenthesis
  587.                 */
  588.         if((p = index(p, ')')) != NULL) {/* look for close paren */
  589.             (void) strcpy(b, ++p);     /* slide string left    */
  590.         } else {
  591.             *b = CNULL;    /* no paren, skip rest of line  */
  592.             break;
  593.         }
  594.     }
  595. }
  596.  
  597. /*
  598. ** add_vert - add a (vertical) link to the chain of aliases.
  599. */
  600.  
  601. node *
  602. add_vert(head, str)
  603. node *head;
  604. char *str;
  605. {
  606.     char *p;
  607.     node *new;
  608.  
  609.     /*
  610.     ** strip colons off the end of alias names
  611.     */
  612.     if((p = index(str, ':')) != NULL) {
  613.         *p = CNULL;
  614.     }
  615.     if((new = (node *) malloc(sizeof(node))) != NNULL) {
  616.         if((new->string = malloc((unsigned) strlen(str)+1)) == NULL) {
  617.             free(new);
  618.             new = NNULL;
  619.         } else {
  620.             (void) strcpy(new->string, str);
  621.             new->vert   = head->vert;
  622.             new->horz   = NNULL;
  623.             head->vert  = new;
  624. /*DEBUG("add_vert %s->%s\n", head->string, new->string);/* */
  625.         }
  626.     }
  627.     return(new);
  628. }
  629.  
  630. /*
  631. ** add_horz - add a (horizontal) link to the chain of recipients.
  632. */
  633.  
  634. void
  635. add_horz(head, str)
  636. node *head;
  637. char *str;
  638. {
  639.     node *new;
  640.  
  641.     if((new = (node *) malloc(sizeof(node))) != NNULL) {
  642.         if((new->string = malloc((unsigned) strlen(str)+1)) == NULL) {
  643.             free(new);
  644.             new = NNULL;
  645.         } else {
  646.             (void) strcpy(new->string, str);
  647.             new->horz  = head->horz;
  648.             new->vert  = NNULL;
  649.             head->horz = new;
  650.         }
  651. /*DEBUG("add_horz %s->%s\n", head->string, new->string);/* */
  652.     }
  653. }
  654.  
  655. node *
  656. pop(head)
  657. node *head;
  658. {
  659.     node *ret = NNULL;
  660.  
  661.  
  662.     if(head != NNULL) {
  663.         ret = head->horz;
  664.         if(ret != NNULL) {
  665.             head->horz = ret->horz;
  666.         }
  667.     }
  668.     return(ret);
  669. }
  670. @
  671.  
  672.  
  673. 1.4
  674. log
  675. @forwarding with uumail:user only if the file starts
  676. with Forward:
  677. @
  678. text
  679. @d20 4
  680. d36 1
  681. a36 1
  682. static char     *rcsid="$Id: alias.c,v 1.3 1993/10/10 19:30:47 Aussem Exp Aussem $";
  683. a74 1
  684. #ifndef SENDMAIL
  685. a75 1
  686. #endif /* not SENDMAIL */
  687. a110 1
  688. #ifndef SENDMAIL
  689. a115 1
  690. #endif /* not SENDMAIL */
  691. a136 1
  692. #ifndef SENDMAIL
  693. d148 1
  694. a156 1
  695. #endif /* not SENDMAIL */
  696. a179 1
  697. #ifndef SENDMAIL
  698. d231 3
  699. d250 1
  700. d269 1
  701. a289 2
  702. #endif /* not SENDMAIL */
  703.  
  704. d314 1
  705. a314 1
  706.  
  707. a330 1
  708. #ifndef SENDMAIL
  709. a388 1
  710. #endif /* not SENDMAIL */
  711. @
  712.  
  713.  
  714. 1.3
  715. log
  716. @uumail:<user> for forwarding supported
  717. @
  718. text
  719. @d20 3
  720. d32 1
  721. a32 1
  722. static char     *rcsid="$Id: alias.c,v 1.2 1993/09/18 16:47:47 Aussem Exp Aussem $";
  723. d270 2
  724. a271 1
  725.                 if(flag && strncmp(buf,"From ",5)==0)
  726. d273 4
  727. @
  728.  
  729.  
  730. 1.2
  731. log
  732. @insert GNU license text in the header
  733. @
  734. text
  735. @d20 3
  736. d29 1
  737. a29 1
  738. static char     *rcsid="$Id: alias.c,v 1.1 1993/09/08 16:27:13 Aussem Exp Aussem $";
  739. d111 1
  740. d248 2
  741. d256 21
  742. @
  743.  
  744.  
  745. 1.1
  746. log
  747. @Initial revision
  748. @
  749. text
  750. @d4 4
  751. a7 1
  752.  * $Log$
  753. d9 15
  754. d26 1
  755. a26 1
  756. static char     *rcsid="$Id$";
  757. @
  758.