modules/qc/query_command.c

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

DEFINITIONS

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.58 $
   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     UT_free(qe->version);
 246 
 247     if (qe->sources_list != NULL) {
 248       g_list_free(qe->sources_list); 
 249       qe->sources_list=NULL;
 250     }
 251     UT_free(qe);
 252   }
 253 } /* QC_environ_free() */
 254 
 255 /* QC_free() */
 256 /*++++++++++++++++++++++++++++++++++++++
 257   Free the query_command.
 258 
 259   Query_command *qc query_command to be freed.
 260 
 261   XXX I'm not sure the bitmaps will get freed.
 262   qc->inv_attrs_bitmap
 263   qc->object_type_bitmap
 264   qc->keytypes_bitmap
 265 
 266   More:
 267   +html+ <PRE>
 268   Authors:
 269         ottrey
 270   +html+ </PRE><DL COMPACT>
 271   +html+ <DT>Online References:
 272   +html+ <DD><UL>
 273   +html+ </UL></DL>
 274 
 275   ++++++++++++++++++++++++++++++++++++++*/
 276 void QC_free(Query_command *qc) {
     /* [<][>][^][v][top][bottom][index][help] */
 277   if (qc != NULL) {
 278     if (qc->keys != NULL) {
 279       UT_free(qc->keys);
 280     }
 281     UT_free(qc);
 282   }
 283 } /* QC_free() */
 284 
 285 
 286 
 287 /* QC_fill() */
 288 /*++++++++++++++++++++++++++++++++++++++
 289   Create a new query_command.
 290   Returns 0 when OK, -1 when query incorrect.
 291   
 292   char *query_str The garden variety whois query string.
 293 
 294   Query_environ *qe the environment
 295 
 296   More:
 297   +html+ <PRE>
 298   Authors:
 299         ottrey - original code
 300         marek - modified for my getopts, multiple sources;
 301                 and generally cleaned.
 302   +html+ </PRE><DL COMPACT>
 303   +html+ <DT>Online References:
 304   +html+ <DD><UL>
 305   +html+ </UL></DL>
 306 
 307   ++++++++++++++++++++++++++++++++++++++*/
 308 static
 309 int QC_fill(char *query_str, 
     /* [<][>][^][v][top][bottom][index][help] */
 310              Query_command *query_command,
 311              Query_environ *qe) {
 312   
 313   int c;
 314   int synerrflg = 0;
 315   int badparerr = 0;
 316   int minusk = 0;
 317   char *inv_attrs_str = NULL;
 318   char *object_types_str = NULL;
 319   int opt_argc;
 320   gchar **opt_argv;
 321   char *value;
 322 /*  char *tmp_query_str;*/
 323   unsigned key_length;
 324   int i;
 325   int index;
 326   C_Type_t type;
 327   A_Type_t attr;
 328   getopt_state_t *gst = NULL;
 329 
 330   query_command->c_irt_search = FALSE;
 331   query_command->d = 0;
 332   query_command->e = 0;
 333   query_command->g = 0;
 334   query_command->inv_attrs_bitmap = MA_new(MA_END);
 335   query_command->recursive = 1;  /* Recursion is on by default. */
 336   query_command->l = 0;
 337   query_command->m = 0;
 338   query_command->q = -1;
 339   query_command->t = -1;
 340   query_command->v = -1;
 341   query_command->x = 0;
 342   query_command->fast = 0;
 343   query_command->filtered = 0;
 344   query_command->L = 0;
 345   query_command->M = 0;
 346   query_command->R = 0;
 347   query_command->S = 0;
 348 
 349   /* XXX UGLY - "all zeros" in object_type_bitmap means the same as 
 350      "all ones". To limit the inconsistency, this is changed at the end 
 351      of this function, so outside "all zeros" is an illegal value. */
 352   query_command->object_type_bitmap = MA_new(MA_END);
 353   /*
 354   query_command->keytypes_bitmap = MA_new(MA_END);
 355   */
 356   query_command->keys = NULL;
 357 
 358   /* This is so Marek can't crash me :-) */
 359   /* Side Effect - query keys are subsequently cut short to STR_S size. */
 360 
 361 /*  tmp_query_str = (char *)UT_calloc(1, STR_S+1);
 362   strncpy(tmp_query_str, query_str, STR_S);*/
 363 
 364   /* Create the arguments. */
 365   /* This allows only a maximum of MAX_OPT_ARG_C words in the query. */
 366 /*  opt_argv = g_strsplit(tmp_query_str, " ", MAX_OPT_ARG_C);*/
 367   opt_argv = g_strsplit(query_str, " ", MAX_OPT_ARG_C);
 368 
 369   /* Determine the number of arguments. */
 370   for (opt_argc=0; opt_argv[opt_argc] != NULL; opt_argc++);
 371 
 372   dieif( (gst = mg_new(0)) == NULL );
 373   
 374   while ((c = mg_getopt(opt_argc, opt_argv, "acdegi:klrmq:s:t:v:xFKLMRST:V:", 
 375                         gst)) != EOF) {
 376     switch (c) {
 377       case 'a':
 378         /* Remove any user specified sources from the sources list. */
 379         /* free the list only, do not touch the elements */
 380         g_list_free(qe->sources_list); 
 381         qe->sources_list=NULL;
 382 
 383         /* Add all the config sources to the sources list. */
 384         {
 385           int i;
 386           ca_dbSource_t *hdl;
 387           
 388           for (i=0; (hdl = ca_get_SourceHandleByPosition(i)) != NULL; i++) {
 389             qe->sources_list = g_list_append(qe->sources_list, (void *)hdl);
 390           }
 391         }
 392 
 393 
 394       break;
 395 
 396       case 'c':
 397         query_command->c_irt_search = TRUE;
 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           /* 
 418              Now a really stupid hard-coded hack to support "pn" being a
 419              synonym for "ac,tc,zc,ah".  I particularly object to this because
 420              it references attributes that should only be defined in XML - but
 421              I don't see a simplier more robust way of doing this hack.
 422              :-( - ottrey 8/12/99 
 423 
 424              ** removed a memory leak - MB, 1/08/00
 425 
 426              ** removed the use of "ro", added "person" - shane, 2002-01-23
 427 
 428              */
 429           if (   strcmp(inv_attrs_str, "pn") == 0 
 430               || strcmp(inv_attrs_str, "person") == 0) {
 431             hackstr = UT_strdup("ac,tc,zc,ah,cn");
 432             inv_attrs_str = hackstr;
 433           }
 434           while (*inv_attrs_str) {
 435             index = getsubopt(&inv_attrs_str, DF_get_attribute_aliases(), &value);
 436             if (index == -1) {
 437               /* Unknown attribute encountered. */
 438               char *rep = ca_get_qc_badattr ;
 439               SK_cd_puts(&(qe->condat), rep);
 440               UT_free(rep);
 441 
 442               attr = -1;
 443               badparerr++;
 444             }
 445             else {
 446               mask_t inv_attr_mask = MA_new(INV_ATTR_MASK);
 447               attr = DF_get_attribute_index(index);
 448               if ( MA_isset(inv_attr_mask, attr) == 1 ) {
 449                 /* Add the attr to the bitmap. */
 450                 MA_set(&(query_command->inv_attrs_bitmap), attr, 1);
 451               }
 452               else {
 453                 /* "%s" is not an inverse searchable attribute. */
 454                 char *rep = ca_get_qc_fmt_attrnotinv ;
 455                 SK_cd_printf(&(qe->condat), rep, 
 456                     (DF_get_attribute_aliases())[index]);
 457                 UT_free(rep);
 458                 badparerr++;
 459               }
 460             } 
 461           } /* while () */
 462 
 463           if( hackstr != NULL) {
 464             UT_free(hackstr);
 465           }
 466         } /* if () */
 467       break;
 468 
 469       case 'k':
 470         minusk = 1;
 471       break;
 472 
 473       case 'r':
 474         query_command->recursive=0;       /* Unset recursion */
 475       break;
 476 
 477       case 'l':
 478         query_command->l=1;
 479       break;
 480 
 481       case 'm':
 482         query_command->m=1;
 483       break;
 484 
 485       case 'q':
 486         if (gst->optarg != NULL) {
 487           index = getsubopt(&gst->optarg, DF_get_server_queries(), &value);
 488           if (index == -1) {
 489             synerrflg++;
 490           }
 491           else {
 492             query_command->q = index;
 493           } 
 494         } /* if () */
 495       break;
 496 
 497       case 's':
 498         if (gst->optarg != NULL) {
 499           char *token, *cursor = gst->optarg;
 500           ca_dbSource_t *handle;
 501           
 502           /* Remove any sources from the sources list. */
 503           g_list_free(qe->sources_list); 
 504           qe->sources_list=NULL;
 505           
 506           /* go through specified sources */
 507           while( (token = strsep( &cursor, "," )) != NULL ) {
 508             
 509             if( (handle = ca_get_SourceHandleByName(token)) != NULL ) {
 510               /* append */
 511               qe->sources_list 
 512                 = g_list_append(qe->sources_list, (void *) handle );
 513             }
 514             else {
 515               /* bail out */
 516               
 517               /* Unknown source %s requested. */
 518               char *rep = ca_get_qc_fmt_badsource ;
 519               SK_cd_printf(&(qe->condat), rep, token ); 
 520               UT_free(rep);
 521               
 522               /* XXX error */
 523               badparerr++;
 524               
 525             } /* if handle not null */
 526           } /* while sources */
 527         } /* if argument present */
 528         break;
 529         
 530       case 't':
 531         if (gst->optarg != NULL) {
 532           object_types_str = gst->optarg;
 533           while (*object_types_str) {
 534             index = getsubopt(&object_types_str, DF_get_class_aliases(), &value);
 535             if (index == -1) {
 536               /* Unknown object type encountered */
 537               char *rep = ca_get_qc_badobjtype ;
 538               SK_cd_puts(&(qe->condat), rep);
 539               UT_free(rep);
 540               badparerr++;
 541             }
 542             else {
 543               type = DF_get_class_index(index);
 544               query_command->t=type;
 545             }
 546           }
 547         }
 548       break;
 549 
 550       case 'v':
 551         if (gst->optarg != NULL) {
 552           object_types_str = gst->optarg;
 553           if (*object_types_str) {
 554             index = getsubopt(&object_types_str, DF_get_class_aliases(), &value);
 555             if (index == -1) {
 556               /* Unknown object type encountered */
 557               char *rep = ca_get_qc_badobjtype ;
 558               SK_cd_puts(&(qe->condat), rep);
 559               UT_free(rep);
 560               badparerr++;
 561             }
 562             else {
 563               type = DF_get_class_index(index);
 564               query_command->v=type;
 565             }
 566           }
 567         }
 568       break;
 569 
 570       case 'x':
 571         query_command->x=1;
 572       break;
 573 
 574       case 'F':
 575         query_command->fast=1;
 576         query_command->recursive=0; /* implies no recursion */
 577       break;
 578 
 579       case 'K':
 580         query_command->filtered=1;
 581         query_command->recursive=0; /* implies no recursion */
 582       break;
 583 
 584       case 'L':
 585         query_command->L=1;
 586       break;
 587 
 588       case 'M':
 589         query_command->M=1;
 590       break;
 591 
 592       case 'R':
 593         query_command->R=1;
 594       break;
 595 
 596       case 'S':
 597         query_command->S=1;
 598       break;
 599 
 600       case 'T':
 601         if (gst->optarg != NULL) {
 602           /* parse the specification */
 603           object_types_str = gst->optarg;
 604           while (*object_types_str) {
 605             index = getsubopt(&object_types_str, DF_get_class_aliases(), &value);
 606             if (index == -1) {
 607               /* Unknown object type encountered */
 608               char *rep = ca_get_qc_badobjtype ;
 609               SK_cd_puts(&(qe->condat), rep);
 610               UT_free(rep);
 611               badparerr++;
 612             }
 613             else {
 614               type = DF_get_class_index(index);
 615               /* Add the type to the bitmap. */
 616               MA_set(&(query_command->object_type_bitmap), (unsigned) type, 1);
 617             }
 618           }
 619         }
 620       break;
 621 
 622       case 'V':
 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               UT_free(qe->version);
 630               qe->version = UT_strdup(token);
 631             }
 632           }
 633         }
 634       break;
 635 
 636       /* any other flag, including '?' and ':' errors */
 637       default:
 638         synerrflg++;
 639     }
 640   }
 641 
 642   /* copy the key */
 643 
 644   /* Work out the length of space needed */
 645   key_length = 1; /* for terminal '\0' */
 646   for (i=gst->optind ; i < opt_argc; i++) {
 647     /* length for the string + 1 for the '\0'+ 1 for the ' ' */
 648     if (opt_argv[i] != NULL) {
 649       key_length += strlen(opt_argv[i])+1;
 650     }
 651   }
 652   /* allocate */
 653   query_command->keys = (char *)UT_calloc(1, key_length+1);
 654 
 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     log_command(query_str, query_command);
 694 
 695     /* "keep connection" processing:
 696        when opening connection, -k may be alone or with a query
 697        later -k must appear alone (or there must be an empty line,
 698        or an error) for the connection to close.
 699     */
 700     if( minusk ) {
 701       if( qe->k == 0 ) { /* opening */ 
 702         qe->k = 1;
 703       }
 704       else { /* closing, if no key; otherwise keep open */
 705         if( key_length <= 1 ) {
 706           qe->k = 0;
 707         }
 708       }
 709     }
 710     
 711   } /* if no error */
 712 
 713   /* we don't need this anymore */
 714 /*  UT_free(tmp_query_str);*/
 715   UT_free(gst);
 716   g_strfreev(opt_argv);
 717 
 718   if(synerrflg > 0) { /* severe syntax error. Usage must be printed */
 719     return QC_SYNERR;
 720   }
 721   else if(badparerr > 0) { /* the requester has a clue. No Usage info */
 722     return QC_PARERR;
 723   }
 724   else {
 725     return 0;
 726   }
 727 } /* QC_fill() */
 728 
 729 /* QC_environ_new() */
 730 /*++++++++++++++++++++++++++++++++++++++
 731   Create a new query environment.
 732 
 733   More:
 734   +html+ <PRE>
 735   Authors:
 736         ottrey
 737   +html+ </PRE><DL COMPACT>
 738   +html+ <DT>Online References:
 739   +html+ <DD><UL>
 740   +html+ </UL></DL>
 741 
 742   ++++++++++++++++++++++++++++++++++++++*/
 743 Query_environ *QC_environ_new(char *ip, int sock) {
     /* [<][>][^][v][top][bottom][index][help] */
 744   Query_environ *qe;
 745 
 746   qe = (Query_environ *)UT_calloc(1, sizeof(Query_environ));
 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       UT_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)
     /* [<][>][^][v][top][bottom][index][help] */
 788 {
 789   Query_command *qc;
 790   /* allocate place for a copy of the input */
 791   char *copy = UT_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   for(ci = (unsigned char *)input; *ci != 0 && isspace(*ci); ci++) {
 801     /* EMPTY */
 802   }
 803 
 804   for(co = (unsigned char *) copy; *ci != 0; ci++) {
 805     if( strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ"     /* only those are allowed */
 806                "abcdefghijklmnopqrstuvwxyz"
 807                "0123456789-_:+=.,@/?' \n", *ci) != NULL) {
 808       *(co++) = *ci;
 809     }
 810   }
 811 
 812   /* now delete whitespace chars at the end */
 813   while( co != (unsigned char *)copy /* don't read past the beginning */
 814          && isspace(*co) ) {
 815     *co = '\0';
 816     co--;
 817   }
 818 
 819 
 820   qc = (Query_command *)UT_calloc(1, sizeof(Query_command));
 821   
 822   if ( strlen(copy) == 0) {
 823     /* An empty query (Ie return) was sent */
 824     qc->query_type = QC_EMPTY;
 825   } 
 826   else {        /* else <==> input_length > 0 ) */
 827     /* parse query */
 828     qt = QC_fill(copy, qc, qe);
 829 
 830     if( qt == QC_SYNERR || qt == QC_PARERR ) {
 831       qc->query_type = qt;
 832     }
 833     else {
 834       /* Update the query environment */
 835       /* qe = QC_environ_update(qc, qe); */
 836 
 837       /* Only do a query if there are keys. */
 838       if (qc->keys == NULL || strlen(qc->keys) == 0 ) {
 839         if( strlen(qc->keys) == 0 
 840             && ( qc->q != -1 || qc->t != -1 || qc->v != -1 ) ) {
 841           qc->query_type = QC_TEMPLATE;
 842         }
 843         else {
 844           qc->query_type = QC_NOKEY;
 845         }
 846       }
 847       else {
 848         if ( strcmp(qc->keys, "HELP") == 0 ) {
 849           qc->query_type = QC_HELP;
 850         }
 851         /* So, a real query */
 852         else if( qc->filtered ) {
 853           qc->query_type = QC_FILTERED;
 854         }
 855         else {
 856           qc->query_type = QC_REAL;
 857         }
 858       }
 859     }
 860   }
 861 
 862   UT_free(copy);
 863 
 864   return qc;
 865 }
 866 
 867 
 868 /*++++++++++++++++++++++++++++++++++++++
 869 
 870   Get the name of the given query type code.
 871 
 872   char *QC_get_qrytype   returns a pointer to an element of array of static strings
 873 
 874   qc_qtype_t qrytype     query type code
 875 
 876   ++++++++++++++++++++++++++++++++++++++*/
 877 
 878 char *QC_get_qrytype(qc_qtype_t qrytype) {
     /* [<][>][^][v][top][bottom][index][help] */
 879   dieif(qrytype >= QC_TYPE_MAX);
 880 
 881   return qrytype_str[qrytype];
 882 }

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