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.2 2001/06/06 16:31:02 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                 fprintf(stderr, 
 292                         "%s: port must be a number between 0 and 65535\n",
 293                         exename);
 294                 exit(1);
 295             }
 296 
 297             p++;
 298         }
 299 
 300         /* check for stand-alone persistent flag */
 301         else if (!strcmp(argv[p], "-k")) {
 302             /* note we explicitly allow multiple -k options, as this doesn't
 303                add any ambiguity, even if it is pointless */
 304             persistent_mode = 1;
 305 
 306             p++;
 307         }
 308 
 309         /* other flags or arguments */
 310         else {
 311             /* check to see if -k was used - this will cause an error below,
 312                as you can only use -k by itself */
 313             if ((argv[p][0] == '-') && strchr(argv[p], 'k')) {
 314                 persistent_mode = 1;
 315             }
 316 
 317             /* add our argument in any case */
 318             whois_argv[whois_argc++] = argv[p];
 319             p++;
 320         }
 321     }
 322 
 323     /* don't allow any arguments with a persistent mode */
 324     if (persistent_mode) {
 325         if (whois_argc > 0) {
 326             fprintf(stderr, 
 327                     "%s: do not specify arguments with -k\n",
 328                     exename);
 329             exit(1);
 330         }
 331     }
 332 
 333     /* require options otherwise */
 334     else {
 335         if (whois_argc <= 0) {
 336             usage_error(exename);
 337         }
 338     }
 339 
 340     /* */
 341     /* arguments look good - connect to server */
 342     /* */
 343 
 344     /* blank out our address structure for broken (i.e. BSD) Unix variants */
 345     memset(&host_addr, 0, sizeof(struct sockaddr_in));
 346 
 347     /* get port address if not specified */
 348     if (port == -1) {
 349         serv = getservbyname("whois", "tcp");
 350         if (serv == NULL) {
 351             host_addr.sin_port = htons(DEFAULT_WHOIS_PORT);
 352         } else {
 353             host_addr.sin_port = serv->s_port;
 354         }
 355     } else {
 356         host_addr.sin_port = htons(port);
 357     }
 358 
 359     /* get server address (checking if it is an IP number first) */
 360     if (host == NULL) {
 361         host = NICHOST;
 362     }
 363     host_addr.sin_addr.s_addr = inet_addr(host);
 364     if (host_addr.sin_addr.s_addr == -1) {
 365         h = gethostbyname(host);
 366         if (h == NULL) {
 367             fprintf(stderr, 
 368                     "%s: error %d getting server address\n",
 369                     exename,
 370                     h_errno);
 371             exit(1);
 372         }
 373         memcpy(&host_addr.sin_addr, h->h_addr, sizeof(host_addr.sin_addr));
 374     }
 375 
 376     /* fill in the rest of our socket structure */
 377     host_addr.sin_family = AF_INET;
 378 
 379     /* create a socket */
 380     whois_fd = socket(AF_INET, SOCK_STREAM, 0);
 381     if (whois_fd == -1) {
 382         fprintf(stderr, 
 383                 "%s: error %d creating a socket; %s\n",
 384                 exename,
 385                 errno,
 386                 strerror(errno));
 387         exit(1);
 388     }
 389 
 390     /* connect to the server */
 391     if (connect(whois_fd, 
 392                 (struct sockaddr *)&host_addr, 
 393                 sizeof(struct sockaddr_in)) != 0) 
 394     {
 395         fprintf(stderr, 
 396                 "%s: error %d connecting to server; %s\n",
 397                 exename,
 398                 errno,
 399                 strerror(errno));
 400         exit(1);
 401     }
 402 
 403     /* bind FILE structures to our file descriptor for easy handling */
 404     whois_in = fdopen(whois_fd, "r");
 405     if (whois_in == NULL) {
 406         fprintf(stderr, 
 407                 "%s: error %d creating input stream; %s\n",
 408                 exename,
 409                 errno,
 410                 strerror(errno));
 411     }
 412     setbuf(whois_in, NULL);
 413     whois_out = fdopen(whois_fd, "w");
 414     if (whois_out == NULL) {
 415         fprintf(stderr, 
 416                 "%s: error %d creating input stream; %s\n",
 417                 exename,
 418                 errno,
 419                 strerror(errno));
 420     }
 421     setbuf(whois_out, NULL);
 422 
 423 
 424     /* */
 425     /* Query away */
 426     /* */
 427 
 428     /* if we had flags, we're running in "interactive" mode */
 429     if (whois_argc > 0) {
 430 
 431         /* combine our arguments into a single string */
 432         query_len = 0;
 433         for (i=0; i<whois_argc; i++) {
 434             query_len += (1 + strlen(whois_argv[i]));
 435         }
 436         query = (char *)malloc(query_len+1);
 437         if (query == NULL) {
 438             fprintf(stderr, "%s: out of memory\n", exename);
 439             exit(1);
 440         }
 441         strcpy(query, whois_argv[0]);
 442         for (i=1; i<whois_argc; i++) {
 443             strcat(query, " ");
 444             strcat(query, whois_argv[i]);
 445         }
 446 
 447         /* now send our query to the server */
 448         whois_query(whois_in, whois_out, query);
 449     }
 450 
 451     /* otherwise we're in "batch" mode - read each query a line at a time */
 452     else {
 453 
 454         /* make a buffer to read into */
 455         query_len = 8192;
 456         query = (char *)malloc(query_len);
 457         if (query == NULL) {
 458             fprintf(stderr, "%s: out of memory\n", exename);
 459             exit(1);
 460         }
 461 
 462         /* enter persistent mode */
 463         fputs("-k\n", whois_out);
 464 
 465         /* loop and query */
 466         while (fgets(query, query_len, stdin) != NULL) {
 467             if (strchr(query, '\n') == NULL) {
 468                 fprintf(stderr, "%s: query line too long\n", exename);
 469                 exit(1);
 470             }
 471             whois_query(whois_in, whois_out, query);
 472         }
 473 
 474         /* exit persistent mode */
 475         fputs("-k\n", whois_out);
 476     }
 477 
 478     /* everything exited fine */
 479     return 0;
 480 }
 481 
 482 

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