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

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