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.38 $
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 char *inv_attrs_str = NULL;
322 char *object_types_str = NULL;
323 int opt_argc;
324 gchar **opt_argv;
325 char *value;
326 char *tmp_query_str;
327 int key_length;
328 int i;
329 int index;
330 int type;
331 int attr;
332 char str_buf[STR_XL];
333 getopt_state_t *gst = NULL;
334
335 query_command->e = 0;
336 query_command->g = 0;
337 query_command->inv_attrs_bitmap = MA_new(MA_END);
338 query_command->recursive = 1; /* Recursion is on by default. */
339 query_command->l = 0;
340 query_command->m = 0;
341 query_command->q = -1;
342 query_command->t = -1;
343 query_command->v = -1;
344 query_command->x = 0;
345 query_command->fast = 0;
346 query_command->filtered = 0;
347 query_command->L = 0;
348 query_command->M = 0;
349 query_command->R = 0;
350 query_command->S = 0;
351 query_command->object_type_bitmap = MA_new(MA_END);
352 /*
353 query_command->keytypes_bitmap = MA_new(MA_END);
354 */
355 query_command->keys = NULL;
356
357 /* This is so Marek can't crash me :-) */
358 /* Side Effect - query keys are subsequently cut short to STR_S size. */
359
360 dieif( wr_calloc((void **)&tmp_query_str, 1, STR_S+1) != UT_OK);
361 strncpy(tmp_query_str, query_str, STR_S);
362
363 /* Create the arguments. */
364 /* This allows only a maximum of MAX_OPT_ARG_C words in the query. */
365 opt_argv = g_strsplit(tmp_query_str, " ", MAX_OPT_ARG_C);
366
367 /* Determine the number of arguments. */
368 for (opt_argc=0; opt_argv[opt_argc] != NULL; opt_argc++);
369
370 dieif( (gst = mg_new(0)) == NULL );
371
372 while ((c = mg_getopt(opt_argc, opt_argv, "aegi:klrmq:s:t:v:xFKLMRST:V:",
373 gst)) != EOF) {
374 switch (c) {
375 case 'a':
376 /* Remove any user specified sources from the sources list. */
377 /* free the list only, do not touch the elements */
378 g_list_free(qe->sources_list);
379 qe->sources_list=NULL;
380
381 /* Add all the config sources to the sources list. */
382 {
383 int i;
384 ca_dbSource_t *hdl;
385
386 for (i=0; (hdl = ca_get_SourceHandleByPosition(i)) != NULL; i++) {
387 qe->sources_list = g_list_append(qe->sources_list, (void *)hdl);
388 }
389 }
390
391
392 break;
393
394 case 'e':
395 query_command->e=1;
396 break;
397
398 case 'g':
399 query_command->g=1;
400 break;
401
402 case 'i':
403 if (gst->optarg != NULL) {
404 char *hackstr = NULL;
405
406 inv_attrs_str = gst->optarg;
407 /* Now a really stupid hard-coded hack to support "pn" being a synonym for "ac,tc,zc,ah" */
408 /* I particularly object to this because it references attributes that should only be
409 defined in XML - but I don't see a simplier more robust way of doing this hack.
410 :-( - ottrey 8/12/99
411 ** removed a memory leak - MB, 1/08/00
412 */
413 if ( strcmp(inv_attrs_str, "pn") == 0
414 || strcmp(inv_attrs_str, "ro") == 0) {
415 wr_malloc( (void **)& hackstr, 24); /* make a copy */
416 strcpy(hackstr, "ac,tc,zc,ah");
417 inv_attrs_str = hackstr;
418 }
419 while (*inv_attrs_str) {
420 index = getsubopt(&inv_attrs_str, DF_get_attribute_aliases(), &value);
421 if (index == -1) {
422 attr = -1;
423 strcpy(str_buf, "");
424 sprintf(str_buf, "Unknown attribute encountered.\n");
425 SK_cd_puts(&(qe->condat), str_buf);
426 badparerr++;
427 }
428 else {
429 mask_t inv_attr_mask = MA_new(INV_ATTR_MASK);
430 attr = DF_get_attribute_index(index);
431 if ( MA_isset(inv_attr_mask, attr) == 1 ) {
432 /* Add the attr to the bitmap. */
433 MA_set(&(query_command->inv_attrs_bitmap), attr, 1);
434 }
435 else {
436 strcpy(str_buf, "");
437 sprintf(str_buf, "\"%s\" does not belong to inv_attr.\n", (DF_get_attribute_aliases())[index]);
438 SK_cd_puts(&(qe->condat), str_buf);
439 badparerr++;
440 }
441 }
442 } /* while () */
443
444 if( hackstr != NULL) {
445 wr_free(hackstr);
446 }
447 } /* if () */
448 break;
449
450 case 'k':
451 /* triggering flag == a XOR operation */
452 qe->k ^= 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 obejct 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 } /* if no error */
658
659 /* we don't need this anymore */
660 wr_free(tmp_query_str);
661 wr_free(gst);
662
663 if(synerrflg > 0) { /* severe syntax error. Usage must be printed */
664 return QC_SYNERR;
665 }
666 else if(badparerr > 0) { /* the requester has a clue. No Usage info */
667 return QC_PARERR;
668 }
669 else {
670 return 0;
671 }
672 } /* QC_fill() */
673
674 /* QC_environ_new() */
675 /*++++++++++++++++++++++++++++++++++++++
676 Create a new query environment.
677
678 More:
679 +html+ <PRE>
680 Authors:
681 ottrey
682 +html+ </PRE><DL COMPACT>
683 +html+ <DT>Online References:
684 +html+ <DD><UL>
685 +html+ </UL></DL>
686
687 ++++++++++++++++++++++++++++++++++++++*/
688 Query_environ *QC_environ_new(char *ip, unsigned sock) {
/* [<][>][^][v][top][bottom][index][help] */
689 Query_environ *qe;
690
691
692 dieif( wr_calloc((void **)&qe, 1, sizeof(Query_environ)+1 ) != UT_OK);
693 qe->condat.ip = ip;
694 qe->condat.sock = sock;
695
696 /* The source is initialized to include only the deflook sources */
697 {
698 int i;
699 ca_dbSource_t *hdl;
700
701 for (i=0; (hdl = ca_get_SourceHandleByPosition(i)) != NULL; i++) {
702 if( ca_get_srcdeflook(hdl) ) {
703 qe->sources_list = g_list_append(qe->sources_list, (void *)hdl);
704 }
705 }
706 }
707
708 return qe;
709
710 } /* QC_environ_new() */
711
712
713
714 /*++ QC_create()
715
716 try to parse the query and fill in the QC struct, setting
717 qc->query_type accordingly.
718
719 by marek.
720 ++++++++++++++++++++++++++++++++++++++*/
721 Query_command *QC_create(char *input, Query_environ *qe)
/* [<][>][^][v][top][bottom][index][help] */
722 {
723 Query_command *qc;
724 /* allocate place for a copy of the input */
725 char *copy = calloc(1,strlen(input)+1);
726 char *ci, *co;
727 int qt;
728 /* clean the string from junk - allow only known chars, something like
729 tr/A-Za-z0-9\-\_\:\+\=\.\,\@\/ \n//cd;
730
731 strip leading spaces too
732 */
733
734 dieif(copy == NULL);
735
736 for(ci = input; *ci != 0 && isspace(*ci); ci++) {
737 /* EMPTY */
738 }
739
740 for(co = copy; *ci != 0; ci++) {
741 if( strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ" /* only those are allowed */
742 "abcdefghijklmnopqrstuvwxyz"
743 "0123456789-_:+=.,@/' \n", *ci) != NULL) {
744 *(co++) = *ci;
745 }
746 }
747
748 /* now delete whitespace chars at the end */
749 co--;
750 while( isspace(*co) ) {
751 *co = '\0';
752 co--;
753 }
754
755
756 dieif( wr_calloc((void **)&qc, 1, sizeof(Query_command)+1) != UT_OK);
757
758 if ( strlen(copy) == 0) {
759 /* An empty query (Ie return) was sent */
760 qc->query_type = QC_EMPTY;
761 }
762 else { /* else <==> input_length > 0 ) */
763 /* parse query */
764 qt = QC_fill(copy, qc, qe);
765
766 if( qt == QC_SYNERR || qt == QC_PARERR ) {
767 qc->query_type = qt;
768 }
769 else {
770 /* Update the query environment */
771 /* qe = QC_environ_update(qc, qe); */
772
773 /* Only do a query if there are keys. */
774 if (qc->keys == NULL || strlen(qc->keys) == 0 ) {
775 if( strlen(qc->keys) == 0
776 && ( qc->q != -1 || qc->t != -1 || qc->v != -1 ) ) {
777 qc->query_type = QC_TEMPLATE;
778 }
779 else {
780 qc->query_type = QC_NOKEY;
781 }
782 }
783 else {
784 if ( strcmp(qc->keys, "HELP") == 0 ) {
785 qc->query_type = QC_HELP;
786 }
787 /* So, a real query */
788 else if( qc->filtered ) {
789 qc->query_type = QC_FILTERED;
790 }
791 else {
792 qc->query_type = QC_REAL;
793 }
794 }
795 }
796 }
797
798 free(copy);
799
800 return qc;
801 }
802
803
804 char *QC_get_qrytype(qc_qtype_t qrytype) {
/* [<][>][^][v][top][bottom][index][help] */
805 dieif(qrytype >= QC_TYPE_MAX);
806
807 return qrytype_str[qrytype];
808 }