/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* inetadm - administer services controlled by inetd and print out inetd
* service related information.
*/
#include <locale.h>
#include <libintl.h>
#include <libscf.h>
#include <libscf_priv.h>
#include <libuutil.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <inetsvc.h>
#include <errno.h>
#ifndef TEXT_DOMAIN
#endif /* TEXT_DOMAIN */
/* Strings for output to the user, and checking user's input */
/* String for checking if an instance is under inetd's control. */
/*
* Used to hold a list of scf_value_t's whilst performing a transaction
* to write a proto list back.
*/
typedef struct scf_val_el {
} scf_val_el_t;
/*
* Structure used to encapsulate argc and argv so they can be passed using the
* single data argument supplied by scf_walk_fmri() for the consumption of
* modify_inst_props_cb().
*/
typedef struct arglist {
int argc;
char **argv;
} arglist_t;
static scf_handle_t *h;
static void
scfdie()
{
scf_strerror(scf_error()));
}
static void
{
"Usage:\n"
" inetadm\n"
" inetadm -?\n"
" inetadm -p\n"
" inetadm -l {FMRI | pattern}...\n"
" inetadm -e {FMRI | pattern}...\n"
" inetadm -d {FMRI | pattern}...\n"
" inetadm -m {FMRI | pattern}... {name=value}...\n"
" inetadm -M {name=value}...\n"));
if (!detailed)
"\n"
"Without any options inetadm lists all inetd managed services.\n"
"\n"
"Options:\n"
" -? Print help.\n"
" -p List all default inetd property values.\n"
" -l List all inetd property values for the inet "
"service(s).\n"
" -e Enable the inet service(s).\n"
" -d Disable the inet service(s).\n"
" -m Modify the inet service(s) inetd property values.\n"
" -M Modify default inetd property values.\n"));
}
/*
* Add the proto list contained in array 'plist' to entry 'entry', storing
* aside the scf_value_t's created and added to the entry in a list that the
* pointer referenced by sv_list is made to point at.
*/
static void
{
int i;
UU_LIST_POOL_DEBUG)) == NULL))
scfdie();
}
}
/*
* A counterpart to add_proto_list(), this function removes and frees the
* scf_value_t's it added to entry 'entry'.
*/
static void
{
}
}
/*
* modify_prop takes an instance, property group, property name, type, and
* value, and modifies the specified property in the repository to the
* submitted value.
*/
static void
{
scf_value_t *v;
char *fmri;
(v = scf_value_create(h)) == NULL)
scfdie();
/* Get the property group or create it if it is missing. */
if (scf_error() != SCF_ERROR_NOT_FOUND)
scfdie();
scfdie();
gpg) == -1) {
switch (scf_error()) {
case SCF_ERROR_EXISTS:
break;
default:
scfdie();
}
}
}
if (scf_error() != SCF_ERROR_NOT_FOUND)
scfdie();
create = 1;
}
scfdie();
do {
if (scf_error() != SCF_ERROR_PERMISSION_DENIED)
scfdie();
}
/* Modify the property or create it if it is missing */
if (create)
else
if (ret == -1)
scfdie();
switch (type) {
case SCF_TYPE_BOOLEAN:
break;
case SCF_TYPE_INTEGER:
break;
case SCF_TYPE_ASTRING:
&sv_list);
scfdie();
}
break;
default:
}
scfdie();
if (ret == -1) {
if (scf_error() != SCF_ERROR_PERMISSION_DENIED)
scfdie();
}
if (ret == 0) {
scfdie();
}
} while (ret == 0);
}
/*
* delete_prop takes an instance, property group name and property, and
* deletes the specified property from the repository.
*/
static void
{
int ret;
scfdie();
if (scf_error() != SCF_ERROR_NOT_FOUND)
scfdie();
}
do {
if (scf_error() != SCF_ERROR_PERMISSION_DENIED)
scfdie();
}
prop) != SCF_SUCCESS) {
if (scf_error() != SCF_ERROR_NOT_FOUND)
scfdie();
gettext("Error: \"%s\" property does not exist.\n"),
prop);
}
if (ret < 0) {
if (scf_error() != SCF_ERROR_PERMISSION_DENIED)
scfdie();
}
if (ret == 0) {
scfdie();
}
} while (ret == 0);
(void) scf_entry_destroy(ent);
}
/*
* commit_props evaluates an entire property list that has been created
* based on command line options, and either deletes or modifies properties
* as requested.
*/
static void
{
int i;
case IVE_UNSET:
break;
case IVE_INVALID:
break;
case IVE_VALID:
case INET_TYPE_STRING:
break;
case INET_TYPE_STRING_LIST:
break;
case INET_TYPE_INTEGER:
break;
case INET_TYPE_BOOLEAN:
break;
}
}
}
}
/*
* list_callback is the callback function to be handed to simple_walk_instances
* in list_services. It is called once on every instance on a machine. If
* and instance FMRI.
*/
/*ARGSUSED*/
static int
{
char *inst_name;
/*
* Get the FMRI of the instance, and check if its delegated restarter
* is inetd.
*/
return (SCF_FAILED);
SCF_PROPERTY_RESTARTER)) == NULL)
goto out;
goto out;
goto out;
/* Free restarter prop so it can be reused below */
/*
* We know that this instance is managed by inetd.
* Now get the enabled and state properties.
*/
SCF_PROPERTY_ENABLED)) == NULL) ||
"property.\n"), inst_name);
goto out;
}
SCF_PROPERTY_STATE)) == NULL) ||
"property.\n"), inst_name);
goto out;
}
if (*enabled)
else
out:
return (SCF_SUCCESS);
}
/*
* list_services calls list_callback on every instance on the machine.
*/
static void
{
scfdie();
}
static void
{
case INET_TYPE_STRING:
break;
case INET_TYPE_STRING_LIST:
{
int j = 0;
/*
* Print string list as comma separated list.
*/
(void) printf("\"\n");
}
break;
case INET_TYPE_INTEGER:
break;
case INET_TYPE_BOOLEAN:
else
break;
}
}
/*
* list_props_cb is a callback function for scf_walk_fmri that lists all
* relevant inetd properties for an instance managed by inetd.
*/
/* ARGSUSED0 */
static int
{
int i;
const char *restart_str;
scf_handle_t *h;
(scf_handle_bind(h) == -1))
scfdie();
/*
* Get the property that holds the name of this instance's
* restarter, and make sure that it is inetd.
*/
SCF_PROPERTY_RESTARTER)) == NULL) {
if (scf_error() == SCF_ERROR_NOT_FOUND)
"\"%s\" has no restarter property. inetd is not "
"the delegated restarter of this instance.\n"),
instname);
if (scf_error() == SCF_ERROR_INVALID_ARGUMENT)
"instance.\n"), instname);
scfdie();
}
"specified service instance \"%s\".\n"), instname);
}
/*
* This instance is controlled by inetd, so now we display all
* of its properties. First the mandatory properties, and then
* the properties that have default values, substituting the
* default values inherited from inetd as necessary (this is done
* for us by read_instance_props()).
*/
NULL) {
scf_strerror(err));
}
for (i = 0; i < numprops; i++) {
/* Skip rpc version properties if it's not an RPC service */
if (!is_rpc)
continue;
/* If it's not an unset property, print it out. */
(void) printf("%-9s%s=",
print_prop_val(&proplist[i]);
continue;
}
/* arg0 is non-default, but also doesn't have to be set. */
if (i == PT_ARG0_INDEX)
continue;
/* all other properties should have values. */
if (proplist[i].ip_default) {
"and has no defined default value.\n"),
} else {
}
}
return (0);
}
/*
* set_svc_enable_cb is a callback function for scf_walk_fmri that sets the
* enabled property in the repository for an instance based on the value given
* by 'data'.
*/
static int
{
if (desired) {
if (smf_enable_instance(instname, 0) == 0)
return (0);
} else {
if (smf_disable_instance(instname, 0) == 0)
return (0);
}
switch (scf_error()) {
"instance.\n"), instname);
break;
case SCF_ERROR_NOT_FOUND:
instname);
break;
default:
scfdie();
}
return (0);
}
/*
* list_defaults lists all the default property values being provided by
* inetd.
*/
static void
{
scf_handle_t *h;
int i;
(scf_handle_bind(h) == -1))
scfdie();
scf_strerror(err));
}
(void) printf("NAME=VALUE\n");
for (i = 0; i < numprops; i++) {
if (!proptable[i].ip_default)
continue;
continue;
}
print_prop_val(&proptable[i]);
}
}
/*
* modify_inst_props_cb is a callback function for scf_walk_fmri that modifies
* the properties that are given as name=value pairs on the command line
* to the requested value.
*/
static int
{
int i, j;
char *value;
scfdie();
/*
* For each property to be changed, look up the property name in the
* property table. Change each property in the mod array, and then
* write the entire thing back.
*/
for (i = 0; i < argc; i++) {
/* Separate argument into name and value pair */
"\"%s\"\n"), argv[i]);
*value = '\0';
value++;
/* Find property name in array of properties */
break;
}
"property.\n"), argv[i]);
if (*value == '\0') {
/* mark property for deletion */
/* return the '=' taken out above */
*(--value) = '=';
continue;
} else {
"property and can not be deleted.\n"),
argv[i]);
}
}
case INET_TYPE_INTEGER:
"integer value.\n"), value);
break;
case INET_TYPE_STRING:
"than %l characters.\n"), max_val);
== NULL) {
}
break;
case INET_TYPE_STRING_LIST:
"Error: Out of memory.\n"));
"Error: String value in "
"%s property longer than "
"%l characters.\n"),
} else {
"Error: No values "
"specified for %s "
"property.\n"),
}
}
break;
case INET_TYPE_BOOLEAN:
else
"boolean value. (TRUE or FALSE)\n"), value);
}
/* mark property for modification */
/* return the '=' taken out above */
*(--value) = '=';
}
if (smf_refresh_instance(fmri) != 0)
fmri);
return (0);
}
/*
* modify_defaults takes n name=value pairs for inetd default property values,
* parses them, and then modifies the values in the repository.
*/
static void
{
int i, j;
char *value;
scfdie();
if (scf_error() == SCF_ERROR_NOT_FOUND) {
"\n"));
} else {
scfdie();
}
}
scfdie();
for (i = 0; i < argc; i++) {
/* Separate argument into name and value pair */
"\"\n"), argv[i]);
*value = '\0';
value++;
/* Find property name in array of defaults */
if (!mod[j].ip_default)
continue;
break;
}
"property.\n"), argv[i]);
if (*value == '\0')
"properties.\n"));
case INET_TYPE_INTEGER:
"integer value.\n"), value);
break;
case INET_TYPE_STRING:
"than %l characters.\n"), max_val);
== NULL)
break;
case INET_TYPE_BOOLEAN:
else
"boolean value. (TRUE or FALSE)\n"), value);
}
/* mark property for modification */
}
if (refresh_inetd() != 0)
}
int
{
int opt;
int exit_status = 0;
(void) textdomain(TEXT_DOMAIN);
scfdie();
if (scf_handle_bind(h) == -1)
if (argc == 1) {
goto out;
}
switch (opt) {
case 'l':
lflag = 1;
break;
case 'e':
eflag = 1;
break;
case 'd':
dflag = 1;
break;
case 'p':
pflag = 1;
break;
case 'M':
Mflag = 1;
break;
case 'm':
mflag = 1;
break;
case '?':
if (optopt == '?') {
goto out;
} else {
}
default:
}
}
/*
* All options are mutually exclusive, and we must have an option
* if we reached here.
*/
serr = 0;
if (lflag) {
&exit_status, uu_warn);
} else if (dflag) {
enable = 0;
} else if (eflag) {
enable = 1;
} else if (mflag) {
/* count number of fmri arguments */
fmri_args++;
cpp++;
}
/* if no x=y args or no fmri, show usage */
/* setup args for modify_inst_props_cb */
} else if (Mflag) {
} else if (pflag) {
/* ensure there's no trailing garbage */
if (argc != 0)
}
if (serr != 0) {
scf_strerror(serr));
}
out:
(void) scf_handle_unbind(h);
return (exit_status);
}