10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 54740Sjeanm * Common Development and Distribution License (the "License"). 64740Sjeanm * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 22*7887SLiane.Praza@Sun.COM * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 26*7887SLiane.Praza@Sun.COM /* 27*7887SLiane.Praza@Sun.COM * XML document manipulation routines 28*7887SLiane.Praza@Sun.COM * 29*7887SLiane.Praza@Sun.COM * These routines provide translation to and from the internal representation to 30*7887SLiane.Praza@Sun.COM * XML. Directionally-oriented verbs are with respect to the external source, 31*7887SLiane.Praza@Sun.COM * so lxml_get_service() fetches a service from the XML file into the 32*7887SLiane.Praza@Sun.COM * internal representation. 33*7887SLiane.Praza@Sun.COM */ 340Sstevel@tonic-gate 350Sstevel@tonic-gate #include <libxml/parser.h> 360Sstevel@tonic-gate #include <libxml/xinclude.h> 370Sstevel@tonic-gate 380Sstevel@tonic-gate #include <assert.h> 390Sstevel@tonic-gate #include <ctype.h> 400Sstevel@tonic-gate #include <errno.h> 410Sstevel@tonic-gate #include <libintl.h> 42*7887SLiane.Praza@Sun.COM #include <libscf.h> 43*7887SLiane.Praza@Sun.COM #include <libscf_priv.h> 440Sstevel@tonic-gate #include <libuutil.h> 45*7887SLiane.Praza@Sun.COM #include <sasl/saslutil.h> 460Sstevel@tonic-gate #include <stdlib.h> 470Sstevel@tonic-gate #include <string.h> 480Sstevel@tonic-gate 494740Sjeanm #include <sys/types.h> 504740Sjeanm #include <sys/stat.h> 514740Sjeanm #include <unistd.h> 524740Sjeanm 530Sstevel@tonic-gate #include "svccfg.h" 540Sstevel@tonic-gate 550Sstevel@tonic-gate /* 56*7887SLiane.Praza@Sun.COM * snprintf(3C) format strings for constructing property names that include 57*7887SLiane.Praza@Sun.COM * the locale designation. Use %s to indicate where the locale should go. 580Sstevel@tonic-gate * 59*7887SLiane.Praza@Sun.COM * The VALUE_* symbols are an exception. The firs %s will be replaced with 60*7887SLiane.Praza@Sun.COM * "value_". The second %s will be replaced by the name of the value and 61*7887SLiane.Praza@Sun.COM * %%s will be replaced by the locale designation. These formats are 62*7887SLiane.Praza@Sun.COM * processed twice by snprintf(3C). The first time captures the value name 63*7887SLiane.Praza@Sun.COM * and the second time captures the locale. 640Sstevel@tonic-gate */ 65*7887SLiane.Praza@Sun.COM #define LOCALE_ONLY_FMT ("%s") 66*7887SLiane.Praza@Sun.COM #define COMMON_NAME_FMT ("common_name_%s") 67*7887SLiane.Praza@Sun.COM #define DESCRIPTION_FMT ("description_%s") 68*7887SLiane.Praza@Sun.COM #define UNITS_FMT ("units_%s") 69*7887SLiane.Praza@Sun.COM #define VALUE_COMMON_NAME_FMT ("%s%s_common_name_%%s") 70*7887SLiane.Praza@Sun.COM #define VALUE_DESCRIPTION_FMT ("%s%s_description_%%s") 71*7887SLiane.Praza@Sun.COM 72*7887SLiane.Praza@Sun.COM /* Attribute names */ 730Sstevel@tonic-gate const char * const delete_attr = "delete"; 740Sstevel@tonic-gate const char * const enabled_attr = "enabled"; 75*7887SLiane.Praza@Sun.COM const char * const lang_attr = "lang"; 76*7887SLiane.Praza@Sun.COM const char * const manpath_attr = "manpath"; 77*7887SLiane.Praza@Sun.COM const char * const max_attr = "max"; 78*7887SLiane.Praza@Sun.COM const char * const min_attr = "min"; 790Sstevel@tonic-gate const char * const name_attr = "name"; 800Sstevel@tonic-gate const char * const override_attr = "override"; 81*7887SLiane.Praza@Sun.COM const char * const required_attr = "required"; 82*7887SLiane.Praza@Sun.COM const char * const section_attr = "section"; 83*7887SLiane.Praza@Sun.COM const char * const set_attr = "set"; 84*7887SLiane.Praza@Sun.COM const char * const target_attr = "target"; 85*7887SLiane.Praza@Sun.COM const char * const timeout_seconds_attr = "timeout_seconds"; 86*7887SLiane.Praza@Sun.COM const char * const title_attr = "title"; 870Sstevel@tonic-gate const char * const type_attr = "type"; 88*7887SLiane.Praza@Sun.COM const char * const uri_attr = "uri"; 890Sstevel@tonic-gate const char * const value_attr = "value"; 90*7887SLiane.Praza@Sun.COM const char * const version_attr = "version"; 91*7887SLiane.Praza@Sun.COM const char * const xml_lang_attr = "xml:lang"; 92*7887SLiane.Praza@Sun.COM 93*7887SLiane.Praza@Sun.COM /* Attribute values */ 94*7887SLiane.Praza@Sun.COM const char * const all_value = "all"; 95*7887SLiane.Praza@Sun.COM 960Sstevel@tonic-gate const char * const true = "true"; 970Sstevel@tonic-gate const char * const false = "false"; 980Sstevel@tonic-gate 990Sstevel@tonic-gate /* 1000Sstevel@tonic-gate * The following list must be kept in the same order as that of 1010Sstevel@tonic-gate * element_t array 1020Sstevel@tonic-gate */ 1030Sstevel@tonic-gate static const char *lxml_elements[] = { 1040Sstevel@tonic-gate "astring_list", /* SC_ASTRING */ 1050Sstevel@tonic-gate "boolean_list", /* SC_BOOLEAN */ 106*7887SLiane.Praza@Sun.COM "cardinality", /* SC_CARDINALITY */ 107*7887SLiane.Praza@Sun.COM "choices", /* SC_CHOICES */ 1080Sstevel@tonic-gate "common_name", /* SC_COMMON_NAME */ 109*7887SLiane.Praza@Sun.COM "constraints", /* SC_CONSTRAINTS */ 1100Sstevel@tonic-gate "count_list", /* SC_COUNT */ 1110Sstevel@tonic-gate "create_default_instance", /* SC_INSTANCE_CREATE_DEFAULT */ 1120Sstevel@tonic-gate "dependency", /* SC_DEPENDENCY */ 1130Sstevel@tonic-gate "dependent", /* SC_DEPENDENT */ 1140Sstevel@tonic-gate "description", /* SC_DESCRIPTION */ 1150Sstevel@tonic-gate "doc_link", /* SC_DOC_LINK */ 1160Sstevel@tonic-gate "documentation", /* SC_DOCUMENTATION */ 1170Sstevel@tonic-gate "enabled", /* SC_ENABLED */ 1180Sstevel@tonic-gate "exec_method", /* SC_EXEC_METHOD */ 1190Sstevel@tonic-gate "fmri_list", /* SC_FMRI */ 1200Sstevel@tonic-gate "host_list", /* SC_HOST */ 1210Sstevel@tonic-gate "hostname_list", /* SC_HOSTNAME */ 122*7887SLiane.Praza@Sun.COM "include_values", /* SC_INCLUDE_VALUES */ 1230Sstevel@tonic-gate "instance", /* SC_INSTANCE */ 1240Sstevel@tonic-gate "integer_list", /* SC_INTEGER */ 125*7887SLiane.Praza@Sun.COM "internal_separators", /* SC_INTERNAL_SEPARATORS */ 1260Sstevel@tonic-gate "loctext", /* SC_LOCTEXT */ 1270Sstevel@tonic-gate "manpage", /* SC_MANPAGE */ 1280Sstevel@tonic-gate "method_context", /* SC_METHOD_CONTEXT */ 1290Sstevel@tonic-gate "method_credential", /* SC_METHOD_CREDENTIAL */ 1300Sstevel@tonic-gate "method_profile", /* SC_METHOD_PROFILE */ 1310Sstevel@tonic-gate "method_environment", /* SC_METHOD_ENVIRONMENT */ 1320Sstevel@tonic-gate "envvar", /* SC_METHOD_ENVVAR */ 1330Sstevel@tonic-gate "net_address_v4_list", /* SC_NET_ADDR_V4 */ 1340Sstevel@tonic-gate "net_address_v6_list", /* SC_NET_ADDR_V6 */ 1350Sstevel@tonic-gate "opaque_list", /* SC_OPAQUE */ 136*7887SLiane.Praza@Sun.COM "pg_pattern", /* SC_PG_PATTERN */ 137*7887SLiane.Praza@Sun.COM "prop_pattern", /* SC_PROP_PATTERN */ 1380Sstevel@tonic-gate "property", /* SC_PROPERTY */ 1390Sstevel@tonic-gate "property_group", /* SC_PROPERTY_GROUP */ 1400Sstevel@tonic-gate "propval", /* SC_PROPVAL */ 141*7887SLiane.Praza@Sun.COM "range", /* SC_RANGE */ 1420Sstevel@tonic-gate "restarter", /* SC_RESTARTER */ 1430Sstevel@tonic-gate "service", /* SC_SERVICE */ 1440Sstevel@tonic-gate "service_bundle", /* SC_SERVICE_BUNDLE */ 1450Sstevel@tonic-gate "service_fmri", /* SC_SERVICE_FMRI */ 1460Sstevel@tonic-gate "single_instance", /* SC_INSTANCE_SINGLE */ 1470Sstevel@tonic-gate "stability", /* SC_STABILITY */ 1480Sstevel@tonic-gate "template", /* SC_TEMPLATE */ 1490Sstevel@tonic-gate "time_list", /* SC_TIME */ 150*7887SLiane.Praza@Sun.COM "units", /* SC_UNITS */ 1510Sstevel@tonic-gate "uri_list", /* SC_URI */ 1520Sstevel@tonic-gate "ustring_list", /* SC_USTRING */ 153*7887SLiane.Praza@Sun.COM "value", /* SC_VALUE */ 1540Sstevel@tonic-gate "value_node", /* SC_VALUE_NODE */ 155*7887SLiane.Praza@Sun.COM "values", /* SC_VALUES */ 156*7887SLiane.Praza@Sun.COM "visibility", /* SC_VISIBILITY */ 1570Sstevel@tonic-gate "xi:fallback", /* SC_XI_FALLBACK */ 1580Sstevel@tonic-gate "xi:include" /* SC_XI_INCLUDE */ 1590Sstevel@tonic-gate }; 1600Sstevel@tonic-gate 1610Sstevel@tonic-gate /* 1620Sstevel@tonic-gate * The following list must be kept in the same order as that of 1630Sstevel@tonic-gate * element_t array 1640Sstevel@tonic-gate */ 1650Sstevel@tonic-gate static const char *lxml_prop_types[] = { 1660Sstevel@tonic-gate "astring", /* SC_ASTRING */ 1670Sstevel@tonic-gate "boolean", /* SC_BOOLEAN */ 168*7887SLiane.Praza@Sun.COM "", /* SC_CARDINALITY */ 169*7887SLiane.Praza@Sun.COM "", /* SC_CHOICES */ 1700Sstevel@tonic-gate "", /* SC_COMMON_NAME */ 171*7887SLiane.Praza@Sun.COM "", /* SC_CONSTRAINTS */ 1720Sstevel@tonic-gate "count", /* SC_COUNT */ 1730Sstevel@tonic-gate "", /* SC_INSTANCE_CREATE_DEFAULT */ 1740Sstevel@tonic-gate "", /* SC_DEPENDENCY */ 1750Sstevel@tonic-gate "", /* SC_DEPENDENT */ 1760Sstevel@tonic-gate "", /* SC_DESCRIPTION */ 1770Sstevel@tonic-gate "", /* SC_DOC_LINK */ 1780Sstevel@tonic-gate "", /* SC_DOCUMENTATION */ 1790Sstevel@tonic-gate "", /* SC_ENABLED */ 1800Sstevel@tonic-gate "", /* SC_EXEC_METHOD */ 1810Sstevel@tonic-gate "fmri", /* SC_FMRI */ 1820Sstevel@tonic-gate "host", /* SC_HOST */ 1830Sstevel@tonic-gate "hostname", /* SC_HOSTNAME */ 184*7887SLiane.Praza@Sun.COM "", /* SC_INCLUDE_VALUES */ 1850Sstevel@tonic-gate "", /* SC_INSTANCE */ 1860Sstevel@tonic-gate "integer", /* SC_INTEGER */ 187*7887SLiane.Praza@Sun.COM "", /* SC_INTERNAL_SEPARATORS */ 1880Sstevel@tonic-gate "", /* SC_LOCTEXT */ 1890Sstevel@tonic-gate "", /* SC_MANPAGE */ 1900Sstevel@tonic-gate "", /* SC_METHOD_CONTEXT */ 1910Sstevel@tonic-gate "", /* SC_METHOD_CREDENTIAL */ 1920Sstevel@tonic-gate "", /* SC_METHOD_PROFILE */ 1930Sstevel@tonic-gate "", /* SC_METHOD_ENVIRONMENT */ 1940Sstevel@tonic-gate "", /* SC_METHOD_ENVVAR */ 1950Sstevel@tonic-gate "net_address_v4", /* SC_NET_ADDR_V4 */ 1960Sstevel@tonic-gate "net_address_v6", /* SC_NET_ADDR_V6 */ 1970Sstevel@tonic-gate "opaque", /* SC_OPAQUE */ 198*7887SLiane.Praza@Sun.COM "", /* SC_PG_PATTERN */ 199*7887SLiane.Praza@Sun.COM "", /* SC_PROP_PATTERN */ 2000Sstevel@tonic-gate "", /* SC_PROPERTY */ 2010Sstevel@tonic-gate "", /* SC_PROPERTY_GROUP */ 2020Sstevel@tonic-gate "", /* SC_PROPVAL */ 203*7887SLiane.Praza@Sun.COM "", /* SC_RANGE */ 2040Sstevel@tonic-gate "", /* SC_RESTARTER */ 2050Sstevel@tonic-gate "", /* SC_SERVICE */ 2060Sstevel@tonic-gate "", /* SC_SERVICE_BUNDLE */ 2070Sstevel@tonic-gate "", /* SC_SERVICE_FMRI */ 2080Sstevel@tonic-gate "", /* SC_INSTANCE_SINGLE */ 2090Sstevel@tonic-gate "", /* SC_STABILITY */ 2100Sstevel@tonic-gate "", /* SC_TEMPLATE */ 2110Sstevel@tonic-gate "time", /* SC_TIME */ 212*7887SLiane.Praza@Sun.COM "", /* SC_UNITS */ 2130Sstevel@tonic-gate "uri", /* SC_URI */ 2140Sstevel@tonic-gate "ustring", /* SC_USTRING */ 215*7887SLiane.Praza@Sun.COM "", /* SC_VALUE */ 216*7887SLiane.Praza@Sun.COM "", /* SC_VALUE_NODE */ 217*7887SLiane.Praza@Sun.COM "", /* SC_VALUES */ 218*7887SLiane.Praza@Sun.COM "", /* SC_VISIBILITY */ 219*7887SLiane.Praza@Sun.COM "", /* SC_XI_FALLBACK */ 2200Sstevel@tonic-gate "" /* SC_XI_INCLUDE */ 2210Sstevel@tonic-gate }; 2220Sstevel@tonic-gate 2230Sstevel@tonic-gate int 2240Sstevel@tonic-gate lxml_init() 2250Sstevel@tonic-gate { 2260Sstevel@tonic-gate if (getenv("SVCCFG_NOVALIDATE") == NULL) { 2270Sstevel@tonic-gate /* 2280Sstevel@tonic-gate * DTD validation, with line numbers. 2290Sstevel@tonic-gate */ 2300Sstevel@tonic-gate xmlLineNumbersDefault(1); 2310Sstevel@tonic-gate xmlLoadExtDtdDefaultValue |= XML_DETECT_IDS; 2320Sstevel@tonic-gate xmlLoadExtDtdDefaultValue |= XML_COMPLETE_ATTRS; 2330Sstevel@tonic-gate } 2340Sstevel@tonic-gate 2350Sstevel@tonic-gate return (0); 2360Sstevel@tonic-gate } 2370Sstevel@tonic-gate 2380Sstevel@tonic-gate static bundle_type_t 2390Sstevel@tonic-gate lxml_xlate_bundle_type(xmlChar *type) 2400Sstevel@tonic-gate { 2410Sstevel@tonic-gate if (xmlStrcmp(type, (const xmlChar *)"manifest") == 0) 2420Sstevel@tonic-gate return (SVCCFG_MANIFEST); 2430Sstevel@tonic-gate 2440Sstevel@tonic-gate if (xmlStrcmp(type, (const xmlChar *)"profile") == 0) 2450Sstevel@tonic-gate return (SVCCFG_PROFILE); 2460Sstevel@tonic-gate 2470Sstevel@tonic-gate if (xmlStrcmp(type, (const xmlChar *)"archive") == 0) 2480Sstevel@tonic-gate return (SVCCFG_ARCHIVE); 2490Sstevel@tonic-gate 2500Sstevel@tonic-gate return (SVCCFG_UNKNOWN_BUNDLE); 2510Sstevel@tonic-gate } 2520Sstevel@tonic-gate 2530Sstevel@tonic-gate static service_type_t 2540Sstevel@tonic-gate lxml_xlate_service_type(xmlChar *type) 2550Sstevel@tonic-gate { 2560Sstevel@tonic-gate if (xmlStrcmp(type, (const xmlChar *)"service") == 0) 2570Sstevel@tonic-gate return (SVCCFG_SERVICE); 2580Sstevel@tonic-gate 2590Sstevel@tonic-gate if (xmlStrcmp(type, (const xmlChar *)"restarter") == 0) 2600Sstevel@tonic-gate return (SVCCFG_RESTARTER); 2610Sstevel@tonic-gate 2620Sstevel@tonic-gate if (xmlStrcmp(type, (const xmlChar *)"milestone") == 0) 2630Sstevel@tonic-gate return (SVCCFG_MILESTONE); 2640Sstevel@tonic-gate 2650Sstevel@tonic-gate return (SVCCFG_UNKNOWN_SERVICE); 2660Sstevel@tonic-gate } 2670Sstevel@tonic-gate 2680Sstevel@tonic-gate static element_t 2690Sstevel@tonic-gate lxml_xlate_element(const xmlChar *tag) 2700Sstevel@tonic-gate { 2710Sstevel@tonic-gate int i; 2720Sstevel@tonic-gate 2730Sstevel@tonic-gate for (i = 0; i < sizeof (lxml_elements) / sizeof (char *); i++) 2740Sstevel@tonic-gate if (xmlStrcmp(tag, (const xmlChar *)lxml_elements[i]) == 0) 2750Sstevel@tonic-gate return ((element_t)i); 2760Sstevel@tonic-gate 2770Sstevel@tonic-gate return ((element_t)-1); 2780Sstevel@tonic-gate } 2790Sstevel@tonic-gate 2800Sstevel@tonic-gate static uint_t 2810Sstevel@tonic-gate lxml_xlate_boolean(const xmlChar *value) 2820Sstevel@tonic-gate { 2830Sstevel@tonic-gate if (xmlStrcmp(value, (const xmlChar *)true) == 0) 2840Sstevel@tonic-gate return (1); 2850Sstevel@tonic-gate 2860Sstevel@tonic-gate if (xmlStrcmp(value, (const xmlChar *)false) == 0) 2870Sstevel@tonic-gate return (0); 2880Sstevel@tonic-gate 2890Sstevel@tonic-gate uu_die(gettext("illegal boolean value \"%s\"\n"), value); 2900Sstevel@tonic-gate 2910Sstevel@tonic-gate /*NOTREACHED*/ 2920Sstevel@tonic-gate } 2930Sstevel@tonic-gate 2940Sstevel@tonic-gate static scf_type_t 2950Sstevel@tonic-gate lxml_element_to_type(element_t type) 2960Sstevel@tonic-gate { 2970Sstevel@tonic-gate switch (type) { 2980Sstevel@tonic-gate case SC_ASTRING: return (SCF_TYPE_ASTRING); 2990Sstevel@tonic-gate case SC_BOOLEAN: return (SCF_TYPE_BOOLEAN); 3000Sstevel@tonic-gate case SC_COUNT: return (SCF_TYPE_COUNT); 3010Sstevel@tonic-gate case SC_FMRI: return (SCF_TYPE_FMRI); 3020Sstevel@tonic-gate case SC_HOST: return (SCF_TYPE_HOST); 3030Sstevel@tonic-gate case SC_HOSTNAME: return (SCF_TYPE_HOSTNAME); 3040Sstevel@tonic-gate case SC_INTEGER: return (SCF_TYPE_INTEGER); 3050Sstevel@tonic-gate case SC_NET_ADDR_V4: return (SCF_TYPE_NET_ADDR_V4); 3060Sstevel@tonic-gate case SC_NET_ADDR_V6: return (SCF_TYPE_NET_ADDR_V6); 3070Sstevel@tonic-gate case SC_OPAQUE: return (SCF_TYPE_OPAQUE); 3080Sstevel@tonic-gate case SC_TIME: return (SCF_TYPE_TIME); 3090Sstevel@tonic-gate case SC_URI: return (SCF_TYPE_URI); 3100Sstevel@tonic-gate case SC_USTRING: return (SCF_TYPE_USTRING); 3110Sstevel@tonic-gate 3120Sstevel@tonic-gate default: 3130Sstevel@tonic-gate uu_die(gettext("unknown value type (%d)\n"), type); 3140Sstevel@tonic-gate } 3150Sstevel@tonic-gate 3160Sstevel@tonic-gate /* NOTREACHED */ 3170Sstevel@tonic-gate } 3180Sstevel@tonic-gate 3190Sstevel@tonic-gate static scf_type_t 3200Sstevel@tonic-gate lxml_element_to_scf_type(element_t type) 3210Sstevel@tonic-gate { 3220Sstevel@tonic-gate switch (type) { 3230Sstevel@tonic-gate case SC_ASTRING: return (SCF_TYPE_ASTRING); 3240Sstevel@tonic-gate case SC_BOOLEAN: return (SCF_TYPE_BOOLEAN); 3250Sstevel@tonic-gate case SC_COUNT: return (SCF_TYPE_COUNT); 3260Sstevel@tonic-gate case SC_FMRI: return (SCF_TYPE_FMRI); 3270Sstevel@tonic-gate case SC_HOST: return (SCF_TYPE_HOST); 3280Sstevel@tonic-gate case SC_HOSTNAME: return (SCF_TYPE_HOSTNAME); 3290Sstevel@tonic-gate case SC_INTEGER: return (SCF_TYPE_INTEGER); 3300Sstevel@tonic-gate case SC_NET_ADDR_V4: return (SCF_TYPE_NET_ADDR_V4); 3310Sstevel@tonic-gate case SC_NET_ADDR_V6: return (SCF_TYPE_NET_ADDR_V6); 3320Sstevel@tonic-gate case SC_OPAQUE: return (SCF_TYPE_OPAQUE); 3330Sstevel@tonic-gate case SC_TIME: return (SCF_TYPE_TIME); 3340Sstevel@tonic-gate case SC_URI: return (SCF_TYPE_URI); 3350Sstevel@tonic-gate case SC_USTRING: return (SCF_TYPE_USTRING); 3360Sstevel@tonic-gate default: 3370Sstevel@tonic-gate uu_die(gettext("unknown value type (%d)\n"), type); 3380Sstevel@tonic-gate } 3390Sstevel@tonic-gate 3400Sstevel@tonic-gate /* NOTREACHED */ 3410Sstevel@tonic-gate } 3420Sstevel@tonic-gate 343*7887SLiane.Praza@Sun.COM /* 344*7887SLiane.Praza@Sun.COM * Create a SCF_TYPE_BOOLEAN property name pname and attach it to the 345*7887SLiane.Praza@Sun.COM * property group at pgrp. The value of the property will be set from the 346*7887SLiane.Praza@Sun.COM * attribute named attr. attr must have a value of 0, 1, true or false. 347*7887SLiane.Praza@Sun.COM * 348*7887SLiane.Praza@Sun.COM * Zero is returned on success. An error is indicated by -1. It indicates 349*7887SLiane.Praza@Sun.COM * that either the attribute had an invalid value or that we could not 350*7887SLiane.Praza@Sun.COM * attach the property to pgrp. The attribute should not have an invalid 351*7887SLiane.Praza@Sun.COM * value if the DTD is correctly written. 352*7887SLiane.Praza@Sun.COM */ 353*7887SLiane.Praza@Sun.COM static int 354*7887SLiane.Praza@Sun.COM new_bool_prop_from_attr(pgroup_t *pgrp, const char *pname, xmlNodePtr n, 355*7887SLiane.Praza@Sun.COM const char *attr) 356*7887SLiane.Praza@Sun.COM { 357*7887SLiane.Praza@Sun.COM uint64_t bool; 358*7887SLiane.Praza@Sun.COM xmlChar *val; 359*7887SLiane.Praza@Sun.COM property_t *p; 360*7887SLiane.Praza@Sun.COM int r; 361*7887SLiane.Praza@Sun.COM 362*7887SLiane.Praza@Sun.COM val = xmlGetProp(n, (xmlChar *)attr); 363*7887SLiane.Praza@Sun.COM if (val == NULL) 364*7887SLiane.Praza@Sun.COM return (0); 365*7887SLiane.Praza@Sun.COM 366*7887SLiane.Praza@Sun.COM if ((xmlStrcmp(val, (xmlChar *)"0") == 0) || 367*7887SLiane.Praza@Sun.COM (xmlStrcmp(val, (xmlChar *)"false") == 0)) { 368*7887SLiane.Praza@Sun.COM bool = 0; 369*7887SLiane.Praza@Sun.COM } else if ((xmlStrcmp(val, (xmlChar *)"1") == 0) || 370*7887SLiane.Praza@Sun.COM (xmlStrcmp(val, (xmlChar *)"true") == 0)) { 371*7887SLiane.Praza@Sun.COM bool = 1; 372*7887SLiane.Praza@Sun.COM } else { 373*7887SLiane.Praza@Sun.COM xmlFree(val); 374*7887SLiane.Praza@Sun.COM return (-1); 375*7887SLiane.Praza@Sun.COM } 376*7887SLiane.Praza@Sun.COM xmlFree(val); 377*7887SLiane.Praza@Sun.COM p = internal_property_create(pname, SCF_TYPE_BOOLEAN, 1, bool); 378*7887SLiane.Praza@Sun.COM r = internal_attach_property(pgrp, p); 379*7887SLiane.Praza@Sun.COM 380*7887SLiane.Praza@Sun.COM if (r != 0) 381*7887SLiane.Praza@Sun.COM internal_property_free(p); 382*7887SLiane.Praza@Sun.COM 383*7887SLiane.Praza@Sun.COM return (r); 384*7887SLiane.Praza@Sun.COM } 385*7887SLiane.Praza@Sun.COM 3860Sstevel@tonic-gate static int 3870Sstevel@tonic-gate new_str_prop_from_attr(pgroup_t *pgrp, const char *pname, scf_type_t ty, 3880Sstevel@tonic-gate xmlNodePtr n, const char *attr) 3890Sstevel@tonic-gate { 3900Sstevel@tonic-gate xmlChar *val; 3910Sstevel@tonic-gate property_t *p; 3920Sstevel@tonic-gate int r; 3930Sstevel@tonic-gate 3940Sstevel@tonic-gate val = xmlGetProp(n, (xmlChar *)attr); 3950Sstevel@tonic-gate 3960Sstevel@tonic-gate p = internal_property_create(pname, ty, 1, val); 3970Sstevel@tonic-gate r = internal_attach_property(pgrp, p); 3980Sstevel@tonic-gate 3990Sstevel@tonic-gate if (r != 0) 4000Sstevel@tonic-gate internal_property_free(p); 4010Sstevel@tonic-gate 4020Sstevel@tonic-gate return (r); 4030Sstevel@tonic-gate } 4040Sstevel@tonic-gate 4050Sstevel@tonic-gate static int 406*7887SLiane.Praza@Sun.COM new_opt_str_prop_from_attr(pgroup_t *pgrp, const char *pname, scf_type_t ty, 407*7887SLiane.Praza@Sun.COM xmlNodePtr n, const char *attr, const char *dflt) 408*7887SLiane.Praza@Sun.COM { 409*7887SLiane.Praza@Sun.COM xmlChar *val; 410*7887SLiane.Praza@Sun.COM property_t *p; 411*7887SLiane.Praza@Sun.COM int r; 412*7887SLiane.Praza@Sun.COM 413*7887SLiane.Praza@Sun.COM val = xmlGetProp(n, (xmlChar *)attr); 414*7887SLiane.Praza@Sun.COM if (val == NULL) { 415*7887SLiane.Praza@Sun.COM if (dflt == NULL) { 416*7887SLiane.Praza@Sun.COM /* 417*7887SLiane.Praza@Sun.COM * A missing attribute is considered to be a 418*7887SLiane.Praza@Sun.COM * success in this function, because many of the 419*7887SLiane.Praza@Sun.COM * attributes are optional. Missing non-optional 420*7887SLiane.Praza@Sun.COM * attributes will be detected later when template 421*7887SLiane.Praza@Sun.COM * validation is done. 422*7887SLiane.Praza@Sun.COM */ 423*7887SLiane.Praza@Sun.COM return (0); 424*7887SLiane.Praza@Sun.COM } else { 425*7887SLiane.Praza@Sun.COM val = (xmlChar *)dflt; 426*7887SLiane.Praza@Sun.COM } 427*7887SLiane.Praza@Sun.COM } 428*7887SLiane.Praza@Sun.COM 429*7887SLiane.Praza@Sun.COM p = internal_property_create(pname, ty, 1, val); 430*7887SLiane.Praza@Sun.COM r = internal_attach_property(pgrp, p); 431*7887SLiane.Praza@Sun.COM 432*7887SLiane.Praza@Sun.COM if (r != 0) 433*7887SLiane.Praza@Sun.COM internal_property_free(p); 434*7887SLiane.Praza@Sun.COM 435*7887SLiane.Praza@Sun.COM return (r); 436*7887SLiane.Praza@Sun.COM } 437*7887SLiane.Praza@Sun.COM 438*7887SLiane.Praza@Sun.COM static int 4390Sstevel@tonic-gate lxml_ignorable_block(xmlNodePtr n) 4400Sstevel@tonic-gate { 4410Sstevel@tonic-gate return ((xmlStrcmp(n->name, (xmlChar *)"text") == 0 || 4420Sstevel@tonic-gate xmlStrcmp(n->name, (xmlChar *)"comment") == 0) ? 1 : 0); 4430Sstevel@tonic-gate } 4440Sstevel@tonic-gate 4450Sstevel@tonic-gate static int 4460Sstevel@tonic-gate lxml_validate_string_value(scf_type_t type, const char *v) 4470Sstevel@tonic-gate { 4480Sstevel@tonic-gate static scf_value_t *scf_value = NULL; 4490Sstevel@tonic-gate static scf_handle_t *scf_hndl = NULL; 4500Sstevel@tonic-gate 4510Sstevel@tonic-gate if (scf_hndl == NULL && (scf_hndl = scf_handle_create(SCF_VERSION)) == 4520Sstevel@tonic-gate NULL) 4530Sstevel@tonic-gate return (-1); 4540Sstevel@tonic-gate 4550Sstevel@tonic-gate if (scf_value == NULL && (scf_value = scf_value_create(scf_hndl)) == 4560Sstevel@tonic-gate NULL) 4570Sstevel@tonic-gate return (-1); 4580Sstevel@tonic-gate 4590Sstevel@tonic-gate return (scf_value_set_from_string(scf_value, type, v)); 4600Sstevel@tonic-gate } 4610Sstevel@tonic-gate 4620Sstevel@tonic-gate static void 4630Sstevel@tonic-gate lxml_free_str(value_t *val) 4640Sstevel@tonic-gate { 4650Sstevel@tonic-gate free(val->sc_u.sc_string); 4660Sstevel@tonic-gate } 4670Sstevel@tonic-gate 4680Sstevel@tonic-gate static value_t * 4690Sstevel@tonic-gate lxml_make_value(element_t type, const xmlChar *value) 4700Sstevel@tonic-gate { 4710Sstevel@tonic-gate value_t *v; 4720Sstevel@tonic-gate char *endptr; 4730Sstevel@tonic-gate scf_type_t scf_type = SCF_TYPE_INVALID; 4740Sstevel@tonic-gate 4750Sstevel@tonic-gate v = internal_value_new(); 4760Sstevel@tonic-gate 4770Sstevel@tonic-gate v->sc_type = lxml_element_to_type(type); 4780Sstevel@tonic-gate 4790Sstevel@tonic-gate switch (type) { 4800Sstevel@tonic-gate case SC_COUNT: 4810Sstevel@tonic-gate /* 4820Sstevel@tonic-gate * Although an SC_COUNT represents a uint64_t the use 4830Sstevel@tonic-gate * of a negative value is acceptable due to the usage 4840Sstevel@tonic-gate * established by inetd(1M). 4850Sstevel@tonic-gate */ 4860Sstevel@tonic-gate errno = 0; 4870Sstevel@tonic-gate v->sc_u.sc_count = strtoull((char *)value, &endptr, 10); 4880Sstevel@tonic-gate if (errno != 0 || endptr == (char *)value || *endptr) 4890Sstevel@tonic-gate uu_die(gettext("illegal value \"%s\" for " 4900Sstevel@tonic-gate "%s (%s)\n"), (char *)value, 4910Sstevel@tonic-gate lxml_prop_types[type], 4920Sstevel@tonic-gate (errno) ? strerror(errno) : 4930Sstevel@tonic-gate gettext("Illegal character")); 4940Sstevel@tonic-gate break; 4950Sstevel@tonic-gate case SC_INTEGER: 4960Sstevel@tonic-gate errno = 0; 4970Sstevel@tonic-gate v->sc_u.sc_integer = strtoll((char *)value, &endptr, 10); 4980Sstevel@tonic-gate if (errno != 0 || *endptr) 4990Sstevel@tonic-gate uu_die(gettext("illegal value \"%s\" for " 5000Sstevel@tonic-gate "%s (%s)\n"), (char *)value, 5010Sstevel@tonic-gate lxml_prop_types[type], 5020Sstevel@tonic-gate (errno) ? strerror(errno) : "Illegal character"); 5030Sstevel@tonic-gate break; 5040Sstevel@tonic-gate case SC_OPAQUE: 5050Sstevel@tonic-gate case SC_HOST: 5060Sstevel@tonic-gate case SC_HOSTNAME: 5070Sstevel@tonic-gate case SC_NET_ADDR_V4: 5080Sstevel@tonic-gate case SC_NET_ADDR_V6: 5090Sstevel@tonic-gate case SC_FMRI: 5100Sstevel@tonic-gate case SC_URI: 5110Sstevel@tonic-gate case SC_TIME: 5120Sstevel@tonic-gate case SC_ASTRING: 5130Sstevel@tonic-gate case SC_USTRING: 5140Sstevel@tonic-gate scf_type = lxml_element_to_scf_type(type); 5150Sstevel@tonic-gate 5160Sstevel@tonic-gate if ((v->sc_u.sc_string = strdup((char *)value)) == NULL) 5170Sstevel@tonic-gate uu_die(gettext("string duplication failed (%s)\n"), 5180Sstevel@tonic-gate strerror(errno)); 5190Sstevel@tonic-gate if (lxml_validate_string_value(scf_type, 5200Sstevel@tonic-gate v->sc_u.sc_string) != 0) 5210Sstevel@tonic-gate uu_die(gettext("illegal value \"%s\" for " 5220Sstevel@tonic-gate "%s (%s)\n"), (char *)value, 5230Sstevel@tonic-gate lxml_prop_types[type], 5240Sstevel@tonic-gate (scf_error()) ? scf_strerror(scf_error()) : 5250Sstevel@tonic-gate gettext("Illegal format")); 5260Sstevel@tonic-gate v->sc_free = lxml_free_str; 5270Sstevel@tonic-gate break; 5280Sstevel@tonic-gate case SC_BOOLEAN: 5290Sstevel@tonic-gate v->sc_u.sc_count = lxml_xlate_boolean(value); 5300Sstevel@tonic-gate break; 5310Sstevel@tonic-gate default: 5320Sstevel@tonic-gate uu_die(gettext("unknown value type (%d)\n"), type); 5330Sstevel@tonic-gate break; 5340Sstevel@tonic-gate } 5350Sstevel@tonic-gate 5360Sstevel@tonic-gate return (v); 5370Sstevel@tonic-gate } 5380Sstevel@tonic-gate 5390Sstevel@tonic-gate static int 5400Sstevel@tonic-gate lxml_get_value(property_t *prop, element_t vtype, xmlNodePtr value) 5410Sstevel@tonic-gate { 5420Sstevel@tonic-gate xmlNodePtr cursor; 5430Sstevel@tonic-gate 5440Sstevel@tonic-gate for (cursor = value->xmlChildrenNode; cursor != NULL; 5450Sstevel@tonic-gate cursor = cursor->next) { 5460Sstevel@tonic-gate xmlChar *assigned_value; 5470Sstevel@tonic-gate value_t *v; 5480Sstevel@tonic-gate 5490Sstevel@tonic-gate if (lxml_ignorable_block(cursor)) 5500Sstevel@tonic-gate continue; 5510Sstevel@tonic-gate 5520Sstevel@tonic-gate switch (lxml_xlate_element(cursor->name)) { 5530Sstevel@tonic-gate case SC_VALUE_NODE: 5540Sstevel@tonic-gate if ((assigned_value = xmlGetProp(cursor, 5550Sstevel@tonic-gate (xmlChar *)value_attr)) == NULL) 5560Sstevel@tonic-gate uu_die(gettext("no value on value node?\n")); 5570Sstevel@tonic-gate break; 5580Sstevel@tonic-gate default: 5590Sstevel@tonic-gate uu_die(gettext("value list contains illegal element " 5600Sstevel@tonic-gate "\'%s\'\n"), cursor->name); 5610Sstevel@tonic-gate break; 5620Sstevel@tonic-gate } 5630Sstevel@tonic-gate 5640Sstevel@tonic-gate v = lxml_make_value(vtype, assigned_value); 5650Sstevel@tonic-gate 5660Sstevel@tonic-gate xmlFree(assigned_value); 5670Sstevel@tonic-gate 5680Sstevel@tonic-gate internal_attach_value(prop, v); 5690Sstevel@tonic-gate } 5700Sstevel@tonic-gate 5710Sstevel@tonic-gate return (0); 5720Sstevel@tonic-gate } 5730Sstevel@tonic-gate 5740Sstevel@tonic-gate static int 5750Sstevel@tonic-gate lxml_get_propval(pgroup_t *pgrp, xmlNodePtr propval) 5760Sstevel@tonic-gate { 5770Sstevel@tonic-gate property_t *p; 5780Sstevel@tonic-gate element_t r; 5790Sstevel@tonic-gate value_t *v; 5800Sstevel@tonic-gate xmlChar *type, *val, *override; 5810Sstevel@tonic-gate 5820Sstevel@tonic-gate p = internal_property_new(); 5830Sstevel@tonic-gate 5840Sstevel@tonic-gate p->sc_property_name = (char *)xmlGetProp(propval, (xmlChar *)name_attr); 585*7887SLiane.Praza@Sun.COM if ((p->sc_property_name == NULL) || (*p->sc_property_name == 0)) 5860Sstevel@tonic-gate uu_die(gettext("property name missing in group '%s'\n"), 5870Sstevel@tonic-gate pgrp->sc_pgroup_name); 5880Sstevel@tonic-gate 5890Sstevel@tonic-gate type = xmlGetProp(propval, (xmlChar *)type_attr); 590*7887SLiane.Praza@Sun.COM if ((type == NULL) || (*type == 0)) 5910Sstevel@tonic-gate uu_die(gettext("property type missing for property '%s/%s'\n"), 5920Sstevel@tonic-gate pgrp->sc_pgroup_name, p->sc_property_name); 5930Sstevel@tonic-gate 5940Sstevel@tonic-gate for (r = 0; r < sizeof (lxml_prop_types) / sizeof (char *); ++r) { 5950Sstevel@tonic-gate if (xmlStrcmp(type, (const xmlChar *)lxml_prop_types[r]) == 0) 5960Sstevel@tonic-gate break; 5970Sstevel@tonic-gate } 598*7887SLiane.Praza@Sun.COM xmlFree(type); 5990Sstevel@tonic-gate if (r >= sizeof (lxml_prop_types) / sizeof (char *)) 6000Sstevel@tonic-gate uu_die(gettext("property type invalid for property '%s/%s'\n"), 6010Sstevel@tonic-gate pgrp->sc_pgroup_name, p->sc_property_name); 6020Sstevel@tonic-gate 6030Sstevel@tonic-gate p->sc_value_type = lxml_element_to_type(r); 6040Sstevel@tonic-gate 6050Sstevel@tonic-gate val = xmlGetProp(propval, (xmlChar *)value_attr); 6060Sstevel@tonic-gate if (val == NULL) 6070Sstevel@tonic-gate uu_die(gettext("property value missing for property '%s/%s'\n"), 6080Sstevel@tonic-gate pgrp->sc_pgroup_name, p->sc_property_name); 6090Sstevel@tonic-gate 6100Sstevel@tonic-gate v = lxml_make_value(r, val); 611*7887SLiane.Praza@Sun.COM xmlFree(val); 6120Sstevel@tonic-gate internal_attach_value(p, v); 6130Sstevel@tonic-gate 6140Sstevel@tonic-gate override = xmlGetProp(propval, (xmlChar *)override_attr); 6150Sstevel@tonic-gate p->sc_property_override = (xmlStrcmp(override, (xmlChar *)true) == 0); 6160Sstevel@tonic-gate xmlFree(override); 6170Sstevel@tonic-gate 6180Sstevel@tonic-gate return (internal_attach_property(pgrp, p)); 6190Sstevel@tonic-gate } 6200Sstevel@tonic-gate 6210Sstevel@tonic-gate static int 6220Sstevel@tonic-gate lxml_get_property(pgroup_t *pgrp, xmlNodePtr property) 6230Sstevel@tonic-gate { 6240Sstevel@tonic-gate property_t *p; 6250Sstevel@tonic-gate xmlNodePtr cursor; 6260Sstevel@tonic-gate element_t r; 6270Sstevel@tonic-gate xmlChar *type, *override; 6280Sstevel@tonic-gate 6290Sstevel@tonic-gate p = internal_property_new(); 6300Sstevel@tonic-gate 631*7887SLiane.Praza@Sun.COM if (((p->sc_property_name = (char *)xmlGetProp(property, 632*7887SLiane.Praza@Sun.COM (xmlChar *)name_attr)) == NULL) || (*p->sc_property_name == 0)) 6330Sstevel@tonic-gate uu_die(gettext("property name missing in group \'%s\'\n"), 6340Sstevel@tonic-gate pgrp->sc_pgroup_name); 6350Sstevel@tonic-gate 636*7887SLiane.Praza@Sun.COM if (((type = xmlGetProp(property, (xmlChar *)type_attr)) == NULL) || 637*7887SLiane.Praza@Sun.COM (*type == 0)) { 6380Sstevel@tonic-gate uu_die(gettext("property type missing for " 6390Sstevel@tonic-gate "property \'%s/%s\'\n"), pgrp->sc_pgroup_name, 6400Sstevel@tonic-gate p->sc_property_name); 641*7887SLiane.Praza@Sun.COM } 6420Sstevel@tonic-gate 6435040Swesolows for (r = 0; r < sizeof (lxml_prop_types) / sizeof (char *); r++) { 6445040Swesolows if (xmlStrcmp(type, (const xmlChar *)lxml_prop_types[r]) == 0) 6455040Swesolows break; 6465040Swesolows } 6475040Swesolows 6485040Swesolows if (r >= sizeof (lxml_prop_types) / sizeof (char *)) { 6495040Swesolows uu_die(gettext("property type invalid for property '%s/%s'\n"), 6505040Swesolows pgrp->sc_pgroup_name, p->sc_property_name); 6515040Swesolows } 6525040Swesolows 6535040Swesolows p->sc_value_type = lxml_element_to_type(r); 6545040Swesolows 6550Sstevel@tonic-gate for (cursor = property->xmlChildrenNode; cursor != NULL; 6560Sstevel@tonic-gate cursor = cursor->next) { 6570Sstevel@tonic-gate if (lxml_ignorable_block(cursor)) 6580Sstevel@tonic-gate continue; 6590Sstevel@tonic-gate 6600Sstevel@tonic-gate switch (r = lxml_xlate_element(cursor->name)) { 6610Sstevel@tonic-gate case SC_ASTRING: 6620Sstevel@tonic-gate case SC_BOOLEAN: 6630Sstevel@tonic-gate case SC_COUNT: 6640Sstevel@tonic-gate case SC_FMRI: 6650Sstevel@tonic-gate case SC_HOST: 6660Sstevel@tonic-gate case SC_HOSTNAME: 6670Sstevel@tonic-gate case SC_INTEGER: 6680Sstevel@tonic-gate case SC_NET_ADDR_V4: 6690Sstevel@tonic-gate case SC_NET_ADDR_V6: 6700Sstevel@tonic-gate case SC_OPAQUE: 6710Sstevel@tonic-gate case SC_TIME: 6720Sstevel@tonic-gate case SC_URI: 6730Sstevel@tonic-gate case SC_USTRING: 6740Sstevel@tonic-gate if (strcmp(lxml_prop_types[r], (const char *)type) != 0) 6750Sstevel@tonic-gate uu_die(gettext("property \'%s\' " 6760Sstevel@tonic-gate "type-to-list mismatch\n"), 6770Sstevel@tonic-gate p->sc_property_name); 6780Sstevel@tonic-gate 6790Sstevel@tonic-gate (void) lxml_get_value(p, r, cursor); 6800Sstevel@tonic-gate break; 6810Sstevel@tonic-gate default: 6820Sstevel@tonic-gate uu_die(gettext("unknown value list type: %s\n"), 6830Sstevel@tonic-gate cursor->name); 6840Sstevel@tonic-gate break; 6850Sstevel@tonic-gate } 6860Sstevel@tonic-gate } 6870Sstevel@tonic-gate 6880Sstevel@tonic-gate xmlFree(type); 6890Sstevel@tonic-gate 6900Sstevel@tonic-gate override = xmlGetProp(property, (xmlChar *)override_attr); 6910Sstevel@tonic-gate p->sc_property_override = (xmlStrcmp(override, (xmlChar *)true) == 0); 6920Sstevel@tonic-gate xmlFree(override); 6930Sstevel@tonic-gate 6940Sstevel@tonic-gate return (internal_attach_property(pgrp, p)); 6950Sstevel@tonic-gate } 6960Sstevel@tonic-gate 6970Sstevel@tonic-gate static int 6980Sstevel@tonic-gate lxml_get_pgroup_stability(pgroup_t *pgrp, xmlNodePtr stab) 6990Sstevel@tonic-gate { 7000Sstevel@tonic-gate return (new_str_prop_from_attr(pgrp, SCF_PROPERTY_STABILITY, 7010Sstevel@tonic-gate SCF_TYPE_ASTRING, stab, value_attr)); 7020Sstevel@tonic-gate } 7030Sstevel@tonic-gate 7040Sstevel@tonic-gate /* 7050Sstevel@tonic-gate * Property groups can go on any of a service, an instance, or a template. 7060Sstevel@tonic-gate */ 7070Sstevel@tonic-gate static int 7080Sstevel@tonic-gate lxml_get_pgroup(entity_t *entity, xmlNodePtr pgroup) 7090Sstevel@tonic-gate { 7100Sstevel@tonic-gate pgroup_t *pg; 7110Sstevel@tonic-gate xmlNodePtr cursor; 7120Sstevel@tonic-gate xmlChar *name, *type, *delete; 7130Sstevel@tonic-gate 7140Sstevel@tonic-gate /* 7150Sstevel@tonic-gate * property group attributes: 7160Sstevel@tonic-gate * name: string 7170Sstevel@tonic-gate * type: string | framework | application 7180Sstevel@tonic-gate */ 7190Sstevel@tonic-gate name = xmlGetProp(pgroup, (xmlChar *)name_attr); 7200Sstevel@tonic-gate type = xmlGetProp(pgroup, (xmlChar *)type_attr); 7210Sstevel@tonic-gate pg = internal_pgroup_find_or_create(entity, (char *)name, (char *)type); 7220Sstevel@tonic-gate xmlFree(name); 7230Sstevel@tonic-gate xmlFree(type); 7240Sstevel@tonic-gate 7250Sstevel@tonic-gate /* 7260Sstevel@tonic-gate * Walk the children of this lxml_elements, which are a stability 7270Sstevel@tonic-gate * element, property elements, or propval elements. 7280Sstevel@tonic-gate */ 7290Sstevel@tonic-gate for (cursor = pgroup->xmlChildrenNode; cursor != NULL; 7300Sstevel@tonic-gate cursor = cursor->next) { 7310Sstevel@tonic-gate if (lxml_ignorable_block(cursor)) 7320Sstevel@tonic-gate continue; 7330Sstevel@tonic-gate 7340Sstevel@tonic-gate switch (lxml_xlate_element(cursor->name)) { 7350Sstevel@tonic-gate case SC_STABILITY: 7360Sstevel@tonic-gate (void) lxml_get_pgroup_stability(pg, cursor); 7370Sstevel@tonic-gate break; 7380Sstevel@tonic-gate case SC_PROPERTY: 7390Sstevel@tonic-gate (void) lxml_get_property(pg, cursor); 7400Sstevel@tonic-gate break; 7410Sstevel@tonic-gate case SC_PROPVAL: 7420Sstevel@tonic-gate (void) lxml_get_propval(pg, cursor); 7430Sstevel@tonic-gate break; 7440Sstevel@tonic-gate default: 7450Sstevel@tonic-gate abort(); 7460Sstevel@tonic-gate break; 7470Sstevel@tonic-gate } 7480Sstevel@tonic-gate } 7490Sstevel@tonic-gate 7500Sstevel@tonic-gate delete = xmlGetProp(pgroup, (xmlChar *)delete_attr); 7510Sstevel@tonic-gate pg->sc_pgroup_delete = (xmlStrcmp(delete, (xmlChar *)true) == 0); 7520Sstevel@tonic-gate xmlFree(delete); 7530Sstevel@tonic-gate 7540Sstevel@tonic-gate return (0); 7550Sstevel@tonic-gate } 7560Sstevel@tonic-gate 7570Sstevel@tonic-gate 7580Sstevel@tonic-gate /* 7590Sstevel@tonic-gate * Dependency groups, execution methods can go on either a service or an 7600Sstevel@tonic-gate * instance. 7610Sstevel@tonic-gate */ 7620Sstevel@tonic-gate 7630Sstevel@tonic-gate static int 7640Sstevel@tonic-gate lxml_get_method_profile(pgroup_t *pg, xmlNodePtr profile) 7650Sstevel@tonic-gate { 7660Sstevel@tonic-gate property_t *p; 7670Sstevel@tonic-gate 7680Sstevel@tonic-gate p = internal_property_create(SCF_PROPERTY_USE_PROFILE, SCF_TYPE_BOOLEAN, 7690Sstevel@tonic-gate 1, (uint64_t)1); 7700Sstevel@tonic-gate if (internal_attach_property(pg, p) != 0) 7710Sstevel@tonic-gate return (-1); 7720Sstevel@tonic-gate 7730Sstevel@tonic-gate return (new_str_prop_from_attr(pg, SCF_PROPERTY_PROFILE, 7740Sstevel@tonic-gate SCF_TYPE_ASTRING, profile, name_attr)); 7750Sstevel@tonic-gate } 7760Sstevel@tonic-gate 7770Sstevel@tonic-gate static int 7780Sstevel@tonic-gate lxml_get_method_credential(pgroup_t *pg, xmlNodePtr cred) 7790Sstevel@tonic-gate { 7800Sstevel@tonic-gate property_t *p; 7810Sstevel@tonic-gate 7820Sstevel@tonic-gate p = internal_property_create(SCF_PROPERTY_USE_PROFILE, SCF_TYPE_BOOLEAN, 7830Sstevel@tonic-gate 1, (uint64_t)0); 7840Sstevel@tonic-gate if (internal_attach_property(pg, p) != 0) 7850Sstevel@tonic-gate return (-1); 7860Sstevel@tonic-gate 7870Sstevel@tonic-gate if (new_str_prop_from_attr(pg, SCF_PROPERTY_USER, SCF_TYPE_ASTRING, 7880Sstevel@tonic-gate cred, "user") != 0) 7890Sstevel@tonic-gate return (-1); 7900Sstevel@tonic-gate 7910Sstevel@tonic-gate if (new_str_prop_from_attr(pg, SCF_PROPERTY_GROUP, SCF_TYPE_ASTRING, 7920Sstevel@tonic-gate cred, "group") != 0) 7930Sstevel@tonic-gate return (-1); 7940Sstevel@tonic-gate 7950Sstevel@tonic-gate if (new_str_prop_from_attr(pg, SCF_PROPERTY_SUPP_GROUPS, 7960Sstevel@tonic-gate SCF_TYPE_ASTRING, cred, "supp_groups") != 0) 7970Sstevel@tonic-gate return (-1); 7980Sstevel@tonic-gate 7990Sstevel@tonic-gate if (new_str_prop_from_attr(pg, SCF_PROPERTY_PRIVILEGES, 8000Sstevel@tonic-gate SCF_TYPE_ASTRING, cred, "privileges") != 0) 8010Sstevel@tonic-gate return (-1); 8020Sstevel@tonic-gate 8030Sstevel@tonic-gate if (new_str_prop_from_attr(pg, SCF_PROPERTY_LIMIT_PRIVILEGES, 8040Sstevel@tonic-gate SCF_TYPE_ASTRING, cred, "limit_privileges") != 0) 8050Sstevel@tonic-gate return (-1); 8060Sstevel@tonic-gate 8070Sstevel@tonic-gate return (0); 8080Sstevel@tonic-gate } 8090Sstevel@tonic-gate 8100Sstevel@tonic-gate static char * 8110Sstevel@tonic-gate lxml_get_envvar(xmlNodePtr envvar) 8120Sstevel@tonic-gate { 8130Sstevel@tonic-gate char *name; 8140Sstevel@tonic-gate char *value; 8150Sstevel@tonic-gate char *ret; 8160Sstevel@tonic-gate 817*7887SLiane.Praza@Sun.COM name = (char *)xmlGetProp(envvar, (xmlChar *)name_attr); 818*7887SLiane.Praza@Sun.COM value = (char *)xmlGetProp(envvar, (xmlChar *)value_attr); 8190Sstevel@tonic-gate 8200Sstevel@tonic-gate if (strlen(name) == 0 || strchr(name, '=') != NULL) 8210Sstevel@tonic-gate uu_die(gettext("Invalid environment variable " 8220Sstevel@tonic-gate "\"%s\".\n"), name); 8230Sstevel@tonic-gate if (strstr(name, "SMF_") == name) 8240Sstevel@tonic-gate uu_die(gettext("Invalid environment variable " 8250Sstevel@tonic-gate "\"%s\"; \"SMF_\" prefix is reserved.\n"), name); 8260Sstevel@tonic-gate 8270Sstevel@tonic-gate ret = uu_msprintf("%s=%s", name, value); 8280Sstevel@tonic-gate xmlFree(name); 8290Sstevel@tonic-gate xmlFree(value); 8300Sstevel@tonic-gate return (ret); 8310Sstevel@tonic-gate } 8320Sstevel@tonic-gate 8330Sstevel@tonic-gate static int 8340Sstevel@tonic-gate lxml_get_method_environment(pgroup_t *pg, xmlNodePtr environment) 8350Sstevel@tonic-gate { 8360Sstevel@tonic-gate property_t *p; 8370Sstevel@tonic-gate xmlNodePtr cursor; 8380Sstevel@tonic-gate value_t *val; 8390Sstevel@tonic-gate 8400Sstevel@tonic-gate p = internal_property_create(SCF_PROPERTY_ENVIRONMENT, 8410Sstevel@tonic-gate SCF_TYPE_ASTRING, 0); 8420Sstevel@tonic-gate 8430Sstevel@tonic-gate for (cursor = environment->xmlChildrenNode; cursor != NULL; 8440Sstevel@tonic-gate cursor = cursor->next) { 8450Sstevel@tonic-gate char *tmp; 8460Sstevel@tonic-gate 8470Sstevel@tonic-gate if (lxml_ignorable_block(cursor)) 8480Sstevel@tonic-gate continue; 8490Sstevel@tonic-gate 8500Sstevel@tonic-gate if (lxml_xlate_element(cursor->name) != SC_METHOD_ENVVAR) 8510Sstevel@tonic-gate uu_die(gettext("illegal element \"%s\" on " 8520Sstevel@tonic-gate "method environment for \"%s\"\n"), 8530Sstevel@tonic-gate cursor->name, pg->sc_pgroup_name); 8540Sstevel@tonic-gate 8550Sstevel@tonic-gate if ((tmp = lxml_get_envvar(cursor)) == NULL) 8560Sstevel@tonic-gate uu_die(gettext("Out of memory\n")); 8570Sstevel@tonic-gate 8580Sstevel@tonic-gate val = internal_value_new(); 8590Sstevel@tonic-gate val->sc_u.sc_string = tmp; 8600Sstevel@tonic-gate val->sc_type = SCF_TYPE_ASTRING; 8610Sstevel@tonic-gate val->sc_free = lxml_free_str; 8620Sstevel@tonic-gate internal_attach_value(p, val); 8630Sstevel@tonic-gate } 8640Sstevel@tonic-gate 8650Sstevel@tonic-gate if (internal_attach_property(pg, p) != 0) { 8660Sstevel@tonic-gate internal_property_free(p); 8670Sstevel@tonic-gate return (-1); 8680Sstevel@tonic-gate } 8690Sstevel@tonic-gate 8700Sstevel@tonic-gate return (0); 8710Sstevel@tonic-gate } 8720Sstevel@tonic-gate 8730Sstevel@tonic-gate static int 8740Sstevel@tonic-gate lxml_get_method_context(pgroup_t *pg, xmlNodePtr ctx) 8750Sstevel@tonic-gate { 8760Sstevel@tonic-gate xmlNodePtr cursor; 8770Sstevel@tonic-gate 8780Sstevel@tonic-gate if (new_str_prop_from_attr(pg, SCF_PROPERTY_WORKING_DIRECTORY, 8790Sstevel@tonic-gate SCF_TYPE_ASTRING, ctx, "working_directory") != 0) 8800Sstevel@tonic-gate return (-1); 8810Sstevel@tonic-gate 8820Sstevel@tonic-gate if (new_str_prop_from_attr(pg, SCF_PROPERTY_PROJECT, SCF_TYPE_ASTRING, 8830Sstevel@tonic-gate ctx, "project") != 0) 8840Sstevel@tonic-gate return (-1); 8850Sstevel@tonic-gate 8860Sstevel@tonic-gate if (new_str_prop_from_attr(pg, SCF_PROPERTY_RESOURCE_POOL, 8870Sstevel@tonic-gate SCF_TYPE_ASTRING, ctx, "resource_pool") != 0) 8880Sstevel@tonic-gate return (-1); 8890Sstevel@tonic-gate 8900Sstevel@tonic-gate for (cursor = ctx->xmlChildrenNode; cursor != NULL; 8910Sstevel@tonic-gate cursor = cursor->next) { 8920Sstevel@tonic-gate if (lxml_ignorable_block(cursor)) 8930Sstevel@tonic-gate continue; 8940Sstevel@tonic-gate 8950Sstevel@tonic-gate switch (lxml_xlate_element(cursor->name)) { 8960Sstevel@tonic-gate case SC_METHOD_CREDENTIAL: 8970Sstevel@tonic-gate (void) lxml_get_method_credential(pg, cursor); 8980Sstevel@tonic-gate break; 8990Sstevel@tonic-gate case SC_METHOD_PROFILE: 9000Sstevel@tonic-gate (void) lxml_get_method_profile(pg, cursor); 9010Sstevel@tonic-gate break; 9020Sstevel@tonic-gate case SC_METHOD_ENVIRONMENT: 9030Sstevel@tonic-gate (void) lxml_get_method_environment(pg, cursor); 9040Sstevel@tonic-gate break; 9050Sstevel@tonic-gate default: 9060Sstevel@tonic-gate semerr(gettext("illegal element \'%s\' in method " 9070Sstevel@tonic-gate "context\n"), (char *)cursor); 9080Sstevel@tonic-gate break; 9090Sstevel@tonic-gate } 9100Sstevel@tonic-gate } 9110Sstevel@tonic-gate 9120Sstevel@tonic-gate return (0); 9130Sstevel@tonic-gate } 9140Sstevel@tonic-gate 9150Sstevel@tonic-gate static int 9160Sstevel@tonic-gate lxml_get_entity_method_context(entity_t *entity, xmlNodePtr ctx) 9170Sstevel@tonic-gate { 9180Sstevel@tonic-gate pgroup_t *pg; 9190Sstevel@tonic-gate 9200Sstevel@tonic-gate pg = internal_pgroup_find_or_create(entity, SCF_PG_METHOD_CONTEXT, 9210Sstevel@tonic-gate (char *)scf_group_framework); 9220Sstevel@tonic-gate 9230Sstevel@tonic-gate return (lxml_get_method_context(pg, ctx)); 9240Sstevel@tonic-gate } 9250Sstevel@tonic-gate 9260Sstevel@tonic-gate static int 9270Sstevel@tonic-gate lxml_get_exec_method(entity_t *entity, xmlNodePtr emeth) 9280Sstevel@tonic-gate { 9290Sstevel@tonic-gate pgroup_t *pg; 9300Sstevel@tonic-gate property_t *p; 9310Sstevel@tonic-gate xmlChar *name, *timeout, *delete; 9320Sstevel@tonic-gate xmlNodePtr cursor; 9330Sstevel@tonic-gate int r = 0; 9340Sstevel@tonic-gate 9350Sstevel@tonic-gate name = xmlGetProp(emeth, (xmlChar *)name_attr); 9360Sstevel@tonic-gate pg = internal_pgroup_find_or_create(entity, (char *)name, 9370Sstevel@tonic-gate (char *)SCF_GROUP_METHOD); 9380Sstevel@tonic-gate xmlFree(name); 9390Sstevel@tonic-gate 9400Sstevel@tonic-gate if (new_str_prop_from_attr(pg, SCF_PROPERTY_TYPE, SCF_TYPE_ASTRING, 9410Sstevel@tonic-gate emeth, type_attr) != 0 || 9420Sstevel@tonic-gate new_str_prop_from_attr(pg, SCF_PROPERTY_EXEC, SCF_TYPE_ASTRING, 9430Sstevel@tonic-gate emeth, "exec") != 0) 9440Sstevel@tonic-gate return (-1); 9450Sstevel@tonic-gate 946*7887SLiane.Praza@Sun.COM timeout = xmlGetProp(emeth, (xmlChar *)timeout_seconds_attr); 9470Sstevel@tonic-gate if (timeout != NULL) { 9480Sstevel@tonic-gate uint64_t u_timeout; 9490Sstevel@tonic-gate char *endptr; 9500Sstevel@tonic-gate /* 9510Sstevel@tonic-gate * Although an SC_COUNT represents a uint64_t the use 9520Sstevel@tonic-gate * of a negative value is acceptable due to the usage 9530Sstevel@tonic-gate * established by inetd(1M). 9540Sstevel@tonic-gate */ 9550Sstevel@tonic-gate errno = 0; 9560Sstevel@tonic-gate u_timeout = strtoull((char *)timeout, &endptr, 10); 9570Sstevel@tonic-gate if (errno != 0 || endptr == (char *)timeout || *endptr) 9580Sstevel@tonic-gate uu_die(gettext("illegal value \"%s\" for " 9590Sstevel@tonic-gate "timeout_seconds (%s)\n"), 9600Sstevel@tonic-gate (char *)timeout, (errno) ? strerror(errno): 9610Sstevel@tonic-gate gettext("Illegal character")); 9620Sstevel@tonic-gate p = internal_property_create(SCF_PROPERTY_TIMEOUT, 9630Sstevel@tonic-gate SCF_TYPE_COUNT, 1, u_timeout); 9640Sstevel@tonic-gate r = internal_attach_property(pg, p); 9650Sstevel@tonic-gate xmlFree(timeout); 9660Sstevel@tonic-gate } 9670Sstevel@tonic-gate if (r != 0) 9680Sstevel@tonic-gate return (-1); 9690Sstevel@tonic-gate 9700Sstevel@tonic-gate /* 9710Sstevel@tonic-gate * There is a possibility that a method context also exists, in which 9720Sstevel@tonic-gate * case the following attributes are defined: project, resource_pool, 9730Sstevel@tonic-gate * working_directory, profile, user, group, privileges, limit_privileges 9740Sstevel@tonic-gate */ 9750Sstevel@tonic-gate for (cursor = emeth->xmlChildrenNode; cursor != NULL; 9760Sstevel@tonic-gate cursor = cursor->next) { 9770Sstevel@tonic-gate if (lxml_ignorable_block(cursor)) 9780Sstevel@tonic-gate continue; 9790Sstevel@tonic-gate 9800Sstevel@tonic-gate switch (lxml_xlate_element(cursor->name)) { 9810Sstevel@tonic-gate case SC_STABILITY: 9820Sstevel@tonic-gate if (lxml_get_pgroup_stability(pg, cursor) != 0) 9830Sstevel@tonic-gate return (-1); 9840Sstevel@tonic-gate break; 9850Sstevel@tonic-gate 9860Sstevel@tonic-gate case SC_METHOD_CONTEXT: 9870Sstevel@tonic-gate (void) lxml_get_method_context(pg, cursor); 9880Sstevel@tonic-gate break; 9890Sstevel@tonic-gate 9900Sstevel@tonic-gate case SC_PROPVAL: 9910Sstevel@tonic-gate (void) lxml_get_propval(pg, cursor); 9920Sstevel@tonic-gate break; 9930Sstevel@tonic-gate 9940Sstevel@tonic-gate case SC_PROPERTY: 9950Sstevel@tonic-gate (void) lxml_get_property(pg, cursor); 9960Sstevel@tonic-gate break; 9970Sstevel@tonic-gate 9980Sstevel@tonic-gate default: 9990Sstevel@tonic-gate uu_die(gettext("illegal element \"%s\" on " 10000Sstevel@tonic-gate "execution method \"%s\"\n"), cursor->name, 10010Sstevel@tonic-gate pg->sc_pgroup_name); 10020Sstevel@tonic-gate break; 10030Sstevel@tonic-gate } 10040Sstevel@tonic-gate } 10050Sstevel@tonic-gate 10060Sstevel@tonic-gate delete = xmlGetProp(emeth, (xmlChar *)delete_attr); 10070Sstevel@tonic-gate pg->sc_pgroup_delete = (xmlStrcmp(delete, (xmlChar *)true) == 0); 10080Sstevel@tonic-gate xmlFree(delete); 10090Sstevel@tonic-gate 10100Sstevel@tonic-gate return (0); 10110Sstevel@tonic-gate } 10120Sstevel@tonic-gate 10130Sstevel@tonic-gate static int 10140Sstevel@tonic-gate lxml_get_dependency(entity_t *entity, xmlNodePtr dependency) 10150Sstevel@tonic-gate { 10160Sstevel@tonic-gate pgroup_t *pg; 10170Sstevel@tonic-gate property_t *p; 10180Sstevel@tonic-gate xmlNodePtr cursor; 10190Sstevel@tonic-gate xmlChar *name; 10200Sstevel@tonic-gate xmlChar *delete; 10210Sstevel@tonic-gate 10220Sstevel@tonic-gate /* 10230Sstevel@tonic-gate * dependency attributes: 10240Sstevel@tonic-gate * name: string 10250Sstevel@tonic-gate * grouping: require_all | require_any | exclude_all | optional_all 10260Sstevel@tonic-gate * reset_on: string (error | restart | refresh | none) 10270Sstevel@tonic-gate * type: service / path /host 10280Sstevel@tonic-gate */ 10290Sstevel@tonic-gate 10300Sstevel@tonic-gate name = xmlGetProp(dependency, (xmlChar *)name_attr); 10310Sstevel@tonic-gate pg = internal_pgroup_find_or_create(entity, (char *)name, 10320Sstevel@tonic-gate (char *)SCF_GROUP_DEPENDENCY); 10330Sstevel@tonic-gate xmlFree(name); 10340Sstevel@tonic-gate 10350Sstevel@tonic-gate if (new_str_prop_from_attr(pg, SCF_PROPERTY_TYPE, SCF_TYPE_ASTRING, 10360Sstevel@tonic-gate dependency, type_attr) != 0) 10370Sstevel@tonic-gate return (-1); 10380Sstevel@tonic-gate 10390Sstevel@tonic-gate if (new_str_prop_from_attr(pg, SCF_PROPERTY_RESTART_ON, 10400Sstevel@tonic-gate SCF_TYPE_ASTRING, dependency, "restart_on") != 0) 10410Sstevel@tonic-gate return (-1); 10420Sstevel@tonic-gate 10430Sstevel@tonic-gate if (new_str_prop_from_attr(pg, SCF_PROPERTY_GROUPING, SCF_TYPE_ASTRING, 10440Sstevel@tonic-gate dependency, "grouping") != 0) 10450Sstevel@tonic-gate return (-1); 10460Sstevel@tonic-gate 10470Sstevel@tonic-gate p = internal_property_create(SCF_PROPERTY_ENTITIES, SCF_TYPE_FMRI, 0); 10480Sstevel@tonic-gate if (internal_attach_property(pg, p) != 0) 10490Sstevel@tonic-gate return (-1); 10500Sstevel@tonic-gate 10510Sstevel@tonic-gate for (cursor = dependency->xmlChildrenNode; cursor != NULL; 10520Sstevel@tonic-gate cursor = cursor->next) { 10530Sstevel@tonic-gate xmlChar *value; 10540Sstevel@tonic-gate value_t *v; 10550Sstevel@tonic-gate 10560Sstevel@tonic-gate if (lxml_ignorable_block(cursor)) 10570Sstevel@tonic-gate continue; 10580Sstevel@tonic-gate 10590Sstevel@tonic-gate switch (lxml_xlate_element(cursor->name)) { 10600Sstevel@tonic-gate case SC_STABILITY: 10610Sstevel@tonic-gate if (lxml_get_pgroup_stability(pg, cursor) != 0) 10620Sstevel@tonic-gate return (-1); 10630Sstevel@tonic-gate break; 10640Sstevel@tonic-gate 10650Sstevel@tonic-gate case SC_SERVICE_FMRI: 10660Sstevel@tonic-gate value = xmlGetProp(cursor, (xmlChar *)value_attr); 10670Sstevel@tonic-gate if (value != NULL) { 10680Sstevel@tonic-gate if (lxml_validate_string_value(SCF_TYPE_FMRI, 10690Sstevel@tonic-gate (char *)value) != 0) 10700Sstevel@tonic-gate uu_die(gettext("illegal value \"%s\" " 10710Sstevel@tonic-gate "for %s (%s)\n"), (char *)value, 10720Sstevel@tonic-gate lxml_prop_types[SC_FMRI], 10730Sstevel@tonic-gate (scf_error()) ? 10740Sstevel@tonic-gate scf_strerror(scf_error()) : 10750Sstevel@tonic-gate gettext("Illegal format")); 10760Sstevel@tonic-gate v = internal_value_new(); 10770Sstevel@tonic-gate v->sc_type = SCF_TYPE_FMRI; 10780Sstevel@tonic-gate v->sc_u.sc_string = (char *)value; 10790Sstevel@tonic-gate internal_attach_value(p, v); 10800Sstevel@tonic-gate } 10810Sstevel@tonic-gate 10820Sstevel@tonic-gate break; 10830Sstevel@tonic-gate 10840Sstevel@tonic-gate case SC_PROPVAL: 10850Sstevel@tonic-gate (void) lxml_get_propval(pg, cursor); 10860Sstevel@tonic-gate break; 10870Sstevel@tonic-gate 10880Sstevel@tonic-gate case SC_PROPERTY: 10890Sstevel@tonic-gate (void) lxml_get_property(pg, cursor); 10900Sstevel@tonic-gate break; 10910Sstevel@tonic-gate 10920Sstevel@tonic-gate default: 10930Sstevel@tonic-gate uu_die(gettext("illegal element \"%s\" on " 10940Sstevel@tonic-gate "dependency group \"%s\"\n"), cursor->name, name); 10950Sstevel@tonic-gate break; 10960Sstevel@tonic-gate } 10970Sstevel@tonic-gate } 10980Sstevel@tonic-gate 10990Sstevel@tonic-gate delete = xmlGetProp(dependency, (xmlChar *)delete_attr); 11000Sstevel@tonic-gate pg->sc_pgroup_delete = (xmlStrcmp(delete, (xmlChar *)true) == 0); 11010Sstevel@tonic-gate xmlFree(delete); 11020Sstevel@tonic-gate 11030Sstevel@tonic-gate return (0); 11040Sstevel@tonic-gate } 11050Sstevel@tonic-gate 11060Sstevel@tonic-gate /* 11070Sstevel@tonic-gate * Dependents are hairy. They should cause a dependency pg to be created in 11080Sstevel@tonic-gate * another service, but we can't do that here; we'll have to wait until the 11090Sstevel@tonic-gate * import routines. So for now we'll add the dependency group that should go 11100Sstevel@tonic-gate * in the other service to the entity's dependent list. 11110Sstevel@tonic-gate */ 11120Sstevel@tonic-gate static int 11130Sstevel@tonic-gate lxml_get_dependent(entity_t *entity, xmlNodePtr dependent) 11140Sstevel@tonic-gate { 11150Sstevel@tonic-gate xmlChar *name, *or; 11160Sstevel@tonic-gate xmlNodePtr sf; 11170Sstevel@tonic-gate xmlChar *fmri, *delete; 11180Sstevel@tonic-gate pgroup_t *pg; 11190Sstevel@tonic-gate property_t *p; 11200Sstevel@tonic-gate xmlNodePtr n; 11210Sstevel@tonic-gate char *myfmri; 11220Sstevel@tonic-gate 11230Sstevel@tonic-gate name = xmlGetProp(dependent, (xmlChar *)name_attr); 11240Sstevel@tonic-gate 11250Sstevel@tonic-gate if (internal_pgroup_find(entity, (char *)name, NULL) != NULL) { 11260Sstevel@tonic-gate semerr(gettext("Property group and dependent of entity %s " 11270Sstevel@tonic-gate "have same name \"%s\".\n"), entity->sc_name, name); 11280Sstevel@tonic-gate xmlFree(name); 11290Sstevel@tonic-gate return (-1); 11300Sstevel@tonic-gate } 11310Sstevel@tonic-gate 11320Sstevel@tonic-gate or = xmlGetProp(dependent, (xmlChar *)override_attr); 11330Sstevel@tonic-gate 11340Sstevel@tonic-gate pg = internal_pgroup_new(); 11350Sstevel@tonic-gate pg->sc_pgroup_name = (char *)name; 11360Sstevel@tonic-gate pg->sc_pgroup_type = (char *)SCF_GROUP_DEPENDENCY; 11370Sstevel@tonic-gate pg->sc_pgroup_override = (xmlStrcmp(or, (xmlChar *)true) == 0); 11380Sstevel@tonic-gate xmlFree(or); 11390Sstevel@tonic-gate if (internal_attach_dependent(entity, pg) != 0) { 11400Sstevel@tonic-gate xmlFree(name); 11410Sstevel@tonic-gate internal_pgroup_free(pg); 11420Sstevel@tonic-gate return (-1); 11430Sstevel@tonic-gate } 11440Sstevel@tonic-gate 11450Sstevel@tonic-gate for (sf = dependent->children; sf != NULL; sf = sf->next) 11460Sstevel@tonic-gate if (xmlStrcmp(sf->name, (xmlChar *)"service_fmri") == 0) 11470Sstevel@tonic-gate break; 11480Sstevel@tonic-gate assert(sf != NULL); 11490Sstevel@tonic-gate fmri = xmlGetProp(sf, (xmlChar *)value_attr); 11500Sstevel@tonic-gate pg->sc_pgroup_fmri = (char *)fmri; 11510Sstevel@tonic-gate 11520Sstevel@tonic-gate if (new_str_prop_from_attr(pg, SCF_PROPERTY_RESTART_ON, 11530Sstevel@tonic-gate SCF_TYPE_ASTRING, dependent, "restart_on") != 0) 11540Sstevel@tonic-gate return (-1); 11550Sstevel@tonic-gate 11560Sstevel@tonic-gate if (new_str_prop_from_attr(pg, SCF_PROPERTY_GROUPING, SCF_TYPE_ASTRING, 11570Sstevel@tonic-gate dependent, "grouping") != 0) 11580Sstevel@tonic-gate return (-1); 11590Sstevel@tonic-gate 11600Sstevel@tonic-gate myfmri = safe_malloc(max_scf_fmri_len + 1); 11610Sstevel@tonic-gate if (entity->sc_etype == SVCCFG_SERVICE_OBJECT) { 11620Sstevel@tonic-gate if (snprintf(myfmri, max_scf_fmri_len + 1, "svc:/%s", 11630Sstevel@tonic-gate entity->sc_name) < 0) 11640Sstevel@tonic-gate bad_error("snprintf", errno); 11650Sstevel@tonic-gate } else { 11660Sstevel@tonic-gate assert(entity->sc_etype == SVCCFG_INSTANCE_OBJECT); 11670Sstevel@tonic-gate if (snprintf(myfmri, max_scf_fmri_len + 1, "svc:/%s:%s", 11680Sstevel@tonic-gate entity->sc_parent->sc_name, entity->sc_name) < 0) 11690Sstevel@tonic-gate bad_error("snprintf", errno); 11700Sstevel@tonic-gate } 11710Sstevel@tonic-gate 11720Sstevel@tonic-gate p = internal_property_create(SCF_PROPERTY_ENTITIES, SCF_TYPE_FMRI, 1, 11730Sstevel@tonic-gate myfmri); 11740Sstevel@tonic-gate if (internal_attach_property(pg, p) != 0) 11750Sstevel@tonic-gate return (-1); 11760Sstevel@tonic-gate 11770Sstevel@tonic-gate /* Create a property to serve as a do-not-export flag. */ 11780Sstevel@tonic-gate p = internal_property_create("external", SCF_TYPE_BOOLEAN, 1, 11790Sstevel@tonic-gate (uint64_t)1); 11800Sstevel@tonic-gate if (internal_attach_property(pg, p) != 0) 11810Sstevel@tonic-gate return (-1); 11820Sstevel@tonic-gate 11830Sstevel@tonic-gate for (n = sf->next; n != NULL; n = n->next) { 11840Sstevel@tonic-gate if (lxml_ignorable_block(n)) 11850Sstevel@tonic-gate continue; 11860Sstevel@tonic-gate 11870Sstevel@tonic-gate switch (lxml_xlate_element(n->name)) { 11880Sstevel@tonic-gate case SC_STABILITY: 11890Sstevel@tonic-gate if (new_str_prop_from_attr(pg, 11900Sstevel@tonic-gate SCF_PROPERTY_ENTITY_STABILITY, SCF_TYPE_ASTRING, n, 11910Sstevel@tonic-gate value_attr) != 0) 11920Sstevel@tonic-gate return (-1); 11930Sstevel@tonic-gate break; 11940Sstevel@tonic-gate 11950Sstevel@tonic-gate case SC_PROPVAL: 11960Sstevel@tonic-gate (void) lxml_get_propval(pg, n); 11970Sstevel@tonic-gate break; 11980Sstevel@tonic-gate 11990Sstevel@tonic-gate case SC_PROPERTY: 12000Sstevel@tonic-gate (void) lxml_get_property(pg, n); 12010Sstevel@tonic-gate break; 12020Sstevel@tonic-gate 12030Sstevel@tonic-gate default: 12040Sstevel@tonic-gate uu_die(gettext("unexpected element %s.\n"), n->name); 12050Sstevel@tonic-gate } 12060Sstevel@tonic-gate } 12070Sstevel@tonic-gate 12080Sstevel@tonic-gate /* Go back and fill in defaults. */ 12090Sstevel@tonic-gate if (internal_property_find(pg, SCF_PROPERTY_TYPE) == NULL) { 12100Sstevel@tonic-gate p = internal_property_create(SCF_PROPERTY_TYPE, 12110Sstevel@tonic-gate SCF_TYPE_ASTRING, 1, "service"); 12120Sstevel@tonic-gate if (internal_attach_property(pg, p) != 0) 12130Sstevel@tonic-gate return (-1); 12140Sstevel@tonic-gate } 12150Sstevel@tonic-gate 12160Sstevel@tonic-gate delete = xmlGetProp(dependent, (xmlChar *)delete_attr); 12170Sstevel@tonic-gate pg->sc_pgroup_delete = (xmlStrcmp(delete, (xmlChar *)true) == 0); 12180Sstevel@tonic-gate xmlFree(delete); 12190Sstevel@tonic-gate 12200Sstevel@tonic-gate pg = internal_pgroup_find_or_create(entity, "dependents", 12210Sstevel@tonic-gate (char *)scf_group_framework); 1222306Sbustos p = internal_property_create((char *)name, SCF_TYPE_FMRI, 1, fmri); 12230Sstevel@tonic-gate if (internal_attach_property(pg, p) != 0) 12240Sstevel@tonic-gate return (-1); 12250Sstevel@tonic-gate 12260Sstevel@tonic-gate return (0); 12270Sstevel@tonic-gate } 12280Sstevel@tonic-gate 12290Sstevel@tonic-gate static int 12300Sstevel@tonic-gate lxml_get_entity_stability(entity_t *entity, xmlNodePtr rstr) 12310Sstevel@tonic-gate { 12320Sstevel@tonic-gate pgroup_t *pg; 12330Sstevel@tonic-gate property_t *p; 12340Sstevel@tonic-gate xmlChar *stabval; 12350Sstevel@tonic-gate 1236*7887SLiane.Praza@Sun.COM if (((stabval = xmlGetProp(rstr, (xmlChar *)value_attr)) == NULL) || 1237*7887SLiane.Praza@Sun.COM (*stabval == 0)) { 12380Sstevel@tonic-gate uu_warn(gettext("no stability value found\n")); 12390Sstevel@tonic-gate stabval = (xmlChar *)strdup("External"); 12400Sstevel@tonic-gate } 12410Sstevel@tonic-gate 12420Sstevel@tonic-gate pg = internal_pgroup_find_or_create(entity, (char *)scf_pg_general, 12430Sstevel@tonic-gate (char *)scf_group_framework); 12440Sstevel@tonic-gate 12450Sstevel@tonic-gate p = internal_property_create(SCF_PROPERTY_ENTITY_STABILITY, 12460Sstevel@tonic-gate SCF_TYPE_ASTRING, 1, stabval); 12470Sstevel@tonic-gate 12480Sstevel@tonic-gate return (internal_attach_property(pg, p)); 12490Sstevel@tonic-gate } 12500Sstevel@tonic-gate 12510Sstevel@tonic-gate static int 12520Sstevel@tonic-gate lxml_get_restarter(entity_t *entity, xmlNodePtr rstr) 12530Sstevel@tonic-gate { 12540Sstevel@tonic-gate pgroup_t *pg; 12550Sstevel@tonic-gate property_t *p; 12560Sstevel@tonic-gate xmlChar *restarter; 12570Sstevel@tonic-gate xmlNode *cursor; 12580Sstevel@tonic-gate int r; 12590Sstevel@tonic-gate 12600Sstevel@tonic-gate /* 12610Sstevel@tonic-gate * Go find child. Child is a service_fmri element. value attribute 12620Sstevel@tonic-gate * contains restarter FMRI. 12630Sstevel@tonic-gate */ 12640Sstevel@tonic-gate 12650Sstevel@tonic-gate pg = internal_pgroup_find_or_create(entity, (char *)scf_pg_general, 12660Sstevel@tonic-gate (char *)scf_group_framework); 12670Sstevel@tonic-gate 12680Sstevel@tonic-gate /* 12690Sstevel@tonic-gate * Walk its child elements, as appropriate. 12700Sstevel@tonic-gate */ 12710Sstevel@tonic-gate for (cursor = rstr->xmlChildrenNode; cursor != NULL; 12720Sstevel@tonic-gate cursor = cursor->next) { 12730Sstevel@tonic-gate if (lxml_ignorable_block(cursor)) 12740Sstevel@tonic-gate continue; 12750Sstevel@tonic-gate 12760Sstevel@tonic-gate switch (lxml_xlate_element(cursor->name)) { 12770Sstevel@tonic-gate case SC_SERVICE_FMRI: 12780Sstevel@tonic-gate restarter = xmlGetProp(cursor, (xmlChar *)value_attr); 12790Sstevel@tonic-gate break; 12800Sstevel@tonic-gate default: 12810Sstevel@tonic-gate uu_die(gettext("illegal element \"%s\" on restarter " 12820Sstevel@tonic-gate "element for \"%s\"\n"), cursor->name, 12830Sstevel@tonic-gate entity->sc_name); 12840Sstevel@tonic-gate break; 12850Sstevel@tonic-gate } 12860Sstevel@tonic-gate } 12870Sstevel@tonic-gate 12880Sstevel@tonic-gate p = internal_property_create(SCF_PROPERTY_RESTARTER, SCF_TYPE_FMRI, 1, 12890Sstevel@tonic-gate restarter); 12900Sstevel@tonic-gate 12910Sstevel@tonic-gate r = internal_attach_property(pg, p); 12920Sstevel@tonic-gate if (r != 0) { 12930Sstevel@tonic-gate internal_property_free(p); 12940Sstevel@tonic-gate return (-1); 12950Sstevel@tonic-gate } 12960Sstevel@tonic-gate 12970Sstevel@tonic-gate return (0); 12980Sstevel@tonic-gate } 12990Sstevel@tonic-gate 1300*7887SLiane.Praza@Sun.COM /* 1301*7887SLiane.Praza@Sun.COM * Add a property containing the localized text from the manifest. The 1302*7887SLiane.Praza@Sun.COM * property is added to the property group at pg. The name of the created 1303*7887SLiane.Praza@Sun.COM * property is based on the format at pn_format. This is an snprintf(3C) 1304*7887SLiane.Praza@Sun.COM * format containing a single %s conversion specification. At conversion 1305*7887SLiane.Praza@Sun.COM * time, the %s is replaced by the locale designation. 1306*7887SLiane.Praza@Sun.COM * 1307*7887SLiane.Praza@Sun.COM * source is the source element and it is only used for error messages. 1308*7887SLiane.Praza@Sun.COM */ 1309*7887SLiane.Praza@Sun.COM static int 1310*7887SLiane.Praza@Sun.COM lxml_get_loctext(entity_t *service, pgroup_t *pg, xmlNodePtr loctext, 1311*7887SLiane.Praza@Sun.COM const char *pn_format, const char *source) 13120Sstevel@tonic-gate { 1313*7887SLiane.Praza@Sun.COM int extra; 13140Sstevel@tonic-gate xmlNodePtr cursor; 13150Sstevel@tonic-gate xmlChar *val; 13160Sstevel@tonic-gate char *stripped, *cp; 13170Sstevel@tonic-gate property_t *p; 1318*7887SLiane.Praza@Sun.COM char *prop_name; 13190Sstevel@tonic-gate int r; 13200Sstevel@tonic-gate 1321*7887SLiane.Praza@Sun.COM if (((val = xmlGetProp(loctext, (xmlChar *)xml_lang_attr)) == NULL) || 1322*7887SLiane.Praza@Sun.COM (*val == 0)) { 1323*7887SLiane.Praza@Sun.COM if (((val = xmlGetProp(loctext, 1324*7887SLiane.Praza@Sun.COM (xmlChar *)lang_attr)) == NULL) || (*val == 0)) { 13250Sstevel@tonic-gate val = (xmlChar *)"unknown"; 1326*7887SLiane.Praza@Sun.COM } 1327*7887SLiane.Praza@Sun.COM } 1328*7887SLiane.Praza@Sun.COM 1329*7887SLiane.Praza@Sun.COM _scf_sanitize_locale((char *)val); 1330*7887SLiane.Praza@Sun.COM prop_name = safe_malloc(max_scf_name_len + 1); 1331*7887SLiane.Praza@Sun.COM if ((extra = snprintf(prop_name, max_scf_name_len + 1, pn_format, 1332*7887SLiane.Praza@Sun.COM val)) >= max_scf_name_len + 1) { 1333*7887SLiane.Praza@Sun.COM extra -= max_scf_name_len; 1334*7887SLiane.Praza@Sun.COM uu_die(gettext("%s attribute is %d characters too long for " 1335*7887SLiane.Praza@Sun.COM "%s in %s\n"), 1336*7887SLiane.Praza@Sun.COM xml_lang_attr, extra, source, service->sc_name); 1337*7887SLiane.Praza@Sun.COM } 1338*7887SLiane.Praza@Sun.COM xmlFree(val); 13390Sstevel@tonic-gate 13400Sstevel@tonic-gate for (cursor = loctext->xmlChildrenNode; cursor != NULL; 13410Sstevel@tonic-gate cursor = cursor->next) { 13420Sstevel@tonic-gate if (strcmp("text", (const char *)cursor->name) == 0) { 13430Sstevel@tonic-gate break; 13440Sstevel@tonic-gate } else if (strcmp("comment", (const char *)cursor->name) != 0) { 13450Sstevel@tonic-gate uu_die(gettext("illegal element \"%s\" on loctext " 13460Sstevel@tonic-gate "element for \"%s\"\n"), cursor->name, 13470Sstevel@tonic-gate service->sc_name); 13480Sstevel@tonic-gate } 13490Sstevel@tonic-gate } 13500Sstevel@tonic-gate 13510Sstevel@tonic-gate if (cursor == NULL) { 13520Sstevel@tonic-gate uu_die(gettext("loctext element has no content for \"%s\"\n"), 13530Sstevel@tonic-gate service->sc_name); 13540Sstevel@tonic-gate } 13550Sstevel@tonic-gate 13560Sstevel@tonic-gate /* 13570Sstevel@tonic-gate * Remove leading and trailing whitespace. 13580Sstevel@tonic-gate */ 13590Sstevel@tonic-gate if ((stripped = strdup((const char *)cursor->content)) == NULL) 13600Sstevel@tonic-gate uu_die(gettext("Out of memory\n")); 13610Sstevel@tonic-gate 13624740Sjeanm for (; isspace(*stripped); stripped++) 13634740Sjeanm ; 13644740Sjeanm for (cp = stripped + strlen(stripped) - 1; isspace(*cp); cp--) 13654740Sjeanm ; 13660Sstevel@tonic-gate *(cp + 1) = '\0'; 13670Sstevel@tonic-gate 1368*7887SLiane.Praza@Sun.COM p = internal_property_create(prop_name, SCF_TYPE_USTRING, 1, 13690Sstevel@tonic-gate stripped); 13700Sstevel@tonic-gate 13710Sstevel@tonic-gate r = internal_attach_property(pg, p); 1372*7887SLiane.Praza@Sun.COM if (r != 0) { 13730Sstevel@tonic-gate internal_property_free(p); 1374*7887SLiane.Praza@Sun.COM free(prop_name); 1375*7887SLiane.Praza@Sun.COM } 13760Sstevel@tonic-gate 13770Sstevel@tonic-gate return (r); 13780Sstevel@tonic-gate } 13790Sstevel@tonic-gate 1380*7887SLiane.Praza@Sun.COM /* 1381*7887SLiane.Praza@Sun.COM * This function processes all loctext elements in the current XML element 1382*7887SLiane.Praza@Sun.COM * designated by container. A property is created for each loctext element 1383*7887SLiane.Praza@Sun.COM * and added to the property group at pg. The name of the property is 1384*7887SLiane.Praza@Sun.COM * derived from the loctext language designation using the format at 1385*7887SLiane.Praza@Sun.COM * pn_format. pn_format should be an snprintf format string containing one 1386*7887SLiane.Praza@Sun.COM * %s which is replaced by the language designation. 1387*7887SLiane.Praza@Sun.COM * 1388*7887SLiane.Praza@Sun.COM * The function returns 0 on success and -1 if it is unable to attach the 1389*7887SLiane.Praza@Sun.COM * newly created property to pg. 1390*7887SLiane.Praza@Sun.COM */ 13910Sstevel@tonic-gate static int 1392*7887SLiane.Praza@Sun.COM lxml_get_all_loctext(entity_t *service, pgroup_t *pg, xmlNodePtr container, 1393*7887SLiane.Praza@Sun.COM const char *pn_format, const char *source) 13940Sstevel@tonic-gate { 13950Sstevel@tonic-gate xmlNodePtr cursor; 13960Sstevel@tonic-gate 13970Sstevel@tonic-gate /* 1398*7887SLiane.Praza@Sun.COM * Iterate through one or more loctext elements. The locale is 1399*7887SLiane.Praza@Sun.COM * used to generate the property name; the contents are the ustring 1400*7887SLiane.Praza@Sun.COM * value for the property. 14010Sstevel@tonic-gate */ 1402*7887SLiane.Praza@Sun.COM for (cursor = container->xmlChildrenNode; cursor != NULL; 14030Sstevel@tonic-gate cursor = cursor->next) { 14040Sstevel@tonic-gate if (lxml_ignorable_block(cursor)) 14050Sstevel@tonic-gate continue; 14060Sstevel@tonic-gate 14070Sstevel@tonic-gate switch (lxml_xlate_element(cursor->name)) { 14080Sstevel@tonic-gate case SC_LOCTEXT: 1409*7887SLiane.Praza@Sun.COM if (lxml_get_loctext(service, pg, cursor, pn_format, 1410*7887SLiane.Praza@Sun.COM source)) 14110Sstevel@tonic-gate return (-1); 14120Sstevel@tonic-gate break; 14130Sstevel@tonic-gate default: 1414*7887SLiane.Praza@Sun.COM uu_die(gettext("illegal element \"%s\" on %s element " 1415*7887SLiane.Praza@Sun.COM "for \"%s\"\n"), cursor->name, container->name, 14160Sstevel@tonic-gate service->sc_name); 14170Sstevel@tonic-gate break; 14180Sstevel@tonic-gate } 14190Sstevel@tonic-gate } 14200Sstevel@tonic-gate 14210Sstevel@tonic-gate return (0); 14220Sstevel@tonic-gate } 14230Sstevel@tonic-gate 1424*7887SLiane.Praza@Sun.COM /* 1425*7887SLiane.Praza@Sun.COM * Obtain the specified cardinality attribute and place it in a property 1426*7887SLiane.Praza@Sun.COM * named prop_name. The converted attribute is placed at *value, and the 1427*7887SLiane.Praza@Sun.COM * newly created property is returned to propp. NULL is returned to propp 1428*7887SLiane.Praza@Sun.COM * if the attribute is not provided in the manifest. 1429*7887SLiane.Praza@Sun.COM * 1430*7887SLiane.Praza@Sun.COM * 0 is returned upon success, and -1 indicates that the manifest contained 1431*7887SLiane.Praza@Sun.COM * an invalid cardinality value. 1432*7887SLiane.Praza@Sun.COM */ 14330Sstevel@tonic-gate static int 1434*7887SLiane.Praza@Sun.COM lxml_get_cardinality_attribute(entity_t *service, xmlNodePtr cursor, 1435*7887SLiane.Praza@Sun.COM const char *attr_name, const char *prop_name, uint64_t *value, 1436*7887SLiane.Praza@Sun.COM property_t **propp) 1437*7887SLiane.Praza@Sun.COM { 1438*7887SLiane.Praza@Sun.COM char *c; 1439*7887SLiane.Praza@Sun.COM property_t *p; 1440*7887SLiane.Praza@Sun.COM xmlChar *val; 1441*7887SLiane.Praza@Sun.COM uint64_t count; 1442*7887SLiane.Praza@Sun.COM char *endptr; 1443*7887SLiane.Praza@Sun.COM 1444*7887SLiane.Praza@Sun.COM *propp = NULL; 1445*7887SLiane.Praza@Sun.COM val = xmlGetProp(cursor, (xmlChar *)attr_name); 1446*7887SLiane.Praza@Sun.COM if (val == NULL) 1447*7887SLiane.Praza@Sun.COM return (0); 1448*7887SLiane.Praza@Sun.COM if (*val == 0) { 1449*7887SLiane.Praza@Sun.COM xmlFree(val); 1450*7887SLiane.Praza@Sun.COM return (0); 1451*7887SLiane.Praza@Sun.COM } 1452*7887SLiane.Praza@Sun.COM 1453*7887SLiane.Praza@Sun.COM /* 1454*7887SLiane.Praza@Sun.COM * Make sure that the string at val doesn't have a leading minus 1455*7887SLiane.Praza@Sun.COM * sign. The strtoull() call below does not catch this problem. 1456*7887SLiane.Praza@Sun.COM */ 1457*7887SLiane.Praza@Sun.COM for (c = (char *)val; *c != 0; c++) { 1458*7887SLiane.Praza@Sun.COM if (isspace(*c)) 1459*7887SLiane.Praza@Sun.COM continue; 1460*7887SLiane.Praza@Sun.COM if (isdigit(*c)) 1461*7887SLiane.Praza@Sun.COM break; 1462*7887SLiane.Praza@Sun.COM semerr(gettext("\"%c\" is not a legal character in the %s " 1463*7887SLiane.Praza@Sun.COM "attribute of the %s element in %s.\n"), *c, 1464*7887SLiane.Praza@Sun.COM attr_name, prop_name, service->sc_name); 1465*7887SLiane.Praza@Sun.COM xmlFree(val); 1466*7887SLiane.Praza@Sun.COM return (-1); 1467*7887SLiane.Praza@Sun.COM } 1468*7887SLiane.Praza@Sun.COM errno = 0; 1469*7887SLiane.Praza@Sun.COM count = strtoull((char *)val, &endptr, 10); 1470*7887SLiane.Praza@Sun.COM if (errno != 0 || endptr == (char *)val || *endptr) { 1471*7887SLiane.Praza@Sun.COM semerr(gettext("\"%s\" is not a legal number for the %s " 1472*7887SLiane.Praza@Sun.COM "attribute of the %s element in %s.\n"), (char *)val, 1473*7887SLiane.Praza@Sun.COM attr_name, prop_name, service->sc_name); 1474*7887SLiane.Praza@Sun.COM xmlFree(val); 1475*7887SLiane.Praza@Sun.COM return (-1); 1476*7887SLiane.Praza@Sun.COM } 1477*7887SLiane.Praza@Sun.COM 1478*7887SLiane.Praza@Sun.COM xmlFree(val); 1479*7887SLiane.Praza@Sun.COM 1480*7887SLiane.Praza@Sun.COM /* Value is valid. Create the property. */ 1481*7887SLiane.Praza@Sun.COM p = internal_property_create(prop_name, SCF_TYPE_COUNT, 1, count); 1482*7887SLiane.Praza@Sun.COM *value = count; 1483*7887SLiane.Praza@Sun.COM *propp = p; 1484*7887SLiane.Praza@Sun.COM return (0); 1485*7887SLiane.Praza@Sun.COM } 1486*7887SLiane.Praza@Sun.COM 1487*7887SLiane.Praza@Sun.COM /* 1488*7887SLiane.Praza@Sun.COM * The cardinality is specified by two attributes max and min at cursor. 1489*7887SLiane.Praza@Sun.COM * Both are optional, but if present they must be unsigned integers. 1490*7887SLiane.Praza@Sun.COM */ 1491*7887SLiane.Praza@Sun.COM static int 1492*7887SLiane.Praza@Sun.COM lxml_get_tm_cardinality(entity_t *service, pgroup_t *pg, xmlNodePtr cursor) 14930Sstevel@tonic-gate { 1494*7887SLiane.Praza@Sun.COM int min_attached = 0; 1495*7887SLiane.Praza@Sun.COM int compare = 1; 1496*7887SLiane.Praza@Sun.COM property_t *min_prop; 1497*7887SLiane.Praza@Sun.COM property_t *max_prop; 1498*7887SLiane.Praza@Sun.COM uint64_t max; 1499*7887SLiane.Praza@Sun.COM uint64_t min; 1500*7887SLiane.Praza@Sun.COM int r; 1501*7887SLiane.Praza@Sun.COM 1502*7887SLiane.Praza@Sun.COM r = lxml_get_cardinality_attribute(service, cursor, min_attr, 1503*7887SLiane.Praza@Sun.COM SCF_PROPERTY_TM_CARDINALITY_MIN, &min, &min_prop); 1504*7887SLiane.Praza@Sun.COM if (r != 0) 1505*7887SLiane.Praza@Sun.COM return (r); 1506*7887SLiane.Praza@Sun.COM if (min_prop == NULL) 1507*7887SLiane.Praza@Sun.COM compare = 0; 1508*7887SLiane.Praza@Sun.COM r = lxml_get_cardinality_attribute(service, cursor, max_attr, 1509*7887SLiane.Praza@Sun.COM SCF_PROPERTY_TM_CARDINALITY_MAX, &max, &max_prop); 1510*7887SLiane.Praza@Sun.COM if (r != 0) 1511*7887SLiane.Praza@Sun.COM goto errout; 1512*7887SLiane.Praza@Sun.COM if ((max_prop != NULL) && (compare == 1)) { 1513*7887SLiane.Praza@Sun.COM if (max < min) { 1514*7887SLiane.Praza@Sun.COM semerr(gettext("Cardinality max is less than min for " 1515*7887SLiane.Praza@Sun.COM "the %s element in %s.\n"), pg->sc_pgroup_name, 1516*7887SLiane.Praza@Sun.COM service->sc_fmri); 1517*7887SLiane.Praza@Sun.COM goto errout; 1518*7887SLiane.Praza@Sun.COM } 1519*7887SLiane.Praza@Sun.COM } 1520*7887SLiane.Praza@Sun.COM 1521*7887SLiane.Praza@Sun.COM /* Attach the properties to the property group. */ 1522*7887SLiane.Praza@Sun.COM if (min_prop) { 1523*7887SLiane.Praza@Sun.COM if (internal_attach_property(pg, min_prop) == 0) { 1524*7887SLiane.Praza@Sun.COM min_attached = 1; 1525*7887SLiane.Praza@Sun.COM } else { 1526*7887SLiane.Praza@Sun.COM goto errout; 1527*7887SLiane.Praza@Sun.COM } 1528*7887SLiane.Praza@Sun.COM } 1529*7887SLiane.Praza@Sun.COM if (max_prop) { 1530*7887SLiane.Praza@Sun.COM if (internal_attach_property(pg, max_prop) != 0) { 1531*7887SLiane.Praza@Sun.COM if (min_attached) 1532*7887SLiane.Praza@Sun.COM internal_detach_property(pg, min_prop); 1533*7887SLiane.Praza@Sun.COM goto errout; 1534*7887SLiane.Praza@Sun.COM } 1535*7887SLiane.Praza@Sun.COM } 1536*7887SLiane.Praza@Sun.COM return (0); 1537*7887SLiane.Praza@Sun.COM 1538*7887SLiane.Praza@Sun.COM errout: 1539*7887SLiane.Praza@Sun.COM if (min_prop) 1540*7887SLiane.Praza@Sun.COM internal_property_free(min_prop); 1541*7887SLiane.Praza@Sun.COM if (max_prop) 1542*7887SLiane.Praza@Sun.COM internal_property_free(max_prop); 1543*7887SLiane.Praza@Sun.COM return (-1); 1544*7887SLiane.Praza@Sun.COM } 1545*7887SLiane.Praza@Sun.COM 1546*7887SLiane.Praza@Sun.COM /* 1547*7887SLiane.Praza@Sun.COM * Get the common_name which is present as localized text at common_name in 1548*7887SLiane.Praza@Sun.COM * the manifest. The common_name is stored as the value of a property in 1549*7887SLiane.Praza@Sun.COM * the property group whose name is SCF_PG_TM_COMMON_NAME and type is 1550*7887SLiane.Praza@Sun.COM * SCF_GROUP_TEMPLATE. This property group will be created in service if 1551*7887SLiane.Praza@Sun.COM * it is not already there. 1552*7887SLiane.Praza@Sun.COM */ 1553*7887SLiane.Praza@Sun.COM static int 1554*7887SLiane.Praza@Sun.COM lxml_get_tm_common_name(entity_t *service, xmlNodePtr common_name) 1555*7887SLiane.Praza@Sun.COM { 15560Sstevel@tonic-gate pgroup_t *pg; 15570Sstevel@tonic-gate 15580Sstevel@tonic-gate /* 15590Sstevel@tonic-gate * Create the property group, if absent. 15600Sstevel@tonic-gate */ 1561*7887SLiane.Praza@Sun.COM pg = internal_pgroup_find_or_create(service, SCF_PG_TM_COMMON_NAME, 1562*7887SLiane.Praza@Sun.COM SCF_GROUP_TEMPLATE); 1563*7887SLiane.Praza@Sun.COM 1564*7887SLiane.Praza@Sun.COM return (lxml_get_all_loctext(service, pg, common_name, LOCALE_ONLY_FMT, 1565*7887SLiane.Praza@Sun.COM "common_name")); 1566*7887SLiane.Praza@Sun.COM } 1567*7887SLiane.Praza@Sun.COM 1568*7887SLiane.Praza@Sun.COM /* 1569*7887SLiane.Praza@Sun.COM * Get the description which is present as localized text at description in 1570*7887SLiane.Praza@Sun.COM * the manifest. The description is stored as the value of a property in 1571*7887SLiane.Praza@Sun.COM * the property group whose name is SCF_PG_TM_DESCRIPTION and type is 1572*7887SLiane.Praza@Sun.COM * SCF_GROUP_TEMPLATE. This property group will be created in service if 1573*7887SLiane.Praza@Sun.COM * it is not already there. 1574*7887SLiane.Praza@Sun.COM */ 1575*7887SLiane.Praza@Sun.COM static int 1576*7887SLiane.Praza@Sun.COM lxml_get_tm_description(entity_t *service, xmlNodePtr description) 1577*7887SLiane.Praza@Sun.COM { 1578*7887SLiane.Praza@Sun.COM pgroup_t *pg; 15790Sstevel@tonic-gate 15800Sstevel@tonic-gate /* 1581*7887SLiane.Praza@Sun.COM * Create the property group, if absent. 15820Sstevel@tonic-gate */ 1583*7887SLiane.Praza@Sun.COM pg = internal_pgroup_find_or_create(service, SCF_PG_TM_DESCRIPTION, 1584*7887SLiane.Praza@Sun.COM SCF_GROUP_TEMPLATE); 1585*7887SLiane.Praza@Sun.COM 1586*7887SLiane.Praza@Sun.COM return (lxml_get_all_loctext(service, pg, description, 1587*7887SLiane.Praza@Sun.COM LOCALE_ONLY_FMT, "description")); 15880Sstevel@tonic-gate } 15890Sstevel@tonic-gate 15900Sstevel@tonic-gate static char * 15910Sstevel@tonic-gate lxml_label_to_groupname(const char *prefix, const char *in) 15920Sstevel@tonic-gate { 15930Sstevel@tonic-gate char *out, *cp; 15940Sstevel@tonic-gate size_t len, piece_len; 15950Sstevel@tonic-gate 15960Sstevel@tonic-gate out = uu_zalloc(2 * scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) + 1); 15970Sstevel@tonic-gate if (out == NULL) 15980Sstevel@tonic-gate return (NULL); 15990Sstevel@tonic-gate 16000Sstevel@tonic-gate (void) strcpy(out, prefix); 16010Sstevel@tonic-gate (void) strcat(out, in); 16020Sstevel@tonic-gate 16030Sstevel@tonic-gate len = strlen(out); 16040Sstevel@tonic-gate if (len > max_scf_name_len) { 16050Sstevel@tonic-gate /* Use the first half and the second half. */ 16060Sstevel@tonic-gate piece_len = (max_scf_name_len - 2) / 2; 16070Sstevel@tonic-gate 16080Sstevel@tonic-gate (void) strncpy(out + piece_len, "..", 2); 16090Sstevel@tonic-gate 16100Sstevel@tonic-gate (void) strcpy(out + piece_len + 2, out + (len - piece_len)); 16110Sstevel@tonic-gate 16120Sstevel@tonic-gate len = strlen(out); 16130Sstevel@tonic-gate } 16140Sstevel@tonic-gate 16150Sstevel@tonic-gate /* 16160Sstevel@tonic-gate * Translate non-property characters to '_'. 16170Sstevel@tonic-gate */ 16180Sstevel@tonic-gate for (cp = out; *cp != '\0'; ++cp) { 16190Sstevel@tonic-gate if (!(isalnum(*cp) || *cp == '_' || *cp == '-')) 16200Sstevel@tonic-gate *cp = '_'; 16210Sstevel@tonic-gate } 16220Sstevel@tonic-gate 16230Sstevel@tonic-gate *cp = '\0'; 16240Sstevel@tonic-gate 16250Sstevel@tonic-gate return (out); 16260Sstevel@tonic-gate } 16270Sstevel@tonic-gate 1628*7887SLiane.Praza@Sun.COM /* 1629*7887SLiane.Praza@Sun.COM * If *p is NULL, astring_prop_value() first creates a property with the 1630*7887SLiane.Praza@Sun.COM * name specified in prop_name. The address of the newly created property 1631*7887SLiane.Praza@Sun.COM * is placed in *p. 1632*7887SLiane.Praza@Sun.COM * 1633*7887SLiane.Praza@Sun.COM * In either case, newly created property or existing property, a new 1634*7887SLiane.Praza@Sun.COM * SCF_TYPE_ASTRING value will created and attached to the property at *p. 1635*7887SLiane.Praza@Sun.COM * The value of the newly created property is prop_value. 1636*7887SLiane.Praza@Sun.COM * 1637*7887SLiane.Praza@Sun.COM * free_flag is used to indicate whether or not the memory at prop_value 1638*7887SLiane.Praza@Sun.COM * should be freed when the property is freed by a call to 1639*7887SLiane.Praza@Sun.COM * internal_property_free(). 1640*7887SLiane.Praza@Sun.COM */ 1641*7887SLiane.Praza@Sun.COM static void 1642*7887SLiane.Praza@Sun.COM astring_prop_value(property_t **p, const char *prop_name, char *prop_value, 1643*7887SLiane.Praza@Sun.COM boolean_t free_flag) 1644*7887SLiane.Praza@Sun.COM { 1645*7887SLiane.Praza@Sun.COM value_t *v; 1646*7887SLiane.Praza@Sun.COM 1647*7887SLiane.Praza@Sun.COM if (*p == NULL) { 1648*7887SLiane.Praza@Sun.COM /* Create the property */ 1649*7887SLiane.Praza@Sun.COM *p = internal_property_new(); 1650*7887SLiane.Praza@Sun.COM (*p)->sc_property_name = (char *)prop_name; 1651*7887SLiane.Praza@Sun.COM (*p)->sc_value_type = SCF_TYPE_ASTRING; 1652*7887SLiane.Praza@Sun.COM } 1653*7887SLiane.Praza@Sun.COM 1654*7887SLiane.Praza@Sun.COM /* Add the property value to the property's list of values. */ 1655*7887SLiane.Praza@Sun.COM v = internal_value_new(); 1656*7887SLiane.Praza@Sun.COM v->sc_type = SCF_TYPE_ASTRING; 1657*7887SLiane.Praza@Sun.COM if (free_flag == B_TRUE) 1658*7887SLiane.Praza@Sun.COM v->sc_free = lxml_free_str; 1659*7887SLiane.Praza@Sun.COM v->sc_u.sc_string = prop_value; 1660*7887SLiane.Praza@Sun.COM internal_attach_value(*p, v); 1661*7887SLiane.Praza@Sun.COM } 1662*7887SLiane.Praza@Sun.COM 1663*7887SLiane.Praza@Sun.COM /* 1664*7887SLiane.Praza@Sun.COM * If p points to a null pointer, create an internal_separators property 1665*7887SLiane.Praza@Sun.COM * saving the address at p. For each character at seps create a property 1666*7887SLiane.Praza@Sun.COM * value and attach it to the property at p. 1667*7887SLiane.Praza@Sun.COM */ 1668*7887SLiane.Praza@Sun.COM static void 1669*7887SLiane.Praza@Sun.COM seps_to_prop_values(property_t **p, xmlChar *seps) 1670*7887SLiane.Praza@Sun.COM { 1671*7887SLiane.Praza@Sun.COM value_t *v; 1672*7887SLiane.Praza@Sun.COM char val_str[2]; 1673*7887SLiane.Praza@Sun.COM 1674*7887SLiane.Praza@Sun.COM if (*p == NULL) { 1675*7887SLiane.Praza@Sun.COM *p = internal_property_new(); 1676*7887SLiane.Praza@Sun.COM (*p)->sc_property_name = 1677*7887SLiane.Praza@Sun.COM (char *)SCF_PROPERTY_INTERNAL_SEPARATORS; 1678*7887SLiane.Praza@Sun.COM (*p)->sc_value_type = SCF_TYPE_ASTRING; 1679*7887SLiane.Praza@Sun.COM } 1680*7887SLiane.Praza@Sun.COM 1681*7887SLiane.Praza@Sun.COM /* Add the values to the property's list. */ 1682*7887SLiane.Praza@Sun.COM val_str[1] = 0; /* Terminate the string. */ 1683*7887SLiane.Praza@Sun.COM for (; *seps != 0; seps++) { 1684*7887SLiane.Praza@Sun.COM v = internal_value_new(); 1685*7887SLiane.Praza@Sun.COM v->sc_type = (*p)->sc_value_type; 1686*7887SLiane.Praza@Sun.COM v->sc_free = lxml_free_str; 1687*7887SLiane.Praza@Sun.COM val_str[0] = *seps; 1688*7887SLiane.Praza@Sun.COM v->sc_u.sc_string = strdup(val_str); 1689*7887SLiane.Praza@Sun.COM if (v->sc_u.sc_string == NULL) 1690*7887SLiane.Praza@Sun.COM uu_die(gettext("Out of memory\n")); 1691*7887SLiane.Praza@Sun.COM internal_attach_value(*p, v); 1692*7887SLiane.Praza@Sun.COM } 1693*7887SLiane.Praza@Sun.COM } 1694*7887SLiane.Praza@Sun.COM 1695*7887SLiane.Praza@Sun.COM /* 1696*7887SLiane.Praza@Sun.COM * Create an internal_separators property and attach it to the property 1697*7887SLiane.Praza@Sun.COM * group at pg. The separator characters are provided in the text nodes 1698*7887SLiane.Praza@Sun.COM * that are the children of seps. Each separator character is stored as a 1699*7887SLiane.Praza@Sun.COM * property value in the internal_separators property. 1700*7887SLiane.Praza@Sun.COM */ 1701*7887SLiane.Praza@Sun.COM static int 1702*7887SLiane.Praza@Sun.COM lxml_get_tm_internal_seps(entity_t *service, pgroup_t *pg, xmlNodePtr seps) 1703*7887SLiane.Praza@Sun.COM { 1704*7887SLiane.Praza@Sun.COM xmlNodePtr cursor; 1705*7887SLiane.Praza@Sun.COM property_t *prop = NULL; 1706*7887SLiane.Praza@Sun.COM int r; 1707*7887SLiane.Praza@Sun.COM 1708*7887SLiane.Praza@Sun.COM for (cursor = seps->xmlChildrenNode; cursor != NULL; 1709*7887SLiane.Praza@Sun.COM cursor = cursor->next) { 1710*7887SLiane.Praza@Sun.COM if (strcmp("text", (const char *)cursor->name) == 0) { 1711*7887SLiane.Praza@Sun.COM seps_to_prop_values(&prop, cursor->content); 1712*7887SLiane.Praza@Sun.COM } else if (strcmp("comment", (const char *)cursor->name) != 0) { 1713*7887SLiane.Praza@Sun.COM uu_die(gettext("illegal element \"%s\" on %s element " 1714*7887SLiane.Praza@Sun.COM "for \"%s\"\n"), cursor->name, seps->name, 1715*7887SLiane.Praza@Sun.COM service->sc_name); 1716*7887SLiane.Praza@Sun.COM } 1717*7887SLiane.Praza@Sun.COM } 1718*7887SLiane.Praza@Sun.COM if (prop == NULL) { 1719*7887SLiane.Praza@Sun.COM semerr(gettext("The %s element in %s had an empty list of " 1720*7887SLiane.Praza@Sun.COM "separators.\n"), (const char *)seps->name, 1721*7887SLiane.Praza@Sun.COM service->sc_name); 1722*7887SLiane.Praza@Sun.COM return (-1); 1723*7887SLiane.Praza@Sun.COM } 1724*7887SLiane.Praza@Sun.COM r = internal_attach_property(pg, prop); 1725*7887SLiane.Praza@Sun.COM if (r != 0) 1726*7887SLiane.Praza@Sun.COM internal_property_free(prop); 1727*7887SLiane.Praza@Sun.COM return (r); 1728*7887SLiane.Praza@Sun.COM } 1729*7887SLiane.Praza@Sun.COM 17300Sstevel@tonic-gate static int 17310Sstevel@tonic-gate lxml_get_tm_manpage(entity_t *service, xmlNodePtr manpage) 17320Sstevel@tonic-gate { 17330Sstevel@tonic-gate pgroup_t *pg; 17340Sstevel@tonic-gate char *pgname; 17350Sstevel@tonic-gate xmlChar *title; 17360Sstevel@tonic-gate 17370Sstevel@tonic-gate /* 17380Sstevel@tonic-gate * Fetch title attribute, convert to something sanitized, and create 17390Sstevel@tonic-gate * property group. 17400Sstevel@tonic-gate */ 1741*7887SLiane.Praza@Sun.COM title = xmlGetProp(manpage, (xmlChar *)title_attr); 17420Sstevel@tonic-gate pgname = (char *)lxml_label_to_groupname(SCF_PG_TM_MAN_PREFIX, 17430Sstevel@tonic-gate (const char *)title); 1744*7887SLiane.Praza@Sun.COM xmlFree(title); 17450Sstevel@tonic-gate 17460Sstevel@tonic-gate pg = internal_pgroup_find_or_create(service, pgname, 17470Sstevel@tonic-gate (char *)SCF_GROUP_TEMPLATE); 17480Sstevel@tonic-gate 17490Sstevel@tonic-gate /* 17500Sstevel@tonic-gate * Each attribute is an astring property within the group. 17510Sstevel@tonic-gate */ 1752*7887SLiane.Praza@Sun.COM if (new_str_prop_from_attr(pg, SCF_PROPERTY_TM_TITLE, 1753*7887SLiane.Praza@Sun.COM SCF_TYPE_ASTRING, manpage, title_attr) != 0 || 1754*7887SLiane.Praza@Sun.COM new_str_prop_from_attr(pg, SCF_PROPERTY_TM_SECTION, 1755*7887SLiane.Praza@Sun.COM SCF_TYPE_ASTRING, manpage, section_attr) != 0 || 1756*7887SLiane.Praza@Sun.COM new_str_prop_from_attr(pg, SCF_PROPERTY_TM_MANPATH, 1757*7887SLiane.Praza@Sun.COM SCF_TYPE_ASTRING, manpage, manpath_attr) != 0) 17580Sstevel@tonic-gate return (-1); 17590Sstevel@tonic-gate 17600Sstevel@tonic-gate return (0); 17610Sstevel@tonic-gate } 17620Sstevel@tonic-gate 17630Sstevel@tonic-gate static int 17640Sstevel@tonic-gate lxml_get_tm_doclink(entity_t *service, xmlNodePtr doc_link) 17650Sstevel@tonic-gate { 17660Sstevel@tonic-gate pgroup_t *pg; 17670Sstevel@tonic-gate char *pgname; 17680Sstevel@tonic-gate xmlChar *name; 17690Sstevel@tonic-gate 17700Sstevel@tonic-gate /* 17710Sstevel@tonic-gate * Fetch name attribute, convert name to something sanitized, and create 17720Sstevel@tonic-gate * property group. 17730Sstevel@tonic-gate */ 1774*7887SLiane.Praza@Sun.COM name = xmlGetProp(doc_link, (xmlChar *)name_attr); 17750Sstevel@tonic-gate 17760Sstevel@tonic-gate pgname = (char *)lxml_label_to_groupname(SCF_PG_TM_DOC_PREFIX, 17770Sstevel@tonic-gate (const char *)name); 17780Sstevel@tonic-gate 17790Sstevel@tonic-gate pg = internal_pgroup_find_or_create(service, pgname, 17800Sstevel@tonic-gate (char *)SCF_GROUP_TEMPLATE); 1781*7887SLiane.Praza@Sun.COM xmlFree(name); 17820Sstevel@tonic-gate 17830Sstevel@tonic-gate /* 17840Sstevel@tonic-gate * Each attribute is an astring property within the group. 17850Sstevel@tonic-gate */ 1786*7887SLiane.Praza@Sun.COM if (new_str_prop_from_attr(pg, SCF_PROPERTY_TM_NAME, SCF_TYPE_ASTRING, 1787*7887SLiane.Praza@Sun.COM doc_link, name_attr) != 0 || 1788*7887SLiane.Praza@Sun.COM new_str_prop_from_attr(pg, SCF_PROPERTY_TM_URI, SCF_TYPE_ASTRING, 1789*7887SLiane.Praza@Sun.COM doc_link, uri_attr) != 0) 17900Sstevel@tonic-gate return (-1); 17910Sstevel@tonic-gate 17920Sstevel@tonic-gate return (0); 17930Sstevel@tonic-gate } 17940Sstevel@tonic-gate 17950Sstevel@tonic-gate static int 17960Sstevel@tonic-gate lxml_get_tm_documentation(entity_t *service, xmlNodePtr documentation) 17970Sstevel@tonic-gate { 17980Sstevel@tonic-gate xmlNodePtr cursor; 17990Sstevel@tonic-gate 18000Sstevel@tonic-gate for (cursor = documentation->xmlChildrenNode; cursor != NULL; 18010Sstevel@tonic-gate cursor = cursor->next) { 18020Sstevel@tonic-gate if (lxml_ignorable_block(cursor)) 18030Sstevel@tonic-gate continue; 18040Sstevel@tonic-gate 18050Sstevel@tonic-gate switch (lxml_xlate_element(cursor->name)) { 18060Sstevel@tonic-gate case SC_MANPAGE: 18070Sstevel@tonic-gate (void) lxml_get_tm_manpage(service, cursor); 18080Sstevel@tonic-gate break; 18090Sstevel@tonic-gate case SC_DOC_LINK: 18100Sstevel@tonic-gate (void) lxml_get_tm_doclink(service, cursor); 18110Sstevel@tonic-gate break; 18120Sstevel@tonic-gate default: 18130Sstevel@tonic-gate uu_die(gettext("illegal element \"%s\" on template " 18140Sstevel@tonic-gate "for service \"%s\"\n"), 18150Sstevel@tonic-gate cursor->name, service->sc_name); 18160Sstevel@tonic-gate } 18170Sstevel@tonic-gate } 18180Sstevel@tonic-gate 18190Sstevel@tonic-gate return (0); 18200Sstevel@tonic-gate } 18210Sstevel@tonic-gate 18220Sstevel@tonic-gate static int 1823*7887SLiane.Praza@Sun.COM lxml_get_prop_pattern_attributes(pgroup_t *pg, xmlNodePtr cursor) 1824*7887SLiane.Praza@Sun.COM { 1825*7887SLiane.Praza@Sun.COM if (new_opt_str_prop_from_attr(pg, SCF_PROPERTY_TM_NAME, 1826*7887SLiane.Praza@Sun.COM SCF_TYPE_ASTRING, cursor, name_attr, NULL) != 0) { 1827*7887SLiane.Praza@Sun.COM return (-1); 1828*7887SLiane.Praza@Sun.COM } 1829*7887SLiane.Praza@Sun.COM if (new_opt_str_prop_from_attr(pg, SCF_PROPERTY_TM_TYPE, 1830*7887SLiane.Praza@Sun.COM SCF_TYPE_ASTRING, cursor, type_attr, "") != 0) { 1831*7887SLiane.Praza@Sun.COM return (-1); 1832*7887SLiane.Praza@Sun.COM } 1833*7887SLiane.Praza@Sun.COM if (new_bool_prop_from_attr(pg, SCF_PROPERTY_TM_REQUIRED, cursor, 1834*7887SLiane.Praza@Sun.COM required_attr) != 0) 1835*7887SLiane.Praza@Sun.COM return (-1); 1836*7887SLiane.Praza@Sun.COM return (0); 1837*7887SLiane.Praza@Sun.COM } 1838*7887SLiane.Praza@Sun.COM 1839*7887SLiane.Praza@Sun.COM static int 1840*7887SLiane.Praza@Sun.COM lxml_get_tm_include_values(entity_t *service, pgroup_t *pg, 1841*7887SLiane.Praza@Sun.COM xmlNodePtr include_values, const char *prop_name) 1842*7887SLiane.Praza@Sun.COM { 1843*7887SLiane.Praza@Sun.COM boolean_t attach_to_pg = B_FALSE; 1844*7887SLiane.Praza@Sun.COM property_t *p; 1845*7887SLiane.Praza@Sun.COM int r = 0; 1846*7887SLiane.Praza@Sun.COM char *type; 1847*7887SLiane.Praza@Sun.COM 1848*7887SLiane.Praza@Sun.COM /* Get the type attribute of the include_values element. */ 1849*7887SLiane.Praza@Sun.COM type = (char *)xmlGetProp(include_values, (const xmlChar *)type_attr); 1850*7887SLiane.Praza@Sun.COM if ((type == NULL) || (*type == 0)) { 1851*7887SLiane.Praza@Sun.COM uu_die(gettext("%s element requires a %s attribute in the %s " 1852*7887SLiane.Praza@Sun.COM "service.\n"), include_values->name, type_attr, 1853*7887SLiane.Praza@Sun.COM service->sc_name); 1854*7887SLiane.Praza@Sun.COM } 1855*7887SLiane.Praza@Sun.COM 1856*7887SLiane.Praza@Sun.COM /* Add the type to the values of the prop_name property. */ 1857*7887SLiane.Praza@Sun.COM p = internal_property_find(pg, prop_name); 1858*7887SLiane.Praza@Sun.COM if (p == NULL) 1859*7887SLiane.Praza@Sun.COM attach_to_pg = B_TRUE; 1860*7887SLiane.Praza@Sun.COM astring_prop_value(&p, prop_name, type, B_FALSE); 1861*7887SLiane.Praza@Sun.COM if (attach_to_pg == B_TRUE) { 1862*7887SLiane.Praza@Sun.COM r = internal_attach_property(pg, p); 1863*7887SLiane.Praza@Sun.COM if (r != 0) 1864*7887SLiane.Praza@Sun.COM internal_property_free(p); 1865*7887SLiane.Praza@Sun.COM } 1866*7887SLiane.Praza@Sun.COM return (r); 1867*7887SLiane.Praza@Sun.COM } 1868*7887SLiane.Praza@Sun.COM 1869*7887SLiane.Praza@Sun.COM #define RC_MIN 0 1870*7887SLiane.Praza@Sun.COM #define RC_MAX 1 1871*7887SLiane.Praza@Sun.COM #define RC_COUNT 2 1872*7887SLiane.Praza@Sun.COM 1873*7887SLiane.Praza@Sun.COM /* 1874*7887SLiane.Praza@Sun.COM * Verify that the strings at min and max are valid numeric strings. Also 1875*7887SLiane.Praza@Sun.COM * verify that max is numerically >= min. 1876*7887SLiane.Praza@Sun.COM * 1877*7887SLiane.Praza@Sun.COM * 0 is returned if the range is valid, and -1 is returned if it is not. 1878*7887SLiane.Praza@Sun.COM */ 1879*7887SLiane.Praza@Sun.COM static int 1880*7887SLiane.Praza@Sun.COM verify_range(entity_t *service, xmlNodePtr range, char *min, char *max) 1881*7887SLiane.Praza@Sun.COM { 1882*7887SLiane.Praza@Sun.COM char *c; 1883*7887SLiane.Praza@Sun.COM int i; 1884*7887SLiane.Praza@Sun.COM int is_signed = 0; 1885*7887SLiane.Praza@Sun.COM int inverted = 0; 1886*7887SLiane.Praza@Sun.COM const char *limit[RC_COUNT]; 1887*7887SLiane.Praza@Sun.COM char *strings[RC_COUNT]; 1888*7887SLiane.Praza@Sun.COM uint64_t urange[RC_COUNT]; /* unsigned range. */ 1889*7887SLiane.Praza@Sun.COM int64_t srange[RC_COUNT]; /* signed range. */ 1890*7887SLiane.Praza@Sun.COM 1891*7887SLiane.Praza@Sun.COM strings[RC_MIN] = min; 1892*7887SLiane.Praza@Sun.COM strings[RC_MAX] = max; 1893*7887SLiane.Praza@Sun.COM limit[RC_MIN] = min_attr; 1894*7887SLiane.Praza@Sun.COM limit[RC_MAX] = max_attr; 1895*7887SLiane.Praza@Sun.COM 1896*7887SLiane.Praza@Sun.COM /* See if the range is signed. */ 1897*7887SLiane.Praza@Sun.COM for (i = 0; (i < RC_COUNT) && (is_signed == 0); i++) { 1898*7887SLiane.Praza@Sun.COM c = strings[i]; 1899*7887SLiane.Praza@Sun.COM while (isspace(*c)) { 1900*7887SLiane.Praza@Sun.COM c++; 1901*7887SLiane.Praza@Sun.COM } 1902*7887SLiane.Praza@Sun.COM if (*c == '-') 1903*7887SLiane.Praza@Sun.COM is_signed = 1; 1904*7887SLiane.Praza@Sun.COM } 1905*7887SLiane.Praza@Sun.COM 1906*7887SLiane.Praza@Sun.COM /* Attempt to convert the strings. */ 1907*7887SLiane.Praza@Sun.COM for (i = 0; i < RC_COUNT; i++) { 1908*7887SLiane.Praza@Sun.COM errno = 0; 1909*7887SLiane.Praza@Sun.COM if (is_signed) { 1910*7887SLiane.Praza@Sun.COM srange[i] = strtoll(strings[i], &c, 0); 1911*7887SLiane.Praza@Sun.COM } else { 1912*7887SLiane.Praza@Sun.COM urange[i] = strtoull(strings[i], &c, 0); 1913*7887SLiane.Praza@Sun.COM } 1914*7887SLiane.Praza@Sun.COM if ((errno != 0) || (c == strings[i]) || (*c != 0)) { 1915*7887SLiane.Praza@Sun.COM /* Conversion failed. */ 1916*7887SLiane.Praza@Sun.COM uu_die(gettext("Unable to convert %s for the %s " 1917*7887SLiane.Praza@Sun.COM "element in service %s.\n"), limit[i], 1918*7887SLiane.Praza@Sun.COM (char *)range->name, service->sc_name); 1919*7887SLiane.Praza@Sun.COM } 1920*7887SLiane.Praza@Sun.COM } 1921*7887SLiane.Praza@Sun.COM 1922*7887SLiane.Praza@Sun.COM /* Make sure that min is <= max */ 1923*7887SLiane.Praza@Sun.COM if (is_signed) { 1924*7887SLiane.Praza@Sun.COM if (srange[RC_MAX] < srange[RC_MIN]) 1925*7887SLiane.Praza@Sun.COM inverted = 1; 1926*7887SLiane.Praza@Sun.COM } else { 1927*7887SLiane.Praza@Sun.COM if (urange[RC_MAX] < urange[RC_MIN]) 1928*7887SLiane.Praza@Sun.COM inverted = 1; 1929*7887SLiane.Praza@Sun.COM } 1930*7887SLiane.Praza@Sun.COM if (inverted != 0) { 1931*7887SLiane.Praza@Sun.COM semerr(gettext("Maximum less than minimum for the %s element " 1932*7887SLiane.Praza@Sun.COM "in service %s.\n"), (char *)range->name, 1933*7887SLiane.Praza@Sun.COM service->sc_name); 1934*7887SLiane.Praza@Sun.COM return (-1); 1935*7887SLiane.Praza@Sun.COM } 1936*7887SLiane.Praza@Sun.COM 1937*7887SLiane.Praza@Sun.COM return (0); 1938*7887SLiane.Praza@Sun.COM } 1939*7887SLiane.Praza@Sun.COM 1940*7887SLiane.Praza@Sun.COM /* 1941*7887SLiane.Praza@Sun.COM * This, function creates a property named prop_name. The range element 1942*7887SLiane.Praza@Sun.COM * should have two attributes -- min and max. The property value then 1943*7887SLiane.Praza@Sun.COM * becomes the concatenation of their value separated by a comma. The 1944*7887SLiane.Praza@Sun.COM * property is then attached to the property group at pg. 1945*7887SLiane.Praza@Sun.COM * 1946*7887SLiane.Praza@Sun.COM * If pg already contains a property with a name of prop_name, it is only 1947*7887SLiane.Praza@Sun.COM * necessary to create a new value and attach it to the existing property. 1948*7887SLiane.Praza@Sun.COM */ 1949*7887SLiane.Praza@Sun.COM static int 1950*7887SLiane.Praza@Sun.COM lxml_get_tm_range(entity_t *service, pgroup_t *pg, xmlNodePtr range, 1951*7887SLiane.Praza@Sun.COM const char *prop_name) 1952*7887SLiane.Praza@Sun.COM { 1953*7887SLiane.Praza@Sun.COM boolean_t attach_to_pg = B_FALSE; 1954*7887SLiane.Praza@Sun.COM char *max; 1955*7887SLiane.Praza@Sun.COM char *min; 1956*7887SLiane.Praza@Sun.COM property_t *p; 1957*7887SLiane.Praza@Sun.COM char *prop_value; 1958*7887SLiane.Praza@Sun.COM int r = 0; 1959*7887SLiane.Praza@Sun.COM 1960*7887SLiane.Praza@Sun.COM /* Get max and min from the XML description. */ 1961*7887SLiane.Praza@Sun.COM max = (char *)xmlGetProp(range, (xmlChar *)max_attr); 1962*7887SLiane.Praza@Sun.COM if ((max == NULL) || (*max == 0)) { 1963*7887SLiane.Praza@Sun.COM uu_die(gettext("%s element is missing the %s attribute in " 1964*7887SLiane.Praza@Sun.COM "service %s.\n"), (char *)range->name, max_attr, 1965*7887SLiane.Praza@Sun.COM service->sc_name); 1966*7887SLiane.Praza@Sun.COM } 1967*7887SLiane.Praza@Sun.COM min = (char *)xmlGetProp(range, (xmlChar *)min_attr); 1968*7887SLiane.Praza@Sun.COM if ((min == NULL) || (*min == 0)) { 1969*7887SLiane.Praza@Sun.COM uu_die(gettext("%s element is missing the %s attribute in " 1970*7887SLiane.Praza@Sun.COM "service %s.\n"), (char *)range->name, min_attr, 1971*7887SLiane.Praza@Sun.COM service->sc_name); 1972*7887SLiane.Praza@Sun.COM } 1973*7887SLiane.Praza@Sun.COM if (verify_range(service, range, min, max) != 0) { 1974*7887SLiane.Praza@Sun.COM xmlFree(min); 1975*7887SLiane.Praza@Sun.COM xmlFree(max); 1976*7887SLiane.Praza@Sun.COM return (-1); 1977*7887SLiane.Praza@Sun.COM } 1978*7887SLiane.Praza@Sun.COM 1979*7887SLiane.Praza@Sun.COM /* Property value is concatenation of min and max. */ 1980*7887SLiane.Praza@Sun.COM prop_value = safe_malloc(max_scf_value_len + 1); 1981*7887SLiane.Praza@Sun.COM if (snprintf(prop_value, max_scf_value_len + 1, "%s,%s", min, max) >= 1982*7887SLiane.Praza@Sun.COM max_scf_value_len + 1) { 1983*7887SLiane.Praza@Sun.COM uu_die(gettext("min and max are too long for the %s element " 1984*7887SLiane.Praza@Sun.COM "of %s.\n"), (char *)range->name, service->sc_name); 1985*7887SLiane.Praza@Sun.COM } 1986*7887SLiane.Praza@Sun.COM xmlFree(min); 1987*7887SLiane.Praza@Sun.COM xmlFree(max); 1988*7887SLiane.Praza@Sun.COM 1989*7887SLiane.Praza@Sun.COM /* 1990*7887SLiane.Praza@Sun.COM * If necessary create the property and attach it to the property 1991*7887SLiane.Praza@Sun.COM * group. 1992*7887SLiane.Praza@Sun.COM */ 1993*7887SLiane.Praza@Sun.COM p = internal_property_find(pg, prop_name); 1994*7887SLiane.Praza@Sun.COM if (p == NULL) 1995*7887SLiane.Praza@Sun.COM attach_to_pg = B_TRUE; 1996*7887SLiane.Praza@Sun.COM astring_prop_value(&p, prop_name, prop_value, B_TRUE); 1997*7887SLiane.Praza@Sun.COM if (attach_to_pg == B_TRUE) { 1998*7887SLiane.Praza@Sun.COM r = internal_attach_property(pg, p); 1999*7887SLiane.Praza@Sun.COM if (r != 0) { 2000*7887SLiane.Praza@Sun.COM internal_property_free(p); 2001*7887SLiane.Praza@Sun.COM } 2002*7887SLiane.Praza@Sun.COM } 2003*7887SLiane.Praza@Sun.COM return (r); 2004*7887SLiane.Praza@Sun.COM } 2005*7887SLiane.Praza@Sun.COM 2006*7887SLiane.Praza@Sun.COM /* 2007*7887SLiane.Praza@Sun.COM * Determine how many plain characters are represented by count Base32 2008*7887SLiane.Praza@Sun.COM * encoded characters. 5 plain text characters are converted to 8 Base32 2009*7887SLiane.Praza@Sun.COM * characters. 2010*7887SLiane.Praza@Sun.COM */ 2011*7887SLiane.Praza@Sun.COM static size_t 2012*7887SLiane.Praza@Sun.COM encoded_count_to_plain(size_t count) 2013*7887SLiane.Praza@Sun.COM { 2014*7887SLiane.Praza@Sun.COM return (5 * ((count + 7) / 8)); 2015*7887SLiane.Praza@Sun.COM } 2016*7887SLiane.Praza@Sun.COM 2017*7887SLiane.Praza@Sun.COM /* 2018*7887SLiane.Praza@Sun.COM * The value element contains 0 or 1 common_name element followed by 0 or 1 2019*7887SLiane.Praza@Sun.COM * description element. It also has a required attribute called "name". 2020*7887SLiane.Praza@Sun.COM * The common_name and description are stored as property values in pg. 2021*7887SLiane.Praza@Sun.COM * The property names are: 2022*7887SLiane.Praza@Sun.COM * value_<name>_common_name_<lang> 2023*7887SLiane.Praza@Sun.COM * value_<name>_description_<lang> 2024*7887SLiane.Praza@Sun.COM * 2025*7887SLiane.Praza@Sun.COM * The <name> portion of the preceeding proper names requires more 2026*7887SLiane.Praza@Sun.COM * explanation. Ideally it would just the name attribute of this value 2027*7887SLiane.Praza@Sun.COM * element. Unfortunately, the name attribute can contain characters that 2028*7887SLiane.Praza@Sun.COM * are not legal in a property name. Thus, we base 32 encode the name 2029*7887SLiane.Praza@Sun.COM * attribute and use that for <name>. 2030*7887SLiane.Praza@Sun.COM * 2031*7887SLiane.Praza@Sun.COM * There are cases where the caller needs to know the name, so it is 2032*7887SLiane.Praza@Sun.COM * returned through the name_value pointer if it is not NULL. 2033*7887SLiane.Praza@Sun.COM * 2034*7887SLiane.Praza@Sun.COM * Parameters: 2035*7887SLiane.Praza@Sun.COM * service - Information about the service that is being 2036*7887SLiane.Praza@Sun.COM * processed. This function only uses this parameter 2037*7887SLiane.Praza@Sun.COM * for producing error messages. 2038*7887SLiane.Praza@Sun.COM * 2039*7887SLiane.Praza@Sun.COM * pg - The property group to receive the newly created 2040*7887SLiane.Praza@Sun.COM * properties. 2041*7887SLiane.Praza@Sun.COM * 2042*7887SLiane.Praza@Sun.COM * value - Pointer to the value element in the XML tree. 2043*7887SLiane.Praza@Sun.COM * 2044*7887SLiane.Praza@Sun.COM * name_value - Address to receive the value of the name attribute. 2045*7887SLiane.Praza@Sun.COM * The caller must free the memory. 2046*7887SLiane.Praza@Sun.COM */ 2047*7887SLiane.Praza@Sun.COM static int 2048*7887SLiane.Praza@Sun.COM lxml_get_tm_value_element(entity_t *service, pgroup_t *pg, xmlNodePtr value, 2049*7887SLiane.Praza@Sun.COM char **name_value) 2050*7887SLiane.Praza@Sun.COM { 2051*7887SLiane.Praza@Sun.COM char *common_name_fmt; 2052*7887SLiane.Praza@Sun.COM xmlNodePtr cursor; 2053*7887SLiane.Praza@Sun.COM char *description_fmt; 2054*7887SLiane.Praza@Sun.COM char *encoded_value = NULL; 2055*7887SLiane.Praza@Sun.COM size_t extra; 2056*7887SLiane.Praza@Sun.COM char *value_name; 2057*7887SLiane.Praza@Sun.COM int r = 0; 2058*7887SLiane.Praza@Sun.COM 2059*7887SLiane.Praza@Sun.COM common_name_fmt = safe_malloc(max_scf_name_len + 1); 2060*7887SLiane.Praza@Sun.COM description_fmt = safe_malloc(max_scf_name_len + 1); 2061*7887SLiane.Praza@Sun.COM 2062*7887SLiane.Praza@Sun.COM /* 2063*7887SLiane.Praza@Sun.COM * Get the value of our name attribute, so that we can use it to 2064*7887SLiane.Praza@Sun.COM * construct property names. 2065*7887SLiane.Praza@Sun.COM */ 2066*7887SLiane.Praza@Sun.COM value_name = (char *)xmlGetProp(value, (xmlChar *)name_attr); 2067*7887SLiane.Praza@Sun.COM /* The value name must be present, but it can be empty. */ 2068*7887SLiane.Praza@Sun.COM if (value_name == NULL) { 2069*7887SLiane.Praza@Sun.COM uu_die(gettext("%s element requires a %s attribute in the %s " 2070*7887SLiane.Praza@Sun.COM "service.\n"), (char *)value->name, name_attr, 2071*7887SLiane.Praza@Sun.COM service->sc_name); 2072*7887SLiane.Praza@Sun.COM } 2073*7887SLiane.Praza@Sun.COM 2074*7887SLiane.Praza@Sun.COM /* 2075*7887SLiane.Praza@Sun.COM * The value_name may contain characters that are not valid in in a 2076*7887SLiane.Praza@Sun.COM * property name. So we will encode value_name and then use the 2077*7887SLiane.Praza@Sun.COM * encoded value in the property name. 2078*7887SLiane.Praza@Sun.COM */ 2079*7887SLiane.Praza@Sun.COM encoded_value = safe_malloc(max_scf_name_len + 1); 2080*7887SLiane.Praza@Sun.COM if (scf_encode32(value_name, strlen(value_name), encoded_value, 2081*7887SLiane.Praza@Sun.COM max_scf_name_len + 1, &extra, SCF_ENCODE32_PAD) != 0) { 2082*7887SLiane.Praza@Sun.COM extra = encoded_count_to_plain(extra - max_scf_name_len); 2083*7887SLiane.Praza@Sun.COM uu_die(gettext("Constructed property name is %u characters " 2084*7887SLiane.Praza@Sun.COM "too long for value \"%s\" in the %s service.\n"), 2085*7887SLiane.Praza@Sun.COM extra, value_name, service->sc_name); 2086*7887SLiane.Praza@Sun.COM } 2087*7887SLiane.Praza@Sun.COM if ((extra = snprintf(common_name_fmt, max_scf_name_len + 1, 2088*7887SLiane.Praza@Sun.COM VALUE_COMMON_NAME_FMT, SCF_PROPERTY_TM_VALUE_PREFIX, 2089*7887SLiane.Praza@Sun.COM encoded_value)) >= max_scf_name_len + 1) { 2090*7887SLiane.Praza@Sun.COM extra = encoded_count_to_plain(extra - max_scf_name_len); 2091*7887SLiane.Praza@Sun.COM uu_die(gettext("Name attribute is " 2092*7887SLiane.Praza@Sun.COM "%u characters too long for %s in service %s\n"), 2093*7887SLiane.Praza@Sun.COM extra, (char *)value->name, service->sc_name); 2094*7887SLiane.Praza@Sun.COM } 2095*7887SLiane.Praza@Sun.COM if ((extra = snprintf(description_fmt, max_scf_name_len + 1, 2096*7887SLiane.Praza@Sun.COM VALUE_DESCRIPTION_FMT, SCF_PROPERTY_TM_VALUE_PREFIX, 2097*7887SLiane.Praza@Sun.COM encoded_value)) >= max_scf_name_len + 1) { 2098*7887SLiane.Praza@Sun.COM extra = encoded_count_to_plain(extra - max_scf_name_len); 2099*7887SLiane.Praza@Sun.COM uu_die(gettext("Name attribute is " 2100*7887SLiane.Praza@Sun.COM "%u characters too long for %s in service %s\n"), 2101*7887SLiane.Praza@Sun.COM extra, (char *)value->name, service->sc_name); 2102*7887SLiane.Praza@Sun.COM } 2103*7887SLiane.Praza@Sun.COM 2104*7887SLiane.Praza@Sun.COM for (cursor = value->xmlChildrenNode; 2105*7887SLiane.Praza@Sun.COM cursor != NULL; 2106*7887SLiane.Praza@Sun.COM cursor = cursor->next) { 2107*7887SLiane.Praza@Sun.COM if (lxml_ignorable_block(cursor)) 2108*7887SLiane.Praza@Sun.COM continue; 2109*7887SLiane.Praza@Sun.COM switch (lxml_xlate_element(cursor->name)) { 2110*7887SLiane.Praza@Sun.COM case SC_COMMON_NAME: 2111*7887SLiane.Praza@Sun.COM r = lxml_get_all_loctext(service, pg, cursor, 2112*7887SLiane.Praza@Sun.COM common_name_fmt, (const char *)cursor->name); 2113*7887SLiane.Praza@Sun.COM break; 2114*7887SLiane.Praza@Sun.COM case SC_DESCRIPTION: 2115*7887SLiane.Praza@Sun.COM r = lxml_get_all_loctext(service, pg, cursor, 2116*7887SLiane.Praza@Sun.COM description_fmt, (const char *)cursor->name); 2117*7887SLiane.Praza@Sun.COM break; 2118*7887SLiane.Praza@Sun.COM default: 2119*7887SLiane.Praza@Sun.COM uu_die(gettext("\"%s\" is an illegal element in %s " 2120*7887SLiane.Praza@Sun.COM "of service %s\n"), (char *)cursor->name, 2121*7887SLiane.Praza@Sun.COM (char *)value->name, service->sc_name); 2122*7887SLiane.Praza@Sun.COM } 2123*7887SLiane.Praza@Sun.COM if (r != 0) 2124*7887SLiane.Praza@Sun.COM break; 2125*7887SLiane.Praza@Sun.COM } 2126*7887SLiane.Praza@Sun.COM 2127*7887SLiane.Praza@Sun.COM free(description_fmt); 2128*7887SLiane.Praza@Sun.COM free(common_name_fmt); 2129*7887SLiane.Praza@Sun.COM if (r == 0) { 2130*7887SLiane.Praza@Sun.COM *name_value = safe_strdup(value_name); 2131*7887SLiane.Praza@Sun.COM } 2132*7887SLiane.Praza@Sun.COM xmlFree(value_name); 2133*7887SLiane.Praza@Sun.COM free(encoded_value); 2134*7887SLiane.Praza@Sun.COM return (r); 2135*7887SLiane.Praza@Sun.COM } 2136*7887SLiane.Praza@Sun.COM 2137*7887SLiane.Praza@Sun.COM static int 2138*7887SLiane.Praza@Sun.COM lxml_get_tm_choices(entity_t *service, pgroup_t *pg, xmlNodePtr choices) 2139*7887SLiane.Praza@Sun.COM { 2140*7887SLiane.Praza@Sun.COM xmlNodePtr cursor; 2141*7887SLiane.Praza@Sun.COM char *name_value; 2142*7887SLiane.Praza@Sun.COM property_t *name_prop = NULL; 2143*7887SLiane.Praza@Sun.COM int r = 0; 2144*7887SLiane.Praza@Sun.COM 2145*7887SLiane.Praza@Sun.COM for (cursor = choices->xmlChildrenNode; 2146*7887SLiane.Praza@Sun.COM (cursor != NULL) && (r == 0); 2147*7887SLiane.Praza@Sun.COM cursor = cursor->next) { 2148*7887SLiane.Praza@Sun.COM if (lxml_ignorable_block(cursor)) 2149*7887SLiane.Praza@Sun.COM continue; 2150*7887SLiane.Praza@Sun.COM switch (lxml_xlate_element(cursor->name)) { 2151*7887SLiane.Praza@Sun.COM case SC_INCLUDE_VALUES: 2152*7887SLiane.Praza@Sun.COM (void) lxml_get_tm_include_values(service, pg, cursor, 2153*7887SLiane.Praza@Sun.COM SCF_PROPERTY_TM_CHOICES_INCLUDE_VALUES); 2154*7887SLiane.Praza@Sun.COM break; 2155*7887SLiane.Praza@Sun.COM case SC_RANGE: 2156*7887SLiane.Praza@Sun.COM r = lxml_get_tm_range(service, pg, cursor, 2157*7887SLiane.Praza@Sun.COM SCF_PROPERTY_TM_CHOICES_RANGE); 2158*7887SLiane.Praza@Sun.COM if (r != 0) 2159*7887SLiane.Praza@Sun.COM goto out; 2160*7887SLiane.Praza@Sun.COM break; 2161*7887SLiane.Praza@Sun.COM case SC_VALUE: 2162*7887SLiane.Praza@Sun.COM r = lxml_get_tm_value_element(service, pg, cursor, 2163*7887SLiane.Praza@Sun.COM &name_value); 2164*7887SLiane.Praza@Sun.COM if (r == 0) { 2165*7887SLiane.Praza@Sun.COM /* 2166*7887SLiane.Praza@Sun.COM * There is no need to free the memory 2167*7887SLiane.Praza@Sun.COM * associated with name_value, because the 2168*7887SLiane.Praza@Sun.COM * property value will end up pointing to 2169*7887SLiane.Praza@Sun.COM * the memory. 2170*7887SLiane.Praza@Sun.COM */ 2171*7887SLiane.Praza@Sun.COM astring_prop_value(&name_prop, 2172*7887SLiane.Praza@Sun.COM SCF_PROPERTY_TM_CHOICES_NAME, name_value, 2173*7887SLiane.Praza@Sun.COM B_TRUE); 2174*7887SLiane.Praza@Sun.COM } else { 2175*7887SLiane.Praza@Sun.COM goto out; 2176*7887SLiane.Praza@Sun.COM } 2177*7887SLiane.Praza@Sun.COM break; 2178*7887SLiane.Praza@Sun.COM default: 2179*7887SLiane.Praza@Sun.COM uu_die(gettext("%s is an invalid element of " 2180*7887SLiane.Praza@Sun.COM "choices for service %s.\n"), cursor->name, 2181*7887SLiane.Praza@Sun.COM service->sc_name); 2182*7887SLiane.Praza@Sun.COM } 2183*7887SLiane.Praza@Sun.COM } 2184*7887SLiane.Praza@Sun.COM 2185*7887SLiane.Praza@Sun.COM out: 2186*7887SLiane.Praza@Sun.COM /* Attach the name property if we created one. */ 2187*7887SLiane.Praza@Sun.COM if ((r == 0) && (name_prop != NULL)) { 2188*7887SLiane.Praza@Sun.COM r = internal_attach_property(pg, name_prop); 2189*7887SLiane.Praza@Sun.COM } 2190*7887SLiane.Praza@Sun.COM if ((r != 0) && (name_prop != NULL)) { 2191*7887SLiane.Praza@Sun.COM internal_property_free(name_prop); 2192*7887SLiane.Praza@Sun.COM } 2193*7887SLiane.Praza@Sun.COM 2194*7887SLiane.Praza@Sun.COM return (r); 2195*7887SLiane.Praza@Sun.COM } 2196*7887SLiane.Praza@Sun.COM 2197*7887SLiane.Praza@Sun.COM static int 2198*7887SLiane.Praza@Sun.COM lxml_get_tm_constraints(entity_t *service, pgroup_t *pg, xmlNodePtr constraints) 2199*7887SLiane.Praza@Sun.COM { 2200*7887SLiane.Praza@Sun.COM xmlNodePtr cursor; 2201*7887SLiane.Praza@Sun.COM char *name_value; 2202*7887SLiane.Praza@Sun.COM property_t *name_prop = NULL; 2203*7887SLiane.Praza@Sun.COM int r = 0; 2204*7887SLiane.Praza@Sun.COM 2205*7887SLiane.Praza@Sun.COM for (cursor = constraints->xmlChildrenNode; 2206*7887SLiane.Praza@Sun.COM (cursor != NULL) && (r == 0); 2207*7887SLiane.Praza@Sun.COM cursor = cursor->next) { 2208*7887SLiane.Praza@Sun.COM if (lxml_ignorable_block(cursor)) 2209*7887SLiane.Praza@Sun.COM continue; 2210*7887SLiane.Praza@Sun.COM switch (lxml_xlate_element(cursor->name)) { 2211*7887SLiane.Praza@Sun.COM case SC_RANGE: 2212*7887SLiane.Praza@Sun.COM r = lxml_get_tm_range(service, pg, cursor, 2213*7887SLiane.Praza@Sun.COM SCF_PROPERTY_TM_CONSTRAINT_RANGE); 2214*7887SLiane.Praza@Sun.COM if (r != 0) 2215*7887SLiane.Praza@Sun.COM goto out; 2216*7887SLiane.Praza@Sun.COM break; 2217*7887SLiane.Praza@Sun.COM case SC_VALUE: 2218*7887SLiane.Praza@Sun.COM r = lxml_get_tm_value_element(service, pg, cursor, 2219*7887SLiane.Praza@Sun.COM &name_value); 2220*7887SLiane.Praza@Sun.COM if (r == 0) { 2221*7887SLiane.Praza@Sun.COM /* 2222*7887SLiane.Praza@Sun.COM * There is no need to free the memory 2223*7887SLiane.Praza@Sun.COM * associated with name_value, because the 2224*7887SLiane.Praza@Sun.COM * property value will end up pointing to 2225*7887SLiane.Praza@Sun.COM * the memory. 2226*7887SLiane.Praza@Sun.COM */ 2227*7887SLiane.Praza@Sun.COM astring_prop_value(&name_prop, 2228*7887SLiane.Praza@Sun.COM SCF_PROPERTY_TM_CONSTRAINT_NAME, name_value, 2229*7887SLiane.Praza@Sun.COM B_TRUE); 2230*7887SLiane.Praza@Sun.COM } else { 2231*7887SLiane.Praza@Sun.COM goto out; 2232*7887SLiane.Praza@Sun.COM } 2233*7887SLiane.Praza@Sun.COM break; 2234*7887SLiane.Praza@Sun.COM default: 2235*7887SLiane.Praza@Sun.COM uu_die(gettext("%s is an invalid element of " 2236*7887SLiane.Praza@Sun.COM "constraints for service %s.\n"), cursor->name, 2237*7887SLiane.Praza@Sun.COM service->sc_name); 2238*7887SLiane.Praza@Sun.COM } 2239*7887SLiane.Praza@Sun.COM } 2240*7887SLiane.Praza@Sun.COM 2241*7887SLiane.Praza@Sun.COM out: 2242*7887SLiane.Praza@Sun.COM /* Attach the name property if we created one. */ 2243*7887SLiane.Praza@Sun.COM if ((r == 0) && (name_prop != NULL)) { 2244*7887SLiane.Praza@Sun.COM r = internal_attach_property(pg, name_prop); 2245*7887SLiane.Praza@Sun.COM } 2246*7887SLiane.Praza@Sun.COM if ((r != 0) && (name_prop != NULL)) { 2247*7887SLiane.Praza@Sun.COM internal_property_free(name_prop); 2248*7887SLiane.Praza@Sun.COM } 2249*7887SLiane.Praza@Sun.COM 2250*7887SLiane.Praza@Sun.COM return (r); 2251*7887SLiane.Praza@Sun.COM } 2252*7887SLiane.Praza@Sun.COM 2253*7887SLiane.Praza@Sun.COM /* 2254*7887SLiane.Praza@Sun.COM * The values element contains one or more value elements. 2255*7887SLiane.Praza@Sun.COM */ 2256*7887SLiane.Praza@Sun.COM static int 2257*7887SLiane.Praza@Sun.COM lxml_get_tm_values(entity_t *service, pgroup_t *pg, xmlNodePtr values) 2258*7887SLiane.Praza@Sun.COM { 2259*7887SLiane.Praza@Sun.COM xmlNodePtr cursor; 2260*7887SLiane.Praza@Sun.COM char *name_value; 2261*7887SLiane.Praza@Sun.COM property_t *name_prop = NULL; 2262*7887SLiane.Praza@Sun.COM int r = 0; 2263*7887SLiane.Praza@Sun.COM 2264*7887SLiane.Praza@Sun.COM for (cursor = values->xmlChildrenNode; 2265*7887SLiane.Praza@Sun.COM (cursor != NULL) && (r == 0); 2266*7887SLiane.Praza@Sun.COM cursor = cursor->next) { 2267*7887SLiane.Praza@Sun.COM if (lxml_ignorable_block(cursor)) 2268*7887SLiane.Praza@Sun.COM continue; 2269*7887SLiane.Praza@Sun.COM if (lxml_xlate_element(cursor->name) != SC_VALUE) { 2270*7887SLiane.Praza@Sun.COM uu_die(gettext("\"%s\" is an illegal element in the " 2271*7887SLiane.Praza@Sun.COM "%s element of %s\n"), (char *)cursor->name, 2272*7887SLiane.Praza@Sun.COM (char *)values->name, service->sc_name); 2273*7887SLiane.Praza@Sun.COM } 2274*7887SLiane.Praza@Sun.COM r = lxml_get_tm_value_element(service, pg, cursor, &name_value); 2275*7887SLiane.Praza@Sun.COM if (r == 0) { 2276*7887SLiane.Praza@Sun.COM /* 2277*7887SLiane.Praza@Sun.COM * There is no need to free the memory 2278*7887SLiane.Praza@Sun.COM * associated with name_value, because the 2279*7887SLiane.Praza@Sun.COM * property value will end up pointing to 2280*7887SLiane.Praza@Sun.COM * the memory. 2281*7887SLiane.Praza@Sun.COM */ 2282*7887SLiane.Praza@Sun.COM astring_prop_value(&name_prop, 2283*7887SLiane.Praza@Sun.COM SCF_PROPERTY_TM_VALUES_NAME, name_value, 2284*7887SLiane.Praza@Sun.COM B_TRUE); 2285*7887SLiane.Praza@Sun.COM } 2286*7887SLiane.Praza@Sun.COM } 2287*7887SLiane.Praza@Sun.COM 2288*7887SLiane.Praza@Sun.COM /* Attach the name property if we created one. */ 2289*7887SLiane.Praza@Sun.COM if ((r == 0) && (name_prop != NULL)) { 2290*7887SLiane.Praza@Sun.COM r = internal_attach_property(pg, name_prop); 2291*7887SLiane.Praza@Sun.COM } 2292*7887SLiane.Praza@Sun.COM if ((r != 0) && (name_prop != NULL)) { 2293*7887SLiane.Praza@Sun.COM internal_property_free(name_prop); 2294*7887SLiane.Praza@Sun.COM } 2295*7887SLiane.Praza@Sun.COM 2296*7887SLiane.Praza@Sun.COM return (r); 2297*7887SLiane.Praza@Sun.COM } 2298*7887SLiane.Praza@Sun.COM 2299*7887SLiane.Praza@Sun.COM /* 2300*7887SLiane.Praza@Sun.COM * This function processes a prop_pattern element within a pg_pattern XML 2301*7887SLiane.Praza@Sun.COM * element. First it creates a property group to hold the prop_pattern 2302*7887SLiane.Praza@Sun.COM * information. The name of this property group is the concatenation of: 2303*7887SLiane.Praza@Sun.COM * - SCF_PG_TM_PROP_PATTERN_PREFIX 2304*7887SLiane.Praza@Sun.COM * - The unique part of the property group name of the enclosing 2305*7887SLiane.Praza@Sun.COM * pg_pattern. The property group name of the enclosing pg_pattern 2306*7887SLiane.Praza@Sun.COM * is passed to us in pgpat_name. The unique part, is the part 2307*7887SLiane.Praza@Sun.COM * following SCF_PG_TM_PG_PATTERN_PREFIX. 2308*7887SLiane.Praza@Sun.COM * - The name of this prop_pattern element. 2309*7887SLiane.Praza@Sun.COM * 2310*7887SLiane.Praza@Sun.COM * After creating the property group, the prop_pattern attributes are saved 2311*7887SLiane.Praza@Sun.COM * as properties in the PG. Finally, the prop_pattern elements are 2312*7887SLiane.Praza@Sun.COM * processed and added to the PG. 2313*7887SLiane.Praza@Sun.COM */ 2314*7887SLiane.Praza@Sun.COM static int 2315*7887SLiane.Praza@Sun.COM lxml_get_tm_prop_pattern(entity_t *service, xmlNodePtr prop_pattern, 2316*7887SLiane.Praza@Sun.COM const char *pgpat_name) 2317*7887SLiane.Praza@Sun.COM { 2318*7887SLiane.Praza@Sun.COM xmlNodePtr cursor; 2319*7887SLiane.Praza@Sun.COM int extra; 2320*7887SLiane.Praza@Sun.COM pgroup_t *pg; 2321*7887SLiane.Praza@Sun.COM property_t *p; 2322*7887SLiane.Praza@Sun.COM char *pg_name; 2323*7887SLiane.Praza@Sun.COM size_t prefix_len; 2324*7887SLiane.Praza@Sun.COM xmlChar *prop_pattern_name; 2325*7887SLiane.Praza@Sun.COM int r; 2326*7887SLiane.Praza@Sun.COM const char *unique; 2327*7887SLiane.Praza@Sun.COM value_t *v; 2328*7887SLiane.Praza@Sun.COM 2329*7887SLiane.Praza@Sun.COM /* Find the unique part of the pg_pattern property group name. */ 2330*7887SLiane.Praza@Sun.COM prefix_len = strlen(SCF_PG_TM_PG_PAT_BASE); 2331*7887SLiane.Praza@Sun.COM assert(strncmp(pgpat_name, SCF_PG_TM_PG_PAT_BASE, prefix_len) == 0); 2332*7887SLiane.Praza@Sun.COM unique = pgpat_name + prefix_len; 2333*7887SLiane.Praza@Sun.COM 2334*7887SLiane.Praza@Sun.COM /* 2335*7887SLiane.Praza@Sun.COM * We need to get the value of the name attribute first. The 2336*7887SLiane.Praza@Sun.COM * prop_pattern name as well as the name of the enclosing 2337*7887SLiane.Praza@Sun.COM * pg_pattern both constitute part of the name of the property 2338*7887SLiane.Praza@Sun.COM * group that we will create. 2339*7887SLiane.Praza@Sun.COM */ 2340*7887SLiane.Praza@Sun.COM prop_pattern_name = xmlGetProp(prop_pattern, (xmlChar *)name_attr); 2341*7887SLiane.Praza@Sun.COM if ((prop_pattern_name == NULL) || (*prop_pattern_name == 0)) { 2342*7887SLiane.Praza@Sun.COM semerr(gettext("prop_pattern name is missing for %s\n"), 2343*7887SLiane.Praza@Sun.COM service->sc_name); 2344*7887SLiane.Praza@Sun.COM return (-1); 2345*7887SLiane.Praza@Sun.COM } 2346*7887SLiane.Praza@Sun.COM if (uu_check_name((const char *)prop_pattern_name, 2347*7887SLiane.Praza@Sun.COM UU_NAME_DOMAIN) != 0) { 2348*7887SLiane.Praza@Sun.COM semerr(gettext("prop_pattern name, \"%s\", for %s is not " 2349*7887SLiane.Praza@Sun.COM "valid.\n"), prop_pattern_name, service->sc_name); 2350*7887SLiane.Praza@Sun.COM xmlFree(prop_pattern_name); 2351*7887SLiane.Praza@Sun.COM return (-1); 2352*7887SLiane.Praza@Sun.COM } 2353*7887SLiane.Praza@Sun.COM pg_name = safe_malloc(max_scf_name_len + 1); 2354*7887SLiane.Praza@Sun.COM if ((extra = snprintf(pg_name, max_scf_name_len + 1, "%s%s_%s", 2355*7887SLiane.Praza@Sun.COM SCF_PG_TM_PROP_PATTERN_PREFIX, unique, 2356*7887SLiane.Praza@Sun.COM (char *)prop_pattern_name)) >= max_scf_name_len + 1) { 2357*7887SLiane.Praza@Sun.COM uu_die(gettext("prop_pattern name, \"%s\", for %s is %d " 2358*7887SLiane.Praza@Sun.COM "characters too long\n"), (char *)prop_pattern_name, 2359*7887SLiane.Praza@Sun.COM service->sc_name, extra - max_scf_name_len); 2360*7887SLiane.Praza@Sun.COM } 2361*7887SLiane.Praza@Sun.COM 2362*7887SLiane.Praza@Sun.COM /* 2363*7887SLiane.Praza@Sun.COM * Create the property group, the property referencing the pg_pattern 2364*7887SLiane.Praza@Sun.COM * name, and add the prop_pattern attributes to the property group. 2365*7887SLiane.Praza@Sun.COM */ 2366*7887SLiane.Praza@Sun.COM pg = internal_pgroup_create_strict(service, pg_name, 2367*7887SLiane.Praza@Sun.COM SCF_GROUP_TEMPLATE_PROP_PATTERN); 2368*7887SLiane.Praza@Sun.COM if (pg == NULL) { 2369*7887SLiane.Praza@Sun.COM uu_die(gettext("Property group for prop_pattern, \"%s\", " 2370*7887SLiane.Praza@Sun.COM "already exists in %s\n"), prop_pattern_name, 2371*7887SLiane.Praza@Sun.COM service->sc_name); 2372*7887SLiane.Praza@Sun.COM } 2373*7887SLiane.Praza@Sun.COM 2374*7887SLiane.Praza@Sun.COM p = internal_property_create(SCF_PROPERTY_TM_PG_PATTERN, 2375*7887SLiane.Praza@Sun.COM SCF_TYPE_ASTRING, 1, safe_strdup(pgpat_name)); 2376*7887SLiane.Praza@Sun.COM /* 2377*7887SLiane.Praza@Sun.COM * Unfortunately, internal_property_create() does not set the free 2378*7887SLiane.Praza@Sun.COM * function for the value, so we'll set it now. 2379*7887SLiane.Praza@Sun.COM */ 2380*7887SLiane.Praza@Sun.COM v = uu_list_first(p->sc_property_values); 2381*7887SLiane.Praza@Sun.COM v->sc_free = lxml_free_str; 2382*7887SLiane.Praza@Sun.COM if (internal_attach_property(pg, p) != 0) 2383*7887SLiane.Praza@Sun.COM internal_property_free(p); 2384*7887SLiane.Praza@Sun.COM 2385*7887SLiane.Praza@Sun.COM 2386*7887SLiane.Praza@Sun.COM r = lxml_get_prop_pattern_attributes(pg, prop_pattern); 2387*7887SLiane.Praza@Sun.COM if (r != 0) 2388*7887SLiane.Praza@Sun.COM goto out; 2389*7887SLiane.Praza@Sun.COM 2390*7887SLiane.Praza@Sun.COM /* 2391*7887SLiane.Praza@Sun.COM * Now process the elements of prop_pattern 2392*7887SLiane.Praza@Sun.COM */ 2393*7887SLiane.Praza@Sun.COM for (cursor = prop_pattern->xmlChildrenNode; 2394*7887SLiane.Praza@Sun.COM cursor != NULL; 2395*7887SLiane.Praza@Sun.COM cursor = cursor->next) { 2396*7887SLiane.Praza@Sun.COM if (lxml_ignorable_block(cursor)) 2397*7887SLiane.Praza@Sun.COM continue; 2398*7887SLiane.Praza@Sun.COM 2399*7887SLiane.Praza@Sun.COM switch (lxml_xlate_element(cursor->name)) { 2400*7887SLiane.Praza@Sun.COM case SC_CARDINALITY: 2401*7887SLiane.Praza@Sun.COM r = lxml_get_tm_cardinality(service, pg, cursor); 2402*7887SLiane.Praza@Sun.COM if (r != 0) 2403*7887SLiane.Praza@Sun.COM goto out; 2404*7887SLiane.Praza@Sun.COM break; 2405*7887SLiane.Praza@Sun.COM case SC_CHOICES: 2406*7887SLiane.Praza@Sun.COM r = lxml_get_tm_choices(service, pg, cursor); 2407*7887SLiane.Praza@Sun.COM if (r != 0) 2408*7887SLiane.Praza@Sun.COM goto out; 2409*7887SLiane.Praza@Sun.COM break; 2410*7887SLiane.Praza@Sun.COM case SC_COMMON_NAME: 2411*7887SLiane.Praza@Sun.COM (void) lxml_get_all_loctext(service, pg, cursor, 2412*7887SLiane.Praza@Sun.COM COMMON_NAME_FMT, (const char *)cursor->name); 2413*7887SLiane.Praza@Sun.COM break; 2414*7887SLiane.Praza@Sun.COM case SC_CONSTRAINTS: 2415*7887SLiane.Praza@Sun.COM r = lxml_get_tm_constraints(service, pg, cursor); 2416*7887SLiane.Praza@Sun.COM if (r != 0) 2417*7887SLiane.Praza@Sun.COM goto out; 2418*7887SLiane.Praza@Sun.COM break; 2419*7887SLiane.Praza@Sun.COM case SC_DESCRIPTION: 2420*7887SLiane.Praza@Sun.COM (void) lxml_get_all_loctext(service, pg, cursor, 2421*7887SLiane.Praza@Sun.COM DESCRIPTION_FMT, (const char *)cursor->name); 2422*7887SLiane.Praza@Sun.COM break; 2423*7887SLiane.Praza@Sun.COM case SC_INTERNAL_SEPARATORS: 2424*7887SLiane.Praza@Sun.COM r = lxml_get_tm_internal_seps(service, pg, cursor); 2425*7887SLiane.Praza@Sun.COM if (r != 0) 2426*7887SLiane.Praza@Sun.COM goto out; 2427*7887SLiane.Praza@Sun.COM break; 2428*7887SLiane.Praza@Sun.COM case SC_UNITS: 2429*7887SLiane.Praza@Sun.COM (void) lxml_get_all_loctext(service, pg, cursor, 2430*7887SLiane.Praza@Sun.COM UNITS_FMT, "units"); 2431*7887SLiane.Praza@Sun.COM break; 2432*7887SLiane.Praza@Sun.COM case SC_VALUES: 2433*7887SLiane.Praza@Sun.COM (void) lxml_get_tm_values(service, pg, cursor); 2434*7887SLiane.Praza@Sun.COM break; 2435*7887SLiane.Praza@Sun.COM case SC_VISIBILITY: 2436*7887SLiane.Praza@Sun.COM /* 2437*7887SLiane.Praza@Sun.COM * The visibility element is empty, so we only need 2438*7887SLiane.Praza@Sun.COM * to proccess the value attribute. 2439*7887SLiane.Praza@Sun.COM */ 2440*7887SLiane.Praza@Sun.COM (void) new_str_prop_from_attr(pg, 2441*7887SLiane.Praza@Sun.COM SCF_PROPERTY_TM_VISIBILITY, SCF_TYPE_ASTRING, 2442*7887SLiane.Praza@Sun.COM cursor, value_attr); 2443*7887SLiane.Praza@Sun.COM break; 2444*7887SLiane.Praza@Sun.COM default: 2445*7887SLiane.Praza@Sun.COM uu_die(gettext("illegal element \"%s\" in prop_pattern " 2446*7887SLiane.Praza@Sun.COM "for service \"%s\"\n"), cursor->name, 2447*7887SLiane.Praza@Sun.COM service->sc_name); 2448*7887SLiane.Praza@Sun.COM } 2449*7887SLiane.Praza@Sun.COM } 2450*7887SLiane.Praza@Sun.COM 2451*7887SLiane.Praza@Sun.COM out: 2452*7887SLiane.Praza@Sun.COM xmlFree(prop_pattern_name); 2453*7887SLiane.Praza@Sun.COM free(pg_name); 2454*7887SLiane.Praza@Sun.COM return (r); 2455*7887SLiane.Praza@Sun.COM } 2456*7887SLiane.Praza@Sun.COM 2457*7887SLiane.Praza@Sun.COM /* 2458*7887SLiane.Praza@Sun.COM * Get the pg_pattern attributes and save them as properties in the 2459*7887SLiane.Praza@Sun.COM * property group at pg. The pg_pattern element accepts four attributes -- 2460*7887SLiane.Praza@Sun.COM * name, type, required and target. 2461*7887SLiane.Praza@Sun.COM */ 2462*7887SLiane.Praza@Sun.COM static int 2463*7887SLiane.Praza@Sun.COM lxml_get_pg_pattern_attributes(pgroup_t *pg, xmlNodePtr cursor) 2464*7887SLiane.Praza@Sun.COM { 2465*7887SLiane.Praza@Sun.COM if (new_opt_str_prop_from_attr(pg, SCF_PROPERTY_TM_NAME, 2466*7887SLiane.Praza@Sun.COM SCF_TYPE_ASTRING, cursor, name_attr, NULL) != 0) { 2467*7887SLiane.Praza@Sun.COM return (-1); 2468*7887SLiane.Praza@Sun.COM } 2469*7887SLiane.Praza@Sun.COM if (new_opt_str_prop_from_attr(pg, SCF_PROPERTY_TM_TYPE, 2470*7887SLiane.Praza@Sun.COM SCF_TYPE_ASTRING, cursor, type_attr, NULL) != 0) { 2471*7887SLiane.Praza@Sun.COM return (-1); 2472*7887SLiane.Praza@Sun.COM } 2473*7887SLiane.Praza@Sun.COM if (new_opt_str_prop_from_attr(pg, SCF_PROPERTY_TM_TARGET, 2474*7887SLiane.Praza@Sun.COM SCF_TYPE_ASTRING, cursor, target_attr, NULL) != 0) { 2475*7887SLiane.Praza@Sun.COM return (-1); 2476*7887SLiane.Praza@Sun.COM } 2477*7887SLiane.Praza@Sun.COM if (new_bool_prop_from_attr(pg, SCF_PROPERTY_TM_REQUIRED, cursor, 2478*7887SLiane.Praza@Sun.COM required_attr) != 0) 2479*7887SLiane.Praza@Sun.COM return (-1); 2480*7887SLiane.Praza@Sun.COM return (0); 2481*7887SLiane.Praza@Sun.COM } 2482*7887SLiane.Praza@Sun.COM 2483*7887SLiane.Praza@Sun.COM /* 2484*7887SLiane.Praza@Sun.COM * There are several restrictions on the pg_pattern attributes that cannot 2485*7887SLiane.Praza@Sun.COM * be specifed in the service bundle DTD. This function verifies that 2486*7887SLiane.Praza@Sun.COM * those restrictions have been satisfied. The restrictions are: 2487*7887SLiane.Praza@Sun.COM * 2488*7887SLiane.Praza@Sun.COM * - The target attribute may have a value of "instance" only when the 2489*7887SLiane.Praza@Sun.COM * template block is in a service declaration. 2490*7887SLiane.Praza@Sun.COM * 2491*7887SLiane.Praza@Sun.COM * - The target attribute may have a value of "delegate" only when the 2492*7887SLiane.Praza@Sun.COM * template block applies to a restarter. 2493*7887SLiane.Praza@Sun.COM * 2494*7887SLiane.Praza@Sun.COM * - The target attribute may have a value of "all" only when the 2495*7887SLiane.Praza@Sun.COM * template block applies to the master restarter. 2496*7887SLiane.Praza@Sun.COM * 2497*7887SLiane.Praza@Sun.COM * The function returns 0 on success and -1 on failure. 2498*7887SLiane.Praza@Sun.COM */ 2499*7887SLiane.Praza@Sun.COM static int 2500*7887SLiane.Praza@Sun.COM verify_pg_pattern_attributes(entity_t *s, pgroup_t *pg) 2501*7887SLiane.Praza@Sun.COM { 2502*7887SLiane.Praza@Sun.COM int is_restarter; 2503*7887SLiane.Praza@Sun.COM property_t *target; 2504*7887SLiane.Praza@Sun.COM value_t *v; 2505*7887SLiane.Praza@Sun.COM 2506*7887SLiane.Praza@Sun.COM /* Find the value of the target property. */ 2507*7887SLiane.Praza@Sun.COM target = internal_property_find(pg, SCF_PROPERTY_TM_TARGET); 2508*7887SLiane.Praza@Sun.COM if (target == NULL) { 2509*7887SLiane.Praza@Sun.COM uu_die(gettext("pg_pattern is missing the %s attribute " 2510*7887SLiane.Praza@Sun.COM "in %s\n"), target_attr, s->sc_name); 2511*7887SLiane.Praza@Sun.COM return (-1); 2512*7887SLiane.Praza@Sun.COM } 2513*7887SLiane.Praza@Sun.COM v = uu_list_first(target->sc_property_values); 2514*7887SLiane.Praza@Sun.COM assert(v != NULL); 2515*7887SLiane.Praza@Sun.COM assert(v->sc_type == SCF_TYPE_ASTRING); 2516*7887SLiane.Praza@Sun.COM 2517*7887SLiane.Praza@Sun.COM /* 2518*7887SLiane.Praza@Sun.COM * If target has a value of instance, the template must be in a 2519*7887SLiane.Praza@Sun.COM * service object. 2520*7887SLiane.Praza@Sun.COM */ 2521*7887SLiane.Praza@Sun.COM if (strcmp(v->sc_u.sc_string, "instance") == 0) { 2522*7887SLiane.Praza@Sun.COM if (s->sc_etype != SVCCFG_SERVICE_OBJECT) { 2523*7887SLiane.Praza@Sun.COM uu_warn(gettext("pg_pattern %s attribute may only " 2524*7887SLiane.Praza@Sun.COM "have a value of \"instance\" when it is in a " 2525*7887SLiane.Praza@Sun.COM "service declaration.\n"), target_attr); 2526*7887SLiane.Praza@Sun.COM return (-1); 2527*7887SLiane.Praza@Sun.COM } 2528*7887SLiane.Praza@Sun.COM } 2529*7887SLiane.Praza@Sun.COM 2530*7887SLiane.Praza@Sun.COM /* 2531*7887SLiane.Praza@Sun.COM * If target has a value of "delegate", the template must be in a 2532*7887SLiane.Praza@Sun.COM * restarter. 2533*7887SLiane.Praza@Sun.COM */ 2534*7887SLiane.Praza@Sun.COM if (strcmp(v->sc_u.sc_string, "delegate") == 0) { 2535*7887SLiane.Praza@Sun.COM is_restarter = 0; 2536*7887SLiane.Praza@Sun.COM if ((s->sc_etype == SVCCFG_SERVICE_OBJECT) && 2537*7887SLiane.Praza@Sun.COM (s->sc_u.sc_service.sc_service_type == SVCCFG_RESTARTER)) { 2538*7887SLiane.Praza@Sun.COM is_restarter = 1; 2539*7887SLiane.Praza@Sun.COM } 2540*7887SLiane.Praza@Sun.COM if ((s->sc_etype == SVCCFG_INSTANCE_OBJECT) && 2541*7887SLiane.Praza@Sun.COM (s->sc_parent->sc_u.sc_service.sc_service_type == 2542*7887SLiane.Praza@Sun.COM SVCCFG_RESTARTER)) { 2543*7887SLiane.Praza@Sun.COM is_restarter = 1; 2544*7887SLiane.Praza@Sun.COM } 2545*7887SLiane.Praza@Sun.COM if (is_restarter == 0) { 2546*7887SLiane.Praza@Sun.COM uu_warn(gettext("pg_pattern %s attribute has a " 2547*7887SLiane.Praza@Sun.COM "value of \"delegate\" but is not in a " 2548*7887SLiane.Praza@Sun.COM "restarter service\n"), target_attr); 2549*7887SLiane.Praza@Sun.COM return (-1); 2550*7887SLiane.Praza@Sun.COM } 2551*7887SLiane.Praza@Sun.COM } 2552*7887SLiane.Praza@Sun.COM 2553*7887SLiane.Praza@Sun.COM /* 2554*7887SLiane.Praza@Sun.COM * If target has a value of "all", the template must be in the 2555*7887SLiane.Praza@Sun.COM * global (SCF_SERVICE_GLOBAL) service. 2556*7887SLiane.Praza@Sun.COM */ 2557*7887SLiane.Praza@Sun.COM if (strcmp(v->sc_u.sc_string, all_value) == 0) { 2558*7887SLiane.Praza@Sun.COM if (s->sc_etype != SVCCFG_SERVICE_OBJECT) { 2559*7887SLiane.Praza@Sun.COM uu_warn(gettext("pg_pattern %s attribute has a " 2560*7887SLiane.Praza@Sun.COM "value of \"%s\" but is not in a " 2561*7887SLiane.Praza@Sun.COM "service entity.\n"), target_attr, all_value); 2562*7887SLiane.Praza@Sun.COM return (-1); 2563*7887SLiane.Praza@Sun.COM } 2564*7887SLiane.Praza@Sun.COM if (strcmp(s->sc_fmri, SCF_SERVICE_GLOBAL) != 0) { 2565*7887SLiane.Praza@Sun.COM uu_warn(gettext("pg_pattern %s attribute has a " 2566*7887SLiane.Praza@Sun.COM "value of \"%s\" but is in the \"%s\" service. " 2567*7887SLiane.Praza@Sun.COM "pg_patterns with target \"%s\" are only allowed " 2568*7887SLiane.Praza@Sun.COM "in the global service.\n"), 2569*7887SLiane.Praza@Sun.COM target_attr, all_value, s->sc_fmri, all_value); 2570*7887SLiane.Praza@Sun.COM return (-1); 2571*7887SLiane.Praza@Sun.COM } 2572*7887SLiane.Praza@Sun.COM } 2573*7887SLiane.Praza@Sun.COM 2574*7887SLiane.Praza@Sun.COM return (0); 2575*7887SLiane.Praza@Sun.COM } 2576*7887SLiane.Praza@Sun.COM 2577*7887SLiane.Praza@Sun.COM static int 2578*7887SLiane.Praza@Sun.COM lxml_get_tm_pg_pattern(entity_t *service, xmlNodePtr pg_pattern) 2579*7887SLiane.Praza@Sun.COM { 2580*7887SLiane.Praza@Sun.COM xmlNodePtr cursor; 2581*7887SLiane.Praza@Sun.COM int out_len; 2582*7887SLiane.Praza@Sun.COM xmlChar *name; 2583*7887SLiane.Praza@Sun.COM pgroup_t *pg = NULL; 2584*7887SLiane.Praza@Sun.COM char *pg_name; 2585*7887SLiane.Praza@Sun.COM int r = -1; 2586*7887SLiane.Praza@Sun.COM xmlChar *type; 2587*7887SLiane.Praza@Sun.COM 2588*7887SLiane.Praza@Sun.COM pg_name = safe_malloc(max_scf_name_len + 1); 2589*7887SLiane.Praza@Sun.COM 2590*7887SLiane.Praza@Sun.COM /* 2591*7887SLiane.Praza@Sun.COM * Get the name and type attributes. Their presence or absence 2592*7887SLiane.Praza@Sun.COM * determines whcih prefix we will use for the property group name. 2593*7887SLiane.Praza@Sun.COM * There are four cases -- neither attribute is present, both are 2594*7887SLiane.Praza@Sun.COM * present, only name is present or only type is present. 2595*7887SLiane.Praza@Sun.COM */ 2596*7887SLiane.Praza@Sun.COM name = xmlGetProp(pg_pattern, (xmlChar *)name_attr); 2597*7887SLiane.Praza@Sun.COM type = xmlGetProp(pg_pattern, (xmlChar *)type_attr); 2598*7887SLiane.Praza@Sun.COM if ((name == NULL) || (*name == 0)) { 2599*7887SLiane.Praza@Sun.COM if ((type == NULL) || (*type == 0)) { 2600*7887SLiane.Praza@Sun.COM /* PG name contains only the prefix in this case */ 2601*7887SLiane.Praza@Sun.COM if (strlcpy(pg_name, SCF_PG_TM_PG_PATTERN_PREFIX, 2602*7887SLiane.Praza@Sun.COM max_scf_name_len + 1) >= max_scf_name_len + 1) { 2603*7887SLiane.Praza@Sun.COM uu_die(gettext("Unable to create pg_pattern " 2604*7887SLiane.Praza@Sun.COM "property for %s\n"), service->sc_name); 2605*7887SLiane.Praza@Sun.COM } 2606*7887SLiane.Praza@Sun.COM } else { 2607*7887SLiane.Praza@Sun.COM /* 2608*7887SLiane.Praza@Sun.COM * If we have a type and no name, the type becomes 2609*7887SLiane.Praza@Sun.COM * part of the pg_pattern property group name. 2610*7887SLiane.Praza@Sun.COM */ 2611*7887SLiane.Praza@Sun.COM if ((out_len = snprintf(pg_name, max_scf_name_len + 1, 2612*7887SLiane.Praza@Sun.COM "%s%s", SCF_PG_TM_PG_PATTERN_T_PREFIX, type)) >= 2613*7887SLiane.Praza@Sun.COM max_scf_name_len + 1) { 2614*7887SLiane.Praza@Sun.COM uu_die(gettext("pg_pattern type is for %s is " 2615*7887SLiane.Praza@Sun.COM "%d bytes too long\n"), service->sc_name, 2616*7887SLiane.Praza@Sun.COM out_len - max_scf_name_len); 2617*7887SLiane.Praza@Sun.COM } 2618*7887SLiane.Praza@Sun.COM } 2619*7887SLiane.Praza@Sun.COM } else { 2620*7887SLiane.Praza@Sun.COM const char *prefix; 2621*7887SLiane.Praza@Sun.COM 2622*7887SLiane.Praza@Sun.COM /* Make sure that the name is valid. */ 2623*7887SLiane.Praza@Sun.COM if (uu_check_name((const char *)name, UU_NAME_DOMAIN) != 0) { 2624*7887SLiane.Praza@Sun.COM semerr(gettext("pg_pattern name attribute, \"%s\", " 2625*7887SLiane.Praza@Sun.COM "for %s is invalid\n"), name, service->sc_name); 2626*7887SLiane.Praza@Sun.COM goto out; 2627*7887SLiane.Praza@Sun.COM } 2628*7887SLiane.Praza@Sun.COM 2629*7887SLiane.Praza@Sun.COM /* 2630*7887SLiane.Praza@Sun.COM * As long as the pg_pattern has a name, it becomes part of 2631*7887SLiane.Praza@Sun.COM * the name of the pg_pattern property group name. We 2632*7887SLiane.Praza@Sun.COM * merely need to pick the appropriate prefix. 2633*7887SLiane.Praza@Sun.COM */ 2634*7887SLiane.Praza@Sun.COM if ((type == NULL) || (*type == 0)) { 2635*7887SLiane.Praza@Sun.COM prefix = SCF_PG_TM_PG_PATTERN_N_PREFIX; 2636*7887SLiane.Praza@Sun.COM } else { 2637*7887SLiane.Praza@Sun.COM prefix = SCF_PG_TM_PG_PATTERN_NT_PREFIX; 2638*7887SLiane.Praza@Sun.COM } 2639*7887SLiane.Praza@Sun.COM if ((out_len = snprintf(pg_name, max_scf_name_len + 1, "%s%s", 2640*7887SLiane.Praza@Sun.COM prefix, name)) >= max_scf_name_len + 1) { 2641*7887SLiane.Praza@Sun.COM uu_die(gettext("pg_pattern property group name " 2642*7887SLiane.Praza@Sun.COM "for %s is %d bytes too long\n"), service->sc_name, 2643*7887SLiane.Praza@Sun.COM out_len - max_scf_name_len); 2644*7887SLiane.Praza@Sun.COM } 2645*7887SLiane.Praza@Sun.COM } 2646*7887SLiane.Praza@Sun.COM 2647*7887SLiane.Praza@Sun.COM /* 2648*7887SLiane.Praza@Sun.COM * Create the property group for holding this pg_pattern 2649*7887SLiane.Praza@Sun.COM * information, and capture the pg_pattern attributes. 2650*7887SLiane.Praza@Sun.COM */ 2651*7887SLiane.Praza@Sun.COM pg = internal_pgroup_create_strict(service, pg_name, 2652*7887SLiane.Praza@Sun.COM SCF_GROUP_TEMPLATE_PG_PATTERN); 2653*7887SLiane.Praza@Sun.COM if (pg == NULL) { 2654*7887SLiane.Praza@Sun.COM if ((name == NULL) || (*name == 0)) { 2655*7887SLiane.Praza@Sun.COM if ((type == NULL) ||(*type == 0)) { 2656*7887SLiane.Praza@Sun.COM semerr(gettext("pg_pattern with empty name and " 2657*7887SLiane.Praza@Sun.COM "type is not unique in %s\n"), 2658*7887SLiane.Praza@Sun.COM service->sc_name); 2659*7887SLiane.Praza@Sun.COM } else { 2660*7887SLiane.Praza@Sun.COM semerr(gettext("pg_pattern with empty name and " 2661*7887SLiane.Praza@Sun.COM "type \"%s\" is not unique in %s\n"), 2662*7887SLiane.Praza@Sun.COM type, service->sc_name); 2663*7887SLiane.Praza@Sun.COM } 2664*7887SLiane.Praza@Sun.COM } else { 2665*7887SLiane.Praza@Sun.COM if ((type == NULL) || (*type == 0)) { 2666*7887SLiane.Praza@Sun.COM semerr(gettext("pg_pattern with name \"%s\" " 2667*7887SLiane.Praza@Sun.COM "and empty type is not unique in %s\n"), 2668*7887SLiane.Praza@Sun.COM name, service->sc_name); 2669*7887SLiane.Praza@Sun.COM } else { 2670*7887SLiane.Praza@Sun.COM semerr(gettext("pg_pattern with name \"%s\" " 2671*7887SLiane.Praza@Sun.COM "and type \"%s\" is not unique in %s\n"), 2672*7887SLiane.Praza@Sun.COM name, type, service->sc_name); 2673*7887SLiane.Praza@Sun.COM } 2674*7887SLiane.Praza@Sun.COM } 2675*7887SLiane.Praza@Sun.COM goto out; 2676*7887SLiane.Praza@Sun.COM } 2677*7887SLiane.Praza@Sun.COM 2678*7887SLiane.Praza@Sun.COM /* 2679*7887SLiane.Praza@Sun.COM * Get the pg_pattern attributes from the manifest and verify 2680*7887SLiane.Praza@Sun.COM * that they satisfy our restrictions. 2681*7887SLiane.Praza@Sun.COM */ 2682*7887SLiane.Praza@Sun.COM r = lxml_get_pg_pattern_attributes(pg, pg_pattern); 2683*7887SLiane.Praza@Sun.COM if (r != 0) 2684*7887SLiane.Praza@Sun.COM goto out; 2685*7887SLiane.Praza@Sun.COM if (verify_pg_pattern_attributes(service, pg) != 0) { 2686*7887SLiane.Praza@Sun.COM semerr(gettext("Invalid pg_pattern attributes in %s\n"), 2687*7887SLiane.Praza@Sun.COM service->sc_name); 2688*7887SLiane.Praza@Sun.COM r = -1; 2689*7887SLiane.Praza@Sun.COM goto out; 2690*7887SLiane.Praza@Sun.COM } 2691*7887SLiane.Praza@Sun.COM 2692*7887SLiane.Praza@Sun.COM /* 2693*7887SLiane.Praza@Sun.COM * Now process all of the elements of pg_pattern. 2694*7887SLiane.Praza@Sun.COM */ 2695*7887SLiane.Praza@Sun.COM for (cursor = pg_pattern->xmlChildrenNode; 2696*7887SLiane.Praza@Sun.COM cursor != NULL; 2697*7887SLiane.Praza@Sun.COM cursor = cursor->next) { 2698*7887SLiane.Praza@Sun.COM if (lxml_ignorable_block(cursor)) 2699*7887SLiane.Praza@Sun.COM continue; 2700*7887SLiane.Praza@Sun.COM 2701*7887SLiane.Praza@Sun.COM switch (lxml_xlate_element(cursor->name)) { 2702*7887SLiane.Praza@Sun.COM case SC_COMMON_NAME: 2703*7887SLiane.Praza@Sun.COM (void) lxml_get_all_loctext(service, pg, cursor, 2704*7887SLiane.Praza@Sun.COM COMMON_NAME_FMT, (const char *)cursor->name); 2705*7887SLiane.Praza@Sun.COM break; 2706*7887SLiane.Praza@Sun.COM case SC_DESCRIPTION: 2707*7887SLiane.Praza@Sun.COM (void) lxml_get_all_loctext(service, pg, cursor, 2708*7887SLiane.Praza@Sun.COM DESCRIPTION_FMT, (const char *)cursor->name); 2709*7887SLiane.Praza@Sun.COM break; 2710*7887SLiane.Praza@Sun.COM case SC_PROP_PATTERN: 2711*7887SLiane.Praza@Sun.COM r = lxml_get_tm_prop_pattern(service, cursor, 2712*7887SLiane.Praza@Sun.COM pg_name); 2713*7887SLiane.Praza@Sun.COM if (r != 0) 2714*7887SLiane.Praza@Sun.COM goto out; 2715*7887SLiane.Praza@Sun.COM break; 2716*7887SLiane.Praza@Sun.COM default: 2717*7887SLiane.Praza@Sun.COM uu_die(gettext("illegal element \"%s\" in pg_pattern " 2718*7887SLiane.Praza@Sun.COM "for service \"%s\"\n"), cursor->name, 2719*7887SLiane.Praza@Sun.COM service->sc_name); 2720*7887SLiane.Praza@Sun.COM } 2721*7887SLiane.Praza@Sun.COM } 2722*7887SLiane.Praza@Sun.COM 2723*7887SLiane.Praza@Sun.COM out: 2724*7887SLiane.Praza@Sun.COM if ((r != 0) && (pg != NULL)) { 2725*7887SLiane.Praza@Sun.COM internal_detach_pgroup(service, pg); 2726*7887SLiane.Praza@Sun.COM internal_pgroup_free(pg); 2727*7887SLiane.Praza@Sun.COM } 2728*7887SLiane.Praza@Sun.COM free(pg_name); 2729*7887SLiane.Praza@Sun.COM xmlFree(name); 2730*7887SLiane.Praza@Sun.COM xmlFree(type); 2731*7887SLiane.Praza@Sun.COM 2732*7887SLiane.Praza@Sun.COM return (r); 2733*7887SLiane.Praza@Sun.COM } 2734*7887SLiane.Praza@Sun.COM 2735*7887SLiane.Praza@Sun.COM static int 27360Sstevel@tonic-gate lxml_get_template(entity_t *service, xmlNodePtr templ) 27370Sstevel@tonic-gate { 27380Sstevel@tonic-gate xmlNodePtr cursor; 27390Sstevel@tonic-gate 27400Sstevel@tonic-gate for (cursor = templ->xmlChildrenNode; cursor != NULL; 27410Sstevel@tonic-gate cursor = cursor->next) { 27420Sstevel@tonic-gate if (lxml_ignorable_block(cursor)) 27430Sstevel@tonic-gate continue; 27440Sstevel@tonic-gate 27450Sstevel@tonic-gate switch (lxml_xlate_element(cursor->name)) { 27460Sstevel@tonic-gate case SC_COMMON_NAME: 27470Sstevel@tonic-gate (void) lxml_get_tm_common_name(service, cursor); 27480Sstevel@tonic-gate break; 27490Sstevel@tonic-gate case SC_DESCRIPTION: 27500Sstevel@tonic-gate (void) lxml_get_tm_description(service, cursor); 27510Sstevel@tonic-gate break; 27520Sstevel@tonic-gate case SC_DOCUMENTATION: 27530Sstevel@tonic-gate (void) lxml_get_tm_documentation(service, cursor); 27540Sstevel@tonic-gate break; 2755*7887SLiane.Praza@Sun.COM case SC_PG_PATTERN: 2756*7887SLiane.Praza@Sun.COM if (lxml_get_tm_pg_pattern(service, cursor) != 0) 2757*7887SLiane.Praza@Sun.COM return (-1); 2758*7887SLiane.Praza@Sun.COM break; 27590Sstevel@tonic-gate default: 27600Sstevel@tonic-gate uu_die(gettext("illegal element \"%s\" on template " 27610Sstevel@tonic-gate "for service \"%s\"\n"), 27620Sstevel@tonic-gate cursor->name, service->sc_name); 27630Sstevel@tonic-gate } 27640Sstevel@tonic-gate } 27650Sstevel@tonic-gate 27660Sstevel@tonic-gate return (0); 27670Sstevel@tonic-gate } 27680Sstevel@tonic-gate 27690Sstevel@tonic-gate static int 27700Sstevel@tonic-gate lxml_get_default_instance(entity_t *service, xmlNodePtr definst) 27710Sstevel@tonic-gate { 27720Sstevel@tonic-gate entity_t *i; 27730Sstevel@tonic-gate xmlChar *enabled; 27740Sstevel@tonic-gate pgroup_t *pg; 27750Sstevel@tonic-gate property_t *p; 27760Sstevel@tonic-gate char *package; 27770Sstevel@tonic-gate uint64_t enabled_val = 0; 27780Sstevel@tonic-gate 27790Sstevel@tonic-gate i = internal_instance_new("default"); 27800Sstevel@tonic-gate 27810Sstevel@tonic-gate if ((enabled = xmlGetProp(definst, (xmlChar *)enabled_attr)) != NULL) { 27820Sstevel@tonic-gate enabled_val = (strcmp(true, (const char *)enabled) == 0) ? 27830Sstevel@tonic-gate 1 : 0; 27840Sstevel@tonic-gate xmlFree(enabled); 27850Sstevel@tonic-gate } 27860Sstevel@tonic-gate 27870Sstevel@tonic-gate /* 27880Sstevel@tonic-gate * New general property group with enabled boolean property set. 27890Sstevel@tonic-gate */ 27900Sstevel@tonic-gate 27910Sstevel@tonic-gate pg = internal_pgroup_new(); 27920Sstevel@tonic-gate (void) internal_attach_pgroup(i, pg); 27930Sstevel@tonic-gate 27940Sstevel@tonic-gate pg->sc_pgroup_name = (char *)scf_pg_general; 27950Sstevel@tonic-gate pg->sc_pgroup_type = (char *)scf_group_framework; 27960Sstevel@tonic-gate pg->sc_pgroup_flags = 0; 27970Sstevel@tonic-gate 27980Sstevel@tonic-gate p = internal_property_create(SCF_PROPERTY_ENABLED, SCF_TYPE_BOOLEAN, 1, 27990Sstevel@tonic-gate enabled_val); 28000Sstevel@tonic-gate 28010Sstevel@tonic-gate (void) internal_attach_property(pg, p); 28020Sstevel@tonic-gate 28030Sstevel@tonic-gate /* 28040Sstevel@tonic-gate * Add general/package property if PKGINST is set. 28050Sstevel@tonic-gate */ 28060Sstevel@tonic-gate if ((package = getenv("PKGINST")) != NULL) { 28070Sstevel@tonic-gate p = internal_property_create(SCF_PROPERTY_PACKAGE, 28080Sstevel@tonic-gate SCF_TYPE_ASTRING, 1, package); 28090Sstevel@tonic-gate 28100Sstevel@tonic-gate (void) internal_attach_property(pg, p); 28110Sstevel@tonic-gate } 28120Sstevel@tonic-gate 28130Sstevel@tonic-gate return (internal_attach_entity(service, i)); 28140Sstevel@tonic-gate } 28150Sstevel@tonic-gate 28160Sstevel@tonic-gate /* 28170Sstevel@tonic-gate * Translate an instance element into an internal property tree, added to 28185040Swesolows * service. If op is SVCCFG_OP_APPLY (i.e., apply a profile), forbid 28195040Swesolows * subelements and set the enabled property to override. 28200Sstevel@tonic-gate */ 28210Sstevel@tonic-gate static int 28225040Swesolows lxml_get_instance(entity_t *service, xmlNodePtr inst, svccfg_op_t op) 28230Sstevel@tonic-gate { 28240Sstevel@tonic-gate entity_t *i; 28250Sstevel@tonic-gate pgroup_t *pg; 28260Sstevel@tonic-gate property_t *p; 28270Sstevel@tonic-gate xmlNodePtr cursor; 28280Sstevel@tonic-gate xmlChar *enabled; 28290Sstevel@tonic-gate int r; 28300Sstevel@tonic-gate 28310Sstevel@tonic-gate /* 28320Sstevel@tonic-gate * Fetch its attributes, as appropriate. 28330Sstevel@tonic-gate */ 28340Sstevel@tonic-gate i = internal_instance_new((char *)xmlGetProp(inst, 28350Sstevel@tonic-gate (xmlChar *)name_attr)); 28360Sstevel@tonic-gate 28370Sstevel@tonic-gate /* 28380Sstevel@tonic-gate * Note that this must be done before walking the children so that 28390Sstevel@tonic-gate * sc_fmri is set in case we enter lxml_get_dependent(). 28400Sstevel@tonic-gate */ 28410Sstevel@tonic-gate r = internal_attach_entity(service, i); 28420Sstevel@tonic-gate if (r != 0) 28430Sstevel@tonic-gate return (r); 28440Sstevel@tonic-gate 28450Sstevel@tonic-gate enabled = xmlGetProp(inst, (xmlChar *)enabled_attr); 28460Sstevel@tonic-gate 28470Sstevel@tonic-gate /* 28480Sstevel@tonic-gate * New general property group with enabled boolean property set. 28490Sstevel@tonic-gate */ 28500Sstevel@tonic-gate pg = internal_pgroup_new(); 28510Sstevel@tonic-gate (void) internal_attach_pgroup(i, pg); 28520Sstevel@tonic-gate 28530Sstevel@tonic-gate pg->sc_pgroup_name = (char *)scf_pg_general; 28540Sstevel@tonic-gate pg->sc_pgroup_type = (char *)scf_group_framework; 28550Sstevel@tonic-gate pg->sc_pgroup_flags = 0; 28560Sstevel@tonic-gate 28570Sstevel@tonic-gate p = internal_property_create(SCF_PROPERTY_ENABLED, SCF_TYPE_BOOLEAN, 1, 28580Sstevel@tonic-gate (uint64_t)(strcmp(true, (const char *)enabled) == 0 ? 1 : 0)); 28590Sstevel@tonic-gate 28605040Swesolows p->sc_property_override = (op == SVCCFG_OP_APPLY); 28610Sstevel@tonic-gate 28620Sstevel@tonic-gate (void) internal_attach_property(pg, p); 28630Sstevel@tonic-gate 28640Sstevel@tonic-gate xmlFree(enabled); 28650Sstevel@tonic-gate 28660Sstevel@tonic-gate /* 28670Sstevel@tonic-gate * Walk its child elements, as appropriate. 28680Sstevel@tonic-gate */ 28690Sstevel@tonic-gate for (cursor = inst->xmlChildrenNode; cursor != NULL; 28700Sstevel@tonic-gate cursor = cursor->next) { 28710Sstevel@tonic-gate if (lxml_ignorable_block(cursor)) 28720Sstevel@tonic-gate continue; 28730Sstevel@tonic-gate 28745040Swesolows if (op == SVCCFG_OP_APPLY) { 28750Sstevel@tonic-gate semerr(gettext("Instance \"%s\" may not contain " 28760Sstevel@tonic-gate "elements in profiles.\n"), i->sc_name, 28770Sstevel@tonic-gate cursor->name); 28780Sstevel@tonic-gate return (-1); 28790Sstevel@tonic-gate } 28800Sstevel@tonic-gate 28810Sstevel@tonic-gate switch (lxml_xlate_element(cursor->name)) { 28820Sstevel@tonic-gate case SC_RESTARTER: 28830Sstevel@tonic-gate (void) lxml_get_restarter(i, cursor); 28840Sstevel@tonic-gate break; 28850Sstevel@tonic-gate case SC_DEPENDENCY: 28860Sstevel@tonic-gate (void) lxml_get_dependency(i, cursor); 28870Sstevel@tonic-gate break; 28880Sstevel@tonic-gate case SC_DEPENDENT: 28890Sstevel@tonic-gate (void) lxml_get_dependent(i, cursor); 28900Sstevel@tonic-gate break; 28910Sstevel@tonic-gate case SC_METHOD_CONTEXT: 28920Sstevel@tonic-gate (void) lxml_get_entity_method_context(i, cursor); 28930Sstevel@tonic-gate break; 28940Sstevel@tonic-gate case SC_EXEC_METHOD: 28950Sstevel@tonic-gate (void) lxml_get_exec_method(i, cursor); 28960Sstevel@tonic-gate break; 28970Sstevel@tonic-gate case SC_PROPERTY_GROUP: 28980Sstevel@tonic-gate (void) lxml_get_pgroup(i, cursor); 28990Sstevel@tonic-gate break; 29000Sstevel@tonic-gate case SC_TEMPLATE: 2901*7887SLiane.Praza@Sun.COM if (lxml_get_template(i, cursor) != 0) 2902*7887SLiane.Praza@Sun.COM return (-1); 29030Sstevel@tonic-gate break; 29040Sstevel@tonic-gate default: 29050Sstevel@tonic-gate uu_die(gettext( 29060Sstevel@tonic-gate "illegal element \"%s\" on instance \"%s\"\n"), 29070Sstevel@tonic-gate cursor->name, i->sc_name); 29080Sstevel@tonic-gate break; 29090Sstevel@tonic-gate } 29100Sstevel@tonic-gate } 29110Sstevel@tonic-gate 29120Sstevel@tonic-gate return (0); 29130Sstevel@tonic-gate } 29140Sstevel@tonic-gate 29150Sstevel@tonic-gate /* ARGSUSED1 */ 29160Sstevel@tonic-gate static int 29170Sstevel@tonic-gate lxml_get_single_instance(entity_t *entity, xmlNodePtr si) 29180Sstevel@tonic-gate { 29190Sstevel@tonic-gate pgroup_t *pg; 29200Sstevel@tonic-gate property_t *p; 29210Sstevel@tonic-gate int r; 29220Sstevel@tonic-gate 29230Sstevel@tonic-gate pg = internal_pgroup_find_or_create(entity, (char *)scf_pg_general, 29240Sstevel@tonic-gate (char *)scf_group_framework); 29250Sstevel@tonic-gate 29260Sstevel@tonic-gate p = internal_property_create(SCF_PROPERTY_SINGLE_INSTANCE, 29270Sstevel@tonic-gate SCF_TYPE_BOOLEAN, 1, (uint64_t)1); 29280Sstevel@tonic-gate 29290Sstevel@tonic-gate r = internal_attach_property(pg, p); 29300Sstevel@tonic-gate if (r != 0) { 29310Sstevel@tonic-gate internal_property_free(p); 29320Sstevel@tonic-gate return (-1); 29330Sstevel@tonic-gate } 29340Sstevel@tonic-gate 29350Sstevel@tonic-gate return (0); 29360Sstevel@tonic-gate } 29370Sstevel@tonic-gate 29380Sstevel@tonic-gate /* 29390Sstevel@tonic-gate * Translate a service element into an internal instance/property tree, added 29405040Swesolows * to bundle. If op is SVCCFG_OP_APPLY, allow only instance subelements. 29410Sstevel@tonic-gate */ 29420Sstevel@tonic-gate static int 29435040Swesolows lxml_get_service(bundle_t *bundle, xmlNodePtr svc, svccfg_op_t op) 29440Sstevel@tonic-gate { 29450Sstevel@tonic-gate entity_t *s; 29460Sstevel@tonic-gate xmlNodePtr cursor; 29470Sstevel@tonic-gate xmlChar *type; 29480Sstevel@tonic-gate xmlChar *version; 29490Sstevel@tonic-gate int e; 29500Sstevel@tonic-gate 29510Sstevel@tonic-gate /* 29520Sstevel@tonic-gate * Fetch attributes, as appropriate. 29530Sstevel@tonic-gate */ 29540Sstevel@tonic-gate s = internal_service_new((char *)xmlGetProp(svc, 29550Sstevel@tonic-gate (xmlChar *)name_attr)); 29560Sstevel@tonic-gate 2957*7887SLiane.Praza@Sun.COM version = xmlGetProp(svc, (xmlChar *)version_attr); 29580Sstevel@tonic-gate s->sc_u.sc_service.sc_service_version = atol((const char *)version); 29590Sstevel@tonic-gate xmlFree(version); 29600Sstevel@tonic-gate 29610Sstevel@tonic-gate type = xmlGetProp(svc, (xmlChar *)type_attr); 29620Sstevel@tonic-gate s->sc_u.sc_service.sc_service_type = lxml_xlate_service_type(type); 29630Sstevel@tonic-gate xmlFree(type); 29640Sstevel@tonic-gate 29650Sstevel@tonic-gate /* 29660Sstevel@tonic-gate * Walk its child elements, as appropriate. 29670Sstevel@tonic-gate */ 29680Sstevel@tonic-gate for (cursor = svc->xmlChildrenNode; cursor != NULL; 29690Sstevel@tonic-gate cursor = cursor->next) { 29700Sstevel@tonic-gate if (lxml_ignorable_block(cursor)) 29710Sstevel@tonic-gate continue; 29720Sstevel@tonic-gate 29730Sstevel@tonic-gate e = lxml_xlate_element(cursor->name); 29740Sstevel@tonic-gate 29755040Swesolows if (op == SVCCFG_OP_APPLY && e != SC_INSTANCE) { 29760Sstevel@tonic-gate semerr(gettext("Service \"%s\" may not contain the " 29770Sstevel@tonic-gate "non-instance element \"%s\" in a profile.\n"), 29780Sstevel@tonic-gate s->sc_name, cursor->name); 29790Sstevel@tonic-gate 29800Sstevel@tonic-gate return (-1); 29810Sstevel@tonic-gate } 29820Sstevel@tonic-gate 29830Sstevel@tonic-gate switch (e) { 29840Sstevel@tonic-gate case SC_INSTANCE: 2985*7887SLiane.Praza@Sun.COM if (lxml_get_instance(s, cursor, op) != 0) 2986*7887SLiane.Praza@Sun.COM return (-1); 29870Sstevel@tonic-gate break; 29880Sstevel@tonic-gate case SC_TEMPLATE: 2989*7887SLiane.Praza@Sun.COM if (lxml_get_template(s, cursor) != 0) 2990*7887SLiane.Praza@Sun.COM return (-1); 29910Sstevel@tonic-gate break; 29920Sstevel@tonic-gate case SC_STABILITY: 29930Sstevel@tonic-gate (void) lxml_get_entity_stability(s, cursor); 29940Sstevel@tonic-gate break; 29950Sstevel@tonic-gate case SC_DEPENDENCY: 29960Sstevel@tonic-gate (void) lxml_get_dependency(s, cursor); 29970Sstevel@tonic-gate break; 29980Sstevel@tonic-gate case SC_DEPENDENT: 29990Sstevel@tonic-gate (void) lxml_get_dependent(s, cursor); 30000Sstevel@tonic-gate break; 30010Sstevel@tonic-gate case SC_RESTARTER: 30020Sstevel@tonic-gate (void) lxml_get_restarter(s, cursor); 30030Sstevel@tonic-gate break; 30040Sstevel@tonic-gate case SC_EXEC_METHOD: 30050Sstevel@tonic-gate (void) lxml_get_exec_method(s, cursor); 30060Sstevel@tonic-gate break; 30070Sstevel@tonic-gate case SC_METHOD_CONTEXT: 30080Sstevel@tonic-gate (void) lxml_get_entity_method_context(s, cursor); 30090Sstevel@tonic-gate break; 30100Sstevel@tonic-gate case SC_PROPERTY_GROUP: 30110Sstevel@tonic-gate (void) lxml_get_pgroup(s, cursor); 30120Sstevel@tonic-gate break; 30130Sstevel@tonic-gate case SC_INSTANCE_CREATE_DEFAULT: 30140Sstevel@tonic-gate (void) lxml_get_default_instance(s, cursor); 30150Sstevel@tonic-gate break; 30160Sstevel@tonic-gate case SC_INSTANCE_SINGLE: 30170Sstevel@tonic-gate (void) lxml_get_single_instance(s, cursor); 30180Sstevel@tonic-gate break; 30190Sstevel@tonic-gate default: 30200Sstevel@tonic-gate uu_die(gettext( 30210Sstevel@tonic-gate "illegal element \"%s\" on service \"%s\"\n"), 30220Sstevel@tonic-gate cursor->name, s->sc_name); 30230Sstevel@tonic-gate break; 30240Sstevel@tonic-gate } 30250Sstevel@tonic-gate } 30260Sstevel@tonic-gate 30270Sstevel@tonic-gate return (internal_attach_service(bundle, s)); 30280Sstevel@tonic-gate } 30290Sstevel@tonic-gate 30300Sstevel@tonic-gate #ifdef DEBUG 30310Sstevel@tonic-gate void 30320Sstevel@tonic-gate lxml_dump(int g, xmlNodePtr p) 30330Sstevel@tonic-gate { 30340Sstevel@tonic-gate if (p && p->name) { 30350Sstevel@tonic-gate printf("%d %s\n", g, p->name); 30360Sstevel@tonic-gate 30370Sstevel@tonic-gate for (p = p->xmlChildrenNode; p != NULL; p = p->next) 30380Sstevel@tonic-gate lxml_dump(g + 1, p); 30390Sstevel@tonic-gate } 30400Sstevel@tonic-gate } 30410Sstevel@tonic-gate #endif /* DEBUG */ 30420Sstevel@tonic-gate 30430Sstevel@tonic-gate static int 30440Sstevel@tonic-gate lxml_is_known_dtd(const xmlChar *dtdname) 30450Sstevel@tonic-gate { 30460Sstevel@tonic-gate if (dtdname == NULL || 30470Sstevel@tonic-gate strcmp(MANIFEST_DTD_PATH, (const char *)dtdname) != 0) 30480Sstevel@tonic-gate return (0); 30490Sstevel@tonic-gate 30500Sstevel@tonic-gate return (1); 30510Sstevel@tonic-gate } 30520Sstevel@tonic-gate 30530Sstevel@tonic-gate static int 30540Sstevel@tonic-gate lxml_get_bundle(bundle_t *bundle, bundle_type_t bundle_type, 30555040Swesolows xmlNodePtr subbundle, svccfg_op_t op) 30560Sstevel@tonic-gate { 30570Sstevel@tonic-gate xmlNodePtr cursor; 30580Sstevel@tonic-gate xmlChar *type; 30590Sstevel@tonic-gate int e; 30600Sstevel@tonic-gate 30610Sstevel@tonic-gate /* 30620Sstevel@tonic-gate * 1. Get bundle attributes. 30630Sstevel@tonic-gate */ 3064*7887SLiane.Praza@Sun.COM type = xmlGetProp(subbundle, (xmlChar *)type_attr); 30650Sstevel@tonic-gate bundle->sc_bundle_type = lxml_xlate_bundle_type(type); 30660Sstevel@tonic-gate if (bundle->sc_bundle_type != bundle_type && 30670Sstevel@tonic-gate bundle_type != SVCCFG_UNKNOWN_BUNDLE) { 30680Sstevel@tonic-gate semerr(gettext("included bundle of different type.\n")); 30690Sstevel@tonic-gate return (-1); 30700Sstevel@tonic-gate } 30710Sstevel@tonic-gate 30720Sstevel@tonic-gate xmlFree(type); 30730Sstevel@tonic-gate 30745040Swesolows switch (op) { 30755040Swesolows case SVCCFG_OP_IMPORT: 30760Sstevel@tonic-gate if (bundle->sc_bundle_type != SVCCFG_MANIFEST) { 30770Sstevel@tonic-gate semerr(gettext("document is not a manifest.\n")); 30780Sstevel@tonic-gate return (-1); 30790Sstevel@tonic-gate } 30805040Swesolows break; 30815040Swesolows case SVCCFG_OP_APPLY: 30820Sstevel@tonic-gate if (bundle->sc_bundle_type != SVCCFG_PROFILE) { 30830Sstevel@tonic-gate semerr(gettext("document is not a profile.\n")); 30840Sstevel@tonic-gate return (-1); 30850Sstevel@tonic-gate } 30865040Swesolows break; 30875040Swesolows case SVCCFG_OP_RESTORE: 30885040Swesolows if (bundle->sc_bundle_type != SVCCFG_ARCHIVE) { 30895040Swesolows semerr(gettext("document is not an archive.\n")); 30905040Swesolows return (-1); 30915040Swesolows } 30925040Swesolows break; 30930Sstevel@tonic-gate } 30940Sstevel@tonic-gate 3095*7887SLiane.Praza@Sun.COM if (((bundle->sc_bundle_name = xmlGetProp(subbundle, 3096*7887SLiane.Praza@Sun.COM (xmlChar *)name_attr)) == NULL) || (*bundle->sc_bundle_name == 0)) { 30970Sstevel@tonic-gate semerr(gettext("service bundle lacks name attribute\n")); 30980Sstevel@tonic-gate return (-1); 30990Sstevel@tonic-gate } 31000Sstevel@tonic-gate 31010Sstevel@tonic-gate /* 31020Sstevel@tonic-gate * 2. Get services, descend into each one and build state. 31030Sstevel@tonic-gate */ 31040Sstevel@tonic-gate for (cursor = subbundle->xmlChildrenNode; cursor != NULL; 31050Sstevel@tonic-gate cursor = cursor->next) { 31060Sstevel@tonic-gate if (lxml_ignorable_block(cursor)) 31070Sstevel@tonic-gate continue; 31080Sstevel@tonic-gate 31090Sstevel@tonic-gate e = lxml_xlate_element(cursor->name); 31100Sstevel@tonic-gate 31110Sstevel@tonic-gate switch (e) { 31120Sstevel@tonic-gate case SC_XI_INCLUDE: 31130Sstevel@tonic-gate continue; 31140Sstevel@tonic-gate 31150Sstevel@tonic-gate case SC_SERVICE_BUNDLE: 31165040Swesolows if (lxml_get_bundle(bundle, bundle_type, cursor, op)) 31170Sstevel@tonic-gate return (-1); 31180Sstevel@tonic-gate break; 31190Sstevel@tonic-gate case SC_SERVICE: 3120*7887SLiane.Praza@Sun.COM if (lxml_get_service(bundle, cursor, op) != 0) 3121*7887SLiane.Praza@Sun.COM return (-1); 31220Sstevel@tonic-gate break; 31230Sstevel@tonic-gate } 31240Sstevel@tonic-gate } 31250Sstevel@tonic-gate 31260Sstevel@tonic-gate return (0); 31270Sstevel@tonic-gate } 31280Sstevel@tonic-gate 31290Sstevel@tonic-gate /* 31300Sstevel@tonic-gate * Load an XML tree from filename and translate it into an internal service 31315040Swesolows * tree bundle. Require that the bundle be of appropriate type for the 31325040Swesolows * operation: archive for RESTORE, manifest for IMPORT, profile for APPLY. 31330Sstevel@tonic-gate */ 31340Sstevel@tonic-gate int 31355040Swesolows lxml_get_bundle_file(bundle_t *bundle, const char *filename, svccfg_op_t op) 31360Sstevel@tonic-gate { 31370Sstevel@tonic-gate xmlDocPtr document; 31380Sstevel@tonic-gate xmlNodePtr cursor; 31390Sstevel@tonic-gate xmlDtdPtr dtd = NULL; 31400Sstevel@tonic-gate xmlValidCtxtPtr vcp; 31410Sstevel@tonic-gate boolean_t do_validate; 31420Sstevel@tonic-gate char *dtdpath = NULL; 31430Sstevel@tonic-gate int r; 31440Sstevel@tonic-gate 31450Sstevel@tonic-gate /* 31464740Sjeanm * Verify we can read the file before we try to parse it. 31474740Sjeanm */ 31484740Sjeanm if (access(filename, R_OK | F_OK) == -1) { 31494740Sjeanm semerr(gettext("unable to open file: %s\n"), strerror(errno)); 31504740Sjeanm return (-1); 31514740Sjeanm } 31524740Sjeanm 31534740Sjeanm /* 31540Sstevel@tonic-gate * Until libxml2 addresses DTD-based validation with XInclude, we don't 31550Sstevel@tonic-gate * validate service profiles (i.e. the apply path). 31560Sstevel@tonic-gate */ 31575040Swesolows do_validate = (op != SVCCFG_OP_APPLY) && 31585040Swesolows (getenv("SVCCFG_NOVALIDATE") == NULL); 31590Sstevel@tonic-gate if (do_validate) 31600Sstevel@tonic-gate dtdpath = getenv("SVCCFG_DTD"); 31610Sstevel@tonic-gate 31620Sstevel@tonic-gate if (dtdpath != NULL) 31630Sstevel@tonic-gate xmlLoadExtDtdDefaultValue = 0; 31640Sstevel@tonic-gate 31654740Sjeanm if ((document = xmlReadFile(filename, NULL, 0)) == NULL) { 31660Sstevel@tonic-gate semerr(gettext("couldn't parse document\n")); 31670Sstevel@tonic-gate return (-1); 31680Sstevel@tonic-gate } 31690Sstevel@tonic-gate 31700Sstevel@tonic-gate /* 31710Sstevel@tonic-gate * Verify that this is a document type we understand. 31720Sstevel@tonic-gate */ 31730Sstevel@tonic-gate if ((dtd = xmlGetIntSubset(document)) == NULL) { 31740Sstevel@tonic-gate semerr(gettext("document has no DTD\n")); 31750Sstevel@tonic-gate return (-1); 31760Sstevel@tonic-gate } 31770Sstevel@tonic-gate 31780Sstevel@tonic-gate if (!lxml_is_known_dtd(dtd->SystemID)) { 31790Sstevel@tonic-gate semerr(gettext("document DTD unknown; not service bundle?\n")); 31800Sstevel@tonic-gate return (-1); 31810Sstevel@tonic-gate } 31820Sstevel@tonic-gate 31830Sstevel@tonic-gate if ((cursor = xmlDocGetRootElement(document)) == NULL) { 31840Sstevel@tonic-gate semerr(gettext("document is empty\n")); 31850Sstevel@tonic-gate xmlFreeDoc(document); 31860Sstevel@tonic-gate return (-1); 31870Sstevel@tonic-gate } 31880Sstevel@tonic-gate 31890Sstevel@tonic-gate if (xmlStrcmp(cursor->name, (const xmlChar *)"service_bundle") != 0) { 31900Sstevel@tonic-gate semerr(gettext("document is not a service bundle\n")); 31910Sstevel@tonic-gate xmlFreeDoc(document); 31920Sstevel@tonic-gate return (-1); 31930Sstevel@tonic-gate } 31940Sstevel@tonic-gate 31950Sstevel@tonic-gate 31960Sstevel@tonic-gate if (dtdpath != NULL) { 31970Sstevel@tonic-gate dtd = xmlParseDTD(NULL, (xmlChar *)dtdpath); 31980Sstevel@tonic-gate if (dtd == NULL) { 31990Sstevel@tonic-gate semerr(gettext("Could not parse DTD \"%s\".\n"), 32000Sstevel@tonic-gate dtdpath); 32010Sstevel@tonic-gate return (-1); 32020Sstevel@tonic-gate } 32030Sstevel@tonic-gate 32040Sstevel@tonic-gate if (document->extSubset != NULL) 32050Sstevel@tonic-gate xmlFreeDtd(document->extSubset); 32060Sstevel@tonic-gate 32070Sstevel@tonic-gate document->extSubset = dtd; 32080Sstevel@tonic-gate } 32090Sstevel@tonic-gate 32104740Sjeanm if (xmlXIncludeProcessFlags(document, XML_PARSE_XINCLUDE) == -1) { 32110Sstevel@tonic-gate semerr(gettext("couldn't handle XInclude statements " 32124740Sjeanm "in document\n")); 32130Sstevel@tonic-gate return (-1); 32140Sstevel@tonic-gate } 32150Sstevel@tonic-gate 32160Sstevel@tonic-gate if (do_validate) { 32170Sstevel@tonic-gate vcp = xmlNewValidCtxt(); 32180Sstevel@tonic-gate if (vcp == NULL) 32190Sstevel@tonic-gate uu_die(gettext("could not allocate memory")); 32200Sstevel@tonic-gate vcp->warning = xmlParserValidityWarning; 32210Sstevel@tonic-gate vcp->error = xmlParserValidityError; 32220Sstevel@tonic-gate 32230Sstevel@tonic-gate r = xmlValidateDocument(vcp, document); 32240Sstevel@tonic-gate 32250Sstevel@tonic-gate xmlFreeValidCtxt(vcp); 32260Sstevel@tonic-gate 32270Sstevel@tonic-gate if (r == 0) { 32280Sstevel@tonic-gate semerr(gettext("Document is not valid.\n")); 32290Sstevel@tonic-gate xmlFreeDoc(document); 32300Sstevel@tonic-gate return (-1); 32310Sstevel@tonic-gate } 32320Sstevel@tonic-gate } 32330Sstevel@tonic-gate 32340Sstevel@tonic-gate 32350Sstevel@tonic-gate #ifdef DEBUG 32360Sstevel@tonic-gate lxml_dump(0, cursor); 32370Sstevel@tonic-gate #endif /* DEBUG */ 32380Sstevel@tonic-gate 32395040Swesolows r = lxml_get_bundle(bundle, SVCCFG_UNKNOWN_BUNDLE, cursor, op); 32400Sstevel@tonic-gate 32410Sstevel@tonic-gate xmlFreeDoc(document); 32420Sstevel@tonic-gate 32430Sstevel@tonic-gate return (r); 32440Sstevel@tonic-gate } 32450Sstevel@tonic-gate 32460Sstevel@tonic-gate int 32470Sstevel@tonic-gate lxml_inventory(const char *filename) 32480Sstevel@tonic-gate { 32490Sstevel@tonic-gate bundle_t *b; 32500Sstevel@tonic-gate uu_list_walk_t *svcs, *insts; 32510Sstevel@tonic-gate entity_t *svc, *inst; 32520Sstevel@tonic-gate 32530Sstevel@tonic-gate b = internal_bundle_new(); 32540Sstevel@tonic-gate 32555040Swesolows if (lxml_get_bundle_file(b, filename, SVCCFG_OP_IMPORT) != 0) { 32560Sstevel@tonic-gate internal_bundle_free(b); 32570Sstevel@tonic-gate return (-1); 32580Sstevel@tonic-gate } 32590Sstevel@tonic-gate 32600Sstevel@tonic-gate svcs = uu_list_walk_start(b->sc_bundle_services, 0); 32610Sstevel@tonic-gate if (svcs == NULL) 32620Sstevel@tonic-gate uu_die(gettext("Couldn't walk services")); 32630Sstevel@tonic-gate 32640Sstevel@tonic-gate while ((svc = uu_list_walk_next(svcs)) != NULL) { 32650Sstevel@tonic-gate uu_list_t *inst_list; 32660Sstevel@tonic-gate 32670Sstevel@tonic-gate inst_list = svc->sc_u.sc_service.sc_service_instances; 32680Sstevel@tonic-gate insts = uu_list_walk_start(inst_list, 0); 32690Sstevel@tonic-gate if (insts == NULL) 32700Sstevel@tonic-gate uu_die(gettext("Couldn't walk instances")); 32710Sstevel@tonic-gate 32720Sstevel@tonic-gate while ((inst = uu_list_walk_next(insts)) != NULL) 32730Sstevel@tonic-gate (void) printf("svc:/%s:%s\n", svc->sc_name, 32740Sstevel@tonic-gate inst->sc_name); 32750Sstevel@tonic-gate 32760Sstevel@tonic-gate uu_list_walk_end(insts); 32770Sstevel@tonic-gate } 32780Sstevel@tonic-gate 32790Sstevel@tonic-gate uu_list_walk_end(svcs); 32800Sstevel@tonic-gate 32810Sstevel@tonic-gate svcs = uu_list_walk_start(b->sc_bundle_services, 0); 32820Sstevel@tonic-gate while ((svc = uu_list_walk_next(svcs)) != NULL) { 32830Sstevel@tonic-gate (void) fputs("svc:/", stdout); 32840Sstevel@tonic-gate (void) puts(svc->sc_name); 32850Sstevel@tonic-gate } 32860Sstevel@tonic-gate uu_list_walk_end(svcs); 32870Sstevel@tonic-gate 32880Sstevel@tonic-gate internal_bundle_free(b); 32890Sstevel@tonic-gate 32900Sstevel@tonic-gate return (0); 32910Sstevel@tonic-gate } 3292