1: /* 2: * Copyright (c) 1985,1989 Regents of the University of California. 3: * All rights reserved. 4: * 5: * Redistribution and use in source and binary forms are permitted provided 6: * that: (1) source distributions retain this entire copyright notice and 7: * comment, and (2) distributions including binaries display the following 8: * acknowledgement: ``This product includes software developed by the 9: * University of California, Berkeley and its contributors'' in the 10: * documentation or other materials provided with the distribution and in 11: * all advertising materials mentioning features or use of this software. 12: * Neither the name of the University nor the names of its contributors may 13: * be used to endorse or promote products derived from this software without 14: * specific prior written permission. 15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 16: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 17: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 18: */ 19: 20: #if !defined(lint) && defined(DOSCCS) 21: static char sccsid[] = "@(#)subr.c 5.22 (Berkeley) 8/3/90"; 22: #endif 23: 24: /* 25: ******************************************************************************* 26: * 27: * subr.c -- 28: * 29: * Miscellaneous subroutines for the name server 30: * lookup program. 31: * 32: * Copyright (c) 1985 33: * Andrew Cherenson 34: * U.C. Berkeley 35: * CS298-26 Fall 1985 36: * 37: ******************************************************************************* 38: */ 39: 40: #include <sys/types.h> 41: #include <netdb.h> 42: #include <sys/socket.h> 43: #include <netinet/in.h> 44: #include <arpa/nameser.h> 45: #include <arpa/inet.h> 46: #include <signal.h> 47: #include <setjmp.h> 48: #include <stdio.h> 49: #include <string.h> 50: #include "res.h" 51: 52: 53: 54: /* 55: ******************************************************************************* 56: * 57: * IntrHandler -- 58: * 59: * This routine is called whenever a control-C is typed. 60: * It performs three main functions: 61: * - closes an open socket connection, 62: * - closes an open output file (used by LookupHost, et al.), 63: * - jumps back to the main read-eval loop. 64: * 65: * If a user types a ^C in the middle of a routine that uses a socket, 66: * the routine would not be able to close the socket. To prevent an 67: * overflow of the process's open file table, the socket and output 68: * file descriptors are closed by the interrupt handler. 69: * 70: * Side effects: 71: * Open file descriptors are closed. 72: * If filePtr is valid, it is closed. 73: * Flow of control returns to the main() routine. 74: * 75: ******************************************************************************* 76: */ 77: 78: #ifdef SVR3 79: void 80: #else 81: int 82: #endif 83: IntrHandler() 84: { 85: extern jmp_buf env; 86: #if defined(BSD) && BSD >= 199006 87: extern FILE *yyin; /* scanner input file */ 88: extern void yyrestart(); /* routine to restart scanner after interrupt */ 89: #endif 90: 91: SendRequest_close(); 92: ListHost_close(); 93: if (filePtr != NULL && filePtr != stdout) { 94: fclose(filePtr); 95: filePtr = NULL; 96: } 97: printf("\n"); 98: #if defined(BSD) && BSD >= 199006 99: yyrestart(yyin); 100: #endif 101: longjmp(env, 1); 102: } 103: 104: 105: /* 106: ******************************************************************************* 107: * 108: * Malloc -- 109: * Calloc -- 110: * 111: * Calls the malloc library routine with SIGINT blocked to prevent 112: * corruption of malloc's data structures. We need to do this because 113: * a control-C doesn't kill the program -- it causes a return to the 114: * main command loop. 115: * 116: * NOTE: This method doesn't prevent the pointer returned by malloc 117: * from getting lost, so it is possible to get "core leaks". 118: * 119: * If malloc fails, the program exits. 120: * 121: * Results: 122: * (address) - address of new buffer. 123: * 124: ******************************************************************************* 125: */ 126: 127: char * 128: Malloc(size) 129: int size; 130: { 131: char *ptr; 132: 133: #ifdef SYSV 134: #ifdef SVR3 135: sighold(SIGINT); 136: ptr = malloc((unsigned) size); 137: sigrelse(SIGINT); 138: #else 139: { int (*old)(); 140: old = signal(SIGINT, SIG_IGN); 141: ptr = malloc((unsigned) size); 142: signal(SIGINT, old); 143: } 144: #endif 145: #else 146: { long saveMask; 147: saveMask = sigblock(sigmask(SIGINT)); 148: ptr = (char *)malloc((unsigned) size); 149: (void) sigsetmask(saveMask); 150: } 151: #endif 152: if (ptr == NULL) { 153: fflush(stdout); 154: fprintf(stderr, "*** Can't allocate memory\n"); 155: fflush(stderr); 156: abort(); 157: /*NOTREACHED*/ 158: } else { 159: return(ptr); 160: } 161: } 162: 163: char * 164: Calloc(num, size) 165: register int num, size; 166: { 167: char *ptr = Malloc(num*size); 168: bzero(ptr, num*size); 169: return(ptr); 170: } 171: 172: 173: /* 174: ******************************************************************************* 175: * 176: * PrintHostInfo -- 177: * 178: * Prints out the HostInfo structure for a host. 179: * 180: ******************************************************************************* 181: */ 182: 183: void 184: PrintHostInfo(file, title, hp) 185: FILE *file; 186: char *title; 187: register HostInfo *hp; 188: { 189: register char **cp; 190: register ServerInfo **sp; 191: char comma; 192: int i; 193: 194: fprintf(file, "%-7s %s", title, hp->name); 195: 196: if (hp->addrList != NULL) { 197: if (hp->addrList[1] != NULL) { 198: fprintf(file, "\nAddresses:"); 199: } else { 200: fprintf(file, "\nAddress:"); 201: } 202: comma = ' '; 203: i = 0; 204: for (cp = hp->addrList; cp && *cp; cp++) { 205: i++; 206: if (i > 4) { 207: fprintf(file, "\n\t"); 208: comma = ' '; 209: i = 0; 210: } 211: fprintf(file,"%c %s", comma, inet_ntoa(*(struct in_addr *)*cp)); 212: comma = ','; 213: } 214: } 215: 216: if (hp->aliases != NULL) { 217: fprintf(file, "\nAliases:"); 218: comma = ' '; 219: i = 10; 220: for (cp = hp->aliases; cp && *cp && **cp; cp++) { 221: i += strlen(*cp) + 2; 222: if (i > 75) { 223: fprintf(file, "\n\t"); 224: comma = ' '; 225: i = 10; 226: } 227: fprintf(file, "%c %s", comma, *cp); 228: comma = ','; 229: } 230: } 231: 232: if (hp->servers != NULL) { 233: fprintf(file, "\nServed by:\n"); 234: for (sp = hp->servers; *sp != NULL ; sp++) { 235: 236: fprintf(file, "- %s\n\t", (*sp)->name); 237: 238: comma = ' '; 239: i = 0; 240: for (cp = (*sp)->addrList; cp && *cp && **cp; cp++) { 241: i++; 242: if (i > 4) { 243: fprintf(file, "\n\t"); 244: comma = ' '; 245: i = 0; 246: } 247: fprintf(file, 248: "%c %s", comma, inet_ntoa(*(struct in_addr *)*cp)); 249: comma = ','; 250: } 251: fprintf(file, "\n\t"); 252: 253: comma = ' '; 254: i = 10; 255: for (cp = (*sp)->domains; cp && *cp && **cp; cp++) { 256: i += strlen(*cp) + 2; 257: if (i > 75) { 258: fprintf(file, "\n\t"); 259: comma = ' '; 260: i = 10; 261: } 262: fprintf(file, "%c %s", comma, *cp); 263: comma = ','; 264: } 265: fprintf(file, "\n"); 266: } 267: } 268: 269: fprintf(file, "\n\n"); 270: } 271: 272: /* 273: ******************************************************************************* 274: * 275: * OpenFile -- 276: * 277: * Parses a command string for a file name and opens 278: * the file. 279: * 280: * Results: 281: * file pointer - the open was successful. 282: * NULL - there was an error opening the file or 283: * the input string was invalid. 284: * 285: ******************************************************************************* 286: */ 287: 288: FILE * 289: OpenFile(string, file) 290: char *string; 291: char *file; 292: { 293: char *redirect; 294: FILE *tmpPtr; 295: 296: /* 297: * Open an output file if we see '>' or >>'. 298: * Check for overwrite (">") or concatenation (">>"). 299: */ 300: 301: redirect = strchr(string, '>'); 302: if (redirect == NULL) { 303: return(NULL); 304: } 305: if (redirect[1] == '>') { 306: sscanf(redirect, ">> %s", file); 307: tmpPtr = fopen(file, "a+"); 308: } else { 309: sscanf(redirect, "> %s", file); 310: tmpPtr = fopen(file, "w"); 311: } 312: 313: if (tmpPtr != NULL) { 314: redirect[0] = '\0'; 315: } 316: 317: return(tmpPtr); 318: } 319: 320: /* 321: ******************************************************************************* 322: * 323: * DecodeError -- 324: * 325: * Converts an error code into a character string. 326: * 327: ******************************************************************************* 328: */ 329: 330: char * 331: DecodeError(result) 332: int result; 333: { 334: switch (result) { 335: case NOERROR: return("Success"); break; 336: case FORMERR: return("Format error"); break; 337: case SERVFAIL: return("Server failed"); break; 338: case NXDOMAIN: return("Non-existent domain"); break; 339: case NOTIMP: return("Not implemented"); break; 340: case REFUSED: return("Query refused"); break; 341: case NOCHANGE: return("No change"); break; 342: case TIME_OUT: return("Timed out"); break; 343: case NO_INFO: return("No information"); break; 344: case ERROR: return("Unspecified error"); break; 345: case NONAUTH: return("Non-authoritative answer"); break; 346: case NO_RESPONSE: return("No response from server"); break; 347: default: break; 348: } 349: return("BAD ERROR VALUE"); 350: } 351: 352: 353: int 354: StringToClass(class, dflt) 355: char *class; 356: int dflt; 357: { 358: if (strcasecmp(class, "IN") == 0) 359: return(C_IN); 360: if (strcasecmp(class, "HESIOD") == 0 || 361: strcasecmp(class, "HS") == 0) 362: return(C_HS); 363: if (strcasecmp(class, "CHAOS") == 0) 364: return(C_CHAOS); 365: if (strcasecmp(class, "ANY") == 0) 366: return(C_ANY); 367: fprintf(stderr, "unknown query class: %s\n", class); 368: return(dflt); 369: } 370: 371: 372: /* 373: ******************************************************************************* 374: * 375: * StringToType -- 376: * 377: * Converts a string form of a query type name to its 378: * corresponding integer value. 379: * 380: ******************************************************************************* 381: */ 382: 383: int 384: StringToType(type, dflt) 385: char *type; 386: int dflt; 387: { 388: if (strcasecmp(type, "A") == 0) 389: return(T_A); 390: if (strcasecmp(type, "NS") == 0) 391: return(T_NS); /* authoritative server */ 392: if (strcasecmp(type, "MX") == 0) 393: return(T_MX); /* mail exchanger */ 394: if (strcasecmp(type, "CNAME") == 0) 395: return(T_CNAME); /* canonical name */ 396: if (strcasecmp(type, "SOA") == 0) 397: return(T_SOA); /* start of authority zone */ 398: if (strcasecmp(type, "MB") == 0) 399: return(T_MB); /* mailbox domain name */ 400: if (strcasecmp(type, "MG") == 0) 401: return(T_MG); /* mail group member */ 402: if (strcasecmp(type, "MR") == 0) 403: return(T_MR); /* mail rename name */ 404: if (strcasecmp(type, "WKS") == 0) 405: return(T_WKS); /* well known service */ 406: if (strcasecmp(type, "PTR") == 0) 407: return(T_PTR); /* domain name pointer */ 408: if (strcasecmp(type, "HINFO") == 0) 409: return(T_HINFO); /* host information */ 410: if (strcasecmp(type, "MINFO") == 0) 411: return(T_MINFO); /* mailbox information */ 412: if (strcasecmp(type, "AXFR") == 0) 413: return(T_AXFR); /* zone transfer */ 414: if (strcasecmp(type, "MAILA") == 0) 415: return(T_MAILA); /* mail agent */ 416: if (strcasecmp(type, "MAILB") == 0) 417: return(T_MAILB); /* mail box */ 418: if (strcasecmp(type, "ANY") == 0) 419: return(T_ANY); /* matches any type */ 420: if (strcasecmp(type, "UINFO") == 0) 421: return(T_UINFO); /* user info */ 422: if (strcasecmp(type, "UID") == 0) 423: return(T_UID); /* user id */ 424: if (strcasecmp(type, "GID") == 0) 425: return(T_GID); /* group id */ 426: if (strcasecmp(type, "TXT") == 0) 427: return(T_TXT); /* text */ 428: fprintf(stderr, "unknown query type: %s\n", type); 429: return(dflt); 430: } 431: 432: /* 433: ******************************************************************************* 434: * 435: * DecodeType -- 436: * 437: * Converts a query type to a descriptive name. 438: * (A more verbose form of p_type.) 439: * 440: * 441: ******************************************************************************* 442: */ 443: 444: static char nbuf[20]; 445: 446: char * 447: DecodeType(type) 448: int type; 449: { 450: switch (type) { 451: case T_A: 452: return("address"); 453: case T_NS: 454: return("name server"); 455: case T_CNAME: 456: return("canonical name"); 457: case T_SOA: 458: return("start of authority"); 459: case T_MB: 460: return("mailbox"); 461: case T_MG: 462: return("mail group member"); 463: case T_MR: 464: return("mail rename"); 465: case T_NULL: 466: return("null"); 467: case T_WKS: 468: return("well-known service"); 469: case T_PTR: 470: return("domain name pointer"); 471: case T_HINFO: 472: return("host information"); 473: case T_MINFO: 474: return("mailbox information"); 475: case T_MX: 476: return("mail exchanger"); 477: case T_TXT: 478: return("text"); 479: case T_UINFO: 480: return("user information"); 481: case T_UID: 482: return("user ID"); 483: case T_GID: 484: return("group ID"); 485: case T_AXFR: 486: return("zone transfer"); 487: case T_MAILB: 488: return("mailbox-related data"); 489: case T_MAILA: 490: return("mail agent"); 491: case T_ANY: 492: return("\"any\""); 493: default: 494: (void) sprintf(nbuf, "%d", type); 495: return (nbuf); 496: } 497: }