]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/bind/bin/nslookup/subr.c
unfinished sblive driver, playback/mixer only for now - not enabled in
[FreeBSD/FreeBSD.git] / contrib / bind / bin / nslookup / subr.c
1 /*
2  * Copyright (c) 1985, 1989
3  *    The Regents of the University of California.  All rights reserved.
4  * 
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by the University of
16  *      California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  * 
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33
34 /*
35  * Portions Copyright (c) 1993 by Digital Equipment Corporation.
36  * 
37  * Permission to use, copy, modify, and distribute this software for any
38  * purpose with or without fee is hereby granted, provided that the above
39  * copyright notice and this permission notice appear in all copies, and that
40  * the name of Digital Equipment Corporation not be used in advertising or
41  * publicity pertaining to distribution of the document or software without
42  * specific, written prior permission.
43  * 
44  * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
45  * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
46  * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
47  * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
48  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
49  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
50  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
51  * SOFTWARE.
52  */
53
54 #ifndef lint
55 static const char sccsid[] = "@(#)subr.c        5.24 (Berkeley) 3/2/91";
56 static const char rcsid[] = "$Id: subr.c,v 8.13 1999/10/13 16:39:20 vixie Exp $";
57 #endif /* not lint */
58
59 /*
60  *******************************************************************************
61  *
62  *  subr.c --
63  *
64  *      Miscellaneous subroutines for the name server
65  *      lookup program.
66  *
67  *      Copyright (c) 1985
68  *      Andrew Cherenson
69  *      U.C. Berkeley
70  *      CS298-26  Fall 1985
71  *
72  *******************************************************************************
73  */
74
75 #include "port_before.h"
76
77 #include <sys/types.h>
78 #include <sys/param.h>
79 #include <sys/socket.h>
80
81 #include <netinet/in.h>
82 #include <arpa/nameser.h>
83 #include <arpa/inet.h>
84
85 #include <netdb.h>
86 #include <setjmp.h>
87 #include <signal.h>
88 #include <stdio.h>
89 #include <stdlib.h>
90 #include <string.h>
91
92 #include "port_after.h"
93
94 #include "resolv.h"
95 #include "res.h"
96
97 /*
98  *******************************************************************************
99  *
100  *  IntrHandler --
101  *
102  *      This routine is called whenever a control-C is typed.
103  *      It performs three main functions:
104  *       - closes an open socket connection,
105  *       - closes an open output file (used by LookupHost, et al.),
106  *       - jumps back to the main read-eval loop.
107  *
108  *      If a user types a ^C in the middle of a routine that uses a socket,
109  *      the routine would not be able to close the socket. To prevent an
110  *      overflow of the process's open file table, the socket and output
111  *      file descriptors are closed by the interrupt handler.
112  *
113  *  Side effects:
114  *      Open file descriptors are closed.
115  *      If filePtr is valid, it is closed.
116  *      Flow of control returns to the main() routine.
117  *
118  *******************************************************************************
119  */
120
121 SIG_FN
122 IntrHandler()
123 {
124     extern jmp_buf env;
125 #if defined(BSD) && BSD >= 199006 && !defined(RISCOS_BSD) && !defined(__osf__)
126     extern FILE *yyin;          /* scanner input file */
127     extern void yyrestart();    /* routine to restart scanner after interrupt */
128 #endif
129     extern void ListHost_close(void);
130
131     SendRequest_close();
132     ListHost_close();
133     if (filePtr != NULL && filePtr != stdout) {
134         fclose(filePtr);
135         filePtr = NULL;
136     }
137     printf("\n");
138 #if defined(BSD) && BSD >= 199006 && !defined(RISCOS_BSD) && !defined(__osf__)
139     yyrestart(yyin);
140 #endif
141     longjmp(env, 1);
142 }
143 \f
144
145 /*
146  *******************************************************************************
147  *
148  *  Malloc --
149  *  Calloc --
150  *
151  *      Calls the malloc library routine with SIGINT blocked to prevent
152  *      corruption of malloc's data structures. We need to do this because
153  *      a control-C doesn't kill the program -- it causes a return to the
154  *      main command loop.
155  *
156  *      NOTE: This method doesn't prevent the pointer returned by malloc
157  *      from getting lost, so it is possible to get "core leaks".
158  *
159  *      If malloc fails, the program exits.
160  *
161  *  Results:
162  *      (address)       - address of new buffer.
163  *
164  *******************************************************************************
165  */
166
167 char *
168 Malloc(size)
169     int size;
170 {
171     char        *ptr;
172
173 #ifdef SYSV
174 #if defined(SVR3) || defined(SVR4)
175     sighold(SIGINT);
176     ptr = malloc((unsigned) size);
177     sigrelse(SIGINT);
178 #else
179     { SIG_FN (*old)();
180       old = signal(SIGINT, SIG_IGN);
181       ptr = malloc((unsigned) size);
182       signal(SIGINT, old);
183     }
184 #endif
185 #else
186 #ifdef POSIX_SIGNALS
187     { sigset_t sset;
188       sigemptyset(&sset);
189       sigaddset(&sset,SIGINT);
190       sigprocmask(SIG_BLOCK,&sset,NULL);
191       ptr = malloc((unsigned) size);
192       sigprocmask(SIG_UNBLOCK,&sset,NULL);
193     }
194 #else
195     { int saveMask;
196       saveMask = sigblock(sigmask(SIGINT));
197       ptr = malloc((unsigned) size);
198       (void) sigsetmask(saveMask);
199     }
200 #endif
201 #endif
202     if (ptr == NULL) {
203         fflush(stdout);
204         fprintf(stderr, "*** Can't allocate memory\n");
205         fflush(stderr);
206         abort();
207         /*NOTREACHED*/
208     }
209     return (ptr);
210 }
211
212 char *
213 Calloc(num, size)
214     register int num, size;
215 {
216     char *ptr = Malloc(num*size);
217     memset(ptr, 0, num*size);
218     return(ptr);
219 }
220
221 \f
222 /*
223  *******************************************************************************
224  *
225  *  PrintHostInfo --
226  *
227  *      Prints out the HostInfo structure for a host.
228  *
229  *******************************************************************************
230  */
231
232 void
233 PrintHostInfo(file, title, hp)
234         FILE    *file;
235         char    *title;
236         register HostInfo *hp;
237 {
238         register char           **cp;
239         register ServerInfo     **sp;
240         char                    comma;
241         int                     i;
242
243         fprintf(file, "%-7s  %s", title, hp->name);
244
245         if (hp->addrList != NULL) {
246             if (hp->addrList[1] != NULL) {
247                 fprintf(file, "\nAddresses:");
248             } else {
249                 fprintf(file, "\nAddress:");
250             }
251             comma = ' ';
252             i = 0;
253             for (cp = hp->addrList; cp && *cp; cp++) {
254                 i++;
255                 if (i > 4) {
256                     fprintf(file, "\n\t");
257                     comma = ' ';
258                     i = 0;
259                 }
260                 fprintf(file,"%c %s", comma, inet_ntoa(*(struct in_addr *)*cp));
261                 comma = ',';
262             }
263         }
264
265         if (hp->aliases != NULL) {
266             fprintf(file, "\nAliases:");
267             comma = ' ';
268             i = 10;
269             for (cp = hp->aliases; cp && *cp && **cp; cp++) {
270                 i += strlen(*cp) + 2;
271                 if (i > 75) {
272                     fprintf(file, "\n\t");
273                     comma = ' ';
274                     i = 10;
275                 }
276                 fprintf(file, "%c %s", comma, *cp);
277                 comma = ',';
278             }
279         }
280
281         if (hp->servers != NULL) {
282             fprintf(file, "\nServed by:\n");
283             for (sp = hp->servers; *sp != NULL ; sp++) {
284
285                 fprintf(file, "- %s\n\t",  (*sp)->name);
286
287                 comma = ' ';
288                 i = 0;
289                 for (cp = (*sp)->addrList; cp && *cp && **cp; cp++) {
290                     i++;
291                     if (i > 4) {
292                         fprintf(file, "\n\t");
293                         comma = ' ';
294                         i = 0;
295                     }
296                     fprintf(file,
297                         "%c %s", comma, inet_ntoa(*(struct in_addr *)*cp));
298                     comma = ',';
299                 }
300                 fprintf(file, "\n\t");
301
302                 comma = ' ';
303                 i = 10;
304                 for (cp = (*sp)->domains; cp && *cp && **cp; cp++) {
305                     i += strlen(*cp) + 2;
306                     if (i > 75) {
307                         fprintf(file, "\n\t");
308                         comma = ' ';
309                         i = 10;
310                     }
311                     fprintf(file, "%c %s", comma, *cp);
312                     comma = ',';
313                 }
314                 fprintf(file, "\n");
315             }
316         }
317
318         fprintf(file, "\n\n");
319 }
320 \f
321 /*
322  *******************************************************************************
323  *
324  *  OpenFile --
325  *
326  *      Parses a command string for a file name and opens
327  *      the file. The file name is copued to the argument FILE. The
328  *      parameter SIZE parameter includes space for a null byte.
329  *
330  *  Results:
331  *      file pointer    - the open was successful.
332  *      NULL            - there was an error opening the file or
333  *                        the input string was invalid.
334  *
335  *******************************************************************************
336  */
337
338 FILE *
339 OpenFile(string, file, size)
340     char *string;
341     char *file;
342     size_t size;
343 {
344         char    *redirect;
345         FILE    *tmpPtr;
346         int     i;
347
348         /*
349          *  Open an output file if we see '>' or >>'.
350          *  Check for overwrite (">") or concatenation (">>").
351          */
352
353         redirect = strchr(string, '>');
354         if (redirect == NULL) {
355             return(NULL);
356         }
357
358         tmpPtr = NULL;
359         if (redirect[1] == '>') {
360             i = pickString(redirect + 2, file, size);
361             if (i > 0) {
362                 tmpPtr = fopen(file, "a+");
363             }
364         } else {
365             i = pickString(redirect + 1, file, size);
366             if (i > 0) {
367                 tmpPtr = fopen(file, "w");
368             }
369         }
370
371         if (tmpPtr != NULL) {
372             redirect[0] = '\0';
373         }
374
375         return(tmpPtr);
376 }
377 \f
378 /*
379  *******************************************************************************
380  *
381  *  DecodeError --
382  *
383  *      Converts an error code into a character string.
384  *
385  *******************************************************************************
386  */
387
388 const struct res_sym error_syms[] = {
389         { NOERROR,      "Success" },
390         { FORMERR,      "Format error" },
391         { SERVFAIL,     "Server failed" },
392         { NXDOMAIN,     "Non-existent host/domain" },
393         { NOTIMP,       "Not implemented" },
394         { REFUSED,      "Query refused" },
395 #ifdef NOCHANGE
396         { NOCHANGE,     "No change" },
397 #endif
398         { TIME_OUT,     "Timed out" },
399         { NO_INFO,      "No information" },
400         { ERROR,        "Unspecified error" },
401         { NONAUTH,      "Non-authoritative answer" },
402         { NO_RESPONSE,  "No response from server" },
403         { 0,            NULL }
404 };
405
406 const char *
407 DecodeError(result)
408     int result;
409 {
410         const char *string;
411         int success;
412
413         string = sym_ntos(error_syms, result, &success);
414         if (success)
415                 return string;
416         return ("BAD ERROR VALUE");
417 }
418 \f
419
420 int
421 StringToClass(class, dflt, errorfile)
422     char *class;
423     int dflt;
424     FILE *errorfile;
425 {
426         int result, success;
427
428         result = sym_ston(__p_class_syms, class, &success);
429         if (success)
430                 return result;
431
432         if (errorfile)
433                 fprintf(errorfile, "unknown query class: %s\n", class);
434         return(dflt);
435 }
436 \f
437
438 /*
439  *******************************************************************************
440  *
441  *  StringToType --
442  *
443  *      Converts a string form of a query type name to its
444  *      corresponding integer value.
445  *
446  *******************************************************************************
447  */
448
449 int
450 StringToType(type, dflt, errorfile)
451     char *type;
452     int dflt;
453     FILE *errorfile;
454 {
455         int result, success;
456
457         result = sym_ston(__p_type_syms, type, &success);
458         if (success)
459                 return (result);
460
461         if (errorfile)
462                 fprintf(errorfile, "unknown query type: %s\n", type);
463         return (dflt);
464 }
465 \f
466 /*
467  *******************************************************************************
468  *
469  *  DecodeType --
470  *
471  *      Converts a query type to a descriptive name.
472  *      (A more verbose form of p_type.)
473  *
474  *
475  *******************************************************************************
476  */
477
478 const char *
479 DecodeType(type)
480         int type;
481 {
482
483         return (sym_ntop(__p_type_syms, type, (int *)0));
484 }
485
486
487
488
489 /*
490  * Skip over leading white space in SRC and then copy the next sequence of
491  * non-whitespace characters into DEST. No more than (DEST_SIZE - 1)
492  * characters are copied. DEST is always null-terminated. Returns 0 if no
493  * characters could be copied into DEST. Returns the number of characters
494  * in SRC that were processed (i.e. the count of characters in the leading
495  * white space and the first non-whitespace sequence).
496  *
497  *      int i;
498  *      char *p = "  foo bar ", *q;
499  *      char buf[100];
500  *
501  *      q = p + pickString(p, buf, sizeof buff);
502  *      assert (strcmp (q, " bar ") == 0) ;
503  *
504  */
505
506 int
507 pickString(const char *src, char *dest, size_t dest_size) {
508         const char *start;
509         const char *end ;
510         size_t sublen ;
511
512         if (dest_size == 0 || dest == NULL || src == NULL)
513                 return 0;
514         
515         for (start = src ; isspace(*start) ; start++)
516                 /* nada */ ;
517
518         for (end = start ; *end != '\0' && !isspace(*end) ; end++)
519                 /* nada */ ;
520
521         sublen = end - start ;
522         
523         if (sublen == 0 || sublen > (dest_size - 1))
524                 return 0;
525
526         strncpy (dest, start, sublen);
527
528         dest[sublen] = '\0' ;
529
530         return (end - src);
531 }
532
533
534
535
536 /*
537  * match the string FORMAT against the string SRC. Leading whitespace in
538  * FORMAT will match any amount of (including no) leading whitespace in
539  * SRC. Any amount of whitespace inside FORMAT matches any non-zero amount
540  * of whitespace in SRC. Value returned is 0 if match didn't occur, or the
541  * amount of characters in SRC that did match 
542  *
543  *      int i ;
544  *
545  *      i = matchString(" a    b c", "a b c") ; 
546  *      assert (i == 5) ;
547  *      i = matchString("a b c", "  a b c");  
548  *      assert (i == 0) ;    becasue no leading white space in format
549  *      i = matchString(" a b c", " a   b     c"); 
550  *      assert(i == 12);
551  *      i = matchString("aa bb ", "aa      bb      ddd sd"); 
552  *      assert(i == 16);
553  */
554 int
555 matchString (const char *format, const char *src) {
556         const char *f = format;
557         const char *s = src;
558
559         if (f == NULL || s == NULL)
560                 goto notfound;
561
562         if (isspace(*f)) {
563                 while (isspace(*f))
564                         f++ ;
565                 while (isspace(*s))
566                         s++ ;
567         }
568         
569         while (1) {
570                 if (isspace(*f)) {
571                         if (!isspace(*s))
572                                 goto notfound;
573                         while(isspace(*s))
574                                 s++;
575                         /* any amount of whitespace in the format string
576                            will match any amount of space in the source
577                            string. */
578                         while (isspace(*f))
579                                 f++;
580                 } else if (*f == '\0') {
581                         return (s - src);
582                 } else if (*f != *s) {
583                         goto notfound;
584                 } else {
585                         s++ ;
586                         f++ ;
587                 }
588         }
589  notfound:
590         return 0 ;
591 }