modules/qc/query_command.c

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

FUNCTIONS

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

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

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