## 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] */