modules/qc/query_command.c
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- qc_sources_list_to_string
- QC_environ_to_string
- QC_query_command_to_string
- log_command
- QC_environ_free
- QC_free
- QC_fill
- QC_environ_new
- QC_create
- QC_get_qrytype
1 /***************************************
2 $Revision: 1.41 $
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_dictSyms.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 make sources list (allocated string).
64 expects list to hold source handles
65 */
66 char *
67 qc_sources_list_to_string(GList *list)
/* [<][>][^][v][top][bottom][index][help] */
68 {
69 char *result = NULL;
70 int oldlen = 0;
71 GList *qitem;
72
73 for( qitem = g_list_first(list);
74 qitem != NULL;
75 qitem = g_list_next(qitem)) {
76 ca_dbSource_t *source_hdl = (ca_dbSource_t *) ( qitem->data );
77 char *srcname = ca_get_srcname( source_hdl );
78
79 dieif( wr_realloc( (void **)& result, oldlen + strlen(srcname) + 2)
80 != UT_OK);
81 if(oldlen > 0) {
82 strcat(result, ",");
83 }
84 strcat(result, srcname);
85 }
86
87 return result;
88 }
89
90 /* QC_environ_to_string() */
91 /*++++++++++++++++++++++++++++++++++++++
92 Convert the query_environ to a string.
93
94 Query_environ *query_environ The query_environ to be converted.
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+ </UL></DL>
104
105 ++++++++++++++++++++++++++++++++++++++*/
106 char *QC_environ_to_string(Query_environ qe) {
/* [<][>][^][v][top][bottom][index][help] */
107 char *result;
108 char *str1;
109 char str2[IP_ADDRSTR_MAX];
110 char result_buf[STR_XL];
111
112 str1 = qc_sources_list_to_string(qe.sources_list);
113
114 if( IP_addr_b2a( &(qe.pIP), str2, IP_ADDRSTR_MAX) != IP_OK ) {
115 *str2 = '\0';
116 }
117
118 sprintf(result_buf, "host=%s, keep_connection=%s, sources=%s, version=%s%s%s", qe.condat.ip,
119 qe.k?"on":"off",
120 str1,
121 (qe.version == NULL) ? "?" : qe.version,
122 *str2 == '\0' ? "" : ", passedIP=",
123 *str2 == '\0' ? "" : str2
124 );
125
126 wr_free(str1);
127
128 dieif( wr_malloc((void **)&result, strlen(result_buf)+1) != UT_OK);
129
130 strcpy(result, result_buf);
131
132 return result;
133
134 } /* QC_environ_to_string() */
135
136 /* QC_query_command_to_string() */
137 /*++++++++++++++++++++++++++++++++++++++
138 Convert the query_command to a string.
139
140 Query_command *query_command The query_command to be converted.
141
142 More:
143 +html+ <PRE>
144 Authors:
145 ottrey
146 +html+ </PRE><DL COMPACT>
147 +html+ <DT>Online References:
148 +html+ <DD><UL>
149 +html+ </UL></DL>
150
151 ++++++++++++++++++++++++++++++++++++++*/
152 char *QC_query_command_to_string(Query_command *query_command) {
/* [<][>][^][v][top][bottom][index][help] */
153 char *result;
154 char result_buf[STR_XL];
155 char *str1;
156 char *str2;
157 char *str3;
158
159 str1 = MA_to_string(query_command->inv_attrs_bitmap, DF_get_attribute_names());
160 str2 = MA_to_string(query_command->object_type_bitmap, DF_get_class_names());
161 str3 = WK_to_string(query_command->keytypes_bitmap);
162
163 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]",
164 str1,
165 query_command->recursive?"y":"n",
166 str2,
167 query_command->e,
168 query_command->g,
169 query_command->l,
170 query_command->m,
171 query_command->q,
172 query_command->t,
173 query_command->v,
174 query_command->x,
175 query_command->fast,
176 query_command->filtered,
177 query_command->L,
178 query_command->M,
179 query_command->R,
180 query_command->S,
181 str3,
182 query_command->keys);
183 wr_free(str1);
184 wr_free(str2);
185 wr_free(str3);
186
187 dieif( wr_malloc((void **)&result, strlen(result_buf)+1) != UT_OK);
188 strcpy(result, result_buf);
189
190 return result;
191
192 } /* QC_query_command_to_string() */
193
194 /* log_command() */
195 /*++++++++++++++++++++++++++++++++++++++
196 Log the command.
197 This is more to do with Tracing. And should/will get merged with a tracing
198 module (when it is finalized.)
199
200 char *query_str
201
202 Query_command *query_command
203
204 More:
205 +html+ <PRE>
206 Authors:
207 ottrey
208 +html+ </PRE><DL COMPACT>
209 +html+ <DT>Online References:
210 +html+ <DD><UL>
211 +html+ </UL></DL>
212
213 ++++++++++++++++++++++++++++++++++++++*/
214 static void log_command(char *query_str, Query_command *query_command) {
/* [<][>][^][v][top][bottom][index][help] */
215 char *str;
216
217 if( ER_is_traced(FAC_QC, ASP_QC_BUILD) ) {
218 str = QC_query_command_to_string(query_command);
219 ER_dbg_va(FAC_QC, ASP_QC_BUILD,
220 "query=[%s] %s", query_str, str);
221 wr_free(str);
222 }
223 } /* log_command() */
224
225 /* QC_environ_free() */
226 /*++++++++++++++++++++++++++++++++++++++
227 Free the query_environ.
228
229 Query_command *qc query_environ to be freed.
230
231 More:
232 +html+ <PRE>
233 Authors:
234 ottrey
235 +html+ </PRE><DL COMPACT>
236 +html+ <DT>Online References:
237 +html+ <DD><UL>
238 +html+ </UL></DL>
239
240 ++++++++++++++++++++++++++++++++++++++*/
241 void QC_environ_free(Query_environ *qe) {
/* [<][>][^][v][top][bottom][index][help] */
242 if (qe != NULL) {
243 if (qe->version != NULL) {
244 wr_free(qe->version);
245 }
246
247 if (qe->sources_list != NULL) {
248 g_list_free(qe->sources_list);
249 qe->sources_list=NULL;
250 }
251 wr_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 wr_free(qc->keys);
280 }
281 wr_free(qc);
282 }
283 } /* QC_free() */
284
285
286
287 /* QC_fill() */
288 /*++++++++++++++++++++++++++++++++++++++
289 Create a new query_command.
290
291
292
293 char *query_str The garden variety whois query string.
294
295 Query_environ *qe the environment
296
297 Pre-condition:
298
299 Returns -1 when query incorrect, 0 otherwise
300
301 More:
302 +html+ <PRE>
303 Authors:
304 ottrey - original code
305 marek - modified for my getopts, multiple sources;
306 and generally cleaned.
307 +html+ </PRE><DL COMPACT>
308 +html+ <DT>Online References:
309 +html+ <DD><UL>
310 +html+ </UL></DL>
311
312 ++++++++++++++++++++++++++++++++++++++*/
313 static
314 int QC_fill(char *query_str,
/* [<][>][^][v][top][bottom][index][help] */
315 Query_command *query_command,
316 Query_environ *qe) {
317
318 int c;
319 int synerrflg = 0;
320 int badparerr = 0;
321 int minusk = 0;
322 char *inv_attrs_str = NULL;
323 char *object_types_str = NULL;
324 int opt_argc;
325 gchar **opt_argv;
326 char *value;
327 char *tmp_query_str;
328 int key_length;
329 int i;
330 int index;
331 int type;
332 int attr;
333 char str_buf[STR_XL];
334 getopt_state_t *gst = NULL;
335
336 query_command->e = 0;
337 query_command->g = 0;
338 query_command->inv_attrs_bitmap = MA_new(MA_END);
339 query_command->recursive = 1; /* Recursion is on by default. */
340 query_command->l = 0;
341 query_command->m = 0;
342 query_command->q = -1;
343 query_command->t = -1;
344 query_command->v = -1;
345 query_command->x = 0;
346 query_command->fast = 0;
347 query_command->filtered = 0;
348 query_command->L = 0;
349 query_command->M = 0;
350 query_command->R = 0;
351 query_command->S = 0;
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 dieif( wr_calloc((void **)&tmp_query_str, 1, STR_S+1) != UT_OK);
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
368 /* Determine the number of arguments. */
369 for (opt_argc=0; opt_argv[opt_argc] != NULL; opt_argc++);
370
371 dieif( (gst = mg_new(0)) == NULL );
372
373 while ((c = mg_getopt(opt_argc, opt_argv, "aegi:klrmq:s:t:v:xFKLMRST:V:",
374 gst)) != EOF) {
375 switch (c) {
376 case 'a':
377 /* Remove any user specified sources from the sources list. */
378 /* free the list only, do not touch the elements */
379 g_list_free(qe->sources_list);
380 qe->sources_list=NULL;
381
382 /* Add all the config sources to the sources list. */
383 {
384 int i;
385 ca_dbSource_t *hdl;
386
387 for (i=0; (hdl = ca_get_SourceHandleByPosition(i)) != NULL; i++) {
388 qe->sources_list = g_list_append(qe->sources_list, (void *)hdl);
389 }
390 }
391
392
393 break;
394
395 case 'e':
396 query_command->e=1;
397 break;
398
399 case 'g':
400 query_command->g=1;
401 break;
402
403 case 'i':
404 if (gst->optarg != NULL) {
405 char *hackstr = NULL;
406
407 inv_attrs_str = gst->optarg;
408 /* Now a really stupid hard-coded hack to support "pn" being a synonym for "ac,tc,zc,ah" */
409 /* I particularly object to this because it references attributes that should only be
410 defined in XML - but I don't see a simplier more robust way of doing this hack.
411 :-( - ottrey 8/12/99
412 ** removed a memory leak - MB, 1/08/00
413 */
414 if ( strcmp(inv_attrs_str, "pn") == 0
415 || strcmp(inv_attrs_str, "ro") == 0) {
416 wr_malloc( (void **)& hackstr, 24); /* make a copy */
417 strcpy(hackstr, "ac,tc,zc,ah");
418 inv_attrs_str = hackstr;
419 }
420 while (*inv_attrs_str) {
421 index = getsubopt(&inv_attrs_str, DF_get_attribute_aliases(), &value);
422 if (index == -1) {
423 attr = -1;
424 strcpy(str_buf, "");
425 sprintf(str_buf, "Unknown attribute encountered.\n");
426 SK_cd_puts(&(qe->condat), str_buf);
427 badparerr++;
428 }
429 else {
430 mask_t inv_attr_mask = MA_new(INV_ATTR_MASK);
431 attr = DF_get_attribute_index(index);
432 if ( MA_isset(inv_attr_mask, attr) == 1 ) {
433 /* Add the attr to the bitmap. */
434 MA_set(&(query_command->inv_attrs_bitmap), attr, 1);
435 }
436 else {
437 strcpy(str_buf, "");
438 sprintf(str_buf, "\"%s\" is not an inverse searchable attribute.\n", (DF_get_attribute_aliases())[index]);
439 SK_cd_puts(&(qe->condat), str_buf);
440 badparerr++;
441 }
442 }
443 } /* while () */
444
445 if( hackstr != NULL) {
446 wr_free(hackstr);
447 }
448 } /* if () */
449 break;
450
451 case 'k':
452 minusk = 1;
453 break;
454
455 case 'r':
456 query_command->recursive=0; /* Unset recursion */
457 break;
458
459 case 'l':
460 query_command->l=1;
461 break;
462
463 case 'm':
464 query_command->m=1;
465 break;
466
467 case 'q':
468 if (gst->optarg != NULL) {
469 index = getsubopt(&gst->optarg, DF_get_server_queries(), &value);
470 if (index == -1) {
471 synerrflg++;
472 }
473 else {
474 query_command->q = index;
475 }
476 } /* if () */
477 break;
478
479 case 's':
480 if (gst->optarg != NULL) {
481 char *token, *cursor = gst->optarg;
482 ca_dbSource_t *handle;
483
484 /* Remove any sources from the sources list. */
485 g_list_free(qe->sources_list);
486 qe->sources_list=NULL;
487
488 /* go through specified sources */
489 while( (token = strsep( &cursor, "," )) != NULL ) {
490
491 if( (handle = ca_get_SourceHandleByName(token)) != NULL ) {
492 /* append */
493 qe->sources_list
494 = g_list_append(qe->sources_list, (void *) handle );
495 }
496 else {
497 /* bail out */
498
499 SK_cd_printf(&(qe->condat),
500 "%% Unknown source %s requested.\n",token );
501
502 /* XXX error */
503 badparerr++;
504
505 } /* if handle not null */
506 } /* while sources */
507 } /* if argument present */
508 break;
509
510 case 't':
511 if (gst->optarg != NULL) {
512 object_types_str = gst->optarg;
513 while (*object_types_str) {
514 index = getsubopt(&object_types_str, DF_get_class_aliases(), &value);
515 if (index == -1) {
516 strcpy(str_buf, "");
517 sprintf(str_buf, "Unknown object encountered.\n");
518 SK_cd_puts(&(qe->condat), str_buf);
519 badparerr++;
520 }
521 else {
522 type = DF_get_class_index(index);
523 query_command->t=type;
524 }
525 }
526 }
527 break;
528
529 case 'v':
530 if (gst->optarg != NULL) {
531 object_types_str = gst->optarg;
532 if (*object_types_str) {
533 index = getsubopt(&object_types_str, DF_get_class_aliases(), &value);
534 if (index == -1) {
535 strcpy(str_buf, "");
536 sprintf(str_buf, "Unknown object encountered.\n");
537 SK_cd_puts(&(qe->condat), str_buf);
538 badparerr++;
539 }
540 else {
541 type = DF_get_class_index(index);
542 query_command->v=type;
543 }
544 }
545 }
546 break;
547
548 case 'x':
549 query_command->x=1;
550 break;
551
552 case 'F':
553 query_command->fast=1;
554 query_command->recursive=0; /* implies no recursion */
555 break;
556
557 case 'K':
558 query_command->filtered=1;
559 query_command->recursive=0; /* implies no recursion */
560 break;
561
562 case 'L':
563 query_command->L=1;
564 break;
565
566 case 'M':
567 query_command->M=1;
568 break;
569
570 case 'R':
571 query_command->R=1;
572 break;
573
574 case 'S':
575 query_command->S=1;
576 break;
577
578 case 'T':
579 if (gst->optarg != NULL) {
580 object_types_str = gst->optarg;
581 while (*object_types_str) {
582 index = getsubopt(&object_types_str, DF_get_class_aliases(), &value);
583 if (index == -1) {
584 strcpy(str_buf, "");
585 sprintf(str_buf, "Unknown object type encountered.\n");
586 SK_cd_puts(&(qe->condat), str_buf);
587 badparerr++;
588 }
589 else {
590 type = DF_get_class_index(index);
591 /* Add the type to the bitmap. */
592 MA_set(&(query_command->object_type_bitmap), type, 1);
593 }
594 }
595 }
596 break;
597
598 case 'V':
599 if (qe->version != NULL) {
600 /* free up the old client info */
601 wr_free(qe->version);
602 }
603
604 {
605 char *token, *cursor = gst->optarg;
606 while( (token = strsep( &cursor, "," )) != NULL ) {
607 if(IP_addr_e2b( & (qe->pIP), token)
608 != IP_OK ) {
609 /* means it was not an IP -> it was a version */
610 dieif( wr_malloc( (void **)&(qe->version),
611 strlen(token)+1) != UT_OK);
612 strcpy(qe->version, token);
613 }
614 }
615 }
616 break;
617
618 /* any other flag, including '?' and ':' errors */
619 default:
620 synerrflg++;
621 }
622 }
623
624 /* copy the key */
625
626 /* Work out the length of space needed */
627 key_length = 1; /* for terminal '\0' */
628 for (i=gst->optind ; i < opt_argc; i++) {
629 /* length for the string + 1 for the '\0'+ 1 for the ' ' */
630 if (opt_argv[i] != NULL) {
631 key_length += strlen(opt_argv[i])+1;
632 }
633 }
634 /* allocate */
635 dieif( wr_calloc((void **)&(query_command->keys), 1, key_length+1) != UT_OK);
636 /* copy */
637 for (i=gst->optind; i < opt_argc; i++) {
638 strcat(query_command->keys, opt_argv[i]);
639 if ( (i + 1) < opt_argc) {
640 strcat(query_command->keys, " ");
641 }
642 }
643
644 /* if no error, process the key, otherwise don't bother */
645 if ( ! synerrflg && ! badparerr ) {
646 /* convert the key to uppercase. */
647 for (i=0; i <= key_length; i++) {
648 query_command->keys[i] = toupper(query_command->keys[i]);
649 }
650
651 /* make the keytypes_bitmap. */
652 query_command->keytypes_bitmap = WK_new(query_command->keys);
653
654 /* tracing */
655 log_command(tmp_query_str, query_command);
656
657
658 /* "keep connection" processing:
659 when opening connection, -k may be alone or with a query
660 later -k must appear alone (or there must be an empty line,
661 or an error) for the connection to close.
662 */
663 if( minusk ) {
664 if( qe->k == 0 ) { /* opening */
665 qe->k = 1;
666 }
667 else { /* closing, if no key; otherwise keep open */
668 if( key_length <= 1 ) {
669 qe->k = 0;
670 }
671 }
672 }
673
674 } /* if no error */
675
676 /* we don't need this anymore */
677 wr_free(tmp_query_str);
678 wr_free(gst);
679
680 if(synerrflg > 0) { /* severe syntax error. Usage must be printed */
681 return QC_SYNERR;
682 }
683 else if(badparerr > 0) { /* the requester has a clue. No Usage info */
684 return QC_PARERR;
685 }
686 else {
687 return 0;
688 }
689 } /* QC_fill() */
690
691 /* QC_environ_new() */
692 /*++++++++++++++++++++++++++++++++++++++
693 Create a new query environment.
694
695 More:
696 +html+ <PRE>
697 Authors:
698 ottrey
699 +html+ </PRE><DL COMPACT>
700 +html+ <DT>Online References:
701 +html+ <DD><UL>
702 +html+ </UL></DL>
703
704 ++++++++++++++++++++++++++++++++++++++*/
705 Query_environ *QC_environ_new(char *ip, unsigned sock) {
/* [<][>][^][v][top][bottom][index][help] */
706 Query_environ *qe;
707
708
709 dieif( wr_calloc((void **)&qe, 1, sizeof(Query_environ)+1 ) != UT_OK);
710 qe->condat.ip = ip;
711 qe->condat.sock = sock;
712
713 /* The source is initialized to include only the deflook sources */
714 {
715 int i;
716 ca_dbSource_t *hdl;
717
718 for (i=0; (hdl = ca_get_SourceHandleByPosition(i)) != NULL; i++) {
719 if( ca_get_srcdeflook(hdl) ) {
720 qe->sources_list = g_list_append(qe->sources_list, (void *)hdl);
721 }
722 }
723 }
724
725 return qe;
726
727 } /* QC_environ_new() */
728
729
730
731 /*++ QC_create()
732
733 try to parse the query and fill in the QC struct, setting
734 qc->query_type accordingly.
735
736 by marek.
737 ++++++++++++++++++++++++++++++++++++++*/
738 Query_command *QC_create(char *input, Query_environ *qe)
/* [<][>][^][v][top][bottom][index][help] */
739 {
740 Query_command *qc;
741 /* allocate place for a copy of the input */
742 char *copy = calloc(1,strlen(input)+1);
743 char *ci, *co;
744 int qt;
745 /* clean the string from junk - allow only known chars, something like
746 tr/A-Za-z0-9\-\_\:\+\=\.\,\@\/ \n//cd;
747
748 strip leading spaces too
749 */
750
751 dieif(copy == NULL);
752
753 for(ci = input; *ci != 0 && isspace(*ci); ci++) {
754 /* EMPTY */
755 }
756
757 for(co = copy; *ci != 0; ci++) {
758 if( strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ" /* only those are allowed */
759 "abcdefghijklmnopqrstuvwxyz"
760 "0123456789-_:+=.,@/' \n", *ci) != NULL) {
761 *(co++) = *ci;
762 }
763 }
764
765 /* now delete whitespace chars at the end */
766 co--;
767 while( isspace(*co) ) {
768 *co = '\0';
769 co--;
770 }
771
772
773 dieif( wr_calloc((void **)&qc, 1, sizeof(Query_command)+1) != UT_OK);
774
775 if ( strlen(copy) == 0) {
776 /* An empty query (Ie return) was sent */
777 qc->query_type = QC_EMPTY;
778 }
779 else { /* else <==> input_length > 0 ) */
780 /* parse query */
781 qt = QC_fill(copy, qc, qe);
782
783 if( qt == QC_SYNERR || qt == QC_PARERR ) {
784 qc->query_type = qt;
785 }
786 else {
787 /* Update the query environment */
788 /* qe = QC_environ_update(qc, qe); */
789
790 /* Only do a query if there are keys. */
791 if (qc->keys == NULL || strlen(qc->keys) == 0 ) {
792 if( strlen(qc->keys) == 0
793 && ( qc->q != -1 || qc->t != -1 || qc->v != -1 ) ) {
794 qc->query_type = QC_TEMPLATE;
795 }
796 else {
797 qc->query_type = QC_NOKEY;
798 }
799 }
800 else {
801 if ( strcmp(qc->keys, "HELP") == 0 ) {
802 qc->query_type = QC_HELP;
803 }
804 /* So, a real query */
805 else if( qc->filtered ) {
806 qc->query_type = QC_FILTERED;
807 }
808 else {
809 qc->query_type = QC_REAL;
810 }
811 }
812 }
813 }
814
815 free(copy);
816
817 return qc;
818 }
819
820
821 char *QC_get_qrytype(qc_qtype_t qrytype) {
/* [<][>][^][v][top][bottom][index][help] */
822 dieif(qrytype >= QC_TYPE_MAX);
823
824 return qrytype_str[qrytype];
825 }