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 | }