|
|
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: /* route() puts the new route in 'temp' */ ! 118: if(route(domain,user,look_smart,temp,cost) != EX_OK) { ! 119: continue; /* If routing fails, try ! 120: /* next larger substring. ! 121: /* */ ! 122: } ! 123: /* ! 124: ** After routing, reparse the new route into domain and user. ! 125: */ ! 126: form = parse( temp, domain, user ); ! 127: ! 128: DEBUG("resolve: parse route '%s' = '%s' @ '%s' (%s)\n", ! 129: temp,user,domain,sform(form)); ! 130: ! 131: } else if((getcost) && (rsvp(form) == UUCP)) { ! 132: /* get the cost of the route ! 133: ** even if we're not going route the mail. ! 134: ** this allows smart decisions about using ! 135: ** the -r flag to uux when we're not routing. ! 136: */ ! 137: char junk[SMLBUF]; ! 138: if(route(domain,user,0,junk,cost) != EX_OK) { ! 139: continue; /* If routing fails, try ! 140: /* next larger substring. ! 141: /* */ ! 142: } ! 143: } ! 144: break; /* route is resolved */ ! 145: } ! 146: /* ! 147: ** For LOCAL mail in non-local format, we rewrite the full address into ! 148: ** <user> and leave <domain> blank. ! 149: */ ! 150: if ((rsvp( form ) == LOCAL) && (form != LOCAL )) { ! 151: build( domain, user, form, temp ); ! 152: (void) strcpy( user, temp ); ! 153: (void) strcpy( domain, "" ); ! 154: form = LOCAL; ! 155: } ! 156: /* ! 157: ** If we were supposed to route an address but failed (form == ERROR), ! 158: ** or after routing we are left with an address that still needs to ! 159: ** be routed (rsvp( form ) == ROUTE), complain. ! 160: */ ! 161: if ((form == ERROR) || (rsvp( form ) == ROUTE )) { ! 162: exitstat = EX_NOHOST; ! 163: ADVISE("resolve failed '%s' = '%s' @ '%s' (%s)\n", ! 164: address, user, domain, sform(form)); ! 165: form = ERROR; ! 166: } else { ! 167: ADVISE("resolve '%s' = '%s' @ '%s' (%s)\n", ! 168: address, user, domain, sform(form)); ! 169: } ! 170: return ( form ); ! 171: } ! 172: ! 173: /* ! 174: ** ! 175: ** route(): route domain, plug in user. ! 176: ** ! 177: ** Less complicated than it looks. Each section is documented. ! 178: ** ! 179: */ ! 180: ! 181: route(domain, user, look_smart, result, cost) ! 182: char *domain; /* domain or host name */ ! 183: char *user; /* user name */ ! 184: int look_smart; /* do we try to route through a smarter host? */ ! 185: char *result; /* output route */ ! 186: int *cost; /* cost of output route */ ! 187: { ! 188: int uucpdom = 0; ! 189: int domains, step; /* to split domain */ ! 190: char *domainv[MAXDOMS]; /* " " " */ ! 191: char temp[SMLBUF], path[SMLBUF]; ! 192: ! 193: /* ! 194: ** Fully qualify the domain, and then strip the last (top level domain) ! 195: ** component off, so that we look it up separately. ! 196: */ ! 197: temp[0] = '.'; ! 198: (void) strcpy(temp+1, domain ); ! 199: ! 200: domains = ssplit( temp+1, '.', domainv ); ! 201: ! 202: /* ! 203: ** check target domain for the local host name and host domain. ! 204: ** if it matches, then skip the lookup in the database. ! 205: ** this prevents mail loops for cases where SMARTHOST is defined ! 206: ** in the routing table, but the local host is not. It also is ! 207: ** a little faster when the local host is the target domain. ! 208: */ ! 209: if((strcmpic(domain, hostname) == 0) ! 210: || (strcmpic(domain, hostdomain) == 0)) { ! 211: step = 0; ! 212: *cost = 0; ! 213: (void) strcpy(path, "%s"); ! 214: DEBUG("route: '%s' is local\n", domain); ! 215: goto route_complete; ! 216: } ! 217: ! 218: /* If the domain ends in .UUCP, trim that off. */ ! 219: if((domains > 0) && isuucp(domainv[domains-1])) { ! 220: domains--; ! 221: domainv[domains][-1] = '\0'; ! 222: uucpdom = 1; ! 223: } ! 224: /* ! 225: ** Try to get the path for successive components of the domain. ! 226: ** Example for osgd.cb.att.uucp: ! 227: ** osgd.cb.att ! 228: ** cb.att ! 229: ** att ! 230: ** uucp ( remember stripping top level? ) ! 231: ** SMARTHOST ! 232: ** Returns with error if we find no path. ! 233: */ ! 234: for(step = 0; (step < domains); step++) { ! 235: if((getpath(domainv[step]-1, path, cost) == EX_OK) /* w/ dot */ ! 236: || (getpath(domainv[step] , path, cost) == EX_OK))/* no dot */ ! 237: break; ! 238: } ! 239: ! 240: if(step == domains) { ! 241: /* ! 242: ** we've looked at each component of the domain without success ! 243: */ ! 244: /* ! 245: ** If domain is a UUCP address, look for a UUCP gateway. ! 246: */ ! 247: if((uucpdom == 0) || (getpath(".UUCP", path, cost) != EX_OK)) { ! 248: /* ! 249: ** The domain not is a UUCP address, or we can't ! 250: ** find a UUCP gateway. If this is our last chance, ! 251: ** look for a smarter host to deliver the mail. ! 252: */ ! 253: if((look_smart == 0) ! 254: || (getpath(SMARTHOST, path, cost) != EX_OK)) { ! 255: /* ! 256: ** All our efforts have been in vain. ! 257: ** Tell them the bad news. ! 258: */ ! 259: DEBUG("route '%s' failed\n", domain); ! 260: return( EX_NOHOST ); ! 261: } ! 262: } ! 263: } ! 264: ! 265: route_complete: ! 266: ! 267: DEBUG("route: '%s' (%s) = '%s' (%d)\n", domain, domainv[step]?domainv[step]:"NULL", path, *cost); ! 268: ! 269: /* ! 270: ** If we matched on the entire domain name, this address is fully resolved, ! 271: ** and we plug <user> into it. If we matched on only part of the domain ! 272: ** name, we plug <domain>!<user> in. ! 273: */ ! 274: build(domain, user, (step == 0) ? LOCAL : UUCP, temp); ! 275: (void) sprintf(result, path, temp); ! 276: return( EX_OK ); ! 277: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.