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