modules/qc/query_command.c

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

FUNCTIONS

This source file includes following functions.
  1. strsep
  2. my_getopt
  3. QC_environ_to_string
  4. QC_query_command_to_string
  5. log_command
  6. QC_environ_free
  7. QC_free
  8. QC_fill
  9. QC_environ_new
  10. QC_create
  11. QC_get_qrytype

   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)
     /* [<][>][^][v][top][bottom][index][help] */
  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) {
     /* [<][>][^][v][top][bottom][index][help] */
 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) {
     /* [<][>][^][v][top][bottom][index][help] */
 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) {
     /* [<][>][^][v][top][bottom][index][help] */
 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) {
     /* [<][>][^][v][top][bottom][index][help] */
 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) {
     /* [<][>][^][v][top][bottom][index][help] */
 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) {
     /* [<][>][^][v][top][bottom][index][help] */
 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, 
     /* [<][>][^][v][top][bottom][index][help] */
 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) {
     /* [<][>][^][v][top][bottom][index][help] */
 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)
     /* [<][>][^][v][top][bottom][index][help] */
 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) {
     /* [<][>][^][v][top][bottom][index][help] */
 844   dieif(qrytype >= QC_TYPE_MAX);
 845 
 846   return qrytype_str[qrytype];
 847 }

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