utils/whois3/whois3.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following functions.
  1. whois_query
  2. usage_error
  3. main

   1 /*
   2 Copyright (c) 2001,2002                 RIPE NCC
   3 
   4 
   5 All Rights Reserved
   6 
   7 Permission to use, copy, modify, and distribute this software and its
   8 documentation for any purpose and without fee is hereby granted,
   9 provided that the above copyright notice appear in all copies and that
  10 both that copyright notice and this permission notice appear in
  11 supporting documentation, and that the name of the author not be
  12 used in advertising or publicity pertaining to distribution of the
  13 software without specific, written prior permission.
  14 
  15 THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  16 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
  17 AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
  18 DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
  19 AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  20 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  21 */
  22 
  23 /* $Id: whois3.c,v 1.9 2002/07/02 15:56:34 shane Exp $ */
  24 
  25 #include <string.h>
  26 #include <stdlib.h>
  27 #include <stdio.h>
  28 #include <limits.h>
  29 #include <netdb.h>
  30 #include <errno.h>
  31 #include <netdb.h>
  32 #include <sys/types.h>
  33 #include <sys/socket.h>
  34 #include <netinet/in.h>
  35 #include <unistd.h>
  36 
  37 
  38 /* help text is defined in this file as flag_txt[] */
  39 #include "flags.h"
  40 
  41 /*
  42  * CONSTANTS 
  43  */
  44 
  45 /* default name to query - can be set at runtime via the "-h" option */
  46 #define NICHOST "whois.ripe.net"
  47 
  48 /* default port - only used if there is no entry for "whois" in the 
  49    /etc/services file and no "-p" option is specified */
  50 #define DEFAULT_WHOIS_PORT 43
  51 
  52 
  53 
  54 /* 
  55  * FUNCTIONS 
  56  */
  57 
  58 
  59 /* 
  60   whois_query
  61 
  62   Writes the query string in "query" to the "out" descriptor, and reads
  63   the result in the "in" descriptor.  The "out" buffer may have either no
  64   buffering or line buffering, but must NOT have full buffering.
  65 
  66   The routine then outputs each line the server returns, until the server
  67   ends the connection.  If the "check_for_blank" variable is set to
  68   non-zero, then the routine will also return when two consecutive blank
  69   lines appear in the server response.
  70 
  71   If an error occurs sending or reading the query, -1 is returned.
  72  */
  73 
  74 int 
  75 whois_query(FILE *in, FILE *out, const char *query, int check_for_blank)
     /* [<][>][^][v][top][bottom][index][help] */
  76 {
  77     char buf[1024];
  78     int last_line_blank;
  79     char *p;
  80     char *query_copy;
  81 
  82     /* manipulate a copy of the query */
  83     query_copy = (char *)malloc(strlen(query) + 3);
  84     strcpy(query_copy, query);
  85 
  86     /* remove any newline or carriage return */
  87     p = strchr(query_copy, '\r');
  88     if (p != NULL) {
  89         *p = '\0';
  90     }
  91     p = strchr(query_copy, '\n');
  92     if (p != NULL) {
  93         *p = '\0';
  94     }
  95 
  96     /* add CR+LF */
  97     strcat(query_copy, "\r\n");
  98 
  99     /* send query */
 100     if (fputs(query_copy, out) == EOF) {
 101         return -1;
 102     }
 103 
 104     /* wait for reply to finish, printing until then */
 105     last_line_blank = 0;
 106     for (;;) {
 107         /* read next line */
 108         if (fgets(buf, sizeof(buf), in) == NULL) {
 109             return -1;
 110         }
 111 
 112         /* output the line */
 113         fputs(buf, stdout);
 114 
 115         /* if entire line fit in buffer */
 116         if (strchr(buf, '\n')) {
 117             /* if line is empty */
 118             if (!strcmp(buf, "\n")) {
 119                 /* if the last line was also blank, we're done */
 120                 if (check_for_blank && last_line_blank) {
 121                     return 1;
 122                 }
 123                 last_line_blank = 1;
 124             }
 125 
 126             /* non-empty line */
 127             else {
 128                 last_line_blank = 0;
 129             }
 130         }
 131 
 132         /* otherwise read until end of line */
 133         else {
 134             do {
 135                 if (fgets(buf, sizeof(buf), in) == NULL) {
 136                     return 0;
 137                 }
 138                 fputs(buf, stdout);
 139             } while (!strchr(buf, '\n'));
 140             last_line_blank = 0;
 141         }
 142     }
 143 }
 144 
 145 
 146 /* usage_error - output proper syntax and exit */
 147 void 
 148 usage_error(const char *exename)
     /* [<][>][^][v][top][bottom][index][help] */
 149 {
 150     fprintf(stderr, 
 151             "%s: [-h host | --host=host] [-p port | --port=port] -k | query\n",
 152             exename);
 153     fprintf(stderr, "\n");
 154     fprintf(stderr, 
 155             "When querying a Whois server running RIPE software, you may\n");
 156     fprintf(stderr, 
 157             "use the following flags:\n");
 158     fprintf(stderr, "\n");
 159     fputs(flag_txt, stderr);
 160     exit(1);
 161 }
 162 
 163 
 164 /* main - program entry point */
 165 int 
 166 main(int argc, char *argv[])
     /* [<][>][^][v][top][bottom][index][help] */
 167 {
 168     /* name of executable */
 169     char *exename;
 170 
 171     /* variables used to parse arguments */
 172     int p;
 173     char *nptr;
 174     char *endptr;
 175 
 176     /* arguments to forward to whois server */
 177     char **whois_argv;
 178     int whois_argc;
 179 
 180     /* server name and port to query */
 181     char *host;
 182     long port;
 183 
 184     /* persistent mode flag and line buffer */
 185     int persistent_mode;
 186     char linebuf[BUFSIZ];
 187 
 188     /* connection information */
 189     struct servent *serv;
 190     struct hostent *h;
 191     struct sockaddr_in host_addr;
 192     int whois_fd;
 193     FILE *whois_in, *whois_out;
 194     char whois_in_linebuf[BUFSIZ];
 195 
 196     /* query string */
 197     char *query;
 198     int query_len;
 199 
 200     /* the all-seeing i */
 201     int i;
 202 
 203 
 204     /* */
 205     /* parse command line */
 206     /* */
 207 
 208     /* get the name of this executable */
 209     if (argc > 0) {
 210         exename = "whois3";
 211     } else {
 212         exename = argv[0];
 213     }
 214 
 215     /* set defaults for parameters */
 216     host = NULL;
 217     port = -1;
 218     persistent_mode = 0;
 219 
 220     /* allocate enough space for our argument list */
 221     whois_argv = (char **)malloc(sizeof(char *) * (argc+1));
 222     if (whois_argv == NULL) {
 223         fprintf(stderr, "%s: out of memory\n", exename);
 224         exit(1);
 225     }
 226     whois_argc = 0;
 227 
 228     /* parse command-line arguments */
 229     p = 1;
 230     while (p < argc) {
 231 
 232         /* check for short host name */
 233         if (!strncmp(argv[p], "-h", 2)) {
 234             /* only specify host once */
 235             if (host != NULL) {
 236                 usage_error(exename);
 237             }
 238 
 239             /* see if the host was specified after the 'h' */
 240             host = argv[p] + 2;
 241 
 242             /* if not, then it must be the next argument */
 243             if (*host == '\0') {
 244                 p++;
 245                 if (p >= argc) {
 246                     usage_error(exename);
 247                 }
 248                 host = argv[p];
 249             }
 250             p++;
 251         } 
 252 
 253         /* check for long host name */
 254         else if (!strncmp(argv[p], "--host=", 7)) {
 255             /* only specify host once */
 256             if (host != NULL) {
 257                 usage_error(exename);
 258             }
 259 
 260             /* grab host name */
 261             host = argv[p] + 7;
 262             if (*host == '\0') {
 263                 usage_error(exename);
 264             }
 265             p++;
 266         }
 267 
 268         /* check for short port name */
 269         else if (!strncmp(argv[p], "-p", 2)) {
 270             /* only specify port once */
 271             if (port != -1) {
 272                 usage_error(exename);
 273             }
 274 
 275             /* see if the port was specified after the 'p' */
 276             nptr = argv[p] + 2;
 277             if (*nptr == '\0') {
 278                 p++;
 279                 if (p >= argc) {
 280                     usage_error(exename);
 281                 }
 282                 nptr = argv[p];
 283             }
 284 
 285             /* see if this is a valid port */
 286             port = strtol(nptr, &endptr, 0);
 287             if ((port < 0) || (port > 65535) || (*endptr != '\0')) {
 288                 serv = getservbyname(nptr, "tcp");
 289                 if (serv == NULL) {
 290                     fprintf(stderr, 
 291                             "%s: port must be a number between 0 and 65535, "
 292                             "or the name of a service\n",
 293                             exename);
 294                     exit(1);
 295                 }
 296                 port = ntohs(serv->s_port);
 297             }
 298 
 299             p++;
 300         }
 301 
 302         /* check for long port name */
 303         else if (!strncmp(argv[p], "--port=", 7)) {
 304             /* only specify port once */
 305             if (port != -1) {
 306                 usage_error(exename);
 307             }
 308 
 309             nptr = argv[p] + 7;
 310 
 311             /* see if this is a valid port */
 312             port = strtol(nptr, &endptr, 0);
 313             if ((port < 0) || (port > 65535) || (*endptr != '\0')) {
 314                 serv = getservbyname(nptr, "tcp");
 315                 if (serv == NULL) {
 316                     fprintf(stderr, 
 317                             "%s: port must be a number between 0 and 65535\n",
 318                             exename);
 319                     exit(1);
 320                 }
 321                 port = ntohs(serv->s_port);
 322             }
 323 
 324             p++;
 325         }
 326 
 327         /* check for stand-alone persistent flag */
 328         else if (!strcmp(argv[p], "-k")) {
 329             /* note we explicitly allow multiple -k options, as this doesn't
 330                add any ambiguity, even if it is pointless */
 331             persistent_mode = 1;
 332 
 333             p++;
 334         }
 335 
 336         /* check for help, so we can give local usage */
 337         else if (!strcmp(argv[p], "-?")) {
 338             usage_error(exename);
 339         }
 340 
 341         /* other flags or arguments */
 342         else {
 343             /* add our argument in any case */
 344             whois_argv[whois_argc++] = argv[p];
 345             p++;
 346         }
 347     }
 348 
 349     /* don't allow any arguments with a persistent mode */
 350     if (persistent_mode) {
 351         if (whois_argc > 0) {
 352             fprintf(stderr, 
 353                     "%s: do not specify arguments with -k\n",
 354                     exename);
 355             exit(1);
 356         }
 357         /* set to line buffering if we are in persistent mode, 
 358            to allow programs to pipe the result without block buffering */
 359         setvbuf(stdout, linebuf, _IOLBF, BUFSIZ);
 360     }
 361 
 362     /* require options otherwise */
 363     else {
 364         if (whois_argc <= 0) {
 365             usage_error(exename);
 366         }
 367     }
 368 
 369     /* */
 370     /* arguments look good - connect to server */
 371     /* */
 372 
 373     /* blank out our address structure for broken (i.e. BSD) Unix variants */
 374     memset(&host_addr, 0, sizeof(struct sockaddr_in));
 375 
 376     /* get port address if not specified */
 377     if (port == -1) {
 378         serv = getservbyname("whois", "tcp");
 379         if (serv == NULL) {
 380             host_addr.sin_port = htons(DEFAULT_WHOIS_PORT);
 381         } else {
 382             host_addr.sin_port = serv->s_port;
 383         }
 384     } else {
 385         host_addr.sin_port = htons(port);
 386     }
 387 
 388     /* get server address (checking if it is an IP number first) */
 389     if (host == NULL) {
 390         host = NICHOST;
 391     }
 392     host_addr.sin_addr.s_addr = inet_addr(host);
 393     if (host_addr.sin_addr.s_addr == -1) {
 394         h = gethostbyname(host);
 395         if (h == NULL) {
 396             fprintf(stderr, 
 397                     "%s: error %d getting server address\n",
 398                     exename,
 399                     h_errno);
 400             exit(1);
 401         }
 402         memcpy(&host_addr.sin_addr, h->h_addr, sizeof(host_addr.sin_addr));
 403     }
 404 
 405     /* fill in the rest of our socket structure */
 406     host_addr.sin_family = AF_INET;
 407 
 408     /* create a socket */
 409     whois_fd = socket(AF_INET, SOCK_STREAM, 0);
 410     if (whois_fd == -1) {
 411         fprintf(stderr, 
 412                 "%s: error %d creating a socket; %s\n",
 413                 exename,
 414                 errno,
 415                 strerror(errno));
 416         exit(1);
 417     }
 418 
 419     /* connect to the server */
 420     if (connect(whois_fd, 
 421                 (struct sockaddr *)&host_addr, 
 422                 sizeof(struct sockaddr_in)) != 0) 
 423     {
 424         fprintf(stderr, 
 425                 "%s: error %d connecting to server; %s\n",
 426                 exename,
 427                 errno,
 428                 strerror(errno));
 429         exit(1);
 430     }
 431 
 432     /* bind FILE structures to our file descriptor for easy handling */
 433     whois_in = fdopen(whois_fd, "r");
 434     if (whois_in == NULL) {
 435         fprintf(stderr, 
 436                 "%s: error %d creating input stream; %s\n",
 437                 exename,
 438                 errno,
 439                 strerror(errno));
 440     }
 441     setvbuf(whois_in, whois_in_linebuf, _IOLBF, sizeof(whois_in_linebuf));
 442     whois_out = fdopen(whois_fd, "w");
 443     if (whois_out == NULL) {
 444         fprintf(stderr, 
 445                 "%s: error %d creating input stream; %s\n",
 446                 exename,
 447                 errno,
 448                 strerror(errno));
 449     }
 450     setbuf(whois_out, NULL);
 451 
 452 
 453     /* */
 454     /* Query away */
 455     /* */
 456 
 457     /* if we had flags, we're running in "interactive" mode */
 458     if (whois_argc > 0) {
 459 
 460         /* combine our arguments into a single string */
 461         query_len = 0;
 462         for (i=0; i<whois_argc; i++) {
 463             query_len += (1 + strlen(whois_argv[i]));
 464         }
 465         query = (char *)malloc(query_len+1);
 466         if (query == NULL) {
 467             fprintf(stderr, "%s: out of memory\n", exename);
 468             exit(1);
 469         }
 470         strcpy(query, whois_argv[0]);
 471         for (i=1; i<whois_argc; i++) {
 472             strcat(query, " ");
 473             strcat(query, whois_argv[i]);
 474         }
 475 
 476         /* now send our query to the server */
 477         whois_query(whois_in, whois_out, query, 0);
 478     }
 479 
 480     /* otherwise we're in "batch" mode - read each query a line at a time */
 481     else {
 482 
 483         /* make a buffer to read into */
 484         query_len = 8192;
 485         query = (char *)malloc(query_len);
 486         if (query == NULL) {
 487             fprintf(stderr, "%s: out of memory\n", exename);
 488             exit(1);
 489         }
 490 
 491         /* enter persistent mode */
 492         if (whois_query(whois_in, whois_out, "-k", 1) == -1) {
 493             fprintf(stderr, "%s: unable to send query\n", exename);
 494             exit(1);
 495         }
 496 
 497         /* loop and query */
 498         while (fgets(query, query_len, stdin) != NULL) {
 499             if (strchr(query, '\n') == NULL) {
 500                 fprintf(stderr, "%s: query line too long\n", exename);
 501                 exit(1);
 502             }
 503             if (whois_query(whois_in, whois_out, query, 1) == -1) {
 504                 fprintf(stderr, "%s: unable to send query\n", exename);
 505                 exit(1);
 506             }
 507         }
 508 
 509         /* exit persistent mode */
 510         fputs("-k\n", whois_out);
 511     }
 512 
 513     /* everything exited fine */
 514     return 0;
 515 }
 516 
 517 

/* [<][>][^][v][top][bottom][index][help] */