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

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