Source File modules/qc/query_command.c

    1    | /***************************************
    2    |   $Revision: 1.48 $
    3    |
    4    |   Query command module (qc).  This is what the whois query gets stored as in
    5    |   memory.
    6    |
    7    |   Status: NOT REVUED, TESTED
    8    |
    9    |   ******************/ /******************
    10   |   Filename            : query_command.c
    11   |   Author              : ottrey@ripe.net
    12   |   Modifications by    : marek@ripe.net
    13   |   ******************/ /******************
    14   |   Copyright (c) 1999                              RIPE NCC
    15   |
    16   |   All Rights Reserved
    17   |
    18   |   Permission to use, copy, modify, and distribute this software and its
    19   |   documentation for any purpose and without fee is hereby granted,
    20   |   provided that the above copyright notice appear in all copies and that
    21   |   both that copyright notice and this permission notice appear in
    22   |   supporting documentation, and that the name of the author not be
    23   |   used in advertising or publicity pertaining to distribution of the
    24   |   software without specific, written prior permission.
    25   |
    26   |   THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
    27   |   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
    28   |   AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
    29   |   DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
    30   |   AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    31   |   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
    32   |   ***************************************/
    33   | #include <stdlib.h>
    34   | #include <stdio.h>
    35   | #include <string.h>
    36   | #include <ctype.h>
    37   |
    38   | #define QC_IMPL
    39   |
    40   | #include "query_command.h"
    41   | #include "defs.h"
    42   | #include "constants.h"
    43   | #include "which_keytypes.h"
    44   | #include "memwrap.h"
    45   |
    46   | #include "ca_configFns.h"
    47   | #include "ca_dictionary.h"
    48   | #include "ca_macros.h"
    49   | #include "ca_srcAttribs.h"
    50   |
    51   | #include "getopt.h"
    52   |
    53   | #define MAX_OPT_ARG_C 20
    54   |
    55   | /*+ String sizes +*/
    56   | #define STR_S   63
    57   | #define STR_M   255
    58   | #define STR_L   1023
    59   | #define STR_XL  4095
    60   | #define STR_XXL 16383
    61   |
    62   |
    63   | /*++++++++++++++++++++++++++++++++++++++
    64   |   make a list of sources. expects list to hold source handles
    65   |
    66   |   char *
    67   |   qc_sources_list_to_string     returns an allocated string, must be freed
    68   |
    69   |   GList *list                   list of source handles (as defined by CA)
    70   |
    71   |   ++++++++++++++++++++++++++++++++++++++*/
    72   | char *
    73   | qc_sources_list_to_string(GList *list)
    74   | {
    75   |   char *result = NULL;
    76   |   int oldlen = 0;
    77   |   GList *qitem;
    78   |
    79   |   for( qitem = g_list_first(list);
    80   |        qitem != NULL;
    81   |        qitem = g_list_next(qitem)) {
    82   |     ca_dbSource_t *source_hdl = (ca_dbSource_t *) ( qitem->data );
    83   |     char *srcname = ca_get_srcname( source_hdl );
    84   |
    85   |     dieif( wr_realloc( (void **)& result, oldlen + strlen(srcname) + 2)
    86   | 	   != UT_OK);
    87   |     if(oldlen > 0) {
    88   |       strcat(result, ",");
    89   |     }
    90   |     strcat(result, srcname);
    91   |   }
    92   |
    93   |   return result;
    94   | }
    95   |
    96   | /* QC_environ_to_string() */
    97   | /*++++++++++++++++++++++++++++++++++++++
    98   |   Convert the query_environ to a string.
    99   |
    100  |   Query_environ *query_environ The query_environ to be converted.
    101  |
    102  |   More:
    103  |   +html+ <PRE>
    104  |   Authors:
    105  |         ottrey
    106  |   +html+ </PRE><DL COMPACT>
    107  |   +html+ <DT>Online References:
    108  |   +html+ <DD><UL>
    109  |   +html+ </UL></DL>
    110  |
    111  |   ++++++++++++++++++++++++++++++++++++++*/
    112  | char *QC_environ_to_string(Query_environ qe) {
    113  |   char *result;
    114  |   char *str1;
    115  |   char str2[IP_ADDRSTR_MAX];
    116  |   char result_buf[STR_XL];
    117  |
    118  |   str1 = qc_sources_list_to_string(qe.sources_list);
    119  |
    120  |   if( IP_addr_b2a( &(qe.pIP), str2, IP_ADDRSTR_MAX) != IP_OK ) {
    121  |     *str2 = '\0';
    122  |   }
    123  |
    124  |   sprintf(result_buf, "host=%s, keep_connection=%s, sources=%s, version=%s%s%s", qe.condat.ip,
    125  |           qe.k?"on":"off",
    126  |           str1,
    127  |           (qe.version == NULL) ? "?" : qe.version,
    128  |           *str2 == '\0' ? "" : ", passedIP=",
    129  |           *str2 == '\0' ? "" : str2
    130  |           );
    131  |
    132  |   wr_free(str1);
    133  |
    134  |   dieif( wr_malloc((void **)&result, strlen(result_buf)+1) != UT_OK);
    135  |
    136  |   strcpy(result, result_buf);
    137  |
    138  |   return result;
    139  |
    140  | } /* QC_environ_to_string() */
    141  |
    142  | /* QC_query_command_to_string() */
    143  | /*++++++++++++++++++++++++++++++++++++++
    144  |   Convert the query_command to a string.
    145  |
    146  |   Query_command *query_command The query_command to be converted.
    147  |
    148  |   More:
    149  |   +html+ <PRE>
    150  |   Authors:
    151  |         ottrey
    152  |   +html+ </PRE><DL COMPACT>
    153  |   +html+ <DT>Online References:
    154  |   +html+ <DD><UL>
    155  |   +html+ </UL></DL>
    156  |
    157  |   ++++++++++++++++++++++++++++++++++++++*/
    158  | char *QC_query_command_to_string(Query_command *query_command) {
    159  |   char *result;
    160  |   char result_buf[STR_XL];
    161  |   char *str1;
    162  |   char *str2;
    163  |   char *str3;
    164  |
    165  |   str1 = MA_to_string(query_command->inv_attrs_bitmap, DF_get_attribute_names());
    166  |   str2 = MA_to_string(query_command->object_type_bitmap, DF_get_class_names());
    167  |   str3 = WK_to_string(query_command->keytypes_bitmap);
    168  |
    169  |   sprintf(result_buf, "Query_command : inv_attrs=%s, recursive=%s, object_type=%s, (e=%d,g=%d,l=%d,m=%d,q=%d,t=%d,v=%d,x=%d,F=%d,K=%d,L=%d,M=%d,R=%d,S=%d), possible keytypes=%s, keys=[%s]",
    170  |           str1,
    171  | 	  query_command->recursive?"y":"n",
    172  |           str2,
    173  |           query_command->e,
    174  |           query_command->g,
    175  |           query_command->l,
    176  |           query_command->m,
    177  |           query_command->q,
    178  |           query_command->t,
    179  |           query_command->v,
    180  |           query_command->x,
    181  |           query_command->fast,
    182  |           query_command->filtered,
    183  |           query_command->L,
    184  |           query_command->M,
    185  |           query_command->R,
    186  |           query_command->S,
    187  |           str3,
    188  |           query_command->keys);
    189  |   wr_free(str1);
    190  |   wr_free(str2);
    191  |   wr_free(str3);
    192  |
    193  |   dieif( wr_malloc((void **)&result, strlen(result_buf)+1) != UT_OK);
    194  |   strcpy(result, result_buf);
    195  |
    196  |   return result;
    197  |
    198  | } /* QC_query_command_to_string() */
    199  |
    200  | /* log_command() */
    201  | /*++++++++++++++++++++++++++++++++++++++
    202  |   Log the command.
    203  |   This is more to do with Tracing.  And should/will get merged with a tracing
    204  |   module (when it is finalized.)
    205  |
    206  |   char *query_str
    207  |
    208  |   Query_command *query_command
    209  |
    210  |   More:
    211  |   +html+ <PRE>
    212  |   Authors:
    213  |         ottrey
    214  |   +html+ </PRE><DL COMPACT>
    215  |   +html+ <DT>Online References:
    216  |   +html+ <DD><UL>
    217  |   +html+ </UL></DL>
    218  |
    219  |   ++++++++++++++++++++++++++++++++++++++*/
    220  | static void log_command(char *query_str, Query_command *query_command) {
    221  |   char *str;
    222  |
    223  |   if( ER_is_traced(FAC_QC, ASP_QC_BUILD) ) {
    224  |     str = QC_query_command_to_string(query_command);
    225  |     ER_dbg_va(FAC_QC, ASP_QC_BUILD,
    226  | 	      "query=[%s]   %s", query_str, str);
    227  |     wr_free(str);
    228  |   }
    229  | } /* log_command() */
    230  |
    231  | /* QC_environ_free() */
    232  | /*++++++++++++++++++++++++++++++++++++++
    233  |   Free the query_environ.
    234  |
    235  |   Query_command *qc query_environ to be freed.
    236  |
    237  |   More:
    238  |   +html+ <PRE>
    239  |   Authors:
    240  |         ottrey
    241  |   +html+ </PRE><DL COMPACT>
    242  |   +html+ <DT>Online References:
    243  |   +html+ <DD><UL>
    244  |   +html+ </UL></DL>
    245  |
    246  |   ++++++++++++++++++++++++++++++++++++++*/
    247  | void QC_environ_free(Query_environ *qe) {
    248  |   if (qe != NULL) {
    249  |     if (qe->version != NULL) {
    250  |       wr_free(qe->version);
    251  |     }
    252  |
    253  |     if (qe->sources_list != NULL) {
    254  |       g_list_free(qe->sources_list);
    255  |       qe->sources_list=NULL;
    256  |     }
    257  |     wr_free(qe);
    258  |   }
    259  | } /* QC_environ_free() */
    260  |
    261  | /* QC_free() */
    262  | /*++++++++++++++++++++++++++++++++++++++
    263  |   Free the query_command.
    264  |
    265  |   Query_command *qc query_command to be freed.
    266  |
    267  |   XXX I'm not sure the bitmaps will get freed.
    268  |   qc->inv_attrs_bitmap
    269  |   qc->object_type_bitmap
    270  |   qc->keytypes_bitmap
    271  |
    272  |   More:
    273  |   +html+ <PRE>
    274  |   Authors:
    275  |         ottrey
    276  |   +html+ </PRE><DL COMPACT>
    277  |   +html+ <DT>Online References:
    278  |   +html+ <DD><UL>
    279  |   +html+ </UL></DL>
    280  |
    281  |   ++++++++++++++++++++++++++++++++++++++*/
    282  | void QC_free(Query_command *qc) {
    283  |   if (qc != NULL) {
    284  |     if (qc->keys != NULL) {
    285  |       wr_free(qc->keys);
    286  |     }
    287  |     wr_free(qc);
    288  |   }
    289  | } /* QC_free() */
    290  |
    291  |
    292  |
    293  | /* QC_fill() */
    294  | /*++++++++++++++++++++++++++++++++++++++
    295  |   Create a new query_command.
    296  |   Returns 0 when OK, -1 when query incorrect.
    297  |
    298  |   char *query_str The garden variety whois query string.
    299  |
    300  |   Query_environ *qe the environment
    301  |
    302  |   More:
    303  |   +html+ <PRE>
    304  |   Authors:
    305  |         ottrey - original code
    306  | 	marek - modified for my getopts, multiple sources;
    307  | 	        and generally cleaned.
    308  |   +html+ </PRE><DL COMPACT>
    309  |   +html+ <DT>Online References:
    310  |   +html+ <DD><UL>
    311  |   +html+ </UL></DL>
    312  |
    313  |   ++++++++++++++++++++++++++++++++++++++*/
    314  | static
    315  | int QC_fill(char *query_str,
    316  | 	     Query_command *query_command,
    317  | 	     Query_environ *qe) {
    318  |
    319  |   int c;
    320  |   int synerrflg = 0;
    321  |   int badparerr = 0;
    322  |   int minusk = 0;
    323  |   char *inv_attrs_str = NULL;
    324  |   char *object_types_str = NULL;
    325  |   int opt_argc;
    326  |   gchar **opt_argv;
    327  |   char *value;
    328  |   char *tmp_query_str;
    329  |   unsigned key_length;
    330  |   int i;
    331  |   int index;
    332  |   C_Type_t type;
    333  |   A_Type_t attr;
    334  |   getopt_state_t *gst = NULL;
    335  |
    336  |   query_command->d = 0;
    337  |   query_command->e = 0;
    338  |   query_command->g = 0;
    339  |   query_command->inv_attrs_bitmap = MA_new(MA_END);
    340  |   query_command->recursive = 1;  /* Recursion is on by default. */
    341  |   query_command->l = 0;
    342  |   query_command->m = 0;
    343  |   query_command->q = -1;
    344  |   query_command->t = -1;
    345  |   query_command->v = -1;
    346  |   query_command->x = 0;
    347  |   query_command->fast = 0;
    348  |   query_command->filtered = 0;
    349  |   query_command->L = 0;
    350  |   query_command->M = 0;
    351  |   query_command->R = 0;
    352  |   query_command->S = 0;
    353  |
    354  |   /* XXX UGLY - "all zeros" in object_type_bitmap means the same as
    355  |      "all ones". To limit the inconsistency, this is changed at the end
    356  |      of this function, so outside "all zeros" is an illegal value. */
    357  |   query_command->object_type_bitmap = MA_new(MA_END);
    358  |   /*
    359  |   query_command->keytypes_bitmap = MA_new(MA_END);
    360  |   */
    361  |   query_command->keys = NULL;
    362  |
    363  |   /* This is so Marek can't crash me :-) */
    364  |   /* Side Effect - query keys are subsequently cut short to STR_S size. */
    365  |
    366  |   dieif( wr_calloc((void **)&tmp_query_str, 1, STR_S+1) != UT_OK);
    367  |   strncpy(tmp_query_str, query_str, STR_S);
    368  |
    369  |   /* Create the arguments. */
    370  |   /* This allows only a maximum of MAX_OPT_ARG_C words in the query. */
    371  |   opt_argv = g_strsplit(tmp_query_str, " ", MAX_OPT_ARG_C);
    372  |
    373  |   /* Determine the number of arguments. */
    374  |   for (opt_argc=0; opt_argv[opt_argc] != NULL; opt_argc++);
    375  |
    376  |   dieif( (gst = mg_new(0)) == NULL );
    377  |
    378  |   while ((c = mg_getopt(opt_argc, opt_argv, "adegi:klrmq:s:t:v:xFKLMRST:V:",
    379  | 			gst)) != EOF) {
    380  |     switch (c) {
    381  |       case 'a':
    382  |         /* Remove any user specified sources from the sources list. */
    383  | 	/* free the list only, do not touch the elements */
    384  | 	g_list_free(qe->sources_list);
    385  | 	qe->sources_list=NULL;
    386  |
    387  |         /* Add all the config sources to the sources list. */
    388  | 	{
    389  | 	  int i;
    390  | 	  ca_dbSource_t *hdl;
    391  |
    392  | 	  for (i=0; (hdl = ca_get_SourceHandleByPosition(i)) != NULL; i++) {
    393  | 	    qe->sources_list = g_list_append(qe->sources_list, (void *)hdl);
    394  | 	  }
    395  | 	}
    396  |
    397  |
    398  |       break;
    399  |
    400  |       case 'e':
    401  |         query_command->e=1;
    402  |       break;
    403  |
    404  |       case 'd':
    405  |         query_command->d=1;
    406  |       break;
    407  |
    408  |       case 'g':
    409  |         query_command->g=1;
    410  |       break;
    411  |
    412  |       case 'i':
    413  |         if (gst->optarg != NULL) {
    414  | 	  char *hackstr = NULL;
    415  |
    416  |           inv_attrs_str = gst->optarg;
    417  |           /* Now a really stupid hard-coded hack to support "pn" being a synonym for "ac,tc,zc,ah" */
    418  |           /* I particularly object to this because it references attributes that should only be
    419  |              defined in XML - but I don't see a simplier more robust way of doing this hack.
    420  |              :-( - ottrey 8/12/99
    421  | 	     ** removed a memory leak - MB, 1/08/00
    422  | 	     */
    423  |           if (   strcmp(inv_attrs_str, "pn") == 0
    424  | 	      || strcmp(inv_attrs_str, "ro") == 0) {
    425  | 	    wr_malloc( (void **)& hackstr, 24);  /* make a copy */
    426  | 	    strcpy(hackstr, "ac,tc,zc,ah");
    427  | 	    inv_attrs_str = hackstr;
    428  |           }
    429  |           while (*inv_attrs_str) {
    430  |             index = getsubopt(&inv_attrs_str, DF_get_attribute_aliases(), &value);
    431  |             if (index == -1) {
    432  | 	      /* Unknown attribute encountered. */
    433  | 	      char *rep = ca_get_qc_badattr ;
    434  |               SK_cd_puts(&(qe->condat), rep);
    435  | 	      wr_free(rep);
    436  |
    437  |               attr = -1;
    438  |               badparerr++;
    439  |             }
    440  |             else {
    441  |               mask_t inv_attr_mask = MA_new(INV_ATTR_MASK);
    442  |               attr = DF_get_attribute_index(index);
    443  |               if ( MA_isset(inv_attr_mask, attr) == 1 ) {
    444  |                 /* Add the attr to the bitmap. */
    445  |                 MA_set(&(query_command->inv_attrs_bitmap), attr, 1);
    446  |               }
    447  |               else {
    448  | 	        /* "%s" is not an inverse searchable attribute. */
    449  | 	        char *rep = ca_get_qc_fmt_attrnotinv ;
    450  | 	        SK_cd_printf(&(qe->condat), rep,
    451  | 		    (DF_get_attribute_aliases())[index]);
    452  |                 wr_free(rep);
    453  |                 badparerr++;
    454  |               }
    455  |             }
    456  |           } /* while () */
    457  |
    458  | 	  if( hackstr != NULL) {
    459  | 	    wr_free(hackstr);
    460  | 	  }
    461  |         } /* if () */
    462  |       break;
    463  |
    464  |       case 'k':
    465  | 	minusk = 1;
    466  |       break;
    467  |
    468  |       case 'r':
    469  |         query_command->recursive=0;       /* Unset recursion */
    470  |       break;
    471  |
    472  |       case 'l':
    473  |         query_command->l=1;
    474  |       break;
    475  |
    476  |       case 'm':
    477  |         query_command->m=1;
    478  |       break;
    479  |
    480  |       case 'q':
    481  |         if (gst->optarg != NULL) {
    482  |           index = getsubopt(&gst->optarg, DF_get_server_queries(), &value);
    483  |           if (index == -1) {
    484  |             synerrflg++;
    485  |           }
    486  |           else {
    487  |             query_command->q = index;
    488  |           }
    489  |         } /* if () */
    490  |       break;
    491  |
    492  |       case 's':
    493  |         if (gst->optarg != NULL) {
    494  | 	  char *token, *cursor = gst->optarg;
    495  | 	  ca_dbSource_t *handle;
    496  |
    497  |           /* Remove any sources from the sources list. */
    498  | 	  g_list_free(qe->sources_list);
    499  | 	  qe->sources_list=NULL;
    500  |
    501  | 	  /* go through specified sources */
    502  | 	  while( (token = strsep( &cursor, "," )) != NULL ) {
    503  |
    504  | 	    if( (handle = ca_get_SourceHandleByName(token)) != NULL ) {
    505  | 	      /* append */
    506  | 	      qe->sources_list
    507  | 		= g_list_append(qe->sources_list, (void *) handle );
    508  | 	    }
    509  | 	    else {
    510  | 	      /* bail out */
    511  |
    512  | 	      /* Unknown source %s requested. */
    513  | 	      char *rep = ca_get_qc_fmt_badsource ;
    514  | 	      SK_cd_printf(&(qe->condat), rep, token );
    515  | 	      wr_free(rep);
    516  |
    517  | 	      /* XXX error */
    518  | 	      badparerr++;
    519  |
    520  | 	    } /* if handle not null */
    521  | 	  } /* while sources */
    522  |         } /* if argument present */
    523  | 	break;
    524  |
    525  |       case 't':
    526  |         if (gst->optarg != NULL) {
    527  |           object_types_str = gst->optarg;
    528  |           while (*object_types_str) {
    529  |             index = getsubopt(&object_types_str, DF_get_class_aliases(), &value);
    530  |             if (index == -1) {
    531  | 	      /* Unknown object type encountered */
    532  | 	      char *rep = ca_get_qc_badobjtype ;
    533  |               SK_cd_puts(&(qe->condat), rep);
    534  | 	      wr_free(rep);
    535  |               badparerr++;
    536  |             }
    537  |             else {
    538  |               type = DF_get_class_index(index);
    539  |               query_command->t=type;
    540  |             }
    541  |           }
    542  |         }
    543  |       break;
    544  |
    545  |       case 'v':
    546  |         if (gst->optarg != NULL) {
    547  |           object_types_str = gst->optarg;
    548  |           if (*object_types_str) {
    549  |             index = getsubopt(&object_types_str, DF_get_class_aliases(), &value);
    550  |             if (index == -1) {
    551  | 	      /* Unknown object type encountered */
    552  | 	      char *rep = ca_get_qc_badobjtype ;
    553  |               SK_cd_puts(&(qe->condat), rep);
    554  | 	      wr_free(rep);
    555  |               badparerr++;
    556  |             }
    557  |             else {
    558  |               type = DF_get_class_index(index);
    559  |               query_command->v=type;
    560  |             }
    561  |           }
    562  |         }
    563  |       break;
    564  |
    565  |       case 'x':
    566  |         query_command->x=1;
    567  |       break;
    568  |
    569  |       case 'F':
    570  |         query_command->fast=1;
    571  | 	query_command->recursive=0; /* implies no recursion */
    572  |       break;
    573  |
    574  |       case 'K':
    575  |         query_command->filtered=1;
    576  | 	query_command->recursive=0; /* implies no recursion */
    577  |       break;
    578  |
    579  |       case 'L':
    580  |         query_command->L=1;
    581  |       break;
    582  |
    583  |       case 'M':
    584  |         query_command->M=1;
    585  |       break;
    586  |
    587  |       case 'R':
    588  |         query_command->R=1;
    589  |       break;
    590  |
    591  |       case 'S':
    592  |         query_command->S=1;
    593  |       break;
    594  |
    595  |       case 'T':
    596  |         if (gst->optarg != NULL) {
    597  | 	  /* parse the specification */
    598  |           object_types_str = gst->optarg;
    599  |           while (*object_types_str) {
    600  |             index = getsubopt(&object_types_str, DF_get_class_aliases(), &value);
    601  |             if (index == -1) {
    602  | 	      /* Unknown object type encountered */
    603  | 	      char *rep = ca_get_qc_badobjtype ;
    604  |               SK_cd_puts(&(qe->condat), rep);
    605  | 	      wr_free(rep);
    606  |               badparerr++;
    607  |             }
    608  |             else {
    609  |               type = DF_get_class_index(index);
    610  |               /* Add the type to the bitmap. */
    611  |               MA_set(&(query_command->object_type_bitmap), (unsigned) type, 1);
    612  |             }
    613  |           }
    614  |         }
    615  |       break;
    616  |
    617  |       case 'V':
    618  |         if (qe->version != NULL) {
    619  |           /* free up the old client info */
    620  |           wr_free(qe->version);
    621  |         }
    622  |
    623  |         {
    624  |           char *token, *cursor = gst->optarg;
    625  |           while( (token = strsep( &cursor, "," )) != NULL ) {
    626  |             if(IP_addr_e2b( & (qe->pIP), token)
    627  |                != IP_OK ) {
    628  |               /* means it was not an IP -> it was a version */
    629  |               dieif( wr_malloc( (void **)&(qe->version),
    630  | 				strlen(token)+1) != UT_OK);
    631  |               strcpy(qe->version, token);
    632  |             }
    633  |           }
    634  |         }
    635  |       break;
    636  |
    637  |       /* any other flag, including '?' and ':' errors */
    638  |       default:
    639  |         synerrflg++;
    640  |     }
    641  |   }
    642  |
    643  |   /* copy the key */
    644  |
    645  |   /* Work out the length of space needed */
    646  |   key_length = 1; /* for terminal '\0' */
    647  |   for (i=gst->optind ; i < opt_argc; i++) {
    648  |     /* length for the string + 1 for the '\0'+ 1 for the ' ' */
    649  |     if (opt_argv[i] != NULL) {
    650  |       key_length += strlen(opt_argv[i])+1;
    651  |     }
    652  |   }
    653  |   /* allocate */
    654  |   dieif( wr_calloc((void **)&(query_command->keys), 1, key_length+1) != UT_OK);
    655  |   /* copy */
    656  |   for (i=gst->optind; i < opt_argc; i++) {
    657  |     strcat(query_command->keys, opt_argv[i]);
    658  |     if ( (i + 1) < opt_argc) {
    659  |       strcat(query_command->keys, " ");
    660  |     }
    661  |   }
    662  |
    663  |   /* if no error, process the key, otherwise don't bother */
    664  |   if ( ! synerrflg && ! badparerr ) {
    665  |     /* convert the key to uppercase. */
    666  |     for (i=0; i <= key_length; i++) {
    667  |       query_command->keys[i] = toupper(query_command->keys[i]);
    668  |     }
    669  |
    670  |     /* make the keytypes_bitmap. */
    671  |     query_command->keytypes_bitmap = WK_new(query_command->keys);
    672  |
    673  |     /* fix the object type bitmap - turn "all zeros" into "all ones" */
    674  |     if( MA_bitcount(query_command->object_type_bitmap) == 0 ) {
    675  |       query_command->object_type_bitmap = MA_not(query_command->object_type_bitmap);
    676  |     }
    677  |
    678  |     /* -d handling: if the keytype is IPv4/v6 address/prefix/range, then
    679  |        exclude the domains unless -d is set
    680  |        XXX this must be kept in sync with new types */
    681  |     if( query_command->d == 0
    682  | 	&& ( MA_isset(query_command->keytypes_bitmap, WK_IPADDRESS)
    683  | 	     || MA_isset(query_command->keytypes_bitmap, WK_IPRANGE )
    684  | 	     || MA_isset(query_command->keytypes_bitmap, WK_IPPREFIX )
    685  | 	     || MA_isset(query_command->keytypes_bitmap, WK_IP6PREFIX )
    686  | 	     ) ) {
    687  |
    688  |       MA_set(&(query_command->object_type_bitmap), C_DN , 0);
    689  |     }
    690  |
    691  |     /* tracing */
    692  |     log_command(tmp_query_str, query_command);
    693  |
    694  |     /* "keep connection" processing:
    695  |        when opening connection, -k may be alone or with a query
    696  |        later -k must appear alone (or there must be an empty line,
    697  |        or an error) for the connection to close.
    698  |     */
    699  |     if( minusk ) {
    700  |       if( qe->k == 0 ) { /* opening */
    701  | 	qe->k = 1;
    702  |       }
    703  |       else { /* closing, if no key; otherwise keep open */
    704  | 	if( key_length <= 1 ) {
    705  | 	  qe->k = 0;
    706  | 	}
    707  |       }
    708  |     }
    709  |
    710  |   } /* if no error */
    711  |
    712  |   /* we don't need this anymore */
    713  |   wr_free(tmp_query_str);
    714  |   wr_free(gst);
    715  |   g_strfreev(opt_argv);
    716  |
    717  |   if(synerrflg > 0) { /* severe syntax error. Usage must be printed */
    718  |     return QC_SYNERR;
    719  |   }
    720  |   else if(badparerr > 0) { /* the requester has a clue. No Usage info */
    721  |     return QC_PARERR;
    722  |   }
    723  |   else {
    724  |     return 0;
    725  |   }
    726  | } /* QC_fill() */
    727  |
    728  | /* QC_environ_new() */
    729  | /*++++++++++++++++++++++++++++++++++++++
    730  |   Create a new query environment.
    731  |
    732  |   More:
    733  |   +html+ <PRE>
    734  |   Authors:
    735  |         ottrey
    736  |   +html+ </PRE><DL COMPACT>
    737  |   +html+ <DT>Online References:
    738  |   +html+ <DD><UL>
    739  |   +html+ </UL></DL>
    740  |
    741  |   ++++++++++++++++++++++++++++++++++++++*/
    742  | Query_environ *QC_environ_new(char *ip, int sock) {
    743  |   Query_environ *qe;
    744  |
    745  |
    746  |   dieif( wr_calloc((void **)&qe, 1, sizeof(Query_environ)+1 ) != UT_OK);
    747  |   qe->condat.ip = ip;
    748  |   qe->condat.sock = sock;
    749  |
    750  |   /* The source is initialized to include only the deflook sources */
    751  |   {
    752  |     int i;
    753  |     ca_dbSource_t *hdl;
    754  |
    755  |     for (i=0; (hdl = ca_get_SourceHandleByPosition(i)) != NULL; i++) {
    756  |       char *amrmrulez = ca_get_srcdeflook(hdl);
    757  |       if( strcmp(amrmrulez, "y")==0 ) {
    758  | 	qe->sources_list = g_list_append(qe->sources_list, (void *)hdl);
    759  |       }
    760  |       free(amrmrulez);
    761  |     }
    762  |   }
    763  |
    764  |   return qe;
    765  |
    766  | } /* QC_environ_new() */
    767  |
    768  |
    769  |
    770  |
    771  | /* QC_create() */
    772  | /*++++++++++++++++++++++++++++++++++++++
    773  |   try to parse the query and fill in the QC struct, setting
    774  |   qc->query_type accordingly.
    775  |
    776  |   Query_command *QC_create    returns allocated structure
    777  |
    778  |   char *input                 user query
    779  |
    780  |   Query_environ *qe           query environment structure
    781  |
    782  |   Author:
    783  |     marek.
    784  |
    785  |   ++++++++++++++++++++++++++++++++++++++*/
    786  |
    787  | Query_command *QC_create(char *input, Query_environ *qe)
    788  | {
    789  |   Query_command *qc;
    790  |   /* allocate place for a copy of the input */
    791  |   char *copy = calloc(1,strlen(input)+1);
    792  |   unsigned char *ci, *co;
    793  |   int qt;
    794  |   /* clean the string from junk - allow only known chars, something like
    795  |      tr/A-Za-z0-9\-\_\:\+\=\.\,\@\/ \n//cd;
    796  |
    797  |      strip leading spaces too
    798  |   */
    799  |
    800  |   dieif(copy == NULL);
    801  |
    802  |   for(ci = (unsigned char *)input; *ci != 0 && isspace(*ci); ci++) {
    803  |     /* EMPTY */
    804  |   }
    805  |
    806  |   for(co = (unsigned char *) copy; *ci != 0; ci++) {
    807  |     if( strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ"     /* only those are allowed */
    808  | 	       "abcdefghijklmnopqrstuvwxyz"
    809  | 	       "0123456789-_:+=.,@/' \n", *ci) != NULL) {
    810  |       *(co++) = *ci;
    811  |     }
    812  |   }
    813  |
    814  |   /* now delete whitespace chars at the end */
    815  |   while( co != (unsigned char *)copy /* don't read past the beginning */
    816  | 	 && isspace(*co) ) {
    817  |     *co = '\0';
    818  |     co--;
    819  |   }
    820  |
    821  |
    822  |   dieif( wr_calloc((void **)&qc, 1, sizeof(Query_command)+1) != UT_OK);
    823  |
    824  |   if ( strlen(copy) == 0) {
    825  |     /* An empty query (Ie return) was sent */
    826  |     qc->query_type = QC_EMPTY;
    827  |   }
    828  |   else {        /* else <==> input_length > 0 ) */
    829  |     /* parse query */
    830  |     qt = QC_fill(copy, qc, qe);
    831  |
    832  |     if( qt == QC_SYNERR || qt == QC_PARERR ) {
    833  |       qc->query_type = qt;
    834  |     }
    835  |     else {
    836  |       /* Update the query environment */
    837  |       /* qe = QC_environ_update(qc, qe); */
    838  |
    839  |       /* Only do a query if there are keys. */
    840  |       if (qc->keys == NULL || strlen(qc->keys) == 0 ) {
    841  | 	if( strlen(qc->keys) == 0
    842  | 	    && ( qc->q != -1 || qc->t != -1 || qc->v != -1 ) ) {
    843  | 	  qc->query_type = QC_TEMPLATE;
    844  | 	}
    845  | 	else {
    846  | 	  qc->query_type = QC_NOKEY;
    847  | 	}
    848  |       }
    849  |       else {
    850  | 	if ( strcmp(qc->keys, "HELP") == 0 ) {
    851  | 	  qc->query_type = QC_HELP;
    852  | 	}
    853  | 	/* So, a real query */
    854  | 	else if( qc->filtered ) {
    855  | 	  qc->query_type = QC_FILTERED;
    856  | 	}
    857  | 	else {
    858  | 	  qc->query_type = QC_REAL;
    859  | 	}
    860  |       }
    861  |     }
    862  |   }
    863  |
    864  |   free(copy);
    865  |
    866  |   return qc;
    867  | }
    868  |
    869  |
    870  | /*++++++++++++++++++++++++++++++++++++++
    871  |
    872  |   Get the name of the given query type code.
    873  |
    874  |   char *QC_get_qrytype   returns a pointer to an element of array of static strings
    875  |
    876  |   qc_qtype_t qrytype     query type code
    877  |
    878  |   ++++++++++++++++++++++++++++++++++++++*/
    879  |
    880  | char *QC_get_qrytype(qc_qtype_t qrytype) {
    881  |   dieif(qrytype >= QC_TYPE_MAX);
    882  |
    883  |   return qrytype_str[qrytype];
    884  | }