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 *
smlAddTag(SML_TAG ** r_tag,int a_index,SML_TAG * a_subTag)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
smlDelTag(SML_TAG * tag,SML_TAG * sub_tag)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
smlFreeTag(SML_TAG * tag)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
smlGetNumParams(SML_TAG * a_tag)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
smlGetParam_r(SML_TAG * tag,char * name,char * buf,int bufLen)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 *
smlGetParam(SML_TAG * tag,char * name)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 *
smlGetParamName(SML_TAG * tag,int index)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 *
smlGetParamByTag(SML_TAG * tag,int index,char * tagName,char * paramName)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 *
smlGetTagByTagParam(SML_TAG * tag,int index,char * tagName,char * paramName,char * paramValue)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 *
smlGetParamByTagParam(SML_TAG * tag,int index,char * tagName,char * paramName,char * paramValue,char * paramReturn)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 *
smlGetElementName(SML_TAG * a_tag)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 *
smlGetTag(SML_TAG * tag,int index)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 *
smlGetTagByName(SML_TAG * tag,int index,char * name)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
smlConvertStringToTag(SML_TAG ** r_tag,char * str)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
smlReadOneTag(SML_TAG ** r_tag,char * a_str)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 *
smlNewTag(char * name)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 *
smlConvertTagToString(SML_TAG * tag)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
smlDbgPrintTag(SML_TAG * a_tag,char * a_format,...)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
smlDelParam(SML_TAG * tag,char * name)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
smlSetParamF(SML_TAG * tag,char * name,char * format,...)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 *
smlGetParamF(SML_TAG * tag,char * format,...)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
smlSetParam(SML_TAG * tag,char * name,char * value)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
smlParamEqF(SML_TAG * tag,char * findTag,char * findParam,char * format,...)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
smlParamEq(SML_TAG * tag,char * findTag,char * findParam,char * str)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
smlFindAndDelTag(SML_TAG * tag,char * findTag)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 *
smlDup(SML_TAG * 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
smlSetFileStatInfo(SML_TAG ** tag,struct stat * statbuf,char * path)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
smlFstatCompareEq(struct stat * statbuf,SML_TAG * tag,char * path)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
smlSetVerbose(boolean_t setting)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
smlGetVerbose()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 *
sml_strPrintf(char * a_format,...)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
sml_strPrintf_r(char * a_buf,int a_bufLen,char * a_format,...)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 *
sml_XmlEncodeString(char * a_plainTextString)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 *
sml_XmlDecodeString(char * a_xmlEncodedString)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
_smlReadTag(SML_TAG ** r_tag,char ** a_str,char * parent)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
_smlWriteParamValue(char ** a_str,char * value)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
_smlWriteSimpleTag(char ** a_str,SML_TAG * tag)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
_smlFreeTag(SML_TAG * tag)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
_smlLogMsg(LogMsgType a_type,const char * a_format,...)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