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