1    | /***************************************
2    |   $Revision: 1.22 $
3    | 
4    |   Query command module (qc).  This is what the whois query gets stored as in
5    |   memory.
6    | 
7    |   Status: NOT REVUED, NOT TESTED
8    | 
9    |   ******************/ /******************
10   |   Filename            : query_command.c
11   |   Author              : ottrey@ripe.net
12   |   OSs Tested          : Solaris
13   |   To Do               : Write some kind of options parser (to check for valid
14   |                         combinations of options.)
15   |   Comments            :
16   |   ******************/ /******************
17   |   Copyright (c) 1999                              RIPE NCC
18   |  
19   |   All Rights Reserved
20   |   
21   |   Permission to use, copy, modify, and distribute this software and its
22   |   documentation for any purpose and without fee is hereby granted,
23   |   provided that the above copyright notice appear in all copies and that
24   |   both that copyright notice and this permission notice appear in
25   |   supporting documentation, and that the name of the author not be
26   |   used in advertising or publicity pertaining to distribution of the
27   |   software without specific, written prior permission.
28   |   
29   |   THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
30   |   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
31   |   AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
32   |   DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
33   |   AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
34   |   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
35   |   ***************************************/
36   | #include <stdlib.h>
37   | #include <stdio.h>
38   | #include <string.h>
39   | #include <ctype.h>
40   | 
41   | #include "query_command.h"
42   | #include "defs.h"
43   | #include "constants.h"
44   | #include "which_keytypes.h"
45   | #include "memwrap.h"
46   | 
47   | #define MAX_OPT_ARG_C 20
48   | 
49   | /*+ String sizes +*/
50   | #define STR_S   63
51   | #define STR_M   255
52   | #define STR_L   1023
53   | #define STR_XL  4095
54   | #define STR_XXL 16383
55   | 
56   | /* XXX These probably wont get used.  I'm using a switch statement instead.  -ottrey 5/7/99 */
57   | /*
58   | mask_t Inv_attr_mask;
59   | mask_t Object_mask;
60   | */
61   | 
62   | #ifdef HAVE_STRSEP
63   | /* good */
64   | #else 
65   | #  if defined(HAVE_STRTOK_R) && !defined(HAVE_STRSEP)
66   | /* emulate strsep with strtok_r 
67   |    by making first arg to strtok_r point to the last 
68   | */
69   | char *
70   | strsep(char **stringp, const char *delim)
71   | {
72   |   return strtok_r( *stringp, delim, stringp);
73   | }
74   | #  else
75   | #  error "must have strsep or strtok_r"
76   | #  endif
77   | #endif
78   | 
79   | 
80   | /* my_getopt() */
81   | /*++++++++++++++++++++++++++++++++++++++
82   |   A thread safe version of getopt, used to get the options from the whois
83   |   query.
84   | 
85   |   int opt_argc The number of query arguments.
86   |   
87   |   char **opt_argv The query arguments.
88   |   
89   |   char *optstring The string containing valid options.
90   |   
91   |   int *my_optind_ptr A pointer to the index into the options of the option
92   |   returned.
93   |   
94   |   char **my_optarg_ptr A pointer to the arguments to be returned.
95   |    
96   |   More:
97   |   +html+ <PRE>
98   |   Authors:
99   |         ottrey
100  |   +html+ </PRE><DL COMPACT>
101  |   +html+ <DT>Online References:
102  |   +html+ <DD><UL>
103  |   +html+     <LI>man getopt
104  |   +html+ </UL></DL>
105  | 
106  |   ++++++++++++++++++++++++++++++++++++++*/
107  | static int my_getopt(int opt_argc, char **opt_argv, char *optstring, int *my_optind_ptr, char **my_optarg_ptr) {
108  |   int c='?';
109  |   int i, j;
110  |   int no_options;
111  |   int optind = *my_optind_ptr;
112  |   char option[3];
113  |   int option_matched=0;
114  |   
115  |   /* Get the number of options in the option string */
116  |   for(i=0, no_options=0; i < strlen(optstring) ; i++) {
117  |     if (optstring[i] != ':') {
118  |       no_options++;
119  |     }
120  |   }
121  | 
122  |   /* Iterate through all the option until it matches the current opt_argv */
123  |   /* Ie. opt_argv[optind] */
124  |   for (i=0, j=0; i <= no_options; i++, j++) {
125  |     /* Construct one option from the optstring */
126  |     option[0] = '-';
127  |     if (optstring[j] == ':') {
128  |       j++;
129  |     }
130  |     option[1] = optstring[j];
131  |     if ( optstring[j+1] == ':' ) {
132  |       option[2] = ':';
133  |     }
134  |     else {
135  |       option[2] = '\0';
136  |     }
137  |     option[3] = '\0';
138  | 
139  |     if (optind < opt_argc) {
140  |       if (strlen(opt_argv[optind]) > 0) {
141  |         /*
142  |         printf("opt_argv[%d] == option <==> %s == %s\n", optind, opt_argv[optind], option);
143  |         */
144  |         if (strncmp(opt_argv[optind], option, 2) == 0) {
145  |           /* Does the option have arguments. */
146  |           if (option[2] == ':') {
147  |             /* If the option has arguments */
148  |             if (strlen(opt_argv[optind]) > 2) {
149  |               /* If the arguments are in this token */
150  |               *my_optarg_ptr = (opt_argv[optind])+2;
151  |             }
152  |             else {
153  |               /* If the arguments are in the next token */
154  |               *my_optarg_ptr = opt_argv[optind+1];
155  |               optind++;
156  |             }
157  |           }
158  |           else {
159  |             /* There are no arguments to this token */
160  |             *my_optarg_ptr = NULL;
161  |           }
162  |           /* Option matched - break out of the search */
163  |           option_matched = 1;
164  |           break;
165  |         }
166  |       }
167  |     }
168  |   } /* for() */
169  |   
170  |   if ( option_matched == 1 ) {
171  |     /* This option was matched, return it. */
172  |     c = option[1];
173  | 
174  |     /* Move to the next opt_argv */
175  |     optind++;
176  |     *my_optind_ptr = optind;
177  |   }
178  |   else {
179  |     /* Discontinue search */
180  |     c = EOF;
181  |   }
182  | 
183  |   return c;
184  | 
185  | } /* my_getopt() */
186  | 
187  | /* QC_environ_to_string() */
188  | /*++++++++++++++++++++++++++++++++++++++
189  |   Convert the query_environ to a string.
190  | 
191  |   Query_environ *query_environ The query_environ to be converted.
192  |    
193  |   More:
194  |   +html+ <PRE>
195  |   Authors:
196  |         ottrey
197  |   +html+ </PRE><DL COMPACT>
198  |   +html+ <DT>Online References:
199  |   +html+ <DD><UL>
200  |   +html+ </UL></DL>
201  | 
202  |   ++++++++++++++++++++++++++++++++++++++*/
203  | char *QC_environ_to_string(Query_environ qe) {
204  |   char *result;
205  |   char *str1;
206  |   char str2[IP_ADDRSTR_MAX];
207  |   char result_buf[STR_XL];
208  | 
209  |   str1 = DF_sources_list_to_string(qe.sources_list);
210  |   
211  |   if( IP_addr_b2a( &(qe.pIP), str2, IP_ADDRSTR_MAX) != IP_OK ) { 
212  |     *str2 = '\0';
213  |   }
214  |   
215  |   sprintf(result_buf, "host=%s, keep_connection=%s, sources=%s, version=%s%s%s", qe.condat.ip, 
216  |           qe.k?"on":"off", 
217  |           str1, 
218  |           (qe.version == NULL) ? "?" : qe.version,
219  |           *str2 == '\0' ? "" : ", passedIP=",
220  |           *str2 == '\0' ? "" : str2
221  |           );
222  |   
223  |   wr_free(str1);
224  | 
225  |   //result = (char *)calloc(1, strlen(result_buf)+1);
226  |   dieif( wr_malloc((void **)&result, strlen(result_buf)+1) != UT_OK);  
227  | 
228  |   strcpy(result, result_buf);
229  |   
230  |   return result;
231  |   
232  | } /* QC_environ_to_string() */
233  | 
234  | /* QC_query_command_to_string() */
235  | /*++++++++++++++++++++++++++++++++++++++
236  |   Convert the query_command to a string.
237  | 
238  |   Query_command *query_command The query_command to be converted.
239  |    
240  |   More:
241  |   +html+ <PRE>
242  |   Authors:
243  |         ottrey
244  |   +html+ </PRE><DL COMPACT>
245  |   +html+ <DT>Online References:
246  |   +html+ <DD><UL>
247  |   +html+ </UL></DL>
248  | 
249  |   ++++++++++++++++++++++++++++++++++++++*/
250  | char *QC_query_command_to_string(Query_command *query_command) {
251  |   char *result;
252  |   char result_buf[STR_XL];
253  |   char *str1;
254  |   char *str2;
255  |   char *str3;
256  | 
257  |   str1 = MA_to_string(query_command->inv_attrs_bitmap, DF_get_attribute_names());
258  |   str2 = MA_to_string(query_command->object_type_bitmap, DF_get_class_names());
259  |   str3 = WK_to_string(query_command->keytypes_bitmap);
260  |   
261  |   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]\n",
262  |           str1,
263  | 	  query_command->recursive?"y":"n",
264  |           str2,
265  |           query_command->e,
266  |           query_command->g,
267  |           query_command->l,
268  |           query_command->m,
269  |           query_command->q,
270  |           query_command->t,
271  |           query_command->v,
272  |           query_command->x,
273  |           query_command->fast,
274  |           query_command->filtered,
275  |           query_command->L,
276  |           query_command->M,
277  |           query_command->R,
278  |           query_command->S,
279  |           str3,
280  |           query_command->keys);
281  |   wr_free(str1);
282  |   wr_free(str2);
283  |   wr_free(str3);
284  | 
285  |   //  result = (char *)calloc(1, strlen(result_buf)+1);
286  |   dieif( wr_malloc((void **)&result, strlen(result_buf)+1) != UT_OK);  
287  |   strcpy(result, result_buf);
288  | 
289  |   return result;
290  |   
291  | } /* QC_query_command_to_string() */
292  | 
293  | /* log_command() */
294  | /*++++++++++++++++++++++++++++++++++++++
295  |   Log the command.
296  |   This is more to do with Tracing.  And should/will get merged with a tracing
297  |   module (when it is finalized.)
298  | 
299  |   char *query_str
300  |   
301  |   Query_command *query_command
302  |    
303  |   More:
304  |   +html+ <PRE>
305  |   Authors:
306  |         ottrey
307  |   +html+ </PRE><DL COMPACT>
308  |   +html+ <DT>Online References:
309  |   +html+ <DD><UL>
310  |   +html+ </UL></DL>
311  | 
312  |   ++++++++++++++++++++++++++++++++++++++*/
313  | static void log_command(char *query_str, Query_command *query_command) {
314  |   FILE *logf;
315  |   char *str;
316  | 
317  |   if (CO_get_comnd_logging() == 1) {
318  |     str = QC_query_command_to_string(query_command);
319  |     if (strcmp(CO_get_comnd_logfile(), "stdout") == 0) {
320  |       printf("query=[%s]\n%s", query_str, str);
321  |     }
322  |     else {
323  |       logf = fopen(CO_get_comnd_logfile(), "a");
324  |       fprintf(logf, "query=[%s]\n%s", query_str, str);
325  |       fclose(logf);
326  |     }
327  |     wr_free(str);
328  |   }
329  | 
330  | } /* log_command() */
331  | 
332  | /* QC_environ_free() */
333  | /*++++++++++++++++++++++++++++++++++++++
334  |   Free the query_environ.
335  | 
336  |   Query_command *qc query_environ to be freed.
337  | 
338  |   More:
339  |   +html+ <PRE>
340  |   Authors:
341  |         ottrey
342  |   +html+ </PRE><DL COMPACT>
343  |   +html+ <DT>Online References:
344  |   +html+ <DD><UL>
345  |   +html+ </UL></DL>
346  | 
347  |   ++++++++++++++++++++++++++++++++++++++*/
348  | void QC_environ_free(Query_environ *qe) {
349  |   if (qe != NULL) {
350  |     if (qe->sources_list != NULL) {
351  |       g_list_free(qe->sources_list);
352  |     }
353  |     wr_free(qe);
354  |   }
355  | } /* QC_environ_free() */
356  | 
357  | /* QC_free() */
358  | /*++++++++++++++++++++++++++++++++++++++
359  |   Free the query_command.
360  | 
361  |   Query_command *qc query_command to be freed.
362  | 
363  |   XXX I'm not sure the bitmaps will get freed.
364  |   qc->inv_attrs_bitmap
365  |   qc->object_type_bitmap
366  |   qc->keytypes_bitmap
367  | 
368  |   More:
369  |   +html+ <PRE>
370  |   Authors:
371  |         ottrey
372  |   +html+ </PRE><DL COMPACT>
373  |   +html+ <DT>Online References:
374  |   +html+ <DD><UL>
375  |   +html+ </UL></DL>
376  | 
377  |   ++++++++++++++++++++++++++++++++++++++*/
378  | void QC_free(Query_command *qc) {
379  |   if (qc != NULL) {
380  |     if (qc->keys != NULL) {
381  |       wr_free(qc->keys);
382  |     }
383  |     wr_free(qc);
384  |   }
385  | } /* QC_free() */
386  | 
387  | 
388  | 
389  | /* QC_fill() */
390  | /*++++++++++++++++++++++++++++++++++++++
391  |   Create a new query_command.
392  | 
393  |   char *query_str The garden variety whois query string.
394  | 
395  |   Query_environ *qe the environment
396  | 
397  |   Pre-condition: 
398  | 
399  |   More:
400  |   +html+ <PRE>
401  |   Authors:
402  |         ottrey
403  |   +html+ </PRE><DL COMPACT>
404  |   +html+ <DT>Online References:
405  |   +html+ <DD><UL>
406  |   +html+ </UL></DL>
407  | 
408  |   ++++++++++++++++++++++++++++++++++++++*/
409  | static
410  | void QC_fill(char *query_str, 
411  | 	     Query_command *query_command,
412  | 	     Query_environ *qe) {
413  |   char *my_optarg;
414  |   int my_optind = 0;
415  |   int c;
416  |   int errflg = 0;
417  |   char *inv_attrs_str = NULL;
418  |   char *object_types_str = NULL;
419  |   char *sources_str = NULL;
420  |   int opt_argc;
421  |   gchar **opt_argv;
422  |   char *value;
423  |   char *tmp_query_str;
424  |   int key_length;
425  |   int i;
426  |   int index;
427  |   int type;
428  |   int attr;
429  | 
430  |   char str_buf[STR_XL];
431  | 
432  |   GList *first_source;
433  | 
434  |   query_command->e = 0;
435  |   query_command->g = 0;
436  |   query_command->inv_attrs_bitmap = MA_new(MA_END);
437  |   query_command->recursive = 1;  /* Recursion is on by default. */
438  |   query_command->l = 0;
439  |   query_command->m = 0;
440  |   query_command->q = 0;
441  |   query_command->t = 0;
442  |   query_command->v = 0;
443  |   query_command->x = 0;
444  |   query_command->fast = 0;
445  |   query_command->filtered = 0;
446  |   query_command->L = 0;
447  |   query_command->M = 0;
448  |   query_command->R = 0;
449  |   query_command->S = 0;
450  |   query_command->object_type_bitmap = MA_new(MA_END);
451  |   /*
452  |   query_command->keytypes_bitmap = MA_new(MA_END);
453  |   */
454  |   query_command->keys = NULL;
455  | 
456  |   /* This is so Marek can't crash me :-) */
457  |   /* Side Effect - query keys are subsequently cut short to STR_S size. */
458  |   //tmp_query_str = (char *)calloc(1, STR_S+1);
459  |   dieif( wr_calloc((void **)&tmp_query_str, 1, STR_S+1) != UT_OK);  
460  |   strncpy(tmp_query_str, query_str, STR_S);
461  | 
462  |   /* Create the arguments. */
463  |   /* This allows only a maximum of MAX_OPT_ARG_C words in the query. */
464  |   opt_argv = g_strsplit(tmp_query_str, " ", MAX_OPT_ARG_C);
465  | 
466  |   /* Determine the number of arguments. */
467  |   for (opt_argc=0; opt_argv[opt_argc] != NULL; opt_argc++);
468  | 
469  |   while ((c = my_getopt(opt_argc, opt_argv, "aegi:klrmq:s:t:v:xFKLMRST:V:", &my_optind, &my_optarg)) != EOF) {
470  |     switch (c) {
471  |       case 'a':
472  |         /* Remove any user specified sources from the sources list. */
473  |         while ((first_source = g_list_first(qe->sources_list)) != NULL) {
474  |           qe->sources_list = g_list_remove(qe->sources_list, first_source->data);
475  |         }
476  |         /* Add all the config sources to the sources list. */
477  |         for (i=0; DF_get_source(i) != NULL; i++) {
478  |           qe->sources_list = g_list_append(qe->sources_list, (void *)DF_get_database(i));
479  |         }
480  |       break;
481  | 
482  |       case 'e':
483  |         query_command->e=1;
484  |       break;
485  | 
486  |       case 'g':
487  |         query_command->g=1;
488  |       break;
489  | 
490  |       case 'i':
491  |         if (my_optarg != NULL) {
492  |           inv_attrs_str = my_optarg;
493  |           /* Now a really stupid hard-coded hack to support "pn" being a synonym for "ac,tc,zc,ah" */
494  |           /* I particularly object to this because it references attributes that should only be 
495  |              defined in XML - but I don't see a simplier more robust way of doing this hack.
496  |              :-( - ottrey 8/12/99 */
497  |           if (strcmp(inv_attrs_str, "pn") == 0) {
498  |             //inv_attrs_str = (char *)malloc(12);
499  | 	    dieif( wr_malloc((void **)&inv_attrs_str, 12) != UT_OK);  
500  |             strcpy(inv_attrs_str, "ac,tc,zc,ah");
501  |           }
502  |           else if (strcmp(inv_attrs_str, "ro") == 0) {
503  |             //inv_attrs_str = (char *)malloc(12);
504  | 	    dieif( wr_malloc((void **)&inv_attrs_str, 12) != UT_OK); 
505  |             strcpy(inv_attrs_str, "ac,tc,zc,ah");
506  |           }
507  |           while (*inv_attrs_str) {
508  |             index = getsubopt(&inv_attrs_str, DF_get_attribute_aliases(), &value);
509  |             if (index == -1) {
510  |               attr = -1;
511  |               strcpy(str_buf, "");
512  |               sprintf(str_buf, "Unknown attribute encountered.\n"); 
513  |               SK_cd_puts(&(qe->condat), str_buf);
514  |               errflg++;
515  |             }
516  |             else {
517  |               mask_t inv_attr_mask = MA_new(INV_ATTR_MASK);
518  |               attr = DF_get_attribute_index(index);
519  |               if ( MA_isset(inv_attr_mask, attr) == 1 ) {
520  |                 /* Add the attr to the bitmap. */
521  |                 MA_set(&(query_command->inv_attrs_bitmap), attr, 1);
522  |               }
523  |               else {
524  |                 strcpy(str_buf, "");
525  |                 sprintf(str_buf, "\"%s\" does not belong to inv_attr.\n", (DF_get_attribute_aliases())[index]); 
526  |                 SK_cd_puts(&(qe->condat), str_buf);
527  |                 errflg++;
528  |               }
529  |               /*
530  |               MA_free(&inv_attr_mask);
531  |               */
532  |             } 
533  |           } /* while () */
534  |         } /* if () */
535  |       break;
536  | 
537  |       case 'k':
538  |         /* This is a tricky XOR operation....  ;-)
539  |            State transition for k_flag:
540  |            0 -> 0 then k flag = 0, connected = 0
541  |            0 -> 1 then k flag = 1, connected = 1
542  |            1 -> 0 then k flag = 1, connected = 1
543  |            1 -> 1 then k flag = 0, connected = 0
544  |         */
545  |         qe->k ^= 1;
546  |       break;
547  | 
548  |       case 'r':
549  |         query_command->recursive=0;       /* Unset recursion */
550  |       break;
551  | 
552  |       case 'l':
553  |         query_command->l=1;
554  |       break;
555  | 
556  |       case 'm':
557  |         query_command->m=1;
558  |       break;
559  | 
560  |       case 'q':
561  |         if (my_optarg != NULL) {
562  |           index = getsubopt(&my_optarg, DF_get_server_queries(), &value);
563  |           if (index == -1) {
564  |             errflg++;
565  |           }
566  |           else {
567  |             query_command->q=index;
568  |           } 
569  |         } /* if () */
570  |       break;
571  | 
572  |       case 's':
573  |         if (my_optarg != NULL) {
574  |           sources_str = my_optarg;
575  |           /* Remove any sources from the sources list. */
576  |           while ((first_source = g_list_first(qe->sources_list)) != NULL) {
577  |             qe->sources_list = g_list_remove(qe->sources_list, first_source->data);
578  |           }
579  |           while (*sources_str) {
580  |             index = getsubopt(&sources_str, DF_get_sources(), &value);
581  |             if (index == -1) {
582  |               strcpy(str_buf, "");
583  |               sprintf(str_buf, "Unknown source encountered.\nNot one of: %s\n", DF_sources_to_string()); 
584  |               SK_cd_puts(&(qe->condat), str_buf);
585  | 
586  |               /* Put the default source back in. */
587  |               SK_cd_puts(&(qe->condat), "Reverting to default source - ");
588  |               SK_cd_puts(&(qe->condat), CO_get_database());
589  |               SK_cd_puts(&(qe->condat), "\n");
590  |               qe->sources_list = g_list_append(qe->sources_list, (void *)CO_get_database());
591  |               errflg++;
592  |             }
593  |             else {
594  |               qe->sources_list = g_list_append(qe->sources_list, (void *)DF_get_database(index));
595  |             } 
596  |           } /* while () */
597  |         } /* if () */
598  |       break;
599  | 
600  |       case 't':
601  |         if (my_optarg != NULL) {
602  |           object_types_str = my_optarg;
603  |           while (*object_types_str) {
604  |             index = getsubopt(&object_types_str, DF_get_class_aliases(), &value);
605  |             if (index == -1) {
606  |               strcpy(str_buf, "");
607  |               sprintf(str_buf, "Unknown object encountered.\n"); 
608  |               SK_cd_puts(&(qe->condat), str_buf);
609  |               errflg++;
610  |             }
611  |             else {
612  |               type = DF_get_class_index(index);
613  |               query_command->t=type;
614  |             }
615  |           }
616  |         }
617  |       break;
618  | 
619  |       case 'v':
620  |         if (my_optarg != NULL) {
621  |           object_types_str = my_optarg;
622  |           if (*object_types_str) {
623  |             index = getsubopt(&object_types_str, DF_get_class_aliases(), &value);
624  |             if (index == -1) {
625  |               strcpy(str_buf, "");
626  |               sprintf(str_buf, "Unknown object encountered.\n"); 
627  |               SK_cd_puts(&(qe->condat), str_buf);
628  |               errflg++;
629  |             }
630  |             else {
631  |               type = DF_get_class_index(index);
632  |               query_command->v=type;
633  |             }
634  |           }
635  |         }
636  |       break;
637  | 
638  |       case 'x':
639  |         query_command->x=1;
640  |       break;
641  | 
642  |       case 'F':
643  |         query_command->fast=1;
644  |       break;
645  | 
646  |       case 'K':
647  |         query_command->filtered=1;
648  |       break;
649  | 
650  |       case 'L':
651  |         query_command->L=1;
652  |       break;
653  | 
654  |       case 'M':
655  |         query_command->M=1;
656  |       break;
657  | 
658  |       case 'R':
659  |         query_command->R=1;
660  |       break;
661  | 
662  |       case 'S':
663  |         query_command->S=1;
664  |       break;
665  | 
666  |       case 'T':
667  |         if (my_optarg != NULL) {
668  |           object_types_str = my_optarg;
669  |           while (*object_types_str) {
670  |             index = getsubopt(&object_types_str, DF_get_class_aliases(), &value);
671  |             if (index == -1) {
672  |               strcpy(str_buf, "");
673  |               sprintf(str_buf, "Unknown class encountered.\n"); 
674  |               SK_cd_puts(&(qe->condat), str_buf);
675  |               errflg++;
676  |             }
677  |             else {
678  |               type = DF_get_class_index(index);
679  |               /* Add the type to the bitmap. */
680  |               MA_set(&(query_command->object_type_bitmap), type, 1);
681  |             }
682  |           }
683  |         }
684  |       break;
685  | 
686  |       case 'V':
687  |         if (qe->version != NULL) {
688  |           /* free up the old client info */
689  |           wr_free(qe->version);
690  |         }
691  |         
692  |         {
693  |           char *token, *cursor = my_optarg;
694  |           while( (token = strsep( &cursor, "," )) != NULL ) {
695  |             if(IP_addr_e2b( & (qe->pIP), token) 
696  |                != IP_OK ) {
697  |               /* means it was not an IP -> it was a version */
698  | 	      //qe->version = (char *)malloc(strlen(token)+1);
699  |               dieif( wr_malloc( (void **)&(qe->version), 
700  | 				strlen(token)+1) != UT_OK);  
701  |               strcpy(qe->version, token);
702  |             }
703  |           }
704  |         }
705  |       break;
706  | 
707  |       case '?':
708  |         errflg++;
709  |       break;
710  | 
711  |       default:
712  |         errflg++;
713  |     }
714  |   }
715  | 
716  |   /* XXX Report the error.  This could be improved. */
717  |   if (opt_argv[my_optind] != NULL) {
718  |     if ( (errflg) || (strncmp(opt_argv[my_optind], "-", 1) == 0) ) {
719  |       strncpy(str_buf, USAGE, STR_XL-1);
720  |       SK_cd_puts(&(qe->condat), str_buf);
721  |     }
722  |   }
723  |   else {
724  |     if (errflg) {
725  |       strncpy(str_buf, USAGE, STR_XL-1);
726  |       SK_cd_puts(&(qe->condat), str_buf);
727  |     }
728  |   }
729  |     
730  | 
731  |   /* Work out the length of space needed */
732  |   key_length = 0;
733  |   for (i=my_optind ; i < opt_argc; i++) {
734  |     /* length for the string + 1 for the '\0'+ 1 for the ' ' 
735  |        [MB removed: + 1 for good luck.] */
736  |     if (opt_argv[i] != NULL) {
737  |       key_length += strlen(opt_argv[i])+2;
738  |     }
739  |   }
740  | 
741  |   //query_command->keys = (char *)calloc(1, key_length+1);  
742  |   
743  |   dieif( wr_calloc((void **)&(query_command->keys), 1, key_length+1) != UT_OK);  
744  |   strcpy(query_command->keys, "");
745  |   if (errflg == 0) {
746  |     for (i=my_optind; i < opt_argc; i++) {
747  |       strcat(query_command->keys, opt_argv[i]);
748  |       if ( (i + 1) < opt_argc) {
749  |         strcat(query_command->keys, " ");
750  |       }
751  |     }
752  |   } /* XXX - Be careful about where this brace goes. */
753  | 
754  |   /* Now convert the key to uppercase. */
755  |   for (i=0; i <= key_length; i++) {
756  |     query_command->keys[i] = toupper(query_command->keys[i]);
757  |   }
758  | 
759  |   /* Now make the keytypes_bitmap. */
760  |   query_command->keytypes_bitmap = WK_new(query_command->keys);
761  | 
762  |   if ( CO_get_comnd_logging() == 1 ) {
763  |     log_command(tmp_query_str, query_command);
764  |   }
765  | 
766  |   /* Now we don't need this anymore */
767  |   wr_free(tmp_query_str);
768  | 
769  | } /* QC_fill() */
770  | 
771  | /* QC_environ_new() */
772  | /*++++++++++++++++++++++++++++++++++++++
773  |   Create a new query environment.
774  | 
775  |   More:
776  |   +html+ <PRE>
777  |   Authors:
778  |         ottrey
779  |   +html+ </PRE><DL COMPACT>
780  |   +html+ <DT>Online References:
781  |   +html+ <DD><UL>
782  |   +html+ </UL></DL>
783  | 
784  |   ++++++++++++++++++++++++++++++++++++++*/
785  | Query_environ *QC_environ_new(char *ip, unsigned sock) {
786  |   Query_environ *qe;
787  | 
788  |   //qe = (Query_environ *)calloc(1, sizeof(Query_environ)+1);
789  |   dieif( wr_calloc((void **)&qe, 1, sizeof(Query_environ)+1 ) != UT_OK);  
790  |   qe->condat.ip = ip;
791  |   qe->condat.sock = sock;
792  | 
793  |   /* The source is initialized to be the one defined in the config by default. */
794  |   qe->sources_list = g_list_append(qe->sources_list, (void *)CO_get_database());
795  | 
796  |   return qe;
797  | 
798  | } /* QC_environ_new() */
799  | 
800  | Query_command *QC_create(char *input, Query_environ *qe)
801  | {
802  |   Query_command *qc;
803  | 
804  |   //  query_command = (Query_command *)calloc(1, sizeof(Query_command)+1);
805  |   dieif( wr_calloc((void **)&qc, 1, sizeof(Query_command)+1) != UT_OK);
806  |   
807  |   if ( strlen(input) == 0) {
808  |     /* An empty query (Ie return) was sent */
809  |     qc->query_type = PW_EMPTY;
810  |   } 
811  |   else {        /* else <==> input_length > 0 ) */
812  |     /* parse query */
813  |     
814  |     QC_fill(input, qc, qe);
815  |   
816  |     /* Update the query environment */
817  |     // qe = QC_environ_update(qc, qe);
818  |     
819  |     /* Only do a query if there are keys. */
820  |     if (qc->keys == NULL || strlen(qc->keys) == 0 ) {
821  |       qc->query_type = PW_NOKEY;
822  |     }
823  |     else {
824  |       if( strlen(qc->keys) == 0 ) {
825  |         qc->query_type = PW_TEMPLATE;
826  |       }
827  |       else if ( strcmp(qc->keys, "help") == 0 ) {
828  |         qc->query_type = PW_HELP;
829  |       }
830  |       else {
831  |         /* Some real query */
832  |         qc->query_type = PW_REAL;
833  |       }
834  |     }
835  |   }
836  |   return qc;
837  | }