home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / pp / pp-6.0 / Lib / parse / ad_local.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-18  |  13.4 KB  |  569 lines

  1. /* ad_local.c: process a local address */
  2.  
  3. # ifndef lint
  4. static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/parse/RCS/ad_local.c,v 6.0 1991/12/18 20:23:41 jpo Rel $";
  5. # endif
  6.  
  7. /*
  8.  * $Header: /xtel/pp/pp-beta/Lib/parse/RCS/ad_local.c,v 6.0 1991/12/18 20:23:41 jpo Rel $
  9.  *
  10.  * $Log: ad_local.c,v $
  11.  * Revision 6.0  1991/12/18  20:23:41  jpo
  12.  * Release 6.0
  13.  *
  14.  */
  15.  
  16. #include "head.h"
  17. #include "adr.h"
  18. #include "alias.h"
  19.  
  20. extern char    *loc_dom_mta;
  21. extern LIST_RCHAN    *tb_getuser();
  22. extern Redirection *redirect_new();
  23. extern void redirect_add();
  24. extern void redirect_free ();
  25.  
  26. static int do_alias_check(), do_user_check(), reparse_local();
  27.  
  28. int ad_local (locname, ad, rp)
  29. char    *locname;
  30. register ADDR    *ad;
  31. RP_Buf    *rp;
  32. {
  33.     ALIAS    alias_struct,
  34.     *alp = &alias_struct;
  35.     int    retval;
  36.     char    tmp[BUFSIZ];
  37.  
  38.     PP_TRACE (("ad_local (%s, ad=%s, %s)",
  39.            locname, ad->ad_value, 
  40.            (ad->aparse->local_hub_name) ? ad->aparse->local_hub_name : "main hub"));
  41.  
  42.     if (ad->aparse->dont_use_aliases != TRUE) {
  43.         switch (tb_getalias (locname, alp, 
  44.                      ad->aparse->local_hub_name)) {
  45.             case NOTOK:
  46.             /* -- routine or table error -- */
  47.             PP_TRACE (("ad_local/tb_getalias failed on %s", 
  48.                    locname));    
  49.             (void) sprintf(tmp, "Alias error for '%s'", locname);
  50.             set_error(ad, tmp);
  51.             return parselose (rp, RP_USER, 
  52.                       "Alias error for %s",
  53.                       locname);
  54.             case OK:
  55.             /* -- found, do alias check -- */
  56.             if (alp->alias_external != ALIAS_EXTERNAL
  57.                 || ad->ad_resp == NO)
  58.                 return do_alias_check (locname,
  59.                                alp, ad, rp);
  60.  
  61.             default:
  62.             break;
  63.         }
  64.     }
  65.     /* -- otherwise do the user checks -- */
  66.     if (rp_isbad(retval = do_user_check(locname,
  67.                         ad,
  68.                         rp))
  69.         && !rp_isbad(reparse_local(locname, ad, rp)))
  70.         retval = RP_AOK;
  71.     return retval;
  72.  
  73.  
  74.     /* NOTREACHED */
  75. }
  76.  
  77. /*   */
  78.  
  79. static int redirect_copy (pto, from, ad, rp)
  80. Redirection    **pto, *from;
  81. ADDR    *ad;
  82. RP_Buf    *rp;
  83. {
  84.     Redirection    *tmp;
  85.     char    buf[BUFSIZ];
  86.     
  87.     while (from != (Redirection *) NULL) {
  88.         if (redirect_before(*pto, from) == TRUE) {
  89.             (void) sprintf(buf,
  90.                        "Redirection loop detected for '%s'",
  91.                        from->rd_addr);
  92.             set_error(ad, buf);
  93.             return parselose (rp, RP_USER,
  94.                       "Redirection loop detected for '%s'",
  95.                       from->rd_addr);
  96.         }
  97.         tmp = from->rd_next;
  98.         from->rd_next = (Redirection *) NULL;
  99.         redirect_add(pto, from);
  100.         from = tmp;
  101.     }
  102.     return RP_AOK;
  103. }
  104.            
  105. static void ad_copy (ad, new, resp)
  106. register ADDR    *ad;
  107. ADDR    *new;
  108. int    resp;
  109. {
  110.     PP_DBG (("ad_copy()"));
  111.  
  112.     if (ad->ad_outchan)
  113.         list_rchan_free (ad->ad_outchan);
  114.     ad->ad_outchan = new->ad_outchan;
  115.     new->ad_outchan = NULLIST_RCHAN;
  116.     ad->ad_parse_stat = new->ad_parse_stat;
  117.     
  118.     if (resp == YES) {
  119.         Aparse_ptr tmp = ad->aparse;
  120.         ad->aparse = new->aparse;
  121.         ad->aparse->recurse_count = tmp->recurse_count;
  122.         ad->aparse->dont_use_aliases = tmp->dont_use_aliases;
  123.         new->aparse = tmp;
  124.     }
  125. }
  126.         
  127.  
  128. int alias2adr (buf, alp, ap)
  129. char    *buf;
  130. ALIAS    *alp;
  131. register Aparse_ptr    ap;
  132. {
  133.     char    tmp[BUFSIZ];
  134.     OR_ptr    holder;
  135.  
  136.     if (alp->alias_ad_type == AD_ANY_TYPE) {
  137.         /* need to keep domain as may be local subdom */
  138.         switch (ap->ad_type) {
  139.             case AD_822_TYPE:
  140.             if (ap->ap_domain) 
  141.                 (void) sprintf(buf, "%s@%s",
  142.                            alp->alias_user, 
  143.                            ap->ap_domain->ap_obvalue);
  144.             else
  145.                 (void) strcpy(buf, alp->alias_user);
  146.             break;
  147.             case AD_X400_TYPE:
  148.             if (ap->lastMatch
  149.                 && ap->orname->on_or) {
  150.                 holder = ap->lastMatch->or_next;
  151.                 ap->lastMatch->or_next = NULLOR;
  152.                 
  153.                 or_or2std(ap->lastMatch, tmp, FALSE);
  154.                 ap->lastMatch->or_next = holder;
  155.                 (void) sprintf(buf, "%s%s",
  156.                            alp->alias_user,
  157.                            tmp);
  158.             } else
  159.                 (void) strcpy(buf, alp->alias_user);
  160.             break;
  161.             default:
  162.             (void) strcpy (buf, alp->alias_user);
  163.             break;
  164.         }
  165.     } else
  166.         (void) strcpy (buf, alp->alias_user);
  167. }
  168.  
  169. static int do_alias_check (name, alp, ad, rp)
  170. char    *name;
  171. ALIAS    *alp;
  172. register ADDR    *ad;
  173. RP_Buf    *rp;
  174. {
  175.     char    tmp[BUFSIZ], buf[BUFSIZ];
  176.     register ADDR    *new;
  177.     int    copy_results, retval, type;
  178.  
  179.     if ((type = alp->alias_ad_type) == AD_ANY_TYPE)
  180.         type = ad->aparse->ad_type;
  181.  
  182.     alias2adr(buf, alp, ad->aparse);
  183.     if (aparse_inAliasList (buf, ad->aparse->aliases) == OK) {
  184.         if (alp->alias_external == ALIAS_EXTERNAL)
  185.             PP_NOTICE(("circular aliases found '%s' ['%s' -> '%s'] - BUT external so ignore !",
  186.                    alp->alias_user, name, 
  187.                    buf));
  188.         else {
  189.             PP_LOG(LLOG_EXCEPTIONS,
  190.                    ("do_alias_check circular aliases '%s' ['%s' -> '%s']",
  191.                 alp->alias_user, name, 
  192.                 buf));
  193.             (void) sprintf(tmp,
  194.                        "local circular alias/synonym detected");
  195.             set_error(ad, tmp);
  196.             (void) strcpy(rp->rp_line, tmp);
  197.             return RP_PARSE;
  198.         }
  199.     } else
  200.         aparse_addToAliasList (buf, 
  201.                        &(ad->aparse->aliases));
  202.  
  203.     new = adr_new(buf,
  204.               type,
  205.               ad->ad_extension);
  206.     aparse_copy_for_recursion(new->aparse, ad->aparse);
  207.     if (alp->alias_external == ALIAS_EXTERNAL)
  208.         new->aparse->dont_use_aliases = TRUE;
  209.  
  210.     switch (alp->alias_type) {
  211.         case ALIAS_SYNONYM:
  212.         new->ad_resp = ad->ad_resp;
  213.         copy_results = YES;
  214.         break;
  215.         
  216.         case ALIAS_PROPER:
  217.         new->ad_resp = YES;
  218.         copy_results = ad->ad_resp;
  219.         break;
  220.     }
  221.  
  222.  
  223.     retval = ad_parse_aux (new, rp);
  224.     if (!rp_isbad(retval) &&
  225.         alp->alias_type == ALIAS_PROPER) {
  226.         /* add redirect */
  227.         char    tbuf[BUFSIZ], *dn = NULLCP;
  228.         OR_ptr    or;
  229.  
  230.         switch (ad->aparse->ad_type) {
  231.             case AD_X400_TYPE:
  232.             if (isstr(ad->aparse->x400_str))
  233.                 (void) strcpy(tbuf, ad->aparse->x400_str);
  234.             else if (ad->aparse->orname->on_or != NULLOR)
  235.                 or_or2std(ad->aparse->orname->on_or, 
  236.                       tbuf, FALSE);
  237.             else if (isstr(ad->ad_r400adr))
  238.                 (void) strcpy(tbuf, ad->ad_r400adr);
  239.             else
  240.                 tbuf[0] = '\0';
  241.             
  242.             if (isstr(ad->aparse->x400_dn))
  243.                 dn = ad->aparse->x400_dn;
  244.             break;
  245.             case AD_822_TYPE:
  246.             default:
  247.             if (isstr(ad->aparse->r822_str))
  248.                 (void) or_rfc2or_aux(ad->aparse->r822_str,
  249.                              &or,
  250.                              ad->ad_no);
  251.             else if (isstr(ad->ad_r822adr))
  252.                 (void) or_rfc2or_aux(ad->ad_r822adr,
  253.                              &or,
  254.                              ad->ad_no);
  255.             else
  256.                 or = NULLOR;
  257.  
  258.             if (or != NULLOR) {
  259.                 or_or2std(or, tbuf, FALSE);
  260.                 or_free (or);
  261.             } else
  262.                 tbuf[0] = '\0';
  263.         }
  264.         if (tbuf[0] != '\0') {
  265.             Redirection    *rtmp ;
  266.  
  267.             rtmp = redirect_new(tbuf,
  268.                         (dn == NULLCP) ? "" : dn,
  269.                         NULLUTC,
  270.                         RDR_MD_ASSIGNED);
  271.             
  272.             /* add in redirect */
  273.             if (rp_isbad(retval = redirect_copy(&(ad->ad_redirection_history),
  274.                            rtmp,
  275.                            ad, rp))) {
  276.                 /* redirect loop so don't copy results */
  277.                 copy_results = NO;
  278.                 redirect_free(rtmp);
  279.             }
  280.         }
  281.  
  282.     }
  283.  
  284.     if (!rp_isbad(retval)
  285.         && new->ad_redirection_history != (Redirection *) NULL) {
  286.         /* add in redirection history from recursion */
  287.         if (rp_isbad(retval = redirect_copy(&(ad->ad_redirection_history),
  288.                        new->ad_redirection_history,
  289.                        ad, rp))) {
  290.             /* redirect loop so don't copy results */
  291.             copy_results = NO;
  292.         } else
  293.             new->ad_redirection_history = (Redirection *) NULL;
  294.     }
  295.  
  296.     ad_copy (ad, new, copy_results);
  297.  
  298.     if (new)
  299.         adr_free(new);
  300.  
  301.     return retval;
  302. }
  303.  
  304. /*   */
  305.  
  306. static int do_user_check(name, ad, rp)
  307. char    *name;
  308. register ADDR    *ad;
  309. RP_Buf    *rp;
  310. {
  311.     char    buf[BUFSIZ], tmp[BUFSIZ];
  312.     int    next;
  313.     AP_ptr    dmn = NULLAP;
  314.  
  315.     LIST_RCHAN    *ix, *ix2, *newchan = NULLIST_RCHAN, *end;
  316.     
  317.     PP_TRACE (("ad_local/do_user_check (%s, %s)",
  318.            name, 
  319.            (ad->aparse->local_hub_name) ? ad->aparse->local_hub_name : "main hub"));
  320.     
  321.     if ((ad->ad_outchan = 
  322.          tb_getuser (name, ad->aparse->local_hub_name)) == NULLIST_RCHAN) {
  323.         (void) sprintf(buf, 
  324.                    "Unknown local user '%s'",
  325.                    name);
  326.         set_error(ad, buf);
  327.         return parselose (rp, ad->ad_parse_stat = RP_USER,
  328.                   "Unknown local user '%s'", name);
  329.     }
  330.  
  331.     next = TRUE;
  332.     for (ix = ad->ad_outchan;
  333.          ix != NULLIST_RCHAN;
  334.          ix = (next == TRUE) ? ix -> li_next : ix) {
  335.         /* -- check this is the machine on --*/
  336.         /* -- which local delivery is done -- */
  337.         next = TRUE;
  338.         
  339.         if (ix -> li_mta != NULLCP
  340.             && lexequ (ix->li_mta, loc_dom_mta) != 0) {
  341.             /* -- not this machine, update ix -- */
  342.             
  343.             /* lookup given mta */
  344.             if (tb_getchan (ix -> li_mta, &newchan) == NOTOK)
  345.                 newchan = NULLIST_RCHAN;
  346.  
  347.             if (newchan == NULLIST_RCHAN) {
  348.                 /* try normalising given mta */
  349.                 dmn = ap_new(AP_DOMAIN, ix->li_mta);
  350.                 if (rfc822_norm_dmn (dmn, 
  351.                              ad->aparse->dmnorder) != OK
  352.                     || dmn -> ap_recognised == FALSE
  353.                     || dmn -> ap_chankey == NULLCP) {
  354.                     if (dmn -> ap_recognised == FALSE)
  355.                         PP_LOG(LLOG_EXCEPTIONS,
  356.                                ("Internal routing (users table) error for mta '%s' [unable to normalise domain]",
  357.                             ix->li_mta));
  358.                     else if (dmn->ap_chankey == NULLCP)
  359.                         PP_LOG(LLOG_EXCEPTIONS,
  360.                                ("Internal routing (users table) error for mta '%s' [no index to routing info for '%s']",
  361.                             ix->li_mta,
  362.                             dmn->ap_obvalue));
  363.                     
  364.                     (void) sprintf(tmp,
  365.                                "Unknown internal domain '%s'",
  366.                                ix->li_mta);
  367.                     set_error(ad, tmp);
  368.                     ap_free(dmn);
  369.                     return ad->ad_parse_stat =
  370.                         parselose (rp,
  371.                                RP_USER,
  372.                                "Unknown internal domain '%s'",
  373.                                ix -> li_mta);
  374.                 }
  375.                 if (dmn -> ap_islocal == FALSE)
  376.                     PP_LOG(LLOG_EXCEPTIONS,
  377.                            ("Mta '%s' is used for internal routing (users table) but is not marked as local in domain table",
  378.                         dmn -> ap_obvalue));
  379.  
  380.             }
  381.             if (newchan == NULLIST_RCHAN
  382.                 && dmn != NULLAP
  383.                 && tb_getchan (dmn->ap_chankey, &newchan) == NOTOK) {
  384.                 PP_LOG(LLOG_EXCEPTIONS,
  385.                        ("Internal routing (users table) error for mta '%s' [no routing info for '%s']",
  386.                     ix -> li_mta, dmn->ap_chankey));
  387.                 (void) sprintf(tmp,
  388.                            "Unknown internal domain '%s'",
  389.                            ix -> li_mta);
  390.                 set_error(ad, tmp);
  391.                 return ad->ad_parse_stat =
  392.                     parselose (rp,
  393.                            RP_USER,
  394.                            "Domain '%s' not registered in channel table",
  395.                            ix -> li_mta);
  396.             }
  397.             
  398.             if (dmn != NULLAP) {
  399.                 ap_free(dmn);
  400.                 dmn = NULLAP;
  401.             }
  402.             /* insert new list_rchan into ad->ad_outchan */
  403.             end = newchan;
  404.             while (end->li_next != NULLIST_RCHAN)
  405.                 end = end->li_next;
  406.             if (ix == ad->ad_outchan) {
  407.                 end -> li_next = ad->ad_outchan->li_next;
  408.                 ad->ad_outchan = newchan;
  409.             } else {
  410.                 ix2 = ad->ad_outchan;
  411.                 while (ix2 != NULLIST_RCHAN
  412.                        && ix2 -> li_next != ix)
  413.                     ix2 = ix2->li_next;
  414.                 if (ix2 != NULLIST_RCHAN) {
  415.                     end -> li_next = ix -> li_next;
  416.                     ix2->li_next = newchan;
  417.                 }
  418.             }
  419.             ix -> li_next = NULLIST_RCHAN;
  420.             list_rchan_free(ix);
  421.             ix = end;
  422.         } else if (ix -> li_chan == NULLCHAN) {
  423.             /* invalid local channel */
  424.             if (ix == ad->ad_outchan) {
  425.                 ix2 = ix;
  426.                 ix = ad->ad_outchan = ad->ad_outchan->li_next;
  427.                 next = FALSE;
  428.                 /* yuch */
  429.             } else {
  430.                 for (end = ad->ad_outchan;
  431.                      end -> li_next != ix;
  432.                      end = end->li_next)
  433.                     continue;
  434.                 end -> li_next = ix -> li_next;
  435.                 ix2 = ix;
  436.                 ix = end;
  437.             }
  438.             ix2->li_next = NULLIST_RCHAN;
  439.             list_rchan_free(ix2);
  440.         }
  441.     }
  442.  
  443.     if (ad->ad_outchan == NULLIST_RCHAN) {
  444.         set_error(ad, "No valid local delivery channels");
  445.         return ad->ad_parse_stat =
  446.             parselose(rp, RP_USER, "%s",
  447.                   "No valid local delivery channels");
  448.     }
  449.  
  450.     for (ix = ad->ad_outchan; ix; ix = ix -> li_next)
  451.         if (ix->li_mta == NULLCP)
  452.             ix->li_mta = strdup(loc_dom_mta);
  453.  
  454.     return (ad->ad_parse_stat = RP_AOK);
  455. }
  456.  
  457. /*   */
  458.  
  459. static int reparsing = 0;
  460.  
  461. static int reparse_local (inname, ad, rp)
  462. char    *inname;
  463. register ADDR    *ad;
  464. RP_Buf    *rp;
  465. {
  466.     char    *bang = NULLCP,
  467.         *percent = NULLCP,
  468.         *at = NULLCP,
  469.         *ix, *newadrstr, *name,
  470.         *start = strdup(inname);
  471.     int    retval = NOTOK;
  472.     register ADDR    *newadr;
  473.  
  474.     name = start;
  475.     if (reparsing > 0) 
  476.         /* more than one level of reparsing wrong */
  477.         return NOTOK;
  478.     /* remove preceding and trailing quotes */
  479.     while (*name == '"' && *name != '\0') name++;
  480.  
  481.     ix = &(name[strlen(name)]);
  482.     while (*ix == '"' && ix != name) {
  483.         *ix = '\0';
  484.         ix --;
  485.     }
  486.     
  487.     bang = index(name, '!');
  488.     percent = index(name, '%');
  489.     at = index(name, '@');
  490.  
  491.     /* only allow one type of addressing */
  492.     if (!((bang && !percent && !at) ||
  493.           (percent && !bang && !at) ||
  494.           (at && !bang && !percent))) {
  495.         free(start);
  496.         return NOTOK;
  497.     }
  498.  
  499.     if (bang) {
  500.         int    numBangs = 0;
  501.         char    *iix, *jx;
  502.  
  503.         bang = name;
  504.         while ((bang = index(bang, '!')) != NULLCP) {
  505.             numBangs++;
  506.             bang++;
  507.         }
  508.         
  509.         newadrstr = malloc((unsigned)strlen(name) + 2 * (numBangs - 1)
  510.                    + 1);
  511.         iix = name; 
  512.         jx = newadrstr;
  513.         while (numBangs > 1) {
  514.             *jx++ = '@';
  515.             while (*iix != '!' && *iix != '\0')
  516.                 *jx++ = *iix++;
  517.             if (*iix == '!') {
  518.                 numBangs--;
  519.                 if (numBangs == 1) 
  520.                     *jx++ = ':';
  521.                 else
  522.                     *jx++ = ',';
  523.                 iix++;
  524.             }
  525.         }
  526.         *jx = '\0';
  527.         bang = rindex(iix, '!');
  528.         *bang++ = '\0';
  529.         (void) sprintf(newadrstr, "%s%s@%s",
  530.                    newadrstr, bang, iix);
  531.     } else
  532.         newadrstr = strdup(name);
  533.  
  534.     /* with bangs, percents etc. got to be 822 */
  535.     newadr = adr_new(newadrstr,
  536.                  AD_822_TYPE,
  537.                  ad->ad_no);
  538.     aparse_copy_for_recursion(newadr->aparse, ad->aparse);
  539.     
  540.     if (percent
  541.         || ad->aparse->percents == TRUE)
  542.         newadr->aparse->percents = TRUE;
  543.         
  544.     reparsing++;
  545.  
  546.     if (!(rp_isbad(retval = ad_parse_aux(newadr, rp)))) {
  547.         /* parsed okay so copy relevant bits across */
  548.         if (newadr->ad_redirection_history != (Redirection *) NULL) {
  549.             /* add in redirection history from recursion */
  550.             if (!rp_isbad(retval = redirect_copy(&(ad->ad_redirection_history),
  551.                                  newadr->ad_redirection_history,
  552.                                  ad, rp)))
  553.                 newadr->ad_redirection_history = (Redirection *) NULL;
  554.         }
  555.         if (!rp_isbad(retval))
  556.             ad_copy(ad, newadr,  YES);
  557.     } else {
  558.         /* didn't work so ignore errors */
  559.         ;
  560.     }
  561.  
  562.     reparsing--;
  563.  
  564.     free(start);
  565.     free(newadrstr);
  566.     adr_free(newadr);
  567.     return retval;
  568. }
  569.