utils/whois3/whois3.c

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

FUNCTIONS

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.6 2002/02/19 17:22:59 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 
  72 int 
  73 whois_query(FILE *in, FILE *out, char *query, int check_for_blank)
     /* [<][>][^][v][top][bottom][index][help] */
  74 {
  75     char buf[1024];
  76     int last_line_blank;
  77     char *p;
  78 
  79     /* remove any newline or carriage return */
  80     p = strchr(query, '\r');
  81     if (p != NULL) {
  82         *p = '\0';
  83     }
  84     p = strchr(query, '\n');
  85     if (p != NULL) {
  86         *p = '\0';
  87     }
  88 
  89     /* send query */
  90     fputs(query, out);
  91     fputs("\r\n", out);
  92 
  93     /* wait for reply to finish, printing until then */
  94     last_line_blank = 0;
  95     for (;;) {
  96         /* read next line */
  97         if (fgets(buf, sizeof(buf), in) == NULL) {
  98             return 0;
  99         }
 100 
 101         /* output the line */
 102         fputs(buf, stdout);
 103 
 104         /* if entire line fit in buffer */
 105         if (strchr(buf, '\n')) {
 106             /* if line is empty */
 107             if (!strcmp(buf, "\n")) {
 108                 /* if the last line was also blank, we're done */
 109                 if (check_for_blank && last_line_blank) {
 110                     return 1;
 111                 }
 112                 last_line_blank = 1;
 113             }
 114 
 115             /* non-empty line */
 116             else {
 117                 last_line_blank = 0;
 118             }
 119         }
 120 
 121         /* otherwise read until end of line */
 122         else {
 123             do {
 124                 if (fgets(buf, sizeof(buf), in) == NULL) {
 125                     return 0;
 126                 }
 127                 fputs(buf, stdout);
 128             } while (!strchr(buf, '\n'));
 129             last_line_blank = 0;
 130         }
 131     }
 132 }
 133 
 134 
 135 /* usage_error - output proper syntax and exit */
 136 void 
 137 usage_error(const char *exename)
     /* [<][>][^][v][top][bottom][index][help] */
 138 {
 139     fprintf(stderr, 
 140             "%s: [-h host | --host=host] [-p port | --port=port] -k | query\n",
 141             exename);
 142     fprintf(stderr, "\n");
 143     fprintf(stderr, 
 144             "When querying a Whois server running RIPE software, you may\n");
 145     fprintf(stderr, 
 146             "use the following flags:\n");
 147     fprintf(stderr, "\n");
 148     fputs(flag_txt, stderr);
 149     exit(1);
 150 }
 151 
 152 
 153 /* main - program entry point */
 154 int 
 155 main(int argc, char *argv[])
     /* [<][>][^][v][top][bottom][index][help] */
 156 {
 157     /* name of executable */
 158     char *exename;
 159 
 160     /* variables used to parse arguments */
 161     int p;
 162     char *nptr;
 163     char *endptr;
 164 
 165     /* arguments to forward to whois server */
 166     char **whois_argv;
 167     int whois_argc;
 168 
 169     /* server name and port to query */
 170     char *host;
 171     long port;
 172 
 173     /* persistent mode flag */
 174     int persistent_mode;
 175 
 176     /* connection information */
 177     struct servent *serv;
 178     struct hostent *h;
 179     struct sockaddr_in host_addr;
 180     int whois_fd;
 181     FILE *whois_in, *whois_out;
 182 
 183     /* query string */
 184     char *query;
 185     int query_len;
 186 
 187     /* the all-seeing i */
 188     int i;
 189 
 190 
 191     /* */
 192     /* parse command line */
 193     /* */
 194 
 195     /* get the name of this executable */
 196     if (argc > 0) {
 197         exename = "whois3";
 198     } else {
 199         exename = argv[0];
 200     }
 201 
 202     /* set defaults for parameters */
 203     host = NULL;
 204     port = -1;
 205     persistent_mode = 0;
 206 
 207     /* allocate enough space for our argument list */
 208     whois_argv = (char **)malloc(sizeof(char *) * (argc+1));
 209     if (whois_argv == NULL) {
 210         fprintf(stderr, "%s: out of memory\n", exename);
 211         exit(1);
 212     }
 213     whois_argc = 0;
 214 
 215     /* parse command-line arguments */
 216     p = 1;
 217     while (p < argc) {
 218 
 219         /* check for short host name */
 220         if (!strncmp(argv[p], "-h", 2)) {
 221             /* only specify host once */
 222             if (host != NULL) {
 223                 usage_error(exename);
 224             }
 225 
 226             /* see if the host was specified after the 'h' */
 227             host = argv[p] + 2;
 228 
 229             /* if not, then it must be the next argument */
 230             if (*host == '\0') {
 231                 p++;
 232                 if (p >= argc) {
 233                     usage_error(exename);
 234                 }
 235                 host = argv[p];
 236             }
 237             p++;
 238         } 
 239 
 240         /* check for long host name */
 241         else if (!strncmp(argv[p], "--host=", 7)) {
 242             /* only specify host once */
 243             if (host != NULL) {
 244                 usage_error(exename);
 245             }
 246 
 247             /* grab host name */
 248             host = argv[p] + 7;
 249             if (*host == '\0') {
 250                 usage_error(exename);
 251             }
 252             p++;
 253         }
 254 
 255         /* check for short port name */
 256         else if (!strncmp(argv[p], "-p", 2)) {
 257             /* only specify port once */
 258             if (port != -1) {
 259                 usage_error(exename);
 260             }
 261 
 262             /* see if the port was specified after the 'p' */
 263             nptr = argv[p] + 2;
 264             if (*nptr == '\0') {
 265                 p++;
 266                 if (p >= argc) {
 267                     usage_error(exename);
 268                 }
 269                 nptr = argv[p];
 270             }
 271 
 272             /* see if this is a valid port */
 273             port = strtol(nptr, &endptr, 0);
 274             if ((port < 0) || (port > 65535) || (*endptr != '\0')) {
 275                 serv = getservbyname(nptr, "tcp");
 276                 if (serv == NULL) {
 277                     fprintf(stderr, 
 278                             "%s: port must be a number between 0 and 65535, "
 279                             "or the name of a service\n",
 280                             exename);
 281                     exit(1);
 282                 }
 283                 port = ntohs(serv->s_port);
 284             }
 285 
 286             p++;
 287         }
 288 
 289         /* check for long port name */
 290         else if (!strncmp(argv[p], "--port=", 7)) {
 291             /* only specify port once */
 292             if (port != -1) {
 293                 usage_error(exename);
 294             }
 295 
 296             nptr = argv[p] + 7;
 297 
 298             /* see if this is a valid port */
 299             port = strtol(nptr, &endptr, 0);
 300             if ((port < 0) || (port > 65535) || (*endptr != '\0')) {
 301                 serv = getservbyname(nptr, "tcp");
 302                 if (serv == NULL) {
 303                     fprintf(stderr, 
 304                             "%s: port must be a number between 0 and 65535\n",
 305                             exename);
 306                     exit(1);
 307                 }
 308                 port = ntohs(serv->s_port);
 309             }
 310 
 311             p++;
 312         }
 313 
 314         /* check for stand-alone persistent flag */
 315         else if (!strcmp(argv[p], "-k")) {
 316             /* note we explicitly allow multiple -k options, as this doesn't
 317                add any ambiguity, even if it is pointless */
 318             persistent_mode = 1;
 319 
 320             p++;
 321         }
 322 
 323         /* check for help, so we can give local usage */
 324         else if (!strcmp(argv[p], "-?")) {
 325             usage_error(exename);
 326         }
 327 
 328         /* other flags or arguments */
 329         else {
 330             /* check to see if -k was used - this will cause an error below,
 331                as you can only use -k by itself */
 332             if ((argv[p][0] == '-') && strchr(argv[p], 'k')) {
 333                 persistent_mode = 1;
 334             }
 335 
 336             /* add our argument in any case */
 337             whois_argv[whois_argc++] = argv[p];
 338             p++;
 339         }
 340     }
 341 
 342     /* don't allow any arguments with a persistent mode */
 343     if (persistent_mode) {
 344         if (whois_argc > 0) {
 345             fprintf(stderr, 
 346                     "%s: do not specify arguments with -k\n",
 347                     exename);
 348             exit(1);
 349         }
 350     }
 351 
 352     /* require options otherwise */
 353     else {
 354         if (whois_argc <= 0) {
 355             usage_error(exename);
 356         }
 357     }
 358 
 359     /* */
 360     /* arguments look good - connect to server */
 361     /* */
 362 
 363     /* blank out our address structure for broken (i.e. BSD) Unix variants */
 364     memset(&host_addr, 0, sizeof(struct sockaddr_in));
 365 
 366     /* get port address if not specified */
 367     if (port == -1) {
 368         serv = getservbyname("whois", "tcp");
 369         if (serv == NULL) {
 370             host_addr.sin_port = htons(DEFAULT_WHOIS_PORT);
 371         } else {
 372             host_addr.sin_port = serv->s_port;
 373         }
 374     } else {
 375         host_addr.sin_port = htons(port);
 376     }
 377 
 378     /* get server address (checking if it is an IP number first) */
 379     if (host == NULL) {
 380         host = NICHOST;
 381     }
 382     host_addr.sin_addr.s_addr = inet_addr(host);
 383     if (host_addr.sin_addr.s_addr == -1) {
 384         h = gethostbyname(host);
 385         if (h == NULL) {
 386             fprintf(stderr, 
 387                     "%s: error %d getting server address\n",
 388                     exename,
 389                     h_errno);
 390             exit(1);
 391         }
 392         memcpy(&host_addr.sin_addr, h->h_addr, sizeof(host_addr.sin_addr));
 393     }
 394 
 395     /* fill in the rest of our socket structure */
 396     host_addr.sin_family = AF_INET;
 397 
 398     /* create a socket */
 399     whois_fd = socket(AF_INET, SOCK_STREAM, 0);
 400     if (whois_fd == -1) {
 401         fprintf(stderr, 
 402                 "%s: error %d creating a socket; %s\n",
 403                 exename,
 404                 errno,
 405                 strerror(errno));
 406         exit(1);
 407     }
 408 
 409     /* connect to the server */
 410     if (connect(whois_fd, 
 411                 (struct sockaddr *)&host_addr, 
 412                 sizeof(struct sockaddr_in)) != 0) 
 413     {
 414         fprintf(stderr, 
 415                 "%s: error %d connecting to server; %s\n",
 416                 exename,
 417                 errno,
 418                 strerror(errno));
 419         exit(1);
 420     }
 421 
 422     /* bind FILE structures to our file descriptor for easy handling */
 423     whois_in = fdopen(whois_fd, "r");
 424     if (whois_in == NULL) {
 425         fprintf(stderr, 
 426                 "%s: error %d creating input stream; %s\n",
 427                 exename,
 428                 errno,
 429                 strerror(errno));
 430     }
 431     setbuf(whois_in, NULL);
 432     whois_out = fdopen(whois_fd, "w");
 433     if (whois_out == NULL) {
 434         fprintf(stderr, 
 435                 "%s: error %d creating input stream; %s\n",
 436                 exename,
 437                 errno,
 438                 strerror(errno));
 439     }
 440     setbuf(whois_out, NULL);
 441 
 442 
 443     /* */
 444     /* Query away */
 445     /* */
 446 
 447     /* if we had flags, we're running in "interactive" mode */
 448     if (whois_argc > 0) {
 449 
 450         /* combine our arguments into a single string */
 451         query_len = 0;
 452         for (i=0; i<whois_argc; i++) {
 453             query_len += (1 + strlen(whois_argv[i]));
 454         }
 455         query = (char *)malloc(query_len+1);
 456         if (query == NULL) {
 457             fprintf(stderr, "%s: out of memory\n", exename);
 458             exit(1);
 459         }
 460         strcpy(query, whois_argv[0]);
 461         for (i=1; i<whois_argc; i++) {
 462             strcat(query, " ");
 463             strcat(query, whois_argv[i]);
 464         }
 465 
 466         /* now send our query to the server */
 467         whois_query(whois_in, whois_out, query, 0);
 468     }
 469 
 470     /* otherwise we're in "batch" mode - read each query a line at a time */
 471     else {
 472 
 473         /* make a buffer to read into */
 474         query_len = 8192;
 475         query = (char *)malloc(query_len);
 476         if (query == NULL) {
 477             fprintf(stderr, "%s: out of memory\n", exename);
 478             exit(1);
 479         }
 480 
 481         /* enter persistent mode */
 482         fputs("-k\n", whois_out);
 483 
 484         /* loop and query */
 485         while (fgets(query, query_len, stdin) != NULL) {
 486             if (strchr(query, '\n') == NULL) {
 487                 fprintf(stderr, "%s: query line too long\n", exename);
 488                 exit(1);
 489             }
 490             whois_query(whois_in, whois_out, query, 1);
 491         }
 492 
 493         /* exit persistent mode */
 494         fputs("-k\n", whois_out);
 495     }
 496 
 497     /* everything exited fine */
 498     return 0;
 499 }
 500 
 501 

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