home *** CD-ROM | disk | FTP | other *** search
/ Beijing Paradise BBS Backup / PARADISE.ISO / software / BBSDOORW / SMAILSRC.ZIP / SMAIL.ZIP / RESOLVE.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-05-05  |  7.7 KB  |  279 lines

  1. /*
  2. **
  3. **  Resolve.c
  4. **
  5. **  Routes then resolves addresses into UUCP or LOCAL.
  6. **
  7. */
  8.  
  9. #ifndef lint
  10. static char     *sccsid="@(#)resolve.c    2.5 (smail) 9/15/87";
  11. #endif
  12.  
  13. #include    <ctype.h>
  14. #include    <stdio.h>
  15. #include    "defs.h"
  16.  
  17. extern int exitstat;        /* set if address doesn't resolve     */
  18. extern enum ehandle handle;    /* what mail we can handle        */
  19. extern enum edebug debug;    /* verbose and debug modes        */
  20. extern enum erouting routing;    /* when to route addresses        */
  21. extern char hostdomain[];    /* */
  22. extern char hostname[];        /* */
  23. extern char *pathfile;        /* location of path database        */
  24. extern int getcost;        /* get path cost even if not routing    */
  25.  
  26. char *sform();
  27.  
  28. /*
  29. **
  30. **  rsvp(): how to resolve addresses.
  31. **
  32. **  After parsing an address into <form>, the resolved form will be
  33. **  rsvp( form ).  If == ROUTE, we route the parsed address and parse again.
  34. **
  35. */
  36.  
  37. # define rsvp(a) table[(int)a][(int)handle]
  38.  
  39. enum eform table[5][3] = {
  40. /*    all        justuucp    none */
  41. {    ERROR,         ERROR,         ERROR },     /* error */
  42. {    LOCAL,         LOCAL,         LOCAL },     /* local */
  43. {    ROUTE,         LOCAL,         LOCAL },     /* domain */
  44. {    UUCP,         UUCP,         LOCAL },     /* uucp */
  45. {    ERROR,         ERROR,         ERROR }};    /* route */
  46.  
  47. /*
  48. **
  49. **  resolve(): resolve addresses to <host, user, form>.
  50. **
  51. **  This is a gnarly piece of code, but it does it all.  Each section 
  52. **  is documented.
  53. **
  54. */
  55.  
  56. enum eform
  57. resolve( address, domain, user , cost)
  58. char *address;                /* the input address     */
  59. char *domain;                /* the returned domain     */
  60. char *user;                /* the returned user     */
  61. int *cost;                /* the returned cost     */
  62. {
  63.     enum eform form;        /* the returned form    */ 
  64.     enum eform parse();        /* to crack addresses    */
  65.     int parts;            /* to ssplit addresses    */
  66.     char *partv[MAXPATH];        /* "  "      "        */
  67.     char temp[SMLBUF];        /* "  "      "        */
  68.     int i;
  69.         
  70.  
  71. /*
  72. **  If we set REROUTE and are prepared to deliver UUCP mail, we split the 
  73. **  address apart at !'s and try to resolve successively larger righthand 
  74. **  substrings until we succeed.  Otherwise, we just resolve the whole thing 
  75. **  once.
  76. */
  77.     if ((routing == REROUTE) && (rsvp( UUCP ) == UUCP)) {
  78.         parts = ssplit( address, '!', partv );
  79.     } else {
  80.         parts = 1;
  81.         partv[0] = address;
  82.     }
  83. /*
  84. **  This for(i) loop selects successively larger
  85. **  righthand substrings of the address.
  86. */
  87.     for( i = parts - 1; i >= 0; i-- ) {
  88. /*
  89. **  Parse the address.
  90. */
  91.         (void) strcpy( temp, partv[i] );
  92.         form = parse( temp, domain, user );
  93.  
  94. DEBUG("resolve: parse address '%s' = '%s' @ '%s' (%s)\n",
  95.     temp,user,domain,sform(form));
  96.  
  97. /*
  98. **  If we are looking at a substring (that's not the entire string)
  99. **  which parses to a LOCAL address, we skip to the next larger substring.
  100. */
  101.         if((i != 0) && (form == LOCAL))
  102.             continue;
  103. /*
  104. **  Routing, when required, is the next step.
  105. **  We route the address if we have a ROUTE form
  106. **  or if we have a UUCP form and we are told to
  107. **  route ALWAYS or REROUTE (i.e., routing != JUSTDOMAIN)
  108. */
  109.         if((rsvp( form ) == ROUTE)
  110.          ||((rsvp( form ) == UUCP) && (routing != JUSTDOMAIN ))) {
  111.  
  112.             int look_smart = 0;
  113.  
  114.             if((routing == REROUTE) && (i == 0)) {
  115.                 look_smart = 1; /* last chance */
  116.             }
  117.  
  118.             /* route() puts the new route in 'temp' */
  119.             if(route(domain,user,look_smart,temp,cost) != EX_OK) {
  120.                 continue;    /* If routing fails, try
  121.                         /* next larger substring.
  122.                         /* */
  123.             }
  124. /*
  125. **  After routing, reparse the new route into domain and user. 
  126. */
  127.             form = parse( temp, domain, user );
  128.  
  129. DEBUG("resolve: parse route '%s' = '%s' @ '%s' (%s)\n",
  130.     temp,user,domain,sform(form));
  131.  
  132.         } else if((getcost) && (rsvp(form) == UUCP)) {
  133.             /* get the cost of the route
  134.             ** even if we're not going route the mail.
  135.             ** this allows smart decisions about using
  136.             ** the -r flag to uux when we're not routing.
  137.             */
  138.             char junk[SMLBUF];
  139.             if(route(domain,user,0,junk,cost) != EX_OK) {
  140.                 continue;    /* If routing fails, try
  141.                         /* next larger substring.
  142.                         /* */
  143.             }
  144.         }
  145.         break;    /* route is resolved */
  146.     }
  147. /*
  148. **  For LOCAL mail in non-local format, we rewrite the full address into 
  149. **  <user> and leave <domain> blank.
  150. */
  151.     if ((rsvp( form ) == LOCAL) && (form != LOCAL )) {
  152.         build( domain, user, form, temp );
  153.         (void) strcpy( user, temp );
  154.         (void) strcpy( domain, "" );
  155.         form = LOCAL;
  156.     }
  157. /*
  158. **  If we were supposed to route an address but failed (form == ERROR), 
  159. **  or after routing we are left with an address that still needs to
  160. **  be routed (rsvp( form ) == ROUTE), complain.
  161. */
  162.     if ((form == ERROR) || (rsvp( form ) == ROUTE )) {
  163.         exitstat = EX_NOHOST;
  164.         ADVISE("resolve failed '%s' = '%s' @ '%s' (%s)\n",
  165.             address, user, domain, sform(form));
  166.         form = ERROR;
  167.     } else {
  168.         ADVISE("resolve '%s' = '%s' @ '%s' (%s)\n",
  169.             address, user, domain, sform(form));
  170.     }
  171.     return ( form );
  172. }
  173.  
  174. /*
  175. **
  176. **  route(): route domain, plug in user.
  177. **
  178. **  Less complicated than it looks.  Each section is documented.
  179. **
  180. */
  181.  
  182. route(domain, user, look_smart, result, cost)
  183. char *domain;            /* domain or host name     */
  184. char *user;            /* user name         */
  185. int look_smart;            /* do we try to route through a smarter host? */
  186. char *result;            /* output route     */
  187. int *cost;            /* cost of output route */
  188. {
  189.     int    uucpdom = 0;
  190.     int    domains, step;            /* to split domain    */
  191.     char    *domainv[MAXDOMS];        /* "  "     "        */
  192.     char    temp[SMLBUF], path[SMLBUF];
  193.  
  194. /*
  195. **  Fully qualify the domain, and then strip the last (top level domain) 
  196. **  component off, so that we look it up separately.
  197. */
  198.     temp[0] = '.';
  199.     (void) strcpy(temp+1, domain );
  200.  
  201.     domains = ssplit( temp+1, '.', domainv );
  202.  
  203. /*
  204. ** check target domain for the local host name and host domain.
  205. ** if it matches, then skip the lookup in the database.
  206. ** this prevents mail loops for cases where SMARTHOST is defined
  207. ** in the routing table, but the local host is not.  It also is
  208. ** a little faster when the local host is the target domain.
  209. */
  210.     if((strcmpic(domain, hostname) == 0)
  211.     || (strcmpic(domain, hostdomain) == 0)) {
  212.         step = 0;
  213.         *cost = 0;
  214.         (void) strcpy(path, "%s");
  215. DEBUG("route: '%s' is local\n", domain);
  216.         goto route_complete;
  217.     }
  218.  
  219.     /* If the domain ends in .UUCP, trim that off. */
  220.     if((domains > 0) && isuucp(domainv[domains-1])) {
  221.         domains--;
  222.         domainv[domains][-1] = '\0';
  223.         uucpdom = 1;
  224.     }
  225. /*
  226. **  Try to get the path for successive components of the domain.  
  227. **  Example for osgd.cb.att.uucp:
  228. **    osgd.cb.att
  229. **    cb.att
  230. **    att
  231. **    uucp ( remember stripping top level? )
  232. **    SMARTHOST
  233. **  Returns with error if we find no path.
  234. */
  235.     for(step = 0; (step < domains); step++) {
  236.         if((getpath(domainv[step]-1, path, cost) == EX_OK) /* w/ dot */
  237.         || (getpath(domainv[step]  , path, cost) == EX_OK))/* no dot */
  238.             break;
  239.     }
  240.  
  241.     if(step == domains) {
  242.     /*
  243.     ** we've looked at each component of the domain without success
  244.     */
  245.         /*
  246.         ** If domain is a UUCP address, look for a UUCP gateway.
  247.         */
  248.         if((uucpdom == 0) || (getpath(".UUCP", path, cost) != EX_OK)) {
  249.             /*
  250.             ** The domain not is a UUCP address, or we can't
  251.             ** find a UUCP gateway.  If this is our last chance,
  252.             ** look for a smarter host to deliver the mail.
  253.             */
  254.             if((look_smart == 0)
  255.             || (getpath(SMARTHOST, path, cost) != EX_OK)) {
  256.                 /*
  257.                 ** All our efforts have been in vain.
  258.                 ** Tell them the bad news.
  259.                 */
  260.                 DEBUG("route '%s' failed\n", domain);
  261.                 return( EX_NOHOST );
  262.             }
  263.         }
  264.     }
  265.  
  266. route_complete:
  267.  
  268. DEBUG("route:  '%s' (%s) = '%s' (%d)\n", domain, domainv[step]?domainv[step]:"NULL", path, *cost);
  269.  
  270. /*
  271. **  If we matched on the entire domain name, this address is fully resolved, 
  272. **  and we plug <user> into it.  If we matched on only part of the domain 
  273. **  name, we plug <domain>!<user> in.  
  274. */
  275.     build(domain, user, (step == 0) ? LOCAL : UUCP, temp);
  276.     (void) sprintf(result, path, temp);
  277.     return( EX_OK );
  278. }
  279.