## 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] */