Source File modules/qc/query_command.c

    1    | /***************************************
    2    |   $Revision: 1.31 $
    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   |   Authors             : ottrey@ripe.net
    12   |                         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   | #define MAX_OPT_ARG_C 20
    47   |
    48   | /*+ String sizes +*/
    49   | #define STR_S   63
    50   | #define STR_M   255
    51   | #define STR_L   1023
    52   | #define STR_XL  4095
    53   | #define STR_XXL 16383
    54   |
    55   | #ifdef HAVE_STRSEP
    56   | /* good */
    57   | #else
    58   | #  if defined(HAVE_STRTOK_R) && !defined(HAVE_STRSEP)
    59   | /* emulate strsep with strtok_r
    60   |    by making first arg to strtok_r point to the last
    61   | */
    62   | char *
    63   | strsep(char **stringp, const char *delim)
    64   | {
    65   |   return strtok_r( *stringp, delim, stringp);
    66   | }
    67   | #  else
    68   | #  error "must have strsep or strtok_r"
    69   | #  endif
    70   | #endif
    71   |
    72   |
    73   | /* my_getopt() */
    74   | /*++++++++++++++++++++++++++++++++++++++
    75   |   A thread safe version of getopt, used to get the options from the whois
    76   |   query.
    77   |
    78   |   int opt_argc The number of query arguments.
    79   |
    80   |   char **opt_argv The query arguments.
    81   |
    82   |   char *optstring The string containing valid options.
    83   |
    84   |   int *my_optind_ptr A pointer to the index into the options of the option
    85   |   returned.
    86   |
    87   |   char **my_optarg_ptr A pointer to the arguments to be returned.
    88   |
    89   |   More:
    90   |   +html+ <PRE>
    91   |   Authors:
    92   |         ottrey
    93   |   +html+ </PRE><DL COMPACT>
    94   |   +html+ <DT>Online References:
    95   |   +html+ <DD><UL>
    96   |   +html+     <LI>man getopt
    97   |   +html+ </UL></DL>
    98   |
    99   |   ++++++++++++++++++++++++++++++++++++++*/
    100  | static int my_getopt(int opt_argc, char **opt_argv, char *optstring, int *my_optind_ptr, char **my_optarg_ptr) {
    101  |   int c='?';
    102  |   int i, j;
    103  |   int no_options;
    104  |   int optind = *my_optind_ptr;
    105  |   char option[4];
    106  |   int option_matched=0;
    107  |
    108  |   /* Get the number of options in the option string */
    109  |   for(i=0, no_options=0; i < strlen(optstring) ; i++) {
    110  |     if (optstring[i] != ':') {
    111  |       no_options++;
    112  |     }
    113  |   }
    114  |
    115  |   /* Iterate through all the option until it matches the current opt_argv */
    116  |   /* Ie. opt_argv[optind] */
    117  |   for (i=0, j=0; i <= no_options; i++, j++) {
    118  |     /* Construct one option from the optstring */
    119  |     option[0] = '-';
    120  |     if (optstring[j] == ':') {
    121  |       j++;
    122  |     }
    123  |     option[1] = optstring[j];
    124  |     if ( optstring[j+1] == ':' ) {
    125  |       option[2] = ':';
    126  |     }
    127  |     else {
    128  |       option[2] = '\0';
    129  |     }
    130  |     option[3] = '\0';
    131  |
    132  |     if (optind < opt_argc) {
    133  |       if (strlen(opt_argv[optind]) > 0) {
    134  |
    135  | 	  /*	  printf("opt_argv[%d] == option <==> %s == %s\n",
    136  | 		  optind, opt_argv[optind], option); */
    137  |
    138  |         if (strncmp(opt_argv[optind], option, 2) == 0) {
    139  |           /* Does the option have arguments. */
    140  |           if (option[2] == ':') {
    141  |             /* If the option has arguments */
    142  |             if (strlen(opt_argv[optind]) > 2) {
    143  |               /* If the arguments are in this token */
    144  |               *my_optarg_ptr = (opt_argv[optind])+2;
    145  |             }
    146  |             else {
    147  |               /* If the arguments are in the next token */
    148  |               *my_optarg_ptr = opt_argv[optind+1];
    149  |               optind++;
    150  |             }
    151  |           }
    152  |           else {
    153  |             /* There are no arguments to this token */
    154  |             *my_optarg_ptr = NULL;
    155  |           }
    156  |           /* Option matched - break out of the search */
    157  |           option_matched = 1;
    158  |           break;
    159  |         }
    160  |       }
    161  |     }
    162  |   } /* for() */
    163  |
    164  |   if ( option_matched == 1 ) {
    165  |     /* This option was matched, return it. */
    166  |     c = option[1];
    167  |
    168  |     /* Move to the next opt_argv */
    169  |     optind++;
    170  |     *my_optind_ptr = optind;
    171  |   }
    172  |   else {
    173  |     /* Discontinue search */
    174  |     c = EOF;
    175  |   }
    176  |
    177  |   return c;
    178  |
    179  | } /* my_getopt() */
    180  |
    181  | /* QC_environ_to_string() */
    182  | /*++++++++++++++++++++++++++++++++++++++
    183  |   Convert the query_environ to a string.
    184  |
    185  |   Query_environ *query_environ The query_environ to be converted.
    186  |
    187  |   More:
    188  |   +html+ <PRE>
    189  |   Authors:
    190  |         ottrey
    191  |   +html+ </PRE><DL COMPACT>
    192  |   +html+ <DT>Online References:
    193  |   +html+ <DD><UL>
    194  |   +html+ </UL></DL>
    195  |
    196  |   ++++++++++++++++++++++++++++++++++++++*/
    197  | char *QC_environ_to_string(Query_environ qe) {
    198  |   char *result;
    199  |   char *str1;
    200  |   char str2[IP_ADDRSTR_MAX];
    201  |   char result_buf[STR_XL];
    202  |
    203  |   str1 = CO_sources_list_to_string(qe.sources_list);
    204  |
    205  |   if( IP_addr_b2a( &(qe.pIP), str2, IP_ADDRSTR_MAX) != IP_OK ) {
    206  |     *str2 = '\0';
    207  |   }
    208  |
    209  |   sprintf(result_buf, "host=%s, keep_connection=%s, sources=%s, version=%s%s%s", qe.condat.ip,
    210  |           qe.k?"on":"off",
    211  |           str1,
    212  |           (qe.version == NULL) ? "?" : qe.version,
    213  |           *str2 == '\0' ? "" : ", passedIP=",
    214  |           *str2 == '\0' ? "" : str2
    215  |           );
    216  |
    217  |   wr_free(str1);
    218  |
    219  |   dieif( wr_malloc((void **)&result, strlen(result_buf)+1) != UT_OK);
    220  |
    221  |   strcpy(result, result_buf);
    222  |
    223  |   return result;
    224  |
    225  | } /* QC_environ_to_string() */
    226  |
    227  | /* QC_query_command_to_string() */
    228  | /*++++++++++++++++++++++++++++++++++++++
    229  |   Convert the query_command to a string.
    230  |
    231  |   Query_command *query_command The query_command to be converted.
    232  |
    233  |   More:
    234  |   +html+ <PRE>
    235  |   Authors:
    236  |         ottrey
    237  |   +html+ </PRE><DL COMPACT>
    238  |   +html+ <DT>Online References:
    239  |   +html+ <DD><UL>
    240  |   +html+ </UL></DL>
    241  |
    242  |   ++++++++++++++++++++++++++++++++++++++*/
    243  | char *QC_query_command_to_string(Query_command *query_command) {
    244  |   char *result;
    245  |   char result_buf[STR_XL];
    246  |   char *str1;
    247  |   char *str2;
    248  |   char *str3;
    249  |
    250  |   str1 = MA_to_string(query_command->inv_attrs_bitmap, DF_get_attribute_names());
    251  |   str2 = MA_to_string(query_command->object_type_bitmap, DF_get_class_names());
    252  |   str3 = WK_to_string(query_command->keytypes_bitmap);
    253  |
    254  |   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]",
    255  |           str1,
    256  | 	  query_command->recursive?"y":"n",
    257  |           str2,
    258  |           query_command->e,
    259  |           query_command->g,
    260  |           query_command->l,
    261  |           query_command->m,
    262  |           query_command->q,
    263  |           query_command->t,
    264  |           query_command->v,
    265  |           query_command->x,
    266  |           query_command->fast,
    267  |           query_command->filtered,
    268  |           query_command->L,
    269  |           query_command->M,
    270  |           query_command->R,
    271  |           query_command->S,
    272  |           str3,
    273  |           query_command->keys);
    274  |   wr_free(str1);
    275  |   wr_free(str2);
    276  |   wr_free(str3);
    277  |
    278  |   dieif( wr_malloc((void **)&result, strlen(result_buf)+1) != UT_OK);
    279  |   strcpy(result, result_buf);
    280  |
    281  |   return result;
    282  |
    283  | } /* QC_query_command_to_string() */
    284  |
    285  | /* log_command() */
    286  | /*++++++++++++++++++++++++++++++++++++++
    287  |   Log the command.
    288  |   This is more to do with Tracing.  And should/will get merged with a tracing
    289  |   module (when it is finalized.)
    290  |
    291  |   char *query_str
    292  |
    293  |   Query_command *query_command
    294  |
    295  |   More:
    296  |   +html+ <PRE>
    297  |   Authors:
    298  |         ottrey
    299  |   +html+ </PRE><DL COMPACT>
    300  |   +html+ <DT>Online References:
    301  |   +html+ <DD><UL>
    302  |   +html+ </UL></DL>
    303  |
    304  |   ++++++++++++++++++++++++++++++++++++++*/
    305  | static void log_command(char *query_str, Query_command *query_command) {
    306  |   char *str;
    307  |
    308  |   if( ER_is_traced(FAC_QC, ASP_QC_BUILD) ) {
    309  |     str = QC_query_command_to_string(query_command);
    310  |     ER_dbg_va(FAC_QC, ASP_QC_BUILD,
    311  | 	      "query=[%s]   %s", query_str, str);
    312  |     wr_free(str);
    313  |   }
    314  | } /* log_command() */
    315  |
    316  | /* QC_environ_free() */
    317  | /*++++++++++++++++++++++++++++++++++++++
    318  |   Free the query_environ.
    319  |
    320  |   Query_command *qc query_environ to be freed.
    321  |
    322  |   More:
    323  |   +html+ <PRE>
    324  |   Authors:
    325  |         ottrey
    326  |   +html+ </PRE><DL COMPACT>
    327  |   +html+ <DT>Online References:
    328  |   +html+ <DD><UL>
    329  |   +html+ </UL></DL>
    330  |
    331  |   ++++++++++++++++++++++++++++++++++++++*/
    332  | void QC_environ_free(Query_environ *qe) {
    333  |   if (qe != NULL) {
    334  |     if (qe->version != NULL) {
    335  |       wr_free(qe->version);
    336  |     }
    337  |
    338  |     if (qe->sources_list != NULL) {
    339  |       g_list_free(qe->sources_list);
    340  |     }
    341  |     wr_free(qe);
    342  |   }
    343  | } /* QC_environ_free() */
    344  |
    345  | /* QC_free() */
    346  | /*++++++++++++++++++++++++++++++++++++++
    347  |   Free the query_command.
    348  |
    349  |   Query_command *qc query_command to be freed.
    350  |
    351  |   XXX I'm not sure the bitmaps will get freed.
    352  |   qc->inv_attrs_bitmap
    353  |   qc->object_type_bitmap
    354  |   qc->keytypes_bitmap
    355  |
    356  |   More:
    357  |   +html+ <PRE>
    358  |   Authors:
    359  |         ottrey
    360  |   +html+ </PRE><DL COMPACT>
    361  |   +html+ <DT>Online References:
    362  |   +html+ <DD><UL>
    363  |   +html+ </UL></DL>
    364  |
    365  |   ++++++++++++++++++++++++++++++++++++++*/
    366  | void QC_free(Query_command *qc) {
    367  |   if (qc != NULL) {
    368  |     if (qc->keys != NULL) {
    369  |       wr_free(qc->keys);
    370  |     }
    371  |     wr_free(qc);
    372  |   }
    373  | } /* QC_free() */
    374  |
    375  |
    376  |
    377  | /* QC_fill() */
    378  | /*++++++++++++++++++++++++++++++++++++++
    379  |   Create a new query_command.
    380  |
    381  |
    382  |
    383  |   char *query_str The garden variety whois query string.
    384  |
    385  |   Query_environ *qe the environment
    386  |
    387  |   Pre-condition:
    388  |
    389  |   Returns -1 when query incorrect, 0 otherwise
    390  |
    391  |   More:
    392  |   +html+ <PRE>
    393  |   Authors:
    394  |         ottrey
    395  |   +html+ </PRE><DL COMPACT>
    396  |   +html+ <DT>Online References:
    397  |   +html+ <DD><UL>
    398  |   +html+ </UL></DL>
    399  |
    400  |   ++++++++++++++++++++++++++++++++++++++*/
    401  | static
    402  | int QC_fill(char *query_str,
    403  | 	     Query_command *query_command,
    404  | 	     Query_environ *qe) {
    405  |   char *my_optarg;
    406  |   int my_optind = 0;
    407  |   int c;
    408  |   int errflg = 0;
    409  |   char *inv_attrs_str = NULL;
    410  |   char *object_types_str = NULL;
    411  |   char *sources_str = NULL;
    412  |   int opt_argc;
    413  |   gchar **opt_argv;
    414  |   char *value;
    415  |   char *tmp_query_str;
    416  |   int key_length;
    417  |   int i;
    418  |   int index;
    419  |   int type;
    420  |   int attr;
    421  |
    422  |   char str_buf[STR_XL];
    423  |
    424  |   GList *first_source;
    425  |
    426  |   query_command->e = 0;
    427  |   query_command->g = 0;
    428  |   query_command->inv_attrs_bitmap = MA_new(MA_END);
    429  |   query_command->recursive = 1;  /* Recursion is on by default. */
    430  |   query_command->l = 0;
    431  |   query_command->m = 0;
    432  |   query_command->q = -1;
    433  |   query_command->t = -1;
    434  |   query_command->v = -1;
    435  |   query_command->x = 0;
    436  |   query_command->fast = 0;
    437  |   query_command->filtered = 0;
    438  |   query_command->L = 0;
    439  |   query_command->M = 0;
    440  |   query_command->R = 0;
    441  |   query_command->S = 0;
    442  |   query_command->object_type_bitmap = MA_new(MA_END);
    443  |   /*
    444  |   query_command->keytypes_bitmap = MA_new(MA_END);
    445  |   */
    446  |   query_command->keys = NULL;
    447  |
    448  |   /* This is so Marek can't crash me :-) */
    449  |   /* Side Effect - query keys are subsequently cut short to STR_S size. */
    450  |
    451  |   dieif( wr_calloc((void **)&tmp_query_str, 1, STR_S+1) != UT_OK);
    452  |   strncpy(tmp_query_str, query_str, STR_S);
    453  |
    454  |   /* Create the arguments. */
    455  |   /* This allows only a maximum of MAX_OPT_ARG_C words in the query. */
    456  |   opt_argv = g_strsplit(tmp_query_str, " ", MAX_OPT_ARG_C);
    457  |
    458  |   /* Determine the number of arguments. */
    459  |   for (opt_argc=0; opt_argv[opt_argc] != NULL; opt_argc++);
    460  |
    461  |   while ((c = my_getopt(opt_argc, opt_argv, "aegi:klrmq:s:t:v:xFKLMRST:V:", &my_optind, &my_optarg)) != EOF) {
    462  |     switch (c) {
    463  |       case 'a':
    464  |         /* Remove any user specified sources from the sources list. */
    465  |         while ((first_source = g_list_first(qe->sources_list)) != NULL) {
    466  |           qe->sources_list = g_list_remove(qe->sources_list, first_source->data);
    467  |         }
    468  | #if 0
    469  |         /* Add all the config sources to the sources list. */
    470  |         for (i=0; CO_get_source(i) != NULL; i++) {
    471  |           qe->sources_list = g_list_append(qe->sources_list, (void *)CO_get_source_database(i));
    472  |         }
    473  | #else
    474  | 	qe->sources_list = g_list_append(qe->sources_list,  CO_get_database() );
    475  | #endif
    476  |
    477  |       break;
    478  |
    479  |       case 'e':
    480  |         query_command->e=1;
    481  |       break;
    482  |
    483  |       case 'g':
    484  |         query_command->g=1;
    485  |       break;
    486  |
    487  |       case 'i':
    488  |         if (my_optarg != NULL) {
    489  |           inv_attrs_str = my_optarg;
    490  |           /* Now a really stupid hard-coded hack to support "pn" being a synonym for "ac,tc,zc,ah" */
    491  |           /* I particularly object to this because it references attributes that should only be
    492  |              defined in XML - but I don't see a simplier more robust way of doing this hack.
    493  |              :-( - ottrey 8/12/99 */
    494  |           if (strcmp(inv_attrs_str, "pn") == 0) {
    495  | 	    dieif( wr_malloc((void **)&inv_attrs_str, 12) != UT_OK);
    496  |             strcpy(inv_attrs_str, "ac,tc,zc,ah");
    497  |           }
    498  |           else if (strcmp(inv_attrs_str, "ro") == 0) {
    499  | 	    dieif( wr_malloc((void **)&inv_attrs_str, 12) != UT_OK);
    500  |             strcpy(inv_attrs_str, "ac,tc,zc,ah");
    501  |           }
    502  |           while (*inv_attrs_str) {
    503  |             index = getsubopt(&inv_attrs_str, DF_get_attribute_aliases(), &value);
    504  |             if (index == -1) {
    505  |               attr = -1;
    506  |               strcpy(str_buf, "");
    507  |               sprintf(str_buf, "Unknown attribute encountered.\n");
    508  |               SK_cd_puts(&(qe->condat), str_buf);
    509  |               errflg++;
    510  |             }
    511  |             else {
    512  |               mask_t inv_attr_mask = MA_new(INV_ATTR_MASK);
    513  |               attr = DF_get_attribute_index(index);
    514  |               if ( MA_isset(inv_attr_mask, attr) == 1 ) {
    515  |                 /* Add the attr to the bitmap. */
    516  |                 MA_set(&(query_command->inv_attrs_bitmap), attr, 1);
    517  |               }
    518  |               else {
    519  |                 strcpy(str_buf, "");
    520  |                 sprintf(str_buf, "\"%s\" does not belong to inv_attr.\n", (DF_get_attribute_aliases())[index]);
    521  |                 SK_cd_puts(&(qe->condat), str_buf);
    522  |                 errflg++;
    523  |               }
    524  |             }
    525  |           } /* while () */
    526  |         } /* if () */
    527  |       break;
    528  |
    529  |       case 'k':
    530  |         /* This is a tricky XOR operation....  ;-)
    531  |            State transition for k_flag:
    532  |            0 -> 0 then k flag = 0, connected = 0
    533  |            0 -> 1 then k flag = 1, connected = 1
    534  |            1 -> 0 then k flag = 1, connected = 1
    535  |            1 -> 1 then k flag = 0, connected = 0
    536  |         */
    537  |         qe->k ^= 1;
    538  |       break;
    539  |
    540  |       case 'r':
    541  |         query_command->recursive=0;       /* Unset recursion */
    542  |       break;
    543  |
    544  |       case 'l':
    545  |         query_command->l=1;
    546  |       break;
    547  |
    548  |       case 'm':
    549  |         query_command->m=1;
    550  |       break;
    551  |
    552  |       case 'q':
    553  |         if (my_optarg != NULL) {
    554  |           index = getsubopt(&my_optarg, DF_get_server_queries(), &value);
    555  |           if (index == -1) {
    556  |             errflg++;
    557  |           }
    558  |           else {
    559  |             query_command->q = index;
    560  |           }
    561  |         } /* if () */
    562  |       break;
    563  |
    564  |       case 's':
    565  |         if (my_optarg != NULL) {
    566  |           sources_str = my_optarg;
    567  |           /* Remove any sources from the sources list. */
    568  |           while ((first_source = g_list_first(qe->sources_list)) != NULL) {
    569  |             qe->sources_list = g_list_remove(qe->sources_list, first_source->data);
    570  |           }
    571  |           while (*sources_str) {
    572  |             index = getsubopt(&sources_str, CO_get_sources(), &value);
    573  |             if (index == -1) {
    574  |               strcpy(str_buf, "");
    575  |               sprintf(str_buf, "Unknown source encountered.\nNot one of: %s\n", CO_sources_to_string());
    576  |               SK_cd_puts(&(qe->condat), str_buf);
    577  |
    578  |               /* Put the default source back in. */
    579  |               SK_cd_puts(&(qe->condat), "Reverting to default source - ");
    580  |               SK_cd_puts(&(qe->condat), CO_get_database());
    581  |               SK_cd_puts(&(qe->condat), "\n");
    582  |               qe->sources_list = g_list_append(qe->sources_list, (void *)CO_get_database());
    583  |               errflg++;
    584  |             }
    585  |             else {
    586  |               qe->sources_list = g_list_append(qe->sources_list, (void *)CO_get_source_database(index));
    587  |             }
    588  |           } /* while () */
    589  |         } /* if () */
    590  |       break;
    591  |
    592  |       case 't':
    593  |         if (my_optarg != NULL) {
    594  |           object_types_str = my_optarg;
    595  |           while (*object_types_str) {
    596  |             index = getsubopt(&object_types_str, DF_get_class_aliases(), &value);
    597  |             if (index == -1) {
    598  |               strcpy(str_buf, "");
    599  |               sprintf(str_buf, "Unknown object encountered.\n");
    600  |               SK_cd_puts(&(qe->condat), str_buf);
    601  |               errflg++;
    602  |             }
    603  |             else {
    604  |               type = DF_get_class_index(index);
    605  |               query_command->t=type;
    606  |             }
    607  |           }
    608  |         }
    609  |       break;
    610  |
    611  |       case 'v':
    612  |         if (my_optarg != NULL) {
    613  |           object_types_str = my_optarg;
    614  |           if (*object_types_str) {
    615  |             index = getsubopt(&object_types_str, DF_get_class_aliases(), &value);
    616  |             if (index == -1) {
    617  |               strcpy(str_buf, "");
    618  |               sprintf(str_buf, "Unknown object encountered.\n");
    619  |               SK_cd_puts(&(qe->condat), str_buf);
    620  |               errflg++;
    621  |             }
    622  |             else {
    623  |               type = DF_get_class_index(index);
    624  |               query_command->v=type;
    625  |             }
    626  |           }
    627  |         }
    628  |       break;
    629  |
    630  |       case 'x':
    631  |         query_command->x=1;
    632  |       break;
    633  |
    634  |       case 'F':
    635  |         query_command->fast=1;
    636  | 	query_command->recursive=0; /* implies no recursion */
    637  |       break;
    638  |
    639  |       case 'K':
    640  |         query_command->filtered=1;
    641  | 	query_command->recursive=0; /* implies no recursion */
    642  |       break;
    643  |
    644  |       case 'L':
    645  |         query_command->L=1;
    646  |       break;
    647  |
    648  |       case 'M':
    649  |         query_command->M=1;
    650  |       break;
    651  |
    652  |       case 'R':
    653  |         query_command->R=1;
    654  |       break;
    655  |
    656  |       case 'S':
    657  |         query_command->S=1;
    658  |       break;
    659  |
    660  |       case 'T':
    661  |         if (my_optarg != NULL) {
    662  |           object_types_str = my_optarg;
    663  |           while (*object_types_str) {
    664  |             index = getsubopt(&object_types_str, DF_get_class_aliases(), &value);
    665  |             if (index == -1) {
    666  |               strcpy(str_buf, "");
    667  |               sprintf(str_buf, "Unknown class encountered.\n");
    668  |               SK_cd_puts(&(qe->condat), str_buf);
    669  |               errflg++;
    670  |             }
    671  |             else {
    672  |               type = DF_get_class_index(index);
    673  |               /* Add the type to the bitmap. */
    674  |               MA_set(&(query_command->object_type_bitmap), type, 1);
    675  |             }
    676  |           }
    677  |         }
    678  |       break;
    679  |
    680  |       case 'V':
    681  |         if (qe->version != NULL) {
    682  |           /* free up the old client info */
    683  |           wr_free(qe->version);
    684  |         }
    685  |
    686  |         {
    687  |           char *token, *cursor = my_optarg;
    688  |           while( (token = strsep( &cursor, "," )) != NULL ) {
    689  |             if(IP_addr_e2b( & (qe->pIP), token)
    690  |                != IP_OK ) {
    691  |               /* means it was not an IP -> it was a version */
    692  |               dieif( wr_malloc( (void **)&(qe->version),
    693  | 				strlen(token)+1) != UT_OK);
    694  |               strcpy(qe->version, token);
    695  |             }
    696  |           }
    697  |         }
    698  |       break;
    699  |
    700  |       case '?':
    701  |         errflg++;
    702  |       break;
    703  |
    704  |       default:
    705  |         errflg++;
    706  |     }
    707  |   }
    708  |
    709  |   /* XXX Report the error.  This could be improved. */
    710  |   /*  if (opt_argv[my_optind] != NULL) { */
    711  |
    712  |   /* this needed improvement, MB */
    713  |   if( my_optind < opt_argc  &&  opt_argv[my_optind] != NULL) {
    714  |     if ( (errflg) || (strncmp(opt_argv[my_optind], "-", 1) == 0) ) {
    715  |       return -1;
    716  |     }
    717  |   }
    718  |   else {
    719  |     if (errflg) {
    720  |       return -1;
    721  |     }
    722  |   }
    723  |
    724  |
    725  |   /* Work out the length of space needed */
    726  |   key_length = 0;
    727  |   for (i=my_optind ; i < opt_argc; i++) {
    728  |     /* length for the string + 1 for the '\0'+ 1 for the ' '
    729  |        [MB removed: + 1 for good luck.] */
    730  |     if (opt_argv[i] != NULL) {
    731  |       key_length += strlen(opt_argv[i])+2;
    732  |     }
    733  |   }
    734  |
    735  |   dieif( wr_calloc((void **)&(query_command->keys), 1, key_length+1) != UT_OK);
    736  |   strcpy(query_command->keys, "");
    737  |   if (errflg == 0) {
    738  |     for (i=my_optind; i < opt_argc; i++) {
    739  |       strcat(query_command->keys, opt_argv[i]);
    740  |       if ( (i + 1) < opt_argc) {
    741  |         strcat(query_command->keys, " ");
    742  |       }
    743  |     }
    744  |   } /* XXX - Be careful about where this brace goes. */
    745  |
    746  |   /* Now convert the key to uppercase. */
    747  |   for (i=0; i <= key_length; i++) {
    748  |     query_command->keys[i] = toupper(query_command->keys[i]);
    749  |   }
    750  |
    751  |   /* Now make the keytypes_bitmap. */
    752  |   query_command->keytypes_bitmap = WK_new(query_command->keys);
    753  |
    754  |   if ( CO_get_comnd_logging() == 1 ) {
    755  |     log_command(tmp_query_str, query_command);
    756  |   }
    757  |
    758  |   /* Now we don't need this anymore */
    759  |   wr_free(tmp_query_str);
    760  |
    761  |   return 0;
    762  |
    763  | } /* QC_fill() */
    764  |
    765  | /* QC_environ_new() */
    766  | /*++++++++++++++++++++++++++++++++++++++
    767  |   Create a new query environment.
    768  |
    769  |   More:
    770  |   +html+ <PRE>
    771  |   Authors:
    772  |         ottrey
    773  |   +html+ </PRE><DL COMPACT>
    774  |   +html+ <DT>Online References:
    775  |   +html+ <DD><UL>
    776  |   +html+ </UL></DL>
    777  |
    778  |   ++++++++++++++++++++++++++++++++++++++*/
    779  | Query_environ *QC_environ_new(char *ip, unsigned sock) {
    780  |   Query_environ *qe;
    781  |
    782  |
    783  |   dieif( wr_calloc((void **)&qe, 1, sizeof(Query_environ)+1 ) != UT_OK);
    784  |   qe->condat.ip = ip;
    785  |   qe->condat.sock = sock;
    786  |
    787  |   /* The source is initialized to be the one defined in the config by default. */
    788  |   qe->sources_list = g_list_append(qe->sources_list, (void *)CO_get_database());
    789  |
    790  |   return qe;
    791  |
    792  | } /* QC_environ_new() */
    793  |
    794  | Query_command *QC_create(char *input, Query_environ *qe)
    795  | {
    796  |   Query_command *qc;
    797  |
    798  |
    799  |   dieif( wr_calloc((void **)&qc, 1, sizeof(Query_command)+1) != UT_OK);
    800  |
    801  |   if ( strlen(input) == 0) {
    802  |     /* An empty query (Ie return) was sent */
    803  |     qc->query_type = QC_EMPTY;
    804  |   }
    805  |   else {        /* else <==> input_length > 0 ) */
    806  |     /* parse query */
    807  |
    808  |     if( QC_fill(input, qc, qe) < 0 ) {
    809  |       qc->query_type = QC_ERROR;
    810  |     }
    811  |     else {
    812  |       /* Update the query environment */
    813  |       /* qe = QC_environ_update(qc, qe); */
    814  |
    815  |       /* Only do a query if there are keys. */
    816  |       if (qc->keys == NULL || strlen(qc->keys) == 0 ) {
    817  | 	if( strlen(qc->keys) == 0
    818  | 	    && ( qc->q != -1 || qc->t != -1 || qc->v != -1 ) ) {
    819  | 	  qc->query_type = QC_TEMPLATE;
    820  | 	}
    821  | 	else {
    822  | 	  qc->query_type = QC_NOKEY;
    823  | 	}
    824  |       }
    825  |       else {
    826  | 	if ( strcmp(qc->keys, "HELP") == 0 ) {
    827  | 	  qc->query_type = QC_HELP;
    828  | 	}
    829  | 	/* So, a real query */
    830  | 	else if( qc->filtered ) {
    831  | 	  qc->query_type = QC_FILTERED;
    832  | 	}
    833  | 	else {
    834  | 	  qc->query_type = QC_REAL;
    835  | 	}
    836  |       }
    837  |     }
    838  |   }
    839  |   return qc;
    840  | }
    841  |
    842  |
    843  | char *QC_get_qrytype(qc_qtype_t qrytype) {
    844  |   dieif(qrytype >= QC_TYPE_MAX);
    845  |
    846  |   return qrytype_str[qrytype];
    847  | }