1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 28 /* 29 * Module: sml.c 30 * Synopsis: simplified markup language (SML) support 31 * Taxonomy: project private 32 * Debug flag: sml 33 * Description: 34 * 35 * This module implements methods that support the processing of a 36 * simplified markup language (SML). Objects that contain SML data 37 * can be created and manipulated, and SML can be imported into 38 * internal SML objects or exported from internal SML objects. 39 * 40 * Public Methods: 41 * 42 * smlAddTag - Add new tag object into existing tag object 43 * smlConvertStringToTag - Convert string into tag object 44 * smlConvertTagToString - Convert a tag object into a string 45 * representation of the XML 46 * smlDbgPrintTag - Print a representation of an XML tag if debugging 47 * smlDelParam - Delete a parameter from a tag object 48 * smlDelTag - Delete element from tag object 49 * smlDup - Duplicate a tag object 50 * smlFindAndDelTag - Delete a tag if found in tag object 51 * smlFreeTag - Free a tag object and all its contents when no 52 * longer needed 53 * smlFstatCompareEq - Compare file status information 54 * smlGetElementName - Return a tag's element name 55 * smlGetNumParams - Get number of parameters set in tag 56 * smlGetParam - Get a parameter from a tag 57 * smlGetParamF - Get a formatted parameter from a tag 58 * smlGetParamByTag - Get a parameter by tag and index 59 * smlGetParamByTagParam Get parameter given tag name, index, 60 * parameter name, and value 61 * smlGetParamName - Get the name of a tag parameter given its index 62 * smlGetParam_r - Get a parameter from a tag into fixed buffer 63 * smlGetTag - Get an element from a tag 64 * smlGetTagByName - Get an element given a name and an index 65 * smlGetTagByTagParam - Get element given tag name, index, parameter name, 66 * and value 67 * smlGetVerbose - get current verbose mode setting 68 * smlLoadTagFromFile - Load a file into a tag object 69 * smlNewTag - Create a new (empty) tag object 70 * smlParamEq - Determine if parameter is equal to a specified value 71 * smlParamEqF - Determine if parameter is equal to a specified value 72 * smlPrintTag - Print a simple XML representation of a tag to stderr 73 * smlReadOneTag - read one complete tag from a datastream 74 * smlReadTagFromDs - read tag object from datastream 75 * smlSetFileStatInfo - encode file status information into tag 76 * smlSetVerbose - set/clear verbose mode for debugging output 77 * smlSetParam - Set parameter value in tag object 78 * smlSetParamF - Set parameter value in tag object 79 * smlWriteTagToDs - Write an XML representation of a tag to a datastream 80 * smlWriteTagToFd - Write an XML representation of a tag to an open file 81 * descriptor 82 * smlWriteTagToFile - Write an XML representation of a tag to a file 83 */ 84 85 /* 86 * Unix includes 87 */ 88 89 #include <locale.h> 90 #include <signal.h> 91 #include <stdio.h> 92 #include <stdlib.h> 93 #include <libintl.h> 94 #include <stdarg.h> 95 #include <string.h> 96 #include <unistd.h> 97 #include <sys/statvfs.h> 98 #include <errno.h> 99 #include <assert.h> 100 #include <sys/types.h> 101 #include <sys/stat.h> 102 #include <fcntl.h> 103 #include <limits.h> 104 #include <strings.h> 105 106 /* 107 * liblu Includes 108 */ 109 110 #include "libinst.h" 111 #include "messages.h" 112 113 /* Should be defined by cc -D */ 114 #if !defined(TEXT_DOMAIN) 115 #define TEXT_DOMAIN "SYS_TEST" 116 #endif 117 118 /* 119 * Private Method Forward Declarations 120 */ 121 122 /*PRINTFLIKE2*/ 123 static void _smlLogMsg(LogMsgType a_type, const char *a_format, ...); 124 125 static int _smlReadTag(SML_TAG **r_tag, char **a_str, char *parent); 126 127 static int _smlWriteSimpleTag(char **a_str, 128 SML_TAG *tag); 129 130 static int _smlWriteParamValue(char **a_str, char *value); 131 132 static void _smlFreeTag(SML_TAG *tag); 133 134 static char *_sml_fileStatInfoTag = "File-Stat-Info"; 135 136 static boolean_t verbose = B_FALSE; 137 138 /* 139 * 140 * This definition controls the maximum size of any individual sml 141 * component, such as a tag name, tag *value*, etc. The code should 142 * someday be revised to dynamically allocate whatever memory is needed 143 * to hold such components while parsing, but that exercise is left for 144 * another day. Any component that exceeds this length is silently 145 * truncated... 146 */ 147 148 #define MAX_SML_COMPONENT_LENGTH 16384 149 150 /* 151 * Public Methods 152 */ 153 154 /* 155 * Name: smlAddTag 156 * Description: Add new tag object into existing tag object 157 * Arguments: r_tag - [RO, *RW] - (SML_TAG **) 158 * Pointer to handle to the tag object to update 159 * The handle may be updated if the tag object is 160 * moved in memory 161 * a_index - [RO] - (int) 162 * Add the tag after the "n"th tag in the tag object 163 * -1 == add the tag to the end of the tag object 164 * 0 == add the tag to the beginning of the tag object 165 * a_subTag - [RO, *RW] - (SML_TAG *) 166 * The tag to add to 'tag' 167 * Returns: SML_TAG * 168 * The location within "r_tag" where "a_subTag" 169 * has been added - this is the handle into the r_tag 170 * object to the tag that was just added 171 * Errors: If the tag object cannot be updated, the process exits 172 */ 173 174 SML_TAG * 175 smlAddTag(SML_TAG **r_tag, int a_index, SML_TAG *a_subTag) 176 { 177 SML_TAG *tag; 178 179 /* entry assertions */ 180 181 assert(SML_TAG__ISVALID(a_subTag)); 182 assert(SML_TAG__R_ISVALID(r_tag)); 183 184 /* if no tag to update specified, ignore request */ 185 186 tag = *r_tag; 187 if (tag == SML_TAG__NULL) { 188 return (tag); 189 } 190 191 /* entry debugging info */ 192 193 _smlLogMsg(LOG_MSG_DEBUG, DBG_SML_ADD_TAG, 194 a_subTag->name, tag->name); 195 196 /* if index is out of range or -1, append to tag object */ 197 198 if ((a_index > tag->tags_num) || (a_index == -1)) { 199 a_index = tag->tags_num; 200 } 201 202 /* bump number of tags in tag object */ 203 204 tag->tags_num++; 205 206 /* expand tag object to hold new subtag */ 207 208 tag->tags = (SML_TAG *)realloc(tag->tags, 209 sizeof (SML_TAG) * tag->tags_num); 210 211 /* if not appending, adjust tag object to hold new subtag */ 212 213 if (a_index < (tag->tags_num - 1)) { 214 (void) memmove(&(tag->tags[a_index + 1]), &(tag->tags[a_index]), 215 sizeof (SML_TAG) * (tag->tags_num - a_index - 1)); 216 } 217 218 /* copy new subtag into correct location in tag object */ 219 220 (void) memcpy(&(tag->tags[a_index]), a_subTag, 221 sizeof (SML_TAG)); 222 223 return (&(tag->tags[a_index])); 224 } 225 226 /* 227 * Name: smlDelTag 228 * Description: Delete element from tag object 229 * Arguments: tag - [RO, *RW] - (SML_TAG *) 230 * The tag object to update 231 * sub_tag - [RO, *RW] - (SML_TAG *) 232 * Element to be removed from the tag object 233 * Returns: void 234 * The sub_tag is removed from the tag object 235 * NOTE: The sub-tag and all elements contained within it are deallocated 236 * the sub-tag is no longer valid when this method returns 237 */ 238 239 void 240 smlDelTag(SML_TAG *tag, SML_TAG *sub_tag) 241 { 242 int index; 243 244 /* entry assertions */ 245 246 assert(SML_TAG__ISVALID(sub_tag)); 247 248 /* if no tag to update specified, ignore request */ 249 250 if (tag == SML_TAG__NULL) { 251 return; 252 } 253 254 /* entry debugging info */ 255 256 _smlLogMsg(LOG_MSG_DEBUG, DBG_SML_DEL_TAG, 257 sub_tag->name, tag->name); 258 259 /* if tag object is empty, ignore request */ 260 261 if (tag->tags_num == 0) { 262 return; 263 } 264 265 /* determine index into tag object of element to remove */ 266 for (index = 0; index < tag->tags_num; index++) { 267 if (sub_tag == &tag->tags[index]) { 268 break; 269 } 270 } 271 272 /* if element not found in tag, ignore request */ 273 274 if (index >= tag->tags_num) { 275 return; 276 } 277 278 /* free up the subtag to be deleted */ 279 280 _smlFreeTag(sub_tag); 281 282 /* 283 * if not removing last element, collapse tag object removing 284 * target element 285 */ 286 287 if (index < (tag->tags_num - 1)) { 288 (void) memmove(&(tag->tags[index]), &(tag->tags[index + 1]), 289 sizeof (SML_TAG) *(tag->tags_num - index - 1)); 290 } 291 292 /* one less tag object in tag */ 293 294 tag->tags_num --; 295 296 /* 297 * If only one tag left, then delete entire tag structure 298 * otherwise reallocate removing unneeded entry 299 */ 300 301 if (tag->tags_num > 0) { 302 /* realloc removing last element in tag object */ 303 304 tag->tags = (SML_TAG *)realloc(tag->tags, 305 sizeof (SML_TAG) *tag->tags_num); 306 } else { 307 tag->tags = SML_TAG__NULL; 308 } 309 } 310 311 /* 312 * Name: smlFreeTag 313 * Description: Free a tag object and all its contents when no longer needed 314 * Arguments: tag - [RO, *RW] - (SML_TAG *) 315 * The tag object to be deleted 316 * Returns: void 317 * The tag object and all its contents are deallocated 318 */ 319 320 void 321 smlFreeTag(SML_TAG *tag) 322 { 323 /* entry assertions */ 324 325 assert(SML_TAG__ISVALID(tag)); 326 327 /* entry debugging info */ 328 329 if (tag->name != (char *)NULL) { 330 _smlLogMsg(LOG_MSG_DEBUG, DBG_SML_FREE_TAG, 331 (unsigned long)tag, tag->name); 332 } 333 334 /* free the tag object contents */ 335 336 _smlFreeTag(tag); 337 338 /* free the tag object handle */ 339 340 bzero(tag, sizeof (SML_TAG)); 341 free(tag); 342 } 343 344 /* 345 * Name: smlGetNumParams 346 * Synopsis: Get number of parameters set in tag 347 * Description: Return the number of parameters set in a tag 348 * Arguments: a_tag - [RO, *RO] - (SML_TAG *) 349 * The tag object to obtain the # params from 350 * Returns: int 351 * Number of parameters set in tag 352 * 0 = no parameters are set 353 */ 354 355 int 356 smlGetNumParams(SML_TAG *a_tag) 357 { 358 return (a_tag ? a_tag->params_num : 0); 359 } 360 361 362 /* 363 * Name: smlGetParam_r 364 * Description: Get a parameter from a tag into a buffer of fixed size 365 * Arguments: tag - [RO, *RO] - (SML_TAG *) 366 * The tag object to obtain the parameter from 367 * name - [RO, *RO] - (char *) 368 * Name of the parameter to retrieve 369 * buf - [RO, *RW] - (char *) 370 * Location of buffer to contain results 371 * bufLen - [RO, *RO] - (int) 372 * Maximum bytes available in buffer to contain results 373 * Returns: void 374 */ 375 376 void 377 smlGetParam_r(SML_TAG *tag, char *name, char *buf, int bufLen) 378 { 379 int k; 380 381 /* entry assertions */ 382 383 assert(name != (char *)NULL); 384 assert(*name != '\0'); 385 assert(buf != (char *)NULL); 386 assert(bufLen > 0); 387 388 /* terminate the buffer */ 389 390 buf[0] = '\0'; 391 buf[bufLen-1] = '\0'; 392 393 bzero(buf, bufLen); 394 395 /* if no tag specified, return NULL */ 396 397 if (tag == SML_TAG__NULL) { 398 return; 399 } 400 401 /* if no parameters in tag, return NULL */ 402 403 if (tag->params == NULL) { 404 return; 405 } 406 407 /* entry debugging info */ 408 409 _smlLogMsg(LOG_MSG_DEBUG, DBG_SML_GET_PARAM, 410 name, tag->name); 411 412 /* scan tag object looking for specified parameter */ 413 414 for (k = 0; k < tag->params_num; k++) { 415 assert(tag->params[k].name != (char *)NULL); 416 assert(tag->params[k].value != (char *)NULL); 417 if (streq(tag->params[k].name, name)) { 418 _smlLogMsg(LOG_MSG_DEBUG, 419 DBG_SML_GOT_PARAM, 420 tag->name, name, tag->params[k].value); 421 (void) strncpy(buf, tag->params[k].value, bufLen-1); 422 return; 423 } 424 } 425 426 /* parameter not found - return */ 427 } 428 429 /* 430 * Name: smlGetParam 431 * Description: Get a parameter from a tag 432 * Arguments: tag - [RO, *RO] - (SML_TAG *) 433 * The tag object to obtain the parameter from 434 * name - [RO, *RO] - (char *) 435 * Name of the parameter to retrieve 436 * Returns: char * 437 * Value of the specified parameter 438 * == (char *)NULL if the parameter does not exist 439 * NOTE: Any parameter returned is placed in new storage for the 440 * calling method. The caller must use 'free' to dispose 441 * of the storage once the parameter is no longer needed. 442 */ 443 444 char * 445 smlGetParam(SML_TAG *tag, char *name) 446 { 447 int k; 448 449 /* entry assertions */ 450 451 assert(name != (char *)NULL); 452 assert(*name != '\0'); 453 454 /* entry debugging info */ 455 456 _smlLogMsg(LOG_MSG_DEBUG, "get param param <%s>", name); 457 458 /* if no tag specified, return NULL */ 459 460 if (tag == SML_TAG__NULL) { 461 return ((char *)NULL); 462 } 463 464 /* if no parameters in tag, return NULL */ 465 466 if (tag->params == NULL) { 467 return ((char *)NULL); 468 } 469 470 /* entry debugging info */ 471 472 _smlLogMsg(LOG_MSG_DEBUG, DBG_SML_GET_PARAM, 473 name, tag->name); 474 475 /* scan tag object looking for specified parameter */ 476 477 for (k = 0; k < tag->params_num; k++) { 478 assert(tag->params[k].name != (char *)NULL); 479 assert(tag->params[k].value != (char *)NULL); 480 if (streq(tag->params[k].name, name)) { 481 _smlLogMsg(LOG_MSG_DEBUG, 482 DBG_SML_GOT_PARAM, 483 tag->name, name, tag->params[k].value); 484 return (strdup(tag->params[k].value)); 485 } 486 } 487 488 /* parameter not found - return NULL */ 489 490 return ((char *)NULL); 491 } 492 493 /* 494 * Name: smlGetParamName 495 * Description: Get the name of a tag parameter given its index 496 * Arguments: tag - [RO, *RO] - (SML_TAG *) 497 * The tag object to obtain the parameter name from 498 * index - [RO] - (int) 499 * Index of parameter name to return 500 * Returns: char * 501 * Name of 'index'th parameter 502 * == (char *)NULL if no such parameter exists in tag 503 * NOTE: Any parameter name returned is placed in new storage for the 504 * calling method. The caller must use 'free' to dispose 505 * of the storage once the parameter name is no longer needed. 506 */ 507 508 char * 509 smlGetParamName(SML_TAG *tag, int index) 510 { 511 /* if no tag specified, return NULL */ 512 513 if (tag == NULL) { 514 return ((char *)NULL); 515 } 516 517 /* entry debugging info */ 518 519 _smlLogMsg(LOG_MSG_DEBUG, DBG_SML_GET_PARAM_NAME, 520 tag->name, index); 521 522 /* if no parameters in tag, return NULL */ 523 524 if (tag->params == NULL) { 525 return ((char *)NULL); 526 } 527 528 /* if index not within range, return NULL */ 529 530 if (index >= tag->params_num) { 531 return ((char *)NULL); 532 } 533 534 /* index within range - return parameter name */ 535 536 assert(tag->params[index].name != (char *)NULL); 537 assert(tag->params[index].value != (char *)NULL); 538 539 _smlLogMsg(LOG_MSG_DEBUG, DBG_SML_GOT_PARAM_NAME, 540 tag->name, index, tag->params[index].name); 541 542 return (strdup(tag->params[index].name)); 543 } 544 545 /* 546 * Name: smlGetParamByTag 547 * Synopsis: Get a parameter value from a tag by name and index 548 * Description: Call to look for a parameter value from a tag with 549 * a given name with a parameter of a given name 550 * Arguments: tag - [RO, *RO] - (SML_TAG *) 551 * The tag object to obtain the parameter 552 * index - [RO] - (int) 553 * Index of nth tag by name to look for 554 * tagName - [RO, *RO] - (char *) 555 * Name of tag to look for 556 * paramName - [RO, *RO] - (char *) 557 * Name of parameter to return value of 558 * Returns: char * 559 * == (char *)NULL - no parameter value set 560 * != (char *)NULL - value of parameter set 561 */ 562 563 char * 564 smlGetParamByTag(SML_TAG *tag, int index, 565 char *tagName, char *paramName) 566 { 567 SML_TAG *rtag; 568 569 /* entry assertions */ 570 571 assert(SML_TAG__ISVALID(tag)); 572 assert(tagName != (char *)NULL); 573 assert(*tagName != '\0'); 574 assert(paramName != (char *)NULL); 575 assert(*paramName != '\0'); 576 577 /* entry debugging info */ 578 579 _smlLogMsg(LOG_MSG_DEBUG, DBG_SML_GET_PARAM_BY_TAG, 580 tagName, index, paramName); 581 582 /* find the requested tag by name and index */ 583 584 rtag = smlGetTagByName(tag, index, tagName); 585 if (rtag == SML_TAG__NULL) { 586 return ((char *)NULL); 587 } 588 589 return (smlGetParam(rtag, paramName)); 590 } 591 592 /* 593 * Name: smlGetTagByTagParam 594 * Synopsis: Get element given tag name, index, parameter name, and value 595 * Description: Call to look for a tag with a given nae, that has a parameter 596 * of a given name with a specified value 597 * Arguments: tag - [RO, *RO] - (SML_TAG *) 598 * The tag object to obtain the element from 599 * index - [RO] - (int) 600 * Index of nth name to return 601 * tagName - [RO, *RO] - (char *) 602 * Tag name to look up 603 * paramName - [RO, *RO] - (char *) 604 * Parameter name to look up 605 * paramValue - [RO, *RO] - (char *) 606 * Parameter value to match 607 * Returns: SML_TAG * 608 * The 'index'th occurance of element 'name' with 609 * a parameter 'name' with value specified 610 * == SML_TAG__NULL if no such element exists 611 */ 612 613 SML_TAG * 614 smlGetTagByTagParam(SML_TAG *tag, int index, 615 char *tagName, char *paramName, char *paramValue) 616 { 617 int ti; /* tag structure index */ 618 619 /* entry assertions */ 620 621 assert(SML_TAG__ISVALID(tag)); 622 assert(tagName != (char *)NULL); 623 assert(*tagName != '\0'); 624 assert(paramName != (char *)NULL); 625 assert(*paramName != '\0'); 626 assert(paramValue != (char *)NULL); 627 assert(*paramValue != '\0'); 628 629 /* if tag has no elements, return NULL */ 630 631 if (tag->tags == NULL) { 632 return (SML_TAG__NULL); 633 } 634 635 /* 636 * Search algorithm: 637 * -> search tag structure; for each tag with element == "tagName": 638 * -> search tag parameters; if parameter name == "paramName" 639 * -> if parameter value != "paramValue"; to next tag 640 * -> if parameter value == "paramValue": 641 * -> if not the "index"th paramValue found; to next tag 642 * -> return tag found 643 */ 644 645 for (ti = 0; ti < tag->tags_num; ti++) { 646 int pi; /* parameter structure index */ 647 648 /* if tag element does not match, go on to next tag */ 649 650 if (strcmp(tag->tags[ti].name, tagName)) { 651 continue; 652 } 653 654 /* element matches: search for specified parameter name/value */ 655 656 for (pi = 0; pi < tag->tags[ti].params_num; pi++) { 657 assert(tag->tags[ti].params[pi].name != (char *)NULL); 658 assert(tag->tags[ti].params[pi].value != (char *)NULL); 659 660 /* if parameter name doesnt match to next parameter */ 661 662 if (strcmp(tag->tags[ti].params[pi].name, paramName)) { 663 continue; 664 } 665 666 /* if parameter value doesnt match to next tag */ 667 668 if (strcmp(tag->tags[ti].params[pi].value, 669 paramValue)) { 670 break; 671 } 672 673 /* 674 * found element/paramname/paramvalue: 675 * -> if this is not the 'index'th one, go to next tag 676 */ 677 678 if (index-- != 0) { 679 break; 680 } 681 682 /* 683 * found specified element/paramname/paramvalue: 684 * -> return the tag found 685 */ 686 687 return (&tag->tags[ti]); 688 } 689 690 } 691 692 /* no such element found - return NULL */ 693 694 return (SML_TAG__NULL); 695 } 696 697 /* 698 * Name: smlGetParamByTagParam 699 * Synopsis: Get parameter given tag name, index, parameter name, and value 700 * Description: Call to return the value of a parameter from a tag of a 701 * given name, with a parameter of a given name with a 702 * specified value 703 * Arguments: tag - [RO, *RO] - (SML_TAG *) 704 * The tag object to obtain the element from 705 * index - [RO] - (int) 706 * Index of nth name to return 707 * tagName - [RO, *RO] - (char *) 708 * Tag name to look up 709 * paramName - [RO, *RO] - (char *) 710 * Parameter name to look up 711 * paramValue - [RO, *RO] - (char *) 712 * Parameter value to match 713 * paramReturn - [RO, *RO] - (char *) 714 * Parameter name to return the value of 715 * Returns: char * 716 * The value of parameter 'paramReturn' from the 717 * The 'index'th occurance of element 'name' with 718 * a parameter 'name' with value specified 719 * == (char *)NULL if no such parameter exists 720 */ 721 722 char * 723 smlGetParamByTagParam(SML_TAG *tag, int index, 724 char *tagName, char *paramName, char *paramValue, char *paramReturn) 725 { 726 int ti; /* tag structure index */ 727 728 /* entry assertions */ 729 730 assert(SML_TAG__ISVALID(tag)); 731 assert(tagName != (char *)NULL); 732 assert(*tagName != '\0'); 733 assert(paramName != (char *)NULL); 734 assert(*paramName != '\0'); 735 assert(paramValue != (char *)NULL); 736 assert(*paramValue != '\0'); 737 assert(paramReturn != (char *)NULL); 738 assert(*paramReturn != '\0'); 739 740 /* if tag has no elements, return NULL */ 741 742 if (tag->tags == NULL) { 743 return ((char *)NULL); 744 } 745 746 /* 747 * Search algorithm: 748 * -> search tag structure; for each tag with element == "tagName": 749 * -> search tag parameters; if parameter name == "paramName" 750 * -> if parameter value != "paramValue"; to next tag 751 * -> if parameter value == "paramValue": 752 * -> if not the "index"th paramValue found; to next tag 753 * -> return value of "paramReturn" 754 */ 755 756 for (ti = 0; ti < tag->tags_num; ti++) { 757 int pi; /* parameter structure index */ 758 759 /* if tag element does not match, go on to next tag */ 760 761 if (strcmp(tag->tags[ti].name, tagName)) { 762 continue; 763 } 764 765 /* element matches: search for specified parameter name/value */ 766 767 for (pi = 0; pi < tag->tags[ti].params_num; pi++) { 768 assert(tag->tags[ti].params[pi].name != (char *)NULL); 769 assert(tag->tags[ti].params[pi].value != (char *)NULL); 770 771 /* if parameter name doesnt match to next parameter */ 772 773 if (strcmp(tag->tags[ti].params[pi].name, paramName)) { 774 continue; 775 } 776 777 /* if parameter value doesnt match to next tag */ 778 779 if (strcmp(tag->tags[ti].params[pi].value, 780 paramValue)) { 781 break; 782 } 783 784 /* 785 * found element/paramname/paramvalue: 786 * -> if this is not the 'index'th one, go to next tag 787 */ 788 789 if (index-- != 0) { 790 break; 791 } 792 793 /* 794 * found specified element/paramname/paramvalue: 795 * -> return parameter requested 796 */ 797 798 return (smlGetParam(&tag->tags[ti], paramReturn)); 799 } 800 801 } 802 803 /* no such element found - return NULL */ 804 805 return ((char *)NULL); 806 } 807 808 /* 809 * Name: smlGetElementName 810 * Description: Return the name of a given tag 811 * Arguments: a_tag - [RO, *RO] - (SML_TAG *) 812 * The tag object to obtain the element name from 813 * Returns: char * 814 * Value of name of specified tag 815 * NOTE: Any name string returned is placed in new storage for the 816 * calling method. The caller must use 'free' to dispose 817 * of the storage once the name string is no longer needed. 818 */ 819 820 char * 821 smlGetElementName(SML_TAG *a_tag) 822 { 823 /* entry assertions */ 824 825 assert(SML_TAG__ISVALID(a_tag)); 826 assert(a_tag->name != (char *)NULL); 827 assert(*a_tag->name != '\0'); 828 829 /* return the tag name */ 830 831 return (strdup(a_tag->name)); 832 } 833 834 /* 835 * Name: smlGetTag 836 * Description: Get an element from a tag 837 * Arguments: tag - [RO, *RO] - (SML_TAG *) 838 * The tag object to obtain the element from 839 * index - [RO] - (int) 840 * Index of element to return 841 * Returns: SML_TAG * 842 * The 'index'th element from the specified tag 843 * == SML_TAG__NULL if no such tag or element 844 */ 845 846 SML_TAG * 847 smlGetTag(SML_TAG *tag, int index) 848 { 849 /* if no tag specified, return NULL */ 850 851 if (tag == NULL) { 852 return (SML_TAG__NULL); 853 } 854 855 /* if tag has no elements, return NULL */ 856 857 if (tag->tags == NULL) { 858 return (SML_TAG__NULL); 859 } 860 861 /* if index not within range, return NULL */ 862 863 if (tag->tags_num <= index) { 864 return (SML_TAG__NULL); 865 } 866 867 /* index within range, return element specified */ 868 869 assert(SML_TAG__ISVALID(&tag->tags[index])); 870 871 return (&tag->tags[index]); 872 } 873 874 /* 875 * Name: smlGetTagByName 876 * Description: Get an element given a name and an index 877 * Arguments: tag - [RO, *RO] - (SML_TAG *) 878 * The tag object to obtain the element from 879 * index - [RO] - (int) 880 * Index of nth name to return 881 * name - [RO, *RO] - (char *) 882 * Tag name to look up 883 * Returns: SML_TAG * 884 * The 'index'th occurance of element 'name' 885 * == SML_TAG__NULL if no such element exists 886 */ 887 888 SML_TAG * 889 smlGetTagByName(SML_TAG *tag, int index, char *name) 890 { 891 int k; 892 893 _smlLogMsg(LOG_MSG_DEBUG, DBG_SML_GET_TAG_BY_NAME, name, index); 894 895 /* if no tag specified, return NULL */ 896 897 if (tag == NULL) { 898 return (SML_TAG__NULL); 899 } 900 901 /* if this tag is the one mentioned, return it */ 902 903 if (streq(tag->name, name) && (index == 0)) { 904 return (tag); 905 } 906 907 /* if tag has no elements, return NULL */ 908 909 if (tag->tags == NULL) { 910 return (SML_TAG__NULL); 911 } 912 913 /* if index out of range, return NULL */ 914 915 if (tag->tags_num <= index) { 916 return (SML_TAG__NULL); 917 } 918 919 /* index within range - search for specified element */ 920 921 for (k = 0; k < tag->tags_num; k++) { 922 if (streq(tag->tags[k].name, name)) { 923 if (index == 0) { 924 assert(SML_TAG__ISVALID(&tag->tags[k])); 925 return (&tag->tags[k]); 926 } else { 927 index--; 928 } 929 } 930 } 931 932 /* no such element found - return NULL */ 933 934 return (SML_TAG__NULL); 935 } 936 937 /* 938 * Name: smlConvertStringToTag 939 * Description: Convert string into tag object 940 * Arguments: err - [RO, *RW] (LU_ERR) 941 * Error object - used to contain any errors encountered 942 * and return those errors to this methods caller 943 * r_tag - [RW, *RW] - (SML_TAG **) 944 * Pointer to handle to place new tag object 945 * str - [RO, *RO] - (char *) 946 * String object to convert to tag object 947 * Returns: int 948 * RESULT_OK - string converted to tag object 949 * RESULT_ERR - problem converting string to tag object 950 * NOTE: Any tag object returned is placed in new storage for the 951 * calling method. The caller must use 'smlFreeTag' to dispose 952 * of the storage once the tag object name is no longer needed. 953 */ 954 955 int 956 smlConvertStringToTag(SML_TAG **r_tag, char *str) 957 { 958 int r; 959 SML_TAG *tag = SML_TAG__NULL; 960 SML_TAG *tmp_tag; 961 962 /* entry assertions */ 963 964 assert(SML_TAG__R_ISVALID(r_tag)); 965 assert(str != (char *)NULL); 966 assert(*str != '\0'); 967 968 tag = smlNewTag("tagfile"); 969 970 for (;;) { 971 r = _smlReadTag(&tmp_tag, &str, NULL); 972 if (r != RESULT_OK) { 973 smlFreeTag(tag); 974 return (r); 975 } 976 if (tmp_tag == SML_TAG__NULL) { 977 if (*str != '\0') { 978 continue; 979 } 980 _smlLogMsg(LOG_MSG_DEBUG, 981 DBG_SML_LOADED_TAGS_FROM_STR, 982 (unsigned long)tag, tag->name); 983 *r_tag = tag; 984 return (RESULT_OK); 985 } 986 _smlLogMsg(LOG_MSG_DEBUG, DBG_SML_READ_IN_TOP_TAG, 987 tmp_tag->name); 988 tag->tags_num++; 989 tag->tags = (SML_TAG *)realloc(tag->tags, 990 sizeof (SML_TAG) *tag->tags_num); 991 (void) memcpy(&(tag->tags[tag->tags_num - 1]), tmp_tag, 992 sizeof (SML_TAG)); 993 } 994 } 995 996 /* 997 * Name: smlReadOneTag 998 * Description: read one complete tag from a datastream 999 * Arguments: err - [RO, *RW] (LU_ERR) 1000 * Error object - used to contain any errors encountered 1001 * and return those errors to this methods caller 1002 * r_tag - [RW, *RW] - (SML_TAG **) 1003 * Pointer to handle to place new tag object 1004 * == SML_TAG__NULL if empty tag found (not an error) 1005 * ds - [RO, *RO] - (LU_DS) 1006 * Handle to datastream to read tag from 1007 * Returns: int 1008 * RESULT_OK - tag successfully read 1009 * RESULT_ERR - problem reading tag 1010 * NOTE: Any tag object returned is placed in new storage for the 1011 * calling method. The caller must use 'smlFreeTag' to dispose 1012 * of the storage once the tag object name is no longer needed. 1013 */ 1014 1015 int 1016 smlReadOneTag(SML_TAG **r_tag, char *a_str) 1017 { 1018 int r; 1019 1020 /* entry assertions */ 1021 1022 assert(SML_TAG__R_ISVALID(r_tag)); 1023 assert(a_str != (char *)NULL); 1024 1025 /* entry debugging info */ 1026 1027 _smlLogMsg(LOG_MSG_DEBUG, DBG_SML_READ_ONE_TAG, a_str); 1028 1029 /* reset return tag */ 1030 1031 *r_tag = SML_TAG__NULL; 1032 1033 /* read tag from datastream, no parent tag to attach it to */ 1034 1035 r = _smlReadTag(r_tag, &a_str, NULL); 1036 if (r != RESULT_OK) { 1037 _smlLogMsg(LOG_MSG_ERR, ERR_SML_CANNOT_READ_TAG); 1038 return (r); 1039 } 1040 1041 if (*r_tag != SML_TAG__NULL) { 1042 _smlLogMsg(LOG_MSG_DEBUG, DBG_SML_ONE_TAG_READ, 1043 (unsigned long)*r_tag, 1044 (*r_tag)->name ? (*r_tag)->name : "<no name>"); 1045 } else { 1046 _smlLogMsg(LOG_MSG_DEBUG, DBG_SML_READ_ONE_TAG_NOTAG); 1047 } 1048 1049 /* exit debugging info */ 1050 1051 return (RESULT_OK); 1052 } 1053 1054 /* 1055 * Name: smlNewTag 1056 * Description: Create a new (empty) tag object 1057 * Arguments: name - [RO, *RO] - (char *) 1058 * Name of tag; NULL to give the tag no name 1059 * Returns: SML_TAG * 1060 * Tag object created 1061 * NOTE: Any tag object returned is placed in new storage for the 1062 * calling method. The caller must use 'smlFreeTag' to dispose 1063 * of the storage once the tag object name is no longer needed. 1064 * Errors: If the tag object cannot be created, the process exits 1065 */ 1066 1067 SML_TAG * 1068 smlNewTag(char *name) 1069 { 1070 SML_TAG *tag; 1071 1072 /* entry assertions */ 1073 1074 assert((name == (char *)NULL) || (*name != '\0')); 1075 1076 /* entry debugging info */ 1077 1078 _smlLogMsg(LOG_MSG_DEBUG, DBG_SML_CREATE_NEW_TAG_OBJECT, 1079 name ? name : "<no name>"); 1080 1081 /* allocate zeroed storage for the tag object */ 1082 1083 tag = (SML_TAG *)calloc(1, sizeof (SML_TAG)); 1084 assert(tag != SML_TAG__NULL); 1085 1086 /* if name is provided, duplicate and assign it */ 1087 1088 if (name != (char *)NULL) { 1089 tag->name = strdup(name); 1090 } 1091 1092 /* exit assertions */ 1093 1094 assert(SML_TAG__ISVALID(tag)); 1095 1096 /* exit debugging info */ 1097 1098 _smlLogMsg(LOG_MSG_DEBUG, DBG_SML_CREATED_NEW_TAG_OBJECT, 1099 (unsigned long)tag, name ? name : "<no name>"); 1100 1101 return (tag); 1102 } 1103 1104 /* 1105 * Name: smlConvertTagToString 1106 * Description: Convert a tag object into a string representation of the XML 1107 * Arguments: tag - [RO, *RO] - (SML_TAG *) 1108 * The tag object to convert to a string 1109 * Returns: char * 1110 * String representation (in XML) of tag object 1111 * == (char *)NULL if conversion is not possible 1112 * NOTE: Any string returned is placed in new storage for the 1113 * calling method. The caller must use 'free' to dispose 1114 * of the storage once the string is no longer needed. 1115 */ 1116 1117 char * 1118 smlConvertTagToString(SML_TAG *tag) 1119 { 1120 char *str = (char *)NULL; 1121 1122 /* entry assertions */ 1123 1124 assert(SML_TAG__ISVALID(tag)); 1125 1126 /* convert the tag object into the datastream */ 1127 1128 (void) _smlWriteSimpleTag(&str, tag); 1129 1130 assert(str != (char *)NULL); 1131 assert(*str != '\0'); 1132 1133 /* return the results */ 1134 1135 return (str); 1136 } 1137 1138 /* 1139 * Name: smlDbgPrintTag 1140 * Synopsis: Print a representation of an XML tag if debugging 1141 * Arguments: a_tag - [RO, *RO] - (SML_TAG *) 1142 * Pointer to tag structure to dump 1143 * a_format - [RO, RO*] (char *) 1144 * printf-style format for debugging message to be output 1145 * VARG_LIST - [RO] (?) 1146 * arguments as appropriate to 'format' specified 1147 * Returns: void 1148 * If one of the debugging flags is set, the hexdump 1149 * is output. 1150 */ 1151 1152 /*PRINTFLIKE2*/ 1153 void 1154 smlDbgPrintTag(SML_TAG *a_tag, char *a_format, ...) 1155 { 1156 va_list ap; 1157 size_t vres = 0; 1158 char bfr[1]; 1159 char *rstr = (char *)NULL; 1160 1161 /* entry assertions */ 1162 1163 assert(a_format != (char *)NULL); 1164 assert(*a_format != '\0'); 1165 assert(SML_TAG__ISVALID(a_tag)); 1166 1167 /* 1168 * output the message header 1169 */ 1170 1171 /* determine size of the message in bytes */ 1172 1173 va_start(ap, a_format); 1174 vres = vsnprintf(bfr, 1, a_format, ap); 1175 va_end(ap); 1176 1177 assert(vres > 0); 1178 1179 /* allocate storage to hold the message */ 1180 1181 rstr = (char *)calloc(1, vres+2); 1182 assert(rstr != (char *)NULL); 1183 1184 /* generate the results of the printf conversion */ 1185 1186 va_start(ap, a_format); 1187 vres = vsnprintf(rstr, vres+1, a_format, ap); 1188 va_end(ap); 1189 1190 assert(vres > 0); 1191 assert(*rstr != '\0'); 1192 1193 _smlLogMsg(LOG_MSG_DEBUG, "%s", rstr); 1194 free(rstr); 1195 1196 /* convert the tag into a string to be printed */ 1197 1198 rstr = smlConvertTagToString(a_tag); 1199 if (rstr != (char *)NULL) { 1200 _smlLogMsg(LOG_MSG_DEBUG, DBG_SML_PRINTTAG, a_tag->name, 1201 strlen(rstr), rstr); 1202 } 1203 free(rstr); 1204 } 1205 1206 /* 1207 * Name: smlDelParam 1208 * Description: Delete a parameter from a tag object 1209 * Arguments: tag - [RO, *RW] - (SML_TAG *) 1210 * The tag object to delete the parameter from 1211 * name - [RO, *RO] - (char *) 1212 * The parameter to delete from the tag object 1213 * Returns: void 1214 * If the parameter exists, it is deleted from the tag 1215 */ 1216 1217 void 1218 smlDelParam(SML_TAG *tag, char *name) 1219 { 1220 int k; 1221 1222 /* entry assertions */ 1223 1224 assert(SML_TAG__ISVALID(tag)); 1225 assert(tag->name != (char *)NULL); 1226 assert(name != NULL); 1227 assert(*name != '\0'); 1228 1229 /* entry debugging info */ 1230 1231 _smlLogMsg(LOG_MSG_DEBUG, DBG_SML_DELETE_PARAM, 1232 tag->name, name); 1233 1234 /* if tag has no parameters, nothing to delete */ 1235 1236 if (tag->params == NULL) { 1237 _smlLogMsg(LOG_MSG_DEBUG, 1238 DBG_SML_DELETE_PARAM_NO_PARAMS); 1239 return; 1240 } 1241 1242 assert(tag->params_num > 0); 1243 1244 /* search the tag for the parameter */ 1245 1246 for (k = 0; k < tag->params_num; k++) { 1247 if (streq(tag->params[k].name, name)) { 1248 break; 1249 } 1250 } 1251 1252 /* if the parameter was not found, nothing to delete */ 1253 1254 if (k >= tag->params_num) { 1255 _smlLogMsg(LOG_MSG_DEBUG, 1256 DBG_SML_DELETE_PARAM_NOT_FOUND, 1257 name); 1258 return; 1259 } 1260 1261 /* parameter found - indicate deleted */ 1262 1263 assert(tag->params[k].name != (char *)NULL); 1264 assert(tag->params[k].value != (char *)NULL); 1265 1266 _smlLogMsg(LOG_MSG_DEBUG, 1267 DBG_SML_DELETE_PARAM_FOUND, 1268 name, tag->params[k].value); 1269 1270 /* free up storage fro parameter */ 1271 1272 free(tag->params[k].name); 1273 free(tag->params[k].value); 1274 1275 /* if not at end, compact parameter storage */ 1276 1277 if (k < (tag->params_num -1)) { 1278 (void) memmove(&(tag->params[k]), &(tag->params[k + 1]), 1279 sizeof (SML_PARAM) *(tag->params_num - k - 1)); 1280 } 1281 1282 /* one less parameter object in tag */ 1283 1284 tag->params_num --; 1285 1286 /* 1287 * If only one parameter left, then delete entire parameter storage, 1288 * otherwise reallocate removing unneeded entry 1289 */ 1290 1291 if (tag->params_num > 0) { 1292 /* realloc removing last element in tag object */ 1293 1294 tag->params = (SML_PARAM *) 1295 realloc(tag->params, 1296 sizeof (SML_PARAM) *tag->params_num); 1297 } else { 1298 tag->params = (SML_PARAM *)NULL; 1299 } 1300 } 1301 1302 /* 1303 * Name: smlSetParamF 1304 * Description: Set formatted parameter value in tag object 1305 * Arguments: tag - [RO, *RW] - (SML_TAG *) 1306 * The tag object to set the parameter in 1307 * name - [RO, *RO] - (char *) 1308 * The parameter to add to the tag object 1309 * format - [RO, RO*] (char *) 1310 * printf-style format to create parameter value from 1311 * ... - [RO] (?) 1312 * arguments as appropriate to 'format' specified 1313 * Returns: void 1314 * The parameter value is set in the tag object 1315 * according to the results of the format string 1316 * and arguments 1317 */ 1318 1319 /*PRINTFLIKE3*/ 1320 void 1321 smlSetParamF(SML_TAG *tag, char *name, char *format, ...) 1322 { 1323 va_list ap; 1324 size_t vres = 0; 1325 char *bfr = NULL; 1326 char fbfr[1]; 1327 1328 /* entry assertions */ 1329 1330 assert(SML_TAG__ISVALID(tag)); 1331 assert(name != (char *)NULL); 1332 assert(*name != '\0'); 1333 assert(format != NULL); 1334 assert(*format != '\0'); 1335 1336 /* determine size of the parameter name in bytes */ 1337 1338 va_start(ap, format); 1339 vres = vsnprintf(fbfr, 1, format, ap); 1340 va_end(ap); 1341 1342 assert(vres > 0); 1343 1344 /* allocate storage to hold the message */ 1345 1346 bfr = (char *)calloc(1, vres+2); 1347 assert(bfr != (char *)NULL); 1348 1349 /* generate the parameter name and store it in the allocated storage */ 1350 1351 va_start(ap, format); 1352 vres = vsnprintf(bfr, vres+1, format, ap); 1353 va_end(ap); 1354 1355 assert(vres > 0); 1356 assert(*bfr != '\0'); 1357 1358 /* add the parameter to the tag */ 1359 1360 smlSetParam(tag, name, bfr); 1361 1362 /* free up temporary storage and return */ 1363 1364 free(bfr); 1365 } 1366 1367 /* 1368 * Name: smlGetParam 1369 * Description: Get a format-generated parameter from a tag 1370 * Arguments: tag - [RO, *RO] - (SML_TAG *) 1371 * The tag object to obtain the parameter from 1372 * format - [RO, RO*] (char *) 1373 * printf-style format for parameter name to be 1374 * looked up to be formatted 1375 * ... - [RO] (?) 1376 * arguments as appropriate to 'format' specified 1377 * Returns: char * 1378 * Value of the specified parameter 1379 * == (char *)NULL if the parameter does not exist 1380 * NOTE: Any parameter returned is placed in new storage for the 1381 * calling method. The caller must use 'free' to dispose 1382 * of the storage once the parameter is no longer needed. 1383 */ 1384 1385 /*PRINTFLIKE2*/ 1386 char * 1387 smlGetParamF(SML_TAG *tag, char *format, ...) 1388 { 1389 va_list ap; 1390 size_t vres = 0; 1391 char *bfr = NULL; 1392 char fbfr[1]; 1393 char *p; 1394 1395 /* entry assertions */ 1396 1397 assert(SML_TAG__ISVALID(tag)); 1398 assert(format != NULL); 1399 assert(*format != '\0'); 1400 1401 /* determine size of the parameter name in bytes */ 1402 1403 va_start(ap, format); 1404 vres = vsnprintf(fbfr, 1, format, ap); 1405 va_end(ap); 1406 1407 assert(vres > 0); 1408 1409 /* allocate storage to hold the message */ 1410 1411 bfr = (char *)calloc(1, vres+2); 1412 assert(bfr != (char *)NULL); 1413 1414 /* generate the parameter name and store it in the allocated storage */ 1415 1416 va_start(ap, format); 1417 vres = vsnprintf(bfr, vres+1, format, ap); 1418 va_end(ap); 1419 1420 assert(vres > 0); 1421 assert(*bfr != '\0'); 1422 1423 /* add the parameter to the tag */ 1424 1425 p = smlGetParam(tag, bfr); 1426 1427 /* free up temporary storage and return */ 1428 1429 free(bfr); 1430 1431 return (p); 1432 } 1433 1434 /* 1435 * Name: smlSetParam 1436 * Description: Set parameter value in tag object 1437 * Arguments: tag - [RO, *RW] - (SML_TAG *) 1438 * The tag object to set the parameter in 1439 * name - [RO, *RO] - (char *) 1440 * The parameter to add to the tag object 1441 * value - [RO, *RO] - (char *) 1442 * The value of the parameter to set in the tag object 1443 * Returns: void 1444 * The parameter value is set in the tag object 1445 */ 1446 1447 void 1448 smlSetParam(SML_TAG *tag, char *name, char *value) 1449 { 1450 SML_PARAM *parameter; 1451 1452 /* entry assertions */ 1453 1454 assert(SML_TAG__ISVALID(tag)); 1455 assert(name != (char *)NULL); 1456 assert(*name != '\0'); 1457 assert(value != (char *)NULL); 1458 1459 /* entry debugging info */ 1460 1461 _smlLogMsg(LOG_MSG_DEBUG, DBG_SML_SET_PARAM, 1462 tag->name, name, value); 1463 1464 /* if parameters exist, see if modifying existing parameter */ 1465 1466 if (tag->params != NULL) { 1467 int k; 1468 for (k = 0; k < tag->params_num; k++) { 1469 assert(tag->params[k].name != (char *)NULL); 1470 assert(tag->params[k].value != (char *)NULL); 1471 1472 /* if name does not match, skip */ 1473 1474 if (!streq(tag->params[k].name, name)) { 1475 continue; 1476 } 1477 1478 /* found parameter - if value is same, leave alone */ 1479 1480 if (streq(tag->params[k].value, value)) { 1481 _smlLogMsg(LOG_MSG_DEBUG, 1482 DBG_SML_SET_PARAM_LEAVE_ALONE, 1483 tag->params[k].value); 1484 return; 1485 } 1486 1487 /* exists and has different value - change */ 1488 1489 _smlLogMsg(LOG_MSG_DEBUG, 1490 DBG_SML_SET_PARAM_MODIFY, 1491 tag->params[k].value); 1492 free(tag->params[k].value); 1493 tag->params[k].value = strdup(value); 1494 return; 1495 } 1496 } 1497 1498 /* not modifying existing - add new parameter */ 1499 1500 _smlLogMsg(LOG_MSG_DEBUG, 1501 DBG_SML_SET_PARAM_CREATE_NEW); 1502 1503 parameter = (SML_PARAM *)calloc(1, sizeof (SML_PARAM)); 1504 bzero(parameter, sizeof (SML_PARAM)); 1505 parameter->name = strdup(name); 1506 parameter->value = strdup(value); 1507 1508 tag->params_num++; 1509 tag->params = (SML_PARAM *)realloc(tag->params, 1510 sizeof (SML_PARAM) *tag->params_num); 1511 (void) memcpy(&(tag->params[tag->params_num - 1]), parameter, 1512 sizeof (SML_PARAM)); 1513 free(parameter); 1514 } 1515 1516 /* 1517 * Name: smlParamEqF 1518 * Description: Determine if parameter is equal to a specified formatted value 1519 * Arguments: tag - [RO, *RO] - (SML_TAG *) 1520 * The tag object to look for the parameter to compare 1521 * findTag - [RO, *RO] - (char *) 1522 * Tag within tag object to look for the parameter in 1523 * findParam - [RO, *RO] - (char *) 1524 * Parameter within tag to look for 1525 * format - [RO, RO*] (char *) 1526 * printf-style format for value to be compared against 1527 * parameter value 1528 * ... - [RO] (?) 1529 * arguments as appropriate to 'format' specified to 1530 * generate the value to compare parameter with 1531 * Returns: boolean_t 1532 * B_TRUE - the parameter exists and matches given value 1533 * B_FALSE - parameter does not exist or does not match 1534 */ 1535 1536 /*PRINTFLIKE4*/ 1537 boolean_t 1538 smlParamEqF(SML_TAG *tag, char *findTag, char *findParam, char *format, ...) 1539 { 1540 va_list ap; 1541 size_t vres = 0; 1542 char *bfr = NULL; 1543 char fbfr[1]; 1544 boolean_t b; 1545 1546 /* entry assertions */ 1547 1548 assert(SML_TAG__ISVALID(tag)); 1549 assert(format != NULL); 1550 assert(*format != '\0'); 1551 1552 /* determine size of the parameter value in bytes */ 1553 1554 va_start(ap, format); 1555 vres = vsnprintf(fbfr, 1, format, ap); 1556 va_end(ap); 1557 1558 assert(vres > 0); 1559 1560 /* allocate storage to hold the message */ 1561 1562 bfr = (char *)calloc(1, vres+2); 1563 assert(bfr != (char *)NULL); 1564 1565 /* generate the parameter value and store it in the allocated storage */ 1566 1567 va_start(ap, format); 1568 vres = vsnprintf(bfr, vres+1, format, ap); 1569 va_end(ap); 1570 1571 assert(vres > 0); 1572 assert(*bfr != '\0'); 1573 1574 /* add the parameter to the tag */ 1575 1576 b = smlParamEq(tag, findTag, findParam, bfr); 1577 1578 /* free up temporary storage and return */ 1579 1580 free(bfr); 1581 1582 return (b); 1583 } 1584 1585 /* 1586 * Name: smlParamEq 1587 * Description: Determine if parameter is equal to a specified value 1588 * Arguments: tag - [RO, *RO] - (SML_TAG *) 1589 * The tag object to look for the parameter to compare 1590 * findTag - [RO, *RO] - (char *) 1591 * Tag within tag object to look for the parameter in 1592 * findParam - [RO, *RO] - (char *) 1593 * Parameter within tag to look for 1594 * str - [RO, *RO] - (char *) 1595 * Value to compare parameter with 1596 * Returns: boolean_t 1597 * B_TRUE - the parameter exists and matches given value 1598 * B_FALSE - parameter does not exist or does not match 1599 */ 1600 1601 boolean_t 1602 smlParamEq(SML_TAG *tag, char *findTag, char *findParam, char *str) 1603 { 1604 SML_TAG *rtag; 1605 char *rparm; 1606 boolean_t answer; 1607 1608 /* entry assertions */ 1609 1610 assert(str != (char *)NULL); 1611 assert(findParam != (char *)NULL); 1612 assert(findTag != (char *)NULL); 1613 assert(SML_TAG__ISVALID(tag)); 1614 1615 /* look for the specified tag - if not found, return false */ 1616 1617 rtag = smlGetTagByName(tag, 0, findTag); 1618 if (rtag == SML_TAG__NULL) { 1619 return (B_FALSE); 1620 } 1621 1622 /* look for the specified parameter - if not found, return false */ 1623 1624 rparm = smlGetParam(rtag, findParam); 1625 if (rparm == (char *)NULL) { 1626 return (B_FALSE); 1627 } 1628 1629 /* parameter found - compare against given value */ 1630 1631 answer = strcasecmp(str, rparm); 1632 1633 /* free up parameter storage */ 1634 1635 free(rparm); 1636 1637 /* return results of comparison */ 1638 1639 return (answer == 0 ? B_TRUE : B_FALSE); 1640 } 1641 1642 /* 1643 * Name: smlFindAndDelTag 1644 * Description: Delete a tag if found in tag object 1645 * Arguments: tag - [RO, *RW] - (SML_TAG *) 1646 * The tag object to delete the tag from 1647 * findTag - [RO, *RO] - (char *) 1648 * Tag within tag object to delete 1649 * Returns: boolean_t 1650 * B_TRUE - tag found and deleted 1651 * B_FALSE - tag not found 1652 */ 1653 1654 boolean_t 1655 smlFindAndDelTag(SML_TAG *tag, char *findTag) 1656 { 1657 SML_TAG *rtag = SML_TAG__NULL; 1658 1659 /* entry assertions */ 1660 1661 assert(SML_TAG__ISVALID(tag)); 1662 assert(findTag != (char *)NULL); 1663 assert(*findTag != '\0'); 1664 1665 /* find the specified tag - if not found, return false */ 1666 1667 rtag = smlGetTagByName(tag, 0, findTag); 1668 if (rtag == SML_TAG__NULL) { 1669 return (B_FALSE); 1670 } 1671 1672 /* tag found - delete it and return true */ 1673 1674 smlDelTag(tag, rtag); 1675 1676 return (B_TRUE); 1677 } 1678 1679 /* 1680 * Name: smlDup 1681 * Description: Duplicate a tag object 1682 * Arguments: tag - [RO, *RO] - (SML_TAG *) 1683 * The tag object to duplicate 1684 * Returns: SML_TAG * 1685 * A handle to a complete duplicate of the tag provided 1686 * NOTE: Any tag object returned is placed in new storage for the 1687 * calling method. The caller must use 'smlFreeTag' to dispose 1688 * of the storage once the tag object name is no longer needed. 1689 * Errors: If the tag object cannot be duplicated, the process exits 1690 */ 1691 1692 SML_TAG * 1693 smlDup(SML_TAG *tag) 1694 { 1695 SML_TAG *rtag = SML_TAG__NULL; 1696 int i; 1697 1698 /* entry assertions */ 1699 1700 assert(SML_TAG__ISVALID(tag)); 1701 1702 /* allocate zeroed storage for the tag object */ 1703 1704 rtag = (SML_TAG *)calloc(1, sizeof (SML_TAG)); 1705 assert(rtag != SML_TAG__NULL); 1706 1707 /* duplicate all parameters of the tag */ 1708 1709 rtag->name = (tag->name ? strdup(tag->name) : (char *)NULL); 1710 rtag->params_num = tag->params_num; 1711 if (tag->params != (SML_PARAM *)NULL) { 1712 rtag->params = (SML_PARAM *) 1713 calloc(1, sizeof (SML_PARAM)*rtag->params_num); 1714 bzero(rtag->params, sizeof (SML_PARAM)*rtag->params_num); 1715 for (i = 0; i < rtag->params_num; i++) { 1716 rtag->params[i].name = tag->params[i].name ? 1717 strdup(tag->params[i].name) : 1718 (char *)NULL; 1719 rtag->params[i].value = tag->params[i].value ? 1720 strdup(tag->params[i].value) : 1721 (char *)NULL; 1722 } 1723 } 1724 1725 /* duplicate all elements of the tag */ 1726 1727 rtag->tags_num = tag->tags_num; 1728 1729 if (tag->tags != SML_TAG__NULL) { 1730 rtag->tags = (SML_TAG *) 1731 calloc(1, sizeof (SML_TAG)*rtag->tags_num); 1732 bzero(rtag->tags, sizeof (SML_TAG)*rtag->tags_num); 1733 for (i = 0; i < rtag->tags_num; i++) { 1734 SML_TAG *stag; 1735 stag = smlDup(&tag->tags[i]); 1736 (void) memcpy(&rtag->tags[i], stag, 1737 sizeof (SML_TAG)); 1738 free(stag); 1739 } 1740 } 1741 1742 /* exit assertions */ 1743 1744 assert(SML_TAG__ISVALID(rtag)); 1745 1746 /* return */ 1747 1748 return (rtag); 1749 } 1750 1751 /* 1752 * Name: smlSetFileStatInfo 1753 * Description; Given a file status structure and path name, encode the 1754 * structure and place it and the name into the specified tag 1755 * in a "_sml_fileStatInfoTag" (private) element 1756 * Arguments: tag - [RO, *RO] - (SML_TAG *) 1757 * The tag object to deposit the information into 1758 * statbuf - [RO, *RO] - (struct stat *) 1759 * Pointer to file status structure to encode 1760 * path - [RO, *RO] - (char *) 1761 * Pointer to path name of file to encode 1762 * Returns: void 1763 * The information is placed into the specified tag object 1764 */ 1765 1766 void 1767 smlSetFileStatInfo(SML_TAG **tag, struct stat *statbuf, char *path) 1768 { 1769 SML_TAG *rtag; 1770 1771 /* entry assertions */ 1772 1773 assert(SML_TAG__R_ISVALID(tag)); 1774 assert(SML_TAG__ISVALID(*tag)); 1775 assert(statbuf != (struct stat *)NULL); 1776 1777 /* if stat info exists, delete it */ 1778 1779 (void) smlFindAndDelTag(*tag, _sml_fileStatInfoTag); 1780 1781 /* create the file stat info inside of the top level tag */ 1782 1783 assert(smlGetTagByName(*tag, 0, _sml_fileStatInfoTag) 1784 == SML_TAG__NULL); 1785 rtag = smlNewTag(_sml_fileStatInfoTag); 1786 assert(SML_TAG__ISVALID(rtag)); 1787 (void) smlAddTag(tag, 0, rtag); 1788 free(rtag); 1789 1790 /* obtain handle on newly created file stat info tag */ 1791 1792 rtag = smlGetTagByName(*tag, 0, _sml_fileStatInfoTag); 1793 assert(SML_TAG__ISVALID(rtag)); 1794 1795 /* add file info as parameters to the tag */ 1796 1797 if (path != (char *)NULL) { 1798 smlSetParam(rtag, "st_path", path); 1799 } 1800 1801 smlSetParamF(rtag, "st_ino", "0x%llx", 1802 (unsigned long long)statbuf->st_ino); 1803 smlSetParamF(rtag, "st_mode", "0x%llx", 1804 (unsigned long long)statbuf->st_mode); 1805 smlSetParamF(rtag, "st_mtime", "0x%llx", 1806 (unsigned long long)statbuf->st_mtime); 1807 smlSetParamF(rtag, "st_ctime", "0x%llx", 1808 (unsigned long long)statbuf->st_ctime); 1809 smlSetParamF(rtag, "st_size", "0x%llx", 1810 (unsigned long long)statbuf->st_size); 1811 } 1812 1813 /* 1814 * Name: smlFstatCompareEQ 1815 * Description: Given a file status structure and path name, look for the 1816 * information placed into a tag object via smlSetFileStatInfo 1817 * and if present compare the encoded information with the 1818 * arguments provided 1819 * Arguments: statbuf - [RO, *RO] - (struct stat *) 1820 * Pointer to file status structure to compare 1821 * tag - [RO, *RO] - (SML_TAG *) 1822 * The tag object to compare against 1823 * path - [RO, *RO] - (char *) 1824 * Pointer to path name of file to compare 1825 * Returns: boolean_t 1826 * B_TRUE - both status structures are identical 1827 * B_FALSE - the status structures are not equal 1828 */ 1829 1830 boolean_t 1831 smlFstatCompareEq(struct stat *statbuf, SML_TAG *tag, char *path) 1832 { 1833 if (tag == SML_TAG__NULL) { 1834 return (B_FALSE); 1835 } 1836 1837 assert(SML_TAG__ISVALID(tag)); 1838 1839 if (statbuf == (struct stat *)NULL) { 1840 return (B_FALSE); 1841 } 1842 1843 if (path != (char *)NULL) { 1844 if (smlParamEq(tag, 1845 _sml_fileStatInfoTag, "st_path", path) != B_TRUE) { 1846 return (B_FALSE); 1847 } 1848 } 1849 1850 if (smlParamEqF(tag, _sml_fileStatInfoTag, "st_ino", 1851 "0x%llx", (unsigned long long)statbuf->st_ino) != B_TRUE) { 1852 return (B_FALSE); 1853 } 1854 1855 if (smlParamEqF(tag, _sml_fileStatInfoTag, "st_mode", 1856 "0x%llx", (unsigned long long)statbuf->st_mode) != B_TRUE) { 1857 return (B_FALSE); 1858 } 1859 1860 if (smlParamEqF(tag, _sml_fileStatInfoTag, "st_mtime", 1861 "0x%llx", (unsigned long long)statbuf->st_mtime) != B_TRUE) { 1862 return (B_FALSE); 1863 } 1864 1865 if (smlParamEqF(tag, _sml_fileStatInfoTag, "st_ctime", 1866 "0x%llx", (unsigned long long)statbuf->st_ctime) != B_TRUE) { 1867 return (B_FALSE); 1868 } 1869 1870 if (smlParamEqF(tag, _sml_fileStatInfoTag, "st_size", 1871 "0x%llx", (unsigned long long)statbuf->st_size) != B_TRUE) { 1872 return (B_FALSE); 1873 } 1874 1875 return (B_TRUE); 1876 } 1877 1878 /* 1879 * Name: set_verbose 1880 * Description: Turns on verbose output 1881 * Scope: public 1882 * Arguments: verbose = B_TRUE indicates verbose mode 1883 * Returns: none 1884 */ 1885 void 1886 smlSetVerbose(boolean_t setting) 1887 { 1888 verbose = setting; 1889 } 1890 1891 /* 1892 * Name: get_verbose 1893 * Description: Returns whether or not to output verbose messages 1894 * Scope: public 1895 * Arguments: none 1896 * Returns: B_TRUE - verbose messages should be output 1897 */ 1898 boolean_t 1899 smlGetVerbose() 1900 { 1901 return (verbose); 1902 } 1903 1904 /* 1905 * Name: sml_strPrintf 1906 * Synopsis: Create string from printf style format and arguments 1907 * Description: Call to convert a printf style format and arguments into a 1908 * string of characters placed in allocated storage 1909 * Arguments: format - [RO, RO*] (char *) 1910 * printf-style format for string to be formatted 1911 * ... - [RO] (?) 1912 * arguments as appropriate to 'format' specified 1913 * Returns: char * 1914 * A string representing the printf conversion results 1915 * NOTE: Any string returned is placed in new storage for the 1916 * calling method. The caller must use 'free' to dispose 1917 * of the storage once the string is no longer needed. 1918 * Errors: If the string cannot be created, the process exits 1919 */ 1920 1921 /*PRINTFLIKE1*/ 1922 char * 1923 sml_strPrintf(char *a_format, ...) 1924 { 1925 va_list ap; 1926 size_t vres = 0; 1927 char bfr[1]; 1928 char *rstr = (char *)NULL; 1929 1930 /* entry assertions */ 1931 1932 assert(a_format != (char *)NULL); 1933 assert(*a_format != '\0'); 1934 1935 /* determine size of the message in bytes */ 1936 1937 va_start(ap, a_format); 1938 vres = vsnprintf(bfr, 1, a_format, ap); 1939 va_end(ap); 1940 1941 assert(vres > 0); 1942 1943 /* allocate storage to hold the message */ 1944 1945 rstr = (char *)calloc(1, vres+2); 1946 assert(rstr != (char *)NULL); 1947 1948 /* generate the results of the printf conversion */ 1949 1950 va_start(ap, a_format); 1951 vres = vsnprintf(rstr, vres+1, a_format, ap); 1952 va_end(ap); 1953 1954 assert(vres > 0); 1955 assert(*rstr != '\0'); 1956 1957 /* return the results */ 1958 1959 return (rstr); 1960 } 1961 1962 /* 1963 * Name: sml_strPrintf_r 1964 * Synopsis: Create string from printf style format and arguments 1965 * Description: Call to convert a printf style format and arguments into a 1966 * string of characters placed in allocated storage 1967 * Arguments: a_buf - [RO, *RW] - (char *) 1968 * - Pointer to buffer used as storage space for the 1969 * returned string created 1970 * a_bufLen - [RO, *RO] - (int) 1971 * - Size of 'a_buf' in bytes - a maximum of 'a_bufLen-1' 1972 * bytes will be placed in 'a_buf' - the returned 1973 * string is always null terminated 1974 * a_format - [RO, RO*] (char *) 1975 * printf-style format for string to be formatted 1976 * VARG_LIST - [RO] (?) 1977 * arguments as appropriate to 'format' specified 1978 * Returns: void 1979 */ 1980 1981 /*PRINTFLIKE3*/ 1982 void 1983 sml_strPrintf_r(char *a_buf, int a_bufLen, char *a_format, ...) 1984 { 1985 va_list ap; 1986 size_t vres = 0; 1987 1988 /* entry assertions */ 1989 1990 assert(a_format != (char *)NULL); 1991 assert(*a_format != '\0'); 1992 assert(a_buf != (char *)NULL); 1993 assert(a_bufLen > 1); 1994 1995 /* generate the results of the printf conversion */ 1996 1997 va_start(ap, a_format); 1998 vres = vsnprintf(a_buf, a_bufLen-1, a_format, ap); 1999 va_end(ap); 2000 2001 assert(vres > 0); 2002 assert(vres < a_bufLen); 2003 2004 a_buf[a_bufLen-1] = '\0'; 2005 } 2006 2007 /* 2008 * Name: sml_XmlEncodeString 2009 * Description: Given a plain text string, convert that string into one that 2010 * encoded using the XML character reference encoding format. 2011 * Arguments: a_plain_text_string - [RO, *RO] (char *) 2012 * The plain text string to convert (encode) 2013 * Returns: char * 2014 * The encoded form of the plain text string provided 2015 * NOTE: Any string returned is placed in new storage for the 2016 * calling method. The caller must use 'lu_memFree' to dispose 2017 * of the storage once the string is no longer needed. 2018 */ 2019 2020 char * 2021 sml_XmlEncodeString(char *a_plainTextString) 2022 { 2023 char *stringHead; /* -> start of string containing encoded data */ 2024 long stringTail; /* byte pos of first free byte in stringHead */ 2025 long stringLength; /* total bytes allocd starting at stringHead */ 2026 char *p; /* temp -> to retrieve bytes from src string */ 2027 long textLength = 0; /* length of the string to convert */ 2028 2029 /* entry assertions */ 2030 2031 assert(a_plainTextString != (char *)NULL); 2032 2033 textLength = strlen(a_plainTextString); 2034 2035 /* Allocate initial string buffer to hold results */ 2036 2037 stringLength = textLength*2; 2038 stringTail = 0; 2039 stringHead = (char *)calloc(1, (size_t)stringLength+2); 2040 assert(stringHead != (char *)NULL); 2041 2042 /* Add in the encoded message text */ 2043 2044 for (p = a_plainTextString; textLength > 0; p++, textLength--) { 2045 /* 2046 * Must have at least 12 bytes: this must be at least the 2047 * maximum number of bytes that can be added for a single 2048 * byte as the last byte of the stream. Assuming the byte 2049 * needs to be encoded, it could be: 2050 * &#xxxxxxxx;\0 2051 * If not that many bytes left, grow the buffer. 2052 */ 2053 2054 if ((stringLength-stringTail) < 12) { 2055 stringLength += (textLength*2)+12; 2056 stringHead = 2057 realloc(stringHead, 2058 (size_t)stringLength+2); 2059 assert(stringHead != (char *)NULL); 2060 } 2061 2062 /* 2063 * See if this byte is a 'printable 7-bit ascii value'. 2064 * If so just add it to the new string; otherwise, must 2065 * output an XML character value encoding for the byte. 2066 */ 2067 2068 switch (*p) { 2069 case '!': 2070 case '#': 2071 case '%': 2072 case '\'': 2073 case '(': 2074 case ')': 2075 case '*': 2076 case '+': 2077 case ',': 2078 case '-': 2079 case '.': 2080 case '/': 2081 case '0': 2082 case '1': 2083 case '2': 2084 case '3': 2085 case '4': 2086 case '5': 2087 case '6': 2088 case '7': 2089 case '8': 2090 case '9': 2091 case ':': 2092 case ';': 2093 case '<': 2094 case '=': 2095 case '>': 2096 case '?': 2097 case '@': 2098 case 'A': 2099 case 'B': 2100 case 'C': 2101 case 'D': 2102 case 'E': 2103 case 'F': 2104 case 'G': 2105 case 'H': 2106 case 'I': 2107 case 'J': 2108 case 'K': 2109 case 'L': 2110 case 'M': 2111 case 'N': 2112 case 'O': 2113 case 'P': 2114 case 'Q': 2115 case 'R': 2116 case 'S': 2117 case 'T': 2118 case 'U': 2119 case 'V': 2120 case 'W': 2121 case 'X': 2122 case 'Y': 2123 case 'Z': 2124 case '[': 2125 case ']': 2126 case '^': 2127 case '_': 2128 case 'a': 2129 case 'b': 2130 case 'c': 2131 case 'd': 2132 case 'e': 2133 case 'f': 2134 case 'g': 2135 case 'h': 2136 case 'i': 2137 case 'j': 2138 case 'k': 2139 case 'l': 2140 case 'm': 2141 case 'n': 2142 case 'o': 2143 case 'p': 2144 case 'q': 2145 case 'r': 2146 case 's': 2147 case 't': 2148 case 'u': 2149 case 'v': 2150 case 'w': 2151 case 'x': 2152 case 'y': 2153 case 'z': 2154 case '{': 2155 case '|': 2156 case '}': 2157 case '~': 2158 case ' ': 2159 /* 2160 * It is a printable 7-bit ascii character: 2161 * just add it to the end of the new string. 2162 */ 2163 2164 stringHead[stringTail++] = *p; 2165 break; 2166 default: 2167 /* 2168 * It is not a printable 7-bit ascii character: 2169 * add it as an xml character value encoding. 2170 */ 2171 2172 stringTail += sprintf(&stringHead[stringTail], "&#%x;", 2173 (*p)&0xFF); 2174 break; 2175 } 2176 } 2177 2178 /* Terminate the new string */ 2179 2180 stringHead[stringTail] = '\0'; 2181 2182 /* realloc the string so it is only as big as it needs to be */ 2183 2184 stringHead = realloc(stringHead, stringTail+1); 2185 assert(stringHead != (char *)NULL); 2186 2187 return (stringHead); 2188 } 2189 2190 /* 2191 * Name: sml_XmlDecodeString 2192 * Description: Given a string encoded using the XML character reference format, 2193 * convert that string into a plain text (unencoded) string. 2194 * Arguments: a_xml_encoded_string - [RO, *RO] (char *) 2195 * The XML encoded string to convert to plain text 2196 * Returns: char * 2197 * The unencoded (plain text) form of the encoded string 2198 * NOTE: Any string returned is placed in new storage for the 2199 * calling method. The caller must use 'lu_memFree' to dispose 2200 * of the storage once the string is no longer needed. 2201 */ 2202 2203 char * 2204 sml_XmlDecodeString(char *a_xmlEncodedString) 2205 { 2206 char *s = NULL; /* -> index into encoded bytes string */ 2207 char *d = NULL; /* -> index into decoded bytes string */ 2208 char *rs = NULL; /* -> string holding ref bytes allocated */ 2209 char *ri = NULL; /* -> index into string holding reference */ 2210 long textLength = 0; /* length of encoded string to decode */ 2211 unsigned long rv = 0; /* temp to hold scanf results of byte conv */ 2212 char *i = NULL; /* temp to hold strchr results */ 2213 char *stringHead = NULL; /* -> plain test buffer */ 2214 ptrdiff_t tmpdiff; 2215 2216 /* 2217 * A finite state machine is used to convert the xml encoded string 2218 * into plain text. The states of the machine are defined below. 2219 */ 2220 2221 int fsmsState = -1; /* Finite state machine state */ 2222 #define fsms_text 0 /* Decoding plain text */ 2223 #define fsms_seenAmp 1 /* Found & */ 2224 #define fsms_seenPound 2 /* Found # following & */ 2225 #define fsms_collect 3 /* Collecting character reference bytes */ 2226 2227 /* entry assertions */ 2228 2229 assert(a_xmlEncodedString != (char *)NULL); 2230 2231 textLength = strlen(a_xmlEncodedString); 2232 2233 /* 2234 * Allocate string that can contain the decoded string. 2235 * Since decoding always results in a shorter string (bytes encoded 2236 * using the XML character reference are larger in the encoded form) 2237 * we can allocate a string the same size as the encoded string. 2238 */ 2239 2240 stringHead = (char *)calloc(1, textLength+1); 2241 assert(stringHead != (char *)NULL); 2242 2243 /* 2244 * Convert all bytes. 2245 */ 2246 2247 /* Decoding plain text */ 2248 fsmsState = fsms_text; 2249 2250 for (s = a_xmlEncodedString, d = stringHead; textLength > 0; 2251 s++, textLength--) { 2252 switch (fsmsState) { 2253 case fsms_text: /* Decoding plain text */ 2254 if (rs != NULL) { 2255 free(rs); 2256 rs = NULL; 2257 ri = NULL; 2258 } 2259 if (*s == '&') { 2260 /* Found & */ 2261 fsmsState = fsms_seenAmp; 2262 continue; 2263 } 2264 *d++ = *s; 2265 continue; 2266 2267 case fsms_seenAmp: /* Found & */ 2268 if (*s == '#') { 2269 /* Found # following & */ 2270 fsmsState = fsms_seenPound; 2271 continue; 2272 } 2273 fsmsState = fsms_text; /* Decoding plain text */ 2274 *d++ = '&'; 2275 *d++ = *s; 2276 continue; 2277 2278 case fsms_seenPound: /* Found # following & */ 2279 i = strchr(s, ';'); 2280 if (i == NULL) { 2281 /* Decoding plain text */ 2282 fsmsState = fsms_text; 2283 *d++ = '&'; 2284 *d++ = '#'; 2285 *d++ = *s; 2286 continue; 2287 } 2288 tmpdiff = (ptrdiff_t)i - (ptrdiff_t)s; 2289 rs = (char *)calloc(1, tmpdiff + 1); 2290 assert(rs != (char *)NULL); 2291 ri = rs; 2292 /* Collecting character reference bytes */ 2293 fsmsState = fsms_collect; 2294 2295 /*FALLTHRU*/ 2296 2297 /* Collecting character reference bytes */ 2298 case fsms_collect: 2299 if (*s != ';') { 2300 switch (*s) { 2301 case '0': 2302 case '1': 2303 case '2': 2304 case '3': 2305 case '4': 2306 case '5': 2307 case '6': 2308 case '7': 2309 case '8': 2310 case '9': 2311 case 'a': 2312 case 'b': 2313 case 'c': 2314 case 'd': 2315 case 'e': 2316 case 'f': 2317 case 'A': 2318 case 'B': 2319 case 'C': 2320 case 'D': 2321 case 'E': 2322 case 'F': 2323 *ri++ = *s; 2324 break; 2325 default: 2326 *ri = '\0'; 2327 *d++ = '&'; 2328 *d++ = '#'; 2329 tmpdiff = (ptrdiff_t)ri - (ptrdiff_t)rs; 2330 (void) strncpy(d, rs, tmpdiff-1); 2331 *d++ = *s; 2332 /* Decoding plain text */ 2333 fsmsState = fsms_text; 2334 break; 2335 } 2336 continue; 2337 } 2338 *ri = '\0'; 2339 if (sscanf(rs, "%lx", &rv) != 1) { 2340 *d++ = '?'; 2341 } else { 2342 *d++ = (rv & 0xFF); 2343 } 2344 /* Decoding plain text */ 2345 fsmsState = fsms_text; 2346 } 2347 } 2348 2349 /* Done converting bytes - deallocate reference byte storage */ 2350 2351 free(rs); 2352 2353 /* terminate the converted (plain text) string */ 2354 2355 *d = '\0'; 2356 2357 /* exit assertions */ 2358 2359 assert(stringHead != (char *)NULL); 2360 2361 return (stringHead); 2362 } 2363 2364 /* 2365 * Private Methods 2366 */ 2367 2368 /* 2369 * Name: _smlReadTag 2370 * Description: read complete tag from a datastream 2371 * Arguments: err - [RO, *RW] (LU_ERR) 2372 * Error object - used to contain any errors encountered 2373 * and return those errors to this methods caller 2374 * r_tag - [RW, *RW] - (SML_TAG **) 2375 * Pointer to handle to place new tag object 2376 * == SML_TAG__NULL if empty tag found (not an error) 2377 * ds - [RO, *RO] - (LU_DS) 2378 * Handle to datastream to read tag from 2379 * parent - [RO, *RO] - (char *) 2380 * Name for parent of tag (NONE if top of tag) 2381 * Returns: int 2382 * RESULT_OK - tag successfully read 2383 * RESULT_ERR - problem reading tag 2384 * NOTE: Any tag object returned is placed in new storage for the 2385 * calling method. The caller must use 'smlFreeTag' to dispose 2386 * of the storage once the tag object name is no longer needed. 2387 * Errors: If the tag object cannot be duplicated, the process exits 2388 */ 2389 2390 static int 2391 _smlReadTag(SML_TAG **r_tag, char **a_str, char *parent) 2392 { 2393 int r; 2394 SML_TAG *tag; 2395 SML_TAG *tmp_tag; 2396 char name[MAX_SML_COMPONENT_LENGTH]; 2397 int pos = 0; 2398 int c; 2399 char *p = *a_str; 2400 2401 /* entry assertions */ 2402 2403 assert(SML_TAG__R_ISVALID(r_tag)); 2404 assert(a_str != (char **)NULL); 2405 2406 /* entry debugging info */ 2407 2408 _smlLogMsg(LOG_MSG_DEBUG, DBG_SML_READ_TAG, 2409 parent ? parent : "<<TOP TAG>>"); 2410 2411 /* reset return tag */ 2412 2413 *r_tag = SML_TAG__NULL; 2414 2415 /* allocate zeroed storage for the tag object */ 2416 2417 tag = (SML_TAG *)calloc(1, sizeof (SML_TAG)); 2418 assert(tag != SML_TAG__NULL); 2419 2420 /* reset name accumulator storage */ 2421 2422 bzero(name, sizeof (name)); 2423 2424 /* ignore delimters before tag */ 2425 2426 for (;;) { 2427 /* read tag character - handle failure/EOF */ 2428 2429 if ((*p == '\0') || ((c = (*p++)) == '\0')) { 2430 if (parent == NULL) { 2431 _smlLogMsg(LOG_MSG_DEBUG, 2432 DBG_SML_READTAG_EXPECTED_EOF, 2433 p ? p : "?"); 2434 smlFreeTag(tag); 2435 *a_str = p; 2436 return (RESULT_OK); 2437 } 2438 2439 /* EOF in middle of processing tag */ 2440 2441 _smlLogMsg(LOG_MSG_ERR, 2442 DBG_SML_READTAG_UNEXPECTED_EOF, 2443 p ? p : "?"); 2444 smlFreeTag(tag); 2445 *a_str = p; 2446 return (RESULT_ERR); 2447 } 2448 2449 /* if beginning of tag, break out */ 2450 2451 if (c == '<') { 2452 break; 2453 } 2454 2455 /* not tag beginning: ignore delimiters if not inside tag yet */ 2456 2457 if (parent == (char *)NULL) { 2458 /* ignore delimters */ 2459 2460 if (strchr(" \t", c) != (char *)NULL) { 2461 continue; 2462 } 2463 2464 /* on blank lines, return no tag object */ 2465 2466 if (c == '\n') { 2467 _smlLogMsg(LOG_MSG_DEBUG, 2468 DBG_SML_READTAG_BLANKLINE, 2469 p ? p : "?"); 2470 smlFreeTag(tag); 2471 *a_str = p; 2472 return (RESULT_OK); 2473 } 2474 2475 /* invalid character before tag start */ 2476 2477 _smlLogMsg(LOG_MSG_ERR, ERR_SML_READTAG_BAD_START_CHAR, 2478 c, (unsigned int)c); 2479 *a_str = p; 2480 return (RESULT_ERR); 2481 } 2482 } 2483 2484 /* 2485 * all delimiters have been ignored and opening tag character seen; 2486 * process tag 2487 */ 2488 2489 assert(c == '<'); 2490 2491 c = *p; 2492 if (*p != '\0') { 2493 p++; 2494 } 2495 2496 /* handle EOF after tag opening character found */ 2497 2498 if (c == '\0') { 2499 _smlLogMsg(LOG_MSG_ERR, 2500 ERR_SML_EOF_BEFORE_TAG_NAME, 2501 parent ? parent : "<<NONE>>"); 2502 smlFreeTag(tag); 2503 *a_str = p; 2504 return (RESULT_ERR); 2505 } 2506 2507 /* is this a tag closure? */ 2508 2509 if (c == '/') { 2510 _smlLogMsg(LOG_MSG_DEBUG, DBG_SML_START_CLOSE_TAG, 2511 parent ? parent : "<<NONE>>"); 2512 2513 for (;;) { 2514 /* get next character of tag name */ 2515 2516 c = *p; 2517 if (*p != '\0') { 2518 p++; 2519 } 2520 2521 /* EOF inside tag name? */ 2522 2523 if (c == '\0') { 2524 _smlLogMsg(LOG_MSG_ERR, 2525 ERR_SML_READTAG_CLOSE_TAG_EOF, 2526 parent ? parent : "<<NONE>>"); 2527 smlFreeTag(tag); 2528 *a_str = p; 2529 return (RESULT_ERR); 2530 } 2531 2532 /* tag close: break out of collection loop */ 2533 2534 if (c == '>') { 2535 break; 2536 } 2537 2538 /* see if illegal character in tag name */ 2539 2540 /* CSTYLED */ 2541 if (strchr("/ \t\n\":<?$'\\`!@#%^&*()+=|[]{};,", c) 2542 != NULL) { 2543 _smlLogMsg(LOG_MSG_ERR, 2544 ERR_SML_READTAG_CLOSE_TAG_ILLCHAR, 2545 c, (unsigned int)c, name); 2546 smlFreeTag(tag); 2547 *a_str = p; 2548 return (RESULT_ERR); 2549 } 2550 2551 /* valid character - add to name if room left */ 2552 2553 if (pos < sizeof (name)-1) { 2554 name[pos] = (c&0xFF); 2555 pos++; 2556 } 2557 2558 assert(pos < sizeof (name)); 2559 } 2560 2561 /* close of tag found */ 2562 2563 assert(c == '>'); 2564 2565 /* is the tag empty? If so that's an error */ 2566 2567 if (*name == '\0') { 2568 _smlLogMsg(LOG_MSG_ERR, 2569 ERR_SML_READTAG_CLOSE_EMPTY_TAG); 2570 smlFreeTag(tag); 2571 *a_str = p; 2572 return (RESULT_ERR); 2573 } 2574 2575 /* if no parent, a close tag outside of any open tag */ 2576 2577 if (parent == (char *)NULL) { 2578 _smlLogMsg(LOG_MSG_ERR, 2579 ERR_SML_READTAG_CLOSE_NO_PARENT, 2580 name); 2581 smlFreeTag(tag); 2582 *a_str = p; 2583 return (RESULT_ERR); 2584 } 2585 2586 /* if not close to current parent, error */ 2587 2588 if (!streq(parent, name)) { 2589 _smlLogMsg(LOG_MSG_ERR, 2590 ERR_SML_READTAG_CLOSE_WRONG_TAG, 2591 name, parent); 2592 smlFreeTag(tag); 2593 *a_str = p; 2594 return (RESULT_ERR); 2595 } 2596 2597 /* close of current tag found - success */ 2598 2599 _smlLogMsg(LOG_MSG_DEBUG, DBG_SML_READTAG_CLOSE_TAG, 2600 name); 2601 smlFreeTag(tag); 2602 *a_str = p; 2603 return (RESULT_OK); 2604 } 2605 2606 /* not starting a close tag */ 2607 2608 assert(c != '/'); 2609 assert(c != '<'); 2610 2611 /* at start of tag - input tag name */ 2612 2613 bzero(name, sizeof (name)); 2614 pos = 0; 2615 2616 for (;;) { 2617 2618 /* EOF inside of tag name? */ 2619 2620 if (c == '\0') { 2621 _smlLogMsg(LOG_MSG_ERR, 2622 ERR_SML_READTAG_TAG_EOF, 2623 name, parent ? parent : "<<NONE>>"); 2624 smlFreeTag(tag); 2625 *a_str = p; 2626 return (RESULT_ERR); 2627 } 2628 2629 /* if separator or end of line then tag name collected */ 2630 2631 if (strchr(" >\t\n", c) != NULL) { 2632 break; 2633 } 2634 2635 /* see if illegal character in tag name */ 2636 2637 /*CSTYLED*/ 2638 if (strchr("\":<>?$'\\`!@#%^&*()+=|[]{};,", c) != NULL) { 2639 _smlLogMsg(LOG_MSG_ERR, 2640 ERR_SML_READTAG_TAG_ILLCHAR, 2641 c, (unsigned int)c, name); 2642 smlFreeTag(tag); 2643 *a_str = p; 2644 return (RESULT_ERR); 2645 } 2646 2647 /* close current tag? */ 2648 2649 if (c == '/') { 2650 /* get next character of tag name */ 2651 2652 c = *p; 2653 if (*p != '\0') { 2654 p++; 2655 } 2656 2657 /* tag close not found? */ 2658 2659 if (c != '>') { 2660 _smlLogMsg(LOG_MSG_ERR, 2661 ERR_SML_READTAG_BADTAG_CLOSE, 2662 name, parent ? parent : "<<NONE>>"); 2663 smlFreeTag(tag); 2664 *a_str = p; 2665 return (RESULT_ERR); 2666 } 2667 2668 /* is the tag empty? If so that's an error */ 2669 2670 if (*name == '\0') { 2671 _smlLogMsg(LOG_MSG_ERR, 2672 ERR_SML_READTAG_EMPTY_TAG, 2673 parent ? parent : "<<NONE>>"); 2674 smlFreeTag(tag); 2675 *a_str = p; 2676 return (RESULT_ERR); 2677 } 2678 2679 /* tag closed */ 2680 2681 _smlLogMsg(LOG_MSG_DEBUG, 2682 DBG_SML_READTAG_CLOSED_TAG, 2683 name, parent ? parent : "<<NONE>>"); 2684 2685 tag->name = strdup(name); 2686 *r_tag = tag; 2687 *a_str = p; 2688 return (RESULT_OK); 2689 } 2690 2691 /* valid character - add to name if room left */ 2692 2693 if (pos < sizeof (name)-1) { 2694 name[pos] = (c&0xFF); 2695 pos++; 2696 } 2697 2698 assert(pos < sizeof (name)); 2699 2700 /* get next character to parse */ 2701 2702 c = *p; 2703 if (*p != '\0') { 2704 p++; 2705 } 2706 } 2707 2708 /* have a valid tag name: <tagname */ 2709 2710 _smlLogMsg(LOG_MSG_DEBUG, DBG_SML_HAVE_TAG_NAME, 2711 name, parent ? parent : "<<NONE>>"); 2712 2713 assert(*name != '\0'); 2714 2715 /* place tag name inside of tag object */ 2716 2717 tag->name = strdup(name); 2718 2719 /* clear out name accumulator to get parameters */ 2720 2721 bzero(name, sizeof (name)); 2722 pos = 0; 2723 2724 /* input parameters */ 2725 2726 if (c != '>') 2727 for (;;) { 2728 2729 char *pname; 2730 char *pvalue; 2731 SML_PARAM *parameter; 2732 2733 /* pass spaces before parameter name */ 2734 2735 for (;;) { 2736 2737 /* get next character of parameter name */ 2738 2739 c = *p; 2740 if (*p != '\0') { 2741 p++; 2742 } 2743 2744 /* EOF inside parameter name? */ 2745 2746 if (c == '\0') { 2747 _smlLogMsg(LOG_MSG_ERR, 2748 ERR_SML_READTAG_PARM_EOF, 2749 tag->name, 2750 parent ? parent : "<<NONE>>"); 2751 smlFreeTag(tag); 2752 *a_str = p; 2753 return (RESULT_ERR); 2754 } 2755 2756 /* if separator/end of line tag parameter collected */ 2757 2758 if (strchr(" \t\n", c) != NULL) { 2759 continue; 2760 } 2761 2762 /* see if illegal character in parameter name */ 2763 2764 /*CSTYLED*/ 2765 if (strchr("\":<?$'\\`!@#%^&*()+=|[]{};,.", c) != 2766 (char *)NULL) { 2767 _smlLogMsg(LOG_MSG_ERR, 2768 ERR_SML_READTAG_PARMNAME_ILLCHAR, 2769 c, (unsigned int)c, name, tag->name, 2770 parent ? parent : "<<NONE>>"); 2771 smlFreeTag(tag); 2772 *a_str = p; 2773 return (RESULT_ERR); 2774 } 2775 2776 /* tag close found? */ 2777 2778 if (c == '>') { 2779 break; 2780 } 2781 2782 /* close tag found ? */ 2783 2784 if (c == '/') { 2785 c = *p; 2786 if (*p != '\0') { 2787 p++; 2788 } 2789 if (c == '>') { 2790 _smlLogMsg(LOG_MSG_DEBUG, 2791 DBG_SML_TAG_ONLY, 2792 tag->name); 2793 *r_tag = tag; 2794 *a_str = p; 2795 return (RESULT_OK); 2796 } 2797 2798 /* / not followed by > */ 2799 _smlLogMsg(LOG_MSG_ERR, 2800 ERR_SML_READTAG_BADPARMNAME_CLOSE, 2801 name, tag->name, 2802 parent ? parent : "<<NONE>>"); 2803 smlFreeTag(tag); 2804 *a_str = p; 2805 return (RESULT_ERR); 2806 } 2807 2808 /* valid character - add to name if room left */ 2809 2810 if (pos < sizeof (name)-1) { 2811 name[pos] = (c&0xFF); 2812 pos++; 2813 } 2814 2815 assert(pos < sizeof (name)); 2816 break; 2817 } 2818 2819 if (c == '>') { 2820 break; 2821 } 2822 2823 /* input parameter name */ 2824 2825 for (;;) { 2826 c = *p; 2827 if (*p != '\0') { 2828 p++; 2829 } 2830 2831 /* EOF inside of parameter name? */ 2832 2833 if (c == '\0') { 2834 _smlLogMsg(LOG_MSG_ERR, 2835 ERR_SML_READTAG_PARM_EOF, 2836 tag->name, 2837 parent ? parent : "<<NONE>>"); 2838 smlFreeTag(tag); 2839 *a_str = p; 2840 return (RESULT_ERR); 2841 } 2842 2843 /*CSTYLED*/ 2844 if (strchr("\t \n\":<>?$'\\`!@%^*()+|[]{},./", c) != NULL) { 2845 _smlLogMsg(LOG_MSG_ERR, 2846 ERR_SML_READTAG_PARMNAME_ILLCHAR, 2847 c, (unsigned int)c, name, tag->name, 2848 parent ? parent : "<<NONE>>"); 2849 smlFreeTag(tag); 2850 *a_str = p; 2851 return (RESULT_ERR); 2852 } 2853 2854 /* name - value separator found ? */ 2855 2856 if (c == '=') { 2857 break; 2858 } 2859 2860 /* valid character - add to name if room left */ 2861 2862 if (pos < sizeof (name)-1) { 2863 name[pos] = (c&0xFF); 2864 pos++; 2865 } 2866 2867 assert(pos < sizeof (name)); 2868 } 2869 2870 /* is the parameter name empty? If so that's an error */ 2871 2872 if (*name == '\0') { 2873 _smlLogMsg(LOG_MSG_ERR, 2874 ERR_SML_READTAG_EMPTY_PARMNAME, 2875 tag->name, parent ? parent : "<<NONE>>"); 2876 smlFreeTag(tag); 2877 *a_str = p; 2878 return (RESULT_ERR); 2879 } 2880 2881 /* have a parameter name */ 2882 2883 _smlLogMsg(LOG_MSG_DEBUG, DBG_SML_HAVE_PARM_NAME, 2884 name, tag->name); 2885 2886 /* duplicate (save) parameter name */ 2887 2888 pname = strdup(name); 2889 2890 /* clear out name accumulator to get parameters */ 2891 2892 bzero(name, sizeof (name)); 2893 pos = 0; 2894 2895 c = *p; 2896 if (*p != '\0') { 2897 p++; 2898 } 2899 2900 if (c != '"') { 2901 _smlLogMsg(LOG_MSG_ERR, 2902 ERR_SML_PARM_SEP_BAD, 2903 c, (unsigned int)c); 2904 free(pname); 2905 smlFreeTag(tag); 2906 *a_str = p; 2907 return (RESULT_ERR); 2908 } 2909 2910 /* input parameter value */ 2911 2912 for (;;) { 2913 c = *p; 2914 if (*p != '\0') { 2915 p++; 2916 } 2917 2918 /* EOF inside of parameter value? */ 2919 2920 if (c == '\0') { 2921 _smlLogMsg(LOG_MSG_ERR, 2922 ERR_SML_READTAG_PARMVAL_EOF, 2923 pname, tag->name, 2924 parent ? parent : "<<NONE>>"); 2925 smlFreeTag(tag); 2926 free(pname); 2927 *a_str = p; 2928 return (RESULT_ERR); 2929 } 2930 2931 /* close of parameter value? */ 2932 2933 if (c == '"') { 2934 break; 2935 } 2936 2937 if (strchr("\n", c) != NULL) { 2938 _smlLogMsg(LOG_MSG_ERR, 2939 ERR_SML_READTAG_PARMVAL_NL, 2940 pname, tag->name, 2941 parent ? parent : "<<NONE>>"); 2942 free(pname); 2943 smlFreeTag(tag); 2944 *a_str = p; 2945 return (RESULT_ERR); 2946 } 2947 2948 /* valid character - add to value if room left */ 2949 2950 if (pos < sizeof (name)-1) { 2951 name[pos] = (c&0xFF); 2952 pos++; 2953 } 2954 2955 assert(pos < sizeof (name)); 2956 } 2957 2958 /* got the value */ 2959 2960 _smlLogMsg(LOG_MSG_DEBUG, DBG_SML_HAVE_PARM_VALUE, 2961 pname, name, tag->name); 2962 2963 pvalue = sml_XmlDecodeString(name); 2964 bzero(name, sizeof (name)); 2965 pos = 0; 2966 2967 parameter = (SML_PARAM *)calloc(1, sizeof (SML_PARAM)); 2968 bzero(parameter, sizeof (SML_PARAM)); 2969 parameter->name = pname; 2970 parameter->value = pvalue; 2971 tag->params_num++; 2972 tag->params = (SML_PARAM *) 2973 realloc(tag->params, 2974 sizeof (SML_PARAM) *tag->params_num); 2975 (void) memcpy(&(tag->params[tag->params_num - 1]), parameter, 2976 sizeof (SML_PARAM)); 2977 2978 free(parameter); 2979 if (c == '>') { 2980 break; 2981 } 2982 } 2983 2984 /* finished processing this tag element entry */ 2985 2986 _smlLogMsg(LOG_MSG_DEBUG, DBG_SML_TAG_HEAD_DONE, 2987 tag->name, parent ? parent : "<<NULL>>"); 2988 2989 tag->tags = NULL; 2990 2991 while (((r = _smlReadTag(&tmp_tag, &p, tag->name)) 2992 == RESULT_OK) && (tmp_tag != NULL)) { 2993 tag->tags_num++; 2994 tag->tags = (SML_TAG *)realloc(tag->tags, 2995 sizeof (SML_TAG) *tag->tags_num); 2996 (void) memcpy(&(tag->tags[tag->tags_num - 1]), tmp_tag, 2997 sizeof (SML_TAG)); 2998 free(tmp_tag); 2999 } 3000 3001 c = *p; 3002 if (*p != '\0') { 3003 p++; 3004 } 3005 3006 *r_tag = tag; 3007 *a_str = p; 3008 return (r); 3009 } 3010 3011 /* 3012 * Name: _smlWriteParamValue 3013 * Description: XML Encode a plain text parameter value and write to datastream 3014 * Arguments: ds - [RO, *RO] - (LU_DS) 3015 * Handle to datastream to write parameter value to 3016 * value - [RO, *RO] - (char *) 3017 * Parameter value to be encoded and written 3018 * Returns: int 3019 * RESULT_OK - tag successfully read 3020 * RESULT_ERR - problem reading tag 3021 */ 3022 3023 static int 3024 _smlWriteParamValue(char **a_str, char *value) 3025 { 3026 char *ns; 3027 char *p; 3028 3029 /* entry assertions */ 3030 3031 assert(a_str != (char **)NULL); 3032 assert(value != (char *)NULL); 3033 3034 /* xml encode the plain text string */ 3035 3036 p = sml_XmlEncodeString(value); 3037 assert(p != (char *)NULL); 3038 3039 /* write the xml encoded parameter value to the datastream */ 3040 3041 ns = sml_strPrintf("%s\"%s\"", *a_str ? *a_str : "", p); 3042 3043 /* free up xml encoded value storage */ 3044 3045 free(p); 3046 3047 if (ns == NULL) { 3048 return (RESULT_ERR); 3049 } 3050 3051 if (*a_str != NULL) { 3052 free(*a_str); 3053 } 3054 *a_str = ns; 3055 3056 /* return results */ 3057 3058 return (RESULT_OK); 3059 } 3060 3061 static int 3062 _smlWriteSimpleTag(char **a_str, SML_TAG *tag) 3063 { 3064 int r; 3065 int k; 3066 char *ns; 3067 char *np0; 3068 char *np1; 3069 3070 if (tag == NULL) { 3071 return (RESULT_OK); 3072 } 3073 3074 if (*a_str == NULL) { 3075 *a_str = strdup(""); 3076 } 3077 3078 if (tag->params_num == 0) { 3079 if (tag->tags_num == 0) { 3080 ns = sml_strPrintf("%s<%s/>\n", *a_str, tag->name); 3081 free(*a_str); 3082 *a_str = ns; 3083 return (RESULT_OK); 3084 } else { 3085 ns = sml_strPrintf("%s<%s>\n", *a_str, tag->name); 3086 if (ns == NULL) { 3087 return (RESULT_ERR); 3088 } 3089 free(*a_str); 3090 *a_str = ns; 3091 } 3092 } else { 3093 ns = sml_strPrintf("%s<%s %s=", *a_str ? *a_str : "", tag->name, 3094 tag->params[0].name); 3095 if (ns == NULL) { 3096 return (RESULT_ERR); 3097 } 3098 free(*a_str); 3099 *a_str = ns; 3100 3101 np0 = NULL; 3102 r = _smlWriteParamValue(&np0, tag->params[0].value); 3103 if ((np0 == NULL) || (r != RESULT_OK)) { 3104 return (RESULT_ERR); 3105 } 3106 3107 ns = sml_strPrintf("%s%s", *a_str, np0); 3108 if (ns == NULL) { 3109 return (RESULT_ERR); 3110 } 3111 3112 free(np0); 3113 free(*a_str); 3114 *a_str = ns; 3115 3116 for (k = 1; k < tag->params_num; k++) { 3117 np0 = sml_strPrintf(" %s=", tag->params[k].name); 3118 if (np0 == NULL) { 3119 return (RESULT_ERR); 3120 } 3121 np1 = NULL; 3122 r = _smlWriteParamValue(&np1, tag->params[k].value); 3123 if ((np1 == NULL) || (r != RESULT_OK)) { 3124 return (RESULT_ERR); 3125 } 3126 3127 ns = sml_strPrintf("%s%s%s", *a_str, np0, np1); 3128 if (ns == NULL) { 3129 return (RESULT_ERR); 3130 } 3131 3132 free(np0); 3133 free(np1); 3134 free(*a_str); 3135 *a_str = ns; 3136 } 3137 3138 if (tag->tags_num == 0) { 3139 np0 = sml_strPrintf("/>\n"); 3140 if (np0 == NULL) { 3141 return (RESULT_ERR); 3142 } 3143 ns = sml_strPrintf("%s%s", *a_str, np0); 3144 if (ns == NULL) { 3145 return (RESULT_ERR); 3146 } 3147 free(np0); 3148 free(*a_str); 3149 *a_str = ns; 3150 } else { 3151 np0 = sml_strPrintf(">\n"); 3152 if (np0 == NULL) { 3153 return (RESULT_ERR); 3154 } 3155 ns = sml_strPrintf("%s%s", *a_str, np0); 3156 if (ns == NULL) { 3157 return (RESULT_ERR); 3158 } 3159 free(np0); 3160 free(*a_str); 3161 *a_str = ns; 3162 } 3163 } 3164 3165 for (k = 0; k < tag->tags_num; k++) { 3166 r = _smlWriteSimpleTag(a_str, &(tag->tags[k])); 3167 if (r != RESULT_OK) { 3168 return (r); 3169 } 3170 } 3171 3172 if (tag->tags_num > 0) { 3173 np0 = sml_strPrintf("</%s>\n", tag->name); 3174 if (np0 == NULL) { 3175 return (RESULT_ERR); 3176 } 3177 ns = sml_strPrintf("%s%s", *a_str ? *a_str : "", np0); 3178 if (ns == NULL) { 3179 return (RESULT_ERR); 3180 } 3181 free(np0); 3182 free(*a_str); 3183 *a_str = ns; 3184 } 3185 3186 return (RESULT_OK); 3187 } 3188 3189 static void 3190 _smlFreeTag(SML_TAG *tag) 3191 { 3192 int k; 3193 3194 /* entry assertions */ 3195 3196 assert(tag != SML_TAG__NULL); 3197 3198 /* entry debugging info */ 3199 3200 _smlLogMsg(LOG_MSG_DEBUG, DBG_SML_INT_FREE_TAG, 3201 (unsigned long)tag, 3202 tag->name ? tag->name : "<<NONE>>", 3203 tag->params_num, tag->tags_num); 3204 3205 for (k = 0; k < tag->params_num; k++) { 3206 _smlLogMsg(LOG_MSG_DEBUG, DBG_SML_INT_FREE_PARAM_NAME, 3207 (unsigned long)(&tag->params[k]), 3208 (unsigned long)(tag->params[k].name), 3209 tag->params[k].name); 3210 free(tag->params[k].name); 3211 tag->params[k].name = (char *)NULL; 3212 _smlLogMsg(LOG_MSG_DEBUG, DBG_SML_INT_FREE_PARAM_VALUE, 3213 (unsigned long)(&tag->params[k]), 3214 (unsigned long)(tag->params[k].value), 3215 tag->params[k].value); 3216 free(tag->params[k].value); 3217 tag->params[k].value = (char *)NULL; 3218 } 3219 3220 for (k = 0; k < tag->tags_num; k++) { 3221 _smlFreeTag(&tag->tags[k]); 3222 } 3223 3224 if (tag->name != NULL) { 3225 _smlLogMsg(LOG_MSG_DEBUG, DBG_SML_INT_FREE_TAG_NAME, 3226 (unsigned long)tag->name, tag->name); 3227 free(tag->name); 3228 tag->name = NULL; 3229 } 3230 3231 3232 if (tag->params != NULL) { 3233 assert(tag->params_num > 0); 3234 bzero(tag->params, sizeof (SML_PARAM)*tag->params_num); 3235 _smlLogMsg(LOG_MSG_DEBUG, DBG_SML_INT_FREE_PARAMS, 3236 (unsigned long)tag->params); 3237 free(tag->params); 3238 tag->params = NULL; 3239 tag->params_num = 0; 3240 } 3241 3242 if (tag->tags != NULL) { 3243 assert(tag->tags_num > 0); 3244 bzero(tag->tags, sizeof (SML_TAG)*tag->tags_num); 3245 _smlLogMsg(LOG_MSG_DEBUG, DBG_SML_INT_FREE_TAGS, 3246 (unsigned long)tag->tags); 3247 free(tag->tags); 3248 tag->tags = NULL; 3249 tag->tags_num = 0; 3250 } 3251 } 3252 3253 /* 3254 * Name: log_msg 3255 * Description: Outputs messages to logging facility. 3256 * Scope: public 3257 * Arguments: type - the severity of the message 3258 * out - where to output the message. 3259 * fmt - the printf format, plus its arguments 3260 * Returns: none 3261 */ 3262 3263 /*PRINTFLIKE2*/ 3264 static void 3265 _smlLogMsg(LogMsgType a_type, const char *a_format, ...) 3266 { 3267 va_list ap; 3268 size_t vres = 0; 3269 char bfr[1]; 3270 char *rstr = (char *)NULL; 3271 FILE *out; 3272 char *prefix; 3273 3274 switch (a_type) { 3275 case LOG_MSG_ERR: 3276 default: 3277 out = stderr; 3278 prefix = MSG_LOG_ERROR; 3279 break; 3280 case LOG_MSG_WRN: 3281 out = stderr; 3282 prefix = MSG_LOG_WARNING; 3283 break; 3284 case LOG_MSG_INFO: 3285 out = stdout; 3286 prefix = NULL; 3287 break; 3288 case LOG_MSG_DEBUG: 3289 if (!smlGetVerbose()) { 3290 /* no debug messages if not verbose mode */ 3291 return; 3292 } 3293 out = stderr; 3294 prefix = MSG_LOG_DEBUG; 3295 break; 3296 } 3297 3298 if (prefix != NULL) { 3299 (void) fprintf(out, "%s: ", prefix); 3300 } 3301 3302 /* determine size of the message in bytes */ 3303 3304 va_start(ap, a_format); 3305 vres = vsnprintf(bfr, 1, a_format, ap); 3306 va_end(ap); 3307 3308 /* allocate storage to hold the message */ 3309 3310 rstr = (char *)malloc(vres+2); 3311 3312 /* generate the results of the printf conversion */ 3313 3314 va_start(ap, a_format); 3315 vres = vsnprintf(rstr, vres+1, a_format, ap); 3316 va_end(ap); 3317 3318 if (fprintf(out, "%s\n", rstr) < 0) { 3319 /* 3320 * nothing output, try stderr as a 3321 * last resort 3322 */ 3323 (void) fprintf(stderr, ERR_LOG_FAIL, a_format); 3324 } 3325 3326 free(rstr); 3327 } 3328