17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
23ba1637f8Smh138676  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate /*
287c478bd9Sstevel@tonic-gate  * inetadm - administer services controlled by inetd and print out inetd
297c478bd9Sstevel@tonic-gate  * service related information.
307c478bd9Sstevel@tonic-gate  */
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate #include <locale.h>
337c478bd9Sstevel@tonic-gate #include <libintl.h>
347c478bd9Sstevel@tonic-gate #include <libscf.h>
357c478bd9Sstevel@tonic-gate #include <libscf_priv.h>
367c478bd9Sstevel@tonic-gate #include <libuutil.h>
377c478bd9Sstevel@tonic-gate #include <stddef.h>
387c478bd9Sstevel@tonic-gate #include <stdio.h>
397c478bd9Sstevel@tonic-gate #include <stdlib.h>
407c478bd9Sstevel@tonic-gate #include <string.h>
417c478bd9Sstevel@tonic-gate #include <syslog.h>
427c478bd9Sstevel@tonic-gate #include <inetsvc.h>
437c478bd9Sstevel@tonic-gate #include <errno.h>
447c478bd9Sstevel@tonic-gate 
457c478bd9Sstevel@tonic-gate #ifndef TEXT_DOMAIN
467c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN	"SUNW_OST_OSCMD"
477c478bd9Sstevel@tonic-gate #endif /* TEXT_DOMAIN */
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate /* Strings for output to the user, and checking user's input */
507c478bd9Sstevel@tonic-gate 
517c478bd9Sstevel@tonic-gate #define	INETADM_TRUE_STR		"TRUE"
527c478bd9Sstevel@tonic-gate #define	INETADM_FALSE_STR		"FALSE"
537c478bd9Sstevel@tonic-gate #define	INETADM_ENABLED_STR		"enabled"
547c478bd9Sstevel@tonic-gate #define	INETADM_DISABLED_STR		"disabled"
557c478bd9Sstevel@tonic-gate #define	INETADM_DEFAULT_STR		"default"
567c478bd9Sstevel@tonic-gate 
577c478bd9Sstevel@tonic-gate /* String for checking if an instance is under inetd's control. */
587c478bd9Sstevel@tonic-gate 
597c478bd9Sstevel@tonic-gate #define	INETADM_INETD_STR		"network/inetd"
607c478bd9Sstevel@tonic-gate 
617c478bd9Sstevel@tonic-gate /*
627c478bd9Sstevel@tonic-gate  * Used to hold a list of scf_value_t's whilst performing a transaction
637c478bd9Sstevel@tonic-gate  * to write a proto list back.
647c478bd9Sstevel@tonic-gate  */
657c478bd9Sstevel@tonic-gate typedef struct scf_val_el {
667c478bd9Sstevel@tonic-gate 	scf_value_t		*val;
677c478bd9Sstevel@tonic-gate 	uu_list_node_t		link;
687c478bd9Sstevel@tonic-gate } scf_val_el_t;
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate /*
717c478bd9Sstevel@tonic-gate  * Structure used to encapsulate argc and argv so they can be passed using the
727c478bd9Sstevel@tonic-gate  * single data argument supplied by scf_walk_fmri() for the consumption of
737c478bd9Sstevel@tonic-gate  * modify_inst_props_cb().
747c478bd9Sstevel@tonic-gate  */
757c478bd9Sstevel@tonic-gate typedef struct arglist {
767c478bd9Sstevel@tonic-gate 	int	argc;
777c478bd9Sstevel@tonic-gate 	char	**argv;
787c478bd9Sstevel@tonic-gate } arglist_t;
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate static scf_handle_t *h;
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate static void
scfdie()837c478bd9Sstevel@tonic-gate scfdie()
847c478bd9Sstevel@tonic-gate {
857c478bd9Sstevel@tonic-gate 	uu_die(gettext("Unexpected libscf error: %s.  Exiting.\n"),
867c478bd9Sstevel@tonic-gate 	    scf_strerror(scf_error()));
877c478bd9Sstevel@tonic-gate }
887c478bd9Sstevel@tonic-gate 
897c478bd9Sstevel@tonic-gate static void
usage(boolean_t detailed)907c478bd9Sstevel@tonic-gate usage(boolean_t detailed)
917c478bd9Sstevel@tonic-gate {
927c478bd9Sstevel@tonic-gate 
937c478bd9Sstevel@tonic-gate 	uu_warn(gettext(
947c478bd9Sstevel@tonic-gate 	    "Usage:\n"
957c478bd9Sstevel@tonic-gate 	    "  inetadm\n"
967c478bd9Sstevel@tonic-gate 	    "  inetadm -?\n"
977c478bd9Sstevel@tonic-gate 	    "  inetadm -p\n"
987c478bd9Sstevel@tonic-gate 	    "  inetadm -l {FMRI | pattern}...\n"
997c478bd9Sstevel@tonic-gate 	    "  inetadm -e {FMRI | pattern}...\n"
1007c478bd9Sstevel@tonic-gate 	    "  inetadm -d {FMRI | pattern}...\n"
1017c478bd9Sstevel@tonic-gate 	    "  inetadm -m {FMRI | pattern}... {name=value}...\n"
1027c478bd9Sstevel@tonic-gate 	    "  inetadm -M {name=value}...\n"));
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate 	if (!detailed)
1057c478bd9Sstevel@tonic-gate 		exit(UU_EXIT_USAGE);
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout, gettext(
1087c478bd9Sstevel@tonic-gate 	    "\n"
1097c478bd9Sstevel@tonic-gate 	    "Without any options inetadm lists all inetd managed services.\n"
1107c478bd9Sstevel@tonic-gate 	    "\n"
1117c478bd9Sstevel@tonic-gate 	    "Options:\n"
1127c478bd9Sstevel@tonic-gate 	    "  -?	Print help.\n"
1137c478bd9Sstevel@tonic-gate 	    "  -p	List all default inetd property values.\n"
1147c478bd9Sstevel@tonic-gate 	    "  -l 	List all inetd property values for the inet "
1157c478bd9Sstevel@tonic-gate 	    "service(s).\n"
1167c478bd9Sstevel@tonic-gate 	    "  -e	Enable the inet service(s).\n"
1177c478bd9Sstevel@tonic-gate 	    "  -d	Disable the inet service(s).\n"
1187c478bd9Sstevel@tonic-gate 	    "  -m	Modify the inet service(s) inetd property values.\n"
1197c478bd9Sstevel@tonic-gate 	    "  -M	Modify default inetd property values.\n"));
1207c478bd9Sstevel@tonic-gate }
1217c478bd9Sstevel@tonic-gate 
1227c478bd9Sstevel@tonic-gate /*
1237c478bd9Sstevel@tonic-gate  * Add the proto list contained in array 'plist' to entry 'entry', storing
1247c478bd9Sstevel@tonic-gate  * aside the scf_value_t's created and added to the entry in a list that the
1257c478bd9Sstevel@tonic-gate  * pointer referenced by sv_list is made to point at.
1267c478bd9Sstevel@tonic-gate  */
1277c478bd9Sstevel@tonic-gate static void
add_proto_list(scf_transaction_entry_t * entry,scf_handle_t * hdl,char ** plist,uu_list_t ** sv_list)1287c478bd9Sstevel@tonic-gate add_proto_list(scf_transaction_entry_t *entry, scf_handle_t *hdl,
1297c478bd9Sstevel@tonic-gate     char **plist, uu_list_t **sv_list)
1307c478bd9Sstevel@tonic-gate {
1317c478bd9Sstevel@tonic-gate 	scf_val_el_t		*sv_el;
1327c478bd9Sstevel@tonic-gate 	int			i;
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate 	static uu_list_pool_t	*sv_pool = NULL;
1357c478bd9Sstevel@tonic-gate 
1367c478bd9Sstevel@tonic-gate 	if ((sv_pool == NULL) &&
1377c478bd9Sstevel@tonic-gate 	    ((sv_pool = uu_list_pool_create("sv_pool",
1387c478bd9Sstevel@tonic-gate 	    sizeof (scf_val_el_t), offsetof(scf_val_el_t, link), NULL,
1397c478bd9Sstevel@tonic-gate 	    UU_LIST_POOL_DEBUG)) == NULL))
1407c478bd9Sstevel@tonic-gate 		uu_die(gettext("Error: %s.\n"), uu_strerror(uu_error()));
1417c478bd9Sstevel@tonic-gate 
1427c478bd9Sstevel@tonic-gate 	if ((*sv_list = uu_list_create(sv_pool, NULL, 0)) == NULL)
1437c478bd9Sstevel@tonic-gate 		uu_die(gettext("Error: %s.\n"), uu_strerror(uu_error()));
1447c478bd9Sstevel@tonic-gate 
1457c478bd9Sstevel@tonic-gate 	for (i = 0; plist[i] != NULL; i++) {
1467c478bd9Sstevel@tonic-gate 		if ((sv_el = malloc(sizeof (scf_val_el_t))) == NULL)
1477c478bd9Sstevel@tonic-gate 			uu_die(gettext("Error:"));
1487c478bd9Sstevel@tonic-gate 
1497c478bd9Sstevel@tonic-gate 		if (((sv_el->val = scf_value_create(hdl)) == NULL) ||
1507c478bd9Sstevel@tonic-gate 		    (scf_value_set_astring(sv_el->val, plist[i]) != 0) ||
1517c478bd9Sstevel@tonic-gate 		    (scf_entry_add_value(entry, sv_el->val) != 0))
1527c478bd9Sstevel@tonic-gate 			scfdie();
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate 		uu_list_node_init(sv_el, &sv_el->link, sv_pool);
1557c478bd9Sstevel@tonic-gate 		(void) uu_list_insert_after(*sv_list, NULL, sv_el);
1567c478bd9Sstevel@tonic-gate 	}
1577c478bd9Sstevel@tonic-gate }
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate /*
1607c478bd9Sstevel@tonic-gate  * A counterpart to add_proto_list(), this function removes and frees the
1617c478bd9Sstevel@tonic-gate  * scf_value_t's it added to entry 'entry'.
1627c478bd9Sstevel@tonic-gate  */
1637c478bd9Sstevel@tonic-gate static void
remove_proto_list(scf_transaction_entry_t * entry,uu_list_t * sv_list)1647c478bd9Sstevel@tonic-gate remove_proto_list(scf_transaction_entry_t *entry, uu_list_t *sv_list)
1657c478bd9Sstevel@tonic-gate {
1667c478bd9Sstevel@tonic-gate 	scf_val_el_t	*sv_el;
1677c478bd9Sstevel@tonic-gate 	void		*cookie = NULL;
1687c478bd9Sstevel@tonic-gate 
1697c478bd9Sstevel@tonic-gate 	scf_entry_reset(entry);
1707c478bd9Sstevel@tonic-gate 
1717c478bd9Sstevel@tonic-gate 	while ((sv_el = uu_list_teardown(sv_list, &cookie)) != NULL) {
1727c478bd9Sstevel@tonic-gate 		scf_value_destroy(sv_el->val);
1737c478bd9Sstevel@tonic-gate 		free(sv_el);
1747c478bd9Sstevel@tonic-gate 	}
1757c478bd9Sstevel@tonic-gate 
1767c478bd9Sstevel@tonic-gate 	uu_list_destroy(sv_list);
1777c478bd9Sstevel@tonic-gate }
1787c478bd9Sstevel@tonic-gate 
1797c478bd9Sstevel@tonic-gate /*
1807c478bd9Sstevel@tonic-gate  * modify_prop takes an instance, property group, property name, type, and
1817c478bd9Sstevel@tonic-gate  * value, and modifies the specified property in the repository to the
1827c478bd9Sstevel@tonic-gate  * submitted value.
1837c478bd9Sstevel@tonic-gate  */
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate static void
modify_prop(const scf_instance_t * inst,const char * pg,const char * prop,scf_type_t type,void * value)1867c478bd9Sstevel@tonic-gate modify_prop(const scf_instance_t *inst, const char *pg, const char *prop,
1877c478bd9Sstevel@tonic-gate     scf_type_t type, void *value)
1887c478bd9Sstevel@tonic-gate {
1897c478bd9Sstevel@tonic-gate 	scf_transaction_t		*tx;
1907c478bd9Sstevel@tonic-gate 	scf_transaction_entry_t		*ent;
1917c478bd9Sstevel@tonic-gate 	scf_propertygroup_t		*gpg;
1927c478bd9Sstevel@tonic-gate 	scf_property_t			*eprop;
1937c478bd9Sstevel@tonic-gate 	scf_value_t			*v;
1947c478bd9Sstevel@tonic-gate 	int				ret, create = 0;
1957c478bd9Sstevel@tonic-gate 	char				*fmri;
1967c478bd9Sstevel@tonic-gate 	ssize_t				max_fmri_len;
1977c478bd9Sstevel@tonic-gate 
1987c478bd9Sstevel@tonic-gate 	if ((gpg = scf_pg_create(h)) == NULL ||
1997c478bd9Sstevel@tonic-gate 	    (eprop = scf_property_create(h)) == NULL ||
2007c478bd9Sstevel@tonic-gate 	    (v = scf_value_create(h)) == NULL)
2017c478bd9Sstevel@tonic-gate 		scfdie();
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate 	/* Get the property group or create it if it is missing. */
2047c478bd9Sstevel@tonic-gate 	if (scf_instance_get_pg(inst, pg, gpg) == -1) {
2057c478bd9Sstevel@tonic-gate 		if (scf_error() != SCF_ERROR_NOT_FOUND)
2067c478bd9Sstevel@tonic-gate 			scfdie();
2077c478bd9Sstevel@tonic-gate 
2087c478bd9Sstevel@tonic-gate 		max_fmri_len = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH);
2097c478bd9Sstevel@tonic-gate 		if ((fmri = malloc(max_fmri_len + 1)) == NULL)
2107c478bd9Sstevel@tonic-gate 			uu_die(gettext("Error: Out of memory.\n"));
2117c478bd9Sstevel@tonic-gate 
2127c478bd9Sstevel@tonic-gate 		if (scf_instance_to_fmri(inst, fmri, max_fmri_len + 1) < 0)
2137c478bd9Sstevel@tonic-gate 			scfdie();
2147c478bd9Sstevel@tonic-gate 
2157c478bd9Sstevel@tonic-gate 		syslog(LOG_NOTICE, "inetadm: Property group \"%s\" missing "
2167c478bd9Sstevel@tonic-gate 		    "from \"%s\", attempting to add it.\n", pg, fmri);
2177c478bd9Sstevel@tonic-gate 		free(fmri);
2187c478bd9Sstevel@tonic-gate 
2197c478bd9Sstevel@tonic-gate 		if (scf_instance_add_pg(inst, pg, SCF_GROUP_FRAMEWORK, 0,
2207c478bd9Sstevel@tonic-gate 		    gpg) == -1) {
2217c478bd9Sstevel@tonic-gate 			switch (scf_error()) {
2227c478bd9Sstevel@tonic-gate 			case SCF_ERROR_EXISTS:
2237c478bd9Sstevel@tonic-gate 				break;
2247c478bd9Sstevel@tonic-gate 			case SCF_ERROR_PERMISSION_DENIED:
2257c478bd9Sstevel@tonic-gate 				uu_die(gettext("Error: Permission denied.\n"));
2267c478bd9Sstevel@tonic-gate 			default:
2277c478bd9Sstevel@tonic-gate 				scfdie();
2287c478bd9Sstevel@tonic-gate 			}
2297c478bd9Sstevel@tonic-gate 		}
2307c478bd9Sstevel@tonic-gate 	}
2317c478bd9Sstevel@tonic-gate 
2327c478bd9Sstevel@tonic-gate 	if (scf_pg_get_property(gpg, prop, eprop) == -1) {
2337c478bd9Sstevel@tonic-gate 		if (scf_error() != SCF_ERROR_NOT_FOUND)
2347c478bd9Sstevel@tonic-gate 			scfdie();
2357c478bd9Sstevel@tonic-gate 
2367c478bd9Sstevel@tonic-gate 		create = 1;
2377c478bd9Sstevel@tonic-gate 	}
2387c478bd9Sstevel@tonic-gate 
2397c478bd9Sstevel@tonic-gate 	if ((tx = scf_transaction_create(h)) == NULL ||
2407c478bd9Sstevel@tonic-gate 	    (ent = scf_entry_create(h)) == NULL)
2417c478bd9Sstevel@tonic-gate 		scfdie();
2427c478bd9Sstevel@tonic-gate 
2437c478bd9Sstevel@tonic-gate 	do {
2447c478bd9Sstevel@tonic-gate 		uu_list_t	*sv_list;
2457c478bd9Sstevel@tonic-gate 
2467c478bd9Sstevel@tonic-gate 		if (scf_transaction_start(tx, gpg) == -1) {
2477c478bd9Sstevel@tonic-gate 			if (scf_error() != SCF_ERROR_PERMISSION_DENIED)
2487c478bd9Sstevel@tonic-gate 				scfdie();
2497c478bd9Sstevel@tonic-gate 
2507c478bd9Sstevel@tonic-gate 			uu_die(gettext("Error: Permission denied.\n"));
2517c478bd9Sstevel@tonic-gate 		}
2527c478bd9Sstevel@tonic-gate 
2537c478bd9Sstevel@tonic-gate 		/* Modify the property or create it if it is missing */
2547c478bd9Sstevel@tonic-gate 		if (create)
2557c478bd9Sstevel@tonic-gate 			ret = scf_transaction_property_new(tx, ent, prop, type);
2567c478bd9Sstevel@tonic-gate 		else
2577c478bd9Sstevel@tonic-gate 			ret = scf_transaction_property_change_type(tx, ent,
2587c478bd9Sstevel@tonic-gate 			    prop, type);
2597c478bd9Sstevel@tonic-gate 		if (ret == -1)
2607c478bd9Sstevel@tonic-gate 			scfdie();
2617c478bd9Sstevel@tonic-gate 
2627c478bd9Sstevel@tonic-gate 		switch (type) {
2637c478bd9Sstevel@tonic-gate 		case SCF_TYPE_BOOLEAN:
2647c478bd9Sstevel@tonic-gate 			scf_value_set_boolean(v, *(uint8_t *)value);
2657c478bd9Sstevel@tonic-gate 			break;
2667c478bd9Sstevel@tonic-gate 		case SCF_TYPE_INTEGER:
2677c478bd9Sstevel@tonic-gate 			scf_value_set_integer(v, *(int64_t *)value);
2687c478bd9Sstevel@tonic-gate 			break;
2697c478bd9Sstevel@tonic-gate 		case SCF_TYPE_ASTRING:
2707c478bd9Sstevel@tonic-gate 			if (strcmp(prop, PR_PROTO_NAME) == 0) {
2717c478bd9Sstevel@tonic-gate 				add_proto_list(ent, h, (char **)value,
2727c478bd9Sstevel@tonic-gate 				    &sv_list);
2737c478bd9Sstevel@tonic-gate 			} else if (scf_value_set_astring(v, value) == -1) {
2747c478bd9Sstevel@tonic-gate 				scfdie();
2757c478bd9Sstevel@tonic-gate 			}
2767c478bd9Sstevel@tonic-gate 			break;
2777c478bd9Sstevel@tonic-gate 		default:
2787c478bd9Sstevel@tonic-gate 			uu_die(gettext("Error: Internal inetadm error"));
2797c478bd9Sstevel@tonic-gate 		}
2807c478bd9Sstevel@tonic-gate 
2817c478bd9Sstevel@tonic-gate 		if ((strcmp(prop, PR_PROTO_NAME) != 0) &&
2827c478bd9Sstevel@tonic-gate 		    (scf_entry_add_value(ent, v) == -1))
2837c478bd9Sstevel@tonic-gate 			scfdie();
2847c478bd9Sstevel@tonic-gate 
2857c478bd9Sstevel@tonic-gate 		ret = scf_transaction_commit(tx);
2867c478bd9Sstevel@tonic-gate 		if (ret == -1) {
2877c478bd9Sstevel@tonic-gate 			if (scf_error() != SCF_ERROR_PERMISSION_DENIED)
2887c478bd9Sstevel@tonic-gate 				scfdie();
2897c478bd9Sstevel@tonic-gate 
2907c478bd9Sstevel@tonic-gate 			uu_die(gettext("Error: Permission denied.\n"));
2917c478bd9Sstevel@tonic-gate 		}
2927c478bd9Sstevel@tonic-gate 
2937c478bd9Sstevel@tonic-gate 		scf_transaction_reset(tx);
2947c478bd9Sstevel@tonic-gate 
2957c478bd9Sstevel@tonic-gate 		if (ret == 0) {
2967c478bd9Sstevel@tonic-gate 			if (scf_pg_update(gpg) == -1)
2977c478bd9Sstevel@tonic-gate 				scfdie();
2987c478bd9Sstevel@tonic-gate 		}
2997c478bd9Sstevel@tonic-gate 
3007c478bd9Sstevel@tonic-gate 		if (strcmp(prop, PR_PROTO_NAME) == 0)
3017c478bd9Sstevel@tonic-gate 			remove_proto_list(ent, sv_list);
3027c478bd9Sstevel@tonic-gate 
3037c478bd9Sstevel@tonic-gate 	} while (ret == 0);
3047c478bd9Sstevel@tonic-gate 
3057c478bd9Sstevel@tonic-gate 	scf_value_destroy(v);
3067c478bd9Sstevel@tonic-gate 	scf_entry_destroy(ent);
3077c478bd9Sstevel@tonic-gate 	scf_transaction_destroy(tx);
3087c478bd9Sstevel@tonic-gate 	scf_property_destroy(eprop);
3097c478bd9Sstevel@tonic-gate 	scf_pg_destroy(gpg);
3107c478bd9Sstevel@tonic-gate }
3117c478bd9Sstevel@tonic-gate 
3127c478bd9Sstevel@tonic-gate /*
3137c478bd9Sstevel@tonic-gate  * delete_prop takes an instance, property group name and property, and
3147c478bd9Sstevel@tonic-gate  * deletes the specified property from the repository.
3157c478bd9Sstevel@tonic-gate  */
3167c478bd9Sstevel@tonic-gate 
3177c478bd9Sstevel@tonic-gate static void
delete_prop(const scf_instance_t * inst,const char * pg,const char * prop)3187c478bd9Sstevel@tonic-gate delete_prop(const scf_instance_t *inst, const char *pg, const char *prop)
3197c478bd9Sstevel@tonic-gate {
3207c478bd9Sstevel@tonic-gate 	scf_transaction_t		*tx;
3217c478bd9Sstevel@tonic-gate 	scf_transaction_entry_t		*ent;
3227c478bd9Sstevel@tonic-gate 	scf_propertygroup_t		*gpg;
3237c478bd9Sstevel@tonic-gate 	scf_property_t			*eprop;
3247c478bd9Sstevel@tonic-gate 	int				ret;
3257c478bd9Sstevel@tonic-gate 
3267c478bd9Sstevel@tonic-gate 	if ((gpg = scf_pg_create(h)) == NULL ||
3277c478bd9Sstevel@tonic-gate 	    (eprop = scf_property_create(h)) == NULL ||
3287c478bd9Sstevel@tonic-gate 	    (tx = scf_transaction_create(h)) == NULL ||
3297c478bd9Sstevel@tonic-gate 	    (ent = scf_entry_create(h)) == NULL)
3307c478bd9Sstevel@tonic-gate 		scfdie();
3317c478bd9Sstevel@tonic-gate 
3327c478bd9Sstevel@tonic-gate 	if (scf_instance_get_pg(inst, pg, gpg) != SCF_SUCCESS) {
3337c478bd9Sstevel@tonic-gate 		if (scf_error() != SCF_ERROR_NOT_FOUND)
3347c478bd9Sstevel@tonic-gate 			scfdie();
3357c478bd9Sstevel@tonic-gate 
3367c478bd9Sstevel@tonic-gate 		uu_die(gettext("Error: \"%s\" property group missing.\n"), pg);
3377c478bd9Sstevel@tonic-gate 	}
3387c478bd9Sstevel@tonic-gate 
3397c478bd9Sstevel@tonic-gate 	do {
3407c478bd9Sstevel@tonic-gate 		if (scf_transaction_start(tx, gpg) != SCF_SUCCESS) {
3417c478bd9Sstevel@tonic-gate 			if (scf_error() != SCF_ERROR_PERMISSION_DENIED)
3427c478bd9Sstevel@tonic-gate 				scfdie();
3437c478bd9Sstevel@tonic-gate 
3447c478bd9Sstevel@tonic-gate 			uu_die(gettext("Error: Permission denied.\n"));
3457c478bd9Sstevel@tonic-gate 		}
3467c478bd9Sstevel@tonic-gate 
3477c478bd9Sstevel@tonic-gate 		if (scf_transaction_property_delete(tx, ent,
3487c478bd9Sstevel@tonic-gate 		    prop) != SCF_SUCCESS) {
3497c478bd9Sstevel@tonic-gate 			if (scf_error() != SCF_ERROR_NOT_FOUND)
3507c478bd9Sstevel@tonic-gate 				scfdie();
3517c478bd9Sstevel@tonic-gate 
3527c478bd9Sstevel@tonic-gate 			uu_die(
3537c478bd9Sstevel@tonic-gate 			    gettext("Error: \"%s\" property does not exist.\n"),
3547c478bd9Sstevel@tonic-gate 			    prop);
3557c478bd9Sstevel@tonic-gate 		}
3567c478bd9Sstevel@tonic-gate 
3577c478bd9Sstevel@tonic-gate 		ret = scf_transaction_commit(tx);
3587c478bd9Sstevel@tonic-gate 		if (ret < 0) {
3597c478bd9Sstevel@tonic-gate 			if (scf_error() != SCF_ERROR_PERMISSION_DENIED)
3607c478bd9Sstevel@tonic-gate 				scfdie();
3617c478bd9Sstevel@tonic-gate 
3627c478bd9Sstevel@tonic-gate 			uu_die(gettext("Error: Permission denied.\n"));
3637c478bd9Sstevel@tonic-gate 		}
3647c478bd9Sstevel@tonic-gate 		if (ret == 0) {
3657c478bd9Sstevel@tonic-gate 			scf_transaction_reset(tx);
3667c478bd9Sstevel@tonic-gate 			if (scf_pg_update(gpg) == -1)
3677c478bd9Sstevel@tonic-gate 				scfdie();
3687c478bd9Sstevel@tonic-gate 		}
3697c478bd9Sstevel@tonic-gate 	} while (ret == 0);
3707c478bd9Sstevel@tonic-gate 
3717c478bd9Sstevel@tonic-gate 	(void) scf_entry_destroy(ent);
3727c478bd9Sstevel@tonic-gate 	scf_transaction_destroy(tx);
3737c478bd9Sstevel@tonic-gate 	scf_property_destroy(eprop);
3747c478bd9Sstevel@tonic-gate 	scf_pg_destroy(gpg);
3757c478bd9Sstevel@tonic-gate }
3767c478bd9Sstevel@tonic-gate 
3777c478bd9Sstevel@tonic-gate /*
3787c478bd9Sstevel@tonic-gate  * commit_props evaluates an entire property list that has been created
3797c478bd9Sstevel@tonic-gate  * based on command line options, and either deletes or modifies properties
3807c478bd9Sstevel@tonic-gate  * as requested.
3817c478bd9Sstevel@tonic-gate  */
3827c478bd9Sstevel@tonic-gate 
3837c478bd9Sstevel@tonic-gate static void
commit_props(const scf_instance_t * inst,inetd_prop_t * mod,boolean_t defaults)3847c478bd9Sstevel@tonic-gate commit_props(const scf_instance_t *inst, inetd_prop_t *mod, boolean_t defaults)
3857c478bd9Sstevel@tonic-gate {
3867c478bd9Sstevel@tonic-gate 	int			i;
3877c478bd9Sstevel@tonic-gate 	uint8_t			new_bool;
3887c478bd9Sstevel@tonic-gate 
389ba1637f8Smh138676 	for (i = 0; mod[i].ip_name != NULL; i++) {
3907c478bd9Sstevel@tonic-gate 		switch (mod[i].ip_error) {
3917c478bd9Sstevel@tonic-gate 		case IVE_UNSET:
3927c478bd9Sstevel@tonic-gate 			break;
3937c478bd9Sstevel@tonic-gate 		case IVE_INVALID:
3947c478bd9Sstevel@tonic-gate 			delete_prop(inst, mod[i].ip_pg, mod[i].ip_name);
3957c478bd9Sstevel@tonic-gate 			break;
3967c478bd9Sstevel@tonic-gate 		case IVE_VALID:
3977c478bd9Sstevel@tonic-gate 			switch (mod[i].ip_type) {
398ba1637f8Smh138676 			case INET_TYPE_STRING:
3997c478bd9Sstevel@tonic-gate 				modify_prop(inst,
4007c478bd9Sstevel@tonic-gate 				    defaults ? PG_NAME_SERVICE_DEFAULTS :
4017c478bd9Sstevel@tonic-gate 				    mod[i].ip_pg, mod[i].ip_name,
4027c478bd9Sstevel@tonic-gate 				    SCF_TYPE_ASTRING,
403ba1637f8Smh138676 				    mod[i].ip_value.iv_string);
4047c478bd9Sstevel@tonic-gate 				break;
405ba1637f8Smh138676 			case INET_TYPE_STRING_LIST:
406ba1637f8Smh138676 				modify_prop(inst,
407ba1637f8Smh138676 				    defaults ? PG_NAME_SERVICE_DEFAULTS :
408ba1637f8Smh138676 				    mod[i].ip_pg, mod[i].ip_name,
409ba1637f8Smh138676 				    SCF_TYPE_ASTRING,
410ba1637f8Smh138676 				    mod[i].ip_value.iv_string_list);
411ba1637f8Smh138676 				break;
412ba1637f8Smh138676 			case INET_TYPE_INTEGER:
4137c478bd9Sstevel@tonic-gate 				modify_prop(inst,
4147c478bd9Sstevel@tonic-gate 				    defaults ? PG_NAME_SERVICE_DEFAULTS :
4157c478bd9Sstevel@tonic-gate 				    mod[i].ip_pg, mod[i].ip_name,
4167c478bd9Sstevel@tonic-gate 				    SCF_TYPE_INTEGER, &mod[i].ip_value.iv_int);
4177c478bd9Sstevel@tonic-gate 				break;
418ba1637f8Smh138676 			case INET_TYPE_BOOLEAN:
4197c478bd9Sstevel@tonic-gate 				new_bool = (mod[i].ip_value.iv_boolean) ? 1 : 0;
4207c478bd9Sstevel@tonic-gate 
4217c478bd9Sstevel@tonic-gate 				modify_prop(inst,
4227c478bd9Sstevel@tonic-gate 				    defaults ? PG_NAME_SERVICE_DEFAULTS :
4237c478bd9Sstevel@tonic-gate 				    mod[i].ip_pg, mod[i].ip_name,
4247c478bd9Sstevel@tonic-gate 				    SCF_TYPE_BOOLEAN, &new_bool);
4257c478bd9Sstevel@tonic-gate 				break;
4267c478bd9Sstevel@tonic-gate 			}
4277c478bd9Sstevel@tonic-gate 		}
4287c478bd9Sstevel@tonic-gate 	}
4297c478bd9Sstevel@tonic-gate }
4307c478bd9Sstevel@tonic-gate 
4317c478bd9Sstevel@tonic-gate /*
4327c478bd9Sstevel@tonic-gate  * list_callback is the callback function to be handed to simple_walk_instances
4337c478bd9Sstevel@tonic-gate  * in list_services.  It is called once on every instance on a machine.  If
4347c478bd9Sstevel@tonic-gate  * that instance is controlled by inetd, it prints enabled/disabled, state,
4357c478bd9Sstevel@tonic-gate  * and instance FMRI.
4367c478bd9Sstevel@tonic-gate  */
4377c478bd9Sstevel@tonic-gate 
4387c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4397c478bd9Sstevel@tonic-gate static int
list_callback(scf_handle_t * hin,scf_instance_t * inst,void * buf)4407c478bd9Sstevel@tonic-gate list_callback(scf_handle_t *hin, scf_instance_t *inst, void *buf)
4417c478bd9Sstevel@tonic-gate {
4427c478bd9Sstevel@tonic-gate 	ssize_t			max_name_length;
4437c478bd9Sstevel@tonic-gate 	char			*inst_name;
4447c478bd9Sstevel@tonic-gate 	scf_simple_prop_t	*prop = NULL, *prop2 = NULL;
4457c478bd9Sstevel@tonic-gate 	const uint8_t		*enabled;
4467c478bd9Sstevel@tonic-gate 	const char		*state, *restart_str;
4477c478bd9Sstevel@tonic-gate 
4487c478bd9Sstevel@tonic-gate 	max_name_length = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH);
4497c478bd9Sstevel@tonic-gate 	if ((inst_name = malloc(max_name_length + 1)) == NULL)
4507c478bd9Sstevel@tonic-gate 		uu_die(gettext("Error: Out of memory.\n"));
4517c478bd9Sstevel@tonic-gate 
4527c478bd9Sstevel@tonic-gate 	/*
4537c478bd9Sstevel@tonic-gate 	 * Get the FMRI of the instance, and check if its delegated restarter
4547c478bd9Sstevel@tonic-gate 	 * is inetd.
4557c478bd9Sstevel@tonic-gate 	 */
4567c478bd9Sstevel@tonic-gate 
4577c478bd9Sstevel@tonic-gate 	if (scf_instance_to_fmri(inst, inst_name, max_name_length + 1) < 0)
4587c478bd9Sstevel@tonic-gate 		return (SCF_FAILED);
4597c478bd9Sstevel@tonic-gate 
4607c478bd9Sstevel@tonic-gate 	if ((prop = scf_simple_prop_get(hin, inst_name, SCF_PG_GENERAL,
4617c478bd9Sstevel@tonic-gate 	    SCF_PROPERTY_RESTARTER)) == NULL)
4627c478bd9Sstevel@tonic-gate 		goto out;
4637c478bd9Sstevel@tonic-gate 
4647c478bd9Sstevel@tonic-gate 	if ((restart_str = scf_simple_prop_next_ustring(prop)) == NULL)
4657c478bd9Sstevel@tonic-gate 		goto out;
4667c478bd9Sstevel@tonic-gate 
4677c478bd9Sstevel@tonic-gate 	if (strstr(restart_str, INETADM_INETD_STR) == NULL)
4687c478bd9Sstevel@tonic-gate 		goto out;
4697c478bd9Sstevel@tonic-gate 
4707c478bd9Sstevel@tonic-gate 	/* Free restarter prop so it can be reused below */
4717c478bd9Sstevel@tonic-gate 	scf_simple_prop_free(prop);
4727c478bd9Sstevel@tonic-gate 
4737c478bd9Sstevel@tonic-gate 	/*
4747c478bd9Sstevel@tonic-gate 	 * We know that this instance is managed by inetd.
4757c478bd9Sstevel@tonic-gate 	 * Now get the enabled and state properties.
4767c478bd9Sstevel@tonic-gate 	 */
4777c478bd9Sstevel@tonic-gate 
4787c478bd9Sstevel@tonic-gate 	if (((prop = scf_simple_prop_get(hin, inst_name, SCF_PG_GENERAL,
4797c478bd9Sstevel@tonic-gate 	    SCF_PROPERTY_ENABLED)) == NULL) ||
4807c478bd9Sstevel@tonic-gate 	    ((enabled = scf_simple_prop_next_boolean(prop)) == NULL)) {
4817c478bd9Sstevel@tonic-gate 		(void) uu_warn(gettext("Error: Instance %s is missing enabled "
4827c478bd9Sstevel@tonic-gate 		    "property.\n"), inst_name);
4837c478bd9Sstevel@tonic-gate 		goto out;
4847c478bd9Sstevel@tonic-gate 	}
4857c478bd9Sstevel@tonic-gate 
4867c478bd9Sstevel@tonic-gate 	if (((prop2 = scf_simple_prop_get(hin, inst_name, SCF_PG_RESTARTER,
4877c478bd9Sstevel@tonic-gate 	    SCF_PROPERTY_STATE)) == NULL) ||
4887c478bd9Sstevel@tonic-gate 	    ((state = scf_simple_prop_next_astring(prop2)) == NULL)) {
4897c478bd9Sstevel@tonic-gate 		(void) uu_warn(gettext("Error: Instance %s is missing state "
4907c478bd9Sstevel@tonic-gate 		    "property.\n"), inst_name);
4917c478bd9Sstevel@tonic-gate 		goto out;
4927c478bd9Sstevel@tonic-gate 	}
4937c478bd9Sstevel@tonic-gate 
4947c478bd9Sstevel@tonic-gate 	/* Print enabled/disabled, state, and FMRI for the instance. */
4957c478bd9Sstevel@tonic-gate 
4967c478bd9Sstevel@tonic-gate 	if (*enabled)
4977c478bd9Sstevel@tonic-gate 		(void) printf("%-10s%-15s%s\n", INETADM_ENABLED_STR, state,
4987c478bd9Sstevel@tonic-gate 		    inst_name);
4997c478bd9Sstevel@tonic-gate 	else
5007c478bd9Sstevel@tonic-gate 		(void) printf("%-10s%-15s%s\n", INETADM_DISABLED_STR, state,
5017c478bd9Sstevel@tonic-gate 		    inst_name);
5027c478bd9Sstevel@tonic-gate 
5037c478bd9Sstevel@tonic-gate out:
5047c478bd9Sstevel@tonic-gate 	free(inst_name);
5057c478bd9Sstevel@tonic-gate 	scf_simple_prop_free(prop);
5067c478bd9Sstevel@tonic-gate 	scf_simple_prop_free(prop2);
5077c478bd9Sstevel@tonic-gate 	return (SCF_SUCCESS);
5087c478bd9Sstevel@tonic-gate }
5097c478bd9Sstevel@tonic-gate 
5107c478bd9Sstevel@tonic-gate /*
5117c478bd9Sstevel@tonic-gate  * list_services calls list_callback on every instance on the machine.
5127c478bd9Sstevel@tonic-gate  */
5137c478bd9Sstevel@tonic-gate 
5147c478bd9Sstevel@tonic-gate static void
list_services()5157c478bd9Sstevel@tonic-gate list_services()
5167c478bd9Sstevel@tonic-gate {
5177c478bd9Sstevel@tonic-gate 	(void) printf("%-10s%-15s%s\n", "ENABLED", "STATE", "FMRI");
5187c478bd9Sstevel@tonic-gate 
5197c478bd9Sstevel@tonic-gate 	if (scf_simple_walk_instances(SCF_STATE_ALL, NULL, list_callback) ==
5207c478bd9Sstevel@tonic-gate 	    SCF_FAILED)
5217c478bd9Sstevel@tonic-gate 		scfdie();
5227c478bd9Sstevel@tonic-gate }
5237c478bd9Sstevel@tonic-gate 
5247c478bd9Sstevel@tonic-gate static void
print_prop_val(inetd_prop_t * prop)525ba1637f8Smh138676 print_prop_val(inetd_prop_t *prop)
5267c478bd9Sstevel@tonic-gate {
5277c478bd9Sstevel@tonic-gate 	switch (prop->ip_type) {
528ba1637f8Smh138676 	case INET_TYPE_STRING:
529ba1637f8Smh138676 		(void) printf("\"%s\"\n", prop->ip_value.iv_string);
530ba1637f8Smh138676 		break;
531ba1637f8Smh138676 	case INET_TYPE_STRING_LIST:
532ba1637f8Smh138676 		{
5337c478bd9Sstevel@tonic-gate 			int	j = 0;
534ba1637f8Smh138676 			char	**cpp = prop->ip_value.iv_string_list;
5357c478bd9Sstevel@tonic-gate 
5367c478bd9Sstevel@tonic-gate 			/*
537ba1637f8Smh138676 			 * Print string list as comma separated list.
5387c478bd9Sstevel@tonic-gate 			 */
5397c478bd9Sstevel@tonic-gate 
5407c478bd9Sstevel@tonic-gate 			(void) printf("\"%s", cpp[j]);
5417c478bd9Sstevel@tonic-gate 			while (cpp[++j] != NULL)
5427c478bd9Sstevel@tonic-gate 				(void) printf(",%s", cpp[j]);
5437c478bd9Sstevel@tonic-gate 			(void) printf("\"\n");
5447c478bd9Sstevel@tonic-gate 		}
5457c478bd9Sstevel@tonic-gate 		break;
546ba1637f8Smh138676 	case INET_TYPE_INTEGER:
5477c478bd9Sstevel@tonic-gate 		(void) printf("%lld\n", prop->ip_value.iv_int);
5487c478bd9Sstevel@tonic-gate 		break;
549ba1637f8Smh138676 	case INET_TYPE_BOOLEAN:
5507c478bd9Sstevel@tonic-gate 		if (prop->ip_value.iv_boolean)
5517c478bd9Sstevel@tonic-gate 			(void) printf("%s\n", INETADM_TRUE_STR);
5527c478bd9Sstevel@tonic-gate 		else
5537c478bd9Sstevel@tonic-gate 			(void) printf("%s\n", INETADM_FALSE_STR);
5547c478bd9Sstevel@tonic-gate 		break;
5557c478bd9Sstevel@tonic-gate 	}
5567c478bd9Sstevel@tonic-gate }
5577c478bd9Sstevel@tonic-gate 
5587c478bd9Sstevel@tonic-gate /*
5597c478bd9Sstevel@tonic-gate  * list_props_cb is a callback function for scf_walk_fmri that lists all
5607c478bd9Sstevel@tonic-gate  * relevant inetd properties for an instance managed by inetd.
5617c478bd9Sstevel@tonic-gate  */
5627c478bd9Sstevel@tonic-gate 
5637c478bd9Sstevel@tonic-gate /* ARGSUSED0 */
5647c478bd9Sstevel@tonic-gate static int
list_props_cb(void * data,scf_walkinfo_t * wip)5657c478bd9Sstevel@tonic-gate list_props_cb(void *data, scf_walkinfo_t *wip)
5667c478bd9Sstevel@tonic-gate {
5677c478bd9Sstevel@tonic-gate 	int			i;
5687c478bd9Sstevel@tonic-gate 	const char		*instname = wip->fmri;
5697c478bd9Sstevel@tonic-gate 	scf_simple_prop_t	*prop;
5707c478bd9Sstevel@tonic-gate 	inetd_prop_t		*proplist;
5717c478bd9Sstevel@tonic-gate 	const char		*restart_str;
5727c478bd9Sstevel@tonic-gate 	boolean_t		is_rpc = B_FALSE;
5737c478bd9Sstevel@tonic-gate 	size_t			numprops;
5747c478bd9Sstevel@tonic-gate 	scf_handle_t		*h;
5757c478bd9Sstevel@tonic-gate 	scf_error_t		err;
5767c478bd9Sstevel@tonic-gate 
5777c478bd9Sstevel@tonic-gate 	if (((h = scf_handle_create(SCF_VERSION)) == NULL) ||
5787c478bd9Sstevel@tonic-gate 	    (scf_handle_bind(h) == -1))
5797c478bd9Sstevel@tonic-gate 		scfdie();
5807c478bd9Sstevel@tonic-gate 
5817c478bd9Sstevel@tonic-gate 	/*
5827c478bd9Sstevel@tonic-gate 	 * Get the property that holds the name of this instance's
5837c478bd9Sstevel@tonic-gate 	 * restarter, and make sure that it is inetd.
5847c478bd9Sstevel@tonic-gate 	 */
5857c478bd9Sstevel@tonic-gate 	if ((prop = scf_simple_prop_get(h, instname, SCF_PG_GENERAL,
5867c478bd9Sstevel@tonic-gate 	    SCF_PROPERTY_RESTARTER)) == NULL) {
5877c478bd9Sstevel@tonic-gate 		if (scf_error() == SCF_ERROR_NOT_FOUND)
5887c478bd9Sstevel@tonic-gate 			uu_die(gettext("Error: Specified service instance "
5897c478bd9Sstevel@tonic-gate 			    "\"%s\" has no restarter property.  inetd is not "
5907c478bd9Sstevel@tonic-gate 			    "the delegated restarter of this instance.\n"),
5917c478bd9Sstevel@tonic-gate 			    instname);
5927c478bd9Sstevel@tonic-gate 		if (scf_error() == SCF_ERROR_INVALID_ARGUMENT)
5937c478bd9Sstevel@tonic-gate 			uu_die(gettext("Error: \"%s\" is not a valid service "
5947c478bd9Sstevel@tonic-gate 			    "instance.\n"), instname);
5957c478bd9Sstevel@tonic-gate 
5967c478bd9Sstevel@tonic-gate 		scfdie();
5977c478bd9Sstevel@tonic-gate 	}
5987c478bd9Sstevel@tonic-gate 
5997c478bd9Sstevel@tonic-gate 	if (((restart_str = scf_simple_prop_next_ustring(prop)) == NULL) ||
6007c478bd9Sstevel@tonic-gate 	    (strstr(restart_str, INETADM_INETD_STR) == NULL)) {
6017c478bd9Sstevel@tonic-gate 		uu_die(gettext("Error: inetd is not the delegated restarter of "
6027c478bd9Sstevel@tonic-gate 		    "specified service instance \"%s\".\n"), instname);
6037c478bd9Sstevel@tonic-gate 	}
6047c478bd9Sstevel@tonic-gate 
6057c478bd9Sstevel@tonic-gate 	scf_simple_prop_free(prop);
6067c478bd9Sstevel@tonic-gate 
6077c478bd9Sstevel@tonic-gate 	/*
6087c478bd9Sstevel@tonic-gate 	 * This instance is controlled by inetd, so now we display all
6097c478bd9Sstevel@tonic-gate 	 * of its properties.  First the mandatory properties, and then
6107c478bd9Sstevel@tonic-gate 	 * the properties that have default values, substituting the
6117c478bd9Sstevel@tonic-gate 	 * default values inherited from inetd as necessary (this is done
6127c478bd9Sstevel@tonic-gate 	 * for us by read_instance_props()).
6137c478bd9Sstevel@tonic-gate 	 */
6147c478bd9Sstevel@tonic-gate 
6157c478bd9Sstevel@tonic-gate 	if ((proplist = read_instance_props(h, instname, &numprops, &err)) ==
6167c478bd9Sstevel@tonic-gate 	    NULL) {
6177c478bd9Sstevel@tonic-gate 		uu_die(gettext("Unexpected libscf error: %s.  Exiting.\n"),
6187c478bd9Sstevel@tonic-gate 		    scf_strerror(err));
6197c478bd9Sstevel@tonic-gate 	}
6207c478bd9Sstevel@tonic-gate 	scf_handle_destroy(h);
6217c478bd9Sstevel@tonic-gate 
6227c478bd9Sstevel@tonic-gate 	(void) printf("%-9s%s\n", "SCOPE", "NAME=VALUE");
6237c478bd9Sstevel@tonic-gate 
6247c478bd9Sstevel@tonic-gate 	for (i = 0; i < numprops; i++) {
6257c478bd9Sstevel@tonic-gate 		/* Skip rpc version properties if it's not an RPC service */
6267c478bd9Sstevel@tonic-gate 		if ((strcmp(PR_RPC_LW_VER_NAME, proplist[i].ip_name) == 0) ||
6277c478bd9Sstevel@tonic-gate 		    (strcmp(PR_RPC_HI_VER_NAME, proplist[i].ip_name) == 0))
6287c478bd9Sstevel@tonic-gate 			if (!is_rpc)
6297c478bd9Sstevel@tonic-gate 				continue;
6307c478bd9Sstevel@tonic-gate 
6317c478bd9Sstevel@tonic-gate 		/* If it's not an unset property, print it out. */
6327c478bd9Sstevel@tonic-gate 		if (proplist[i].ip_error != IVE_UNSET) {
6337c478bd9Sstevel@tonic-gate 			if (strcmp(PR_ISRPC_NAME, proplist[i].ip_name) == 0)
6347c478bd9Sstevel@tonic-gate 				is_rpc = proplist[i].ip_value.iv_boolean;
6357c478bd9Sstevel@tonic-gate 
6367c478bd9Sstevel@tonic-gate 			(void) printf("%-9s%s=",
6377c478bd9Sstevel@tonic-gate 			    proplist[i].from_inetd ? INETADM_DEFAULT_STR : "",
6387c478bd9Sstevel@tonic-gate 			    proplist[i].ip_name);
639ba1637f8Smh138676 			print_prop_val(&proplist[i]);
6407c478bd9Sstevel@tonic-gate 			continue;
6417c478bd9Sstevel@tonic-gate 		}
6427c478bd9Sstevel@tonic-gate 
6437c478bd9Sstevel@tonic-gate 		/* arg0 is non-default, but also doesn't have to be set. */
6447c478bd9Sstevel@tonic-gate 
6457c478bd9Sstevel@tonic-gate 		if (i == PT_ARG0_INDEX)
6467c478bd9Sstevel@tonic-gate 			continue;
6477c478bd9Sstevel@tonic-gate 
6487c478bd9Sstevel@tonic-gate 		/* all other properties should have values. */
6497c478bd9Sstevel@tonic-gate 		if (proplist[i].ip_default) {
6507c478bd9Sstevel@tonic-gate 			(void) uu_warn(gettext("Error: Property %s is missing "
6517c478bd9Sstevel@tonic-gate 			    "and has no defined default value.\n"),
6527c478bd9Sstevel@tonic-gate 			    proplist[i].ip_name);
6537c478bd9Sstevel@tonic-gate 		} else {
6547c478bd9Sstevel@tonic-gate 			(void) uu_warn(gettext("Error: Required property %s is "
6557c478bd9Sstevel@tonic-gate 			    "missing.\n"), proplist[i].ip_name);
6567c478bd9Sstevel@tonic-gate 		}
6577c478bd9Sstevel@tonic-gate 	}
6587c478bd9Sstevel@tonic-gate 
6597c478bd9Sstevel@tonic-gate 	free_instance_props(proplist);
6607c478bd9Sstevel@tonic-gate 	return (0);
6617c478bd9Sstevel@tonic-gate }
6627c478bd9Sstevel@tonic-gate 
6637c478bd9Sstevel@tonic-gate /*
6647c478bd9Sstevel@tonic-gate  * set_svc_enable_cb is a callback function for scf_walk_fmri that sets the
6657c478bd9Sstevel@tonic-gate  * enabled property in the repository for an instance based on the value given
6667c478bd9Sstevel@tonic-gate  * by 'data'.
6677c478bd9Sstevel@tonic-gate  */
6687c478bd9Sstevel@tonic-gate 
6697c478bd9Sstevel@tonic-gate static int
set_svc_enable_cb(void * data,scf_walkinfo_t * wip)6707c478bd9Sstevel@tonic-gate set_svc_enable_cb(void *data, scf_walkinfo_t *wip)
6717c478bd9Sstevel@tonic-gate {
6727c478bd9Sstevel@tonic-gate 	uint8_t			desired = *(uint8_t *)data;
6737c478bd9Sstevel@tonic-gate 	const char		*instname = wip->fmri;
6747c478bd9Sstevel@tonic-gate 
6757c478bd9Sstevel@tonic-gate 	if (desired) {
6767c478bd9Sstevel@tonic-gate 		if (smf_enable_instance(instname, 0) == 0)
6777c478bd9Sstevel@tonic-gate 			return (0);
6787c478bd9Sstevel@tonic-gate 	} else {
6797c478bd9Sstevel@tonic-gate 		if (smf_disable_instance(instname, 0) == 0)
6807c478bd9Sstevel@tonic-gate 			return (0);
6817c478bd9Sstevel@tonic-gate 	}
6827c478bd9Sstevel@tonic-gate 
6837c478bd9Sstevel@tonic-gate 	switch (scf_error()) {
6847c478bd9Sstevel@tonic-gate 	case SCF_ERROR_INVALID_ARGUMENT:
6857c478bd9Sstevel@tonic-gate 		uu_die(gettext("Error: \"%s\" is not a valid service "
6867c478bd9Sstevel@tonic-gate 		    "instance.\n"), instname);
6877c478bd9Sstevel@tonic-gate 		break;
6887c478bd9Sstevel@tonic-gate 	case SCF_ERROR_NOT_FOUND:
6897c478bd9Sstevel@tonic-gate 		uu_die(gettext("Error: Service instance \"%s\" not found.\n"),
6907c478bd9Sstevel@tonic-gate 		    instname);
6917c478bd9Sstevel@tonic-gate 		break;
6927c478bd9Sstevel@tonic-gate 	default:
6937c478bd9Sstevel@tonic-gate 		scfdie();
6947c478bd9Sstevel@tonic-gate 	}
6957c478bd9Sstevel@tonic-gate 
6967c478bd9Sstevel@tonic-gate 	return (0);
6977c478bd9Sstevel@tonic-gate }
6987c478bd9Sstevel@tonic-gate 
6997c478bd9Sstevel@tonic-gate /*
7007c478bd9Sstevel@tonic-gate  * list_defaults lists all the default property values being provided by
7017c478bd9Sstevel@tonic-gate  * inetd.
7027c478bd9Sstevel@tonic-gate  */
7037c478bd9Sstevel@tonic-gate 
7047c478bd9Sstevel@tonic-gate static void
list_defaults()7057c478bd9Sstevel@tonic-gate list_defaults()
7067c478bd9Sstevel@tonic-gate {
7077c478bd9Sstevel@tonic-gate 	scf_handle_t		*h;
7087c478bd9Sstevel@tonic-gate 	scf_error_t		err;
7097c478bd9Sstevel@tonic-gate 	int			i;
7107c478bd9Sstevel@tonic-gate 	inetd_prop_t		*proptable;
7117c478bd9Sstevel@tonic-gate 	size_t			numprops;
7127c478bd9Sstevel@tonic-gate 
7137c478bd9Sstevel@tonic-gate 	if (((h = scf_handle_create(SCF_VERSION)) == NULL) ||
7147c478bd9Sstevel@tonic-gate 	    (scf_handle_bind(h) == -1))
7157c478bd9Sstevel@tonic-gate 		scfdie();
7167c478bd9Sstevel@tonic-gate 
7177c478bd9Sstevel@tonic-gate 	if ((proptable = read_default_props(h, &numprops, &err)) == NULL) {
7187c478bd9Sstevel@tonic-gate 		uu_die(gettext("Unexpected libscf error: %s.  Exiting.\n"),
7197c478bd9Sstevel@tonic-gate 		    scf_strerror(err));
7207c478bd9Sstevel@tonic-gate 	}
7217c478bd9Sstevel@tonic-gate 
7227c478bd9Sstevel@tonic-gate 	(void) printf("NAME=VALUE\n");
7237c478bd9Sstevel@tonic-gate 
7247c478bd9Sstevel@tonic-gate 	for (i = 0; i < numprops; i++) {
7257c478bd9Sstevel@tonic-gate 		if (!proptable[i].ip_default)
7267c478bd9Sstevel@tonic-gate 			continue;
7277c478bd9Sstevel@tonic-gate 
7287c478bd9Sstevel@tonic-gate 		if (proptable[i].ip_error == IVE_UNSET) {
7297c478bd9Sstevel@tonic-gate 			(void) uu_warn(gettext("Error: Default property %s "
7307c478bd9Sstevel@tonic-gate 			    "missing.\n"), proptable[i].ip_name);
7317c478bd9Sstevel@tonic-gate 			continue;
7327c478bd9Sstevel@tonic-gate 		}
7337c478bd9Sstevel@tonic-gate 
7347c478bd9Sstevel@tonic-gate 		(void) printf("%s=", proptable[i].ip_name);
735ba1637f8Smh138676 		print_prop_val(&proptable[i]);
7367c478bd9Sstevel@tonic-gate 	}
7377c478bd9Sstevel@tonic-gate 
7387c478bd9Sstevel@tonic-gate 	free_instance_props(proptable);
7397c478bd9Sstevel@tonic-gate }
7407c478bd9Sstevel@tonic-gate 
7417c478bd9Sstevel@tonic-gate /*
7427c478bd9Sstevel@tonic-gate  * modify_inst_props_cb is a callback function for scf_walk_fmri that modifies
7437c478bd9Sstevel@tonic-gate  * the properties that are given as name=value pairs on the command line
7447c478bd9Sstevel@tonic-gate  * to the requested value.
7457c478bd9Sstevel@tonic-gate  */
7467c478bd9Sstevel@tonic-gate 
7477c478bd9Sstevel@tonic-gate static int
modify_inst_props_cb(void * data,scf_walkinfo_t * wip)7487c478bd9Sstevel@tonic-gate modify_inst_props_cb(void *data, scf_walkinfo_t *wip)
7497c478bd9Sstevel@tonic-gate {
7507c478bd9Sstevel@tonic-gate 	int			i, j;
7517c478bd9Sstevel@tonic-gate 	char			*value;
7527c478bd9Sstevel@tonic-gate 	const char		*fmri = wip->fmri;
7537c478bd9Sstevel@tonic-gate 	scf_instance_t		*inst = wip->inst;
7547c478bd9Sstevel@tonic-gate 	inetd_prop_t		*mod, *prop_table;
7557c478bd9Sstevel@tonic-gate 	size_t			numprops;
7567c478bd9Sstevel@tonic-gate 	ssize_t			max_val;
7577c478bd9Sstevel@tonic-gate 	int64_t			new_int;
7587c478bd9Sstevel@tonic-gate 	int			argc = ((arglist_t *)data)->argc;
7597c478bd9Sstevel@tonic-gate 	char			**argv = ((arglist_t *)data)->argv;
7607c478bd9Sstevel@tonic-gate 
7617c478bd9Sstevel@tonic-gate 	if ((max_val = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH)) < 0)
7627c478bd9Sstevel@tonic-gate 		scfdie();
7637c478bd9Sstevel@tonic-gate 
7647c478bd9Sstevel@tonic-gate 	prop_table = get_prop_table(&numprops);
7657c478bd9Sstevel@tonic-gate 
7667c478bd9Sstevel@tonic-gate 	if ((mod = malloc(numprops * sizeof (inetd_prop_t))) == NULL)
7677c478bd9Sstevel@tonic-gate 		uu_die(gettext("Error: Out of memory.\n"));
7687c478bd9Sstevel@tonic-gate 
7697c478bd9Sstevel@tonic-gate 	(void) memcpy(mod, prop_table, numprops * sizeof (inetd_prop_t));
7707c478bd9Sstevel@tonic-gate 
7717c478bd9Sstevel@tonic-gate 	/*
7727c478bd9Sstevel@tonic-gate 	 * For each property to be changed, look up the property name in the
7737c478bd9Sstevel@tonic-gate 	 * property table.  Change each property in the mod array, and then
7747c478bd9Sstevel@tonic-gate 	 * write the entire thing back.
7757c478bd9Sstevel@tonic-gate 	 */
7767c478bd9Sstevel@tonic-gate 	for (i = 0; i < argc; i++) {
7777c478bd9Sstevel@tonic-gate 		/* Separate argument into name and value pair */
7787c478bd9Sstevel@tonic-gate 		if ((value = strchr(argv[i], '=')) == NULL)
7797c478bd9Sstevel@tonic-gate 			uu_die(gettext("Error: Malformed name=value pair "
7807c478bd9Sstevel@tonic-gate 			    "\"%s\"\n"), argv[i]);
7817c478bd9Sstevel@tonic-gate 
7827c478bd9Sstevel@tonic-gate 		*value = '\0';
7837c478bd9Sstevel@tonic-gate 		value++;
7847c478bd9Sstevel@tonic-gate 
7857c478bd9Sstevel@tonic-gate 		/* Find property name in array of properties */
786ba1637f8Smh138676 		for (j = 0; mod[j].ip_name != NULL; j++) {
7877c478bd9Sstevel@tonic-gate 			if (strcmp(mod[j].ip_name, argv[i]) == 0)
7887c478bd9Sstevel@tonic-gate 				break;
7897c478bd9Sstevel@tonic-gate 		}
7907c478bd9Sstevel@tonic-gate 
791ba1637f8Smh138676 		if (mod[j].ip_name == NULL)
7927c478bd9Sstevel@tonic-gate 			uu_die(gettext("Error: \"%s\" is not a valid "
7937c478bd9Sstevel@tonic-gate 			    "property.\n"), argv[i]);
7947c478bd9Sstevel@tonic-gate 
7957c478bd9Sstevel@tonic-gate 		if (*value == '\0') {
7967c478bd9Sstevel@tonic-gate 			if ((mod[j].ip_default) || (j == PT_ARG0_INDEX)) {
7977c478bd9Sstevel@tonic-gate 				/* mark property for deletion */
7987c478bd9Sstevel@tonic-gate 				mod[j].ip_error = IVE_INVALID;
7997c478bd9Sstevel@tonic-gate 
8007c478bd9Sstevel@tonic-gate 				/* return the '=' taken out above */
8017c478bd9Sstevel@tonic-gate 				*(--value) = '=';
8027c478bd9Sstevel@tonic-gate 
8037c478bd9Sstevel@tonic-gate 				continue;
8047c478bd9Sstevel@tonic-gate 			} else {
8057c478bd9Sstevel@tonic-gate 				uu_die(gettext("\"%s\" is a mandatory "
8067c478bd9Sstevel@tonic-gate 				    "property and can not be deleted.\n"),
8077c478bd9Sstevel@tonic-gate 				    argv[i]);
8087c478bd9Sstevel@tonic-gate 			}
8097c478bd9Sstevel@tonic-gate 		}
8107c478bd9Sstevel@tonic-gate 
8117c478bd9Sstevel@tonic-gate 		switch (mod[j].ip_type) {
812ba1637f8Smh138676 		case INET_TYPE_INTEGER:
813*95c74518SToomas Soome 			if (uu_strtoint(value, &new_int, sizeof (new_int), 0,
814*95c74518SToomas Soome 			    0, 0) == -1)
8157c478bd9Sstevel@tonic-gate 				uu_die(gettext("Error: \"%s\" is not a valid "
8167c478bd9Sstevel@tonic-gate 				    "integer value.\n"), value);
8177c478bd9Sstevel@tonic-gate 
8187c478bd9Sstevel@tonic-gate 			mod[j].ip_value.iv_int = new_int;
8197c478bd9Sstevel@tonic-gate 			break;
820ba1637f8Smh138676 		case INET_TYPE_STRING:
821ba1637f8Smh138676 			if (strlen(value) >= max_val) {
822ba1637f8Smh138676 				uu_die(gettext("Error: String value is longer "
823ba1637f8Smh138676 				    "than %l characters.\n"), max_val);
824ba1637f8Smh138676 			} else if ((mod[j].ip_value.iv_string = strdup(value))
825ba1637f8Smh138676 			    == NULL) {
826ba1637f8Smh138676 				uu_die(gettext("Error: Out of memory.\n"));
827ba1637f8Smh138676 			}
828ba1637f8Smh138676 			break;
829ba1637f8Smh138676 		case INET_TYPE_STRING_LIST:
830ba1637f8Smh138676 			if ((mod[j].ip_value.iv_string_list =
8317c478bd9Sstevel@tonic-gate 			    get_protos(value)) == NULL) {
8327c478bd9Sstevel@tonic-gate 				if (errno == ENOMEM) {
8337c478bd9Sstevel@tonic-gate 					uu_die(gettext(
8347c478bd9Sstevel@tonic-gate 					    "Error: Out of memory.\n"));
8357c478bd9Sstevel@tonic-gate 				} else if (errno == E2BIG) {
8367c478bd9Sstevel@tonic-gate 					uu_die(gettext(
8377c478bd9Sstevel@tonic-gate 					    "Error: String value in "
8387c478bd9Sstevel@tonic-gate 					    "%s property longer than "
8397c478bd9Sstevel@tonic-gate 					    "%l characters.\n"),
8407c478bd9Sstevel@tonic-gate 					    PR_PROTO_NAME, max_val);
8417c478bd9Sstevel@tonic-gate 				} else {
8427c478bd9Sstevel@tonic-gate 					uu_die(gettext(
8437c478bd9Sstevel@tonic-gate 					    "Error: No values "
8447c478bd9Sstevel@tonic-gate 					    "specified for %s "
8457c478bd9Sstevel@tonic-gate 					    "property.\n"),
8467c478bd9Sstevel@tonic-gate 					    PR_PROTO_NAME);
8477c478bd9Sstevel@tonic-gate 				}
8487c478bd9Sstevel@tonic-gate 			}
8497c478bd9Sstevel@tonic-gate 			break;
850ba1637f8Smh138676 		case INET_TYPE_BOOLEAN:
8517c478bd9Sstevel@tonic-gate 			if (strcasecmp(value, INETADM_TRUE_STR) == 0)
8527c478bd9Sstevel@tonic-gate 				mod[j].ip_value.iv_boolean = B_TRUE;
8537c478bd9Sstevel@tonic-gate 			else if (strcasecmp(value, INETADM_FALSE_STR) == 0)
8547c478bd9Sstevel@tonic-gate 				mod[j].ip_value.iv_boolean = B_FALSE;
8557c478bd9Sstevel@tonic-gate 			else
8567c478bd9Sstevel@tonic-gate 				uu_die(gettext("Error: \"%s\" is not a valid "
8577c478bd9Sstevel@tonic-gate 				    "boolean value. (TRUE or FALSE)\n"), value);
8587c478bd9Sstevel@tonic-gate 		}
8597c478bd9Sstevel@tonic-gate 		/* mark property for modification */
8607c478bd9Sstevel@tonic-gate 		mod[j].ip_error = IVE_VALID;
8617c478bd9Sstevel@tonic-gate 
8627c478bd9Sstevel@tonic-gate 		/* return the '=' taken out above */
8637c478bd9Sstevel@tonic-gate 		*(--value) = '=';
8647c478bd9Sstevel@tonic-gate 	}
8657c478bd9Sstevel@tonic-gate 
8667c478bd9Sstevel@tonic-gate 	commit_props(inst, mod, B_FALSE);
8677c478bd9Sstevel@tonic-gate 	free(mod);
8687c478bd9Sstevel@tonic-gate 	if (smf_refresh_instance(fmri) != 0)
8697c478bd9Sstevel@tonic-gate 		uu_die(gettext("Error: Unable to refresh instance %s.\n"),
8707c478bd9Sstevel@tonic-gate 		    fmri);
8717c478bd9Sstevel@tonic-gate 
8727c478bd9Sstevel@tonic-gate 	return (0);
8737c478bd9Sstevel@tonic-gate }
8747c478bd9Sstevel@tonic-gate 
8757c478bd9Sstevel@tonic-gate /*
8767c478bd9Sstevel@tonic-gate  * modify_defaults takes n name=value pairs for inetd default property values,
8777c478bd9Sstevel@tonic-gate  * parses them, and then modifies the values in the repository.
8787c478bd9Sstevel@tonic-gate  */
8797c478bd9Sstevel@tonic-gate 
8807c478bd9Sstevel@tonic-gate static void
modify_defaults(int argc,char * argv[])8817c478bd9Sstevel@tonic-gate modify_defaults(int argc, char *argv[])
8827c478bd9Sstevel@tonic-gate {
8837c478bd9Sstevel@tonic-gate 	int			i, j;
8847c478bd9Sstevel@tonic-gate 	char			*value;
8857c478bd9Sstevel@tonic-gate 	scf_instance_t		*inst;
8867c478bd9Sstevel@tonic-gate 	inetd_prop_t		*mod, *prop_table;
8877c478bd9Sstevel@tonic-gate 	size_t			numprops;
8887c478bd9Sstevel@tonic-gate 	ssize_t			max_val;
8897c478bd9Sstevel@tonic-gate 	int64_t			new_int;
8907c478bd9Sstevel@tonic-gate 
8917c478bd9Sstevel@tonic-gate 	if ((inst = scf_instance_create(h)) == NULL)
8927c478bd9Sstevel@tonic-gate 		scfdie();
8937c478bd9Sstevel@tonic-gate 
8947c478bd9Sstevel@tonic-gate 	if (scf_handle_decode_fmri(h, INETD_INSTANCE_FMRI, NULL, NULL,
8957c478bd9Sstevel@tonic-gate 	    inst, NULL, NULL, SCF_DECODE_FMRI_EXACT) == -1) {
8967c478bd9Sstevel@tonic-gate 		if (scf_error() == SCF_ERROR_NOT_FOUND) {
8977c478bd9Sstevel@tonic-gate 			uu_die(gettext("inetd instance missing in repository."
8987c478bd9Sstevel@tonic-gate 			    "\n"));
8997c478bd9Sstevel@tonic-gate 		} else {
9007c478bd9Sstevel@tonic-gate 			scfdie();
9017c478bd9Sstevel@tonic-gate 		}
9027c478bd9Sstevel@tonic-gate 	}
9037c478bd9Sstevel@tonic-gate 
9047c478bd9Sstevel@tonic-gate 	if ((max_val = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH)) < 0)
9057c478bd9Sstevel@tonic-gate 		scfdie();
9067c478bd9Sstevel@tonic-gate 
9077c478bd9Sstevel@tonic-gate 	prop_table = get_prop_table(&numprops);
9087c478bd9Sstevel@tonic-gate 
9097c478bd9Sstevel@tonic-gate 	if ((mod = malloc(numprops * sizeof (inetd_prop_t))) == NULL)
9107c478bd9Sstevel@tonic-gate 		uu_die(gettext("Error: Out of memory.\n"));
9117c478bd9Sstevel@tonic-gate 
9127c478bd9Sstevel@tonic-gate 	(void) memcpy(mod, prop_table, numprops * sizeof (inetd_prop_t));
9137c478bd9Sstevel@tonic-gate 
9147c478bd9Sstevel@tonic-gate 	for (i = 0; i < argc; i++) {
9157c478bd9Sstevel@tonic-gate 		/* Separate argument into name and value pair */
9167c478bd9Sstevel@tonic-gate 		if ((value = strchr(argv[i], '=')) == NULL)
9177c478bd9Sstevel@tonic-gate 			uu_die(gettext("Error: Malformed name=value pair \"%s"
9187c478bd9Sstevel@tonic-gate 			    "\"\n"), argv[i]);
9197c478bd9Sstevel@tonic-gate 
9207c478bd9Sstevel@tonic-gate 		*value = '\0';
9217c478bd9Sstevel@tonic-gate 		value++;
9227c478bd9Sstevel@tonic-gate 
9237c478bd9Sstevel@tonic-gate 		/* Find property name in array of defaults */
924ba1637f8Smh138676 		for (j = 0; mod[j].ip_name != NULL; j++) {
9257c478bd9Sstevel@tonic-gate 			if (!mod[j].ip_default)
9267c478bd9Sstevel@tonic-gate 				continue;
9277c478bd9Sstevel@tonic-gate 			if (strcmp(mod[j].ip_name, argv[i]) == 0)
9287c478bd9Sstevel@tonic-gate 				break;
9297c478bd9Sstevel@tonic-gate 		}
9307c478bd9Sstevel@tonic-gate 
931ba1637f8Smh138676 		if (mod[j].ip_name == NULL)
9327c478bd9Sstevel@tonic-gate 			uu_die(gettext("Error: \"%s\" is not a default inetd "
9337c478bd9Sstevel@tonic-gate 			    "property.\n"), argv[i]);
9347c478bd9Sstevel@tonic-gate 
9357c478bd9Sstevel@tonic-gate 		if (*value == '\0')
9367c478bd9Sstevel@tonic-gate 			uu_die(gettext("Cannot accept NULL values for default "
9377c478bd9Sstevel@tonic-gate 			    "properties.\n"));
9387c478bd9Sstevel@tonic-gate 
9397c478bd9Sstevel@tonic-gate 		switch (mod[j].ip_type) {
940ba1637f8Smh138676 		case INET_TYPE_INTEGER:
941*95c74518SToomas Soome 			if (uu_strtoint(value, &new_int, sizeof (new_int), 0,
942*95c74518SToomas Soome 			    0, 0) == -1)
9437c478bd9Sstevel@tonic-gate 				uu_die(gettext("Error: \"%s\" is not a valid "
9447c478bd9Sstevel@tonic-gate 				    "integer value.\n"), value);
9457c478bd9Sstevel@tonic-gate 
9467c478bd9Sstevel@tonic-gate 			mod[j].ip_value.iv_int = new_int;
9477c478bd9Sstevel@tonic-gate 			break;
948ba1637f8Smh138676 		case INET_TYPE_STRING:
9497c478bd9Sstevel@tonic-gate 			if (strlen(value) >= max_val)
9507c478bd9Sstevel@tonic-gate 				uu_die(gettext("Error: String value is longer "
9517c478bd9Sstevel@tonic-gate 				    "than %l characters.\n"), max_val);
952ba1637f8Smh138676 			if ((mod[j].ip_value.iv_string = strdup(value))
9537c478bd9Sstevel@tonic-gate 			    == NULL)
9547c478bd9Sstevel@tonic-gate 				uu_die(gettext("Error: Out of memory.\n"));
9557c478bd9Sstevel@tonic-gate 			break;
956ba1637f8Smh138676 		case INET_TYPE_BOOLEAN:
9577c478bd9Sstevel@tonic-gate 			if (strcasecmp(value, INETADM_TRUE_STR) == 0)
9587c478bd9Sstevel@tonic-gate 				mod[j].ip_value.iv_boolean = B_TRUE;
9597c478bd9Sstevel@tonic-gate 			else if (strcasecmp(value, INETADM_FALSE_STR) == 0)
9607c478bd9Sstevel@tonic-gate 				mod[j].ip_value.iv_boolean = B_FALSE;
9617c478bd9Sstevel@tonic-gate 			else
9627c478bd9Sstevel@tonic-gate 				uu_die(gettext("Error: \"%s\" is not a valid "
9637c478bd9Sstevel@tonic-gate 				    "boolean value. (TRUE or FALSE)\n"), value);
9647c478bd9Sstevel@tonic-gate 		}
9657c478bd9Sstevel@tonic-gate 		/* mark property for modification */
9667c478bd9Sstevel@tonic-gate 		mod[j].ip_error = IVE_VALID;
9677c478bd9Sstevel@tonic-gate 	}
9687c478bd9Sstevel@tonic-gate 
9697c478bd9Sstevel@tonic-gate 	commit_props(inst, mod, B_TRUE);
9707c478bd9Sstevel@tonic-gate 	free(mod);
9717c478bd9Sstevel@tonic-gate 	scf_instance_destroy(inst);
9727c478bd9Sstevel@tonic-gate 	if (refresh_inetd() != 0)
9737c478bd9Sstevel@tonic-gate 		uu_warn(gettext("Warning: Unable to refresh inetd.\n"));
9747c478bd9Sstevel@tonic-gate }
9757c478bd9Sstevel@tonic-gate 
9767c478bd9Sstevel@tonic-gate int
main(int argc,char * argv[])9777c478bd9Sstevel@tonic-gate main(int argc, char *argv[])
9787c478bd9Sstevel@tonic-gate {
9797c478bd9Sstevel@tonic-gate 	int		opt;
9807c478bd9Sstevel@tonic-gate 	uint_t		lflag, eflag, dflag, pflag, mflag, Mflag;
9817c478bd9Sstevel@tonic-gate 	uint8_t		enable;
9827c478bd9Sstevel@tonic-gate 	scf_error_t	serr;
9837c478bd9Sstevel@tonic-gate 	int		exit_status = 0;
9847c478bd9Sstevel@tonic-gate 
9857c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
9867c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
9877c478bd9Sstevel@tonic-gate 
9887c478bd9Sstevel@tonic-gate 	if ((h = scf_handle_create(SCF_VERSION)) == NULL)
9897c478bd9Sstevel@tonic-gate 		scfdie();
9907c478bd9Sstevel@tonic-gate 
9917c478bd9Sstevel@tonic-gate 	if (scf_handle_bind(h) == -1)
9927c478bd9Sstevel@tonic-gate 		uu_die(gettext("Error: Couldn't bind to svc.configd.\n"));
9937c478bd9Sstevel@tonic-gate 
9947c478bd9Sstevel@tonic-gate 	if (argc == 1) {
9957c478bd9Sstevel@tonic-gate 		list_services();
9967c478bd9Sstevel@tonic-gate 		goto out;
9977c478bd9Sstevel@tonic-gate 	}
9987c478bd9Sstevel@tonic-gate 
9997c478bd9Sstevel@tonic-gate 	lflag = eflag = dflag = pflag = mflag = Mflag = 0;
10007c478bd9Sstevel@tonic-gate 	while ((opt = getopt(argc, argv, "ledpMm?")) != -1) {
10017c478bd9Sstevel@tonic-gate 		switch (opt) {
10027c478bd9Sstevel@tonic-gate 		case 'l':
10037c478bd9Sstevel@tonic-gate 			lflag = 1;
10047c478bd9Sstevel@tonic-gate 			break;
10057c478bd9Sstevel@tonic-gate 		case 'e':
10067c478bd9Sstevel@tonic-gate 			eflag = 1;
10077c478bd9Sstevel@tonic-gate 			break;
10087c478bd9Sstevel@tonic-gate 		case 'd':
10097c478bd9Sstevel@tonic-gate 			dflag = 1;
10107c478bd9Sstevel@tonic-gate 			break;
10117c478bd9Sstevel@tonic-gate 		case 'p':
10127c478bd9Sstevel@tonic-gate 			pflag = 1;
10137c478bd9Sstevel@tonic-gate 			break;
10147c478bd9Sstevel@tonic-gate 		case 'M':
10157c478bd9Sstevel@tonic-gate 			Mflag = 1;
10167c478bd9Sstevel@tonic-gate 			break;
10177c478bd9Sstevel@tonic-gate 		case 'm':
10187c478bd9Sstevel@tonic-gate 			mflag = 1;
10197c478bd9Sstevel@tonic-gate 			break;
10207c478bd9Sstevel@tonic-gate 		case '?':
10217c478bd9Sstevel@tonic-gate 			if (optopt == '?') {
10227c478bd9Sstevel@tonic-gate 				usage(B_TRUE);
10237c478bd9Sstevel@tonic-gate 				goto out;
10247c478bd9Sstevel@tonic-gate 			} else {
10257c478bd9Sstevel@tonic-gate 				usage(B_FALSE);
10267c478bd9Sstevel@tonic-gate 			}
1027c1a6e54cSToomas Soome 			break;
10287c478bd9Sstevel@tonic-gate 		default:
10297c478bd9Sstevel@tonic-gate 			usage(B_FALSE);
10307c478bd9Sstevel@tonic-gate 		}
10317c478bd9Sstevel@tonic-gate 	}
10327c478bd9Sstevel@tonic-gate 
10337c478bd9Sstevel@tonic-gate 	/*
10347c478bd9Sstevel@tonic-gate 	 * All options are mutually exclusive, and we must have an option
10357c478bd9Sstevel@tonic-gate 	 * if we reached here.
10367c478bd9Sstevel@tonic-gate 	 */
10377c478bd9Sstevel@tonic-gate 	if (lflag + eflag + dflag + pflag + mflag + Mflag != 1)
10387c478bd9Sstevel@tonic-gate 		usage(B_FALSE);
10397c478bd9Sstevel@tonic-gate 
10407c478bd9Sstevel@tonic-gate 	argv += optind;
10417c478bd9Sstevel@tonic-gate 	argc -= optind;
10427c478bd9Sstevel@tonic-gate 	if ((pflag == 0) && (argc == 0))
10437c478bd9Sstevel@tonic-gate 		usage(B_FALSE);
10447c478bd9Sstevel@tonic-gate 
10457c478bd9Sstevel@tonic-gate 	serr = 0;
10467c478bd9Sstevel@tonic-gate 	if (lflag) {
10477c478bd9Sstevel@tonic-gate 		serr = scf_walk_fmri(h, argc, argv, 0, list_props_cb, NULL,
10487c478bd9Sstevel@tonic-gate 		    &exit_status, uu_warn);
10497c478bd9Sstevel@tonic-gate 	} else if (dflag) {
10507c478bd9Sstevel@tonic-gate 		enable = 0;
10517c478bd9Sstevel@tonic-gate 		serr = scf_walk_fmri(h, argc, argv, 0, set_svc_enable_cb,
10527c478bd9Sstevel@tonic-gate 		    &enable, &exit_status, uu_warn);
10537c478bd9Sstevel@tonic-gate 	} else if (eflag) {
10547c478bd9Sstevel@tonic-gate 		enable = 1;
10557c478bd9Sstevel@tonic-gate 		serr = scf_walk_fmri(h, argc, argv, 0, set_svc_enable_cb,
10567c478bd9Sstevel@tonic-gate 		    &enable, &exit_status, uu_warn);
10577c478bd9Sstevel@tonic-gate 	} else if (mflag) {
10587c478bd9Sstevel@tonic-gate 		arglist_t	args;
10597c478bd9Sstevel@tonic-gate 		char		**cpp = argv;
10607c478bd9Sstevel@tonic-gate 		uint_t		fmri_args = 0;
10617c478bd9Sstevel@tonic-gate 
10627c478bd9Sstevel@tonic-gate 		/* count number of fmri arguments */
10637c478bd9Sstevel@tonic-gate 		while ((fmri_args < argc) && (strchr(*cpp, '=') == NULL)) {
10647c478bd9Sstevel@tonic-gate 			fmri_args++;
10657c478bd9Sstevel@tonic-gate 			cpp++;
10667c478bd9Sstevel@tonic-gate 		}
10677c478bd9Sstevel@tonic-gate 
10687c478bd9Sstevel@tonic-gate 		/* if no x=y args or no fmri, show usage */
10697c478bd9Sstevel@tonic-gate 		if ((fmri_args == argc) || (fmri_args == 0))
10707c478bd9Sstevel@tonic-gate 			usage(B_FALSE);
10717c478bd9Sstevel@tonic-gate 
10727c478bd9Sstevel@tonic-gate 		/* setup args for modify_inst_props_cb */
10737c478bd9Sstevel@tonic-gate 		args.argc = argc - fmri_args;
10747c478bd9Sstevel@tonic-gate 		args.argv = argv + fmri_args;
10757c478bd9Sstevel@tonic-gate 
10767c478bd9Sstevel@tonic-gate 		serr = scf_walk_fmri(h, fmri_args, argv, 0,
10777c478bd9Sstevel@tonic-gate 		    modify_inst_props_cb, &args, &exit_status, uu_warn);
10787c478bd9Sstevel@tonic-gate 	} else if (Mflag) {
10797c478bd9Sstevel@tonic-gate 		modify_defaults(argc, argv);
10807c478bd9Sstevel@tonic-gate 	} else if (pflag) {
10817c478bd9Sstevel@tonic-gate 		/* ensure there's no trailing garbage */
10827c478bd9Sstevel@tonic-gate 		if (argc != 0)
10837c478bd9Sstevel@tonic-gate 			usage(B_FALSE);
10847c478bd9Sstevel@tonic-gate 		list_defaults();
10857c478bd9Sstevel@tonic-gate 	}
10867c478bd9Sstevel@tonic-gate 	if (serr != 0) {
10877c478bd9Sstevel@tonic-gate 		uu_warn(gettext("failed to iterate over instances: %s"),
10887c478bd9Sstevel@tonic-gate 		    scf_strerror(serr));
10897c478bd9Sstevel@tonic-gate 		exit(UU_EXIT_FATAL);
10907c478bd9Sstevel@tonic-gate 	}
10917c478bd9Sstevel@tonic-gate 
10927c478bd9Sstevel@tonic-gate out:
10937c478bd9Sstevel@tonic-gate 	(void) scf_handle_unbind(h);
10947c478bd9Sstevel@tonic-gate 	scf_handle_destroy(h);
10957c478bd9Sstevel@tonic-gate 
10967c478bd9Sstevel@tonic-gate 	return (exit_status);
10977c478bd9Sstevel@tonic-gate }
1098