/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (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
*/
/*
*/
/*
* Service Control Manager (SCM) for SVCCTL service.
*
* This routine maintains a list of SMF service and their states. A list
* of Solaris SMF service are displayed on the Server/Connection Manager
* Windows client.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <strings.h>
#include <assert.h>
#include <errno.h>
#include <libscf.h>
#include <libscf_priv.h>
#include <time.h>
#include <dlfcn.h>
#include <smbsrv/libmlsvc.h>
/* Flags for svcctl_scm_pg_get_val() */
static struct {
/*
* svcctl_scm_avl_nodecmp
*
* Comparision function for nodes in an AVL tree of services.
*/
/* ARGSUSED */
static int
{
const svcctl_svc_node_t *l = l_arg;
const svcctl_svc_node_t *r = r_arg;
int ret = 0;
if (ret > 0)
return (1);
if (ret < 0)
return (-1);
return (0);
}
/*
* svcctl_scm_pg_get_val
*
* Get the single value of the named property in the given property group,
* which must have type ty, and put it in *vp. If ty is SCF_TYPE_ASTRING, vp
* is taken to be a char **, and sz is the size of the buffer. sz is unused
* otherwise. Return 0 on success, -1 if the property doesn't exist, has the
* wrong type, or doesn't have a single value. If flags has EMPTY_OK, don't
* complain if the property has no values (but return nonzero). If flags has
* MULTI_OK and the property has multiple values, succeed with E2BIG.
*/
static int
{
return (ret);
return (ret);
switch (scf_error()) {
case SCF_ERROR_NOT_FOUND:
return (ret);
break;
}
return (ret);
default:
return (ret);
}
}
switch (ty) {
case SCF_TYPE_ASTRING:
break;
case SCF_TYPE_BOOLEAN:
break;
case SCF_TYPE_COUNT:
break;
case SCF_TYPE_INTEGER:
break;
case SCF_TYPE_TIME: {
break;
}
case SCF_TYPE_USTRING:
SCF_SUCCESS : -1;
break;
default:
return (ret);
}
if (r != SCF_SUCCESS)
return (ret);
return (ret);
}
/*
* svcctl_scm_get_running_snapshot
*
* Get running snapshot of a service instance.
*/
static scf_snapshot_t *
{
return (NULL);
return (snap);
if (scf_error() != SCF_ERROR_NOT_FOUND)
return (NULL);
return (NULL);
}
/*
* svcctl_scm_inst_get_val
*
* As svcctl_scm_pg_get_val(), except look the property group up in an
* instance. If "use_running" is set, and the running snapshot exists,
* do a composed lookup there. Otherwise, do an (optionally composed)
* lookup on the current values. Note that lookups using snapshots are
* always composed.
*/
static int
{
int r;
if (use_running)
if (composed || use_running)
else
if (snap)
if (r == -1)
return (-1);
return (r);
}
/*
* svcctl_scm_get_restarter_string_prop
*
* Get a string property from the restarter property group of the given
* instance. Return an empty string on normal problems.
*/
static void
{
*buf = '\0';
}
/*
* svcctl_scm_svc_transitioning
*
* Return true if a service instance is transitioning.
*/
static int
{
return ((*nstate_name == '\0'));
}
/*
* svcctl_scm_get_svcstate
*
* Gets the state of an SMF service.
*/
static int
{
char *state_name;
return (-1);
/* Don't print blank fields, to ease parsing. */
if (state_name[0] == '\0') {
state_name[0] = '-';
}
/* Append an asterisk if new state is valid. */
} else
*buf = state_name;
return (0);
}
/*
* svcctl_scm_get_svcdesc
*
* Gets the description of an SMF service.
*/
static int
{
char *x;
char *newbuf;
return (-1);
desc_buf[0] = '-';
desc_buf[0] = '-';
/*
* Collapse multi-line tm_common_name values into a single line.
*/
for (x = desc_buf; *x != '\0'; x++)
if (*x == '\n')
*x = ' ';
return (-1);
}
return (0);
}
/*
* svcctl_scm_get_svcfmri
*
* Gets the FMRI of an SMF service.
*/
static int
{
char *newbuf;
return (-1);
return (-1);
}
} else {
(sizeof (SCF_FMRI_LEGACY_PREFIX) - 1);
}
return (-1);
}
return (0);
}
/*
* svcctl_scm_get_svcname
*
* Gets the FMRI of an SMF service.
*/
static int
{
char *newbuf;
return (-1);
return (-1);
return (-1);
return (0);
}
/*
* svcctl_scm_cb_list_svcinst
*
* Callback function to walk all the services in an SCF repository.
*/
static int
{
return (-1);
return (-1);
return (-1);
return (-1);
return (-1);
/* Insert into AVL tree. */
return (0);
}
/*
* svcctl_scm_map_status
*
* Report the service status.
*
* The mapping between the Microsoft service states and SMF service states
* are as follows.
*
* SMF service states
* ==================
* SCF_STATE_UNINIT 0x00000001
* SCF_STATE_MAINT 0x00000002
* SCF_STATE_OFFLINE 0x00000004
* SCF_STATE_DISABLED 0x00000008
* SCF_STATE_ONLINE 0x00000010
* SCF_STATE_DEGRADED 0x00000020
* SCF_STATE_ALL 0x0000003F
*
* Microsoft service states
* ========================
* SERVICE_CONTINUE_PENDING 0x00000005
* SERVICE_PAUSE_PENDING 0x00000006
* SERVICE_PAUSED 0x00000007
* SERVICE_RUNNING 0x00000004
* SERVICE_START_PENDING 0x00000002
* SERVICE_STOP_PENDING 0x00000003
* SERVICE_STOPPED 0x00000001
*
* Mapping
* =======
*
* SCF_STATE_ONLINE <-> SERVICE_RUNNING
* SCF_STATE_OFFLINE <-> SERVICE_PAUSED
* SCF_STATE_DISABLED <-> SERVICE_STOPPED
* SCF_STATE_UNINIT <-> SERVICE_START_PENDING
* SCF_STATE_DEGRADED <-> SERVICE_STOP_PENDING
* SCF_STATE_MAINT <-> SERVICE_PAUSE_PENDING
* SCF_STATE_STRING_LEGACY <-> SERVICE_RUNNING
* Service Transitioning <-> SERVICE_STOP_PENDING
*/
{
int i;
struct {
const char *scf_state;
} state_map[] = {
};
}
return (SERVICE_STOP_PENDING);
return (SERVICE_RUNNING);
}
/*
* svcctl_scm_enum_services
*
* Enumerates SMF services: handles wide-char or ascii requests.
*
* Returns the number of services written to buf.
*/
{
char *a_name;
char *node_name;
/*LINTED E_BAD_PTR_CAST_ALIGN*/
*resume_handle = 0;
return (0);
}
--numsvcs;
}
}
*resume_handle = 0;
return (0);
}
if (use_wchar) {
/*LINTED E_BAD_PTR_CAST_ALIGN*/
} else {
}
if (offset <= base_offset)
break;
if (use_wchar) {
/*LINTED E_BAD_PTR_CAST_ALIGN*/
} else {
}
if (offset <= base_offset)
break;
}
*resume_handle = 0;
} else {
*resume_handle += ns;
*resume_handle = 0;
}
return (ns);
}
/*
* svcctl_scm_cb_bytes_needed
*
* Callback function to calculate bytes needed to enumerate SMF services.
*/
static int
{
return (UU_WALK_NEXT);
}
/*
* svcctl_scm_bytes_needed
*
* Calculates bytes needed to enumerate SMF services.
*/
static void
{
&bytes_needed, 0);
}
/*
* svcctl_scm_validate_service
*
* Check to see whether or not a service is supported.
*
* Returns:
* ERROR_SUCCESS
* ERROR_SERVICE_DOES_NOT_EXIST
*/
{
return (ERROR_SUCCESS);
return (ERROR_SERVICE_DOES_NOT_EXIST);
}
/*
* svcctl_scm_map_windows_svc
*
* Windows client send windows service name. This method maps windows
* service names to Solaris service names.
*/
static char *
{
int i, size = 0;
struct {
char *win_svc_name;
char *solaris_svc_name;
} win2solaris_svc_map[] = {
{ "eventlog", "system/system-log:default" },
{ "spooler", "application/print/ppd-cache-update:default" }
};
for (i = 0; i < size; ++i) {
if (strcasecmp(svc_name,
win2solaris_svc_map[i].win_svc_name) == 0)
return (win2solaris_svc_map[i].solaris_svc_name);
}
return (NULL);
}
/*
* svcctl_scm_find_service
*
* Lookup a service.
*/
{
return (NULL);
return (f_node);
return (f_node);
}
/*
* svcctl_scm_refresh
*
* Refresh SCM services per context.
*/
int
{
return (svcctl_scm_init(mgr_ctx));
}
/*
* svcctl_scm_scf_handle_init
*
* Initialize SCF handle per context.
*/
int
{
return (svcctl_scm_ops.
return (-1);
return (-1);
}
return (-1);
}
return (0);
}
/*
* svcctl_scm_scf_handle_init
*
* Destroy SCF handle per context.
*/
void
{
}
}
/*
* svcctl_scm_init
*
* Initialize SCM repository per context.
* SCM repository holds a list of SMF services.
* Each SMF service node contains state, description and FMRI.
*/
int
{
int exit_status = 0;
return (-1);
return (-1);
}
return (-1);
}
if (mgr_ctx->mc_scf_numsvcs > 0)
return (0);
}
/*
* svcctl_scm_fini
*
* Destroy SCM repository per context.
*/
void
{
return;
if ((walk =
return;
}
}
/*
* svcctl_init
*
* Initializes the SVCCTL service.
* Initializes handle and ops structure to interposed library.
*/
void
svcctl_init(void)
{
if (svcctl_scm_interposer_hdl == NULL)
return;
bzero((void *)&svcctl_scm_ops,
sizeof (svcctl_scm_ops));
(int (*)())dlsym(svcctl_scm_interposer_hdl,
"svcctl_scm_scf_handle_init");
svcctl_fini();
}
/*
* svcctl_fini
*
* Finalizes the SVCCTL service.
* Closes handle to interposed library.
*/
void
svcctl_fini(void)
{
bzero((void *)&svcctl_scm_ops,
sizeof (svcctl_scm_ops));
}