17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
576cf44abSjeanm * Common Development and Distribution License (the "License").
676cf44abSjeanm * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
2285bcc4e5SSean Wilcox * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
237c478bd9Sstevel@tonic-gate */
24*67b0e063SAlbert Lee /*
25*67b0e063SAlbert Lee * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
26*67b0e063SAlbert Lee */
27*67b0e063SAlbert Lee
287c478bd9Sstevel@tonic-gate
297c478bd9Sstevel@tonic-gate /*
307c478bd9Sstevel@tonic-gate * XML document manipulation routines
317c478bd9Sstevel@tonic-gate *
327c478bd9Sstevel@tonic-gate * These routines provide translation to and from the internal representation to
337c478bd9Sstevel@tonic-gate * XML. Directionally-oriented verbs are with respect to the external source,
347c478bd9Sstevel@tonic-gate * so lxml_get_service() fetches a service from the XML file into the
357c478bd9Sstevel@tonic-gate * internal representation.
367c478bd9Sstevel@tonic-gate */
377c478bd9Sstevel@tonic-gate
381f6eb021SLiane Praza #include <libxml/parser.h>
391f6eb021SLiane Praza #include <libxml/xinclude.h>
401f6eb021SLiane Praza
411f6eb021SLiane Praza #include <assert.h>
421f6eb021SLiane Praza #include <ctype.h>
431f6eb021SLiane Praza #include <errno.h>
441f6eb021SLiane Praza #include <libintl.h>
451f6eb021SLiane Praza #include <libscf.h>
461f6eb021SLiane Praza #include <libscf_priv.h>
471f6eb021SLiane Praza #include <libuutil.h>
481f6eb021SLiane Praza #include <sasl/saslutil.h>
491f6eb021SLiane Praza #include <stdlib.h>
501f6eb021SLiane Praza #include <string.h>
5185bcc4e5SSean Wilcox #include <limits.h>
521f6eb021SLiane Praza
531f6eb021SLiane Praza #include <sys/types.h>
541f6eb021SLiane Praza #include <sys/stat.h>
551f6eb021SLiane Praza #include <unistd.h>
561f6eb021SLiane Praza
5723294c7dSSean Wilcox #include <sys/param.h>
5823294c7dSSean Wilcox #include "manifest_hash.h"
5923294c7dSSean Wilcox
601f6eb021SLiane Praza #include "svccfg.h"
61f6e214c7SGavin Maltby #include "notify_params.h"
621f6eb021SLiane Praza
631f6eb021SLiane Praza /*
641f6eb021SLiane Praza * snprintf(3C) format strings for constructing property names that include
651f6eb021SLiane Praza * the locale designation. Use %s to indicate where the locale should go.
661f6eb021SLiane Praza *
671f6eb021SLiane Praza * The VALUE_* symbols are an exception. The firs %s will be replaced with
681f6eb021SLiane Praza * "value_". The second %s will be replaced by the name of the value and
691f6eb021SLiane Praza * %%s will be replaced by the locale designation. These formats are
701f6eb021SLiane Praza * processed twice by snprintf(3C). The first time captures the value name
711f6eb021SLiane Praza * and the second time captures the locale.
721f6eb021SLiane Praza */
731f6eb021SLiane Praza #define LOCALE_ONLY_FMT ("%s")
741f6eb021SLiane Praza #define COMMON_NAME_FMT ("common_name_%s")
751f6eb021SLiane Praza #define DESCRIPTION_FMT ("description_%s")
761f6eb021SLiane Praza #define UNITS_FMT ("units_%s")
771f6eb021SLiane Praza #define VALUE_COMMON_NAME_FMT ("%s%s_common_name_%%s")
781f6eb021SLiane Praza #define VALUE_DESCRIPTION_FMT ("%s%s_description_%%s")
791f6eb021SLiane Praza
801f6eb021SLiane Praza /* Attribute names */
817c478bd9Sstevel@tonic-gate const char * const delete_attr = "delete";
827c478bd9Sstevel@tonic-gate const char * const enabled_attr = "enabled";
831f6eb021SLiane Praza const char * const lang_attr = "lang";
841f6eb021SLiane Praza const char * const manpath_attr = "manpath";
851f6eb021SLiane Praza const char * const max_attr = "max";
861f6eb021SLiane Praza const char * const min_attr = "min";
877c478bd9Sstevel@tonic-gate const char * const name_attr = "name";
887c478bd9Sstevel@tonic-gate const char * const override_attr = "override";
891f6eb021SLiane Praza const char * const required_attr = "required";
901f6eb021SLiane Praza const char * const section_attr = "section";
911f6eb021SLiane Praza const char * const set_attr = "set";
921f6eb021SLiane Praza const char * const target_attr = "target";
931f6eb021SLiane Praza const char * const timeout_seconds_attr = "timeout_seconds";
941f6eb021SLiane Praza const char * const title_attr = "title";
957c478bd9Sstevel@tonic-gate const char * const type_attr = "type";
961f6eb021SLiane Praza const char * const uri_attr = "uri";
977c478bd9Sstevel@tonic-gate const char * const value_attr = "value";
981f6eb021SLiane Praza const char * const version_attr = "version";
991f6eb021SLiane Praza const char * const xml_lang_attr = "xml:lang";
100f6e214c7SGavin Maltby const char * const active_attr = "active";
1011f6eb021SLiane Praza
1021f6eb021SLiane Praza /* Attribute values */
1031f6eb021SLiane Praza const char * const all_value = "all";
1041f6eb021SLiane Praza
1057c478bd9Sstevel@tonic-gate const char * const true = "true";
1067c478bd9Sstevel@tonic-gate const char * const false = "false";
1077c478bd9Sstevel@tonic-gate
1087c478bd9Sstevel@tonic-gate /*
1097c478bd9Sstevel@tonic-gate * The following list must be kept in the same order as that of
1107c478bd9Sstevel@tonic-gate * element_t array
1117c478bd9Sstevel@tonic-gate */
1127c478bd9Sstevel@tonic-gate static const char *lxml_elements[] = {
1137c478bd9Sstevel@tonic-gate "astring_list", /* SC_ASTRING */
1147c478bd9Sstevel@tonic-gate "boolean_list", /* SC_BOOLEAN */
1151f6eb021SLiane Praza "cardinality", /* SC_CARDINALITY */
1161f6eb021SLiane Praza "choices", /* SC_CHOICES */
1177c478bd9Sstevel@tonic-gate "common_name", /* SC_COMMON_NAME */
1181f6eb021SLiane Praza "constraints", /* SC_CONSTRAINTS */
1197c478bd9Sstevel@tonic-gate "count_list", /* SC_COUNT */
1207c478bd9Sstevel@tonic-gate "create_default_instance", /* SC_INSTANCE_CREATE_DEFAULT */
1217c478bd9Sstevel@tonic-gate "dependency", /* SC_DEPENDENCY */
1227c478bd9Sstevel@tonic-gate "dependent", /* SC_DEPENDENT */
1237c478bd9Sstevel@tonic-gate "description", /* SC_DESCRIPTION */
1247c478bd9Sstevel@tonic-gate "doc_link", /* SC_DOC_LINK */
1257c478bd9Sstevel@tonic-gate "documentation", /* SC_DOCUMENTATION */
1267c478bd9Sstevel@tonic-gate "enabled", /* SC_ENABLED */
127f6e214c7SGavin Maltby "event", /* SC_EVENT */
1287c478bd9Sstevel@tonic-gate "exec_method", /* SC_EXEC_METHOD */
1297c478bd9Sstevel@tonic-gate "fmri_list", /* SC_FMRI */
1307c478bd9Sstevel@tonic-gate "host_list", /* SC_HOST */
1317c478bd9Sstevel@tonic-gate "hostname_list", /* SC_HOSTNAME */
1321f6eb021SLiane Praza "include_values", /* SC_INCLUDE_VALUES */
1337c478bd9Sstevel@tonic-gate "instance", /* SC_INSTANCE */
1347c478bd9Sstevel@tonic-gate "integer_list", /* SC_INTEGER */
1351f6eb021SLiane Praza "internal_separators", /* SC_INTERNAL_SEPARATORS */
1367c478bd9Sstevel@tonic-gate "loctext", /* SC_LOCTEXT */
1377c478bd9Sstevel@tonic-gate "manpage", /* SC_MANPAGE */
1387c478bd9Sstevel@tonic-gate "method_context", /* SC_METHOD_CONTEXT */
1397c478bd9Sstevel@tonic-gate "method_credential", /* SC_METHOD_CREDENTIAL */
1407c478bd9Sstevel@tonic-gate "method_profile", /* SC_METHOD_PROFILE */
1417c478bd9Sstevel@tonic-gate "method_environment", /* SC_METHOD_ENVIRONMENT */
1427c478bd9Sstevel@tonic-gate "envvar", /* SC_METHOD_ENVVAR */
143f6f041a2SAntonello Cruz "net_address_list", /* SC_NET_ADDR */
1447c478bd9Sstevel@tonic-gate "net_address_v4_list", /* SC_NET_ADDR_V4 */
1457c478bd9Sstevel@tonic-gate "net_address_v6_list", /* SC_NET_ADDR_V6 */
146f6e214c7SGavin Maltby "notification_parameters", /* SC_NOTIFICATION_PARAMETERS */
1477c478bd9Sstevel@tonic-gate "opaque_list", /* SC_OPAQUE */
148f6e214c7SGavin Maltby "parameter", /* SC_PARAMETER */
149f6e214c7SGavin Maltby "paramval", /* SC_PARAMVAL */
1501f6eb021SLiane Praza "pg_pattern", /* SC_PG_PATTERN */
1511f6eb021SLiane Praza "prop_pattern", /* SC_PROP_PATTERN */
1527c478bd9Sstevel@tonic-gate "property", /* SC_PROPERTY */
1537c478bd9Sstevel@tonic-gate "property_group", /* SC_PROPERTY_GROUP */
1547c478bd9Sstevel@tonic-gate "propval", /* SC_PROPVAL */
1551f6eb021SLiane Praza "range", /* SC_RANGE */
1567c478bd9Sstevel@tonic-gate "restarter", /* SC_RESTARTER */
1577c478bd9Sstevel@tonic-gate "service", /* SC_SERVICE */
1587c478bd9Sstevel@tonic-gate "service_bundle", /* SC_SERVICE_BUNDLE */
1597c478bd9Sstevel@tonic-gate "service_fmri", /* SC_SERVICE_FMRI */
1607c478bd9Sstevel@tonic-gate "single_instance", /* SC_INSTANCE_SINGLE */
1617c478bd9Sstevel@tonic-gate "stability", /* SC_STABILITY */
1627c478bd9Sstevel@tonic-gate "template", /* SC_TEMPLATE */
1637c478bd9Sstevel@tonic-gate "time_list", /* SC_TIME */
164f6e214c7SGavin Maltby "type", /* SC_TYPE */
1651f6eb021SLiane Praza "units", /* SC_UNITS */
1667c478bd9Sstevel@tonic-gate "uri_list", /* SC_URI */
1677c478bd9Sstevel@tonic-gate "ustring_list", /* SC_USTRING */
1681f6eb021SLiane Praza "value", /* SC_VALUE */
1697c478bd9Sstevel@tonic-gate "value_node", /* SC_VALUE_NODE */
1701f6eb021SLiane Praza "values", /* SC_VALUES */
1711f6eb021SLiane Praza "visibility", /* SC_VISIBILITY */
1727c478bd9Sstevel@tonic-gate "xi:fallback", /* SC_XI_FALLBACK */
1737c478bd9Sstevel@tonic-gate "xi:include" /* SC_XI_INCLUDE */
1747c478bd9Sstevel@tonic-gate };
1757c478bd9Sstevel@tonic-gate
1767c478bd9Sstevel@tonic-gate /*
1777c478bd9Sstevel@tonic-gate * The following list must be kept in the same order as that of
1787c478bd9Sstevel@tonic-gate * element_t array
1797c478bd9Sstevel@tonic-gate */
1807c478bd9Sstevel@tonic-gate static const char *lxml_prop_types[] = {
1817c478bd9Sstevel@tonic-gate "astring", /* SC_ASTRING */
1827c478bd9Sstevel@tonic-gate "boolean", /* SC_BOOLEAN */
1831f6eb021SLiane Praza "", /* SC_CARDINALITY */
1841f6eb021SLiane Praza "", /* SC_CHOICES */
1857c478bd9Sstevel@tonic-gate "", /* SC_COMMON_NAME */
1861f6eb021SLiane Praza "", /* SC_CONSTRAINTS */
1877c478bd9Sstevel@tonic-gate "count", /* SC_COUNT */
1887c478bd9Sstevel@tonic-gate "", /* SC_INSTANCE_CREATE_DEFAULT */
1897c478bd9Sstevel@tonic-gate "", /* SC_DEPENDENCY */
1907c478bd9Sstevel@tonic-gate "", /* SC_DEPENDENT */
1917c478bd9Sstevel@tonic-gate "", /* SC_DESCRIPTION */
1927c478bd9Sstevel@tonic-gate "", /* SC_DOC_LINK */
1937c478bd9Sstevel@tonic-gate "", /* SC_DOCUMENTATION */
1947c478bd9Sstevel@tonic-gate "", /* SC_ENABLED */
195f6e214c7SGavin Maltby "", /* SC_EVENT */
1967c478bd9Sstevel@tonic-gate "", /* SC_EXEC_METHOD */
1977c478bd9Sstevel@tonic-gate "fmri", /* SC_FMRI */
1987c478bd9Sstevel@tonic-gate "host", /* SC_HOST */
1997c478bd9Sstevel@tonic-gate "hostname", /* SC_HOSTNAME */
2001f6eb021SLiane Praza "", /* SC_INCLUDE_VALUES */
2017c478bd9Sstevel@tonic-gate "", /* SC_INSTANCE */
2027c478bd9Sstevel@tonic-gate "integer", /* SC_INTEGER */
2031f6eb021SLiane Praza "", /* SC_INTERNAL_SEPARATORS */
2047c478bd9Sstevel@tonic-gate "", /* SC_LOCTEXT */
2057c478bd9Sstevel@tonic-gate "", /* SC_MANPAGE */
2067c478bd9Sstevel@tonic-gate "", /* SC_METHOD_CONTEXT */
2077c478bd9Sstevel@tonic-gate "", /* SC_METHOD_CREDENTIAL */
2087c478bd9Sstevel@tonic-gate "", /* SC_METHOD_PROFILE */
2097c478bd9Sstevel@tonic-gate "", /* SC_METHOD_ENVIRONMENT */
2107c478bd9Sstevel@tonic-gate "", /* SC_METHOD_ENVVAR */
211f6f041a2SAntonello Cruz "net_address", /* SC_NET_ADDR */
2127c478bd9Sstevel@tonic-gate "net_address_v4", /* SC_NET_ADDR_V4 */
2137c478bd9Sstevel@tonic-gate "net_address_v6", /* SC_NET_ADDR_V6 */
214f6e214c7SGavin Maltby "", /* SC_NOTIFICATION_PARAMETERS */
2157c478bd9Sstevel@tonic-gate "opaque", /* SC_OPAQUE */
216f6e214c7SGavin Maltby "", /* SC_PARAMETER */
217f6e214c7SGavin Maltby "", /* SC_PARAMVAL */
2181f6eb021SLiane Praza "", /* SC_PG_PATTERN */
2191f6eb021SLiane Praza "", /* SC_PROP_PATTERN */
2207c478bd9Sstevel@tonic-gate "", /* SC_PROPERTY */
2217c478bd9Sstevel@tonic-gate "", /* SC_PROPERTY_GROUP */
2227c478bd9Sstevel@tonic-gate "", /* SC_PROPVAL */
2231f6eb021SLiane Praza "", /* SC_RANGE */
2247c478bd9Sstevel@tonic-gate "", /* SC_RESTARTER */
2257c478bd9Sstevel@tonic-gate "", /* SC_SERVICE */
2267c478bd9Sstevel@tonic-gate "", /* SC_SERVICE_BUNDLE */
2277c478bd9Sstevel@tonic-gate "", /* SC_SERVICE_FMRI */
2287c478bd9Sstevel@tonic-gate "", /* SC_INSTANCE_SINGLE */
2297c478bd9Sstevel@tonic-gate "", /* SC_STABILITY */
2307c478bd9Sstevel@tonic-gate "", /* SC_TEMPLATE */
2317c478bd9Sstevel@tonic-gate "time", /* SC_TIME */
232f6e214c7SGavin Maltby "", /* SC_TYPE */
2331f6eb021SLiane Praza "", /* SC_UNITS */
2347c478bd9Sstevel@tonic-gate "uri", /* SC_URI */
2357c478bd9Sstevel@tonic-gate "ustring", /* SC_USTRING */
2361f6eb021SLiane Praza "", /* SC_VALUE */
2371f6eb021SLiane Praza "", /* SC_VALUE_NODE */
2381f6eb021SLiane Praza "", /* SC_VALUES */
2391f6eb021SLiane Praza "", /* SC_VISIBILITY */
2401f6eb021SLiane Praza "", /* SC_XI_FALLBACK */
2417c478bd9Sstevel@tonic-gate "" /* SC_XI_INCLUDE */
2427c478bd9Sstevel@tonic-gate };
2437c478bd9Sstevel@tonic-gate
2447c478bd9Sstevel@tonic-gate int
lxml_init()2457c478bd9Sstevel@tonic-gate lxml_init()
2467c478bd9Sstevel@tonic-gate {
2477c478bd9Sstevel@tonic-gate if (getenv("SVCCFG_NOVALIDATE") == NULL) {
2487c478bd9Sstevel@tonic-gate /*
2497c478bd9Sstevel@tonic-gate * DTD validation, with line numbers.
2507c478bd9Sstevel@tonic-gate */
25180148899SSurya Prakki (void) xmlLineNumbersDefault(1);
2527c478bd9Sstevel@tonic-gate xmlLoadExtDtdDefaultValue |= XML_DETECT_IDS;
2537c478bd9Sstevel@tonic-gate xmlLoadExtDtdDefaultValue |= XML_COMPLETE_ATTRS;
2547c478bd9Sstevel@tonic-gate }
2557c478bd9Sstevel@tonic-gate
2567c478bd9Sstevel@tonic-gate return (0);
2577c478bd9Sstevel@tonic-gate }
2587c478bd9Sstevel@tonic-gate
2597c478bd9Sstevel@tonic-gate static bundle_type_t
lxml_xlate_bundle_type(xmlChar * type)2607c478bd9Sstevel@tonic-gate lxml_xlate_bundle_type(xmlChar *type)
2617c478bd9Sstevel@tonic-gate {
2627c478bd9Sstevel@tonic-gate if (xmlStrcmp(type, (const xmlChar *)"manifest") == 0)
2637c478bd9Sstevel@tonic-gate return (SVCCFG_MANIFEST);
2647c478bd9Sstevel@tonic-gate
2657c478bd9Sstevel@tonic-gate if (xmlStrcmp(type, (const xmlChar *)"profile") == 0)
2667c478bd9Sstevel@tonic-gate return (SVCCFG_PROFILE);
2677c478bd9Sstevel@tonic-gate
2687c478bd9Sstevel@tonic-gate if (xmlStrcmp(type, (const xmlChar *)"archive") == 0)
2697c478bd9Sstevel@tonic-gate return (SVCCFG_ARCHIVE);
2707c478bd9Sstevel@tonic-gate
2717c478bd9Sstevel@tonic-gate return (SVCCFG_UNKNOWN_BUNDLE);
2727c478bd9Sstevel@tonic-gate }
2737c478bd9Sstevel@tonic-gate
2747c478bd9Sstevel@tonic-gate static service_type_t
lxml_xlate_service_type(xmlChar * type)2757c478bd9Sstevel@tonic-gate lxml_xlate_service_type(xmlChar *type)
2767c478bd9Sstevel@tonic-gate {
2777c478bd9Sstevel@tonic-gate if (xmlStrcmp(type, (const xmlChar *)"service") == 0)
2787c478bd9Sstevel@tonic-gate return (SVCCFG_SERVICE);
2797c478bd9Sstevel@tonic-gate
2807c478bd9Sstevel@tonic-gate if (xmlStrcmp(type, (const xmlChar *)"restarter") == 0)
2817c478bd9Sstevel@tonic-gate return (SVCCFG_RESTARTER);
2827c478bd9Sstevel@tonic-gate
2837c478bd9Sstevel@tonic-gate if (xmlStrcmp(type, (const xmlChar *)"milestone") == 0)
2847c478bd9Sstevel@tonic-gate return (SVCCFG_MILESTONE);
2857c478bd9Sstevel@tonic-gate
2867c478bd9Sstevel@tonic-gate return (SVCCFG_UNKNOWN_SERVICE);
2877c478bd9Sstevel@tonic-gate }
2887c478bd9Sstevel@tonic-gate
2897c478bd9Sstevel@tonic-gate static element_t
lxml_xlate_element(const xmlChar * tag)2907c478bd9Sstevel@tonic-gate lxml_xlate_element(const xmlChar *tag)
2917c478bd9Sstevel@tonic-gate {
2927c478bd9Sstevel@tonic-gate int i;
2937c478bd9Sstevel@tonic-gate
2947c478bd9Sstevel@tonic-gate for (i = 0; i < sizeof (lxml_elements) / sizeof (char *); i++)
2957c478bd9Sstevel@tonic-gate if (xmlStrcmp(tag, (const xmlChar *)lxml_elements[i]) == 0)
2967c478bd9Sstevel@tonic-gate return ((element_t)i);
2977c478bd9Sstevel@tonic-gate
2987c478bd9Sstevel@tonic-gate return ((element_t)-1);
2997c478bd9Sstevel@tonic-gate }
3007c478bd9Sstevel@tonic-gate
3017c478bd9Sstevel@tonic-gate static uint_t
lxml_xlate_boolean(const xmlChar * value)3027c478bd9Sstevel@tonic-gate lxml_xlate_boolean(const xmlChar *value)
3037c478bd9Sstevel@tonic-gate {
3047c478bd9Sstevel@tonic-gate if (xmlStrcmp(value, (const xmlChar *)true) == 0)
3057c478bd9Sstevel@tonic-gate return (1);
3067c478bd9Sstevel@tonic-gate
3077c478bd9Sstevel@tonic-gate if (xmlStrcmp(value, (const xmlChar *)false) == 0)
3087c478bd9Sstevel@tonic-gate return (0);
3097c478bd9Sstevel@tonic-gate
3107c478bd9Sstevel@tonic-gate uu_die(gettext("illegal boolean value \"%s\"\n"), value);
3117c478bd9Sstevel@tonic-gate
3127c478bd9Sstevel@tonic-gate /*NOTREACHED*/
3137c478bd9Sstevel@tonic-gate }
3147c478bd9Sstevel@tonic-gate
3157c478bd9Sstevel@tonic-gate static scf_type_t
lxml_element_to_type(element_t type)3167c478bd9Sstevel@tonic-gate lxml_element_to_type(element_t type)
3177c478bd9Sstevel@tonic-gate {
3187c478bd9Sstevel@tonic-gate switch (type) {
3197c478bd9Sstevel@tonic-gate case SC_ASTRING: return (SCF_TYPE_ASTRING);
3207c478bd9Sstevel@tonic-gate case SC_BOOLEAN: return (SCF_TYPE_BOOLEAN);
3217c478bd9Sstevel@tonic-gate case SC_COUNT: return (SCF_TYPE_COUNT);
3227c478bd9Sstevel@tonic-gate case SC_FMRI: return (SCF_TYPE_FMRI);
3237c478bd9Sstevel@tonic-gate case SC_HOST: return (SCF_TYPE_HOST);
3247c478bd9Sstevel@tonic-gate case SC_HOSTNAME: return (SCF_TYPE_HOSTNAME);
3257c478bd9Sstevel@tonic-gate case SC_INTEGER: return (SCF_TYPE_INTEGER);
326f6f041a2SAntonello Cruz case SC_NET_ADDR: return (SCF_TYPE_NET_ADDR);
3277c478bd9Sstevel@tonic-gate case SC_NET_ADDR_V4: return (SCF_TYPE_NET_ADDR_V4);
3287c478bd9Sstevel@tonic-gate case SC_NET_ADDR_V6: return (SCF_TYPE_NET_ADDR_V6);
3297c478bd9Sstevel@tonic-gate case SC_OPAQUE: return (SCF_TYPE_OPAQUE);
3307c478bd9Sstevel@tonic-gate case SC_TIME: return (SCF_TYPE_TIME);
3317c478bd9Sstevel@tonic-gate case SC_URI: return (SCF_TYPE_URI);
3327c478bd9Sstevel@tonic-gate case SC_USTRING: return (SCF_TYPE_USTRING);
3337c478bd9Sstevel@tonic-gate
3347c478bd9Sstevel@tonic-gate default:
3357c478bd9Sstevel@tonic-gate uu_die(gettext("unknown value type (%d)\n"), type);
3367c478bd9Sstevel@tonic-gate }
3377c478bd9Sstevel@tonic-gate
3387c478bd9Sstevel@tonic-gate /* NOTREACHED */
3397c478bd9Sstevel@tonic-gate }
3407c478bd9Sstevel@tonic-gate
341f329b923SSean Wilcox static element_t
lxml_type_to_element(scf_type_t type)342f329b923SSean Wilcox lxml_type_to_element(scf_type_t type)
3437c478bd9Sstevel@tonic-gate {
3447c478bd9Sstevel@tonic-gate switch (type) {
345f329b923SSean Wilcox case SCF_TYPE_ASTRING: return (SC_ASTRING);
346f329b923SSean Wilcox case SCF_TYPE_BOOLEAN: return (SC_BOOLEAN);
347f329b923SSean Wilcox case SCF_TYPE_COUNT: return (SC_COUNT);
348f329b923SSean Wilcox case SCF_TYPE_FMRI: return (SC_FMRI);
349f329b923SSean Wilcox case SCF_TYPE_HOST: return (SC_HOST);
350f329b923SSean Wilcox case SCF_TYPE_HOSTNAME: return (SC_HOSTNAME);
351f329b923SSean Wilcox case SCF_TYPE_INTEGER: return (SC_INTEGER);
352f6f041a2SAntonello Cruz case SCF_TYPE_NET_ADDR: return (SC_NET_ADDR);
353f329b923SSean Wilcox case SCF_TYPE_NET_ADDR_V4: return (SC_NET_ADDR_V4);
354f329b923SSean Wilcox case SCF_TYPE_NET_ADDR_V6: return (SC_NET_ADDR_V6);
355f329b923SSean Wilcox case SCF_TYPE_OPAQUE: return (SC_OPAQUE);
356f329b923SSean Wilcox case SCF_TYPE_TIME: return (SC_TIME);
357f329b923SSean Wilcox case SCF_TYPE_URI: return (SC_URI);
358f329b923SSean Wilcox case SCF_TYPE_USTRING: return (SC_USTRING);
359f329b923SSean Wilcox
3607c478bd9Sstevel@tonic-gate default:
3617c478bd9Sstevel@tonic-gate uu_die(gettext("unknown value type (%d)\n"), type);
3627c478bd9Sstevel@tonic-gate }
3637c478bd9Sstevel@tonic-gate
3647c478bd9Sstevel@tonic-gate /* NOTREACHED */
3657c478bd9Sstevel@tonic-gate }
3667c478bd9Sstevel@tonic-gate
3671f6eb021SLiane Praza /*
3681f6eb021SLiane Praza * Create a SCF_TYPE_BOOLEAN property name pname and attach it to the
3691f6eb021SLiane Praza * property group at pgrp. The value of the property will be set from the
3701f6eb021SLiane Praza * attribute named attr. attr must have a value of 0, 1, true or false.
3711f6eb021SLiane Praza *
3721f6eb021SLiane Praza * Zero is returned on success. An error is indicated by -1. It indicates
3731f6eb021SLiane Praza * that either the attribute had an invalid value or that we could not
3741f6eb021SLiane Praza * attach the property to pgrp. The attribute should not have an invalid
3751f6eb021SLiane Praza * value if the DTD is correctly written.
3761f6eb021SLiane Praza */
3771f6eb021SLiane Praza static int
new_bool_prop_from_attr(pgroup_t * pgrp,const char * pname,xmlNodePtr n,const char * attr)3781f6eb021SLiane Praza new_bool_prop_from_attr(pgroup_t *pgrp, const char *pname, xmlNodePtr n,
3791f6eb021SLiane Praza const char *attr)
3801f6eb021SLiane Praza {
3811f6eb021SLiane Praza uint64_t bool;
3821f6eb021SLiane Praza xmlChar *val;
3831f6eb021SLiane Praza property_t *p;
3841f6eb021SLiane Praza int r;
3851f6eb021SLiane Praza
3861f6eb021SLiane Praza val = xmlGetProp(n, (xmlChar *)attr);
3871f6eb021SLiane Praza if (val == NULL)
3881f6eb021SLiane Praza return (0);
3891f6eb021SLiane Praza
3901f6eb021SLiane Praza if ((xmlStrcmp(val, (xmlChar *)"0") == 0) ||
3911f6eb021SLiane Praza (xmlStrcmp(val, (xmlChar *)"false") == 0)) {
3921f6eb021SLiane Praza bool = 0;
3931f6eb021SLiane Praza } else if ((xmlStrcmp(val, (xmlChar *)"1") == 0) ||
3941f6eb021SLiane Praza (xmlStrcmp(val, (xmlChar *)"true") == 0)) {
3951f6eb021SLiane Praza bool = 1;
3961f6eb021SLiane Praza } else {
3971f6eb021SLiane Praza xmlFree(val);
3981f6eb021SLiane Praza return (-1);
3991f6eb021SLiane Praza }
4001f6eb021SLiane Praza xmlFree(val);
4011f6eb021SLiane Praza p = internal_property_create(pname, SCF_TYPE_BOOLEAN, 1, bool);
4021f6eb021SLiane Praza r = internal_attach_property(pgrp, p);
4031f6eb021SLiane Praza
4041f6eb021SLiane Praza if (r != 0)
4051f6eb021SLiane Praza internal_property_free(p);
4061f6eb021SLiane Praza
4071f6eb021SLiane Praza return (r);
4081f6eb021SLiane Praza }
4091f6eb021SLiane Praza
4107c478bd9Sstevel@tonic-gate static int
new_str_prop_from_attr(pgroup_t * pgrp,const char * pname,scf_type_t ty,xmlNodePtr n,const char * attr)4117c478bd9Sstevel@tonic-gate new_str_prop_from_attr(pgroup_t *pgrp, const char *pname, scf_type_t ty,
4127c478bd9Sstevel@tonic-gate xmlNodePtr n, const char *attr)
4137c478bd9Sstevel@tonic-gate {
4147c478bd9Sstevel@tonic-gate xmlChar *val;
4157c478bd9Sstevel@tonic-gate property_t *p;
4167c478bd9Sstevel@tonic-gate int r;
4177c478bd9Sstevel@tonic-gate
4187c478bd9Sstevel@tonic-gate val = xmlGetProp(n, (xmlChar *)attr);
4197c478bd9Sstevel@tonic-gate
4207c478bd9Sstevel@tonic-gate p = internal_property_create(pname, ty, 1, val);
4217c478bd9Sstevel@tonic-gate r = internal_attach_property(pgrp, p);
4227c478bd9Sstevel@tonic-gate
4237c478bd9Sstevel@tonic-gate if (r != 0)
4247c478bd9Sstevel@tonic-gate internal_property_free(p);
4257c478bd9Sstevel@tonic-gate
4267c478bd9Sstevel@tonic-gate return (r);
4277c478bd9Sstevel@tonic-gate }
4287c478bd9Sstevel@tonic-gate
4297c478bd9Sstevel@tonic-gate static int
new_opt_str_prop_from_attr(pgroup_t * pgrp,const char * pname,scf_type_t ty,xmlNodePtr n,const char * attr,const char * dflt)4301f6eb021SLiane Praza new_opt_str_prop_from_attr(pgroup_t *pgrp, const char *pname, scf_type_t ty,
4311f6eb021SLiane Praza xmlNodePtr n, const char *attr, const char *dflt)
4321f6eb021SLiane Praza {
4331f6eb021SLiane Praza xmlChar *val;
4341f6eb021SLiane Praza property_t *p;
4351f6eb021SLiane Praza int r;
4361f6eb021SLiane Praza
4371f6eb021SLiane Praza val = xmlGetProp(n, (xmlChar *)attr);
4381f6eb021SLiane Praza if (val == NULL) {
4391f6eb021SLiane Praza if (dflt == NULL) {
4401f6eb021SLiane Praza /*
4411f6eb021SLiane Praza * A missing attribute is considered to be a
4421f6eb021SLiane Praza * success in this function, because many of the
4431f6eb021SLiane Praza * attributes are optional. Missing non-optional
4441f6eb021SLiane Praza * attributes will be detected later when template
4451f6eb021SLiane Praza * validation is done.
4461f6eb021SLiane Praza */
4471f6eb021SLiane Praza return (0);
4481f6eb021SLiane Praza } else {
4491f6eb021SLiane Praza val = (xmlChar *)dflt;
4501f6eb021SLiane Praza }
4511f6eb021SLiane Praza }
4521f6eb021SLiane Praza
4531f6eb021SLiane Praza p = internal_property_create(pname, ty, 1, val);
4541f6eb021SLiane Praza r = internal_attach_property(pgrp, p);
4551f6eb021SLiane Praza
4561f6eb021SLiane Praza if (r != 0)
4571f6eb021SLiane Praza internal_property_free(p);
4581f6eb021SLiane Praza
4591f6eb021SLiane Praza return (r);
4601f6eb021SLiane Praza }
4611f6eb021SLiane Praza
4621f6eb021SLiane Praza static int
lxml_ignorable_block(xmlNodePtr n)4637c478bd9Sstevel@tonic-gate lxml_ignorable_block(xmlNodePtr n)
4647c478bd9Sstevel@tonic-gate {
4657c478bd9Sstevel@tonic-gate return ((xmlStrcmp(n->name, (xmlChar *)"text") == 0 ||
4667c478bd9Sstevel@tonic-gate xmlStrcmp(n->name, (xmlChar *)"comment") == 0) ? 1 : 0);
4677c478bd9Sstevel@tonic-gate }
4687c478bd9Sstevel@tonic-gate
469f329b923SSean Wilcox static void
lxml_validate_element(xmlNodePtr n)470f329b923SSean Wilcox lxml_validate_element(xmlNodePtr n)
471f329b923SSean Wilcox {
472f329b923SSean Wilcox xmlValidCtxtPtr vcp;
473f329b923SSean Wilcox
474f329b923SSean Wilcox if (n->doc == NULL)
475f329b923SSean Wilcox uu_die(gettext("Could not validate element\n"));
476f329b923SSean Wilcox
477f329b923SSean Wilcox if (n->doc->extSubset == NULL) {
478f329b923SSean Wilcox xmlDtdPtr dtd;
479f329b923SSean Wilcox dtd = xmlParseDTD(NULL, n->doc->intSubset->SystemID);
480f329b923SSean Wilcox
481f329b923SSean Wilcox if (dtd == NULL) {
482f329b923SSean Wilcox uu_die(gettext("Could not parse DTD \"%s\".\n"),
483f329b923SSean Wilcox n->doc->intSubset->SystemID);
484f329b923SSean Wilcox }
485f329b923SSean Wilcox
486f329b923SSean Wilcox n->doc->extSubset = dtd;
487f329b923SSean Wilcox }
488f329b923SSean Wilcox
489f329b923SSean Wilcox vcp = xmlNewValidCtxt();
490f329b923SSean Wilcox if (vcp == NULL)
491f329b923SSean Wilcox uu_die(gettext("could not allocate memory"));
492f329b923SSean Wilcox
493f329b923SSean Wilcox vcp->warning = xmlParserValidityWarning;
494f329b923SSean Wilcox vcp->error = xmlParserValidityError;
495f329b923SSean Wilcox
496f329b923SSean Wilcox if (xmlValidateElement(vcp, n->doc, n) == 0)
497f329b923SSean Wilcox uu_die(gettext("Document is not valid.\n"));
498f329b923SSean Wilcox
499f329b923SSean Wilcox xmlFreeValidCtxt(vcp);
500f329b923SSean Wilcox }
501f329b923SSean Wilcox
5027c478bd9Sstevel@tonic-gate static int
lxml_validate_string_value(scf_type_t type,const char * v)5037c478bd9Sstevel@tonic-gate lxml_validate_string_value(scf_type_t type, const char *v)
5047c478bd9Sstevel@tonic-gate {
5057c478bd9Sstevel@tonic-gate static scf_value_t *scf_value = NULL;
5067c478bd9Sstevel@tonic-gate static scf_handle_t *scf_hndl = NULL;
5077c478bd9Sstevel@tonic-gate
5087c478bd9Sstevel@tonic-gate if (scf_hndl == NULL && (scf_hndl = scf_handle_create(SCF_VERSION)) ==
5097c478bd9Sstevel@tonic-gate NULL)
5107c478bd9Sstevel@tonic-gate return (-1);
5117c478bd9Sstevel@tonic-gate
5127c478bd9Sstevel@tonic-gate if (scf_value == NULL && (scf_value = scf_value_create(scf_hndl)) ==
5137c478bd9Sstevel@tonic-gate NULL)
5147c478bd9Sstevel@tonic-gate return (-1);
5157c478bd9Sstevel@tonic-gate
5167c478bd9Sstevel@tonic-gate return (scf_value_set_from_string(scf_value, type, v));
5177c478bd9Sstevel@tonic-gate }
5187c478bd9Sstevel@tonic-gate
5197c478bd9Sstevel@tonic-gate static void
lxml_free_str(value_t * val)5207c478bd9Sstevel@tonic-gate lxml_free_str(value_t *val)
5217c478bd9Sstevel@tonic-gate {
5227c478bd9Sstevel@tonic-gate free(val->sc_u.sc_string);
5237c478bd9Sstevel@tonic-gate }
5247c478bd9Sstevel@tonic-gate
525f329b923SSean Wilcox /*
526f329b923SSean Wilcox * Take a value_t structure and a type and value. Based on the type
527f329b923SSean Wilcox * ensure that the value is of that type. If so store the value in
528f329b923SSean Wilcox * the correct location of the value_t structure.
529f329b923SSean Wilcox *
530f329b923SSean Wilcox * If the value is NULL, the value_t structure will have been created
531f329b923SSean Wilcox * and the value would have ultimately been stored as a string value
532f329b923SSean Wilcox * but at the time the type was unknown. Now the type should be known
533f329b923SSean Wilcox * so take the type and value from value_t and validate and store
534f329b923SSean Wilcox * the value correctly if the value is of the stated type.
535f329b923SSean Wilcox */
536f329b923SSean Wilcox void
lxml_store_value(value_t * v,element_t type,const xmlChar * value)537f329b923SSean Wilcox lxml_store_value(value_t *v, element_t type, const xmlChar *value)
5387c478bd9Sstevel@tonic-gate {
5397c478bd9Sstevel@tonic-gate char *endptr;
540f329b923SSean Wilcox int fov = 0;
5417c478bd9Sstevel@tonic-gate scf_type_t scf_type = SCF_TYPE_INVALID;
5427c478bd9Sstevel@tonic-gate
543f329b923SSean Wilcox if (value == NULL) {
544f329b923SSean Wilcox type = lxml_type_to_element(v->sc_type);
545f329b923SSean Wilcox value = (const xmlChar *)v->sc_u.sc_string;
546f329b923SSean Wilcox fov = 1;
547f329b923SSean Wilcox }
5487c478bd9Sstevel@tonic-gate
5497c478bd9Sstevel@tonic-gate switch (type) {
5507c478bd9Sstevel@tonic-gate case SC_COUNT:
5517c478bd9Sstevel@tonic-gate /*
5527c478bd9Sstevel@tonic-gate * Although an SC_COUNT represents a uint64_t the use
5537c478bd9Sstevel@tonic-gate * of a negative value is acceptable due to the usage
5547c478bd9Sstevel@tonic-gate * established by inetd(1M).
5557c478bd9Sstevel@tonic-gate */
5567c478bd9Sstevel@tonic-gate errno = 0;
5577c478bd9Sstevel@tonic-gate v->sc_u.sc_count = strtoull((char *)value, &endptr, 10);
5587c478bd9Sstevel@tonic-gate if (errno != 0 || endptr == (char *)value || *endptr)
5597c478bd9Sstevel@tonic-gate uu_die(gettext("illegal value \"%s\" for "
5607c478bd9Sstevel@tonic-gate "%s (%s)\n"), (char *)value,
5617c478bd9Sstevel@tonic-gate lxml_prop_types[type],
5627c478bd9Sstevel@tonic-gate (errno) ? strerror(errno) :
5637c478bd9Sstevel@tonic-gate gettext("Illegal character"));
5647c478bd9Sstevel@tonic-gate break;
5657c478bd9Sstevel@tonic-gate case SC_INTEGER:
5667c478bd9Sstevel@tonic-gate errno = 0;
5677c478bd9Sstevel@tonic-gate v->sc_u.sc_integer = strtoll((char *)value, &endptr, 10);
5687c478bd9Sstevel@tonic-gate if (errno != 0 || *endptr)
5697c478bd9Sstevel@tonic-gate uu_die(gettext("illegal value \"%s\" for "
5707c478bd9Sstevel@tonic-gate "%s (%s)\n"), (char *)value,
5717c478bd9Sstevel@tonic-gate lxml_prop_types[type],
5727c478bd9Sstevel@tonic-gate (errno) ? strerror(errno) : "Illegal character");
5737c478bd9Sstevel@tonic-gate break;
5747c478bd9Sstevel@tonic-gate case SC_OPAQUE:
5757c478bd9Sstevel@tonic-gate case SC_HOST:
5767c478bd9Sstevel@tonic-gate case SC_HOSTNAME:
577f6f041a2SAntonello Cruz case SC_NET_ADDR:
5787c478bd9Sstevel@tonic-gate case SC_NET_ADDR_V4:
5797c478bd9Sstevel@tonic-gate case SC_NET_ADDR_V6:
5807c478bd9Sstevel@tonic-gate case SC_FMRI:
5817c478bd9Sstevel@tonic-gate case SC_URI:
5827c478bd9Sstevel@tonic-gate case SC_TIME:
5837c478bd9Sstevel@tonic-gate case SC_ASTRING:
5847c478bd9Sstevel@tonic-gate case SC_USTRING:
585f329b923SSean Wilcox scf_type = lxml_element_to_type(type);
5867c478bd9Sstevel@tonic-gate
587*67b0e063SAlbert Lee v->sc_u.sc_string = safe_strdup((const char *)value);
5887c478bd9Sstevel@tonic-gate if (lxml_validate_string_value(scf_type,
5897c478bd9Sstevel@tonic-gate v->sc_u.sc_string) != 0)
5907c478bd9Sstevel@tonic-gate uu_die(gettext("illegal value \"%s\" for "
5917c478bd9Sstevel@tonic-gate "%s (%s)\n"), (char *)value,
5927c478bd9Sstevel@tonic-gate lxml_prop_types[type],
5937c478bd9Sstevel@tonic-gate (scf_error()) ? scf_strerror(scf_error()) :
5947c478bd9Sstevel@tonic-gate gettext("Illegal format"));
5957c478bd9Sstevel@tonic-gate v->sc_free = lxml_free_str;
5967c478bd9Sstevel@tonic-gate break;
5977c478bd9Sstevel@tonic-gate case SC_BOOLEAN:
5987c478bd9Sstevel@tonic-gate v->sc_u.sc_count = lxml_xlate_boolean(value);
5997c478bd9Sstevel@tonic-gate break;
6007c478bd9Sstevel@tonic-gate default:
6017c478bd9Sstevel@tonic-gate uu_die(gettext("unknown value type (%d)\n"), type);
6027c478bd9Sstevel@tonic-gate break;
6037c478bd9Sstevel@tonic-gate }
6047c478bd9Sstevel@tonic-gate
605f329b923SSean Wilcox /* Free the old value */
606f329b923SSean Wilcox if (fov && v->sc_free != NULL)
607f329b923SSean Wilcox free((char *)value);
608f329b923SSean Wilcox }
609f329b923SSean Wilcox
610f329b923SSean Wilcox static value_t *
lxml_make_value(element_t type,const xmlChar * value)611f329b923SSean Wilcox lxml_make_value(element_t type, const xmlChar *value)
612f329b923SSean Wilcox {
613f329b923SSean Wilcox value_t *v;
614f329b923SSean Wilcox
615f329b923SSean Wilcox v = internal_value_new();
616f329b923SSean Wilcox
617f329b923SSean Wilcox v->sc_type = lxml_element_to_type(type);
618f329b923SSean Wilcox
619f329b923SSean Wilcox lxml_store_value(v, type, value);
620f329b923SSean Wilcox
6217c478bd9Sstevel@tonic-gate return (v);
6227c478bd9Sstevel@tonic-gate }
6237c478bd9Sstevel@tonic-gate
6247c478bd9Sstevel@tonic-gate static int
lxml_get_value(property_t * prop,element_t vtype,xmlNodePtr value)6257c478bd9Sstevel@tonic-gate lxml_get_value(property_t *prop, element_t vtype, xmlNodePtr value)
6267c478bd9Sstevel@tonic-gate {
6277c478bd9Sstevel@tonic-gate xmlNodePtr cursor;
6287c478bd9Sstevel@tonic-gate
6297c478bd9Sstevel@tonic-gate for (cursor = value->xmlChildrenNode; cursor != NULL;
6307c478bd9Sstevel@tonic-gate cursor = cursor->next) {
6317c478bd9Sstevel@tonic-gate xmlChar *assigned_value;
6327c478bd9Sstevel@tonic-gate value_t *v;
6337c478bd9Sstevel@tonic-gate
6347c478bd9Sstevel@tonic-gate if (lxml_ignorable_block(cursor))
6357c478bd9Sstevel@tonic-gate continue;
6367c478bd9Sstevel@tonic-gate
6377c478bd9Sstevel@tonic-gate switch (lxml_xlate_element(cursor->name)) {
6387c478bd9Sstevel@tonic-gate case SC_VALUE_NODE:
6397c478bd9Sstevel@tonic-gate if ((assigned_value = xmlGetProp(cursor,
6407c478bd9Sstevel@tonic-gate (xmlChar *)value_attr)) == NULL)
6417c478bd9Sstevel@tonic-gate uu_die(gettext("no value on value node?\n"));
6427c478bd9Sstevel@tonic-gate break;
6437c478bd9Sstevel@tonic-gate default:
6447c478bd9Sstevel@tonic-gate uu_die(gettext("value list contains illegal element "
6457c478bd9Sstevel@tonic-gate "\'%s\'\n"), cursor->name);
6467c478bd9Sstevel@tonic-gate break;
6477c478bd9Sstevel@tonic-gate }
6487c478bd9Sstevel@tonic-gate
6497c478bd9Sstevel@tonic-gate v = lxml_make_value(vtype, assigned_value);
6507c478bd9Sstevel@tonic-gate
6517c478bd9Sstevel@tonic-gate xmlFree(assigned_value);
6527c478bd9Sstevel@tonic-gate
6537c478bd9Sstevel@tonic-gate internal_attach_value(prop, v);
6547c478bd9Sstevel@tonic-gate }
6557c478bd9Sstevel@tonic-gate
6567c478bd9Sstevel@tonic-gate return (0);
6577c478bd9Sstevel@tonic-gate }
6587c478bd9Sstevel@tonic-gate
6597c478bd9Sstevel@tonic-gate static int
lxml_get_propval(pgroup_t * pgrp,xmlNodePtr propval)6607c478bd9Sstevel@tonic-gate lxml_get_propval(pgroup_t *pgrp, xmlNodePtr propval)
6617c478bd9Sstevel@tonic-gate {
6627c478bd9Sstevel@tonic-gate property_t *p;
6637c478bd9Sstevel@tonic-gate element_t r;
6647c478bd9Sstevel@tonic-gate value_t *v;
6657c478bd9Sstevel@tonic-gate xmlChar *type, *val, *override;
666f329b923SSean Wilcox int op = pgrp->sc_parent->sc_op;
6677c478bd9Sstevel@tonic-gate
6687c478bd9Sstevel@tonic-gate p = internal_property_new();
6697c478bd9Sstevel@tonic-gate
6707c478bd9Sstevel@tonic-gate p->sc_property_name = (char *)xmlGetProp(propval, (xmlChar *)name_attr);
6711f6eb021SLiane Praza if ((p->sc_property_name == NULL) || (*p->sc_property_name == 0))
6727c478bd9Sstevel@tonic-gate uu_die(gettext("property name missing in group '%s'\n"),
6737c478bd9Sstevel@tonic-gate pgrp->sc_pgroup_name);
6747c478bd9Sstevel@tonic-gate
6757c478bd9Sstevel@tonic-gate type = xmlGetProp(propval, (xmlChar *)type_attr);
676f329b923SSean Wilcox if ((type != NULL) && (*type != 0)) {
677f329b923SSean Wilcox for (r = 0;
678f329b923SSean Wilcox r < sizeof (lxml_prop_types) / sizeof (char *); ++r) {
679f329b923SSean Wilcox if (xmlStrcmp(type,
680f329b923SSean Wilcox (const xmlChar *)lxml_prop_types[r]) == 0)
6817c478bd9Sstevel@tonic-gate break;
6827c478bd9Sstevel@tonic-gate }
683f329b923SSean Wilcox
6847c478bd9Sstevel@tonic-gate if (r >= sizeof (lxml_prop_types) / sizeof (char *))
685f329b923SSean Wilcox uu_die(gettext("property type invalid for "
686f329b923SSean Wilcox "property '%s/%s'\n"), pgrp->sc_pgroup_name,
687f329b923SSean Wilcox p->sc_property_name);
6887c478bd9Sstevel@tonic-gate
6897c478bd9Sstevel@tonic-gate p->sc_value_type = lxml_element_to_type(r);
690f329b923SSean Wilcox } else if (op == SVCCFG_OP_APPLY) {
691f329b923SSean Wilcox /*
692f329b923SSean Wilcox * Store the property type as invalid, and the value
693f329b923SSean Wilcox * as an ASTRING and let the bundle apply code validate
694f329b923SSean Wilcox * the type/value once the type is found.
695f329b923SSean Wilcox */
696f329b923SSean Wilcox est->sc_miss_type = B_TRUE;
697f329b923SSean Wilcox p->sc_value_type = SCF_TYPE_INVALID;
698f329b923SSean Wilcox r = SC_ASTRING;
699f329b923SSean Wilcox } else {
700f329b923SSean Wilcox uu_die(gettext("property type missing for property '%s/%s'\n"),
701f329b923SSean Wilcox pgrp->sc_pgroup_name, p->sc_property_name);
702f329b923SSean Wilcox }
7037c478bd9Sstevel@tonic-gate
7047c478bd9Sstevel@tonic-gate val = xmlGetProp(propval, (xmlChar *)value_attr);
7057c478bd9Sstevel@tonic-gate if (val == NULL)
7067c478bd9Sstevel@tonic-gate uu_die(gettext("property value missing for property '%s/%s'\n"),
7077c478bd9Sstevel@tonic-gate pgrp->sc_pgroup_name, p->sc_property_name);
7087c478bd9Sstevel@tonic-gate
7097c478bd9Sstevel@tonic-gate v = lxml_make_value(r, val);
7101f6eb021SLiane Praza xmlFree(val);
7117c478bd9Sstevel@tonic-gate internal_attach_value(p, v);
7127c478bd9Sstevel@tonic-gate
713f329b923SSean Wilcox xmlFree(type);
714f329b923SSean Wilcox
7157c478bd9Sstevel@tonic-gate override = xmlGetProp(propval, (xmlChar *)override_attr);
7167c478bd9Sstevel@tonic-gate p->sc_property_override = (xmlStrcmp(override, (xmlChar *)true) == 0);
7177c478bd9Sstevel@tonic-gate xmlFree(override);
7187c478bd9Sstevel@tonic-gate
7197c478bd9Sstevel@tonic-gate return (internal_attach_property(pgrp, p));
7207c478bd9Sstevel@tonic-gate }
7217c478bd9Sstevel@tonic-gate
7227c478bd9Sstevel@tonic-gate static int
lxml_get_property(pgroup_t * pgrp,xmlNodePtr property)7237c478bd9Sstevel@tonic-gate lxml_get_property(pgroup_t *pgrp, xmlNodePtr property)
7247c478bd9Sstevel@tonic-gate {
7257c478bd9Sstevel@tonic-gate property_t *p;
7267c478bd9Sstevel@tonic-gate xmlNodePtr cursor;
7277c478bd9Sstevel@tonic-gate element_t r;
7287c478bd9Sstevel@tonic-gate xmlChar *type, *override;
729f329b923SSean Wilcox int op = pgrp->sc_parent->sc_op;
7307c478bd9Sstevel@tonic-gate
7317c478bd9Sstevel@tonic-gate p = internal_property_new();
7327c478bd9Sstevel@tonic-gate
7331f6eb021SLiane Praza if (((p->sc_property_name = (char *)xmlGetProp(property,
7341f6eb021SLiane Praza (xmlChar *)name_attr)) == NULL) || (*p->sc_property_name == 0))
7357c478bd9Sstevel@tonic-gate uu_die(gettext("property name missing in group \'%s\'\n"),
7367c478bd9Sstevel@tonic-gate pgrp->sc_pgroup_name);
7377c478bd9Sstevel@tonic-gate
738f329b923SSean Wilcox type = xmlGetProp(property, (xmlChar *)type_attr);
739f329b923SSean Wilcox if ((type != NULL) && (*type != 0)) {
740f329b923SSean Wilcox for (r = 0;
741f329b923SSean Wilcox r < sizeof (lxml_prop_types) / sizeof (char *); r++) {
742f329b923SSean Wilcox if (xmlStrcmp(type,
743f329b923SSean Wilcox (const xmlChar *)lxml_prop_types[r]) == 0)
744f329b923SSean Wilcox break;
745f329b923SSean Wilcox }
746f329b923SSean Wilcox
747f329b923SSean Wilcox if (r >= sizeof (lxml_prop_types) / sizeof (char *))
748f329b923SSean Wilcox uu_die(gettext("property type invalid for "
749f329b923SSean Wilcox "property '%s/%s'\n"), pgrp->sc_pgroup_name,
750f329b923SSean Wilcox p->sc_property_name);
751f329b923SSean Wilcox
752f329b923SSean Wilcox p->sc_value_type = lxml_element_to_type(r);
753f329b923SSean Wilcox } else if (op == SVCCFG_OP_APPLY) {
754f329b923SSean Wilcox /*
755f329b923SSean Wilcox * Store the property type as invalid, and let the bundle apply
756f329b923SSean Wilcox * code validate the type/value once the type is found.
757f329b923SSean Wilcox */
758f329b923SSean Wilcox p->sc_value_type = SCF_TYPE_INVALID;
759f329b923SSean Wilcox est->sc_miss_type = B_TRUE;
760f329b923SSean Wilcox } else {
7617c478bd9Sstevel@tonic-gate uu_die(gettext("property type missing for "
7627c478bd9Sstevel@tonic-gate "property \'%s/%s\'\n"), pgrp->sc_pgroup_name,
7637c478bd9Sstevel@tonic-gate p->sc_property_name);
7641f6eb021SLiane Praza }
7657c478bd9Sstevel@tonic-gate
7667c478bd9Sstevel@tonic-gate for (cursor = property->xmlChildrenNode; cursor != NULL;
7677c478bd9Sstevel@tonic-gate cursor = cursor->next) {
7687c478bd9Sstevel@tonic-gate if (lxml_ignorable_block(cursor))
7697c478bd9Sstevel@tonic-gate continue;
7707c478bd9Sstevel@tonic-gate
7717c478bd9Sstevel@tonic-gate switch (r = lxml_xlate_element(cursor->name)) {
7727c478bd9Sstevel@tonic-gate case SC_ASTRING:
7737c478bd9Sstevel@tonic-gate case SC_BOOLEAN:
7747c478bd9Sstevel@tonic-gate case SC_COUNT:
7757c478bd9Sstevel@tonic-gate case SC_FMRI:
7767c478bd9Sstevel@tonic-gate case SC_HOST:
7777c478bd9Sstevel@tonic-gate case SC_HOSTNAME:
7787c478bd9Sstevel@tonic-gate case SC_INTEGER:
779f6f041a2SAntonello Cruz case SC_NET_ADDR:
7807c478bd9Sstevel@tonic-gate case SC_NET_ADDR_V4:
7817c478bd9Sstevel@tonic-gate case SC_NET_ADDR_V6:
7827c478bd9Sstevel@tonic-gate case SC_OPAQUE:
7837c478bd9Sstevel@tonic-gate case SC_TIME:
7847c478bd9Sstevel@tonic-gate case SC_URI:
7857c478bd9Sstevel@tonic-gate case SC_USTRING:
786f329b923SSean Wilcox /*
787f329b923SSean Wilcox * If the type is invalid then this is an apply
788f329b923SSean Wilcox * operation and the type can be taken from the
789f329b923SSean Wilcox * value list.
790f329b923SSean Wilcox */
791f329b923SSean Wilcox if (p->sc_value_type == SCF_TYPE_INVALID) {
792f329b923SSean Wilcox p->sc_value_type = lxml_element_to_type(r);
793f329b923SSean Wilcox type = xmlStrdup((const
794f329b923SSean Wilcox xmlChar *)lxml_prop_types[r]);
795f329b923SSean Wilcox
796f329b923SSean Wilcox } else if (strcmp(lxml_prop_types[r],
797f329b923SSean Wilcox (const char *)type) != 0) {
7987c478bd9Sstevel@tonic-gate uu_die(gettext("property \'%s\' "
7997c478bd9Sstevel@tonic-gate "type-to-list mismatch\n"),
8007c478bd9Sstevel@tonic-gate p->sc_property_name);
801f329b923SSean Wilcox }
8027c478bd9Sstevel@tonic-gate
8037c478bd9Sstevel@tonic-gate (void) lxml_get_value(p, r, cursor);
8047c478bd9Sstevel@tonic-gate break;
8057c478bd9Sstevel@tonic-gate default:
8067c478bd9Sstevel@tonic-gate uu_die(gettext("unknown value list type: %s\n"),
8077c478bd9Sstevel@tonic-gate cursor->name);
8087c478bd9Sstevel@tonic-gate break;
8097c478bd9Sstevel@tonic-gate }
8107c478bd9Sstevel@tonic-gate }
8117c478bd9Sstevel@tonic-gate
8127c478bd9Sstevel@tonic-gate xmlFree(type);
8137c478bd9Sstevel@tonic-gate
8147c478bd9Sstevel@tonic-gate override = xmlGetProp(property, (xmlChar *)override_attr);
8157c478bd9Sstevel@tonic-gate p->sc_property_override = (xmlStrcmp(override, (xmlChar *)true) == 0);
8167c478bd9Sstevel@tonic-gate xmlFree(override);
8177c478bd9Sstevel@tonic-gate
8187c478bd9Sstevel@tonic-gate return (internal_attach_property(pgrp, p));
8197c478bd9Sstevel@tonic-gate }
8207c478bd9Sstevel@tonic-gate
8217c478bd9Sstevel@tonic-gate static int
lxml_get_pgroup_stability(pgroup_t * pgrp,xmlNodePtr stab)8227c478bd9Sstevel@tonic-gate lxml_get_pgroup_stability(pgroup_t *pgrp, xmlNodePtr stab)
8237c478bd9Sstevel@tonic-gate {
824f329b923SSean Wilcox if (pgrp->sc_parent->sc_op == SVCCFG_OP_APPLY)
825f329b923SSean Wilcox lxml_validate_element(stab);
826f329b923SSean Wilcox
8277c478bd9Sstevel@tonic-gate return (new_str_prop_from_attr(pgrp, SCF_PROPERTY_STABILITY,
8287c478bd9Sstevel@tonic-gate SCF_TYPE_ASTRING, stab, value_attr));
8297c478bd9Sstevel@tonic-gate }
8307c478bd9Sstevel@tonic-gate
8317c478bd9Sstevel@tonic-gate /*
8327c478bd9Sstevel@tonic-gate * Property groups can go on any of a service, an instance, or a template.
8337c478bd9Sstevel@tonic-gate */
8347c478bd9Sstevel@tonic-gate static int
lxml_get_pgroup(entity_t * entity,xmlNodePtr pgroup)8357c478bd9Sstevel@tonic-gate lxml_get_pgroup(entity_t *entity, xmlNodePtr pgroup)
8367c478bd9Sstevel@tonic-gate {
8377c478bd9Sstevel@tonic-gate pgroup_t *pg;
8387c478bd9Sstevel@tonic-gate xmlNodePtr cursor;
8397c478bd9Sstevel@tonic-gate xmlChar *name, *type, *delete;
8407c478bd9Sstevel@tonic-gate
8417c478bd9Sstevel@tonic-gate /*
8427c478bd9Sstevel@tonic-gate * property group attributes:
8437c478bd9Sstevel@tonic-gate * name: string
8447c478bd9Sstevel@tonic-gate * type: string | framework | application
8457c478bd9Sstevel@tonic-gate */
8467c478bd9Sstevel@tonic-gate name = xmlGetProp(pgroup, (xmlChar *)name_attr);
8477c478bd9Sstevel@tonic-gate type = xmlGetProp(pgroup, (xmlChar *)type_attr);
8487c478bd9Sstevel@tonic-gate pg = internal_pgroup_find_or_create(entity, (char *)name, (char *)type);
8497c478bd9Sstevel@tonic-gate xmlFree(name);
8507c478bd9Sstevel@tonic-gate xmlFree(type);
8517c478bd9Sstevel@tonic-gate
8527c478bd9Sstevel@tonic-gate /*
8537c478bd9Sstevel@tonic-gate * Walk the children of this lxml_elements, which are a stability
8547c478bd9Sstevel@tonic-gate * element, property elements, or propval elements.
8557c478bd9Sstevel@tonic-gate */
8567c478bd9Sstevel@tonic-gate for (cursor = pgroup->xmlChildrenNode; cursor != NULL;
8577c478bd9Sstevel@tonic-gate cursor = cursor->next) {
8587c478bd9Sstevel@tonic-gate if (lxml_ignorable_block(cursor))
8597c478bd9Sstevel@tonic-gate continue;
8607c478bd9Sstevel@tonic-gate
8617c478bd9Sstevel@tonic-gate switch (lxml_xlate_element(cursor->name)) {
8627c478bd9Sstevel@tonic-gate case SC_STABILITY:
8637c478bd9Sstevel@tonic-gate (void) lxml_get_pgroup_stability(pg, cursor);
8647c478bd9Sstevel@tonic-gate break;
8657c478bd9Sstevel@tonic-gate case SC_PROPERTY:
8667c478bd9Sstevel@tonic-gate (void) lxml_get_property(pg, cursor);
8677c478bd9Sstevel@tonic-gate break;
8687c478bd9Sstevel@tonic-gate case SC_PROPVAL:
8697c478bd9Sstevel@tonic-gate (void) lxml_get_propval(pg, cursor);
8707c478bd9Sstevel@tonic-gate break;
8717c478bd9Sstevel@tonic-gate default:
8727c478bd9Sstevel@tonic-gate abort();
8737c478bd9Sstevel@tonic-gate break;
8747c478bd9Sstevel@tonic-gate }
8757c478bd9Sstevel@tonic-gate }
8767c478bd9Sstevel@tonic-gate
8777c478bd9Sstevel@tonic-gate delete = xmlGetProp(pgroup, (xmlChar *)delete_attr);
8787c478bd9Sstevel@tonic-gate pg->sc_pgroup_delete = (xmlStrcmp(delete, (xmlChar *)true) == 0);
8797c478bd9Sstevel@tonic-gate xmlFree(delete);
8807c478bd9Sstevel@tonic-gate
8817c478bd9Sstevel@tonic-gate return (0);
8827c478bd9Sstevel@tonic-gate }
8837c478bd9Sstevel@tonic-gate
8847c478bd9Sstevel@tonic-gate
8857c478bd9Sstevel@tonic-gate /*
8867c478bd9Sstevel@tonic-gate * Dependency groups, execution methods can go on either a service or an
8877c478bd9Sstevel@tonic-gate * instance.
8887c478bd9Sstevel@tonic-gate */
8897c478bd9Sstevel@tonic-gate
8907c478bd9Sstevel@tonic-gate static int
lxml_get_method_profile(pgroup_t * pg,xmlNodePtr profile)8917c478bd9Sstevel@tonic-gate lxml_get_method_profile(pgroup_t *pg, xmlNodePtr profile)
8927c478bd9Sstevel@tonic-gate {
8937c478bd9Sstevel@tonic-gate property_t *p;
8947c478bd9Sstevel@tonic-gate
8957c478bd9Sstevel@tonic-gate p = internal_property_create(SCF_PROPERTY_USE_PROFILE, SCF_TYPE_BOOLEAN,
8967c478bd9Sstevel@tonic-gate 1, (uint64_t)1);
8977c478bd9Sstevel@tonic-gate if (internal_attach_property(pg, p) != 0)
8987c478bd9Sstevel@tonic-gate return (-1);
8997c478bd9Sstevel@tonic-gate
9007c478bd9Sstevel@tonic-gate return (new_str_prop_from_attr(pg, SCF_PROPERTY_PROFILE,
9017c478bd9Sstevel@tonic-gate SCF_TYPE_ASTRING, profile, name_attr));
9027c478bd9Sstevel@tonic-gate }
9037c478bd9Sstevel@tonic-gate
9047c478bd9Sstevel@tonic-gate static int
lxml_get_method_credential(pgroup_t * pg,xmlNodePtr cred)9057c478bd9Sstevel@tonic-gate lxml_get_method_credential(pgroup_t *pg, xmlNodePtr cred)
9067c478bd9Sstevel@tonic-gate {
9077c478bd9Sstevel@tonic-gate property_t *p;
9087c478bd9Sstevel@tonic-gate
9097c478bd9Sstevel@tonic-gate p = internal_property_create(SCF_PROPERTY_USE_PROFILE, SCF_TYPE_BOOLEAN,
9107c478bd9Sstevel@tonic-gate 1, (uint64_t)0);
9117c478bd9Sstevel@tonic-gate if (internal_attach_property(pg, p) != 0)
9127c478bd9Sstevel@tonic-gate return (-1);
9137c478bd9Sstevel@tonic-gate
91413d8aaa1SSean Wilcox if (new_opt_str_prop_from_attr(pg, SCF_PROPERTY_USER, SCF_TYPE_ASTRING,
91513d8aaa1SSean Wilcox cred, "user", NULL) != 0)
9167c478bd9Sstevel@tonic-gate return (-1);
9177c478bd9Sstevel@tonic-gate
91813d8aaa1SSean Wilcox if (new_opt_str_prop_from_attr(pg, SCF_PROPERTY_GROUP, SCF_TYPE_ASTRING,
91913d8aaa1SSean Wilcox cred, "group", NULL) != 0)
9207c478bd9Sstevel@tonic-gate return (-1);
9217c478bd9Sstevel@tonic-gate
92213d8aaa1SSean Wilcox if (new_opt_str_prop_from_attr(pg, SCF_PROPERTY_SUPP_GROUPS,
92313d8aaa1SSean Wilcox SCF_TYPE_ASTRING, cred, "supp_groups", NULL) != 0)
9247c478bd9Sstevel@tonic-gate return (-1);
9257c478bd9Sstevel@tonic-gate
92613d8aaa1SSean Wilcox if (new_opt_str_prop_from_attr(pg, SCF_PROPERTY_PRIVILEGES,
92713d8aaa1SSean Wilcox SCF_TYPE_ASTRING, cred, "privileges", NULL) != 0)
9287c478bd9Sstevel@tonic-gate return (-1);
9297c478bd9Sstevel@tonic-gate
93013d8aaa1SSean Wilcox if (new_opt_str_prop_from_attr(pg, SCF_PROPERTY_LIMIT_PRIVILEGES,
93113d8aaa1SSean Wilcox SCF_TYPE_ASTRING, cred, "limit_privileges", NULL) != 0)
9327c478bd9Sstevel@tonic-gate return (-1);
9337c478bd9Sstevel@tonic-gate
9347c478bd9Sstevel@tonic-gate return (0);
9357c478bd9Sstevel@tonic-gate }
9367c478bd9Sstevel@tonic-gate
9377c478bd9Sstevel@tonic-gate static char *
lxml_get_envvar(xmlNodePtr envvar)9387c478bd9Sstevel@tonic-gate lxml_get_envvar(xmlNodePtr envvar)
9397c478bd9Sstevel@tonic-gate {
9407c478bd9Sstevel@tonic-gate char *name;
9417c478bd9Sstevel@tonic-gate char *value;
9427c478bd9Sstevel@tonic-gate char *ret;
9437c478bd9Sstevel@tonic-gate
9441f6eb021SLiane Praza name = (char *)xmlGetProp(envvar, (xmlChar *)name_attr);
9451f6eb021SLiane Praza value = (char *)xmlGetProp(envvar, (xmlChar *)value_attr);
9467c478bd9Sstevel@tonic-gate
9477c478bd9Sstevel@tonic-gate if (strlen(name) == 0 || strchr(name, '=') != NULL)
9487c478bd9Sstevel@tonic-gate uu_die(gettext("Invalid environment variable "
9497c478bd9Sstevel@tonic-gate "\"%s\".\n"), name);
9507c478bd9Sstevel@tonic-gate if (strstr(name, "SMF_") == name)
9517c478bd9Sstevel@tonic-gate uu_die(gettext("Invalid environment variable "
9527c478bd9Sstevel@tonic-gate "\"%s\"; \"SMF_\" prefix is reserved.\n"), name);
9537c478bd9Sstevel@tonic-gate
9547c478bd9Sstevel@tonic-gate ret = uu_msprintf("%s=%s", name, value);
9557c478bd9Sstevel@tonic-gate xmlFree(name);
9567c478bd9Sstevel@tonic-gate xmlFree(value);
9577c478bd9Sstevel@tonic-gate return (ret);
9587c478bd9Sstevel@tonic-gate }
9597c478bd9Sstevel@tonic-gate
9607c478bd9Sstevel@tonic-gate static int
lxml_get_method_environment(pgroup_t * pg,xmlNodePtr environment)9617c478bd9Sstevel@tonic-gate lxml_get_method_environment(pgroup_t *pg, xmlNodePtr environment)
9627c478bd9Sstevel@tonic-gate {
9637c478bd9Sstevel@tonic-gate property_t *p;
9647c478bd9Sstevel@tonic-gate xmlNodePtr cursor;
9657c478bd9Sstevel@tonic-gate value_t *val;
9667c478bd9Sstevel@tonic-gate
9677c478bd9Sstevel@tonic-gate p = internal_property_create(SCF_PROPERTY_ENVIRONMENT,
9687c478bd9Sstevel@tonic-gate SCF_TYPE_ASTRING, 0);
9697c478bd9Sstevel@tonic-gate
9707c478bd9Sstevel@tonic-gate for (cursor = environment->xmlChildrenNode; cursor != NULL;
9717c478bd9Sstevel@tonic-gate cursor = cursor->next) {
9727c478bd9Sstevel@tonic-gate char *tmp;
9737c478bd9Sstevel@tonic-gate
9747c478bd9Sstevel@tonic-gate if (lxml_ignorable_block(cursor))
9757c478bd9Sstevel@tonic-gate continue;
9767c478bd9Sstevel@tonic-gate
9777c478bd9Sstevel@tonic-gate if (lxml_xlate_element(cursor->name) != SC_METHOD_ENVVAR)
9787c478bd9Sstevel@tonic-gate uu_die(gettext("illegal element \"%s\" on "
9797c478bd9Sstevel@tonic-gate "method environment for \"%s\"\n"),
9807c478bd9Sstevel@tonic-gate cursor->name, pg->sc_pgroup_name);
9817c478bd9Sstevel@tonic-gate
9827c478bd9Sstevel@tonic-gate if ((tmp = lxml_get_envvar(cursor)) == NULL)
9837c478bd9Sstevel@tonic-gate uu_die(gettext("Out of memory\n"));
9847c478bd9Sstevel@tonic-gate
9857c478bd9Sstevel@tonic-gate val = internal_value_new();
9867c478bd9Sstevel@tonic-gate val->sc_u.sc_string = tmp;
9877c478bd9Sstevel@tonic-gate val->sc_type = SCF_TYPE_ASTRING;
9887c478bd9Sstevel@tonic-gate val->sc_free = lxml_free_str;
9897c478bd9Sstevel@tonic-gate internal_attach_value(p, val);
9907c478bd9Sstevel@tonic-gate }
9917c478bd9Sstevel@tonic-gate
9927c478bd9Sstevel@tonic-gate if (internal_attach_property(pg, p) != 0) {
9937c478bd9Sstevel@tonic-gate internal_property_free(p);
9947c478bd9Sstevel@tonic-gate return (-1);
9957c478bd9Sstevel@tonic-gate }
9967c478bd9Sstevel@tonic-gate
9977c478bd9Sstevel@tonic-gate return (0);
9987c478bd9Sstevel@tonic-gate }
9997c478bd9Sstevel@tonic-gate
10007c478bd9Sstevel@tonic-gate static int
lxml_get_method_context(pgroup_t * pg,xmlNodePtr ctx)10017c478bd9Sstevel@tonic-gate lxml_get_method_context(pgroup_t *pg, xmlNodePtr ctx)
10027c478bd9Sstevel@tonic-gate {
10037c478bd9Sstevel@tonic-gate xmlNodePtr cursor;
10047c478bd9Sstevel@tonic-gate
100513d8aaa1SSean Wilcox if (new_opt_str_prop_from_attr(pg, SCF_PROPERTY_WORKING_DIRECTORY,
100613d8aaa1SSean Wilcox SCF_TYPE_ASTRING, ctx, "working_directory", NULL) != 0)
10077c478bd9Sstevel@tonic-gate return (-1);
10087c478bd9Sstevel@tonic-gate
100913d8aaa1SSean Wilcox if (new_opt_str_prop_from_attr(pg, SCF_PROPERTY_PROJECT,
101013d8aaa1SSean Wilcox SCF_TYPE_ASTRING, ctx, "project", NULL) != 0)
10117c478bd9Sstevel@tonic-gate return (-1);
10127c478bd9Sstevel@tonic-gate
101313d8aaa1SSean Wilcox if (new_opt_str_prop_from_attr(pg, SCF_PROPERTY_RESOURCE_POOL,
101413d8aaa1SSean Wilcox SCF_TYPE_ASTRING, ctx, "resource_pool", NULL) != 0)
10157c478bd9Sstevel@tonic-gate return (-1);
10167c478bd9Sstevel@tonic-gate
10177c478bd9Sstevel@tonic-gate for (cursor = ctx->xmlChildrenNode; cursor != NULL;
10187c478bd9Sstevel@tonic-gate cursor = cursor->next) {
10197c478bd9Sstevel@tonic-gate if (lxml_ignorable_block(cursor))
10207c478bd9Sstevel@tonic-gate continue;
10217c478bd9Sstevel@tonic-gate
10227c478bd9Sstevel@tonic-gate switch (lxml_xlate_element(cursor->name)) {
10237c478bd9Sstevel@tonic-gate case SC_METHOD_CREDENTIAL:
10247c478bd9Sstevel@tonic-gate (void) lxml_get_method_credential(pg, cursor);
10257c478bd9Sstevel@tonic-gate break;
10267c478bd9Sstevel@tonic-gate case SC_METHOD_PROFILE:
10277c478bd9Sstevel@tonic-gate (void) lxml_get_method_profile(pg, cursor);
10287c478bd9Sstevel@tonic-gate break;
10297c478bd9Sstevel@tonic-gate case SC_METHOD_ENVIRONMENT:
10307c478bd9Sstevel@tonic-gate (void) lxml_get_method_environment(pg, cursor);
10317c478bd9Sstevel@tonic-gate break;
10327c478bd9Sstevel@tonic-gate default:
10337c478bd9Sstevel@tonic-gate semerr(gettext("illegal element \'%s\' in method "
10347c478bd9Sstevel@tonic-gate "context\n"), (char *)cursor);
10357c478bd9Sstevel@tonic-gate break;
10367c478bd9Sstevel@tonic-gate }
10377c478bd9Sstevel@tonic-gate }
10387c478bd9Sstevel@tonic-gate
10397c478bd9Sstevel@tonic-gate return (0);
10407c478bd9Sstevel@tonic-gate }
10417c478bd9Sstevel@tonic-gate
10427c478bd9Sstevel@tonic-gate static int
lxml_get_entity_method_context(entity_t * entity,xmlNodePtr ctx)10437c478bd9Sstevel@tonic-gate lxml_get_entity_method_context(entity_t *entity, xmlNodePtr ctx)
10447c478bd9Sstevel@tonic-gate {
10457c478bd9Sstevel@tonic-gate pgroup_t *pg;
10467c478bd9Sstevel@tonic-gate
10477c478bd9Sstevel@tonic-gate pg = internal_pgroup_find_or_create(entity, SCF_PG_METHOD_CONTEXT,
10487c478bd9Sstevel@tonic-gate (char *)scf_group_framework);
10497c478bd9Sstevel@tonic-gate
10507c478bd9Sstevel@tonic-gate return (lxml_get_method_context(pg, ctx));
10517c478bd9Sstevel@tonic-gate }
10527c478bd9Sstevel@tonic-gate
10537c478bd9Sstevel@tonic-gate static int
lxml_get_exec_method(entity_t * entity,xmlNodePtr emeth)10547c478bd9Sstevel@tonic-gate lxml_get_exec_method(entity_t *entity, xmlNodePtr emeth)
10557c478bd9Sstevel@tonic-gate {
10567c478bd9Sstevel@tonic-gate pgroup_t *pg;
10577c478bd9Sstevel@tonic-gate property_t *p;
10587c478bd9Sstevel@tonic-gate xmlChar *name, *timeout, *delete;
10597c478bd9Sstevel@tonic-gate xmlNodePtr cursor;
10607c478bd9Sstevel@tonic-gate int r = 0;
10617c478bd9Sstevel@tonic-gate
1062f329b923SSean Wilcox if (entity->sc_op == SVCCFG_OP_APPLY)
1063f329b923SSean Wilcox lxml_validate_element(emeth);
1064f329b923SSean Wilcox
10657c478bd9Sstevel@tonic-gate name = xmlGetProp(emeth, (xmlChar *)name_attr);
10667c478bd9Sstevel@tonic-gate pg = internal_pgroup_find_or_create(entity, (char *)name,
10677c478bd9Sstevel@tonic-gate (char *)SCF_GROUP_METHOD);
10687c478bd9Sstevel@tonic-gate xmlFree(name);
10697c478bd9Sstevel@tonic-gate
10707c478bd9Sstevel@tonic-gate if (new_str_prop_from_attr(pg, SCF_PROPERTY_TYPE, SCF_TYPE_ASTRING,
10717c478bd9Sstevel@tonic-gate emeth, type_attr) != 0 ||
10727c478bd9Sstevel@tonic-gate new_str_prop_from_attr(pg, SCF_PROPERTY_EXEC, SCF_TYPE_ASTRING,
10737c478bd9Sstevel@tonic-gate emeth, "exec") != 0)
10747c478bd9Sstevel@tonic-gate return (-1);
10757c478bd9Sstevel@tonic-gate
10761f6eb021SLiane Praza timeout = xmlGetProp(emeth, (xmlChar *)timeout_seconds_attr);
10777c478bd9Sstevel@tonic-gate if (timeout != NULL) {
10787c478bd9Sstevel@tonic-gate uint64_t u_timeout;
10797c478bd9Sstevel@tonic-gate char *endptr;
10807c478bd9Sstevel@tonic-gate /*
10817c478bd9Sstevel@tonic-gate * Although an SC_COUNT represents a uint64_t the use
10827c478bd9Sstevel@tonic-gate * of a negative value is acceptable due to the usage
10837c478bd9Sstevel@tonic-gate * established by inetd(1M).
10847c478bd9Sstevel@tonic-gate */
10857c478bd9Sstevel@tonic-gate errno = 0;
10867c478bd9Sstevel@tonic-gate u_timeout = strtoull((char *)timeout, &endptr, 10);
10877c478bd9Sstevel@tonic-gate if (errno != 0 || endptr == (char *)timeout || *endptr)
10887c478bd9Sstevel@tonic-gate uu_die(gettext("illegal value \"%s\" for "
10897c478bd9Sstevel@tonic-gate "timeout_seconds (%s)\n"),
10907c478bd9Sstevel@tonic-gate (char *)timeout, (errno) ? strerror(errno):
10917c478bd9Sstevel@tonic-gate gettext("Illegal character"));
10927c478bd9Sstevel@tonic-gate p = internal_property_create(SCF_PROPERTY_TIMEOUT,
10937c478bd9Sstevel@tonic-gate SCF_TYPE_COUNT, 1, u_timeout);
10947c478bd9Sstevel@tonic-gate r = internal_attach_property(pg, p);
10957c478bd9Sstevel@tonic-gate xmlFree(timeout);
10967c478bd9Sstevel@tonic-gate }
10977c478bd9Sstevel@tonic-gate if (r != 0)
10987c478bd9Sstevel@tonic-gate return (-1);
10997c478bd9Sstevel@tonic-gate
11007c478bd9Sstevel@tonic-gate /*
11017c478bd9Sstevel@tonic-gate * There is a possibility that a method context also exists, in which
11027c478bd9Sstevel@tonic-gate * case the following attributes are defined: project, resource_pool,
11037c478bd9Sstevel@tonic-gate * working_directory, profile, user, group, privileges, limit_privileges
11047c478bd9Sstevel@tonic-gate */
11057c478bd9Sstevel@tonic-gate for (cursor = emeth->xmlChildrenNode; cursor != NULL;
11067c478bd9Sstevel@tonic-gate cursor = cursor->next) {
11077c478bd9Sstevel@tonic-gate if (lxml_ignorable_block(cursor))
11087c478bd9Sstevel@tonic-gate continue;
11097c478bd9Sstevel@tonic-gate
11107c478bd9Sstevel@tonic-gate switch (lxml_xlate_element(cursor->name)) {
11117c478bd9Sstevel@tonic-gate case SC_STABILITY:
11127c478bd9Sstevel@tonic-gate if (lxml_get_pgroup_stability(pg, cursor) != 0)
11137c478bd9Sstevel@tonic-gate return (-1);
11147c478bd9Sstevel@tonic-gate break;
11157c478bd9Sstevel@tonic-gate
11167c478bd9Sstevel@tonic-gate case SC_METHOD_CONTEXT:
11177c478bd9Sstevel@tonic-gate (void) lxml_get_method_context(pg, cursor);
11187c478bd9Sstevel@tonic-gate break;
11197c478bd9Sstevel@tonic-gate
11207c478bd9Sstevel@tonic-gate case SC_PROPVAL:
11217c478bd9Sstevel@tonic-gate (void) lxml_get_propval(pg, cursor);
11227c478bd9Sstevel@tonic-gate break;
11237c478bd9Sstevel@tonic-gate
11247c478bd9Sstevel@tonic-gate case SC_PROPERTY:
11257c478bd9Sstevel@tonic-gate (void) lxml_get_property(pg, cursor);
11267c478bd9Sstevel@tonic-gate break;
11277c478bd9Sstevel@tonic-gate
11287c478bd9Sstevel@tonic-gate default:
11297c478bd9Sstevel@tonic-gate uu_die(gettext("illegal element \"%s\" on "
11307c478bd9Sstevel@tonic-gate "execution method \"%s\"\n"), cursor->name,
11317c478bd9Sstevel@tonic-gate pg->sc_pgroup_name);
11327c478bd9Sstevel@tonic-gate break;
11337c478bd9Sstevel@tonic-gate }
11347c478bd9Sstevel@tonic-gate }
11357c478bd9Sstevel@tonic-gate
11367c478bd9Sstevel@tonic-gate delete = xmlGetProp(emeth, (xmlChar *)delete_attr);
11377c478bd9Sstevel@tonic-gate pg->sc_pgroup_delete = (xmlStrcmp(delete, (xmlChar *)true) == 0);
11387c478bd9Sstevel@tonic-gate xmlFree(delete);
11397c478bd9Sstevel@tonic-gate
11407c478bd9Sstevel@tonic-gate return (0);
11417c478bd9Sstevel@tonic-gate }
11427c478bd9Sstevel@tonic-gate
11437c478bd9Sstevel@tonic-gate static int
lxml_get_dependency(entity_t * entity,xmlNodePtr dependency)11447c478bd9Sstevel@tonic-gate lxml_get_dependency(entity_t *entity, xmlNodePtr dependency)
11457c478bd9Sstevel@tonic-gate {
11467c478bd9Sstevel@tonic-gate pgroup_t *pg;
11477c478bd9Sstevel@tonic-gate property_t *p;
11487c478bd9Sstevel@tonic-gate xmlNodePtr cursor;
11497c478bd9Sstevel@tonic-gate xmlChar *name;
11507c478bd9Sstevel@tonic-gate xmlChar *delete;
11517c478bd9Sstevel@tonic-gate
11527c478bd9Sstevel@tonic-gate /*
11537c478bd9Sstevel@tonic-gate * dependency attributes:
11547c478bd9Sstevel@tonic-gate * name: string
11557c478bd9Sstevel@tonic-gate * grouping: require_all | require_any | exclude_all | optional_all
11567c478bd9Sstevel@tonic-gate * reset_on: string (error | restart | refresh | none)
11577c478bd9Sstevel@tonic-gate * type: service / path /host
11587c478bd9Sstevel@tonic-gate */
11597c478bd9Sstevel@tonic-gate
1160f329b923SSean Wilcox if (entity->sc_op == SVCCFG_OP_APPLY)
1161f329b923SSean Wilcox lxml_validate_element(dependency);
1162f329b923SSean Wilcox
11637c478bd9Sstevel@tonic-gate name = xmlGetProp(dependency, (xmlChar *)name_attr);
11647c478bd9Sstevel@tonic-gate pg = internal_pgroup_find_or_create(entity, (char *)name,
11657c478bd9Sstevel@tonic-gate (char *)SCF_GROUP_DEPENDENCY);
11667c478bd9Sstevel@tonic-gate xmlFree(name);
11677c478bd9Sstevel@tonic-gate
11687c478bd9Sstevel@tonic-gate if (new_str_prop_from_attr(pg, SCF_PROPERTY_TYPE, SCF_TYPE_ASTRING,
11697c478bd9Sstevel@tonic-gate dependency, type_attr) != 0)
11707c478bd9Sstevel@tonic-gate return (-1);
11717c478bd9Sstevel@tonic-gate
11727c478bd9Sstevel@tonic-gate if (new_str_prop_from_attr(pg, SCF_PROPERTY_RESTART_ON,
11737c478bd9Sstevel@tonic-gate SCF_TYPE_ASTRING, dependency, "restart_on") != 0)
11747c478bd9Sstevel@tonic-gate return (-1);
11757c478bd9Sstevel@tonic-gate
11767c478bd9Sstevel@tonic-gate if (new_str_prop_from_attr(pg, SCF_PROPERTY_GROUPING, SCF_TYPE_ASTRING,
11777c478bd9Sstevel@tonic-gate dependency, "grouping") != 0)
11787c478bd9Sstevel@tonic-gate return (-1);
11797c478bd9Sstevel@tonic-gate
11807c478bd9Sstevel@tonic-gate p = internal_property_create(SCF_PROPERTY_ENTITIES, SCF_TYPE_FMRI, 0);
11817c478bd9Sstevel@tonic-gate if (internal_attach_property(pg, p) != 0)
11827c478bd9Sstevel@tonic-gate return (-1);
11837c478bd9Sstevel@tonic-gate
11847c478bd9Sstevel@tonic-gate for (cursor = dependency->xmlChildrenNode; cursor != NULL;
11857c478bd9Sstevel@tonic-gate cursor = cursor->next) {
11867c478bd9Sstevel@tonic-gate xmlChar *value;
11877c478bd9Sstevel@tonic-gate value_t *v;
11887c478bd9Sstevel@tonic-gate
11897c478bd9Sstevel@tonic-gate if (lxml_ignorable_block(cursor))
11907c478bd9Sstevel@tonic-gate continue;
11917c478bd9Sstevel@tonic-gate
11927c478bd9Sstevel@tonic-gate switch (lxml_xlate_element(cursor->name)) {
11937c478bd9Sstevel@tonic-gate case SC_STABILITY:
11947c478bd9Sstevel@tonic-gate if (lxml_get_pgroup_stability(pg, cursor) != 0)
11957c478bd9Sstevel@tonic-gate return (-1);
11967c478bd9Sstevel@tonic-gate break;
11977c478bd9Sstevel@tonic-gate
11987c478bd9Sstevel@tonic-gate case SC_SERVICE_FMRI:
11997c478bd9Sstevel@tonic-gate value = xmlGetProp(cursor, (xmlChar *)value_attr);
12007c478bd9Sstevel@tonic-gate if (value != NULL) {
12017c478bd9Sstevel@tonic-gate if (lxml_validate_string_value(SCF_TYPE_FMRI,
12027c478bd9Sstevel@tonic-gate (char *)value) != 0)
12037c478bd9Sstevel@tonic-gate uu_die(gettext("illegal value \"%s\" "
12047c478bd9Sstevel@tonic-gate "for %s (%s)\n"), (char *)value,
12057c478bd9Sstevel@tonic-gate lxml_prop_types[SC_FMRI],
12067c478bd9Sstevel@tonic-gate (scf_error()) ?
12077c478bd9Sstevel@tonic-gate scf_strerror(scf_error()) :
12087c478bd9Sstevel@tonic-gate gettext("Illegal format"));
12097c478bd9Sstevel@tonic-gate v = internal_value_new();
12107c478bd9Sstevel@tonic-gate v->sc_type = SCF_TYPE_FMRI;
12117c478bd9Sstevel@tonic-gate v->sc_u.sc_string = (char *)value;
12127c478bd9Sstevel@tonic-gate internal_attach_value(p, v);
12137c478bd9Sstevel@tonic-gate }
12147c478bd9Sstevel@tonic-gate
12157c478bd9Sstevel@tonic-gate break;
12167c478bd9Sstevel@tonic-gate
12177c478bd9Sstevel@tonic-gate case SC_PROPVAL:
12187c478bd9Sstevel@tonic-gate (void) lxml_get_propval(pg, cursor);
12197c478bd9Sstevel@tonic-gate break;
12207c478bd9Sstevel@tonic-gate
12217c478bd9Sstevel@tonic-gate case SC_PROPERTY:
12227c478bd9Sstevel@tonic-gate (void) lxml_get_property(pg, cursor);
12237c478bd9Sstevel@tonic-gate break;
12247c478bd9Sstevel@tonic-gate
12257c478bd9Sstevel@tonic-gate default:
12267c478bd9Sstevel@tonic-gate uu_die(gettext("illegal element \"%s\" on "
12277c478bd9Sstevel@tonic-gate "dependency group \"%s\"\n"), cursor->name, name);
12287c478bd9Sstevel@tonic-gate break;
12297c478bd9Sstevel@tonic-gate }
12307c478bd9Sstevel@tonic-gate }
12317c478bd9Sstevel@tonic-gate
12327c478bd9Sstevel@tonic-gate delete = xmlGetProp(dependency, (xmlChar *)delete_attr);
12337c478bd9Sstevel@tonic-gate pg->sc_pgroup_delete = (xmlStrcmp(delete, (xmlChar *)true) == 0);
12347c478bd9Sstevel@tonic-gate xmlFree(delete);
12357c478bd9Sstevel@tonic-gate
12367c478bd9Sstevel@tonic-gate return (0);
12377c478bd9Sstevel@tonic-gate }
12387c478bd9Sstevel@tonic-gate
12397c478bd9Sstevel@tonic-gate /*
12407c478bd9Sstevel@tonic-gate * Dependents are hairy. They should cause a dependency pg to be created in
12417c478bd9Sstevel@tonic-gate * another service, but we can't do that here; we'll have to wait until the
12427c478bd9Sstevel@tonic-gate * import routines. So for now we'll add the dependency group that should go
12437c478bd9Sstevel@tonic-gate * in the other service to the entity's dependent list.
12447c478bd9Sstevel@tonic-gate */
12457c478bd9Sstevel@tonic-gate static int
lxml_get_dependent(entity_t * entity,xmlNodePtr dependent)12467c478bd9Sstevel@tonic-gate lxml_get_dependent(entity_t *entity, xmlNodePtr dependent)
12477c478bd9Sstevel@tonic-gate {
12487c478bd9Sstevel@tonic-gate xmlChar *name, *or;
12497c478bd9Sstevel@tonic-gate xmlNodePtr sf;
12507c478bd9Sstevel@tonic-gate xmlChar *fmri, *delete;
12517c478bd9Sstevel@tonic-gate pgroup_t *pg;
12527c478bd9Sstevel@tonic-gate property_t *p;
12537c478bd9Sstevel@tonic-gate xmlNodePtr n;
12547c478bd9Sstevel@tonic-gate char *myfmri;
12557c478bd9Sstevel@tonic-gate
1256f329b923SSean Wilcox if (entity->sc_op == SVCCFG_OP_APPLY)
1257f329b923SSean Wilcox lxml_validate_element(dependent);
1258f329b923SSean Wilcox
12597c478bd9Sstevel@tonic-gate name = xmlGetProp(dependent, (xmlChar *)name_attr);
12607c478bd9Sstevel@tonic-gate
12617c478bd9Sstevel@tonic-gate if (internal_pgroup_find(entity, (char *)name, NULL) != NULL) {
12627c478bd9Sstevel@tonic-gate semerr(gettext("Property group and dependent of entity %s "
12637c478bd9Sstevel@tonic-gate "have same name \"%s\".\n"), entity->sc_name, name);
12647c478bd9Sstevel@tonic-gate xmlFree(name);
12657c478bd9Sstevel@tonic-gate return (-1);
12667c478bd9Sstevel@tonic-gate }
12677c478bd9Sstevel@tonic-gate
12687c478bd9Sstevel@tonic-gate or = xmlGetProp(dependent, (xmlChar *)override_attr);
12697c478bd9Sstevel@tonic-gate
12707c478bd9Sstevel@tonic-gate pg = internal_pgroup_new();
12717c478bd9Sstevel@tonic-gate pg->sc_pgroup_name = (char *)name;
12727c478bd9Sstevel@tonic-gate pg->sc_pgroup_type = (char *)SCF_GROUP_DEPENDENCY;
12737c478bd9Sstevel@tonic-gate pg->sc_pgroup_override = (xmlStrcmp(or, (xmlChar *)true) == 0);
12747c478bd9Sstevel@tonic-gate xmlFree(or);
12757c478bd9Sstevel@tonic-gate if (internal_attach_dependent(entity, pg) != 0) {
12767c478bd9Sstevel@tonic-gate xmlFree(name);
12777c478bd9Sstevel@tonic-gate internal_pgroup_free(pg);
12787c478bd9Sstevel@tonic-gate return (-1);
12797c478bd9Sstevel@tonic-gate }
12807c478bd9Sstevel@tonic-gate
12817c478bd9Sstevel@tonic-gate for (sf = dependent->children; sf != NULL; sf = sf->next)
12827c478bd9Sstevel@tonic-gate if (xmlStrcmp(sf->name, (xmlChar *)"service_fmri") == 0)
12837c478bd9Sstevel@tonic-gate break;
12847c478bd9Sstevel@tonic-gate assert(sf != NULL);
12857c478bd9Sstevel@tonic-gate fmri = xmlGetProp(sf, (xmlChar *)value_attr);
12867c478bd9Sstevel@tonic-gate pg->sc_pgroup_fmri = (char *)fmri;
12877c478bd9Sstevel@tonic-gate
12887c478bd9Sstevel@tonic-gate if (new_str_prop_from_attr(pg, SCF_PROPERTY_RESTART_ON,
12897c478bd9Sstevel@tonic-gate SCF_TYPE_ASTRING, dependent, "restart_on") != 0)
12907c478bd9Sstevel@tonic-gate return (-1);
12917c478bd9Sstevel@tonic-gate
12927c478bd9Sstevel@tonic-gate if (new_str_prop_from_attr(pg, SCF_PROPERTY_GROUPING, SCF_TYPE_ASTRING,
12937c478bd9Sstevel@tonic-gate dependent, "grouping") != 0)
12947c478bd9Sstevel@tonic-gate return (-1);
12957c478bd9Sstevel@tonic-gate
12967c478bd9Sstevel@tonic-gate myfmri = safe_malloc(max_scf_fmri_len + 1);
12977c478bd9Sstevel@tonic-gate if (entity->sc_etype == SVCCFG_SERVICE_OBJECT) {
12987c478bd9Sstevel@tonic-gate if (snprintf(myfmri, max_scf_fmri_len + 1, "svc:/%s",
12997c478bd9Sstevel@tonic-gate entity->sc_name) < 0)
13007c478bd9Sstevel@tonic-gate bad_error("snprintf", errno);
13017c478bd9Sstevel@tonic-gate } else {
13027c478bd9Sstevel@tonic-gate assert(entity->sc_etype == SVCCFG_INSTANCE_OBJECT);
13037c478bd9Sstevel@tonic-gate if (snprintf(myfmri, max_scf_fmri_len + 1, "svc:/%s:%s",
13047c478bd9Sstevel@tonic-gate entity->sc_parent->sc_name, entity->sc_name) < 0)
13057c478bd9Sstevel@tonic-gate bad_error("snprintf", errno);
13067c478bd9Sstevel@tonic-gate }
13077c478bd9Sstevel@tonic-gate
13087c478bd9Sstevel@tonic-gate p = internal_property_create(SCF_PROPERTY_ENTITIES, SCF_TYPE_FMRI, 1,
13097c478bd9Sstevel@tonic-gate myfmri);
13107c478bd9Sstevel@tonic-gate if (internal_attach_property(pg, p) != 0)
13117c478bd9Sstevel@tonic-gate return (-1);
13127c478bd9Sstevel@tonic-gate
13137c478bd9Sstevel@tonic-gate /* Create a property to serve as a do-not-export flag. */
13147c478bd9Sstevel@tonic-gate p = internal_property_create("external", SCF_TYPE_BOOLEAN, 1,
13157c478bd9Sstevel@tonic-gate (uint64_t)1);
13167c478bd9Sstevel@tonic-gate if (internal_attach_property(pg, p) != 0)
13177c478bd9Sstevel@tonic-gate return (-1);
13187c478bd9Sstevel@tonic-gate
13197c478bd9Sstevel@tonic-gate for (n = sf->next; n != NULL; n = n->next) {
13207c478bd9Sstevel@tonic-gate if (lxml_ignorable_block(n))
13217c478bd9Sstevel@tonic-gate continue;
13227c478bd9Sstevel@tonic-gate
13237c478bd9Sstevel@tonic-gate switch (lxml_xlate_element(n->name)) {
13247c478bd9Sstevel@tonic-gate case SC_STABILITY:
13257c478bd9Sstevel@tonic-gate if (new_str_prop_from_attr(pg,
13267c478bd9Sstevel@tonic-gate SCF_PROPERTY_ENTITY_STABILITY, SCF_TYPE_ASTRING, n,
13277c478bd9Sstevel@tonic-gate value_attr) != 0)
13287c478bd9Sstevel@tonic-gate return (-1);
13297c478bd9Sstevel@tonic-gate break;
13307c478bd9Sstevel@tonic-gate
13317c478bd9Sstevel@tonic-gate case SC_PROPVAL:
13327c478bd9Sstevel@tonic-gate (void) lxml_get_propval(pg, n);
13337c478bd9Sstevel@tonic-gate break;
13347c478bd9Sstevel@tonic-gate
13357c478bd9Sstevel@tonic-gate case SC_PROPERTY:
13367c478bd9Sstevel@tonic-gate (void) lxml_get_property(pg, n);
13377c478bd9Sstevel@tonic-gate break;
13387c478bd9Sstevel@tonic-gate
13397c478bd9Sstevel@tonic-gate default:
13407c478bd9Sstevel@tonic-gate uu_die(gettext("unexpected element %s.\n"), n->name);
13417c478bd9Sstevel@tonic-gate }
13427c478bd9Sstevel@tonic-gate }
13437c478bd9Sstevel@tonic-gate
13447c478bd9Sstevel@tonic-gate /* Go back and fill in defaults. */
13457c478bd9Sstevel@tonic-gate if (internal_property_find(pg, SCF_PROPERTY_TYPE) == NULL) {
13467c478bd9Sstevel@tonic-gate p = internal_property_create(SCF_PROPERTY_TYPE,
13477c478bd9Sstevel@tonic-gate SCF_TYPE_ASTRING, 1, "service");
13487c478bd9Sstevel@tonic-gate if (internal_attach_property(pg, p) != 0)
13497c478bd9Sstevel@tonic-gate return (-1);
13507c478bd9Sstevel@tonic-gate }
13517c478bd9Sstevel@tonic-gate
13527c478bd9Sstevel@tonic-gate delete = xmlGetProp(dependent, (xmlChar *)delete_attr);
13537c478bd9Sstevel@tonic-gate pg->sc_pgroup_delete = (xmlStrcmp(delete, (xmlChar *)true) == 0);
13547c478bd9Sstevel@tonic-gate xmlFree(delete);
13557c478bd9Sstevel@tonic-gate
13567c478bd9Sstevel@tonic-gate pg = internal_pgroup_find_or_create(entity, "dependents",
13577c478bd9Sstevel@tonic-gate (char *)scf_group_framework);
13589e9ae1fcSbustos p = internal_property_create((char *)name, SCF_TYPE_FMRI, 1, fmri);
13597c478bd9Sstevel@tonic-gate if (internal_attach_property(pg, p) != 0)
13607c478bd9Sstevel@tonic-gate return (-1);
13617c478bd9Sstevel@tonic-gate
13627c478bd9Sstevel@tonic-gate return (0);
13637c478bd9Sstevel@tonic-gate }
13647c478bd9Sstevel@tonic-gate
13657c478bd9Sstevel@tonic-gate static int
lxml_get_entity_stability(entity_t * entity,xmlNodePtr rstr)13667c478bd9Sstevel@tonic-gate lxml_get_entity_stability(entity_t *entity, xmlNodePtr rstr)
13677c478bd9Sstevel@tonic-gate {
13687c478bd9Sstevel@tonic-gate pgroup_t *pg;
13697c478bd9Sstevel@tonic-gate property_t *p;
13707c478bd9Sstevel@tonic-gate xmlChar *stabval;
13717c478bd9Sstevel@tonic-gate
13721f6eb021SLiane Praza if (((stabval = xmlGetProp(rstr, (xmlChar *)value_attr)) == NULL) ||
13731f6eb021SLiane Praza (*stabval == 0)) {
13747c478bd9Sstevel@tonic-gate uu_warn(gettext("no stability value found\n"));
1375*67b0e063SAlbert Lee stabval = (xmlChar *)safe_strdup("External");
13767c478bd9Sstevel@tonic-gate }
13777c478bd9Sstevel@tonic-gate
13787c478bd9Sstevel@tonic-gate pg = internal_pgroup_find_or_create(entity, (char *)scf_pg_general,
13797c478bd9Sstevel@tonic-gate (char *)scf_group_framework);
13807c478bd9Sstevel@tonic-gate
13817c478bd9Sstevel@tonic-gate p = internal_property_create(SCF_PROPERTY_ENTITY_STABILITY,
13827c478bd9Sstevel@tonic-gate SCF_TYPE_ASTRING, 1, stabval);
13837c478bd9Sstevel@tonic-gate
13847c478bd9Sstevel@tonic-gate return (internal_attach_property(pg, p));
13857c478bd9Sstevel@tonic-gate }
13867c478bd9Sstevel@tonic-gate
13877c478bd9Sstevel@tonic-gate static int
lxml_get_restarter(entity_t * entity,xmlNodePtr rstr)13887c478bd9Sstevel@tonic-gate lxml_get_restarter(entity_t *entity, xmlNodePtr rstr)
13897c478bd9Sstevel@tonic-gate {
13907c478bd9Sstevel@tonic-gate pgroup_t *pg;
13917c478bd9Sstevel@tonic-gate property_t *p;
13927c478bd9Sstevel@tonic-gate xmlChar *restarter;
13937c478bd9Sstevel@tonic-gate xmlNode *cursor;
13947c478bd9Sstevel@tonic-gate int r;
13957c478bd9Sstevel@tonic-gate
13967c478bd9Sstevel@tonic-gate /*
13977c478bd9Sstevel@tonic-gate * Go find child. Child is a service_fmri element. value attribute
13987c478bd9Sstevel@tonic-gate * contains restarter FMRI.
13997c478bd9Sstevel@tonic-gate */
14007c478bd9Sstevel@tonic-gate
14017c478bd9Sstevel@tonic-gate pg = internal_pgroup_find_or_create(entity, (char *)scf_pg_general,
14027c478bd9Sstevel@tonic-gate (char *)scf_group_framework);
14037c478bd9Sstevel@tonic-gate
14047c478bd9Sstevel@tonic-gate /*
14057c478bd9Sstevel@tonic-gate * Walk its child elements, as appropriate.
14067c478bd9Sstevel@tonic-gate */
14077c478bd9Sstevel@tonic-gate for (cursor = rstr->xmlChildrenNode; cursor != NULL;
14087c478bd9Sstevel@tonic-gate cursor = cursor->next) {
14097c478bd9Sstevel@tonic-gate if (lxml_ignorable_block(cursor))
14107c478bd9Sstevel@tonic-gate continue;
14117c478bd9Sstevel@tonic-gate
14127c478bd9Sstevel@tonic-gate switch (lxml_xlate_element(cursor->name)) {
14137c478bd9Sstevel@tonic-gate case SC_SERVICE_FMRI:
14147c478bd9Sstevel@tonic-gate restarter = xmlGetProp(cursor, (xmlChar *)value_attr);
14157c478bd9Sstevel@tonic-gate break;
14167c478bd9Sstevel@tonic-gate default:
14177c478bd9Sstevel@tonic-gate uu_die(gettext("illegal element \"%s\" on restarter "
14187c478bd9Sstevel@tonic-gate "element for \"%s\"\n"), cursor->name,
14197c478bd9Sstevel@tonic-gate entity->sc_name);
14207c478bd9Sstevel@tonic-gate break;
14217c478bd9Sstevel@tonic-gate }
14227c478bd9Sstevel@tonic-gate }
14237c478bd9Sstevel@tonic-gate
14247c478bd9Sstevel@tonic-gate p = internal_property_create(SCF_PROPERTY_RESTARTER, SCF_TYPE_FMRI, 1,
14257c478bd9Sstevel@tonic-gate restarter);
14267c478bd9Sstevel@tonic-gate
14277c478bd9Sstevel@tonic-gate r = internal_attach_property(pg, p);
14287c478bd9Sstevel@tonic-gate if (r != 0) {
14297c478bd9Sstevel@tonic-gate internal_property_free(p);
14307c478bd9Sstevel@tonic-gate return (-1);
14317c478bd9Sstevel@tonic-gate }
14327c478bd9Sstevel@tonic-gate
14337c478bd9Sstevel@tonic-gate return (0);
14347c478bd9Sstevel@tonic-gate }
14357c478bd9Sstevel@tonic-gate
1436f6e214c7SGavin Maltby static void
lxml_get_paramval(pgroup_t * pgrp,const char * propname,xmlNodePtr pval)1437f6e214c7SGavin Maltby lxml_get_paramval(pgroup_t *pgrp, const char *propname, xmlNodePtr pval)
1438f6e214c7SGavin Maltby {
1439f6e214c7SGavin Maltby property_t *p;
1440f6e214c7SGavin Maltby char *value;
1441f6e214c7SGavin Maltby char *prop;
1442f6e214c7SGavin Maltby
1443*67b0e063SAlbert Lee prop = safe_strdup(propname);
1444f6e214c7SGavin Maltby
1445f6e214c7SGavin Maltby value = (char *)xmlGetProp(pval, (xmlChar *)value_attr);
1446f6e214c7SGavin Maltby if (value == NULL || *value == '\0')
1447f6e214c7SGavin Maltby uu_die(gettext("property value missing for property '%s/%s'\n"),
1448f6e214c7SGavin Maltby pgrp->sc_pgroup_name, propname);
1449f6e214c7SGavin Maltby p = internal_property_create(prop, SCF_TYPE_ASTRING, 1, value);
1450f6e214c7SGavin Maltby
1451f6e214c7SGavin Maltby (void) internal_attach_property(pgrp, p);
1452f6e214c7SGavin Maltby }
1453f6e214c7SGavin Maltby
1454f6e214c7SGavin Maltby static void
lxml_get_parameter(pgroup_t * pgrp,const char * propname,xmlNodePtr param)1455f6e214c7SGavin Maltby lxml_get_parameter(pgroup_t *pgrp, const char *propname, xmlNodePtr param)
1456f6e214c7SGavin Maltby {
1457f6e214c7SGavin Maltby property_t *p = internal_property_new();
1458f6e214c7SGavin Maltby
1459*67b0e063SAlbert Lee p->sc_property_name = safe_strdup(propname);
1460f6e214c7SGavin Maltby p->sc_value_type = SCF_TYPE_ASTRING;
1461f6e214c7SGavin Maltby
1462f6e214c7SGavin Maltby (void) lxml_get_value(p, SC_ASTRING, param);
1463f6e214c7SGavin Maltby
1464f6e214c7SGavin Maltby (void) internal_attach_property(pgrp, p);
1465f6e214c7SGavin Maltby }
1466f6e214c7SGavin Maltby
1467f6e214c7SGavin Maltby static void
lxml_get_type(pgroup_t * pgrp,xmlNodePtr type)1468f6e214c7SGavin Maltby lxml_get_type(pgroup_t *pgrp, xmlNodePtr type)
1469f6e214c7SGavin Maltby {
1470f6e214c7SGavin Maltby property_t *p;
1471f6e214c7SGavin Maltby xmlChar *name;
1472f6e214c7SGavin Maltby xmlChar *active;
1473f6e214c7SGavin Maltby xmlNodePtr cursor;
1474f6e214c7SGavin Maltby uint64_t active_val;
1475f6e214c7SGavin Maltby size_t sz = max_scf_name_len + 1;
1476f6e214c7SGavin Maltby char *propname = safe_malloc(sz);
1477f6e214c7SGavin Maltby
1478f6e214c7SGavin Maltby if (pgrp->sc_parent->sc_op == SVCCFG_OP_APPLY)
1479f6e214c7SGavin Maltby lxml_validate_element(type);
1480f6e214c7SGavin Maltby
1481f6e214c7SGavin Maltby name = xmlGetProp(type, (xmlChar *)name_attr);
1482f6e214c7SGavin Maltby if (name == NULL || *name == '\0')
1483f6e214c7SGavin Maltby uu_die(gettext("attribute name missing in element 'type'\n"));
1484f6e214c7SGavin Maltby
1485f6e214c7SGavin Maltby for (cursor = type->xmlChildrenNode; cursor != NULL;
1486f6e214c7SGavin Maltby cursor = cursor->next) {
1487f6e214c7SGavin Maltby xmlChar *pname;
1488f6e214c7SGavin Maltby
1489f6e214c7SGavin Maltby if (lxml_ignorable_block(cursor))
1490f6e214c7SGavin Maltby continue;
1491f6e214c7SGavin Maltby
1492f6e214c7SGavin Maltby pname = xmlGetProp(cursor, (xmlChar *)name_attr);
1493f6e214c7SGavin Maltby if (pname == NULL || *pname == '\0')
1494f6e214c7SGavin Maltby uu_die(gettext(
1495f6e214c7SGavin Maltby "attribute name missing in sub-element of type\n"));
1496f6e214c7SGavin Maltby
1497f6e214c7SGavin Maltby if (snprintf(propname, sz, "%s,%s", (char *)name,
1498f6e214c7SGavin Maltby (char *)pname) >= sz)
1499f6e214c7SGavin Maltby uu_die(gettext("name '%s,%s' is too long\n"),
1500f6e214c7SGavin Maltby (char *)name, (char *)pname);
1501f6e214c7SGavin Maltby xmlFree(pname);
1502f6e214c7SGavin Maltby
1503f6e214c7SGavin Maltby switch (lxml_xlate_element(cursor->name)) {
1504f6e214c7SGavin Maltby case SC_PARAMETER:
1505f6e214c7SGavin Maltby lxml_get_parameter(pgrp, propname, cursor);
1506f6e214c7SGavin Maltby break;
1507f6e214c7SGavin Maltby
1508f6e214c7SGavin Maltby case SC_PARAMVAL:
1509f6e214c7SGavin Maltby lxml_get_paramval(pgrp, propname, cursor);
1510f6e214c7SGavin Maltby break;
1511f6e214c7SGavin Maltby
1512f6e214c7SGavin Maltby default:
1513f6e214c7SGavin Maltby uu_die(gettext("unknown element %s\n"), cursor->name);
1514f6e214c7SGavin Maltby }
1515f6e214c7SGavin Maltby }
1516f6e214c7SGavin Maltby
1517f6e214c7SGavin Maltby active = xmlGetProp(type, (xmlChar *)active_attr);
1518f6e214c7SGavin Maltby if (active == NULL || strcmp(true, (const char *)active) == 0)
1519f6e214c7SGavin Maltby active_val = 1;
1520f6e214c7SGavin Maltby else
1521f6e214c7SGavin Maltby active_val = 0;
1522f6e214c7SGavin Maltby xmlFree(active);
1523f6e214c7SGavin Maltby
1524f6e214c7SGavin Maltby if (snprintf(propname, sz, "%s,%s", (char *)name,
1525f6e214c7SGavin Maltby SCF_PROPERTY_ACTIVE_POSTFIX) >= sz)
1526f6e214c7SGavin Maltby uu_die(gettext("name '%s,%s' is too long\n"),
1527f6e214c7SGavin Maltby (char *)name, SCF_PROPERTY_ACTIVE_POSTFIX);
1528f6e214c7SGavin Maltby
1529f6e214c7SGavin Maltby p = internal_property_create(propname, SCF_TYPE_BOOLEAN, 1, active_val);
1530f6e214c7SGavin Maltby
1531f6e214c7SGavin Maltby (void) internal_attach_property(pgrp, p);
1532f6e214c7SGavin Maltby
1533f6e214c7SGavin Maltby xmlFree(name);
1534f6e214c7SGavin Maltby }
1535f6e214c7SGavin Maltby
1536f6e214c7SGavin Maltby static void
lxml_get_event(entity_t * entity,const char * pgname,xmlNodePtr np)1537f6e214c7SGavin Maltby lxml_get_event(entity_t *entity, const char *pgname, xmlNodePtr np)
1538f6e214c7SGavin Maltby {
1539f6e214c7SGavin Maltby xmlNodePtr cursor;
1540f6e214c7SGavin Maltby pgroup_t *pgrp;
1541f6e214c7SGavin Maltby
1542f6e214c7SGavin Maltby pgrp = internal_pgroup_find_or_create(entity, pgname,
1543f6e214c7SGavin Maltby SCF_NOTIFY_PARAMS_PG_TYPE);
1544f6e214c7SGavin Maltby for (cursor = np->xmlChildrenNode; cursor != NULL;
1545f6e214c7SGavin Maltby cursor = cursor->next) {
1546f6e214c7SGavin Maltby if (lxml_ignorable_block(cursor))
1547f6e214c7SGavin Maltby continue;
1548f6e214c7SGavin Maltby
1549f6e214c7SGavin Maltby switch (lxml_xlate_element(cursor->name)) {
1550f6e214c7SGavin Maltby case SC_EVENT:
1551f6e214c7SGavin Maltby continue;
1552f6e214c7SGavin Maltby
1553f6e214c7SGavin Maltby case SC_TYPE:
1554f6e214c7SGavin Maltby lxml_get_type(pgrp, cursor);
1555f6e214c7SGavin Maltby break;
1556f6e214c7SGavin Maltby
1557f6e214c7SGavin Maltby default:
1558f6e214c7SGavin Maltby uu_warn(gettext("illegal element '%s' on "
1559f6e214c7SGavin Maltby "notification parameters\n"), cursor->name);
1560f6e214c7SGavin Maltby }
1561f6e214c7SGavin Maltby }
1562f6e214c7SGavin Maltby }
1563f6e214c7SGavin Maltby
1564f6e214c7SGavin Maltby static int
lxml_get_notification_parameters(entity_t * entity,xmlNodePtr np)1565f6e214c7SGavin Maltby lxml_get_notification_parameters(entity_t *entity, xmlNodePtr np)
1566f6e214c7SGavin Maltby {
1567f6e214c7SGavin Maltby char *event = NULL;
1568f6e214c7SGavin Maltby char **pgs = NULL;
1569f6e214c7SGavin Maltby char **p;
1570f6e214c7SGavin Maltby char *pgname = NULL;
1571f6e214c7SGavin Maltby xmlNodePtr cursor;
1572f6e214c7SGavin Maltby int32_t tset, t;
1573f6e214c7SGavin Maltby size_t sz = max_scf_name_len + 1;
1574f6e214c7SGavin Maltby int count;
1575f6e214c7SGavin Maltby int r = -1;
1576f6e214c7SGavin Maltby
1577f6e214c7SGavin Maltby for (count = 0, cursor = np->xmlChildrenNode; cursor != NULL;
1578f6e214c7SGavin Maltby cursor = cursor->next) {
1579f6e214c7SGavin Maltby if (lxml_ignorable_block(cursor))
1580f6e214c7SGavin Maltby continue;
1581f6e214c7SGavin Maltby
1582f6e214c7SGavin Maltby if (lxml_xlate_element(cursor->name) == SC_EVENT) {
1583f6e214c7SGavin Maltby xmlChar *s;
1584f6e214c7SGavin Maltby
1585f6e214c7SGavin Maltby count++;
1586f6e214c7SGavin Maltby if (count > 1)
1587f6e214c7SGavin Maltby uu_die(gettext("Can't have more than 1 element "
1588f6e214c7SGavin Maltby "event in a notification parameter\n"));
1589f6e214c7SGavin Maltby s = xmlGetProp(cursor, (xmlChar *)value_attr);
1590f6e214c7SGavin Maltby if (s == NULL || (event = strdup((char *)s)) == NULL)
1591f6e214c7SGavin Maltby uu_die(gettext("couldn't allocate memory"));
1592f6e214c7SGavin Maltby xmlFree(s);
1593f6e214c7SGavin Maltby }
1594f6e214c7SGavin Maltby }
1595f6e214c7SGavin Maltby
1596f6e214c7SGavin Maltby pgs = tokenize(event, ",");
1597f6e214c7SGavin Maltby
1598f6e214c7SGavin Maltby switch (tset = check_tokens(pgs)) {
1599f6e214c7SGavin Maltby case INVALID_TOKENS:
1600f6e214c7SGavin Maltby uu_die(gettext("Invalid input.\n"));
1601f6e214c7SGavin Maltby /*NOTREACHED*/
1602f6e214c7SGavin Maltby case MIXED_TOKENS:
1603f6e214c7SGavin Maltby semerr(gettext("Can't mix SMF and FMA event definitions\n"));
1604f6e214c7SGavin Maltby goto out;
1605f6e214c7SGavin Maltby case FMA_TOKENS:
1606f6e214c7SGavin Maltby /* make sure this is SCF_NOTIFY_PARAMS_INST */
1607f6e214c7SGavin Maltby if (entity->sc_etype != SVCCFG_INSTANCE_OBJECT ||
1608f6e214c7SGavin Maltby strcmp(entity->sc_fmri, SCF_NOTIFY_PARAMS_INST) != 0) {
1609f6e214c7SGavin Maltby semerr(gettext(
1610f6e214c7SGavin Maltby "Non-SMF transition evenst must go to %s\n"),
1611f6e214c7SGavin Maltby SCF_NOTIFY_PARAMS_INST);
1612f6e214c7SGavin Maltby goto out;
1613f6e214c7SGavin Maltby }
1614f6e214c7SGavin Maltby pgname = safe_malloc(sz);
1615f6e214c7SGavin Maltby for (p = pgs; *p; ++p) {
1616f6e214c7SGavin Maltby if (snprintf(pgname, sz, "%s,%s", de_tag(*p),
1617f6e214c7SGavin Maltby SCF_NOTIFY_PG_POSTFIX) >= sz)
1618f6e214c7SGavin Maltby uu_die(gettext("event name too long: %s\n"),
1619f6e214c7SGavin Maltby *p);
1620f6e214c7SGavin Maltby
1621f6e214c7SGavin Maltby lxml_get_event(entity, pgname, np);
1622f6e214c7SGavin Maltby }
1623f6e214c7SGavin Maltby
1624f6e214c7SGavin Maltby default: /* smf state transition tokens */
1625f6e214c7SGavin Maltby if (entity->sc_etype == SVCCFG_SERVICE_OBJECT &&
1626f6e214c7SGavin Maltby strcmp(entity->sc_fmri, SCF_SERVICE_GLOBAL) == 0) {
1627f6e214c7SGavin Maltby semerr(gettext(
1628f6e214c7SGavin Maltby "Can't set events for global service\n"));
1629f6e214c7SGavin Maltby goto out;
1630f6e214c7SGavin Maltby }
1631f6e214c7SGavin Maltby for (t = 0x1; t < SCF_STATE_ALL; t <<= 1) {
1632f6e214c7SGavin Maltby if (t & tset) {
1633f6e214c7SGavin Maltby lxml_get_event(entity, tset_to_string(t), np);
1634f6e214c7SGavin Maltby }
1635f6e214c7SGavin Maltby if ((t << 16) & tset) {
1636f6e214c7SGavin Maltby lxml_get_event(entity, tset_to_string(t << 16),
1637f6e214c7SGavin Maltby np);
1638f6e214c7SGavin Maltby }
1639f6e214c7SGavin Maltby }
1640f6e214c7SGavin Maltby }
1641f6e214c7SGavin Maltby
1642f6e214c7SGavin Maltby r = 0;
1643f6e214c7SGavin Maltby out:
1644f6e214c7SGavin Maltby free(pgname);
1645f6e214c7SGavin Maltby free(pgs);
1646f6e214c7SGavin Maltby free(event);
1647f6e214c7SGavin Maltby
1648f6e214c7SGavin Maltby return (r);
1649f6e214c7SGavin Maltby }
1650f6e214c7SGavin Maltby
16511f6eb021SLiane Praza /*
16521f6eb021SLiane Praza * Add a property containing the localized text from the manifest. The
16531f6eb021SLiane Praza * property is added to the property group at pg. The name of the created
16541f6eb021SLiane Praza * property is based on the format at pn_format. This is an snprintf(3C)
16551f6eb021SLiane Praza * format containing a single %s conversion specification. At conversion
16561f6eb021SLiane Praza * time, the %s is replaced by the locale designation.
16571f6eb021SLiane Praza *
16581f6eb021SLiane Praza * source is the source element and it is only used for error messages.
16591f6eb021SLiane Praza */
16607c478bd9Sstevel@tonic-gate static int
lxml_get_loctext(entity_t * service,pgroup_t * pg,xmlNodePtr loctext,const char * pn_format,const char * source)16611f6eb021SLiane Praza lxml_get_loctext(entity_t *service, pgroup_t *pg, xmlNodePtr loctext,
16621f6eb021SLiane Praza const char *pn_format, const char *source)
16637c478bd9Sstevel@tonic-gate {
16641f6eb021SLiane Praza int extra;
16657c478bd9Sstevel@tonic-gate xmlNodePtr cursor;
16667c478bd9Sstevel@tonic-gate xmlChar *val;
16677c478bd9Sstevel@tonic-gate char *stripped, *cp;
16687c478bd9Sstevel@tonic-gate property_t *p;
16691f6eb021SLiane Praza char *prop_name;
16707c478bd9Sstevel@tonic-gate int r;
16717c478bd9Sstevel@tonic-gate
16721f6eb021SLiane Praza if (((val = xmlGetProp(loctext, (xmlChar *)xml_lang_attr)) == NULL) ||
16731f6eb021SLiane Praza (*val == 0)) {
16741f6eb021SLiane Praza if (((val = xmlGetProp(loctext,
16751f6eb021SLiane Praza (xmlChar *)lang_attr)) == NULL) || (*val == 0)) {
16767c478bd9Sstevel@tonic-gate val = (xmlChar *)"unknown";
16771f6eb021SLiane Praza }
16781f6eb021SLiane Praza }
16797c478bd9Sstevel@tonic-gate
16801f6eb021SLiane Praza _scf_sanitize_locale((char *)val);
16811f6eb021SLiane Praza prop_name = safe_malloc(max_scf_name_len + 1);
16821f6eb021SLiane Praza if ((extra = snprintf(prop_name, max_scf_name_len + 1, pn_format,
16831f6eb021SLiane Praza val)) >= max_scf_name_len + 1) {
16841f6eb021SLiane Praza extra -= max_scf_name_len;
16851f6eb021SLiane Praza uu_die(gettext("%s attribute is %d characters too long for "
16861f6eb021SLiane Praza "%s in %s\n"),
16871f6eb021SLiane Praza xml_lang_attr, extra, source, service->sc_name);
16881f6eb021SLiane Praza }
16891f6eb021SLiane Praza xmlFree(val);
16907c478bd9Sstevel@tonic-gate
16917c478bd9Sstevel@tonic-gate for (cursor = loctext->xmlChildrenNode; cursor != NULL;
16927c478bd9Sstevel@tonic-gate cursor = cursor->next) {
16937c478bd9Sstevel@tonic-gate if (strcmp("text", (const char *)cursor->name) == 0) {
16947c478bd9Sstevel@tonic-gate break;
16957c478bd9Sstevel@tonic-gate } else if (strcmp("comment", (const char *)cursor->name) != 0) {
16967c478bd9Sstevel@tonic-gate uu_die(gettext("illegal element \"%s\" on loctext "
16977c478bd9Sstevel@tonic-gate "element for \"%s\"\n"), cursor->name,
16987c478bd9Sstevel@tonic-gate service->sc_name);
16997c478bd9Sstevel@tonic-gate }
17007c478bd9Sstevel@tonic-gate }
17017c478bd9Sstevel@tonic-gate
17027c478bd9Sstevel@tonic-gate if (cursor == NULL) {
17037c478bd9Sstevel@tonic-gate uu_die(gettext("loctext element has no content for \"%s\"\n"),
17047c478bd9Sstevel@tonic-gate service->sc_name);
17057c478bd9Sstevel@tonic-gate }
17067c478bd9Sstevel@tonic-gate
17077c478bd9Sstevel@tonic-gate /*
17087c478bd9Sstevel@tonic-gate * Remove leading and trailing whitespace.
17097c478bd9Sstevel@tonic-gate */
1710*67b0e063SAlbert Lee stripped = safe_strdup((const char *)cursor->content);
17117c478bd9Sstevel@tonic-gate
171276cf44abSjeanm for (; isspace(*stripped); stripped++)
171376cf44abSjeanm ;
171476cf44abSjeanm for (cp = stripped + strlen(stripped) - 1; isspace(*cp); cp--)
171576cf44abSjeanm ;
17167c478bd9Sstevel@tonic-gate *(cp + 1) = '\0';
17177c478bd9Sstevel@tonic-gate
17181f6eb021SLiane Praza p = internal_property_create(prop_name, SCF_TYPE_USTRING, 1,
17197c478bd9Sstevel@tonic-gate stripped);
17207c478bd9Sstevel@tonic-gate
17217c478bd9Sstevel@tonic-gate r = internal_attach_property(pg, p);
17221f6eb021SLiane Praza if (r != 0) {
17237c478bd9Sstevel@tonic-gate internal_property_free(p);
17241f6eb021SLiane Praza free(prop_name);
17251f6eb021SLiane Praza }
17267c478bd9Sstevel@tonic-gate
17277c478bd9Sstevel@tonic-gate return (r);
17287c478bd9Sstevel@tonic-gate }
17297c478bd9Sstevel@tonic-gate
17301f6eb021SLiane Praza /*
17311f6eb021SLiane Praza * This function processes all loctext elements in the current XML element
17321f6eb021SLiane Praza * designated by container. A property is created for each loctext element
17331f6eb021SLiane Praza * and added to the property group at pg. The name of the property is
17341f6eb021SLiane Praza * derived from the loctext language designation using the format at
17351f6eb021SLiane Praza * pn_format. pn_format should be an snprintf format string containing one
17361f6eb021SLiane Praza * %s which is replaced by the language designation.
17371f6eb021SLiane Praza *
17381f6eb021SLiane Praza * The function returns 0 on success and -1 if it is unable to attach the
17391f6eb021SLiane Praza * newly created property to pg.
17401f6eb021SLiane Praza */
17411f6eb021SLiane Praza static int
lxml_get_all_loctext(entity_t * service,pgroup_t * pg,xmlNodePtr container,const char * pn_format,const char * source)17421f6eb021SLiane Praza lxml_get_all_loctext(entity_t *service, pgroup_t *pg, xmlNodePtr container,
17431f6eb021SLiane Praza const char *pn_format, const char *source)
17441f6eb021SLiane Praza {
17451f6eb021SLiane Praza xmlNodePtr cursor;
17461f6eb021SLiane Praza
17471f6eb021SLiane Praza /*
17481f6eb021SLiane Praza * Iterate through one or more loctext elements. The locale is
17491f6eb021SLiane Praza * used to generate the property name; the contents are the ustring
17501f6eb021SLiane Praza * value for the property.
17511f6eb021SLiane Praza */
17521f6eb021SLiane Praza for (cursor = container->xmlChildrenNode; cursor != NULL;
17531f6eb021SLiane Praza cursor = cursor->next) {
17541f6eb021SLiane Praza if (lxml_ignorable_block(cursor))
17551f6eb021SLiane Praza continue;
17561f6eb021SLiane Praza
17571f6eb021SLiane Praza switch (lxml_xlate_element(cursor->name)) {
17581f6eb021SLiane Praza case SC_LOCTEXT:
17591f6eb021SLiane Praza if (lxml_get_loctext(service, pg, cursor, pn_format,
17601f6eb021SLiane Praza source))
17611f6eb021SLiane Praza return (-1);
17621f6eb021SLiane Praza break;
17631f6eb021SLiane Praza default:
17641f6eb021SLiane Praza uu_die(gettext("illegal element \"%s\" on %s element "
17651f6eb021SLiane Praza "for \"%s\"\n"), cursor->name, container->name,
17661f6eb021SLiane Praza service->sc_name);
17671f6eb021SLiane Praza break;
17681f6eb021SLiane Praza }
17691f6eb021SLiane Praza }
17701f6eb021SLiane Praza
17711f6eb021SLiane Praza return (0);
17721f6eb021SLiane Praza }
17731f6eb021SLiane Praza
17741f6eb021SLiane Praza /*
17751f6eb021SLiane Praza * Obtain the specified cardinality attribute and place it in a property
17761f6eb021SLiane Praza * named prop_name. The converted attribute is placed at *value, and the
17771f6eb021SLiane Praza * newly created property is returned to propp. NULL is returned to propp
17781f6eb021SLiane Praza * if the attribute is not provided in the manifest.
17791f6eb021SLiane Praza *
17801f6eb021SLiane Praza * 0 is returned upon success, and -1 indicates that the manifest contained
17811f6eb021SLiane Praza * an invalid cardinality value.
17821f6eb021SLiane Praza */
17831f6eb021SLiane Praza static int
lxml_get_cardinality_attribute(entity_t * service,xmlNodePtr cursor,const char * attr_name,const char * prop_name,uint64_t * value,property_t ** propp)17841f6eb021SLiane Praza lxml_get_cardinality_attribute(entity_t *service, xmlNodePtr cursor,
17851f6eb021SLiane Praza const char *attr_name, const char *prop_name, uint64_t *value,
17861f6eb021SLiane Praza property_t **propp)
17871f6eb021SLiane Praza {
17881f6eb021SLiane Praza char *c;
17891f6eb021SLiane Praza property_t *p;
17901f6eb021SLiane Praza xmlChar *val;
17911f6eb021SLiane Praza uint64_t count;
17921f6eb021SLiane Praza char *endptr;
17931f6eb021SLiane Praza
17941f6eb021SLiane Praza *propp = NULL;
17951f6eb021SLiane Praza val = xmlGetProp(cursor, (xmlChar *)attr_name);
17961f6eb021SLiane Praza if (val == NULL)
17971f6eb021SLiane Praza return (0);
17981f6eb021SLiane Praza if (*val == 0) {
17991f6eb021SLiane Praza xmlFree(val);
18001f6eb021SLiane Praza return (0);
18011f6eb021SLiane Praza }
18021f6eb021SLiane Praza
18031f6eb021SLiane Praza /*
18041f6eb021SLiane Praza * Make sure that the string at val doesn't have a leading minus
18051f6eb021SLiane Praza * sign. The strtoull() call below does not catch this problem.
18061f6eb021SLiane Praza */
18071f6eb021SLiane Praza for (c = (char *)val; *c != 0; c++) {
18081f6eb021SLiane Praza if (isspace(*c))
18091f6eb021SLiane Praza continue;
18101f6eb021SLiane Praza if (isdigit(*c))
18111f6eb021SLiane Praza break;
18121f6eb021SLiane Praza semerr(gettext("\"%c\" is not a legal character in the %s "
18131f6eb021SLiane Praza "attribute of the %s element in %s.\n"), *c,
18141f6eb021SLiane Praza attr_name, prop_name, service->sc_name);
18151f6eb021SLiane Praza xmlFree(val);
18161f6eb021SLiane Praza return (-1);
18171f6eb021SLiane Praza }
18181f6eb021SLiane Praza errno = 0;
18191f6eb021SLiane Praza count = strtoull((char *)val, &endptr, 10);
18201f6eb021SLiane Praza if (errno != 0 || endptr == (char *)val || *endptr) {
18211f6eb021SLiane Praza semerr(gettext("\"%s\" is not a legal number for the %s "
18221f6eb021SLiane Praza "attribute of the %s element in %s.\n"), (char *)val,
18231f6eb021SLiane Praza attr_name, prop_name, service->sc_name);
18241f6eb021SLiane Praza xmlFree(val);
18251f6eb021SLiane Praza return (-1);
18261f6eb021SLiane Praza }
18271f6eb021SLiane Praza
18281f6eb021SLiane Praza xmlFree(val);
18291f6eb021SLiane Praza
18301f6eb021SLiane Praza /* Value is valid. Create the property. */
18311f6eb021SLiane Praza p = internal_property_create(prop_name, SCF_TYPE_COUNT, 1, count);
18321f6eb021SLiane Praza *value = count;
18331f6eb021SLiane Praza *propp = p;
18341f6eb021SLiane Praza return (0);
18351f6eb021SLiane Praza }
18361f6eb021SLiane Praza
18371f6eb021SLiane Praza /*
18381f6eb021SLiane Praza * The cardinality is specified by two attributes max and min at cursor.
18391f6eb021SLiane Praza * Both are optional, but if present they must be unsigned integers.
18401f6eb021SLiane Praza */
18411f6eb021SLiane Praza static int
lxml_get_tm_cardinality(entity_t * service,pgroup_t * pg,xmlNodePtr cursor)18421f6eb021SLiane Praza lxml_get_tm_cardinality(entity_t *service, pgroup_t *pg, xmlNodePtr cursor)
18431f6eb021SLiane Praza {
18441f6eb021SLiane Praza int min_attached = 0;
18451f6eb021SLiane Praza int compare = 1;
18461f6eb021SLiane Praza property_t *min_prop;
18471f6eb021SLiane Praza property_t *max_prop;
18481f6eb021SLiane Praza uint64_t max;
18491f6eb021SLiane Praza uint64_t min;
18501f6eb021SLiane Praza int r;
18511f6eb021SLiane Praza
18521f6eb021SLiane Praza r = lxml_get_cardinality_attribute(service, cursor, min_attr,
18531f6eb021SLiane Praza SCF_PROPERTY_TM_CARDINALITY_MIN, &min, &min_prop);
18541f6eb021SLiane Praza if (r != 0)
18551f6eb021SLiane Praza return (r);
18561f6eb021SLiane Praza if (min_prop == NULL)
18571f6eb021SLiane Praza compare = 0;
18581f6eb021SLiane Praza r = lxml_get_cardinality_attribute(service, cursor, max_attr,
18591f6eb021SLiane Praza SCF_PROPERTY_TM_CARDINALITY_MAX, &max, &max_prop);
18601f6eb021SLiane Praza if (r != 0)
18611f6eb021SLiane Praza goto errout;
18621f6eb021SLiane Praza if ((max_prop != NULL) && (compare == 1)) {
18631f6eb021SLiane Praza if (max < min) {
18641f6eb021SLiane Praza semerr(gettext("Cardinality max is less than min for "
18651f6eb021SLiane Praza "the %s element in %s.\n"), pg->sc_pgroup_name,
18661f6eb021SLiane Praza service->sc_fmri);
18671f6eb021SLiane Praza goto errout;
18681f6eb021SLiane Praza }
18691f6eb021SLiane Praza }
18701f6eb021SLiane Praza
18711f6eb021SLiane Praza /* Attach the properties to the property group. */
18721f6eb021SLiane Praza if (min_prop) {
18731f6eb021SLiane Praza if (internal_attach_property(pg, min_prop) == 0) {
18741f6eb021SLiane Praza min_attached = 1;
18751f6eb021SLiane Praza } else {
18761f6eb021SLiane Praza goto errout;
18771f6eb021SLiane Praza }
18781f6eb021SLiane Praza }
18791f6eb021SLiane Praza if (max_prop) {
18801f6eb021SLiane Praza if (internal_attach_property(pg, max_prop) != 0) {
18811f6eb021SLiane Praza if (min_attached)
18821f6eb021SLiane Praza internal_detach_property(pg, min_prop);
18831f6eb021SLiane Praza goto errout;
18841f6eb021SLiane Praza }
18851f6eb021SLiane Praza }
18861f6eb021SLiane Praza return (0);
18871f6eb021SLiane Praza
18881f6eb021SLiane Praza errout:
18891f6eb021SLiane Praza if (min_prop)
18901f6eb021SLiane Praza internal_property_free(min_prop);
18911f6eb021SLiane Praza if (max_prop)
18921f6eb021SLiane Praza internal_property_free(max_prop);
18931f6eb021SLiane Praza return (-1);
18941f6eb021SLiane Praza }
18951f6eb021SLiane Praza
18961f6eb021SLiane Praza /*
18971f6eb021SLiane Praza * Get the common_name which is present as localized text at common_name in
18981f6eb021SLiane Praza * the manifest. The common_name is stored as the value of a property in
18991f6eb021SLiane Praza * the property group whose name is SCF_PG_TM_COMMON_NAME and type is
19001f6eb021SLiane Praza * SCF_GROUP_TEMPLATE. This property group will be created in service if
19011f6eb021SLiane Praza * it is not already there.
19021f6eb021SLiane Praza */
19037c478bd9Sstevel@tonic-gate static int
lxml_get_tm_common_name(entity_t * service,xmlNodePtr common_name)19047c478bd9Sstevel@tonic-gate lxml_get_tm_common_name(entity_t *service, xmlNodePtr common_name)
19057c478bd9Sstevel@tonic-gate {
19067c478bd9Sstevel@tonic-gate pgroup_t *pg;
19077c478bd9Sstevel@tonic-gate
19087c478bd9Sstevel@tonic-gate /*
19097c478bd9Sstevel@tonic-gate * Create the property group, if absent.
19107c478bd9Sstevel@tonic-gate */
19111f6eb021SLiane Praza pg = internal_pgroup_find_or_create(service, SCF_PG_TM_COMMON_NAME,
19121f6eb021SLiane Praza SCF_GROUP_TEMPLATE);
19131f6eb021SLiane Praza
19141f6eb021SLiane Praza return (lxml_get_all_loctext(service, pg, common_name, LOCALE_ONLY_FMT,
19151f6eb021SLiane Praza "common_name"));
19161f6eb021SLiane Praza }
19177c478bd9Sstevel@tonic-gate
19187c478bd9Sstevel@tonic-gate /*
19191f6eb021SLiane Praza * Get the description which is present as localized text at description in
19201f6eb021SLiane Praza * the manifest. The description is stored as the value of a property in
19211f6eb021SLiane Praza * the property group whose name is SCF_PG_TM_DESCRIPTION and type is
19221f6eb021SLiane Praza * SCF_GROUP_TEMPLATE. This property group will be created in service if
19231f6eb021SLiane Praza * it is not already there.
19247c478bd9Sstevel@tonic-gate */
19257c478bd9Sstevel@tonic-gate static int
lxml_get_tm_description(entity_t * service,xmlNodePtr description)19267c478bd9Sstevel@tonic-gate lxml_get_tm_description(entity_t *service, xmlNodePtr description)
19277c478bd9Sstevel@tonic-gate {
19287c478bd9Sstevel@tonic-gate pgroup_t *pg;
19297c478bd9Sstevel@tonic-gate
19307c478bd9Sstevel@tonic-gate /*
19317c478bd9Sstevel@tonic-gate * Create the property group, if absent.
19327c478bd9Sstevel@tonic-gate */
19331f6eb021SLiane Praza pg = internal_pgroup_find_or_create(service, SCF_PG_TM_DESCRIPTION,
19341f6eb021SLiane Praza SCF_GROUP_TEMPLATE);
19357c478bd9Sstevel@tonic-gate
19361f6eb021SLiane Praza return (lxml_get_all_loctext(service, pg, description,
19371f6eb021SLiane Praza LOCALE_ONLY_FMT, "description"));
19387c478bd9Sstevel@tonic-gate }
19397c478bd9Sstevel@tonic-gate
19407c478bd9Sstevel@tonic-gate static char *
lxml_label_to_groupname(const char * prefix,const char * in)19417c478bd9Sstevel@tonic-gate lxml_label_to_groupname(const char *prefix, const char *in)
19427c478bd9Sstevel@tonic-gate {
19437c478bd9Sstevel@tonic-gate char *out, *cp;
19447c478bd9Sstevel@tonic-gate size_t len, piece_len;
19457c478bd9Sstevel@tonic-gate
1946*67b0e063SAlbert Lee out = uu_zalloc(2 * max_scf_name_len + 1);
19477c478bd9Sstevel@tonic-gate if (out == NULL)
19487c478bd9Sstevel@tonic-gate return (NULL);
19497c478bd9Sstevel@tonic-gate
1950*67b0e063SAlbert Lee (void) strlcpy(out, prefix, 2 * max_scf_name_len + 1);
19517c478bd9Sstevel@tonic-gate
1952*67b0e063SAlbert Lee len = strlcat(out, in, 2 * max_scf_name_len + 1);
19537c478bd9Sstevel@tonic-gate if (len > max_scf_name_len) {
19547c478bd9Sstevel@tonic-gate /* Use the first half and the second half. */
19557c478bd9Sstevel@tonic-gate piece_len = (max_scf_name_len - 2) / 2;
19567c478bd9Sstevel@tonic-gate
19577c478bd9Sstevel@tonic-gate (void) strncpy(out + piece_len, "..", 2);
19587c478bd9Sstevel@tonic-gate
19597c478bd9Sstevel@tonic-gate (void) strcpy(out + piece_len + 2, out + (len - piece_len));
19607c478bd9Sstevel@tonic-gate }
19617c478bd9Sstevel@tonic-gate
19627c478bd9Sstevel@tonic-gate /*
19637c478bd9Sstevel@tonic-gate * Translate non-property characters to '_'.
19647c478bd9Sstevel@tonic-gate */
19657c478bd9Sstevel@tonic-gate for (cp = out; *cp != '\0'; ++cp) {
19667c478bd9Sstevel@tonic-gate if (!(isalnum(*cp) || *cp == '_' || *cp == '-'))
19677c478bd9Sstevel@tonic-gate *cp = '_';
19687c478bd9Sstevel@tonic-gate }
19697c478bd9Sstevel@tonic-gate
19707c478bd9Sstevel@tonic-gate return (out);
19717c478bd9Sstevel@tonic-gate }
19727c478bd9Sstevel@tonic-gate
19731f6eb021SLiane Praza /*
19741f6eb021SLiane Praza * If *p is NULL, astring_prop_value() first creates a property with the
19751f6eb021SLiane Praza * name specified in prop_name. The address of the newly created property
19761f6eb021SLiane Praza * is placed in *p.
19771f6eb021SLiane Praza *
19781f6eb021SLiane Praza * In either case, newly created property or existing property, a new
19791f6eb021SLiane Praza * SCF_TYPE_ASTRING value will created and attached to the property at *p.
19801f6eb021SLiane Praza * The value of the newly created property is prop_value.
19811f6eb021SLiane Praza *
19821f6eb021SLiane Praza * free_flag is used to indicate whether or not the memory at prop_value
19831f6eb021SLiane Praza * should be freed when the property is freed by a call to
19841f6eb021SLiane Praza * internal_property_free().
19851f6eb021SLiane Praza */
19861f6eb021SLiane Praza static void
astring_prop_value(property_t ** p,const char * prop_name,char * prop_value,boolean_t free_flag)19871f6eb021SLiane Praza astring_prop_value(property_t **p, const char *prop_name, char *prop_value,
19881f6eb021SLiane Praza boolean_t free_flag)
19891f6eb021SLiane Praza {
19901f6eb021SLiane Praza value_t *v;
19911f6eb021SLiane Praza
19921f6eb021SLiane Praza if (*p == NULL) {
19931f6eb021SLiane Praza /* Create the property */
19941f6eb021SLiane Praza *p = internal_property_new();
19951f6eb021SLiane Praza (*p)->sc_property_name = (char *)prop_name;
19961f6eb021SLiane Praza (*p)->sc_value_type = SCF_TYPE_ASTRING;
19971f6eb021SLiane Praza }
19981f6eb021SLiane Praza
19991f6eb021SLiane Praza /* Add the property value to the property's list of values. */
20001f6eb021SLiane Praza v = internal_value_new();
20011f6eb021SLiane Praza v->sc_type = SCF_TYPE_ASTRING;
20021f6eb021SLiane Praza if (free_flag == B_TRUE)
20031f6eb021SLiane Praza v->sc_free = lxml_free_str;
20041f6eb021SLiane Praza v->sc_u.sc_string = prop_value;
20051f6eb021SLiane Praza internal_attach_value(*p, v);
20061f6eb021SLiane Praza }
20071f6eb021SLiane Praza
20081f6eb021SLiane Praza /*
20091f6eb021SLiane Praza * If p points to a null pointer, create an internal_separators property
20101f6eb021SLiane Praza * saving the address at p. For each character at seps create a property
20111f6eb021SLiane Praza * value and attach it to the property at p.
20121f6eb021SLiane Praza */
20131f6eb021SLiane Praza static void
seps_to_prop_values(property_t ** p,xmlChar * seps)20141f6eb021SLiane Praza seps_to_prop_values(property_t **p, xmlChar *seps)
20151f6eb021SLiane Praza {
20161f6eb021SLiane Praza value_t *v;
20171f6eb021SLiane Praza char val_str[2];
20181f6eb021SLiane Praza
20191f6eb021SLiane Praza if (*p == NULL) {
20201f6eb021SLiane Praza *p = internal_property_new();
20211f6eb021SLiane Praza (*p)->sc_property_name =
20221f6eb021SLiane Praza (char *)SCF_PROPERTY_INTERNAL_SEPARATORS;
20231f6eb021SLiane Praza (*p)->sc_value_type = SCF_TYPE_ASTRING;
20241f6eb021SLiane Praza }
20251f6eb021SLiane Praza
20261f6eb021SLiane Praza /* Add the values to the property's list. */
20271f6eb021SLiane Praza val_str[1] = 0; /* Terminate the string. */
20281f6eb021SLiane Praza for (; *seps != 0; seps++) {
20291f6eb021SLiane Praza v = internal_value_new();
20301f6eb021SLiane Praza v->sc_type = (*p)->sc_value_type;
20311f6eb021SLiane Praza v->sc_free = lxml_free_str;
20321f6eb021SLiane Praza val_str[0] = *seps;
2033*67b0e063SAlbert Lee v->sc_u.sc_string = safe_strdup(val_str);
20341f6eb021SLiane Praza internal_attach_value(*p, v);
20351f6eb021SLiane Praza }
20361f6eb021SLiane Praza }
20371f6eb021SLiane Praza
20381f6eb021SLiane Praza /*
20391f6eb021SLiane Praza * Create an internal_separators property and attach it to the property
20401f6eb021SLiane Praza * group at pg. The separator characters are provided in the text nodes
20411f6eb021SLiane Praza * that are the children of seps. Each separator character is stored as a
20421f6eb021SLiane Praza * property value in the internal_separators property.
20431f6eb021SLiane Praza */
20441f6eb021SLiane Praza static int
lxml_get_tm_internal_seps(entity_t * service,pgroup_t * pg,xmlNodePtr seps)20451f6eb021SLiane Praza lxml_get_tm_internal_seps(entity_t *service, pgroup_t *pg, xmlNodePtr seps)
20461f6eb021SLiane Praza {
20471f6eb021SLiane Praza xmlNodePtr cursor;
20481f6eb021SLiane Praza property_t *prop = NULL;
20491f6eb021SLiane Praza int r;
20501f6eb021SLiane Praza
20511f6eb021SLiane Praza for (cursor = seps->xmlChildrenNode; cursor != NULL;
20521f6eb021SLiane Praza cursor = cursor->next) {
20531f6eb021SLiane Praza if (strcmp("text", (const char *)cursor->name) == 0) {
20541f6eb021SLiane Praza seps_to_prop_values(&prop, cursor->content);
20551f6eb021SLiane Praza } else if (strcmp("comment", (const char *)cursor->name) != 0) {
20561f6eb021SLiane Praza uu_die(gettext("illegal element \"%s\" on %s element "
20571f6eb021SLiane Praza "for \"%s\"\n"), cursor->name, seps->name,
20581f6eb021SLiane Praza service->sc_name);
20591f6eb021SLiane Praza }
20601f6eb021SLiane Praza }
20611f6eb021SLiane Praza if (prop == NULL) {
20621f6eb021SLiane Praza semerr(gettext("The %s element in %s had an empty list of "
20631f6eb021SLiane Praza "separators.\n"), (const char *)seps->name,
20641f6eb021SLiane Praza service->sc_name);
20651f6eb021SLiane Praza return (-1);
20661f6eb021SLiane Praza }
20671f6eb021SLiane Praza r = internal_attach_property(pg, prop);
20681f6eb021SLiane Praza if (r != 0)
20691f6eb021SLiane Praza internal_property_free(prop);
20701f6eb021SLiane Praza return (r);
20711f6eb021SLiane Praza }
20721f6eb021SLiane Praza
20737c478bd9Sstevel@tonic-gate static int
lxml_get_tm_manpage(entity_t * service,xmlNodePtr manpage)20747c478bd9Sstevel@tonic-gate lxml_get_tm_manpage(entity_t *service, xmlNodePtr manpage)
20757c478bd9Sstevel@tonic-gate {
20767c478bd9Sstevel@tonic-gate pgroup_t *pg;
20777c478bd9Sstevel@tonic-gate char *pgname;
2078*67b0e063SAlbert Lee char *name;
20797c478bd9Sstevel@tonic-gate xmlChar *title;
2080*67b0e063SAlbert Lee xmlChar *section;
20817c478bd9Sstevel@tonic-gate
20827c478bd9Sstevel@tonic-gate /*
2083*67b0e063SAlbert Lee * Fetch title and section attributes, convert to something sanitized,
2084*67b0e063SAlbert Lee * and create property group.
20857c478bd9Sstevel@tonic-gate */
20861f6eb021SLiane Praza title = xmlGetProp(manpage, (xmlChar *)title_attr);
2087*67b0e063SAlbert Lee if (title == NULL)
2088*67b0e063SAlbert Lee return (-1);
2089*67b0e063SAlbert Lee section = xmlGetProp(manpage, (xmlChar *)section_attr);
2090*67b0e063SAlbert Lee if (section == NULL) {
2091*67b0e063SAlbert Lee xmlFree(title);
2092*67b0e063SAlbert Lee return (-1);
2093*67b0e063SAlbert Lee }
2094*67b0e063SAlbert Lee
2095*67b0e063SAlbert Lee name = safe_malloc(max_scf_name_len + 1);
2096*67b0e063SAlbert Lee
2097*67b0e063SAlbert Lee /* Find existing property group with underscore separators */
2098*67b0e063SAlbert Lee (void) snprintf(name, max_scf_name_len + 1, "%s_%s", title, section);
2099*67b0e063SAlbert Lee pgname = lxml_label_to_groupname(SCF_PG_TM_MAN_PREFIX, name);
2100*67b0e063SAlbert Lee pg = internal_pgroup_find(service, pgname, SCF_GROUP_TEMPLATE);
2101*67b0e063SAlbert Lee
2102*67b0e063SAlbert Lee uu_free(pgname);
2103*67b0e063SAlbert Lee (void) snprintf(name, max_scf_name_len + 1, "%s%s", title, section);
2104*67b0e063SAlbert Lee pgname = lxml_label_to_groupname(SCF_PG_TM_MAN_PREFIX, name);
2105*67b0e063SAlbert Lee
2106*67b0e063SAlbert Lee if (pg == NULL) {
2107*67b0e063SAlbert Lee pg = internal_pgroup_find_or_create(service, pgname,
2108*67b0e063SAlbert Lee SCF_GROUP_TEMPLATE);
2109*67b0e063SAlbert Lee } else {
2110*67b0e063SAlbert Lee /* Rename property group */
2111*67b0e063SAlbert Lee free((char *)pg->sc_pgroup_name);
2112*67b0e063SAlbert Lee pg->sc_pgroup_name = safe_strdup(pgname);
2113*67b0e063SAlbert Lee }
2114*67b0e063SAlbert Lee
2115*67b0e063SAlbert Lee uu_free(pgname);
2116*67b0e063SAlbert Lee free(name);
2117*67b0e063SAlbert Lee xmlFree(section);
21181f6eb021SLiane Praza xmlFree(title);
21197c478bd9Sstevel@tonic-gate
21207c478bd9Sstevel@tonic-gate
21217c478bd9Sstevel@tonic-gate /*
21227c478bd9Sstevel@tonic-gate * Each attribute is an astring property within the group.
21237c478bd9Sstevel@tonic-gate */
21241f6eb021SLiane Praza if (new_str_prop_from_attr(pg, SCF_PROPERTY_TM_TITLE,
21251f6eb021SLiane Praza SCF_TYPE_ASTRING, manpage, title_attr) != 0 ||
21261f6eb021SLiane Praza new_str_prop_from_attr(pg, SCF_PROPERTY_TM_SECTION,
21271f6eb021SLiane Praza SCF_TYPE_ASTRING, manpage, section_attr) != 0 ||
21281f6eb021SLiane Praza new_str_prop_from_attr(pg, SCF_PROPERTY_TM_MANPATH,
21291f6eb021SLiane Praza SCF_TYPE_ASTRING, manpage, manpath_attr) != 0)
21307c478bd9Sstevel@tonic-gate return (-1);
21317c478bd9Sstevel@tonic-gate
21327c478bd9Sstevel@tonic-gate return (0);
21337c478bd9Sstevel@tonic-gate }
21347c478bd9Sstevel@tonic-gate
21357c478bd9Sstevel@tonic-gate static int
lxml_get_tm_doclink(entity_t * service,xmlNodePtr doc_link)21367c478bd9Sstevel@tonic-gate lxml_get_tm_doclink(entity_t *service, xmlNodePtr doc_link)
21377c478bd9Sstevel@tonic-gate {
21387c478bd9Sstevel@tonic-gate pgroup_t *pg;
21397c478bd9Sstevel@tonic-gate char *pgname;
21407c478bd9Sstevel@tonic-gate xmlChar *name;
21417c478bd9Sstevel@tonic-gate
21427c478bd9Sstevel@tonic-gate /*
21437c478bd9Sstevel@tonic-gate * Fetch name attribute, convert name to something sanitized, and create
21447c478bd9Sstevel@tonic-gate * property group.
21457c478bd9Sstevel@tonic-gate */
21461f6eb021SLiane Praza name = xmlGetProp(doc_link, (xmlChar *)name_attr);
2147*67b0e063SAlbert Lee if (name == NULL)
2148*67b0e063SAlbert Lee return (-1);
21497c478bd9Sstevel@tonic-gate
21507c478bd9Sstevel@tonic-gate pgname = (char *)lxml_label_to_groupname(SCF_PG_TM_DOC_PREFIX,
21517c478bd9Sstevel@tonic-gate (const char *)name);
21527c478bd9Sstevel@tonic-gate
21537c478bd9Sstevel@tonic-gate pg = internal_pgroup_find_or_create(service, pgname,
21547c478bd9Sstevel@tonic-gate (char *)SCF_GROUP_TEMPLATE);
2155*67b0e063SAlbert Lee
2156*67b0e063SAlbert Lee uu_free(pgname);
21571f6eb021SLiane Praza xmlFree(name);
21587c478bd9Sstevel@tonic-gate
21597c478bd9Sstevel@tonic-gate /*
21607c478bd9Sstevel@tonic-gate * Each attribute is an astring property within the group.
21617c478bd9Sstevel@tonic-gate */
21621f6eb021SLiane Praza if (new_str_prop_from_attr(pg, SCF_PROPERTY_TM_NAME, SCF_TYPE_ASTRING,
21631f6eb021SLiane Praza doc_link, name_attr) != 0 ||
21641f6eb021SLiane Praza new_str_prop_from_attr(pg, SCF_PROPERTY_TM_URI, SCF_TYPE_ASTRING,
21651f6eb021SLiane Praza doc_link, uri_attr) != 0)
21667c478bd9Sstevel@tonic-gate return (-1);
21677c478bd9Sstevel@tonic-gate
21687c478bd9Sstevel@tonic-gate return (0);
21697c478bd9Sstevel@tonic-gate }
21707c478bd9Sstevel@tonic-gate
21717c478bd9Sstevel@tonic-gate static int
lxml_get_tm_documentation(entity_t * service,xmlNodePtr documentation)21727c478bd9Sstevel@tonic-gate lxml_get_tm_documentation(entity_t *service, xmlNodePtr documentation)
21737c478bd9Sstevel@tonic-gate {
21747c478bd9Sstevel@tonic-gate xmlNodePtr cursor;
21757c478bd9Sstevel@tonic-gate
21767c478bd9Sstevel@tonic-gate for (cursor = documentation->xmlChildrenNode; cursor != NULL;
21777c478bd9Sstevel@tonic-gate cursor = cursor->next) {
21787c478bd9Sstevel@tonic-gate if (lxml_ignorable_block(cursor))
21797c478bd9Sstevel@tonic-gate continue;
21807c478bd9Sstevel@tonic-gate
21817c478bd9Sstevel@tonic-gate switch (lxml_xlate_element(cursor->name)) {
21827c478bd9Sstevel@tonic-gate case SC_MANPAGE:
21837c478bd9Sstevel@tonic-gate (void) lxml_get_tm_manpage(service, cursor);
21847c478bd9Sstevel@tonic-gate break;
21857c478bd9Sstevel@tonic-gate case SC_DOC_LINK:
21867c478bd9Sstevel@tonic-gate (void) lxml_get_tm_doclink(service, cursor);
21877c478bd9Sstevel@tonic-gate break;
21887c478bd9Sstevel@tonic-gate default:
21897c478bd9Sstevel@tonic-gate uu_die(gettext("illegal element \"%s\" on template "
21907c478bd9Sstevel@tonic-gate "for service \"%s\"\n"),
21917c478bd9Sstevel@tonic-gate cursor->name, service->sc_name);
21927c478bd9Sstevel@tonic-gate }
21937c478bd9Sstevel@tonic-gate }
21947c478bd9Sstevel@tonic-gate
21957c478bd9Sstevel@tonic-gate return (0);
21967c478bd9Sstevel@tonic-gate }
21977c478bd9Sstevel@tonic-gate
21987c478bd9Sstevel@tonic-gate static int
lxml_get_prop_pattern_attributes(pgroup_t * pg,xmlNodePtr cursor)21991f6eb021SLiane Praza lxml_get_prop_pattern_attributes(pgroup_t *pg, xmlNodePtr cursor)
22001f6eb021SLiane Praza {
22011f6eb021SLiane Praza if (new_opt_str_prop_from_attr(pg, SCF_PROPERTY_TM_NAME,
22021f6eb021SLiane Praza SCF_TYPE_ASTRING, cursor, name_attr, NULL) != 0) {
22031f6eb021SLiane Praza return (-1);
22041f6eb021SLiane Praza }
22051f6eb021SLiane Praza if (new_opt_str_prop_from_attr(pg, SCF_PROPERTY_TM_TYPE,
22061f6eb021SLiane Praza SCF_TYPE_ASTRING, cursor, type_attr, "") != 0) {
22071f6eb021SLiane Praza return (-1);
22081f6eb021SLiane Praza }
22091f6eb021SLiane Praza if (new_bool_prop_from_attr(pg, SCF_PROPERTY_TM_REQUIRED, cursor,
22101f6eb021SLiane Praza required_attr) != 0)
22111f6eb021SLiane Praza return (-1);
22121f6eb021SLiane Praza return (0);
22131f6eb021SLiane Praza }
22141f6eb021SLiane Praza
22151f6eb021SLiane Praza static int
lxml_get_tm_include_values(entity_t * service,pgroup_t * pg,xmlNodePtr include_values,const char * prop_name)22161f6eb021SLiane Praza lxml_get_tm_include_values(entity_t *service, pgroup_t *pg,
22171f6eb021SLiane Praza xmlNodePtr include_values, const char *prop_name)
22181f6eb021SLiane Praza {
22191f6eb021SLiane Praza boolean_t attach_to_pg = B_FALSE;
22201f6eb021SLiane Praza property_t *p;
22211f6eb021SLiane Praza int r = 0;
22221f6eb021SLiane Praza char *type;
22231f6eb021SLiane Praza
22241f6eb021SLiane Praza /* Get the type attribute of the include_values element. */
22251f6eb021SLiane Praza type = (char *)xmlGetProp(include_values, (const xmlChar *)type_attr);
22261f6eb021SLiane Praza if ((type == NULL) || (*type == 0)) {
22271f6eb021SLiane Praza uu_die(gettext("%s element requires a %s attribute in the %s "
22281f6eb021SLiane Praza "service.\n"), include_values->name, type_attr,
22291f6eb021SLiane Praza service->sc_name);
22301f6eb021SLiane Praza }
22311f6eb021SLiane Praza
22321f6eb021SLiane Praza /* Add the type to the values of the prop_name property. */
22331f6eb021SLiane Praza p = internal_property_find(pg, prop_name);
22341f6eb021SLiane Praza if (p == NULL)
22351f6eb021SLiane Praza attach_to_pg = B_TRUE;
22361f6eb021SLiane Praza astring_prop_value(&p, prop_name, type, B_FALSE);
22371f6eb021SLiane Praza if (attach_to_pg == B_TRUE) {
22381f6eb021SLiane Praza r = internal_attach_property(pg, p);
22391f6eb021SLiane Praza if (r != 0)
22401f6eb021SLiane Praza internal_property_free(p);
22411f6eb021SLiane Praza }
22421f6eb021SLiane Praza return (r);
22431f6eb021SLiane Praza }
22441f6eb021SLiane Praza
22451f6eb021SLiane Praza #define RC_MIN 0
22461f6eb021SLiane Praza #define RC_MAX 1
22471f6eb021SLiane Praza #define RC_COUNT 2
22481f6eb021SLiane Praza
22491f6eb021SLiane Praza /*
22501f6eb021SLiane Praza * Verify that the strings at min and max are valid numeric strings. Also
22511f6eb021SLiane Praza * verify that max is numerically >= min.
22521f6eb021SLiane Praza *
22531f6eb021SLiane Praza * 0 is returned if the range is valid, and -1 is returned if it is not.
22541f6eb021SLiane Praza */
22551f6eb021SLiane Praza static int
verify_range(entity_t * service,xmlNodePtr range,char * min,char * max)22561f6eb021SLiane Praza verify_range(entity_t *service, xmlNodePtr range, char *min, char *max)
22571f6eb021SLiane Praza {
22581f6eb021SLiane Praza char *c;
22591f6eb021SLiane Praza int i;
22601f6eb021SLiane Praza int is_signed = 0;
22611f6eb021SLiane Praza int inverted = 0;
22621f6eb021SLiane Praza const char *limit[RC_COUNT];
22631f6eb021SLiane Praza char *strings[RC_COUNT];
22641f6eb021SLiane Praza uint64_t urange[RC_COUNT]; /* unsigned range. */
22651f6eb021SLiane Praza int64_t srange[RC_COUNT]; /* signed range. */
22661f6eb021SLiane Praza
22671f6eb021SLiane Praza strings[RC_MIN] = min;
22681f6eb021SLiane Praza strings[RC_MAX] = max;
22691f6eb021SLiane Praza limit[RC_MIN] = min_attr;
22701f6eb021SLiane Praza limit[RC_MAX] = max_attr;
22711f6eb021SLiane Praza
22721f6eb021SLiane Praza /* See if the range is signed. */
22731f6eb021SLiane Praza for (i = 0; (i < RC_COUNT) && (is_signed == 0); i++) {
22741f6eb021SLiane Praza c = strings[i];
22751f6eb021SLiane Praza while (isspace(*c)) {
22761f6eb021SLiane Praza c++;
22771f6eb021SLiane Praza }
22781f6eb021SLiane Praza if (*c == '-')
22791f6eb021SLiane Praza is_signed = 1;
22801f6eb021SLiane Praza }
22811f6eb021SLiane Praza
22821f6eb021SLiane Praza /* Attempt to convert the strings. */
22831f6eb021SLiane Praza for (i = 0; i < RC_COUNT; i++) {
22841f6eb021SLiane Praza errno = 0;
22851f6eb021SLiane Praza if (is_signed) {
22861f6eb021SLiane Praza srange[i] = strtoll(strings[i], &c, 0);
22871f6eb021SLiane Praza } else {
22881f6eb021SLiane Praza urange[i] = strtoull(strings[i], &c, 0);
22891f6eb021SLiane Praza }
22901f6eb021SLiane Praza if ((errno != 0) || (c == strings[i]) || (*c != 0)) {
22911f6eb021SLiane Praza /* Conversion failed. */
22921f6eb021SLiane Praza uu_die(gettext("Unable to convert %s for the %s "
22931f6eb021SLiane Praza "element in service %s.\n"), limit[i],
22941f6eb021SLiane Praza (char *)range->name, service->sc_name);
22951f6eb021SLiane Praza }
22961f6eb021SLiane Praza }
22971f6eb021SLiane Praza
22981f6eb021SLiane Praza /* Make sure that min is <= max */
22991f6eb021SLiane Praza if (is_signed) {
23001f6eb021SLiane Praza if (srange[RC_MAX] < srange[RC_MIN])
23011f6eb021SLiane Praza inverted = 1;
23021f6eb021SLiane Praza } else {
23031f6eb021SLiane Praza if (urange[RC_MAX] < urange[RC_MIN])
23041f6eb021SLiane Praza inverted = 1;
23051f6eb021SLiane Praza }
23061f6eb021SLiane Praza if (inverted != 0) {
23071f6eb021SLiane Praza semerr(gettext("Maximum less than minimum for the %s element "
23081f6eb021SLiane Praza "in service %s.\n"), (char *)range->name,
23091f6eb021SLiane Praza service->sc_name);
23101f6eb021SLiane Praza return (-1);
23111f6eb021SLiane Praza }
23121f6eb021SLiane Praza
23131f6eb021SLiane Praza return (0);
23141f6eb021SLiane Praza }
23151f6eb021SLiane Praza
23161f6eb021SLiane Praza /*
23171f6eb021SLiane Praza * This, function creates a property named prop_name. The range element
23181f6eb021SLiane Praza * should have two attributes -- min and max. The property value then
23191f6eb021SLiane Praza * becomes the concatenation of their value separated by a comma. The
23201f6eb021SLiane Praza * property is then attached to the property group at pg.
23211f6eb021SLiane Praza *
23221f6eb021SLiane Praza * If pg already contains a property with a name of prop_name, it is only
23231f6eb021SLiane Praza * necessary to create a new value and attach it to the existing property.
23241f6eb021SLiane Praza */
23251f6eb021SLiane Praza static int
lxml_get_tm_range(entity_t * service,pgroup_t * pg,xmlNodePtr range,const char * prop_name)23261f6eb021SLiane Praza lxml_get_tm_range(entity_t *service, pgroup_t *pg, xmlNodePtr range,
23271f6eb021SLiane Praza const char *prop_name)
23281f6eb021SLiane Praza {
23291f6eb021SLiane Praza boolean_t attach_to_pg = B_FALSE;
23301f6eb021SLiane Praza char *max;
23311f6eb021SLiane Praza char *min;
23321f6eb021SLiane Praza property_t *p;
23331f6eb021SLiane Praza char *prop_value;
23341f6eb021SLiane Praza int r = 0;
23351f6eb021SLiane Praza
23361f6eb021SLiane Praza /* Get max and min from the XML description. */
23371f6eb021SLiane Praza max = (char *)xmlGetProp(range, (xmlChar *)max_attr);
23381f6eb021SLiane Praza if ((max == NULL) || (*max == 0)) {
23391f6eb021SLiane Praza uu_die(gettext("%s element is missing the %s attribute in "
23401f6eb021SLiane Praza "service %s.\n"), (char *)range->name, max_attr,
23411f6eb021SLiane Praza service->sc_name);
23421f6eb021SLiane Praza }
23431f6eb021SLiane Praza min = (char *)xmlGetProp(range, (xmlChar *)min_attr);
23441f6eb021SLiane Praza if ((min == NULL) || (*min == 0)) {
23451f6eb021SLiane Praza uu_die(gettext("%s element is missing the %s attribute in "
23461f6eb021SLiane Praza "service %s.\n"), (char *)range->name, min_attr,
23471f6eb021SLiane Praza service->sc_name);
23481f6eb021SLiane Praza }
23491f6eb021SLiane Praza if (verify_range(service, range, min, max) != 0) {
23501f6eb021SLiane Praza xmlFree(min);
23511f6eb021SLiane Praza xmlFree(max);
23521f6eb021SLiane Praza return (-1);
23531f6eb021SLiane Praza }
23541f6eb021SLiane Praza
23551f6eb021SLiane Praza /* Property value is concatenation of min and max. */
23561f6eb021SLiane Praza prop_value = safe_malloc(max_scf_value_len + 1);
23571f6eb021SLiane Praza if (snprintf(prop_value, max_scf_value_len + 1, "%s,%s", min, max) >=
23581f6eb021SLiane Praza max_scf_value_len + 1) {
23591f6eb021SLiane Praza uu_die(gettext("min and max are too long for the %s element "
23601f6eb021SLiane Praza "of %s.\n"), (char *)range->name, service->sc_name);
23611f6eb021SLiane Praza }
23621f6eb021SLiane Praza xmlFree(min);
23631f6eb021SLiane Praza xmlFree(max);
23641f6eb021SLiane Praza
23651f6eb021SLiane Praza /*
23661f6eb021SLiane Praza * If necessary create the property and attach it to the property
23671f6eb021SLiane Praza * group.
23681f6eb021SLiane Praza */
23691f6eb021SLiane Praza p = internal_property_find(pg, prop_name);
23701f6eb021SLiane Praza if (p == NULL)
23711f6eb021SLiane Praza attach_to_pg = B_TRUE;
23721f6eb021SLiane Praza astring_prop_value(&p, prop_name, prop_value, B_TRUE);
23731f6eb021SLiane Praza if (attach_to_pg == B_TRUE) {
23741f6eb021SLiane Praza r = internal_attach_property(pg, p);
23751f6eb021SLiane Praza if (r != 0) {
23761f6eb021SLiane Praza internal_property_free(p);
23771f6eb021SLiane Praza }
23781f6eb021SLiane Praza }
23791f6eb021SLiane Praza return (r);
23801f6eb021SLiane Praza }
23811f6eb021SLiane Praza
23821f6eb021SLiane Praza /*
23831f6eb021SLiane Praza * Determine how many plain characters are represented by count Base32
23841f6eb021SLiane Praza * encoded characters. 5 plain text characters are converted to 8 Base32
23851f6eb021SLiane Praza * characters.
23861f6eb021SLiane Praza */
23871f6eb021SLiane Praza static size_t
encoded_count_to_plain(size_t count)23881f6eb021SLiane Praza encoded_count_to_plain(size_t count)
23891f6eb021SLiane Praza {
23901f6eb021SLiane Praza return (5 * ((count + 7) / 8));
23911f6eb021SLiane Praza }
23921f6eb021SLiane Praza
23931f6eb021SLiane Praza /*
23941f6eb021SLiane Praza * The value element contains 0 or 1 common_name element followed by 0 or 1
23951f6eb021SLiane Praza * description element. It also has a required attribute called "name".
23961f6eb021SLiane Praza * The common_name and description are stored as property values in pg.
23971f6eb021SLiane Praza * The property names are:
23981f6eb021SLiane Praza * value_<name>_common_name_<lang>
23991f6eb021SLiane Praza * value_<name>_description_<lang>
24001f6eb021SLiane Praza *
24011f6eb021SLiane Praza * The <name> portion of the preceeding proper names requires more
24021f6eb021SLiane Praza * explanation. Ideally it would just the name attribute of this value
24031f6eb021SLiane Praza * element. Unfortunately, the name attribute can contain characters that
24041f6eb021SLiane Praza * are not legal in a property name. Thus, we base 32 encode the name
24051f6eb021SLiane Praza * attribute and use that for <name>.
24061f6eb021SLiane Praza *
24071f6eb021SLiane Praza * There are cases where the caller needs to know the name, so it is
24081f6eb021SLiane Praza * returned through the name_value pointer if it is not NULL.
24091f6eb021SLiane Praza *
24101f6eb021SLiane Praza * Parameters:
24111f6eb021SLiane Praza * service - Information about the service that is being
24121f6eb021SLiane Praza * processed. This function only uses this parameter
24131f6eb021SLiane Praza * for producing error messages.
24141f6eb021SLiane Praza *
24151f6eb021SLiane Praza * pg - The property group to receive the newly created
24161f6eb021SLiane Praza * properties.
24171f6eb021SLiane Praza *
24181f6eb021SLiane Praza * value - Pointer to the value element in the XML tree.
24191f6eb021SLiane Praza *
24201f6eb021SLiane Praza * name_value - Address to receive the value of the name attribute.
24211f6eb021SLiane Praza * The caller must free the memory.
24221f6eb021SLiane Praza */
24231f6eb021SLiane Praza static int
lxml_get_tm_value_element(entity_t * service,pgroup_t * pg,xmlNodePtr value,char ** name_value)24241f6eb021SLiane Praza lxml_get_tm_value_element(entity_t *service, pgroup_t *pg, xmlNodePtr value,
24251f6eb021SLiane Praza char **name_value)
24261f6eb021SLiane Praza {
24271f6eb021SLiane Praza char *common_name_fmt;
24281f6eb021SLiane Praza xmlNodePtr cursor;
24291f6eb021SLiane Praza char *description_fmt;
24301f6eb021SLiane Praza char *encoded_value = NULL;
24311f6eb021SLiane Praza size_t extra;
24321f6eb021SLiane Praza char *value_name;
24331f6eb021SLiane Praza int r = 0;
24341f6eb021SLiane Praza
24351f6eb021SLiane Praza common_name_fmt = safe_malloc(max_scf_name_len + 1);
24361f6eb021SLiane Praza description_fmt = safe_malloc(max_scf_name_len + 1);
24371f6eb021SLiane Praza
24381f6eb021SLiane Praza /*
24391f6eb021SLiane Praza * Get the value of our name attribute, so that we can use it to
24401f6eb021SLiane Praza * construct property names.
24411f6eb021SLiane Praza */
24421f6eb021SLiane Praza value_name = (char *)xmlGetProp(value, (xmlChar *)name_attr);
24431f6eb021SLiane Praza /* The value name must be present, but it can be empty. */
24441f6eb021SLiane Praza if (value_name == NULL) {
24451f6eb021SLiane Praza uu_die(gettext("%s element requires a %s attribute in the %s "
24461f6eb021SLiane Praza "service.\n"), (char *)value->name, name_attr,
24471f6eb021SLiane Praza service->sc_name);
24481f6eb021SLiane Praza }
24491f6eb021SLiane Praza
24501f6eb021SLiane Praza /*
24511f6eb021SLiane Praza * The value_name may contain characters that are not valid in in a
24521f6eb021SLiane Praza * property name. So we will encode value_name and then use the
24531f6eb021SLiane Praza * encoded value in the property name.
24541f6eb021SLiane Praza */
24551f6eb021SLiane Praza encoded_value = safe_malloc(max_scf_name_len + 1);
24561f6eb021SLiane Praza if (scf_encode32(value_name, strlen(value_name), encoded_value,
24571f6eb021SLiane Praza max_scf_name_len + 1, &extra, SCF_ENCODE32_PAD) != 0) {
24581f6eb021SLiane Praza extra = encoded_count_to_plain(extra - max_scf_name_len);
24591f6eb021SLiane Praza uu_die(gettext("Constructed property name is %u characters "
24601f6eb021SLiane Praza "too long for value \"%s\" in the %s service.\n"),
24611f6eb021SLiane Praza extra, value_name, service->sc_name);
24621f6eb021SLiane Praza }
24631f6eb021SLiane Praza if ((extra = snprintf(common_name_fmt, max_scf_name_len + 1,
24641f6eb021SLiane Praza VALUE_COMMON_NAME_FMT, SCF_PROPERTY_TM_VALUE_PREFIX,
24651f6eb021SLiane Praza encoded_value)) >= max_scf_name_len + 1) {
24661f6eb021SLiane Praza extra = encoded_count_to_plain(extra - max_scf_name_len);
24671f6eb021SLiane Praza uu_die(gettext("Name attribute is "
24681f6eb021SLiane Praza "%u characters too long for %s in service %s\n"),
24691f6eb021SLiane Praza extra, (char *)value->name, service->sc_name);
24701f6eb021SLiane Praza }
24711f6eb021SLiane Praza if ((extra = snprintf(description_fmt, max_scf_name_len + 1,
24721f6eb021SLiane Praza VALUE_DESCRIPTION_FMT, SCF_PROPERTY_TM_VALUE_PREFIX,
24731f6eb021SLiane Praza encoded_value)) >= max_scf_name_len + 1) {
24741f6eb021SLiane Praza extra = encoded_count_to_plain(extra - max_scf_name_len);
24751f6eb021SLiane Praza uu_die(gettext("Name attribute is "
24761f6eb021SLiane Praza "%u characters too long for %s in service %s\n"),
24771f6eb021SLiane Praza extra, (char *)value->name, service->sc_name);
24781f6eb021SLiane Praza }
24791f6eb021SLiane Praza
24801f6eb021SLiane Praza for (cursor = value->xmlChildrenNode;
24811f6eb021SLiane Praza cursor != NULL;
24821f6eb021SLiane Praza cursor = cursor->next) {
24831f6eb021SLiane Praza if (lxml_ignorable_block(cursor))
24841f6eb021SLiane Praza continue;
24851f6eb021SLiane Praza switch (lxml_xlate_element(cursor->name)) {
24861f6eb021SLiane Praza case SC_COMMON_NAME:
24871f6eb021SLiane Praza r = lxml_get_all_loctext(service, pg, cursor,
24881f6eb021SLiane Praza common_name_fmt, (const char *)cursor->name);
24891f6eb021SLiane Praza break;
24901f6eb021SLiane Praza case SC_DESCRIPTION:
24911f6eb021SLiane Praza r = lxml_get_all_loctext(service, pg, cursor,
24921f6eb021SLiane Praza description_fmt, (const char *)cursor->name);
24931f6eb021SLiane Praza break;
24941f6eb021SLiane Praza default:
24951f6eb021SLiane Praza uu_die(gettext("\"%s\" is an illegal element in %s "
24961f6eb021SLiane Praza "of service %s\n"), (char *)cursor->name,
24971f6eb021SLiane Praza (char *)value->name, service->sc_name);
24981f6eb021SLiane Praza }
24991f6eb021SLiane Praza if (r != 0)
25001f6eb021SLiane Praza break;
25011f6eb021SLiane Praza }
25021f6eb021SLiane Praza
25031f6eb021SLiane Praza free(description_fmt);
25041f6eb021SLiane Praza free(common_name_fmt);
25051f6eb021SLiane Praza if (r == 0) {
25061f6eb021SLiane Praza *name_value = safe_strdup(value_name);
25071f6eb021SLiane Praza }
25081f6eb021SLiane Praza xmlFree(value_name);
25091f6eb021SLiane Praza free(encoded_value);
25101f6eb021SLiane Praza return (r);
25111f6eb021SLiane Praza }
25121f6eb021SLiane Praza
25131f6eb021SLiane Praza static int
lxml_get_tm_choices(entity_t * service,pgroup_t * pg,xmlNodePtr choices)25141f6eb021SLiane Praza lxml_get_tm_choices(entity_t *service, pgroup_t *pg, xmlNodePtr choices)
25151f6eb021SLiane Praza {
25161f6eb021SLiane Praza xmlNodePtr cursor;
25171f6eb021SLiane Praza char *name_value;
25181f6eb021SLiane Praza property_t *name_prop = NULL;
25191f6eb021SLiane Praza int r = 0;
25201f6eb021SLiane Praza
25211f6eb021SLiane Praza for (cursor = choices->xmlChildrenNode;
25221f6eb021SLiane Praza (cursor != NULL) && (r == 0);
25231f6eb021SLiane Praza cursor = cursor->next) {
25241f6eb021SLiane Praza if (lxml_ignorable_block(cursor))
25251f6eb021SLiane Praza continue;
25261f6eb021SLiane Praza switch (lxml_xlate_element(cursor->name)) {
25271f6eb021SLiane Praza case SC_INCLUDE_VALUES:
25281f6eb021SLiane Praza (void) lxml_get_tm_include_values(service, pg, cursor,
25291f6eb021SLiane Praza SCF_PROPERTY_TM_CHOICES_INCLUDE_VALUES);
25301f6eb021SLiane Praza break;
25311f6eb021SLiane Praza case SC_RANGE:
25321f6eb021SLiane Praza r = lxml_get_tm_range(service, pg, cursor,
25331f6eb021SLiane Praza SCF_PROPERTY_TM_CHOICES_RANGE);
25341f6eb021SLiane Praza if (r != 0)
25351f6eb021SLiane Praza goto out;
25361f6eb021SLiane Praza break;
25371f6eb021SLiane Praza case SC_VALUE:
25381f6eb021SLiane Praza r = lxml_get_tm_value_element(service, pg, cursor,
25391f6eb021SLiane Praza &name_value);
25401f6eb021SLiane Praza if (r == 0) {
25411f6eb021SLiane Praza /*
25421f6eb021SLiane Praza * There is no need to free the memory
25431f6eb021SLiane Praza * associated with name_value, because the
25441f6eb021SLiane Praza * property value will end up pointing to
25451f6eb021SLiane Praza * the memory.
25461f6eb021SLiane Praza */
25471f6eb021SLiane Praza astring_prop_value(&name_prop,
25481f6eb021SLiane Praza SCF_PROPERTY_TM_CHOICES_NAME, name_value,
25491f6eb021SLiane Praza B_TRUE);
25501f6eb021SLiane Praza } else {
25511f6eb021SLiane Praza goto out;
25521f6eb021SLiane Praza }
25531f6eb021SLiane Praza break;
25541f6eb021SLiane Praza default:
25551f6eb021SLiane Praza uu_die(gettext("%s is an invalid element of "
25561f6eb021SLiane Praza "choices for service %s.\n"), cursor->name,
25571f6eb021SLiane Praza service->sc_name);
25581f6eb021SLiane Praza }
25591f6eb021SLiane Praza }
25601f6eb021SLiane Praza
25611f6eb021SLiane Praza out:
25621f6eb021SLiane Praza /* Attach the name property if we created one. */
25631f6eb021SLiane Praza if ((r == 0) && (name_prop != NULL)) {
25641f6eb021SLiane Praza r = internal_attach_property(pg, name_prop);
25651f6eb021SLiane Praza }
25661f6eb021SLiane Praza if ((r != 0) && (name_prop != NULL)) {
25671f6eb021SLiane Praza internal_property_free(name_prop);
25681f6eb021SLiane Praza }
25691f6eb021SLiane Praza
25701f6eb021SLiane Praza return (r);
25711f6eb021SLiane Praza }
25721f6eb021SLiane Praza
25731f6eb021SLiane Praza static int
lxml_get_tm_constraints(entity_t * service,pgroup_t * pg,xmlNodePtr constraints)25741f6eb021SLiane Praza lxml_get_tm_constraints(entity_t *service, pgroup_t *pg, xmlNodePtr constraints)
25751f6eb021SLiane Praza {
25761f6eb021SLiane Praza xmlNodePtr cursor;
25771f6eb021SLiane Praza char *name_value;
25781f6eb021SLiane Praza property_t *name_prop = NULL;
25791f6eb021SLiane Praza int r = 0;
25801f6eb021SLiane Praza
25811f6eb021SLiane Praza for (cursor = constraints->xmlChildrenNode;
25821f6eb021SLiane Praza (cursor != NULL) && (r == 0);
25831f6eb021SLiane Praza cursor = cursor->next) {
25841f6eb021SLiane Praza if (lxml_ignorable_block(cursor))
25851f6eb021SLiane Praza continue;
25861f6eb021SLiane Praza switch (lxml_xlate_element(cursor->name)) {
25871f6eb021SLiane Praza case SC_RANGE:
25881f6eb021SLiane Praza r = lxml_get_tm_range(service, pg, cursor,
25891f6eb021SLiane Praza SCF_PROPERTY_TM_CONSTRAINT_RANGE);
25901f6eb021SLiane Praza if (r != 0)
25911f6eb021SLiane Praza goto out;
25921f6eb021SLiane Praza break;
25931f6eb021SLiane Praza case SC_VALUE:
25941f6eb021SLiane Praza r = lxml_get_tm_value_element(service, pg, cursor,
25951f6eb021SLiane Praza &name_value);
25961f6eb021SLiane Praza if (r == 0) {
25971f6eb021SLiane Praza /*
25981f6eb021SLiane Praza * There is no need to free the memory
25991f6eb021SLiane Praza * associated with name_value, because the
26001f6eb021SLiane Praza * property value will end up pointing to
26011f6eb021SLiane Praza * the memory.
26021f6eb021SLiane Praza */
26031f6eb021SLiane Praza astring_prop_value(&name_prop,
26041f6eb021SLiane Praza SCF_PROPERTY_TM_CONSTRAINT_NAME, name_value,
26051f6eb021SLiane Praza B_TRUE);
26061f6eb021SLiane Praza } else {
26071f6eb021SLiane Praza goto out;
26081f6eb021SLiane Praza }
26091f6eb021SLiane Praza break;
26101f6eb021SLiane Praza default:
26111f6eb021SLiane Praza uu_die(gettext("%s is an invalid element of "
26121f6eb021SLiane Praza "constraints for service %s.\n"), cursor->name,
26131f6eb021SLiane Praza service->sc_name);
26141f6eb021SLiane Praza }
26151f6eb021SLiane Praza }
26161f6eb021SLiane Praza
26171f6eb021SLiane Praza out:
26181f6eb021SLiane Praza /* Attach the name property if we created one. */
26191f6eb021SLiane Praza if ((r == 0) && (name_prop != NULL)) {
26201f6eb021SLiane Praza r = internal_attach_property(pg, name_prop);
26211f6eb021SLiane Praza }
26221f6eb021SLiane Praza if ((r != 0) && (name_prop != NULL)) {
26231f6eb021SLiane Praza internal_property_free(name_prop);
26241f6eb021SLiane Praza }
26251f6eb021SLiane Praza
26261f6eb021SLiane Praza return (r);
26271f6eb021SLiane Praza }
26281f6eb021SLiane Praza
26291f6eb021SLiane Praza /*
26301f6eb021SLiane Praza * The values element contains one or more value elements.
26311f6eb021SLiane Praza */
26321f6eb021SLiane Praza static int
lxml_get_tm_values(entity_t * service,pgroup_t * pg,xmlNodePtr values)26331f6eb021SLiane Praza lxml_get_tm_values(entity_t *service, pgroup_t *pg, xmlNodePtr values)
26341f6eb021SLiane Praza {
26351f6eb021SLiane Praza xmlNodePtr cursor;
26361f6eb021SLiane Praza char *name_value;
26371f6eb021SLiane Praza property_t *name_prop = NULL;
26381f6eb021SLiane Praza int r = 0;
26391f6eb021SLiane Praza
26401f6eb021SLiane Praza for (cursor = values->xmlChildrenNode;
26411f6eb021SLiane Praza (cursor != NULL) && (r == 0);
26421f6eb021SLiane Praza cursor = cursor->next) {
26431f6eb021SLiane Praza if (lxml_ignorable_block(cursor))
26441f6eb021SLiane Praza continue;
26451f6eb021SLiane Praza if (lxml_xlate_element(cursor->name) != SC_VALUE) {
26461f6eb021SLiane Praza uu_die(gettext("\"%s\" is an illegal element in the "
26471f6eb021SLiane Praza "%s element of %s\n"), (char *)cursor->name,
26481f6eb021SLiane Praza (char *)values->name, service->sc_name);
26491f6eb021SLiane Praza }
26501f6eb021SLiane Praza r = lxml_get_tm_value_element(service, pg, cursor, &name_value);
26511f6eb021SLiane Praza if (r == 0) {
26521f6eb021SLiane Praza /*
26531f6eb021SLiane Praza * There is no need to free the memory
26541f6eb021SLiane Praza * associated with name_value, because the
26551f6eb021SLiane Praza * property value will end up pointing to
26561f6eb021SLiane Praza * the memory.
26571f6eb021SLiane Praza */
26581f6eb021SLiane Praza astring_prop_value(&name_prop,
26591f6eb021SLiane Praza SCF_PROPERTY_TM_VALUES_NAME, name_value,
26601f6eb021SLiane Praza B_TRUE);
26611f6eb021SLiane Praza }
26621f6eb021SLiane Praza }
26631f6eb021SLiane Praza
26641f6eb021SLiane Praza /* Attach the name property if we created one. */
26651f6eb021SLiane Praza if ((r == 0) && (name_prop != NULL)) {
26661f6eb021SLiane Praza r = internal_attach_property(pg, name_prop);
26671f6eb021SLiane Praza }
26681f6eb021SLiane Praza if ((r != 0) && (name_prop != NULL)) {
26691f6eb021SLiane Praza internal_property_free(name_prop);
26701f6eb021SLiane Praza }
26711f6eb021SLiane Praza
26721f6eb021SLiane Praza return (r);
26731f6eb021SLiane Praza }
26741f6eb021SLiane Praza
26751f6eb021SLiane Praza /*
26761f6eb021SLiane Praza * This function processes a prop_pattern element within a pg_pattern XML
26771f6eb021SLiane Praza * element. First it creates a property group to hold the prop_pattern
26781f6eb021SLiane Praza * information. The name of this property group is the concatenation of:
26791f6eb021SLiane Praza * - SCF_PG_TM_PROP_PATTERN_PREFIX
26801f6eb021SLiane Praza * - The unique part of the property group name of the enclosing
26811f6eb021SLiane Praza * pg_pattern. The property group name of the enclosing pg_pattern
26821f6eb021SLiane Praza * is passed to us in pgpat_name. The unique part, is the part
26831f6eb021SLiane Praza * following SCF_PG_TM_PG_PATTERN_PREFIX.
26841f6eb021SLiane Praza * - The name of this prop_pattern element.
26851f6eb021SLiane Praza *
26861f6eb021SLiane Praza * After creating the property group, the prop_pattern attributes are saved
26871f6eb021SLiane Praza * as properties in the PG. Finally, the prop_pattern elements are
26881f6eb021SLiane Praza * processed and added to the PG.
26891f6eb021SLiane Praza */
26901f6eb021SLiane Praza static int
lxml_get_tm_prop_pattern(entity_t * service,xmlNodePtr prop_pattern,const char * pgpat_name)26911f6eb021SLiane Praza lxml_get_tm_prop_pattern(entity_t *service, xmlNodePtr prop_pattern,
26921f6eb021SLiane Praza const char *pgpat_name)
26931f6eb021SLiane Praza {
26941f6eb021SLiane Praza xmlNodePtr cursor;
26951f6eb021SLiane Praza int extra;
26961f6eb021SLiane Praza pgroup_t *pg;
26971f6eb021SLiane Praza property_t *p;
26981f6eb021SLiane Praza char *pg_name;
26991f6eb021SLiane Praza size_t prefix_len;
27001f6eb021SLiane Praza xmlChar *prop_pattern_name;
27011f6eb021SLiane Praza int r;
27021f6eb021SLiane Praza const char *unique;
27031f6eb021SLiane Praza value_t *v;
27041f6eb021SLiane Praza
27051f6eb021SLiane Praza /* Find the unique part of the pg_pattern property group name. */
27061f6eb021SLiane Praza prefix_len = strlen(SCF_PG_TM_PG_PAT_BASE);
27071f6eb021SLiane Praza assert(strncmp(pgpat_name, SCF_PG_TM_PG_PAT_BASE, prefix_len) == 0);
27081f6eb021SLiane Praza unique = pgpat_name + prefix_len;
27091f6eb021SLiane Praza
27101f6eb021SLiane Praza /*
27111f6eb021SLiane Praza * We need to get the value of the name attribute first. The
27121f6eb021SLiane Praza * prop_pattern name as well as the name of the enclosing
27131f6eb021SLiane Praza * pg_pattern both constitute part of the name of the property
27141f6eb021SLiane Praza * group that we will create.
27151f6eb021SLiane Praza */
27161f6eb021SLiane Praza prop_pattern_name = xmlGetProp(prop_pattern, (xmlChar *)name_attr);
27171f6eb021SLiane Praza if ((prop_pattern_name == NULL) || (*prop_pattern_name == 0)) {
27181f6eb021SLiane Praza semerr(gettext("prop_pattern name is missing for %s\n"),
27191f6eb021SLiane Praza service->sc_name);
27201f6eb021SLiane Praza return (-1);
27211f6eb021SLiane Praza }
27221f6eb021SLiane Praza if (uu_check_name((const char *)prop_pattern_name,
27231f6eb021SLiane Praza UU_NAME_DOMAIN) != 0) {
27241f6eb021SLiane Praza semerr(gettext("prop_pattern name, \"%s\", for %s is not "
27251f6eb021SLiane Praza "valid.\n"), prop_pattern_name, service->sc_name);
27261f6eb021SLiane Praza xmlFree(prop_pattern_name);
27271f6eb021SLiane Praza return (-1);
27281f6eb021SLiane Praza }
27291f6eb021SLiane Praza pg_name = safe_malloc(max_scf_name_len + 1);
27301f6eb021SLiane Praza if ((extra = snprintf(pg_name, max_scf_name_len + 1, "%s%s_%s",
27311f6eb021SLiane Praza SCF_PG_TM_PROP_PATTERN_PREFIX, unique,
27321f6eb021SLiane Praza (char *)prop_pattern_name)) >= max_scf_name_len + 1) {
27331f6eb021SLiane Praza uu_die(gettext("prop_pattern name, \"%s\", for %s is %d "
27341f6eb021SLiane Praza "characters too long\n"), (char *)prop_pattern_name,
27351f6eb021SLiane Praza service->sc_name, extra - max_scf_name_len);
27361f6eb021SLiane Praza }
27371f6eb021SLiane Praza
27381f6eb021SLiane Praza /*
27391f6eb021SLiane Praza * Create the property group, the property referencing the pg_pattern
27401f6eb021SLiane Praza * name, and add the prop_pattern attributes to the property group.
27411f6eb021SLiane Praza */
27421f6eb021SLiane Praza pg = internal_pgroup_create_strict(service, pg_name,
27431f6eb021SLiane Praza SCF_GROUP_TEMPLATE_PROP_PATTERN);
27441f6eb021SLiane Praza if (pg == NULL) {
27451f6eb021SLiane Praza uu_die(gettext("Property group for prop_pattern, \"%s\", "
27461f6eb021SLiane Praza "already exists in %s\n"), prop_pattern_name,
27471f6eb021SLiane Praza service->sc_name);
27481f6eb021SLiane Praza }
27491f6eb021SLiane Praza
27501f6eb021SLiane Praza p = internal_property_create(SCF_PROPERTY_TM_PG_PATTERN,
27511f6eb021SLiane Praza SCF_TYPE_ASTRING, 1, safe_strdup(pgpat_name));
27521f6eb021SLiane Praza /*
27531f6eb021SLiane Praza * Unfortunately, internal_property_create() does not set the free
27541f6eb021SLiane Praza * function for the value, so we'll set it now.
27551f6eb021SLiane Praza */
27561f6eb021SLiane Praza v = uu_list_first(p->sc_property_values);
27571f6eb021SLiane Praza v->sc_free = lxml_free_str;
27581f6eb021SLiane Praza if (internal_attach_property(pg, p) != 0)
27591f6eb021SLiane Praza internal_property_free(p);
27601f6eb021SLiane Praza
27611f6eb021SLiane Praza
27621f6eb021SLiane Praza r = lxml_get_prop_pattern_attributes(pg, prop_pattern);
27631f6eb021SLiane Praza if (r != 0)
27641f6eb021SLiane Praza goto out;
27651f6eb021SLiane Praza
27661f6eb021SLiane Praza /*
27671f6eb021SLiane Praza * Now process the elements of prop_pattern
27681f6eb021SLiane Praza */
27691f6eb021SLiane Praza for (cursor = prop_pattern->xmlChildrenNode;
27701f6eb021SLiane Praza cursor != NULL;
27711f6eb021SLiane Praza cursor = cursor->next) {
27721f6eb021SLiane Praza if (lxml_ignorable_block(cursor))
27731f6eb021SLiane Praza continue;
27741f6eb021SLiane Praza
27751f6eb021SLiane Praza switch (lxml_xlate_element(cursor->name)) {
27761f6eb021SLiane Praza case SC_CARDINALITY:
27771f6eb021SLiane Praza r = lxml_get_tm_cardinality(service, pg, cursor);
27781f6eb021SLiane Praza if (r != 0)
27791f6eb021SLiane Praza goto out;
27801f6eb021SLiane Praza break;
27811f6eb021SLiane Praza case SC_CHOICES:
27821f6eb021SLiane Praza r = lxml_get_tm_choices(service, pg, cursor);
27831f6eb021SLiane Praza if (r != 0)
27841f6eb021SLiane Praza goto out;
27851f6eb021SLiane Praza break;
27861f6eb021SLiane Praza case SC_COMMON_NAME:
27871f6eb021SLiane Praza (void) lxml_get_all_loctext(service, pg, cursor,
27881f6eb021SLiane Praza COMMON_NAME_FMT, (const char *)cursor->name);
27891f6eb021SLiane Praza break;
27901f6eb021SLiane Praza case SC_CONSTRAINTS:
27911f6eb021SLiane Praza r = lxml_get_tm_constraints(service, pg, cursor);
27921f6eb021SLiane Praza if (r != 0)
27931f6eb021SLiane Praza goto out;
27941f6eb021SLiane Praza break;
27951f6eb021SLiane Praza case SC_DESCRIPTION:
27961f6eb021SLiane Praza (void) lxml_get_all_loctext(service, pg, cursor,
27971f6eb021SLiane Praza DESCRIPTION_FMT, (const char *)cursor->name);
27981f6eb021SLiane Praza break;
27991f6eb021SLiane Praza case SC_INTERNAL_SEPARATORS:
28001f6eb021SLiane Praza r = lxml_get_tm_internal_seps(service, pg, cursor);
28011f6eb021SLiane Praza if (r != 0)
28021f6eb021SLiane Praza goto out;
28031f6eb021SLiane Praza break;
28041f6eb021SLiane Praza case SC_UNITS:
28051f6eb021SLiane Praza (void) lxml_get_all_loctext(service, pg, cursor,
28061f6eb021SLiane Praza UNITS_FMT, "units");
28071f6eb021SLiane Praza break;
28081f6eb021SLiane Praza case SC_VALUES:
28091f6eb021SLiane Praza (void) lxml_get_tm_values(service, pg, cursor);
28101f6eb021SLiane Praza break;
28111f6eb021SLiane Praza case SC_VISIBILITY:
28121f6eb021SLiane Praza /*
28131f6eb021SLiane Praza * The visibility element is empty, so we only need
28141f6eb021SLiane Praza * to proccess the value attribute.
28151f6eb021SLiane Praza */
28161f6eb021SLiane Praza (void) new_str_prop_from_attr(pg,
28171f6eb021SLiane Praza SCF_PROPERTY_TM_VISIBILITY, SCF_TYPE_ASTRING,
28181f6eb021SLiane Praza cursor, value_attr);
28191f6eb021SLiane Praza break;
28201f6eb021SLiane Praza default:
28211f6eb021SLiane Praza uu_die(gettext("illegal element \"%s\" in prop_pattern "
28221f6eb021SLiane Praza "for service \"%s\"\n"), cursor->name,
28231f6eb021SLiane Praza service->sc_name);
28241f6eb021SLiane Praza }
28251f6eb021SLiane Praza }
28261f6eb021SLiane Praza
28271f6eb021SLiane Praza out:
28281f6eb021SLiane Praza xmlFree(prop_pattern_name);
28291f6eb021SLiane Praza free(pg_name);
28301f6eb021SLiane Praza return (r);
28311f6eb021SLiane Praza }
28321f6eb021SLiane Praza
28331f6eb021SLiane Praza /*
28341f6eb021SLiane Praza * Get the pg_pattern attributes and save them as properties in the
28351f6eb021SLiane Praza * property group at pg. The pg_pattern element accepts four attributes --
28361f6eb021SLiane Praza * name, type, required and target.
28371f6eb021SLiane Praza */
28381f6eb021SLiane Praza static int
lxml_get_pg_pattern_attributes(pgroup_t * pg,xmlNodePtr cursor)28391f6eb021SLiane Praza lxml_get_pg_pattern_attributes(pgroup_t *pg, xmlNodePtr cursor)
28401f6eb021SLiane Praza {
28411f6eb021SLiane Praza if (new_opt_str_prop_from_attr(pg, SCF_PROPERTY_TM_NAME,
28421f6eb021SLiane Praza SCF_TYPE_ASTRING, cursor, name_attr, NULL) != 0) {
28431f6eb021SLiane Praza return (-1);
28441f6eb021SLiane Praza }
28451f6eb021SLiane Praza if (new_opt_str_prop_from_attr(pg, SCF_PROPERTY_TM_TYPE,
28461f6eb021SLiane Praza SCF_TYPE_ASTRING, cursor, type_attr, NULL) != 0) {
28471f6eb021SLiane Praza return (-1);
28481f6eb021SLiane Praza }
28491f6eb021SLiane Praza if (new_opt_str_prop_from_attr(pg, SCF_PROPERTY_TM_TARGET,
28501f6eb021SLiane Praza SCF_TYPE_ASTRING, cursor, target_attr, NULL) != 0) {
28511f6eb021SLiane Praza return (-1);
28521f6eb021SLiane Praza }
28531f6eb021SLiane Praza if (new_bool_prop_from_attr(pg, SCF_PROPERTY_TM_REQUIRED, cursor,
28541f6eb021SLiane Praza required_attr) != 0)
28551f6eb021SLiane Praza return (-1);
28561f6eb021SLiane Praza return (0);
28571f6eb021SLiane Praza }
28581f6eb021SLiane Praza
28591f6eb021SLiane Praza /*
28601f6eb021SLiane Praza * There are several restrictions on the pg_pattern attributes that cannot
28611f6eb021SLiane Praza * be specifed in the service bundle DTD. This function verifies that
28621f6eb021SLiane Praza * those restrictions have been satisfied. The restrictions are:
28631f6eb021SLiane Praza *
28641f6eb021SLiane Praza * - The target attribute may have a value of "instance" only when the
28651f6eb021SLiane Praza * template block is in a service declaration.
28661f6eb021SLiane Praza *
28671f6eb021SLiane Praza * - The target attribute may have a value of "delegate" only when the
28681f6eb021SLiane Praza * template block applies to a restarter.
28691f6eb021SLiane Praza *
28701f6eb021SLiane Praza * - The target attribute may have a value of "all" only when the
28711f6eb021SLiane Praza * template block applies to the master restarter.
28721f6eb021SLiane Praza *
28731f6eb021SLiane Praza * The function returns 0 on success and -1 on failure.
28741f6eb021SLiane Praza */
28751f6eb021SLiane Praza static int
verify_pg_pattern_attributes(entity_t * s,pgroup_t * pg)28761f6eb021SLiane Praza verify_pg_pattern_attributes(entity_t *s, pgroup_t *pg)
28771f6eb021SLiane Praza {
28781f6eb021SLiane Praza int is_restarter;
28791f6eb021SLiane Praza property_t *target;
28801f6eb021SLiane Praza value_t *v;
28811f6eb021SLiane Praza
28821f6eb021SLiane Praza /* Find the value of the target property. */
28831f6eb021SLiane Praza target = internal_property_find(pg, SCF_PROPERTY_TM_TARGET);
28841f6eb021SLiane Praza if (target == NULL) {
28851f6eb021SLiane Praza uu_die(gettext("pg_pattern is missing the %s attribute "
28861f6eb021SLiane Praza "in %s\n"), target_attr, s->sc_name);
28871f6eb021SLiane Praza return (-1);
28881f6eb021SLiane Praza }
28891f6eb021SLiane Praza v = uu_list_first(target->sc_property_values);
28901f6eb021SLiane Praza assert(v != NULL);
28911f6eb021SLiane Praza assert(v->sc_type == SCF_TYPE_ASTRING);
28921f6eb021SLiane Praza
28931f6eb021SLiane Praza /*
28941f6eb021SLiane Praza * If target has a value of instance, the template must be in a
28951f6eb021SLiane Praza * service object.
28961f6eb021SLiane Praza */
28971f6eb021SLiane Praza if (strcmp(v->sc_u.sc_string, "instance") == 0) {
28981f6eb021SLiane Praza if (s->sc_etype != SVCCFG_SERVICE_OBJECT) {
28991f6eb021SLiane Praza uu_warn(gettext("pg_pattern %s attribute may only "
29001f6eb021SLiane Praza "have a value of \"instance\" when it is in a "
29011f6eb021SLiane Praza "service declaration.\n"), target_attr);
29021f6eb021SLiane Praza return (-1);
29031f6eb021SLiane Praza }
29041f6eb021SLiane Praza }
29051f6eb021SLiane Praza
29061f6eb021SLiane Praza /*
29071f6eb021SLiane Praza * If target has a value of "delegate", the template must be in a
29081f6eb021SLiane Praza * restarter.
29091f6eb021SLiane Praza */
29101f6eb021SLiane Praza if (strcmp(v->sc_u.sc_string, "delegate") == 0) {
29111f6eb021SLiane Praza is_restarter = 0;
29121f6eb021SLiane Praza if ((s->sc_etype == SVCCFG_SERVICE_OBJECT) &&
29131f6eb021SLiane Praza (s->sc_u.sc_service.sc_service_type == SVCCFG_RESTARTER)) {
29141f6eb021SLiane Praza is_restarter = 1;
29151f6eb021SLiane Praza }
29161f6eb021SLiane Praza if ((s->sc_etype == SVCCFG_INSTANCE_OBJECT) &&
29171f6eb021SLiane Praza (s->sc_parent->sc_u.sc_service.sc_service_type ==
29181f6eb021SLiane Praza SVCCFG_RESTARTER)) {
29191f6eb021SLiane Praza is_restarter = 1;
29201f6eb021SLiane Praza }
29211f6eb021SLiane Praza if (is_restarter == 0) {
29221f6eb021SLiane Praza uu_warn(gettext("pg_pattern %s attribute has a "
29231f6eb021SLiane Praza "value of \"delegate\" but is not in a "
29241f6eb021SLiane Praza "restarter service\n"), target_attr);
29251f6eb021SLiane Praza return (-1);
29261f6eb021SLiane Praza }
29271f6eb021SLiane Praza }
29281f6eb021SLiane Praza
29291f6eb021SLiane Praza /*
29301f6eb021SLiane Praza * If target has a value of "all", the template must be in the
29311f6eb021SLiane Praza * global (SCF_SERVICE_GLOBAL) service.
29321f6eb021SLiane Praza */
29331f6eb021SLiane Praza if (strcmp(v->sc_u.sc_string, all_value) == 0) {
29341f6eb021SLiane Praza if (s->sc_etype != SVCCFG_SERVICE_OBJECT) {
29351f6eb021SLiane Praza uu_warn(gettext("pg_pattern %s attribute has a "
29361f6eb021SLiane Praza "value of \"%s\" but is not in a "
29371f6eb021SLiane Praza "service entity.\n"), target_attr, all_value);
29381f6eb021SLiane Praza return (-1);
29391f6eb021SLiane Praza }
29401f6eb021SLiane Praza if (strcmp(s->sc_fmri, SCF_SERVICE_GLOBAL) != 0) {
29411f6eb021SLiane Praza uu_warn(gettext("pg_pattern %s attribute has a "
29421f6eb021SLiane Praza "value of \"%s\" but is in the \"%s\" service. "
29431f6eb021SLiane Praza "pg_patterns with target \"%s\" are only allowed "
29441f6eb021SLiane Praza "in the global service.\n"),
29451f6eb021SLiane Praza target_attr, all_value, s->sc_fmri, all_value);
29461f6eb021SLiane Praza return (-1);
29471f6eb021SLiane Praza }
29481f6eb021SLiane Praza }
29491f6eb021SLiane Praza
29501f6eb021SLiane Praza return (0);
29511f6eb021SLiane Praza }
29521f6eb021SLiane Praza
29531f6eb021SLiane Praza static int
lxml_get_tm_pg_pattern(entity_t * service,xmlNodePtr pg_pattern)29541f6eb021SLiane Praza lxml_get_tm_pg_pattern(entity_t *service, xmlNodePtr pg_pattern)
29551f6eb021SLiane Praza {
29561f6eb021SLiane Praza xmlNodePtr cursor;
29571f6eb021SLiane Praza int out_len;
29581f6eb021SLiane Praza xmlChar *name;
29591f6eb021SLiane Praza pgroup_t *pg = NULL;
29601f6eb021SLiane Praza char *pg_name;
29611f6eb021SLiane Praza int r = -1;
29621f6eb021SLiane Praza xmlChar *type;
29631f6eb021SLiane Praza
29641f6eb021SLiane Praza pg_name = safe_malloc(max_scf_name_len + 1);
29651f6eb021SLiane Praza
29661f6eb021SLiane Praza /*
29671f6eb021SLiane Praza * Get the name and type attributes. Their presence or absence
29681f6eb021SLiane Praza * determines whcih prefix we will use for the property group name.
29691f6eb021SLiane Praza * There are four cases -- neither attribute is present, both are
29701f6eb021SLiane Praza * present, only name is present or only type is present.
29711f6eb021SLiane Praza */
29721f6eb021SLiane Praza name = xmlGetProp(pg_pattern, (xmlChar *)name_attr);
29731f6eb021SLiane Praza type = xmlGetProp(pg_pattern, (xmlChar *)type_attr);
29741f6eb021SLiane Praza if ((name == NULL) || (*name == 0)) {
29751f6eb021SLiane Praza if ((type == NULL) || (*type == 0)) {
29761f6eb021SLiane Praza /* PG name contains only the prefix in this case */
29771f6eb021SLiane Praza if (strlcpy(pg_name, SCF_PG_TM_PG_PATTERN_PREFIX,
29781f6eb021SLiane Praza max_scf_name_len + 1) >= max_scf_name_len + 1) {
29791f6eb021SLiane Praza uu_die(gettext("Unable to create pg_pattern "
29801f6eb021SLiane Praza "property for %s\n"), service->sc_name);
29811f6eb021SLiane Praza }
29821f6eb021SLiane Praza } else {
29831f6eb021SLiane Praza /*
29841f6eb021SLiane Praza * If we have a type and no name, the type becomes
29851f6eb021SLiane Praza * part of the pg_pattern property group name.
29861f6eb021SLiane Praza */
29871f6eb021SLiane Praza if ((out_len = snprintf(pg_name, max_scf_name_len + 1,
29881f6eb021SLiane Praza "%s%s", SCF_PG_TM_PG_PATTERN_T_PREFIX, type)) >=
29891f6eb021SLiane Praza max_scf_name_len + 1) {
29901f6eb021SLiane Praza uu_die(gettext("pg_pattern type is for %s is "
29911f6eb021SLiane Praza "%d bytes too long\n"), service->sc_name,
29921f6eb021SLiane Praza out_len - max_scf_name_len);
29931f6eb021SLiane Praza }
29941f6eb021SLiane Praza }
29951f6eb021SLiane Praza } else {
29961f6eb021SLiane Praza const char *prefix;
29971f6eb021SLiane Praza
29981f6eb021SLiane Praza /* Make sure that the name is valid. */
29991f6eb021SLiane Praza if (uu_check_name((const char *)name, UU_NAME_DOMAIN) != 0) {
30001f6eb021SLiane Praza semerr(gettext("pg_pattern name attribute, \"%s\", "
30011f6eb021SLiane Praza "for %s is invalid\n"), name, service->sc_name);
30021f6eb021SLiane Praza goto out;
30031f6eb021SLiane Praza }
30041f6eb021SLiane Praza
30051f6eb021SLiane Praza /*
30061f6eb021SLiane Praza * As long as the pg_pattern has a name, it becomes part of
30071f6eb021SLiane Praza * the name of the pg_pattern property group name. We
30081f6eb021SLiane Praza * merely need to pick the appropriate prefix.
30091f6eb021SLiane Praza */
30101f6eb021SLiane Praza if ((type == NULL) || (*type == 0)) {
30111f6eb021SLiane Praza prefix = SCF_PG_TM_PG_PATTERN_N_PREFIX;
30121f6eb021SLiane Praza } else {
30131f6eb021SLiane Praza prefix = SCF_PG_TM_PG_PATTERN_NT_PREFIX;
30141f6eb021SLiane Praza }
30151f6eb021SLiane Praza if ((out_len = snprintf(pg_name, max_scf_name_len + 1, "%s%s",
30161f6eb021SLiane Praza prefix, name)) >= max_scf_name_len + 1) {
30171f6eb021SLiane Praza uu_die(gettext("pg_pattern property group name "
30181f6eb021SLiane Praza "for %s is %d bytes too long\n"), service->sc_name,
30191f6eb021SLiane Praza out_len - max_scf_name_len);
30201f6eb021SLiane Praza }
30211f6eb021SLiane Praza }
30221f6eb021SLiane Praza
30231f6eb021SLiane Praza /*
30241f6eb021SLiane Praza * Create the property group for holding this pg_pattern
30251f6eb021SLiane Praza * information, and capture the pg_pattern attributes.
30261f6eb021SLiane Praza */
30271f6eb021SLiane Praza pg = internal_pgroup_create_strict(service, pg_name,
30281f6eb021SLiane Praza SCF_GROUP_TEMPLATE_PG_PATTERN);
30291f6eb021SLiane Praza if (pg == NULL) {
30301f6eb021SLiane Praza if ((name == NULL) || (*name == 0)) {
30311f6eb021SLiane Praza if ((type == NULL) ||(*type == 0)) {
30321f6eb021SLiane Praza semerr(gettext("pg_pattern with empty name and "
30331f6eb021SLiane Praza "type is not unique in %s\n"),
30341f6eb021SLiane Praza service->sc_name);
30351f6eb021SLiane Praza } else {
30361f6eb021SLiane Praza semerr(gettext("pg_pattern with empty name and "
30371f6eb021SLiane Praza "type \"%s\" is not unique in %s\n"),
30381f6eb021SLiane Praza type, service->sc_name);
30391f6eb021SLiane Praza }
30401f6eb021SLiane Praza } else {
30411f6eb021SLiane Praza if ((type == NULL) || (*type == 0)) {
30421f6eb021SLiane Praza semerr(gettext("pg_pattern with name \"%s\" "
30431f6eb021SLiane Praza "and empty type is not unique in %s\n"),
30441f6eb021SLiane Praza name, service->sc_name);
30451f6eb021SLiane Praza } else {
30461f6eb021SLiane Praza semerr(gettext("pg_pattern with name \"%s\" "
30471f6eb021SLiane Praza "and type \"%s\" is not unique in %s\n"),
30481f6eb021SLiane Praza name, type, service->sc_name);
30491f6eb021SLiane Praza }
30501f6eb021SLiane Praza }
30511f6eb021SLiane Praza goto out;
30521f6eb021SLiane Praza }
30531f6eb021SLiane Praza
30541f6eb021SLiane Praza /*
30551f6eb021SLiane Praza * Get the pg_pattern attributes from the manifest and verify
30561f6eb021SLiane Praza * that they satisfy our restrictions.
30571f6eb021SLiane Praza */
30581f6eb021SLiane Praza r = lxml_get_pg_pattern_attributes(pg, pg_pattern);
30591f6eb021SLiane Praza if (r != 0)
30601f6eb021SLiane Praza goto out;
30611f6eb021SLiane Praza if (verify_pg_pattern_attributes(service, pg) != 0) {
30621f6eb021SLiane Praza semerr(gettext("Invalid pg_pattern attributes in %s\n"),
30631f6eb021SLiane Praza service->sc_name);
30641f6eb021SLiane Praza r = -1;
30651f6eb021SLiane Praza goto out;
30661f6eb021SLiane Praza }
30671f6eb021SLiane Praza
30681f6eb021SLiane Praza /*
30691f6eb021SLiane Praza * Now process all of the elements of pg_pattern.
30701f6eb021SLiane Praza */
30711f6eb021SLiane Praza for (cursor = pg_pattern->xmlChildrenNode;
30721f6eb021SLiane Praza cursor != NULL;
30731f6eb021SLiane Praza cursor = cursor->next) {
30741f6eb021SLiane Praza if (lxml_ignorable_block(cursor))
30751f6eb021SLiane Praza continue;
30761f6eb021SLiane Praza
30771f6eb021SLiane Praza switch (lxml_xlate_element(cursor->name)) {
30781f6eb021SLiane Praza case SC_COMMON_NAME:
30791f6eb021SLiane Praza (void) lxml_get_all_loctext(service, pg, cursor,
30801f6eb021SLiane Praza COMMON_NAME_FMT, (const char *)cursor->name);
30811f6eb021SLiane Praza break;
30821f6eb021SLiane Praza case SC_DESCRIPTION:
30831f6eb021SLiane Praza (void) lxml_get_all_loctext(service, pg, cursor,
30841f6eb021SLiane Praza DESCRIPTION_FMT, (const char *)cursor->name);
30851f6eb021SLiane Praza break;
30861f6eb021SLiane Praza case SC_PROP_PATTERN:
30871f6eb021SLiane Praza r = lxml_get_tm_prop_pattern(service, cursor,
30881f6eb021SLiane Praza pg_name);
30891f6eb021SLiane Praza if (r != 0)
30901f6eb021SLiane Praza goto out;
30911f6eb021SLiane Praza break;
30921f6eb021SLiane Praza default:
30931f6eb021SLiane Praza uu_die(gettext("illegal element \"%s\" in pg_pattern "
30941f6eb021SLiane Praza "for service \"%s\"\n"), cursor->name,
30951f6eb021SLiane Praza service->sc_name);
30961f6eb021SLiane Praza }
30971f6eb021SLiane Praza }
30981f6eb021SLiane Praza
30991f6eb021SLiane Praza out:
31001f6eb021SLiane Praza if ((r != 0) && (pg != NULL)) {
31011f6eb021SLiane Praza internal_detach_pgroup(service, pg);
31021f6eb021SLiane Praza internal_pgroup_free(pg);
31031f6eb021SLiane Praza }
31041f6eb021SLiane Praza free(pg_name);
31051f6eb021SLiane Praza xmlFree(name);
31061f6eb021SLiane Praza xmlFree(type);
31071f6eb021SLiane Praza
31081f6eb021SLiane Praza return (r);
31091f6eb021SLiane Praza }
31101f6eb021SLiane Praza
31111f6eb021SLiane Praza static int
lxml_get_template(entity_t * service,xmlNodePtr templ)31127c478bd9Sstevel@tonic-gate lxml_get_template(entity_t *service, xmlNodePtr templ)
31137c478bd9Sstevel@tonic-gate {
31147c478bd9Sstevel@tonic-gate xmlNodePtr cursor;
31157c478bd9Sstevel@tonic-gate
31167c478bd9Sstevel@tonic-gate for (cursor = templ->xmlChildrenNode; cursor != NULL;
31177c478bd9Sstevel@tonic-gate cursor = cursor->next) {
31187c478bd9Sstevel@tonic-gate if (lxml_ignorable_block(cursor))
31197c478bd9Sstevel@tonic-gate continue;
31207c478bd9Sstevel@tonic-gate
31217c478bd9Sstevel@tonic-gate switch (lxml_xlate_element(cursor->name)) {
31227c478bd9Sstevel@tonic-gate case SC_COMMON_NAME:
31237c478bd9Sstevel@tonic-gate (void) lxml_get_tm_common_name(service, cursor);
31247c478bd9Sstevel@tonic-gate break;
31257c478bd9Sstevel@tonic-gate case SC_DESCRIPTION:
31267c478bd9Sstevel@tonic-gate (void) lxml_get_tm_description(service, cursor);
31277c478bd9Sstevel@tonic-gate break;
31287c478bd9Sstevel@tonic-gate case SC_DOCUMENTATION:
31297c478bd9Sstevel@tonic-gate (void) lxml_get_tm_documentation(service, cursor);
31307c478bd9Sstevel@tonic-gate break;
31311f6eb021SLiane Praza case SC_PG_PATTERN:
31321f6eb021SLiane Praza if (lxml_get_tm_pg_pattern(service, cursor) != 0)
31331f6eb021SLiane Praza return (-1);
31341f6eb021SLiane Praza break;
31357c478bd9Sstevel@tonic-gate default:
31367c478bd9Sstevel@tonic-gate uu_die(gettext("illegal element \"%s\" on template "
31377c478bd9Sstevel@tonic-gate "for service \"%s\"\n"),
31387c478bd9Sstevel@tonic-gate cursor->name, service->sc_name);
31397c478bd9Sstevel@tonic-gate }
31407c478bd9Sstevel@tonic-gate }
31417c478bd9Sstevel@tonic-gate
31427c478bd9Sstevel@tonic-gate return (0);
31437c478bd9Sstevel@tonic-gate }
31447c478bd9Sstevel@tonic-gate
31457c478bd9Sstevel@tonic-gate static int
lxml_get_default_instance(entity_t * service,xmlNodePtr definst)31467c478bd9Sstevel@tonic-gate lxml_get_default_instance(entity_t *service, xmlNodePtr definst)
31477c478bd9Sstevel@tonic-gate {
31487c478bd9Sstevel@tonic-gate entity_t *i;
31497c478bd9Sstevel@tonic-gate xmlChar *enabled;
31507c478bd9Sstevel@tonic-gate pgroup_t *pg;
31517c478bd9Sstevel@tonic-gate property_t *p;
31527c478bd9Sstevel@tonic-gate char *package;
31537c478bd9Sstevel@tonic-gate uint64_t enabled_val = 0;
31547c478bd9Sstevel@tonic-gate
31557c478bd9Sstevel@tonic-gate i = internal_instance_new("default");
31567c478bd9Sstevel@tonic-gate
31577c478bd9Sstevel@tonic-gate if ((enabled = xmlGetProp(definst, (xmlChar *)enabled_attr)) != NULL) {
31587c478bd9Sstevel@tonic-gate enabled_val = (strcmp(true, (const char *)enabled) == 0) ?
31597c478bd9Sstevel@tonic-gate 1 : 0;
31607c478bd9Sstevel@tonic-gate xmlFree(enabled);
31617c478bd9Sstevel@tonic-gate }
31627c478bd9Sstevel@tonic-gate
31637c478bd9Sstevel@tonic-gate /*
31647c478bd9Sstevel@tonic-gate * New general property group with enabled boolean property set.
31657c478bd9Sstevel@tonic-gate */
31667c478bd9Sstevel@tonic-gate
3167f329b923SSean Wilcox i->sc_op = service->sc_op;
31687c478bd9Sstevel@tonic-gate pg = internal_pgroup_new();
31697c478bd9Sstevel@tonic-gate (void) internal_attach_pgroup(i, pg);
31707c478bd9Sstevel@tonic-gate
31717c478bd9Sstevel@tonic-gate pg->sc_pgroup_name = (char *)scf_pg_general;
31727c478bd9Sstevel@tonic-gate pg->sc_pgroup_type = (char *)scf_group_framework;
31737c478bd9Sstevel@tonic-gate pg->sc_pgroup_flags = 0;
31747c478bd9Sstevel@tonic-gate
31757c478bd9Sstevel@tonic-gate p = internal_property_create(SCF_PROPERTY_ENABLED, SCF_TYPE_BOOLEAN, 1,
31767c478bd9Sstevel@tonic-gate enabled_val);
31777c478bd9Sstevel@tonic-gate
31787c478bd9Sstevel@tonic-gate (void) internal_attach_property(pg, p);
31797c478bd9Sstevel@tonic-gate
31807c478bd9Sstevel@tonic-gate /*
31817c478bd9Sstevel@tonic-gate * Add general/package property if PKGINST is set.
31827c478bd9Sstevel@tonic-gate */
31837c478bd9Sstevel@tonic-gate if ((package = getenv("PKGINST")) != NULL) {
31847c478bd9Sstevel@tonic-gate p = internal_property_create(SCF_PROPERTY_PACKAGE,
31857c478bd9Sstevel@tonic-gate SCF_TYPE_ASTRING, 1, package);
31867c478bd9Sstevel@tonic-gate
31877c478bd9Sstevel@tonic-gate (void) internal_attach_property(pg, p);
31887c478bd9Sstevel@tonic-gate }
31897c478bd9Sstevel@tonic-gate
31907c478bd9Sstevel@tonic-gate return (internal_attach_entity(service, i));
31917c478bd9Sstevel@tonic-gate }
31927c478bd9Sstevel@tonic-gate
31937c478bd9Sstevel@tonic-gate /*
31947c478bd9Sstevel@tonic-gate * Translate an instance element into an internal property tree, added to
3195687293e1SAntonello Cruz * service. If op is SVCCFG_OP_APPLY (i.e., apply a profile), set the
3196687293e1SAntonello Cruz * enabled property to override.
3197f329b923SSean Wilcox *
3198f329b923SSean Wilcox * If op is SVCCFG_OP_APPLY (i.e., apply a profile), do not allow for
3199f329b923SSean Wilcox * modification of template data.
32007c478bd9Sstevel@tonic-gate */
32017c478bd9Sstevel@tonic-gate static int
lxml_get_instance(entity_t * service,xmlNodePtr inst,bundle_type_t bt,svccfg_op_t op)3202687293e1SAntonello Cruz lxml_get_instance(entity_t *service, xmlNodePtr inst, bundle_type_t bt,
3203687293e1SAntonello Cruz svccfg_op_t op)
32047c478bd9Sstevel@tonic-gate {
32057c478bd9Sstevel@tonic-gate entity_t *i;
32067c478bd9Sstevel@tonic-gate pgroup_t *pg;
32077c478bd9Sstevel@tonic-gate property_t *p;
32087c478bd9Sstevel@tonic-gate xmlNodePtr cursor;
32097c478bd9Sstevel@tonic-gate xmlChar *enabled;
3210687293e1SAntonello Cruz int r, e_val;
32117c478bd9Sstevel@tonic-gate
32127c478bd9Sstevel@tonic-gate /*
32137c478bd9Sstevel@tonic-gate * Fetch its attributes, as appropriate.
32147c478bd9Sstevel@tonic-gate */
32157c478bd9Sstevel@tonic-gate i = internal_instance_new((char *)xmlGetProp(inst,
32167c478bd9Sstevel@tonic-gate (xmlChar *)name_attr));
32177c478bd9Sstevel@tonic-gate
32187c478bd9Sstevel@tonic-gate /*
32197c478bd9Sstevel@tonic-gate * Note that this must be done before walking the children so that
32207c478bd9Sstevel@tonic-gate * sc_fmri is set in case we enter lxml_get_dependent().
32217c478bd9Sstevel@tonic-gate */
32227c478bd9Sstevel@tonic-gate r = internal_attach_entity(service, i);
32237c478bd9Sstevel@tonic-gate if (r != 0)
32247c478bd9Sstevel@tonic-gate return (r);
32257c478bd9Sstevel@tonic-gate
3226f329b923SSean Wilcox i->sc_op = op;
32277c478bd9Sstevel@tonic-gate enabled = xmlGetProp(inst, (xmlChar *)enabled_attr);
32287c478bd9Sstevel@tonic-gate
3229687293e1SAntonello Cruz if (enabled == NULL) {
3230687293e1SAntonello Cruz if (bt == SVCCFG_MANIFEST) {
3231687293e1SAntonello Cruz semerr(gettext("Instance \"%s\" missing attribute "
3232687293e1SAntonello Cruz "\"%s\".\n"), i->sc_name, enabled_attr);
3233687293e1SAntonello Cruz return (-1);
3234687293e1SAntonello Cruz }
3235687293e1SAntonello Cruz } else { /* enabled != NULL */
3236687293e1SAntonello Cruz if (strcmp(true, (const char *)enabled) != 0 &&
3237687293e1SAntonello Cruz strcmp(false, (const char *)enabled) != 0) {
3238687293e1SAntonello Cruz xmlFree(enabled);
3239687293e1SAntonello Cruz semerr(gettext("Invalid enabled value\n"));
3240687293e1SAntonello Cruz return (-1);
3241687293e1SAntonello Cruz }
32427c478bd9Sstevel@tonic-gate pg = internal_pgroup_new();
32437c478bd9Sstevel@tonic-gate (void) internal_attach_pgroup(i, pg);
32447c478bd9Sstevel@tonic-gate
32457c478bd9Sstevel@tonic-gate pg->sc_pgroup_name = (char *)scf_pg_general;
32467c478bd9Sstevel@tonic-gate pg->sc_pgroup_type = (char *)scf_group_framework;
32477c478bd9Sstevel@tonic-gate pg->sc_pgroup_flags = 0;
32487c478bd9Sstevel@tonic-gate
3249687293e1SAntonello Cruz e_val = (strcmp(true, (const char *)enabled) == 0);
3250687293e1SAntonello Cruz p = internal_property_create(SCF_PROPERTY_ENABLED,
3251687293e1SAntonello Cruz SCF_TYPE_BOOLEAN, 1, (uint64_t)e_val);
32527c478bd9Sstevel@tonic-gate
32533eae19d9Swesolows p->sc_property_override = (op == SVCCFG_OP_APPLY);
32547c478bd9Sstevel@tonic-gate
32557c478bd9Sstevel@tonic-gate (void) internal_attach_property(pg, p);
32567c478bd9Sstevel@tonic-gate
32577c478bd9Sstevel@tonic-gate xmlFree(enabled);
3258687293e1SAntonello Cruz }
32597c478bd9Sstevel@tonic-gate
32607c478bd9Sstevel@tonic-gate /*
32617c478bd9Sstevel@tonic-gate * Walk its child elements, as appropriate.
32627c478bd9Sstevel@tonic-gate */
32637c478bd9Sstevel@tonic-gate for (cursor = inst->xmlChildrenNode; cursor != NULL;
32647c478bd9Sstevel@tonic-gate cursor = cursor->next) {
32657c478bd9Sstevel@tonic-gate if (lxml_ignorable_block(cursor))
32667c478bd9Sstevel@tonic-gate continue;
32677c478bd9Sstevel@tonic-gate
32687c478bd9Sstevel@tonic-gate switch (lxml_xlate_element(cursor->name)) {
32697c478bd9Sstevel@tonic-gate case SC_RESTARTER:
32707c478bd9Sstevel@tonic-gate (void) lxml_get_restarter(i, cursor);
32717c478bd9Sstevel@tonic-gate break;
32727c478bd9Sstevel@tonic-gate case SC_DEPENDENCY:
32737c478bd9Sstevel@tonic-gate (void) lxml_get_dependency(i, cursor);
32747c478bd9Sstevel@tonic-gate break;
32757c478bd9Sstevel@tonic-gate case SC_DEPENDENT:
32767c478bd9Sstevel@tonic-gate (void) lxml_get_dependent(i, cursor);
32777c478bd9Sstevel@tonic-gate break;
32787c478bd9Sstevel@tonic-gate case SC_METHOD_CONTEXT:
32797c478bd9Sstevel@tonic-gate (void) lxml_get_entity_method_context(i, cursor);
32807c478bd9Sstevel@tonic-gate break;
32817c478bd9Sstevel@tonic-gate case SC_EXEC_METHOD:
32827c478bd9Sstevel@tonic-gate (void) lxml_get_exec_method(i, cursor);
32837c478bd9Sstevel@tonic-gate break;
32847c478bd9Sstevel@tonic-gate case SC_PROPERTY_GROUP:
32857c478bd9Sstevel@tonic-gate (void) lxml_get_pgroup(i, cursor);
32867c478bd9Sstevel@tonic-gate break;
32877c478bd9Sstevel@tonic-gate case SC_TEMPLATE:
3288f329b923SSean Wilcox if (op == SVCCFG_OP_APPLY) {
3289f329b923SSean Wilcox semerr(gettext("Template data for \"%s\" may "
3290f329b923SSean Wilcox "not be modified in a profile.\n"),
3291f329b923SSean Wilcox i->sc_name);
3292f329b923SSean Wilcox
3293f329b923SSean Wilcox return (-1);
3294f329b923SSean Wilcox }
3295f329b923SSean Wilcox
32961f6eb021SLiane Praza if (lxml_get_template(i, cursor) != 0)
32971f6eb021SLiane Praza return (-1);
32987c478bd9Sstevel@tonic-gate break;
3299f6e214c7SGavin Maltby case SC_NOTIFICATION_PARAMETERS:
3300f6e214c7SGavin Maltby if (lxml_get_notification_parameters(i, cursor) != 0)
3301f6e214c7SGavin Maltby return (-1);
3302f6e214c7SGavin Maltby break;
33037c478bd9Sstevel@tonic-gate default:
33047c478bd9Sstevel@tonic-gate uu_die(gettext(
33057c478bd9Sstevel@tonic-gate "illegal element \"%s\" on instance \"%s\"\n"),
33067c478bd9Sstevel@tonic-gate cursor->name, i->sc_name);
33077c478bd9Sstevel@tonic-gate break;
33087c478bd9Sstevel@tonic-gate }
33097c478bd9Sstevel@tonic-gate }
33107c478bd9Sstevel@tonic-gate
33117c478bd9Sstevel@tonic-gate return (0);
33127c478bd9Sstevel@tonic-gate }
33137c478bd9Sstevel@tonic-gate
33147c478bd9Sstevel@tonic-gate /* ARGSUSED1 */
33157c478bd9Sstevel@tonic-gate static int
lxml_get_single_instance(entity_t * entity,xmlNodePtr si)33167c478bd9Sstevel@tonic-gate lxml_get_single_instance(entity_t *entity, xmlNodePtr si)
33177c478bd9Sstevel@tonic-gate {
33187c478bd9Sstevel@tonic-gate pgroup_t *pg;
33197c478bd9Sstevel@tonic-gate property_t *p;
33207c478bd9Sstevel@tonic-gate int r;
33217c478bd9Sstevel@tonic-gate
33227c478bd9Sstevel@tonic-gate pg = internal_pgroup_find_or_create(entity, (char *)scf_pg_general,
33237c478bd9Sstevel@tonic-gate (char *)scf_group_framework);
33247c478bd9Sstevel@tonic-gate
33257c478bd9Sstevel@tonic-gate p = internal_property_create(SCF_PROPERTY_SINGLE_INSTANCE,
33267c478bd9Sstevel@tonic-gate SCF_TYPE_BOOLEAN, 1, (uint64_t)1);
33277c478bd9Sstevel@tonic-gate
33287c478bd9Sstevel@tonic-gate r = internal_attach_property(pg, p);
33297c478bd9Sstevel@tonic-gate if (r != 0) {
33307c478bd9Sstevel@tonic-gate internal_property_free(p);
33317c478bd9Sstevel@tonic-gate return (-1);
33327c478bd9Sstevel@tonic-gate }
33337c478bd9Sstevel@tonic-gate
33347c478bd9Sstevel@tonic-gate return (0);
33357c478bd9Sstevel@tonic-gate }
33367c478bd9Sstevel@tonic-gate
33377c478bd9Sstevel@tonic-gate /*
33389444c26fSTom Whitten * Check to see if the service should allow the upgrade
33399444c26fSTom Whitten * process to handle adding of the manifestfiles linkage.
33409444c26fSTom Whitten *
33419444c26fSTom Whitten * If the service exists and does not have a manifestfiles
33429444c26fSTom Whitten * property group then the upgrade process should handle
33439444c26fSTom Whitten * the service.
33449444c26fSTom Whitten *
33459444c26fSTom Whitten * If the service doesn't exist or the service exists
33469444c26fSTom Whitten * and has a manifestfiles property group then the import
33479444c26fSTom Whitten * process can handle the manifestfiles property group
33489444c26fSTom Whitten * work.
33499444c26fSTom Whitten *
33509444c26fSTom Whitten * This prevents potential cleanup of unaccounted for instances
33519444c26fSTom Whitten * in early manifest import due to upgrade process needing
33529444c26fSTom Whitten * information that has not yet been supplied by manifests
33539444c26fSTom Whitten * that are still located in the /var/svc manifests directory.
33549444c26fSTom Whitten */
33559444c26fSTom Whitten static int
lxml_check_upgrade(const char * service)33569444c26fSTom Whitten lxml_check_upgrade(const char *service) {
33579444c26fSTom Whitten scf_handle_t *h = NULL;
33589444c26fSTom Whitten scf_scope_t *sc = NULL;
33599444c26fSTom Whitten scf_service_t *svc = NULL;
33609444c26fSTom Whitten scf_propertygroup_t *pg = NULL;
33619444c26fSTom Whitten int rc = SCF_FAILED;
33629444c26fSTom Whitten
33639444c26fSTom Whitten if ((h = scf_handle_create(SCF_VERSION)) == NULL ||
33649444c26fSTom Whitten (sc = scf_scope_create(h)) == NULL ||
33659444c26fSTom Whitten (svc = scf_service_create(h)) == NULL ||
33669444c26fSTom Whitten (pg = scf_pg_create(h)) == NULL)
33679444c26fSTom Whitten goto out;
33689444c26fSTom Whitten
33699444c26fSTom Whitten if (scf_handle_bind(h) != 0)
33709444c26fSTom Whitten goto out;
33719444c26fSTom Whitten
33729444c26fSTom Whitten if (scf_handle_get_scope(h, SCF_FMRI_LOCAL_SCOPE, sc) == -1)
33739444c26fSTom Whitten goto out;
33749444c26fSTom Whitten
33759444c26fSTom Whitten if (scf_scope_get_service(sc, service, svc) != SCF_SUCCESS) {
33769444c26fSTom Whitten if (scf_error() == SCF_ERROR_NOT_FOUND)
33779444c26fSTom Whitten rc = SCF_SUCCESS;
33789444c26fSTom Whitten
33799444c26fSTom Whitten goto out;
33809444c26fSTom Whitten }
33819444c26fSTom Whitten
33829444c26fSTom Whitten if (scf_service_get_pg(svc, SCF_PG_MANIFESTFILES, pg) != SCF_SUCCESS)
33839444c26fSTom Whitten goto out;
33849444c26fSTom Whitten
33859444c26fSTom Whitten rc = SCF_SUCCESS;
33869444c26fSTom Whitten out:
33879444c26fSTom Whitten scf_pg_destroy(pg);
33889444c26fSTom Whitten scf_service_destroy(svc);
33899444c26fSTom Whitten scf_scope_destroy(sc);
33909444c26fSTom Whitten scf_handle_destroy(h);
33919444c26fSTom Whitten
33929444c26fSTom Whitten return (rc);
33939444c26fSTom Whitten }
33949444c26fSTom Whitten
33959444c26fSTom Whitten /*
33967c478bd9Sstevel@tonic-gate * Translate a service element into an internal instance/property tree, added
3397f329b923SSean Wilcox * to bundle.
3398f329b923SSean Wilcox *
3399f329b923SSean Wilcox * If op is SVCCFG_OP_APPLY (i.e., apply a profile), do not allow for
3400f329b923SSean Wilcox * modification of template data.
34017c478bd9Sstevel@tonic-gate */
34027c478bd9Sstevel@tonic-gate static int
lxml_get_service(bundle_t * bundle,xmlNodePtr svc,svccfg_op_t op)34033eae19d9Swesolows lxml_get_service(bundle_t *bundle, xmlNodePtr svc, svccfg_op_t op)
34047c478bd9Sstevel@tonic-gate {
340523294c7dSSean Wilcox pgroup_t *pg;
340623294c7dSSean Wilcox property_t *p;
34077c478bd9Sstevel@tonic-gate entity_t *s;
34087c478bd9Sstevel@tonic-gate xmlNodePtr cursor;
34097c478bd9Sstevel@tonic-gate xmlChar *type;
34107c478bd9Sstevel@tonic-gate xmlChar *version;
34117c478bd9Sstevel@tonic-gate int e;
34127c478bd9Sstevel@tonic-gate
34137c478bd9Sstevel@tonic-gate /*
34147c478bd9Sstevel@tonic-gate * Fetch attributes, as appropriate.
34157c478bd9Sstevel@tonic-gate */
34167c478bd9Sstevel@tonic-gate s = internal_service_new((char *)xmlGetProp(svc,
34177c478bd9Sstevel@tonic-gate (xmlChar *)name_attr));
34187c478bd9Sstevel@tonic-gate
34191f6eb021SLiane Praza version = xmlGetProp(svc, (xmlChar *)version_attr);
34207c478bd9Sstevel@tonic-gate s->sc_u.sc_service.sc_service_version = atol((const char *)version);
34217c478bd9Sstevel@tonic-gate xmlFree(version);
34227c478bd9Sstevel@tonic-gate
34237c478bd9Sstevel@tonic-gate type = xmlGetProp(svc, (xmlChar *)type_attr);
34247c478bd9Sstevel@tonic-gate s->sc_u.sc_service.sc_service_type = lxml_xlate_service_type(type);
34257c478bd9Sstevel@tonic-gate xmlFree(type);
34267c478bd9Sstevel@tonic-gate
34277c478bd9Sstevel@tonic-gate /*
3428f329b923SSean Wilcox * Set the global missing type to false before processing the service
3429f329b923SSean Wilcox */
3430f329b923SSean Wilcox est->sc_miss_type = B_FALSE;
3431f329b923SSean Wilcox s->sc_op = op;
3432f329b923SSean Wilcox
3433f329b923SSean Wilcox /*
343423294c7dSSean Wilcox * Now that the service is created create the manifest
343523294c7dSSean Wilcox * property group and add the property value of the service.
343623294c7dSSean Wilcox */
34379444c26fSTom Whitten if (lxml_check_upgrade(s->sc_name) == SCF_SUCCESS &&
34389444c26fSTom Whitten svc->doc->name != NULL &&
343923294c7dSSean Wilcox bundle->sc_bundle_type == SVCCFG_MANIFEST) {
344085bcc4e5SSean Wilcox char *buf, *base, *fname, *bname;
344185bcc4e5SSean Wilcox size_t base_sz = 0;
344285bcc4e5SSean Wilcox
344385bcc4e5SSean Wilcox /*
344485bcc4e5SSean Wilcox * Must remove the PKG_INSTALL_ROOT, point to the correct
344585bcc4e5SSean Wilcox * directory after install
344685bcc4e5SSean Wilcox */
344785bcc4e5SSean Wilcox bname = uu_zalloc(PATH_MAX + 1);
344885bcc4e5SSean Wilcox if (realpath(svc->doc->name, bname) == NULL) {
344985bcc4e5SSean Wilcox uu_die(gettext("Unable to create the real path of the "
345085bcc4e5SSean Wilcox "manifest file \"%s\" : %d\n"), svc->doc->name,
345185bcc4e5SSean Wilcox errno);
345285bcc4e5SSean Wilcox }
345385bcc4e5SSean Wilcox
345485bcc4e5SSean Wilcox base = getenv("PKG_INSTALL_ROOT");
345585bcc4e5SSean Wilcox if (base != NULL && strncmp(bname, base, strlen(base)) == 0) {
345685bcc4e5SSean Wilcox base_sz = strlen(base);
345785bcc4e5SSean Wilcox }
345885bcc4e5SSean Wilcox fname = safe_strdup(bname + base_sz);
345985bcc4e5SSean Wilcox
346085bcc4e5SSean Wilcox uu_free(bname);
346185bcc4e5SSean Wilcox buf = mhash_filename_to_propname(svc->doc->name, B_FALSE);
346223294c7dSSean Wilcox
346323294c7dSSean Wilcox pg = internal_pgroup_create_strict(s, SCF_PG_MANIFESTFILES,
346423294c7dSSean Wilcox SCF_GROUP_FRAMEWORK);
346523294c7dSSean Wilcox
346623294c7dSSean Wilcox if (pg == NULL) {
346723294c7dSSean Wilcox uu_die(gettext("Property group for prop_pattern, "
346823294c7dSSean Wilcox "\"%s\", already exists in %s\n"),
346923294c7dSSean Wilcox SCF_PG_MANIFESTFILES, s->sc_name);
347023294c7dSSean Wilcox }
347123294c7dSSean Wilcox
347223294c7dSSean Wilcox p = internal_property_create(buf, SCF_TYPE_ASTRING, 1, fname);
347323294c7dSSean Wilcox
347423294c7dSSean Wilcox (void) internal_attach_property(pg, p);
347523294c7dSSean Wilcox }
347623294c7dSSean Wilcox
347723294c7dSSean Wilcox /*
34787c478bd9Sstevel@tonic-gate * Walk its child elements, as appropriate.
34797c478bd9Sstevel@tonic-gate */
34807c478bd9Sstevel@tonic-gate for (cursor = svc->xmlChildrenNode; cursor != NULL;
34817c478bd9Sstevel@tonic-gate cursor = cursor->next) {
34827c478bd9Sstevel@tonic-gate if (lxml_ignorable_block(cursor))
34837c478bd9Sstevel@tonic-gate continue;
34847c478bd9Sstevel@tonic-gate
34857c478bd9Sstevel@tonic-gate e = lxml_xlate_element(cursor->name);
34867c478bd9Sstevel@tonic-gate
34877c478bd9Sstevel@tonic-gate switch (e) {
34887c478bd9Sstevel@tonic-gate case SC_INSTANCE:
3489687293e1SAntonello Cruz if (lxml_get_instance(s, cursor,
3490687293e1SAntonello Cruz bundle->sc_bundle_type, op) != 0)
34911f6eb021SLiane Praza return (-1);
34927c478bd9Sstevel@tonic-gate break;
34937c478bd9Sstevel@tonic-gate case SC_TEMPLATE:
3494f329b923SSean Wilcox if (op == SVCCFG_OP_APPLY) {
3495f329b923SSean Wilcox semerr(gettext("Template data for \"%s\" may "
3496f329b923SSean Wilcox "not be modified in a profile.\n"),
3497f329b923SSean Wilcox s->sc_name);
3498f329b923SSean Wilcox
3499f329b923SSean Wilcox return (-1);
3500f329b923SSean Wilcox }
3501f329b923SSean Wilcox
35021f6eb021SLiane Praza if (lxml_get_template(s, cursor) != 0)
35031f6eb021SLiane Praza return (-1);
35047c478bd9Sstevel@tonic-gate break;
3505f6e214c7SGavin Maltby case SC_NOTIFICATION_PARAMETERS:
3506f6e214c7SGavin Maltby if (lxml_get_notification_parameters(s, cursor) != 0)
3507f6e214c7SGavin Maltby return (-1);
3508f6e214c7SGavin Maltby break;
35097c478bd9Sstevel@tonic-gate case SC_STABILITY:
35107c478bd9Sstevel@tonic-gate (void) lxml_get_entity_stability(s, cursor);
35117c478bd9Sstevel@tonic-gate break;
35127c478bd9Sstevel@tonic-gate case SC_DEPENDENCY:
35137c478bd9Sstevel@tonic-gate (void) lxml_get_dependency(s, cursor);
35147c478bd9Sstevel@tonic-gate break;
35157c478bd9Sstevel@tonic-gate case SC_DEPENDENT:
35167c478bd9Sstevel@tonic-gate (void) lxml_get_dependent(s, cursor);
35177c478bd9Sstevel@tonic-gate break;
35187c478bd9Sstevel@tonic-gate case SC_RESTARTER:
35197c478bd9Sstevel@tonic-gate (void) lxml_get_restarter(s, cursor);
35207c478bd9Sstevel@tonic-gate break;
35217c478bd9Sstevel@tonic-gate case SC_EXEC_METHOD:
35227c478bd9Sstevel@tonic-gate (void) lxml_get_exec_method(s, cursor);
35237c478bd9Sstevel@tonic-gate break;
35247c478bd9Sstevel@tonic-gate case SC_METHOD_CONTEXT:
35257c478bd9Sstevel@tonic-gate (void) lxml_get_entity_method_context(s, cursor);
35267c478bd9Sstevel@tonic-gate break;
35277c478bd9Sstevel@tonic-gate case SC_PROPERTY_GROUP:
35287c478bd9Sstevel@tonic-gate (void) lxml_get_pgroup(s, cursor);
35297c478bd9Sstevel@tonic-gate break;
35307c478bd9Sstevel@tonic-gate case SC_INSTANCE_CREATE_DEFAULT:
35317c478bd9Sstevel@tonic-gate (void) lxml_get_default_instance(s, cursor);
35327c478bd9Sstevel@tonic-gate break;
35337c478bd9Sstevel@tonic-gate case SC_INSTANCE_SINGLE:
35347c478bd9Sstevel@tonic-gate (void) lxml_get_single_instance(s, cursor);
35357c478bd9Sstevel@tonic-gate break;
35367c478bd9Sstevel@tonic-gate default:
35377c478bd9Sstevel@tonic-gate uu_die(gettext(
35387c478bd9Sstevel@tonic-gate "illegal element \"%s\" on service \"%s\"\n"),
35397c478bd9Sstevel@tonic-gate cursor->name, s->sc_name);
35407c478bd9Sstevel@tonic-gate break;
35417c478bd9Sstevel@tonic-gate }
35427c478bd9Sstevel@tonic-gate }
35437c478bd9Sstevel@tonic-gate
3544f329b923SSean Wilcox /*
3545f329b923SSean Wilcox * Now that the service has been processed set the missing type
3546f329b923SSean Wilcox * for the service. So that only the services with missing
3547f329b923SSean Wilcox * types are processed.
3548f329b923SSean Wilcox */
3549f329b923SSean Wilcox s->sc_miss_type = est->sc_miss_type;
3550f329b923SSean Wilcox if (est->sc_miss_type)
3551f329b923SSean Wilcox est->sc_miss_type = B_FALSE;
3552f329b923SSean Wilcox
35537c478bd9Sstevel@tonic-gate return (internal_attach_service(bundle, s));
35547c478bd9Sstevel@tonic-gate }
35557c478bd9Sstevel@tonic-gate
35567c478bd9Sstevel@tonic-gate #ifdef DEBUG
35577c478bd9Sstevel@tonic-gate void
lxml_dump(int g,xmlNodePtr p)35587c478bd9Sstevel@tonic-gate lxml_dump(int g, xmlNodePtr p)
35597c478bd9Sstevel@tonic-gate {
35607c478bd9Sstevel@tonic-gate if (p && p->name) {
3561f329b923SSean Wilcox (void) printf("%d %s\n", g, p->name);
35627c478bd9Sstevel@tonic-gate
35637c478bd9Sstevel@tonic-gate for (p = p->xmlChildrenNode; p != NULL; p = p->next)
35647c478bd9Sstevel@tonic-gate lxml_dump(g + 1, p);
35657c478bd9Sstevel@tonic-gate }
35667c478bd9Sstevel@tonic-gate }
35677c478bd9Sstevel@tonic-gate #endif /* DEBUG */
35687c478bd9Sstevel@tonic-gate
35697c478bd9Sstevel@tonic-gate static int
lxml_is_known_dtd(const xmlChar * dtdname)35707c478bd9Sstevel@tonic-gate lxml_is_known_dtd(const xmlChar *dtdname)
35717c478bd9Sstevel@tonic-gate {
35727c478bd9Sstevel@tonic-gate if (dtdname == NULL ||
35737c478bd9Sstevel@tonic-gate strcmp(MANIFEST_DTD_PATH, (const char *)dtdname) != 0)
35747c478bd9Sstevel@tonic-gate return (0);
35757c478bd9Sstevel@tonic-gate
35767c478bd9Sstevel@tonic-gate return (1);
35777c478bd9Sstevel@tonic-gate }
35787c478bd9Sstevel@tonic-gate
35797c478bd9Sstevel@tonic-gate static int
lxml_get_bundle(bundle_t * bundle,bundle_type_t bundle_type,xmlNodePtr subbundle,svccfg_op_t op)35807c478bd9Sstevel@tonic-gate lxml_get_bundle(bundle_t *bundle, bundle_type_t bundle_type,
35813eae19d9Swesolows xmlNodePtr subbundle, svccfg_op_t op)
35827c478bd9Sstevel@tonic-gate {
35837c478bd9Sstevel@tonic-gate xmlNodePtr cursor;
35847c478bd9Sstevel@tonic-gate xmlChar *type;
35857c478bd9Sstevel@tonic-gate int e;
35867c478bd9Sstevel@tonic-gate
35877c478bd9Sstevel@tonic-gate /*
35887c478bd9Sstevel@tonic-gate * 1. Get bundle attributes.
35897c478bd9Sstevel@tonic-gate */
35901f6eb021SLiane Praza type = xmlGetProp(subbundle, (xmlChar *)type_attr);
35917c478bd9Sstevel@tonic-gate bundle->sc_bundle_type = lxml_xlate_bundle_type(type);
35927c478bd9Sstevel@tonic-gate if (bundle->sc_bundle_type != bundle_type &&
35937c478bd9Sstevel@tonic-gate bundle_type != SVCCFG_UNKNOWN_BUNDLE) {
35947c478bd9Sstevel@tonic-gate semerr(gettext("included bundle of different type.\n"));
35957c478bd9Sstevel@tonic-gate return (-1);
35967c478bd9Sstevel@tonic-gate }
35977c478bd9Sstevel@tonic-gate
35987c478bd9Sstevel@tonic-gate xmlFree(type);
35997c478bd9Sstevel@tonic-gate
36003eae19d9Swesolows switch (op) {
36013eae19d9Swesolows case SVCCFG_OP_IMPORT:
36027c478bd9Sstevel@tonic-gate if (bundle->sc_bundle_type != SVCCFG_MANIFEST) {
36037c478bd9Sstevel@tonic-gate semerr(gettext("document is not a manifest.\n"));
36047c478bd9Sstevel@tonic-gate return (-1);
36057c478bd9Sstevel@tonic-gate }
36063eae19d9Swesolows break;
36073eae19d9Swesolows case SVCCFG_OP_APPLY:
36087c478bd9Sstevel@tonic-gate if (bundle->sc_bundle_type != SVCCFG_PROFILE) {
36097c478bd9Sstevel@tonic-gate semerr(gettext("document is not a profile.\n"));
36107c478bd9Sstevel@tonic-gate return (-1);
36117c478bd9Sstevel@tonic-gate }
36123eae19d9Swesolows break;
36133eae19d9Swesolows case SVCCFG_OP_RESTORE:
36143eae19d9Swesolows if (bundle->sc_bundle_type != SVCCFG_ARCHIVE) {
36153eae19d9Swesolows semerr(gettext("document is not an archive.\n"));
36163eae19d9Swesolows return (-1);
36173eae19d9Swesolows }
36183eae19d9Swesolows break;
36197c478bd9Sstevel@tonic-gate }
36207c478bd9Sstevel@tonic-gate
36211f6eb021SLiane Praza if (((bundle->sc_bundle_name = xmlGetProp(subbundle,
36221f6eb021SLiane Praza (xmlChar *)name_attr)) == NULL) || (*bundle->sc_bundle_name == 0)) {
36237c478bd9Sstevel@tonic-gate semerr(gettext("service bundle lacks name attribute\n"));
36247c478bd9Sstevel@tonic-gate return (-1);
36257c478bd9Sstevel@tonic-gate }
36267c478bd9Sstevel@tonic-gate
36277c478bd9Sstevel@tonic-gate /*
36287c478bd9Sstevel@tonic-gate * 2. Get services, descend into each one and build state.
36297c478bd9Sstevel@tonic-gate */
36307c478bd9Sstevel@tonic-gate for (cursor = subbundle->xmlChildrenNode; cursor != NULL;
36317c478bd9Sstevel@tonic-gate cursor = cursor->next) {
36327c478bd9Sstevel@tonic-gate if (lxml_ignorable_block(cursor))
36337c478bd9Sstevel@tonic-gate continue;
36347c478bd9Sstevel@tonic-gate
36357c478bd9Sstevel@tonic-gate e = lxml_xlate_element(cursor->name);
36367c478bd9Sstevel@tonic-gate
36377c478bd9Sstevel@tonic-gate switch (e) {
36387c478bd9Sstevel@tonic-gate case SC_XI_INCLUDE:
36397c478bd9Sstevel@tonic-gate continue;
36407c478bd9Sstevel@tonic-gate
36417c478bd9Sstevel@tonic-gate case SC_SERVICE_BUNDLE:
36423eae19d9Swesolows if (lxml_get_bundle(bundle, bundle_type, cursor, op))
36437c478bd9Sstevel@tonic-gate return (-1);
36447c478bd9Sstevel@tonic-gate break;
36457c478bd9Sstevel@tonic-gate case SC_SERVICE:
36461f6eb021SLiane Praza if (lxml_get_service(bundle, cursor, op) != 0)
36471f6eb021SLiane Praza return (-1);
36487c478bd9Sstevel@tonic-gate break;
36497c478bd9Sstevel@tonic-gate }
36507c478bd9Sstevel@tonic-gate }
36517c478bd9Sstevel@tonic-gate
36527c478bd9Sstevel@tonic-gate return (0);
36537c478bd9Sstevel@tonic-gate }
36547c478bd9Sstevel@tonic-gate
36557c478bd9Sstevel@tonic-gate /*
36567c478bd9Sstevel@tonic-gate * Load an XML tree from filename and translate it into an internal service
36573eae19d9Swesolows * tree bundle. Require that the bundle be of appropriate type for the
36583eae19d9Swesolows * operation: archive for RESTORE, manifest for IMPORT, profile for APPLY.
36597c478bd9Sstevel@tonic-gate */
36607c478bd9Sstevel@tonic-gate int
lxml_get_bundle_file(bundle_t * bundle,const char * filename,svccfg_op_t op)36613eae19d9Swesolows lxml_get_bundle_file(bundle_t *bundle, const char *filename, svccfg_op_t op)
36627c478bd9Sstevel@tonic-gate {
36637c478bd9Sstevel@tonic-gate xmlDocPtr document;
36647c478bd9Sstevel@tonic-gate xmlNodePtr cursor;
36657c478bd9Sstevel@tonic-gate xmlDtdPtr dtd = NULL;
36667c478bd9Sstevel@tonic-gate xmlValidCtxtPtr vcp;
36677c478bd9Sstevel@tonic-gate boolean_t do_validate;
36687c478bd9Sstevel@tonic-gate char *dtdpath = NULL;
36697c478bd9Sstevel@tonic-gate int r;
36707c478bd9Sstevel@tonic-gate
36717c478bd9Sstevel@tonic-gate /*
367276cf44abSjeanm * Verify we can read the file before we try to parse it.
367376cf44abSjeanm */
367476cf44abSjeanm if (access(filename, R_OK | F_OK) == -1) {
367576cf44abSjeanm semerr(gettext("unable to open file: %s\n"), strerror(errno));
367676cf44abSjeanm return (-1);
367776cf44abSjeanm }
367876cf44abSjeanm
367976cf44abSjeanm /*
36807c478bd9Sstevel@tonic-gate * Until libxml2 addresses DTD-based validation with XInclude, we don't
36817c478bd9Sstevel@tonic-gate * validate service profiles (i.e. the apply path).
36827c478bd9Sstevel@tonic-gate */
36833eae19d9Swesolows do_validate = (op != SVCCFG_OP_APPLY) &&
36843eae19d9Swesolows (getenv("SVCCFG_NOVALIDATE") == NULL);
36857c478bd9Sstevel@tonic-gate if (do_validate)
36867c478bd9Sstevel@tonic-gate dtdpath = getenv("SVCCFG_DTD");
36877c478bd9Sstevel@tonic-gate
36887c478bd9Sstevel@tonic-gate if (dtdpath != NULL)
36897c478bd9Sstevel@tonic-gate xmlLoadExtDtdDefaultValue = 0;
36907c478bd9Sstevel@tonic-gate
369176cf44abSjeanm if ((document = xmlReadFile(filename, NULL, 0)) == NULL) {
36927c478bd9Sstevel@tonic-gate semerr(gettext("couldn't parse document\n"));
36937c478bd9Sstevel@tonic-gate return (-1);
36947c478bd9Sstevel@tonic-gate }
36957c478bd9Sstevel@tonic-gate
3696*67b0e063SAlbert Lee document->name = safe_strdup(filename);
369723294c7dSSean Wilcox
36987c478bd9Sstevel@tonic-gate /*
36997c478bd9Sstevel@tonic-gate * Verify that this is a document type we understand.
37007c478bd9Sstevel@tonic-gate */
37017c478bd9Sstevel@tonic-gate if ((dtd = xmlGetIntSubset(document)) == NULL) {
37027c478bd9Sstevel@tonic-gate semerr(gettext("document has no DTD\n"));
37037c478bd9Sstevel@tonic-gate return (-1);
3704f329b923SSean Wilcox } else if (dtdpath == NULL && !do_validate) {
3705f329b923SSean Wilcox /*
3706f329b923SSean Wilcox * If apply then setup so that some validation
3707f329b923SSean Wilcox * for specific elements can be done.
3708f329b923SSean Wilcox */
3709f329b923SSean Wilcox dtdpath = (char *)document->intSubset->SystemID;
37107c478bd9Sstevel@tonic-gate }
37117c478bd9Sstevel@tonic-gate
37127c478bd9Sstevel@tonic-gate if (!lxml_is_known_dtd(dtd->SystemID)) {
37137c478bd9Sstevel@tonic-gate semerr(gettext("document DTD unknown; not service bundle?\n"));
37147c478bd9Sstevel@tonic-gate return (-1);
37157c478bd9Sstevel@tonic-gate }
37167c478bd9Sstevel@tonic-gate
37177c478bd9Sstevel@tonic-gate if ((cursor = xmlDocGetRootElement(document)) == NULL) {
37187c478bd9Sstevel@tonic-gate semerr(gettext("document is empty\n"));
37197c478bd9Sstevel@tonic-gate xmlFreeDoc(document);
37207c478bd9Sstevel@tonic-gate return (-1);
37217c478bd9Sstevel@tonic-gate }
37227c478bd9Sstevel@tonic-gate
37237c478bd9Sstevel@tonic-gate if (xmlStrcmp(cursor->name, (const xmlChar *)"service_bundle") != 0) {
37247c478bd9Sstevel@tonic-gate semerr(gettext("document is not a service bundle\n"));
37257c478bd9Sstevel@tonic-gate xmlFreeDoc(document);
37267c478bd9Sstevel@tonic-gate return (-1);
37277c478bd9Sstevel@tonic-gate }
37287c478bd9Sstevel@tonic-gate
37297c478bd9Sstevel@tonic-gate
37307c478bd9Sstevel@tonic-gate if (dtdpath != NULL) {
37317c478bd9Sstevel@tonic-gate dtd = xmlParseDTD(NULL, (xmlChar *)dtdpath);
37327c478bd9Sstevel@tonic-gate if (dtd == NULL) {
37337c478bd9Sstevel@tonic-gate semerr(gettext("Could not parse DTD \"%s\".\n"),
37347c478bd9Sstevel@tonic-gate dtdpath);
37357c478bd9Sstevel@tonic-gate return (-1);
37367c478bd9Sstevel@tonic-gate }
37377c478bd9Sstevel@tonic-gate
37387c478bd9Sstevel@tonic-gate if (document->extSubset != NULL)
37397c478bd9Sstevel@tonic-gate xmlFreeDtd(document->extSubset);
37407c478bd9Sstevel@tonic-gate
37417c478bd9Sstevel@tonic-gate document->extSubset = dtd;
37427c478bd9Sstevel@tonic-gate }
37437c478bd9Sstevel@tonic-gate
374476cf44abSjeanm if (xmlXIncludeProcessFlags(document, XML_PARSE_XINCLUDE) == -1) {
37457c478bd9Sstevel@tonic-gate semerr(gettext("couldn't handle XInclude statements "
37467c478bd9Sstevel@tonic-gate "in document\n"));
37477c478bd9Sstevel@tonic-gate return (-1);
37487c478bd9Sstevel@tonic-gate }
37497c478bd9Sstevel@tonic-gate
37507c478bd9Sstevel@tonic-gate if (do_validate) {
37517c478bd9Sstevel@tonic-gate vcp = xmlNewValidCtxt();
37527c478bd9Sstevel@tonic-gate if (vcp == NULL)
37537c478bd9Sstevel@tonic-gate uu_die(gettext("could not allocate memory"));
37547c478bd9Sstevel@tonic-gate vcp->warning = xmlParserValidityWarning;
37557c478bd9Sstevel@tonic-gate vcp->error = xmlParserValidityError;
37567c478bd9Sstevel@tonic-gate
37577c478bd9Sstevel@tonic-gate r = xmlValidateDocument(vcp, document);
37587c478bd9Sstevel@tonic-gate
37597c478bd9Sstevel@tonic-gate xmlFreeValidCtxt(vcp);
37607c478bd9Sstevel@tonic-gate
37617c478bd9Sstevel@tonic-gate if (r == 0) {
37627c478bd9Sstevel@tonic-gate semerr(gettext("Document is not valid.\n"));
37637c478bd9Sstevel@tonic-gate xmlFreeDoc(document);
37647c478bd9Sstevel@tonic-gate return (-1);
37657c478bd9Sstevel@tonic-gate }
37667c478bd9Sstevel@tonic-gate }
37677c478bd9Sstevel@tonic-gate
37687c478bd9Sstevel@tonic-gate #ifdef DEBUG
37697c478bd9Sstevel@tonic-gate lxml_dump(0, cursor);
37707c478bd9Sstevel@tonic-gate #endif /* DEBUG */
37717c478bd9Sstevel@tonic-gate
37723eae19d9Swesolows r = lxml_get_bundle(bundle, SVCCFG_UNKNOWN_BUNDLE, cursor, op);
37737c478bd9Sstevel@tonic-gate
37747c478bd9Sstevel@tonic-gate xmlFreeDoc(document);
37757c478bd9Sstevel@tonic-gate
37767c478bd9Sstevel@tonic-gate return (r);
37777c478bd9Sstevel@tonic-gate }
37787c478bd9Sstevel@tonic-gate
37797c478bd9Sstevel@tonic-gate int
lxml_inventory(const char * filename)37807c478bd9Sstevel@tonic-gate lxml_inventory(const char *filename)
37817c478bd9Sstevel@tonic-gate {
37827c478bd9Sstevel@tonic-gate bundle_t *b;
37837c478bd9Sstevel@tonic-gate uu_list_walk_t *svcs, *insts;
37847c478bd9Sstevel@tonic-gate entity_t *svc, *inst;
37857c478bd9Sstevel@tonic-gate
37867c478bd9Sstevel@tonic-gate b = internal_bundle_new();
37877c478bd9Sstevel@tonic-gate
37883eae19d9Swesolows if (lxml_get_bundle_file(b, filename, SVCCFG_OP_IMPORT) != 0) {
37897c478bd9Sstevel@tonic-gate internal_bundle_free(b);
37907c478bd9Sstevel@tonic-gate return (-1);
37917c478bd9Sstevel@tonic-gate }
37927c478bd9Sstevel@tonic-gate
37937c478bd9Sstevel@tonic-gate svcs = uu_list_walk_start(b->sc_bundle_services, 0);
37947c478bd9Sstevel@tonic-gate if (svcs == NULL)
37957c478bd9Sstevel@tonic-gate uu_die(gettext("Couldn't walk services"));
37967c478bd9Sstevel@tonic-gate
37977c478bd9Sstevel@tonic-gate while ((svc = uu_list_walk_next(svcs)) != NULL) {
37987c478bd9Sstevel@tonic-gate uu_list_t *inst_list;
37997c478bd9Sstevel@tonic-gate
38007c478bd9Sstevel@tonic-gate inst_list = svc->sc_u.sc_service.sc_service_instances;
38017c478bd9Sstevel@tonic-gate insts = uu_list_walk_start(inst_list, 0);
38027c478bd9Sstevel@tonic-gate if (insts == NULL)
38037c478bd9Sstevel@tonic-gate uu_die(gettext("Couldn't walk instances"));
38047c478bd9Sstevel@tonic-gate
38057c478bd9Sstevel@tonic-gate while ((inst = uu_list_walk_next(insts)) != NULL)
38067c478bd9Sstevel@tonic-gate (void) printf("svc:/%s:%s\n", svc->sc_name,
38077c478bd9Sstevel@tonic-gate inst->sc_name);
38087c478bd9Sstevel@tonic-gate
38097c478bd9Sstevel@tonic-gate uu_list_walk_end(insts);
38107c478bd9Sstevel@tonic-gate }
38117c478bd9Sstevel@tonic-gate
38127c478bd9Sstevel@tonic-gate uu_list_walk_end(svcs);
38137c478bd9Sstevel@tonic-gate
38147c478bd9Sstevel@tonic-gate svcs = uu_list_walk_start(b->sc_bundle_services, 0);
38157c478bd9Sstevel@tonic-gate while ((svc = uu_list_walk_next(svcs)) != NULL) {
38167c478bd9Sstevel@tonic-gate (void) fputs("svc:/", stdout);
38177c478bd9Sstevel@tonic-gate (void) puts(svc->sc_name);
38187c478bd9Sstevel@tonic-gate }
38197c478bd9Sstevel@tonic-gate uu_list_walk_end(svcs);
38207c478bd9Sstevel@tonic-gate
38217c478bd9Sstevel@tonic-gate internal_bundle_free(b);
38227c478bd9Sstevel@tonic-gate
38237c478bd9Sstevel@tonic-gate return (0);
38247c478bd9Sstevel@tonic-gate }
3825