1: /* 2: ******************************************************************************* 3: * 4: * subr.c -- 5: * 6: * Miscellaneous subroutines for the name server 7: * lookup program. 8: * 9: * Copyright (c) 1985 10: * Andrew Cherenson 11: * CS298-26 Fall 1985 12: * 13: * Copyright (c) 1985 Regents of the University of California. 14: * All rights reserved. The Berkeley software License Agreement 15: * specifies the terms and conditions for redistribution. 16: * 17: ******************************************************************************* 18: */ 19: 20: #ifndef lint 21: static char sccsid[] = "@(#)subr.c 5.3 (Berkeley) 5/1/86"; 22: #endif not lint 23: 24: #include <stdio.h> 25: #include <strings.h> 26: #include <sys/types.h> 27: #include <netdb.h> 28: #include <sys/socket.h> 29: #include <netinet/in.h> 30: #include <arpa/nameser.h> 31: #include <signal.h> 32: #include <setjmp.h> 33: #include "res.h" 34: 35: 36: 37: /* 38: ******************************************************************************* 39: * 40: * IntrHandler -- 41: * 42: * This routine is called whenever a control-C is typed. 43: * It performs three main functions: 44: * - close an open socket connection. 45: * - close an open output file (used by LookupHost, et al.) 46: * - jump back to the main read-eval loop. 47: * 48: * Since a user may type a ^C in the middle of a routine that 49: * is using a socket, the socket would never get closed by the 50: * routine. To prevent an overflow of the process's open file table, 51: * the socket and output file descriptors are closed by 52: * the interrupt handler. 53: * 54: * Side effects: 55: * If sockFD is valid, its socket is closed. 56: * If filePtr is valid, its file is closed. 57: * Flow of control returns to the main() routine. 58: * 59: ******************************************************************************* 60: */ 61: 62: int 63: IntrHandler() 64: { 65: extern jmp_buf env; 66: 67: if (sockFD >= 0) { 68: close(sockFD); 69: sockFD = -1; 70: } 71: if (filePtr != NULL && filePtr != stdout) { 72: fclose(filePtr); 73: filePtr = NULL; 74: } 75: printf("\n"); 76: longjmp(env, 1); 77: } 78: 79: 80: /* 81: ******************************************************************************* 82: * 83: * Calloc -- 84: * 85: * Calls the calloc library routine with the interrupt 86: * signal blocked. The interrupt signal blocking is done 87: * to prevent malloc from getting confused if a 88: * control-C arrives in the middle of its bookkeeping 89: * routines. We need to do this because a control-C 90: * causes a return to the main command loop instead 91: * causing the program to die. 92: * 93: * This method doesn't prevent the pointer returned 94: * by calloc from getting lost, so it is possible 95: * to get "core leaks". 96: * 97: * Results: 98: * (address) - address of new buffer. 99: * NULL - calloc failed. 100: * 101: ******************************************************************************* 102: */ 103: 104: char * 105: Calloc(num, size) 106: unsigned num, size; 107: { 108: char *ptr; 109: int saveMask; 110: extern char *calloc(); 111: 112: saveMask = sigblock(1 << (SIGINT-1)); 113: ptr = calloc(num, size); 114: (void) sigsetmask(saveMask); 115: if (ptr == NULL) { 116: fflush(stdout); 117: fprintf(stderr, "Calloc failed\n"); 118: fflush(stderr); 119: abort(); 120: /*NOTREACHED*/ 121: } else { 122: return(ptr); 123: } 124: } 125: 126: /* 127: ******************************************************************************* 128: * 129: * PrintHostInfo -- 130: * 131: * Prints out the HostInfo structure for a host. 132: * 133: ******************************************************************************* 134: */ 135: 136: void 137: PrintHostInfo(file, title, hp) 138: FILE *file; 139: char *title; 140: register HostInfo *hp; 141: { 142: register char **cp; 143: register ServerInfo **sp; 144: char comma; 145: int i; 146: 147: fprintf(file, "%-7s %s\n", title, hp->name); 148: 149: if (hp->addrList != NULL) { 150: if (hp->addrList[1] != NULL) { 151: fprintf(file, "Addresses:"); 152: } else { 153: fprintf(file, "Address:"); 154: } 155: comma = ' '; 156: i = 0; 157: for (cp = hp->addrList; cp && *cp && **cp; cp++) { 158: i++; 159: if (i > 4) { 160: fprintf(file, "\n\t"); 161: comma = ' '; 162: i = 0; 163: } 164: fprintf(file,"%c %s", comma, inet_ntoa(*(struct in_addr *)*cp)); 165: comma = ','; 166: } 167: } 168: 169: if (hp->aliases != NULL) { 170: fprintf(file, "\nAliases:"); 171: comma = ' '; 172: i = 10; 173: for (cp = hp->aliases; cp && *cp && **cp; cp++) { 174: i += strlen(*cp) + 2; 175: if (i > 75) { 176: fprintf(file, "\n\t"); 177: comma = ' '; 178: i = 10; 179: } 180: fprintf(file, "%c %s", comma, *cp); 181: comma = ','; 182: } 183: } 184: 185: if (hp->servers != NULL) { 186: fprintf(file, "Served by:\n"); 187: for (sp = hp->servers; *sp != NULL ; sp++) { 188: 189: fprintf(file, "- %s\n\t", (*sp)->name); 190: 191: comma = ' '; 192: i = 0; 193: for (cp = (*sp)->addrList; cp && *cp && **cp; cp++) { 194: i++; 195: if (i > 4) { 196: fprintf(file, "\n\t"); 197: comma = ' '; 198: i = 0; 199: } 200: fprintf(file, 201: "%c %s", comma, inet_ntoa(*(struct in_addr *)*cp)); 202: comma = ','; 203: } 204: fprintf(file, "\n\t"); 205: 206: comma = ' '; 207: i = 10; 208: for (cp = (*sp)->domains; cp && *cp && **cp; cp++) { 209: i += strlen(*cp) + 2; 210: if (i > 75) { 211: fprintf(file, "\n\t"); 212: comma = ' '; 213: i = 10; 214: } 215: fprintf(file, "%c %s", comma, *cp); 216: comma = ','; 217: } 218: fprintf(file, "\n"); 219: } 220: } 221: 222: fprintf(file, "\n\n"); 223: } 224: 225: /* 226: ******************************************************************************* 227: * 228: * OpenFile -- 229: * 230: * Parses a command string for a file name and opens 231: * the file. 232: * 233: * Results: 234: * file pointer - the open was successful. 235: * NULL - there was an error opening the file or 236: * the input string was invalid. 237: * 238: ******************************************************************************* 239: */ 240: 241: FILE * 242: OpenFile(string, file) 243: char *string; 244: char *file; 245: { 246: char *redirect; 247: FILE *tmpPtr; 248: 249: /* 250: * Open an output file if we see '>' or >>'. 251: * Check for overwrite (">") or concatenation (">>"). 252: */ 253: 254: redirect = index(string, '>'); 255: if (redirect == NULL) { 256: return(NULL); 257: } 258: if (redirect[1] == '>') { 259: sscanf(redirect, ">> %s", file); 260: tmpPtr = fopen(file, "a+"); 261: } else { 262: sscanf(redirect, "> %s", file); 263: tmpPtr = fopen(file, "w"); 264: } 265: 266: if (tmpPtr != NULL) { 267: redirect[0] = '\0'; 268: } 269: 270: return(tmpPtr); 271: } 272: 273: /* 274: ******************************************************************************* 275: * 276: * DecodeError -- 277: * 278: * Converts an error code into a character string. 279: * 280: ******************************************************************************* 281: */ 282: 283: char * 284: DecodeError(result) 285: int result; 286: { 287: switch(result) { 288: case NOERROR: return("Success"); break; 289: case FORMERR: return("Format error"); break; 290: case SERVFAIL: return("Server failed"); break; 291: case NXDOMAIN: return("Non-existent domain"); break; 292: case NOTIMP: return("Not implemented"); break; 293: case REFUSED: return("Query refused"); break; 294: case NOCHANGE: return("No change"); break; 295: case NO_INFO: return("No information"); break; 296: case ERROR: return("Unspecified error"); break; 297: case TIME_OUT: return("Timed out"); break; 298: case NONAUTH: return("Non-authoritative answer"); break; 299: default: break; 300: } 301: return("BAD ERROR VALUE"); 302: } 303: 304: /* 305: ******************************************************************************* 306: * 307: * StringToType -- 308: * 309: * Converts a string form of a query type name to its 310: * corresponding integer value. 311: * 312: ******************************************************************************* 313: */ 314: 315: int 316: StringToType(type) 317: char *type; 318: { 319: if (strcmp(type, "A") == 0) { 320: return(T_A); 321: } else if (strcmp(type, "NS") == 0) { 322: return(T_NS); /* authoritative server */ 323: } else if (strcmp(type, "MX") == 0) { 324: return(T_MX); /* mail exchanger */ 325: } else if (strcmp(type, "CNAME") == 0) { 326: return(T_CNAME); /* canonical name */ 327: } else if (strcmp(type, "SOA") == 0) { 328: return(T_SOA); /* start of authority zone */ 329: } else if (strcmp(type, "MB") == 0) { 330: return(T_MB); /* mailbox domain name */ 331: } else if (strcmp(type, "MG") == 0) { 332: return(T_MG); /* mail group member */ 333: } else if (strcmp(type, "MR") == 0) { 334: return(T_MR); /* mail rename name */ 335: } else if (strcmp(type, "WKS") == 0) { 336: return(T_WKS); /* well known service */ 337: } else if (strcmp(type, "PTR") == 0) { 338: return(T_PTR); /* domain name pointer */ 339: } else if (strcmp(type, "HINFO") == 0) { 340: return(T_HINFO); /* host information */ 341: } else if (strcmp(type, "MINFO") == 0) { 342: return(T_MINFO); /* mailbox information */ 343: } else if (strcmp(type, "AXFR") == 0) { 344: return(T_AXFR); /* zone transfer */ 345: } else if (strcmp(type, "MAILB") == 0) { 346: return(T_MAILB); /* mail box */ 347: } else if (strcmp(type, "ANY") == 0) { 348: return(T_ANY); /* matches any type */ 349: } else if (strcmp(type, "UINFO") == 0) { 350: return(T_UINFO); /* user info */ 351: } else if (strcmp(type, "UID") == 0) { 352: return(T_UID); /* user id */ 353: } else if (strcmp(type, "GID") == 0) { 354: return(T_GID); /* group id */ 355: } else { 356: return(T_A); 357: } 358: } 359: 360: /* 361: ******************************************************************************* 362: * 363: * DecodeType -- 364: * 365: * Converts a query type to a descriptive name. 366: * (A more verbose form of p_type.) 367: * 368: * 369: ******************************************************************************* 370: */ 371: 372: static char nbuf[20]; 373: extern char *sprintf(); 374: 375: char * 376: DecodeType(type) 377: int type; 378: { 379: switch (type) { 380: case T_A: 381: return("address"); 382: case T_NS: 383: return("name server"); 384: case T_MX: 385: return("mail exchanger"); 386: case T_CNAME: 387: return("cannonical name"); 388: case T_SOA: 389: return("start of authority zone"); 390: case T_MB: 391: return("mailbox domain name"); 392: case T_MG: 393: return("mail group member"); 394: case T_MR: 395: return("mail rename name"); 396: case T_NULL: 397: return("null resource record"); 398: case T_WKS: 399: return("well known service"); 400: case T_PTR: 401: return("domain name pointer"); 402: case T_HINFO: 403: return("host"); 404: case T_MINFO: 405: return("mailbox (MINFO)"); 406: case T_AXFR: 407: return("zone transfer"); 408: case T_MAILB: 409: return("mail box"); 410: case T_ANY: 411: return("any type"); 412: case T_UINFO: 413: return("user info"); 414: case T_UID: 415: return("user id"); 416: case T_GID: 417: return("group id"); 418: default: 419: return (sprintf(nbuf, "%d", type)); 420: } 421: } 422: 423: printanswer(hp) 424: register struct hostent *hp; 425: { 426: register char **cp; 427: int i; 428: char comma; 429: extern char *inet_ntoa(); 430: 431: fprintf(stderr,"Name: %s\n", hp->h_name); 432: fprintf(stderr,"Address: %s\n", 433: inet_ntoa(*(struct in_addr *)hp->h_addr)); 434: if (hp->h_aliases != NULL) { 435: fprintf(stderr, "Aliases:"); 436: comma = ' '; 437: i = 10; 438: for (cp = hp->h_aliases; cp && *cp && **cp; cp++) { 439: i += strlen(*cp) + 2; 440: if (i > 75) { 441: fprintf(stderr, "\n\t"); 442: comma = ' '; 443: i = 10; 444: } 445: fprintf(stderr, "%c %s", comma, *cp); 446: comma = ','; 447: } 448: } 449: fprintf(stderr,"\n\n"); 450: } 451: 452: hperror(errno) 453: int errno; 454: { 455: switch(errno) { 456: case HOST_NOT_FOUND: 457: fprintf(stderr,"Host not found.\n"); 458: break; 459: case TRY_AGAIN: 460: fprintf(stderr,"Host not found, try again.\n"); 461: break; 462: case NO_RECOVERY: 463: fprintf(stderr,"No recovery, Host not found.\n"); 464: break; 465: case NO_ADDRESS: 466: fprintf(stderr,"No Address, look for MF record.\n"); 467: break; 468: } 469: }