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