4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
30 * inetadm - administer services controlled by inetd and print out inetd
31 * service related information.
37 #include <libscf_priv.h>
48 #define TEXT_DOMAIN "SUNW_OST_OSCMD"
49 #endif /* TEXT_DOMAIN */
51 /* Strings for output to the user, and checking user's input */
53 #define INETADM_TRUE_STR "TRUE"
54 #define INETADM_FALSE_STR "FALSE"
55 #define INETADM_ENABLED_STR "enabled"
56 #define INETADM_DISABLED_STR "disabled"
57 #define INETADM_DEFAULT_STR "default"
59 /* String for checking if an instance is under inetd's control. */
61 #define INETADM_INETD_STR "network/inetd"
64 * Used to hold a list of scf_value_t's whilst performing a transaction
65 * to write a proto list back.
67 typedef struct scf_val_el
{
73 * Structure used to encapsulate argc and argv so they can be passed using the
74 * single data argument supplied by scf_walk_fmri() for the consumption of
75 * modify_inst_props_cb().
77 typedef struct arglist
{
82 static scf_handle_t
*h
;
87 uu_die(gettext("Unexpected libscf error: %s. Exiting.\n"),
88 scf_strerror(scf_error()));
92 usage(boolean_t detailed
)
100 " inetadm -l {FMRI | pattern}...\n"
101 " inetadm -e {FMRI | pattern}...\n"
102 " inetadm -d {FMRI | pattern}...\n"
103 " inetadm -m {FMRI | pattern}... {name=value}...\n"
104 " inetadm -M {name=value}...\n"));
109 (void) fprintf(stdout
, gettext(
111 "Without any options inetadm lists all inetd managed services.\n"
115 " -p List all default inetd property values.\n"
116 " -l List all inetd property values for the inet "
118 " -e Enable the inet service(s).\n"
119 " -d Disable the inet service(s).\n"
120 " -m Modify the inet service(s) inetd property values.\n"
121 " -M Modify default inetd property values.\n"));
125 * Add the proto list contained in array 'plist' to entry 'entry', storing
126 * aside the scf_value_t's created and added to the entry in a list that the
127 * pointer referenced by sv_list is made to point at.
130 add_proto_list(scf_transaction_entry_t
*entry
, scf_handle_t
*hdl
,
131 char **plist
, uu_list_t
**sv_list
)
136 static uu_list_pool_t
*sv_pool
= NULL
;
138 if ((sv_pool
== NULL
) &&
139 ((sv_pool
= uu_list_pool_create("sv_pool",
140 sizeof (scf_val_el_t
), offsetof(scf_val_el_t
, link
), NULL
,
141 UU_LIST_POOL_DEBUG
)) == NULL
))
142 uu_die(gettext("Error: %s.\n"), uu_strerror(uu_error()));
144 if ((*sv_list
= uu_list_create(sv_pool
, NULL
, 0)) == NULL
)
145 uu_die(gettext("Error: %s.\n"), uu_strerror(uu_error()));
147 for (i
= 0; plist
[i
] != NULL
; i
++) {
148 if ((sv_el
= malloc(sizeof (scf_val_el_t
))) == NULL
)
149 uu_die(gettext("Error:"));
151 if (((sv_el
->val
= scf_value_create(hdl
)) == NULL
) ||
152 (scf_value_set_astring(sv_el
->val
, plist
[i
]) != 0) ||
153 (scf_entry_add_value(entry
, sv_el
->val
) != 0))
156 uu_list_node_init(sv_el
, &sv_el
->link
, sv_pool
);
157 (void) uu_list_insert_after(*sv_list
, NULL
, sv_el
);
162 * A counterpart to add_proto_list(), this function removes and frees the
163 * scf_value_t's it added to entry 'entry'.
166 remove_proto_list(scf_transaction_entry_t
*entry
, uu_list_t
*sv_list
)
171 scf_entry_reset(entry
);
173 while ((sv_el
= uu_list_teardown(sv_list
, &cookie
)) != NULL
) {
174 scf_value_destroy(sv_el
->val
);
178 uu_list_destroy(sv_list
);
182 * modify_prop takes an instance, property group, property name, type, and
183 * value, and modifies the specified property in the repository to the
188 modify_prop(const scf_instance_t
*inst
, const char *pg
, const char *prop
,
189 scf_type_t type
, void *value
)
191 scf_transaction_t
*tx
;
192 scf_transaction_entry_t
*ent
;
193 scf_propertygroup_t
*gpg
;
194 scf_property_t
*eprop
;
198 ssize_t max_fmri_len
;
200 if ((gpg
= scf_pg_create(h
)) == NULL
||
201 (eprop
= scf_property_create(h
)) == NULL
||
202 (v
= scf_value_create(h
)) == NULL
)
205 /* Get the property group or create it if it is missing. */
206 if (scf_instance_get_pg(inst
, pg
, gpg
) == -1) {
207 if (scf_error() != SCF_ERROR_NOT_FOUND
)
210 max_fmri_len
= scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH
);
211 if ((fmri
= malloc(max_fmri_len
+ 1)) == NULL
)
212 uu_die(gettext("Error: Out of memory.\n"));
214 if (scf_instance_to_fmri(inst
, fmri
, max_fmri_len
+ 1) < 0)
217 syslog(LOG_NOTICE
, "inetadm: Property group \"%s\" missing "
218 "from \"%s\", attempting to add it.\n", pg
, fmri
);
221 if (scf_instance_add_pg(inst
, pg
, SCF_GROUP_FRAMEWORK
, 0,
223 switch (scf_error()) {
224 case SCF_ERROR_EXISTS
:
226 case SCF_ERROR_PERMISSION_DENIED
:
227 uu_die(gettext("Error: Permission denied.\n"));
234 if (scf_pg_get_property(gpg
, prop
, eprop
) == -1) {
235 if (scf_error() != SCF_ERROR_NOT_FOUND
)
241 if ((tx
= scf_transaction_create(h
)) == NULL
||
242 (ent
= scf_entry_create(h
)) == NULL
)
248 if (scf_transaction_start(tx
, gpg
) == -1) {
249 if (scf_error() != SCF_ERROR_PERMISSION_DENIED
)
252 uu_die(gettext("Error: Permission denied.\n"));
255 /* Modify the property or create it if it is missing */
257 ret
= scf_transaction_property_new(tx
, ent
, prop
, type
);
259 ret
= scf_transaction_property_change_type(tx
, ent
,
265 case SCF_TYPE_BOOLEAN
:
266 scf_value_set_boolean(v
, *(uint8_t *)value
);
268 case SCF_TYPE_INTEGER
:
269 scf_value_set_integer(v
, *(int64_t *)value
);
271 case SCF_TYPE_ASTRING
:
272 if (strcmp(prop
, PR_PROTO_NAME
) == 0) {
273 add_proto_list(ent
, h
, (char **)value
,
275 } else if (scf_value_set_astring(v
, value
) == -1) {
280 uu_die(gettext("Error: Internal inetadm error"));
283 if ((strcmp(prop
, PR_PROTO_NAME
) != 0) &&
284 (scf_entry_add_value(ent
, v
) == -1))
287 ret
= scf_transaction_commit(tx
);
289 if (scf_error() != SCF_ERROR_PERMISSION_DENIED
)
292 uu_die(gettext("Error: Permission denied.\n"));
295 scf_transaction_reset(tx
);
298 if (scf_pg_update(gpg
) == -1)
302 if (strcmp(prop
, PR_PROTO_NAME
) == 0)
303 remove_proto_list(ent
, sv_list
);
307 scf_value_destroy(v
);
308 scf_entry_destroy(ent
);
309 scf_transaction_destroy(tx
);
310 scf_property_destroy(eprop
);
315 * delete_prop takes an instance, property group name and property, and
316 * deletes the specified property from the repository.
320 delete_prop(const scf_instance_t
*inst
, const char *pg
, const char *prop
)
322 scf_transaction_t
*tx
;
323 scf_transaction_entry_t
*ent
;
324 scf_propertygroup_t
*gpg
;
325 scf_property_t
*eprop
;
328 if ((gpg
= scf_pg_create(h
)) == NULL
||
329 (eprop
= scf_property_create(h
)) == NULL
||
330 (tx
= scf_transaction_create(h
)) == NULL
||
331 (ent
= scf_entry_create(h
)) == NULL
)
334 if (scf_instance_get_pg(inst
, pg
, gpg
) != SCF_SUCCESS
) {
335 if (scf_error() != SCF_ERROR_NOT_FOUND
)
338 uu_die(gettext("Error: \"%s\" property group missing.\n"), pg
);
342 if (scf_transaction_start(tx
, gpg
) != SCF_SUCCESS
) {
343 if (scf_error() != SCF_ERROR_PERMISSION_DENIED
)
346 uu_die(gettext("Error: Permission denied.\n"));
349 if (scf_transaction_property_delete(tx
, ent
,
350 prop
) != SCF_SUCCESS
) {
351 if (scf_error() != SCF_ERROR_NOT_FOUND
)
355 gettext("Error: \"%s\" property does not exist.\n"),
359 ret
= scf_transaction_commit(tx
);
361 if (scf_error() != SCF_ERROR_PERMISSION_DENIED
)
364 uu_die(gettext("Error: Permission denied.\n"));
367 scf_transaction_reset(tx
);
368 if (scf_pg_update(gpg
) == -1)
373 (void) scf_entry_destroy(ent
);
374 scf_transaction_destroy(tx
);
375 scf_property_destroy(eprop
);
380 * commit_props evaluates an entire property list that has been created
381 * based on command line options, and either deletes or modifies properties
386 commit_props(const scf_instance_t
*inst
, inetd_prop_t
*mod
, boolean_t defaults
)
391 for (i
= 0; mod
[i
].ip_name
!= NULL
; i
++) {
392 switch (mod
[i
].ip_error
) {
396 delete_prop(inst
, mod
[i
].ip_pg
, mod
[i
].ip_name
);
399 switch (mod
[i
].ip_type
) {
400 case INET_TYPE_STRING
:
402 defaults
? PG_NAME_SERVICE_DEFAULTS
:
403 mod
[i
].ip_pg
, mod
[i
].ip_name
,
405 mod
[i
].ip_value
.iv_string
);
407 case INET_TYPE_STRING_LIST
:
409 defaults
? PG_NAME_SERVICE_DEFAULTS
:
410 mod
[i
].ip_pg
, mod
[i
].ip_name
,
412 mod
[i
].ip_value
.iv_string_list
);
414 case INET_TYPE_INTEGER
:
416 defaults
? PG_NAME_SERVICE_DEFAULTS
:
417 mod
[i
].ip_pg
, mod
[i
].ip_name
,
418 SCF_TYPE_INTEGER
, &mod
[i
].ip_value
.iv_int
);
420 case INET_TYPE_BOOLEAN
:
421 new_bool
= (mod
[i
].ip_value
.iv_boolean
) ? 1 : 0;
424 defaults
? PG_NAME_SERVICE_DEFAULTS
:
425 mod
[i
].ip_pg
, mod
[i
].ip_name
,
426 SCF_TYPE_BOOLEAN
, &new_bool
);
434 * list_callback is the callback function to be handed to simple_walk_instances
435 * in list_services. It is called once on every instance on a machine. If
436 * that instance is controlled by inetd, it prints enabled/disabled, state,
442 list_callback(scf_handle_t
*hin
, scf_instance_t
*inst
, void *buf
)
444 ssize_t max_name_length
;
446 scf_simple_prop_t
*prop
= NULL
, *prop2
= NULL
;
447 const uint8_t *enabled
;
448 const char *state
, *restart_str
;
450 max_name_length
= scf_limit(SCF_LIMIT_MAX_NAME_LENGTH
);
451 if ((inst_name
= malloc(max_name_length
+ 1)) == NULL
)
452 uu_die(gettext("Error: Out of memory.\n"));
455 * Get the FMRI of the instance, and check if its delegated restarter
459 if (scf_instance_to_fmri(inst
, inst_name
, max_name_length
+ 1) < 0)
462 if ((prop
= scf_simple_prop_get(hin
, inst_name
, SCF_PG_GENERAL
,
463 SCF_PROPERTY_RESTARTER
)) == NULL
)
466 if ((restart_str
= scf_simple_prop_next_ustring(prop
)) == NULL
)
469 if (strstr(restart_str
, INETADM_INETD_STR
) == NULL
)
472 /* Free restarter prop so it can be reused below */
473 scf_simple_prop_free(prop
);
476 * We know that this instance is managed by inetd.
477 * Now get the enabled and state properties.
480 if (((prop
= scf_simple_prop_get(hin
, inst_name
, SCF_PG_GENERAL
,
481 SCF_PROPERTY_ENABLED
)) == NULL
) ||
482 ((enabled
= scf_simple_prop_next_boolean(prop
)) == NULL
)) {
483 (void) uu_warn(gettext("Error: Instance %s is missing enabled "
484 "property.\n"), inst_name
);
488 if (((prop2
= scf_simple_prop_get(hin
, inst_name
, SCF_PG_RESTARTER
,
489 SCF_PROPERTY_STATE
)) == NULL
) ||
490 ((state
= scf_simple_prop_next_astring(prop2
)) == NULL
)) {
491 (void) uu_warn(gettext("Error: Instance %s is missing state "
492 "property.\n"), inst_name
);
496 /* Print enabled/disabled, state, and FMRI for the instance. */
499 (void) printf("%-10s%-15s%s\n", INETADM_ENABLED_STR
, state
,
502 (void) printf("%-10s%-15s%s\n", INETADM_DISABLED_STR
, state
,
507 scf_simple_prop_free(prop
);
508 scf_simple_prop_free(prop2
);
509 return (SCF_SUCCESS
);
513 * list_services calls list_callback on every instance on the machine.
519 (void) printf("%-10s%-15s%s\n", "ENABLED", "STATE", "FMRI");
521 if (scf_simple_walk_instances(SCF_STATE_ALL
, NULL
, list_callback
) ==
527 print_prop_val(inetd_prop_t
*prop
)
529 switch (prop
->ip_type
) {
530 case INET_TYPE_STRING
:
531 (void) printf("\"%s\"\n", prop
->ip_value
.iv_string
);
533 case INET_TYPE_STRING_LIST
:
536 char **cpp
= prop
->ip_value
.iv_string_list
;
539 * Print string list as comma separated list.
542 (void) printf("\"%s", cpp
[j
]);
543 while (cpp
[++j
] != NULL
)
544 (void) printf(",%s", cpp
[j
]);
545 (void) printf("\"\n");
548 case INET_TYPE_INTEGER
:
549 (void) printf("%lld\n", prop
->ip_value
.iv_int
);
551 case INET_TYPE_BOOLEAN
:
552 if (prop
->ip_value
.iv_boolean
)
553 (void) printf("%s\n", INETADM_TRUE_STR
);
555 (void) printf("%s\n", INETADM_FALSE_STR
);
561 * list_props_cb is a callback function for scf_walk_fmri that lists all
562 * relevant inetd properties for an instance managed by inetd.
567 list_props_cb(void *data
, scf_walkinfo_t
*wip
)
570 const char *instname
= wip
->fmri
;
571 scf_simple_prop_t
*prop
;
572 inetd_prop_t
*proplist
;
573 const char *restart_str
;
574 boolean_t is_rpc
= B_FALSE
;
579 if (((h
= scf_handle_create(SCF_VERSION
)) == NULL
) ||
580 (scf_handle_bind(h
) == -1))
584 * Get the property that holds the name of this instance's
585 * restarter, and make sure that it is inetd.
587 if ((prop
= scf_simple_prop_get(h
, instname
, SCF_PG_GENERAL
,
588 SCF_PROPERTY_RESTARTER
)) == NULL
) {
589 if (scf_error() == SCF_ERROR_NOT_FOUND
)
590 uu_die(gettext("Error: Specified service instance "
591 "\"%s\" has no restarter property. inetd is not "
592 "the delegated restarter of this instance.\n"),
594 if (scf_error() == SCF_ERROR_INVALID_ARGUMENT
)
595 uu_die(gettext("Error: \"%s\" is not a valid service "
596 "instance.\n"), instname
);
601 if (((restart_str
= scf_simple_prop_next_ustring(prop
)) == NULL
) ||
602 (strstr(restart_str
, INETADM_INETD_STR
) == NULL
)) {
603 uu_die(gettext("Error: inetd is not the delegated restarter of "
604 "specified service instance \"%s\".\n"), instname
);
607 scf_simple_prop_free(prop
);
610 * This instance is controlled by inetd, so now we display all
611 * of its properties. First the mandatory properties, and then
612 * the properties that have default values, substituting the
613 * default values inherited from inetd as necessary (this is done
614 * for us by read_instance_props()).
617 if ((proplist
= read_instance_props(h
, instname
, &numprops
, &err
)) ==
619 uu_die(gettext("Unexpected libscf error: %s. Exiting.\n"),
622 scf_handle_destroy(h
);
624 (void) printf("%-9s%s\n", "SCOPE", "NAME=VALUE");
626 for (i
= 0; i
< numprops
; i
++) {
627 /* Skip rpc version properties if it's not an RPC service */
628 if ((strcmp(PR_RPC_LW_VER_NAME
, proplist
[i
].ip_name
) == 0) ||
629 (strcmp(PR_RPC_HI_VER_NAME
, proplist
[i
].ip_name
) == 0))
633 /* If it's not an unset property, print it out. */
634 if (proplist
[i
].ip_error
!= IVE_UNSET
) {
635 if (strcmp(PR_ISRPC_NAME
, proplist
[i
].ip_name
) == 0)
636 is_rpc
= proplist
[i
].ip_value
.iv_boolean
;
638 (void) printf("%-9s%s=",
639 proplist
[i
].from_inetd
? INETADM_DEFAULT_STR
: "",
640 proplist
[i
].ip_name
);
641 print_prop_val(&proplist
[i
]);
645 /* arg0 is non-default, but also doesn't have to be set. */
647 if (i
== PT_ARG0_INDEX
)
650 /* all other properties should have values. */
651 if (proplist
[i
].ip_default
) {
652 (void) uu_warn(gettext("Error: Property %s is missing "
653 "and has no defined default value.\n"),
654 proplist
[i
].ip_name
);
656 (void) uu_warn(gettext("Error: Required property %s is "
657 "missing.\n"), proplist
[i
].ip_name
);
661 free_instance_props(proplist
);
666 * set_svc_enable_cb is a callback function for scf_walk_fmri that sets the
667 * enabled property in the repository for an instance based on the value given
672 set_svc_enable_cb(void *data
, scf_walkinfo_t
*wip
)
674 uint8_t desired
= *(uint8_t *)data
;
675 const char *instname
= wip
->fmri
;
678 if (smf_enable_instance(instname
, 0) == 0)
681 if (smf_disable_instance(instname
, 0) == 0)
685 switch (scf_error()) {
686 case SCF_ERROR_INVALID_ARGUMENT
:
687 uu_die(gettext("Error: \"%s\" is not a valid service "
688 "instance.\n"), instname
);
690 case SCF_ERROR_NOT_FOUND
:
691 uu_die(gettext("Error: Service instance \"%s\" not found.\n"),
702 * list_defaults lists all the default property values being provided by
712 inetd_prop_t
*proptable
;
715 if (((h
= scf_handle_create(SCF_VERSION
)) == NULL
) ||
716 (scf_handle_bind(h
) == -1))
719 if ((proptable
= read_default_props(h
, &numprops
, &err
)) == NULL
) {
720 uu_die(gettext("Unexpected libscf error: %s. Exiting.\n"),
724 (void) printf("NAME=VALUE\n");
726 for (i
= 0; i
< numprops
; i
++) {
727 if (!proptable
[i
].ip_default
)
730 if (proptable
[i
].ip_error
== IVE_UNSET
) {
731 (void) uu_warn(gettext("Error: Default property %s "
732 "missing.\n"), proptable
[i
].ip_name
);
736 (void) printf("%s=", proptable
[i
].ip_name
);
737 print_prop_val(&proptable
[i
]);
740 free_instance_props(proptable
);
744 * modify_inst_props_cb is a callback function for scf_walk_fmri that modifies
745 * the properties that are given as name=value pairs on the command line
746 * to the requested value.
750 modify_inst_props_cb(void *data
, scf_walkinfo_t
*wip
)
754 const char *fmri
= wip
->fmri
;
755 scf_instance_t
*inst
= wip
->inst
;
756 inetd_prop_t
*mod
, *prop_table
;
760 int argc
= ((arglist_t
*)data
)->argc
;
761 char **argv
= ((arglist_t
*)data
)->argv
;
763 if ((max_val
= scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH
)) < 0)
766 prop_table
= get_prop_table(&numprops
);
768 if ((mod
= malloc(numprops
* sizeof (inetd_prop_t
))) == NULL
)
769 uu_die(gettext("Error: Out of memory.\n"));
771 (void) memcpy(mod
, prop_table
, numprops
* sizeof (inetd_prop_t
));
774 * For each property to be changed, look up the property name in the
775 * property table. Change each property in the mod array, and then
776 * write the entire thing back.
778 for (i
= 0; i
< argc
; i
++) {
779 /* Separate argument into name and value pair */
780 if ((value
= strchr(argv
[i
], '=')) == NULL
)
781 uu_die(gettext("Error: Malformed name=value pair "
782 "\"%s\"\n"), argv
[i
]);
787 /* Find property name in array of properties */
788 for (j
= 0; mod
[j
].ip_name
!= NULL
; j
++) {
789 if (strcmp(mod
[j
].ip_name
, argv
[i
]) == 0)
793 if (mod
[j
].ip_name
== NULL
)
794 uu_die(gettext("Error: \"%s\" is not a valid "
795 "property.\n"), argv
[i
]);
797 if (*value
== '\0') {
798 if ((mod
[j
].ip_default
) || (j
== PT_ARG0_INDEX
)) {
799 /* mark property for deletion */
800 mod
[j
].ip_error
= IVE_INVALID
;
802 /* return the '=' taken out above */
807 uu_die(gettext("\"%s\" is a mandatory "
808 "property and can not be deleted.\n"),
813 switch (mod
[j
].ip_type
) {
814 case INET_TYPE_INTEGER
:
815 if (uu_strtoint(value
, &new_int
, sizeof (new_int
), NULL
,
817 uu_die(gettext("Error: \"%s\" is not a valid "
818 "integer value.\n"), value
);
820 mod
[j
].ip_value
.iv_int
= new_int
;
822 case INET_TYPE_STRING
:
823 if (strlen(value
) >= max_val
) {
824 uu_die(gettext("Error: String value is longer "
825 "than %l characters.\n"), max_val
);
826 } else if ((mod
[j
].ip_value
.iv_string
= strdup(value
))
828 uu_die(gettext("Error: Out of memory.\n"));
831 case INET_TYPE_STRING_LIST
:
832 if ((mod
[j
].ip_value
.iv_string_list
=
833 get_protos(value
)) == NULL
) {
834 if (errno
== ENOMEM
) {
836 "Error: Out of memory.\n"));
837 } else if (errno
== E2BIG
) {
839 "Error: String value in "
840 "%s property longer than "
842 PR_PROTO_NAME
, max_val
);
852 case INET_TYPE_BOOLEAN
:
853 if (strcasecmp(value
, INETADM_TRUE_STR
) == 0)
854 mod
[j
].ip_value
.iv_boolean
= B_TRUE
;
855 else if (strcasecmp(value
, INETADM_FALSE_STR
) == 0)
856 mod
[j
].ip_value
.iv_boolean
= B_FALSE
;
858 uu_die(gettext("Error: \"%s\" is not a valid "
859 "boolean value. (TRUE or FALSE)\n"), value
);
861 /* mark property for modification */
862 mod
[j
].ip_error
= IVE_VALID
;
864 /* return the '=' taken out above */
868 commit_props(inst
, mod
, B_FALSE
);
870 if (smf_refresh_instance(fmri
) != 0)
871 uu_die(gettext("Error: Unable to refresh instance %s.\n"),
878 * modify_defaults takes n name=value pairs for inetd default property values,
879 * parses them, and then modifies the values in the repository.
883 modify_defaults(int argc
, char *argv
[])
887 scf_instance_t
*inst
;
888 inetd_prop_t
*mod
, *prop_table
;
893 if ((inst
= scf_instance_create(h
)) == NULL
)
896 if (scf_handle_decode_fmri(h
, INETD_INSTANCE_FMRI
, NULL
, NULL
,
897 inst
, NULL
, NULL
, SCF_DECODE_FMRI_EXACT
) == -1) {
898 if (scf_error() == SCF_ERROR_NOT_FOUND
) {
899 uu_die(gettext("inetd instance missing in repository."
906 if ((max_val
= scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH
)) < 0)
909 prop_table
= get_prop_table(&numprops
);
911 if ((mod
= malloc(numprops
* sizeof (inetd_prop_t
))) == NULL
)
912 uu_die(gettext("Error: Out of memory.\n"));
914 (void) memcpy(mod
, prop_table
, numprops
* sizeof (inetd_prop_t
));
916 for (i
= 0; i
< argc
; i
++) {
917 /* Separate argument into name and value pair */
918 if ((value
= strchr(argv
[i
], '=')) == NULL
)
919 uu_die(gettext("Error: Malformed name=value pair \"%s"
925 /* Find property name in array of defaults */
926 for (j
= 0; mod
[j
].ip_name
!= NULL
; j
++) {
927 if (!mod
[j
].ip_default
)
929 if (strcmp(mod
[j
].ip_name
, argv
[i
]) == 0)
933 if (mod
[j
].ip_name
== NULL
)
934 uu_die(gettext("Error: \"%s\" is not a default inetd "
935 "property.\n"), argv
[i
]);
938 uu_die(gettext("Cannot accept NULL values for default "
941 switch (mod
[j
].ip_type
) {
942 case INET_TYPE_INTEGER
:
943 if (uu_strtoint(value
, &new_int
, sizeof (new_int
), NULL
,
945 uu_die(gettext("Error: \"%s\" is not a valid "
946 "integer value.\n"), value
);
948 mod
[j
].ip_value
.iv_int
= new_int
;
950 case INET_TYPE_STRING
:
951 if (strlen(value
) >= max_val
)
952 uu_die(gettext("Error: String value is longer "
953 "than %l characters.\n"), max_val
);
954 if ((mod
[j
].ip_value
.iv_string
= strdup(value
))
956 uu_die(gettext("Error: Out of memory.\n"));
958 case INET_TYPE_BOOLEAN
:
959 if (strcasecmp(value
, INETADM_TRUE_STR
) == 0)
960 mod
[j
].ip_value
.iv_boolean
= B_TRUE
;
961 else if (strcasecmp(value
, INETADM_FALSE_STR
) == 0)
962 mod
[j
].ip_value
.iv_boolean
= B_FALSE
;
964 uu_die(gettext("Error: \"%s\" is not a valid "
965 "boolean value. (TRUE or FALSE)\n"), value
);
967 /* mark property for modification */
968 mod
[j
].ip_error
= IVE_VALID
;
971 commit_props(inst
, mod
, B_TRUE
);
973 scf_instance_destroy(inst
);
974 if (refresh_inetd() != 0)
975 uu_warn(gettext("Warning: Unable to refresh inetd.\n"));
979 main(int argc
, char *argv
[])
982 uint_t lflag
, eflag
, dflag
, pflag
, mflag
, Mflag
;
987 (void) setlocale(LC_ALL
, "");
988 (void) textdomain(TEXT_DOMAIN
);
990 if ((h
= scf_handle_create(SCF_VERSION
)) == NULL
)
993 if (scf_handle_bind(h
) == -1)
994 uu_die(gettext("Error: Couldn't bind to svc.configd.\n"));
1001 lflag
= eflag
= dflag
= pflag
= mflag
= Mflag
= 0;
1002 while ((opt
= getopt(argc
, argv
, "ledpMm?")) != -1) {
1023 if (optopt
== '?') {
1035 * All options are mutually exclusive, and we must have an option
1036 * if we reached here.
1038 if (lflag
+ eflag
+ dflag
+ pflag
+ mflag
+ Mflag
!= 1)
1043 if ((pflag
== 0) && (argc
== 0))
1048 serr
= scf_walk_fmri(h
, argc
, argv
, 0, list_props_cb
, NULL
,
1049 &exit_status
, uu_warn
);
1052 serr
= scf_walk_fmri(h
, argc
, argv
, 0, set_svc_enable_cb
,
1053 &enable
, &exit_status
, uu_warn
);
1056 serr
= scf_walk_fmri(h
, argc
, argv
, 0, set_svc_enable_cb
,
1057 &enable
, &exit_status
, uu_warn
);
1061 uint_t fmri_args
= 0;
1063 /* count number of fmri arguments */
1064 while ((fmri_args
< argc
) && (strchr(*cpp
, '=') == NULL
)) {
1069 /* if no x=y args or no fmri, show usage */
1070 if ((fmri_args
== argc
) || (fmri_args
== 0))
1073 /* setup args for modify_inst_props_cb */
1074 args
.argc
= argc
- fmri_args
;
1075 args
.argv
= argv
+ fmri_args
;
1077 serr
= scf_walk_fmri(h
, fmri_args
, argv
, 0,
1078 modify_inst_props_cb
, &args
, &exit_status
, uu_warn
);
1080 modify_defaults(argc
, argv
);
1082 /* ensure there's no trailing garbage */
1088 uu_warn(gettext("failed to iterate over instances: %s"),
1089 scf_strerror(serr
));
1090 exit(UU_EXIT_FATAL
);
1094 (void) scf_handle_unbind(h
);
1095 scf_handle_destroy(h
);
1097 return (exit_status
);