1*7961SNatalie.Li@Sun.COM /* 2*7961SNatalie.Li@Sun.COM * CDDL HEADER START 3*7961SNatalie.Li@Sun.COM * 4*7961SNatalie.Li@Sun.COM * The contents of this file are subject to the terms of the 5*7961SNatalie.Li@Sun.COM * Common Development and Distribution License (the "License"). 6*7961SNatalie.Li@Sun.COM * You may not use this file except in compliance with the License. 7*7961SNatalie.Li@Sun.COM * 8*7961SNatalie.Li@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*7961SNatalie.Li@Sun.COM * or http://www.opensolaris.org/os/licensing. 10*7961SNatalie.Li@Sun.COM * See the License for the specific language governing permissions 11*7961SNatalie.Li@Sun.COM * and limitations under the License. 12*7961SNatalie.Li@Sun.COM * 13*7961SNatalie.Li@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each 14*7961SNatalie.Li@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*7961SNatalie.Li@Sun.COM * If applicable, add the following below this CDDL HEADER, with the 16*7961SNatalie.Li@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying 17*7961SNatalie.Li@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner] 18*7961SNatalie.Li@Sun.COM * 19*7961SNatalie.Li@Sun.COM * CDDL HEADER END 20*7961SNatalie.Li@Sun.COM */ 21*7961SNatalie.Li@Sun.COM /* 22*7961SNatalie.Li@Sun.COM * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23*7961SNatalie.Li@Sun.COM * Use is subject to license terms. 24*7961SNatalie.Li@Sun.COM */ 25*7961SNatalie.Li@Sun.COM 26*7961SNatalie.Li@Sun.COM /* 27*7961SNatalie.Li@Sun.COM * Service Control Manager (SCM) for SVCCTL service. 28*7961SNatalie.Li@Sun.COM * 29*7961SNatalie.Li@Sun.COM * This routine maintains a list of SMF service and their states. A list 30*7961SNatalie.Li@Sun.COM * of Solaris SMF service are displayed on the Server/Connection Manager 31*7961SNatalie.Li@Sun.COM * Windows client. 32*7961SNatalie.Li@Sun.COM */ 33*7961SNatalie.Li@Sun.COM 34*7961SNatalie.Li@Sun.COM #include <stdio.h> 35*7961SNatalie.Li@Sun.COM #include <stdlib.h> 36*7961SNatalie.Li@Sun.COM #include <stdarg.h> 37*7961SNatalie.Li@Sun.COM #include <strings.h> 38*7961SNatalie.Li@Sun.COM #include <assert.h> 39*7961SNatalie.Li@Sun.COM #include <errno.h> 40*7961SNatalie.Li@Sun.COM #include <libscf.h> 41*7961SNatalie.Li@Sun.COM #include <libscf_priv.h> 42*7961SNatalie.Li@Sun.COM #include <time.h> 43*7961SNatalie.Li@Sun.COM #include <sys/types.h> 44*7961SNatalie.Li@Sun.COM 45*7961SNatalie.Li@Sun.COM #include "svcctl_scm.h" 46*7961SNatalie.Li@Sun.COM 47*7961SNatalie.Li@Sun.COM #define LEGACY_UNKNOWN "unknown" 48*7961SNatalie.Li@Sun.COM #define SVC_NAME_PROP "name" 49*7961SNatalie.Li@Sun.COM 50*7961SNatalie.Li@Sun.COM /* Flags for svcctl_scm_pg_get_val() */ 51*7961SNatalie.Li@Sun.COM #define EMPTY_OK 0x01 52*7961SNatalie.Li@Sun.COM #define MULTI_OK 0x02 53*7961SNatalie.Li@Sun.COM 54*7961SNatalie.Li@Sun.COM /* 55*7961SNatalie.Li@Sun.COM * svcctl_scm_avl_nodecmp 56*7961SNatalie.Li@Sun.COM * 57*7961SNatalie.Li@Sun.COM * Comparision function for nodes in an AVL tree of services. 58*7961SNatalie.Li@Sun.COM */ 59*7961SNatalie.Li@Sun.COM /* ARGSUSED */ 60*7961SNatalie.Li@Sun.COM static int 61*7961SNatalie.Li@Sun.COM svcctl_scm_avl_nodecmp(const void *l_arg, const void *r_arg, void *m_name_len) 62*7961SNatalie.Li@Sun.COM { 63*7961SNatalie.Li@Sun.COM const svcctl_svc_node_t *l = l_arg; 64*7961SNatalie.Li@Sun.COM const svcctl_svc_node_t *r = r_arg; 65*7961SNatalie.Li@Sun.COM int *max_name_len = m_name_len; 66*7961SNatalie.Li@Sun.COM int ret = 0; 67*7961SNatalie.Li@Sun.COM 68*7961SNatalie.Li@Sun.COM ret = strncasecmp(l->sn_name, r->sn_name, *max_name_len); 69*7961SNatalie.Li@Sun.COM 70*7961SNatalie.Li@Sun.COM if (ret > 0) 71*7961SNatalie.Li@Sun.COM return (1); 72*7961SNatalie.Li@Sun.COM if (ret < 0) 73*7961SNatalie.Li@Sun.COM return (-1); 74*7961SNatalie.Li@Sun.COM return (0); 75*7961SNatalie.Li@Sun.COM } 76*7961SNatalie.Li@Sun.COM 77*7961SNatalie.Li@Sun.COM /* 78*7961SNatalie.Li@Sun.COM * svcctl_scm_pg_get_val 79*7961SNatalie.Li@Sun.COM * 80*7961SNatalie.Li@Sun.COM * Get the single value of the named property in the given property group, 81*7961SNatalie.Li@Sun.COM * which must have type ty, and put it in *vp. If ty is SCF_TYPE_ASTRING, vp 82*7961SNatalie.Li@Sun.COM * is taken to be a char **, and sz is the size of the buffer. sz is unused 83*7961SNatalie.Li@Sun.COM * otherwise. Return 0 on success, -1 if the property doesn't exist, has the 84*7961SNatalie.Li@Sun.COM * wrong type, or doesn't have a single value. If flags has EMPTY_OK, don't 85*7961SNatalie.Li@Sun.COM * complain if the property has no values (but return nonzero). If flags has 86*7961SNatalie.Li@Sun.COM * MULTI_OK and the property has multiple values, succeed with E2BIG. 87*7961SNatalie.Li@Sun.COM */ 88*7961SNatalie.Li@Sun.COM static int 89*7961SNatalie.Li@Sun.COM svcctl_scm_pg_get_val(svcctl_manager_context_t *mgr_ctx, 90*7961SNatalie.Li@Sun.COM scf_propertygroup_t *pg, const char *propname, scf_type_t ty, void *vp, 91*7961SNatalie.Li@Sun.COM size_t sz, uint_t flags) 92*7961SNatalie.Li@Sun.COM { 93*7961SNatalie.Li@Sun.COM int ret = -1, r; 94*7961SNatalie.Li@Sun.COM boolean_t multi = B_FALSE; 95*7961SNatalie.Li@Sun.COM 96*7961SNatalie.Li@Sun.COM assert((flags & ~(EMPTY_OK | MULTI_OK)) == 0); 97*7961SNatalie.Li@Sun.COM 98*7961SNatalie.Li@Sun.COM if (scf_pg_get_property(pg, propname, mgr_ctx->mc_scf_gprop) == -1) 99*7961SNatalie.Li@Sun.COM return (ret); 100*7961SNatalie.Li@Sun.COM 101*7961SNatalie.Li@Sun.COM if (scf_property_is_type(mgr_ctx->mc_scf_gprop, ty) != SCF_SUCCESS) 102*7961SNatalie.Li@Sun.COM return (ret); 103*7961SNatalie.Li@Sun.COM 104*7961SNatalie.Li@Sun.COM if (scf_property_get_value(mgr_ctx->mc_scf_gprop, 105*7961SNatalie.Li@Sun.COM mgr_ctx->mc_scf_gval) != SCF_SUCCESS) { 106*7961SNatalie.Li@Sun.COM switch (scf_error()) { 107*7961SNatalie.Li@Sun.COM case SCF_ERROR_NOT_FOUND: 108*7961SNatalie.Li@Sun.COM return (ret); 109*7961SNatalie.Li@Sun.COM 110*7961SNatalie.Li@Sun.COM case SCF_ERROR_CONSTRAINT_VIOLATED: 111*7961SNatalie.Li@Sun.COM if (flags & MULTI_OK) { 112*7961SNatalie.Li@Sun.COM multi = B_TRUE; 113*7961SNatalie.Li@Sun.COM break; 114*7961SNatalie.Li@Sun.COM } 115*7961SNatalie.Li@Sun.COM return (ret); 116*7961SNatalie.Li@Sun.COM 117*7961SNatalie.Li@Sun.COM case SCF_ERROR_PERMISSION_DENIED: 118*7961SNatalie.Li@Sun.COM default: 119*7961SNatalie.Li@Sun.COM return (ret); 120*7961SNatalie.Li@Sun.COM } 121*7961SNatalie.Li@Sun.COM } 122*7961SNatalie.Li@Sun.COM 123*7961SNatalie.Li@Sun.COM switch (ty) { 124*7961SNatalie.Li@Sun.COM case SCF_TYPE_ASTRING: 125*7961SNatalie.Li@Sun.COM r = scf_value_get_astring 126*7961SNatalie.Li@Sun.COM (mgr_ctx->mc_scf_gval, vp, sz) > 0 ? SCF_SUCCESS : -1; 127*7961SNatalie.Li@Sun.COM break; 128*7961SNatalie.Li@Sun.COM 129*7961SNatalie.Li@Sun.COM case SCF_TYPE_BOOLEAN: 130*7961SNatalie.Li@Sun.COM r = scf_value_get_boolean(mgr_ctx->mc_scf_gval, (uint8_t *)vp); 131*7961SNatalie.Li@Sun.COM break; 132*7961SNatalie.Li@Sun.COM 133*7961SNatalie.Li@Sun.COM case SCF_TYPE_COUNT: 134*7961SNatalie.Li@Sun.COM r = scf_value_get_count(mgr_ctx->mc_scf_gval, (uint64_t *)vp); 135*7961SNatalie.Li@Sun.COM break; 136*7961SNatalie.Li@Sun.COM 137*7961SNatalie.Li@Sun.COM case SCF_TYPE_INTEGER: 138*7961SNatalie.Li@Sun.COM r = scf_value_get_integer(mgr_ctx->mc_scf_gval, (int64_t *)vp); 139*7961SNatalie.Li@Sun.COM break; 140*7961SNatalie.Li@Sun.COM 141*7961SNatalie.Li@Sun.COM case SCF_TYPE_TIME: { 142*7961SNatalie.Li@Sun.COM int64_t sec; 143*7961SNatalie.Li@Sun.COM int32_t ns; 144*7961SNatalie.Li@Sun.COM r = scf_value_get_time(mgr_ctx->mc_scf_gval, &sec, &ns); 145*7961SNatalie.Li@Sun.COM ((struct timeval *)vp)->tv_sec = sec; 146*7961SNatalie.Li@Sun.COM ((struct timeval *)vp)->tv_usec = ns / 1000; 147*7961SNatalie.Li@Sun.COM break; 148*7961SNatalie.Li@Sun.COM } 149*7961SNatalie.Li@Sun.COM 150*7961SNatalie.Li@Sun.COM case SCF_TYPE_USTRING: 151*7961SNatalie.Li@Sun.COM r = scf_value_get_ustring(mgr_ctx->mc_scf_gval, vp, sz) > 0 ? 152*7961SNatalie.Li@Sun.COM SCF_SUCCESS : -1; 153*7961SNatalie.Li@Sun.COM break; 154*7961SNatalie.Li@Sun.COM 155*7961SNatalie.Li@Sun.COM default: 156*7961SNatalie.Li@Sun.COM return (ret); 157*7961SNatalie.Li@Sun.COM } 158*7961SNatalie.Li@Sun.COM 159*7961SNatalie.Li@Sun.COM if (r != SCF_SUCCESS) 160*7961SNatalie.Li@Sun.COM return (ret); 161*7961SNatalie.Li@Sun.COM 162*7961SNatalie.Li@Sun.COM ret = multi ? E2BIG : 0; 163*7961SNatalie.Li@Sun.COM 164*7961SNatalie.Li@Sun.COM return (ret); 165*7961SNatalie.Li@Sun.COM } 166*7961SNatalie.Li@Sun.COM 167*7961SNatalie.Li@Sun.COM /* 168*7961SNatalie.Li@Sun.COM * svcctl_scm_get_running_snapshot 169*7961SNatalie.Li@Sun.COM * 170*7961SNatalie.Li@Sun.COM * Get running snapshot of a service instance. 171*7961SNatalie.Li@Sun.COM */ 172*7961SNatalie.Li@Sun.COM static scf_snapshot_t * 173*7961SNatalie.Li@Sun.COM svcctl_scm_get_running_snapshot(svcctl_manager_context_t *mgr_ctx, 174*7961SNatalie.Li@Sun.COM scf_instance_t *inst) 175*7961SNatalie.Li@Sun.COM { 176*7961SNatalie.Li@Sun.COM scf_snapshot_t *snap; 177*7961SNatalie.Li@Sun.COM 178*7961SNatalie.Li@Sun.COM snap = scf_snapshot_create(mgr_ctx->mc_scf_hdl); 179*7961SNatalie.Li@Sun.COM if (snap == NULL) 180*7961SNatalie.Li@Sun.COM return (NULL); 181*7961SNatalie.Li@Sun.COM 182*7961SNatalie.Li@Sun.COM if (scf_instance_get_snapshot(inst, "running", snap) == 0) 183*7961SNatalie.Li@Sun.COM return (snap); 184*7961SNatalie.Li@Sun.COM 185*7961SNatalie.Li@Sun.COM if (scf_error() != SCF_ERROR_NOT_FOUND) 186*7961SNatalie.Li@Sun.COM return (NULL); 187*7961SNatalie.Li@Sun.COM 188*7961SNatalie.Li@Sun.COM scf_snapshot_destroy(snap); 189*7961SNatalie.Li@Sun.COM return (NULL); 190*7961SNatalie.Li@Sun.COM } 191*7961SNatalie.Li@Sun.COM 192*7961SNatalie.Li@Sun.COM /* 193*7961SNatalie.Li@Sun.COM * svcctl_scm_inst_get_val 194*7961SNatalie.Li@Sun.COM * 195*7961SNatalie.Li@Sun.COM * As svcctl_scm_pg_get_val(), except look the property group up in an 196*7961SNatalie.Li@Sun.COM * instance. If "use_running" is set, and the running snapshot exists, 197*7961SNatalie.Li@Sun.COM * do a composed lookup there. Otherwise, do an (optionally composed) 198*7961SNatalie.Li@Sun.COM * lookup on the current values. Note that lookups using snapshots are 199*7961SNatalie.Li@Sun.COM * always composed. 200*7961SNatalie.Li@Sun.COM */ 201*7961SNatalie.Li@Sun.COM static int 202*7961SNatalie.Li@Sun.COM svcctl_scm_inst_get_val(svcctl_manager_context_t *mgr_ctx, scf_instance_t *inst, 203*7961SNatalie.Li@Sun.COM const char *pgname, const char *propname, scf_type_t ty, void *vp, 204*7961SNatalie.Li@Sun.COM size_t sz, uint_t flags, int use_running, int composed) 205*7961SNatalie.Li@Sun.COM { 206*7961SNatalie.Li@Sun.COM scf_snapshot_t *snap = NULL; 207*7961SNatalie.Li@Sun.COM int r; 208*7961SNatalie.Li@Sun.COM 209*7961SNatalie.Li@Sun.COM if (use_running) 210*7961SNatalie.Li@Sun.COM snap = svcctl_scm_get_running_snapshot(mgr_ctx, inst); 211*7961SNatalie.Li@Sun.COM if (composed || use_running) 212*7961SNatalie.Li@Sun.COM r = scf_instance_get_pg_composed(inst, snap, pgname, 213*7961SNatalie.Li@Sun.COM mgr_ctx->mc_scf_gpg); 214*7961SNatalie.Li@Sun.COM else 215*7961SNatalie.Li@Sun.COM r = scf_instance_get_pg(inst, pgname, mgr_ctx->mc_scf_gpg); 216*7961SNatalie.Li@Sun.COM if (snap) 217*7961SNatalie.Li@Sun.COM scf_snapshot_destroy(snap); 218*7961SNatalie.Li@Sun.COM if (r == -1) 219*7961SNatalie.Li@Sun.COM return (-1); 220*7961SNatalie.Li@Sun.COM 221*7961SNatalie.Li@Sun.COM r = svcctl_scm_pg_get_val(mgr_ctx, mgr_ctx->mc_scf_gpg, propname, ty, 222*7961SNatalie.Li@Sun.COM vp, sz, flags); 223*7961SNatalie.Li@Sun.COM 224*7961SNatalie.Li@Sun.COM return (r); 225*7961SNatalie.Li@Sun.COM } 226*7961SNatalie.Li@Sun.COM 227*7961SNatalie.Li@Sun.COM /* 228*7961SNatalie.Li@Sun.COM * svcctl_scm_get_restarter_string_prop 229*7961SNatalie.Li@Sun.COM * 230*7961SNatalie.Li@Sun.COM * Get a string property from the restarter property group of the given 231*7961SNatalie.Li@Sun.COM * instance. Return an empty string on normal problems. 232*7961SNatalie.Li@Sun.COM */ 233*7961SNatalie.Li@Sun.COM static void 234*7961SNatalie.Li@Sun.COM svcctl_scm_get_restarter_string_prop(svcctl_manager_context_t *mgr_ctx, 235*7961SNatalie.Li@Sun.COM scf_instance_t *inst, const char *pname, char *buf, size_t buf_sz) 236*7961SNatalie.Li@Sun.COM { 237*7961SNatalie.Li@Sun.COM if (svcctl_scm_inst_get_val(mgr_ctx, inst, SCF_PG_RESTARTER, pname, 238*7961SNatalie.Li@Sun.COM SCF_TYPE_ASTRING, buf, buf_sz, 0, 0, 1) != 0) 239*7961SNatalie.Li@Sun.COM *buf = '\0'; 240*7961SNatalie.Li@Sun.COM } 241*7961SNatalie.Li@Sun.COM 242*7961SNatalie.Li@Sun.COM /* 243*7961SNatalie.Li@Sun.COM * svcctl_scm_svc_transitioning 244*7961SNatalie.Li@Sun.COM * 245*7961SNatalie.Li@Sun.COM * Return true if a service instance is transitioning. 246*7961SNatalie.Li@Sun.COM */ 247*7961SNatalie.Li@Sun.COM static int 248*7961SNatalie.Li@Sun.COM svcctl_scm_svc_transitioning(svcctl_manager_context_t *mgr_ctx, 249*7961SNatalie.Li@Sun.COM scf_instance_t *inst) 250*7961SNatalie.Li@Sun.COM { 251*7961SNatalie.Li@Sun.COM char nstate_name[MAX_SCF_STATE_STRING_SZ]; 252*7961SNatalie.Li@Sun.COM 253*7961SNatalie.Li@Sun.COM bzero(nstate_name, MAX_SCF_STATE_STRING_SZ); 254*7961SNatalie.Li@Sun.COM svcctl_scm_get_restarter_string_prop(mgr_ctx, inst, 255*7961SNatalie.Li@Sun.COM SCF_PROPERTY_NEXT_STATE, nstate_name, sizeof (nstate_name)); 256*7961SNatalie.Li@Sun.COM 257*7961SNatalie.Li@Sun.COM return ((*nstate_name == '\0')); 258*7961SNatalie.Li@Sun.COM } 259*7961SNatalie.Li@Sun.COM 260*7961SNatalie.Li@Sun.COM /* 261*7961SNatalie.Li@Sun.COM * svcctl_scm_get_svcstate 262*7961SNatalie.Li@Sun.COM * 263*7961SNatalie.Li@Sun.COM * Gets the state of an SMF service. 264*7961SNatalie.Li@Sun.COM */ 265*7961SNatalie.Li@Sun.COM static int 266*7961SNatalie.Li@Sun.COM svcctl_scm_get_svcstate(svcctl_manager_context_t *mgr_ctx, 267*7961SNatalie.Li@Sun.COM char **buf, scf_walkinfo_t *wip) 268*7961SNatalie.Li@Sun.COM { 269*7961SNatalie.Li@Sun.COM char *state_name; 270*7961SNatalie.Li@Sun.COM size_t max_state_size; 271*7961SNatalie.Li@Sun.COM 272*7961SNatalie.Li@Sun.COM max_state_size = MAX_SCF_STATE_STRING_SZ + 1; 273*7961SNatalie.Li@Sun.COM 274*7961SNatalie.Li@Sun.COM if ((state_name = malloc(max_state_size)) == NULL) 275*7961SNatalie.Li@Sun.COM return (-1); 276*7961SNatalie.Li@Sun.COM 277*7961SNatalie.Li@Sun.COM if (wip->pg == NULL) { 278*7961SNatalie.Li@Sun.COM svcctl_scm_get_restarter_string_prop(mgr_ctx, wip->inst, 279*7961SNatalie.Li@Sun.COM SCF_PROPERTY_STATE, state_name, max_state_size); 280*7961SNatalie.Li@Sun.COM 281*7961SNatalie.Li@Sun.COM /* Don't print blank fields, to ease parsing. */ 282*7961SNatalie.Li@Sun.COM if (state_name[0] == '\0') { 283*7961SNatalie.Li@Sun.COM state_name[0] = '-'; 284*7961SNatalie.Li@Sun.COM state_name[1] = '\0'; 285*7961SNatalie.Li@Sun.COM } 286*7961SNatalie.Li@Sun.COM 287*7961SNatalie.Li@Sun.COM if (svcctl_scm_svc_transitioning(mgr_ctx, wip->inst)) 288*7961SNatalie.Li@Sun.COM /* Append an asterisk if new state is valid. */ 289*7961SNatalie.Li@Sun.COM (void) strlcat(state_name, "*", max_state_size); 290*7961SNatalie.Li@Sun.COM 291*7961SNatalie.Li@Sun.COM } else 292*7961SNatalie.Li@Sun.COM (void) strlcpy(state_name, SCF_STATE_STRING_LEGACY, 293*7961SNatalie.Li@Sun.COM max_state_size); 294*7961SNatalie.Li@Sun.COM 295*7961SNatalie.Li@Sun.COM *buf = state_name; 296*7961SNatalie.Li@Sun.COM return (0); 297*7961SNatalie.Li@Sun.COM } 298*7961SNatalie.Li@Sun.COM 299*7961SNatalie.Li@Sun.COM /* 300*7961SNatalie.Li@Sun.COM * svcctl_scm_get_svcdesc 301*7961SNatalie.Li@Sun.COM * 302*7961SNatalie.Li@Sun.COM * Gets the description of an SMF service. 303*7961SNatalie.Li@Sun.COM */ 304*7961SNatalie.Li@Sun.COM static int 305*7961SNatalie.Li@Sun.COM svcctl_scm_get_svcdesc(svcctl_manager_context_t *mgr_ctx, 306*7961SNatalie.Li@Sun.COM char **buf, scf_walkinfo_t *wip) 307*7961SNatalie.Li@Sun.COM { 308*7961SNatalie.Li@Sun.COM char *x; 309*7961SNatalie.Li@Sun.COM size_t newsize; 310*7961SNatalie.Li@Sun.COM char *newbuf; 311*7961SNatalie.Li@Sun.COM char *desc_buf = NULL; 312*7961SNatalie.Li@Sun.COM 313*7961SNatalie.Li@Sun.COM if ((desc_buf = malloc(mgr_ctx->mc_scf_max_value_len + 1)) == NULL) 314*7961SNatalie.Li@Sun.COM return (-1); 315*7961SNatalie.Li@Sun.COM 316*7961SNatalie.Li@Sun.COM bzero(desc_buf, mgr_ctx->mc_scf_max_value_len + 1); 317*7961SNatalie.Li@Sun.COM if (wip->pg != NULL) 318*7961SNatalie.Li@Sun.COM desc_buf[0] = '-'; 319*7961SNatalie.Li@Sun.COM else if (svcctl_scm_inst_get_val(mgr_ctx, wip->inst, 320*7961SNatalie.Li@Sun.COM SCF_PG_TM_COMMON_NAME, "C", SCF_TYPE_USTRING, desc_buf, 321*7961SNatalie.Li@Sun.COM mgr_ctx->mc_scf_max_value_len, 0, 1, 1) == -1) 322*7961SNatalie.Li@Sun.COM desc_buf[0] = '-'; 323*7961SNatalie.Li@Sun.COM 324*7961SNatalie.Li@Sun.COM /* 325*7961SNatalie.Li@Sun.COM * Collapse multi-line tm_common_name values into a single line. 326*7961SNatalie.Li@Sun.COM */ 327*7961SNatalie.Li@Sun.COM for (x = desc_buf; *x != '\0'; x++) 328*7961SNatalie.Li@Sun.COM if (*x == '\n') 329*7961SNatalie.Li@Sun.COM *x = ' '; 330*7961SNatalie.Li@Sun.COM 331*7961SNatalie.Li@Sun.COM newsize = strlen(desc_buf) + 1; 332*7961SNatalie.Li@Sun.COM if ((newbuf = malloc(newsize)) == NULL) { 333*7961SNatalie.Li@Sun.COM free(desc_buf); 334*7961SNatalie.Li@Sun.COM return (-1); 335*7961SNatalie.Li@Sun.COM } 336*7961SNatalie.Li@Sun.COM 337*7961SNatalie.Li@Sun.COM (void) snprintf(newbuf, newsize, "%s", desc_buf); 338*7961SNatalie.Li@Sun.COM free(desc_buf); 339*7961SNatalie.Li@Sun.COM 340*7961SNatalie.Li@Sun.COM *buf = newbuf; 341*7961SNatalie.Li@Sun.COM return (0); 342*7961SNatalie.Li@Sun.COM } 343*7961SNatalie.Li@Sun.COM 344*7961SNatalie.Li@Sun.COM /* 345*7961SNatalie.Li@Sun.COM * svcctl_scm_get_svcfmri 346*7961SNatalie.Li@Sun.COM * 347*7961SNatalie.Li@Sun.COM * Gets the FMRI of an SMF service. 348*7961SNatalie.Li@Sun.COM */ 349*7961SNatalie.Li@Sun.COM static int 350*7961SNatalie.Li@Sun.COM svcctl_scm_get_svcfmri(svcctl_manager_context_t *mgr_ctx, 351*7961SNatalie.Li@Sun.COM char **buf, scf_walkinfo_t *wip) 352*7961SNatalie.Li@Sun.COM { 353*7961SNatalie.Li@Sun.COM size_t newsize; 354*7961SNatalie.Li@Sun.COM char *newbuf; 355*7961SNatalie.Li@Sun.COM char *fmri_buf = NULL; 356*7961SNatalie.Li@Sun.COM void *fmri_p = NULL; 357*7961SNatalie.Li@Sun.COM size_t fmri_size; 358*7961SNatalie.Li@Sun.COM 359*7961SNatalie.Li@Sun.COM if ((fmri_buf = malloc(mgr_ctx->mc_scf_max_fmri_len + 1)) == NULL) 360*7961SNatalie.Li@Sun.COM return (-1); 361*7961SNatalie.Li@Sun.COM 362*7961SNatalie.Li@Sun.COM if (wip->pg == NULL) { 363*7961SNatalie.Li@Sun.COM if (scf_instance_to_fmri(wip->inst, fmri_buf, 364*7961SNatalie.Li@Sun.COM mgr_ctx->mc_scf_max_fmri_len + 1) == -1) { 365*7961SNatalie.Li@Sun.COM free(fmri_buf); 366*7961SNatalie.Li@Sun.COM return (-1); 367*7961SNatalie.Li@Sun.COM } 368*7961SNatalie.Li@Sun.COM } else { 369*7961SNatalie.Li@Sun.COM (void) strlcpy(fmri_buf, SCF_FMRI_LEGACY_PREFIX, 370*7961SNatalie.Li@Sun.COM mgr_ctx->mc_scf_max_fmri_len + 1); 371*7961SNatalie.Li@Sun.COM 372*7961SNatalie.Li@Sun.COM fmri_p = fmri_buf + sizeof (SCF_FMRI_LEGACY_PREFIX) - 1; 373*7961SNatalie.Li@Sun.COM fmri_size = mgr_ctx->mc_scf_max_fmri_len + 1 - \ 374*7961SNatalie.Li@Sun.COM (sizeof (SCF_FMRI_LEGACY_PREFIX) - 1); 375*7961SNatalie.Li@Sun.COM 376*7961SNatalie.Li@Sun.COM if (svcctl_scm_pg_get_val(mgr_ctx, wip->pg, 377*7961SNatalie.Li@Sun.COM SCF_LEGACY_PROPERTY_NAME, SCF_TYPE_ASTRING, 378*7961SNatalie.Li@Sun.COM fmri_p, fmri_size, 0) != 0) 379*7961SNatalie.Li@Sun.COM (void) strlcat(fmri_buf, LEGACY_UNKNOWN, 380*7961SNatalie.Li@Sun.COM mgr_ctx->mc_scf_max_fmri_len + 1); 381*7961SNatalie.Li@Sun.COM } 382*7961SNatalie.Li@Sun.COM 383*7961SNatalie.Li@Sun.COM newsize = strlen(fmri_buf) + 1; 384*7961SNatalie.Li@Sun.COM if ((newbuf = malloc(newsize)) == NULL) { 385*7961SNatalie.Li@Sun.COM free(fmri_buf); 386*7961SNatalie.Li@Sun.COM return (-1); 387*7961SNatalie.Li@Sun.COM } 388*7961SNatalie.Li@Sun.COM 389*7961SNatalie.Li@Sun.COM (void) snprintf(newbuf, newsize, "%s", fmri_buf); 390*7961SNatalie.Li@Sun.COM free(fmri_buf); 391*7961SNatalie.Li@Sun.COM 392*7961SNatalie.Li@Sun.COM *buf = newbuf; 393*7961SNatalie.Li@Sun.COM return (0); 394*7961SNatalie.Li@Sun.COM } 395*7961SNatalie.Li@Sun.COM 396*7961SNatalie.Li@Sun.COM /* 397*7961SNatalie.Li@Sun.COM * svcctl_scm_get_svcname 398*7961SNatalie.Li@Sun.COM * 399*7961SNatalie.Li@Sun.COM * Gets the FMRI of an SMF service. 400*7961SNatalie.Li@Sun.COM */ 401*7961SNatalie.Li@Sun.COM static int 402*7961SNatalie.Li@Sun.COM svcctl_scm_get_svcname(char **buf, char *fmri) 403*7961SNatalie.Li@Sun.COM { 404*7961SNatalie.Li@Sun.COM char *nm_buf = NULL; 405*7961SNatalie.Li@Sun.COM char *newbuf; 406*7961SNatalie.Li@Sun.COM size_t newsize; 407*7961SNatalie.Li@Sun.COM 408*7961SNatalie.Li@Sun.COM if (fmri == NULL) 409*7961SNatalie.Li@Sun.COM return (-1); 410*7961SNatalie.Li@Sun.COM 411*7961SNatalie.Li@Sun.COM newsize = strlen(fmri); 412*7961SNatalie.Li@Sun.COM if ((newbuf = malloc(newsize)) == NULL) 413*7961SNatalie.Li@Sun.COM return (-1); 414*7961SNatalie.Li@Sun.COM 415*7961SNatalie.Li@Sun.COM if ((nm_buf = strchr(fmri, '/')) == NULL) 416*7961SNatalie.Li@Sun.COM return (-1); 417*7961SNatalie.Li@Sun.COM 418*7961SNatalie.Li@Sun.COM (void) snprintf(newbuf, newsize, "%s", ++nm_buf); 419*7961SNatalie.Li@Sun.COM *buf = newbuf; 420*7961SNatalie.Li@Sun.COM return (0); 421*7961SNatalie.Li@Sun.COM } 422*7961SNatalie.Li@Sun.COM 423*7961SNatalie.Li@Sun.COM /* 424*7961SNatalie.Li@Sun.COM * svcctl_scm_cb_list_svcinst 425*7961SNatalie.Li@Sun.COM * 426*7961SNatalie.Li@Sun.COM * Callback function to walk all the services in an SCF repository. 427*7961SNatalie.Li@Sun.COM */ 428*7961SNatalie.Li@Sun.COM static int 429*7961SNatalie.Li@Sun.COM svcctl_scm_cb_list_svcinst(void *context, scf_walkinfo_t *wip) 430*7961SNatalie.Li@Sun.COM { 431*7961SNatalie.Li@Sun.COM svcctl_svc_node_t *node = NULL; 432*7961SNatalie.Li@Sun.COM uu_avl_index_t idx; 433*7961SNatalie.Li@Sun.COM svcctl_manager_context_t *mgr_ctx = (svcctl_manager_context_t *)context; 434*7961SNatalie.Li@Sun.COM 435*7961SNatalie.Li@Sun.COM node = malloc(sizeof (*node)); 436*7961SNatalie.Li@Sun.COM if (node == NULL) 437*7961SNatalie.Li@Sun.COM return (-1); 438*7961SNatalie.Li@Sun.COM 439*7961SNatalie.Li@Sun.COM node->sn_fmri = NULL; 440*7961SNatalie.Li@Sun.COM if (svcctl_scm_get_svcfmri(mgr_ctx, &node->sn_fmri, wip) != 0) 441*7961SNatalie.Li@Sun.COM return (-1); 442*7961SNatalie.Li@Sun.COM 443*7961SNatalie.Li@Sun.COM node->sn_name = NULL; 444*7961SNatalie.Li@Sun.COM if (svcctl_scm_get_svcname(&node->sn_name, node->sn_fmri) != 0) 445*7961SNatalie.Li@Sun.COM return (-1); 446*7961SNatalie.Li@Sun.COM 447*7961SNatalie.Li@Sun.COM node->sn_desc = NULL; 448*7961SNatalie.Li@Sun.COM if (svcctl_scm_get_svcdesc(mgr_ctx, &node->sn_desc, wip) != 0) 449*7961SNatalie.Li@Sun.COM return (-1); 450*7961SNatalie.Li@Sun.COM 451*7961SNatalie.Li@Sun.COM node->sn_state = NULL; 452*7961SNatalie.Li@Sun.COM if (svcctl_scm_get_svcstate(mgr_ctx, &node->sn_state, wip) != 0) 453*7961SNatalie.Li@Sun.COM return (-1); 454*7961SNatalie.Li@Sun.COM 455*7961SNatalie.Li@Sun.COM /* Insert into AVL tree. */ 456*7961SNatalie.Li@Sun.COM uu_avl_node_init(node, &node->sn_node, mgr_ctx->mc_svcs_pool); 457*7961SNatalie.Li@Sun.COM (void) uu_avl_find(mgr_ctx->mc_svcs, node, 458*7961SNatalie.Li@Sun.COM &mgr_ctx->mc_scf_max_fmri_len, &idx); 459*7961SNatalie.Li@Sun.COM uu_avl_insert(mgr_ctx->mc_svcs, node, idx); 460*7961SNatalie.Li@Sun.COM 461*7961SNatalie.Li@Sun.COM return (0); 462*7961SNatalie.Li@Sun.COM } 463*7961SNatalie.Li@Sun.COM 464*7961SNatalie.Li@Sun.COM /* 465*7961SNatalie.Li@Sun.COM * svcctl_scm_map_status 466*7961SNatalie.Li@Sun.COM * 467*7961SNatalie.Li@Sun.COM * Report the service status. 468*7961SNatalie.Li@Sun.COM * 469*7961SNatalie.Li@Sun.COM * The mapping between the Microsoft service states and SMF service states 470*7961SNatalie.Li@Sun.COM * are as follows. 471*7961SNatalie.Li@Sun.COM * 472*7961SNatalie.Li@Sun.COM * SMF service states 473*7961SNatalie.Li@Sun.COM * ================== 474*7961SNatalie.Li@Sun.COM * SCF_STATE_UNINIT 0x00000001 475*7961SNatalie.Li@Sun.COM * SCF_STATE_MAINT 0x00000002 476*7961SNatalie.Li@Sun.COM * SCF_STATE_OFFLINE 0x00000004 477*7961SNatalie.Li@Sun.COM * SCF_STATE_DISABLED 0x00000008 478*7961SNatalie.Li@Sun.COM * SCF_STATE_ONLINE 0x00000010 479*7961SNatalie.Li@Sun.COM * SCF_STATE_DEGRADED 0x00000020 480*7961SNatalie.Li@Sun.COM * SCF_STATE_ALL 0x0000003F 481*7961SNatalie.Li@Sun.COM * 482*7961SNatalie.Li@Sun.COM * Microsoft service states 483*7961SNatalie.Li@Sun.COM * ======================== 484*7961SNatalie.Li@Sun.COM * SERVICE_CONTINUE_PENDING 0x00000005 485*7961SNatalie.Li@Sun.COM * SERVICE_PAUSE_PENDING 0x00000006 486*7961SNatalie.Li@Sun.COM * SERVICE_PAUSED 0x00000007 487*7961SNatalie.Li@Sun.COM * SERVICE_RUNNING 0x00000004 488*7961SNatalie.Li@Sun.COM * SERVICE_START_PENDING 0x00000002 489*7961SNatalie.Li@Sun.COM * SERVICE_STOP_PENDING 0x00000003 490*7961SNatalie.Li@Sun.COM * SERVICE_STOPPED 0x00000001 491*7961SNatalie.Li@Sun.COM * 492*7961SNatalie.Li@Sun.COM * Mapping 493*7961SNatalie.Li@Sun.COM * ======= 494*7961SNatalie.Li@Sun.COM * 495*7961SNatalie.Li@Sun.COM * SCF_STATE_ONLINE <-> SERVICE_RUNNING 496*7961SNatalie.Li@Sun.COM * SCF_STATE_OFFLINE <-> SERVICE_PAUSED 497*7961SNatalie.Li@Sun.COM * SCF_STATE_DISABLED <-> SERVICE_STOPPED 498*7961SNatalie.Li@Sun.COM * SCF_STATE_UNINIT <-> SERVICE_START_PENDING 499*7961SNatalie.Li@Sun.COM * SCF_STATE_DEGRADED <-> SERVICE_STOP_PENDING 500*7961SNatalie.Li@Sun.COM * SCF_STATE_MAINT <-> SERVICE_PAUSE_PENDING 501*7961SNatalie.Li@Sun.COM * SCF_STATE_STRING_LEGACY <-> SERVICE_RUNNING 502*7961SNatalie.Li@Sun.COM * Service Transitioning <-> SERVICE_STOP_PENDING 503*7961SNatalie.Li@Sun.COM */ 504*7961SNatalie.Li@Sun.COM uint32_t 505*7961SNatalie.Li@Sun.COM svcctl_scm_map_status(const char *state) 506*7961SNatalie.Li@Sun.COM { 507*7961SNatalie.Li@Sun.COM int i; 508*7961SNatalie.Li@Sun.COM 509*7961SNatalie.Li@Sun.COM struct { 510*7961SNatalie.Li@Sun.COM const char *scf_state; 511*7961SNatalie.Li@Sun.COM uint32_t scm_state; 512*7961SNatalie.Li@Sun.COM } state_map[] = { 513*7961SNatalie.Li@Sun.COM { SCF_STATE_STRING_ONLINE, SERVICE_RUNNING }, 514*7961SNatalie.Li@Sun.COM { SCF_STATE_STRING_OFFLINE, SERVICE_PAUSED }, 515*7961SNatalie.Li@Sun.COM { SCF_STATE_STRING_DISABLED, SERVICE_STOPPED }, 516*7961SNatalie.Li@Sun.COM { SCF_STATE_STRING_UNINIT, SERVICE_START_PENDING }, 517*7961SNatalie.Li@Sun.COM { SCF_STATE_STRING_DEGRADED, SERVICE_STOP_PENDING }, 518*7961SNatalie.Li@Sun.COM { SCF_STATE_STRING_MAINT, SERVICE_PAUSE_PENDING }, 519*7961SNatalie.Li@Sun.COM { SCF_STATE_STRING_LEGACY, SERVICE_RUNNING } 520*7961SNatalie.Li@Sun.COM }; 521*7961SNatalie.Li@Sun.COM 522*7961SNatalie.Li@Sun.COM for (i = 0; i < (sizeof (state_map)/sizeof (state_map[0])); ++i) { 523*7961SNatalie.Li@Sun.COM if (strcmp(state, state_map[i].scf_state) == 0) 524*7961SNatalie.Li@Sun.COM return (state_map[i].scm_state); 525*7961SNatalie.Li@Sun.COM } 526*7961SNatalie.Li@Sun.COM 527*7961SNatalie.Li@Sun.COM if (strrchr(state, '*') != 0) /* State Transitioning */ 528*7961SNatalie.Li@Sun.COM return (SERVICE_STOP_PENDING); 529*7961SNatalie.Li@Sun.COM 530*7961SNatalie.Li@Sun.COM return (SERVICE_RUNNING); 531*7961SNatalie.Li@Sun.COM } 532*7961SNatalie.Li@Sun.COM 533*7961SNatalie.Li@Sun.COM /* 534*7961SNatalie.Li@Sun.COM * svcctl_scm_enum_services 535*7961SNatalie.Li@Sun.COM * 536*7961SNatalie.Li@Sun.COM * Enumerates all SMF services. 537*7961SNatalie.Li@Sun.COM */ 538*7961SNatalie.Li@Sun.COM void 539*7961SNatalie.Li@Sun.COM svcctl_scm_enum_services(svcctl_manager_context_t *mgr_ctx, 540*7961SNatalie.Li@Sun.COM unsigned char *services) 541*7961SNatalie.Li@Sun.COM { 542*7961SNatalie.Li@Sun.COM svcctl_svc_node_t *node = NULL; 543*7961SNatalie.Li@Sun.COM int base_offset, offset, i; 544*7961SNatalie.Li@Sun.COM mts_wchar_t *wide_name; 545*7961SNatalie.Li@Sun.COM char *name; 546*7961SNatalie.Li@Sun.COM 547*7961SNatalie.Li@Sun.COM /*LINTED E_BAD_PTR_CAST_ALIGN*/ 548*7961SNatalie.Li@Sun.COM svc_enum_status_t *svc = (svc_enum_status_t *)services; 549*7961SNatalie.Li@Sun.COM 550*7961SNatalie.Li@Sun.COM base_offset = mgr_ctx->mc_scf_numsvcs * sizeof (svc_enum_status_t); 551*7961SNatalie.Li@Sun.COM 552*7961SNatalie.Li@Sun.COM offset = base_offset; 553*7961SNatalie.Li@Sun.COM node = uu_avl_first(mgr_ctx->mc_svcs); 554*7961SNatalie.Li@Sun.COM 555*7961SNatalie.Li@Sun.COM for (i = 0; ((i < mgr_ctx->mc_scf_numsvcs) && (node != NULL)); ++i) { 556*7961SNatalie.Li@Sun.COM svc[i].svc_name = offset; 557*7961SNatalie.Li@Sun.COM /*LINTED E_BAD_PTR_CAST_ALIGN*/ 558*7961SNatalie.Li@Sun.COM wide_name = (mts_wchar_t *)&services[offset]; 559*7961SNatalie.Li@Sun.COM name = node->sn_name; 560*7961SNatalie.Li@Sun.COM (void) mts_mbstowcs(wide_name, name, (strlen(name) + 1)); 561*7961SNatalie.Li@Sun.COM 562*7961SNatalie.Li@Sun.COM offset += SVCCTL_WNSTRLEN(name); 563*7961SNatalie.Li@Sun.COM 564*7961SNatalie.Li@Sun.COM svc[i].display_name = offset; 565*7961SNatalie.Li@Sun.COM /*LINTED E_BAD_PTR_CAST_ALIGN*/ 566*7961SNatalie.Li@Sun.COM wide_name = (mts_wchar_t *)&services[offset]; 567*7961SNatalie.Li@Sun.COM name = node->sn_fmri; 568*7961SNatalie.Li@Sun.COM (void) mts_mbstowcs(wide_name, name, (strlen(name) + 1)); 569*7961SNatalie.Li@Sun.COM 570*7961SNatalie.Li@Sun.COM offset += SVCCTL_WNSTRLEN(name); 571*7961SNatalie.Li@Sun.COM 572*7961SNatalie.Li@Sun.COM svc[i].svc_status.cur_state = 573*7961SNatalie.Li@Sun.COM svcctl_scm_map_status(node->sn_state); 574*7961SNatalie.Li@Sun.COM svc[i].svc_status.service_type = SERVICE_WIN32_SHARE_PROCESS; 575*7961SNatalie.Li@Sun.COM svc[i].svc_status.ctrl_accepted = 0; 576*7961SNatalie.Li@Sun.COM svc[i].svc_status.w32_exitcode = 0; 577*7961SNatalie.Li@Sun.COM svc[i].svc_status.svc_specified_exitcode = 0; 578*7961SNatalie.Li@Sun.COM svc[i].svc_status.check_point = 0; 579*7961SNatalie.Li@Sun.COM svc[i].svc_status.wait_hint = 0; 580*7961SNatalie.Li@Sun.COM 581*7961SNatalie.Li@Sun.COM node = uu_avl_next(mgr_ctx->mc_svcs, node); 582*7961SNatalie.Li@Sun.COM } 583*7961SNatalie.Li@Sun.COM } 584*7961SNatalie.Li@Sun.COM 585*7961SNatalie.Li@Sun.COM /* 586*7961SNatalie.Li@Sun.COM * svcctl_scm_cb_bytes_needed 587*7961SNatalie.Li@Sun.COM * 588*7961SNatalie.Li@Sun.COM * Callback function to calculate bytes needed to enumerate SMF services. 589*7961SNatalie.Li@Sun.COM */ 590*7961SNatalie.Li@Sun.COM static int 591*7961SNatalie.Li@Sun.COM svcctl_scm_cb_bytes_needed(void *svc_node, void *byte_cnt) 592*7961SNatalie.Li@Sun.COM { 593*7961SNatalie.Li@Sun.COM svcctl_svc_node_t *node = svc_node; 594*7961SNatalie.Li@Sun.COM int *cnt = byte_cnt; 595*7961SNatalie.Li@Sun.COM 596*7961SNatalie.Li@Sun.COM *cnt += (strlen(node->sn_fmri) + 1) * sizeof (mts_wchar_t); 597*7961SNatalie.Li@Sun.COM *cnt += (strlen(node->sn_name) + 1) * sizeof (mts_wchar_t); 598*7961SNatalie.Li@Sun.COM 599*7961SNatalie.Li@Sun.COM return (UU_WALK_NEXT); 600*7961SNatalie.Li@Sun.COM } 601*7961SNatalie.Li@Sun.COM 602*7961SNatalie.Li@Sun.COM /* 603*7961SNatalie.Li@Sun.COM * svcctl_scm_bytes_needed 604*7961SNatalie.Li@Sun.COM * 605*7961SNatalie.Li@Sun.COM * Calculates bytes needed to enumerate SMF services. 606*7961SNatalie.Li@Sun.COM */ 607*7961SNatalie.Li@Sun.COM void 608*7961SNatalie.Li@Sun.COM svcctl_scm_bytes_needed(svcctl_manager_context_t *mgr_ctx) 609*7961SNatalie.Li@Sun.COM { 610*7961SNatalie.Li@Sun.COM int bytes_needed = 0, svc_enum_status_size = 0; 611*7961SNatalie.Li@Sun.COM 612*7961SNatalie.Li@Sun.COM (void) uu_avl_walk(mgr_ctx->mc_svcs, svcctl_scm_cb_bytes_needed, 613*7961SNatalie.Li@Sun.COM &bytes_needed, 0); 614*7961SNatalie.Li@Sun.COM 615*7961SNatalie.Li@Sun.COM svc_enum_status_size = 616*7961SNatalie.Li@Sun.COM mgr_ctx->mc_scf_numsvcs * sizeof (svc_enum_status_t); 617*7961SNatalie.Li@Sun.COM bytes_needed += svc_enum_status_size; 618*7961SNatalie.Li@Sun.COM 619*7961SNatalie.Li@Sun.COM mgr_ctx->mc_bytes_needed = bytes_needed; 620*7961SNatalie.Li@Sun.COM } 621*7961SNatalie.Li@Sun.COM 622*7961SNatalie.Li@Sun.COM /* 623*7961SNatalie.Li@Sun.COM * svcctl_scm_validate_service 624*7961SNatalie.Li@Sun.COM * 625*7961SNatalie.Li@Sun.COM * Check to see whether or not a service is supported. 626*7961SNatalie.Li@Sun.COM * 627*7961SNatalie.Li@Sun.COM * Returns: 628*7961SNatalie.Li@Sun.COM * ERROR_SUCCESS 629*7961SNatalie.Li@Sun.COM * ERROR_SERVICE_DOES_NOT_EXIST 630*7961SNatalie.Li@Sun.COM */ 631*7961SNatalie.Li@Sun.COM uint32_t 632*7961SNatalie.Li@Sun.COM svcctl_scm_validate_service(svcctl_manager_context_t *mgr_ctx, char *svc_name) 633*7961SNatalie.Li@Sun.COM { 634*7961SNatalie.Li@Sun.COM svcctl_svc_node_t node; 635*7961SNatalie.Li@Sun.COM uu_avl_index_t idx; 636*7961SNatalie.Li@Sun.COM 637*7961SNatalie.Li@Sun.COM if (svc_name == NULL) 638*7961SNatalie.Li@Sun.COM return (ERROR_SERVICE_DOES_NOT_EXIST); 639*7961SNatalie.Li@Sun.COM 640*7961SNatalie.Li@Sun.COM bzero(&node, sizeof (svcctl_svc_node_t)); 641*7961SNatalie.Li@Sun.COM node.sn_name = svc_name; 642*7961SNatalie.Li@Sun.COM if (uu_avl_find(mgr_ctx->mc_svcs, &node, 643*7961SNatalie.Li@Sun.COM &mgr_ctx->mc_scf_max_fmri_len, &idx) != NULL) 644*7961SNatalie.Li@Sun.COM return (ERROR_SUCCESS); 645*7961SNatalie.Li@Sun.COM 646*7961SNatalie.Li@Sun.COM return (ERROR_SERVICE_DOES_NOT_EXIST); 647*7961SNatalie.Li@Sun.COM } 648*7961SNatalie.Li@Sun.COM 649*7961SNatalie.Li@Sun.COM /* 650*7961SNatalie.Li@Sun.COM * svcctl_scm_find_service 651*7961SNatalie.Li@Sun.COM * 652*7961SNatalie.Li@Sun.COM * Lookup a service. 653*7961SNatalie.Li@Sun.COM */ 654*7961SNatalie.Li@Sun.COM svcctl_svc_node_t * 655*7961SNatalie.Li@Sun.COM svcctl_scm_find_service(svcctl_manager_context_t *mgr_ctx, char *svc_name) 656*7961SNatalie.Li@Sun.COM { 657*7961SNatalie.Li@Sun.COM svcctl_svc_node_t node; 658*7961SNatalie.Li@Sun.COM uu_avl_index_t idx; 659*7961SNatalie.Li@Sun.COM svcctl_svc_node_t *f_node = NULL; 660*7961SNatalie.Li@Sun.COM 661*7961SNatalie.Li@Sun.COM if (svc_name == NULL) 662*7961SNatalie.Li@Sun.COM return (NULL); 663*7961SNatalie.Li@Sun.COM 664*7961SNatalie.Li@Sun.COM bzero(&node, sizeof (svcctl_svc_node_t)); 665*7961SNatalie.Li@Sun.COM node.sn_name = svc_name; 666*7961SNatalie.Li@Sun.COM f_node = uu_avl_find(mgr_ctx->mc_svcs, &node, 667*7961SNatalie.Li@Sun.COM &mgr_ctx->mc_scf_max_fmri_len, &idx); 668*7961SNatalie.Li@Sun.COM if (f_node != NULL) 669*7961SNatalie.Li@Sun.COM return (f_node); 670*7961SNatalie.Li@Sun.COM 671*7961SNatalie.Li@Sun.COM return (NULL); 672*7961SNatalie.Li@Sun.COM } 673*7961SNatalie.Li@Sun.COM 674*7961SNatalie.Li@Sun.COM /* 675*7961SNatalie.Li@Sun.COM * svcctl_scm_refresh 676*7961SNatalie.Li@Sun.COM * 677*7961SNatalie.Li@Sun.COM * Refresh SCM services per context. 678*7961SNatalie.Li@Sun.COM */ 679*7961SNatalie.Li@Sun.COM int 680*7961SNatalie.Li@Sun.COM svcctl_scm_refresh(svcctl_manager_context_t *mgr_ctx) 681*7961SNatalie.Li@Sun.COM { 682*7961SNatalie.Li@Sun.COM svcctl_scm_fini(mgr_ctx); 683*7961SNatalie.Li@Sun.COM return (svcctl_scm_init(mgr_ctx)); 684*7961SNatalie.Li@Sun.COM } 685*7961SNatalie.Li@Sun.COM 686*7961SNatalie.Li@Sun.COM /* 687*7961SNatalie.Li@Sun.COM * svcctl_scm_scf_handle_init 688*7961SNatalie.Li@Sun.COM * 689*7961SNatalie.Li@Sun.COM * Initialize SCF handle per context. 690*7961SNatalie.Li@Sun.COM */ 691*7961SNatalie.Li@Sun.COM int 692*7961SNatalie.Li@Sun.COM svcctl_scm_scf_handle_init(svcctl_manager_context_t *mgr_ctx) 693*7961SNatalie.Li@Sun.COM { 694*7961SNatalie.Li@Sun.COM mgr_ctx->mc_scf_hdl = scf_handle_create(SCF_VERSION); 695*7961SNatalie.Li@Sun.COM if (mgr_ctx->mc_scf_hdl == NULL) 696*7961SNatalie.Li@Sun.COM return (-1); 697*7961SNatalie.Li@Sun.COM 698*7961SNatalie.Li@Sun.COM if (scf_handle_bind(mgr_ctx->mc_scf_hdl) == -1) { 699*7961SNatalie.Li@Sun.COM scf_handle_destroy(mgr_ctx->mc_scf_hdl); 700*7961SNatalie.Li@Sun.COM return (-1); 701*7961SNatalie.Li@Sun.COM } 702*7961SNatalie.Li@Sun.COM 703*7961SNatalie.Li@Sun.COM mgr_ctx->mc_scf_gpg = scf_pg_create(mgr_ctx->mc_scf_hdl); 704*7961SNatalie.Li@Sun.COM mgr_ctx->mc_scf_gprop = scf_property_create(mgr_ctx->mc_scf_hdl); 705*7961SNatalie.Li@Sun.COM mgr_ctx->mc_scf_gval = scf_value_create(mgr_ctx->mc_scf_hdl); 706*7961SNatalie.Li@Sun.COM 707*7961SNatalie.Li@Sun.COM if ((mgr_ctx->mc_scf_gpg == NULL) || 708*7961SNatalie.Li@Sun.COM (mgr_ctx->mc_scf_gprop == NULL) || 709*7961SNatalie.Li@Sun.COM (mgr_ctx->mc_scf_gval == NULL)) { 710*7961SNatalie.Li@Sun.COM (void) scf_handle_unbind(mgr_ctx->mc_scf_hdl); 711*7961SNatalie.Li@Sun.COM scf_handle_destroy(mgr_ctx->mc_scf_hdl); 712*7961SNatalie.Li@Sun.COM return (-1); 713*7961SNatalie.Li@Sun.COM } 714*7961SNatalie.Li@Sun.COM 715*7961SNatalie.Li@Sun.COM mgr_ctx->mc_scf_max_fmri_len = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH); 716*7961SNatalie.Li@Sun.COM mgr_ctx->mc_scf_max_value_len = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH); 717*7961SNatalie.Li@Sun.COM 718*7961SNatalie.Li@Sun.COM return (0); 719*7961SNatalie.Li@Sun.COM } 720*7961SNatalie.Li@Sun.COM 721*7961SNatalie.Li@Sun.COM /* 722*7961SNatalie.Li@Sun.COM * svcctl_scm_scf_handle_init 723*7961SNatalie.Li@Sun.COM * 724*7961SNatalie.Li@Sun.COM * Destroy SCF handle per context. 725*7961SNatalie.Li@Sun.COM */ 726*7961SNatalie.Li@Sun.COM void 727*7961SNatalie.Li@Sun.COM svcctl_scm_scf_handle_fini(svcctl_manager_context_t *mgr_ctx) 728*7961SNatalie.Li@Sun.COM { 729*7961SNatalie.Li@Sun.COM scf_value_destroy(mgr_ctx->mc_scf_gval); 730*7961SNatalie.Li@Sun.COM scf_property_destroy(mgr_ctx->mc_scf_gprop); 731*7961SNatalie.Li@Sun.COM scf_pg_destroy(mgr_ctx->mc_scf_gpg); 732*7961SNatalie.Li@Sun.COM (void) scf_handle_unbind(mgr_ctx->mc_scf_hdl); 733*7961SNatalie.Li@Sun.COM scf_handle_destroy(mgr_ctx->mc_scf_hdl); 734*7961SNatalie.Li@Sun.COM } 735*7961SNatalie.Li@Sun.COM 736*7961SNatalie.Li@Sun.COM /* 737*7961SNatalie.Li@Sun.COM * svcctl_scm_init 738*7961SNatalie.Li@Sun.COM * 739*7961SNatalie.Li@Sun.COM * Initialize SCM repository per context. 740*7961SNatalie.Li@Sun.COM * SCM repository holds a list of SMF services. 741*7961SNatalie.Li@Sun.COM * Each SMF service node contains state, description and FMRI. 742*7961SNatalie.Li@Sun.COM */ 743*7961SNatalie.Li@Sun.COM int 744*7961SNatalie.Li@Sun.COM svcctl_scm_init(svcctl_manager_context_t *mgr_ctx) 745*7961SNatalie.Li@Sun.COM { 746*7961SNatalie.Li@Sun.COM int exit_status = 0; 747*7961SNatalie.Li@Sun.COM 748*7961SNatalie.Li@Sun.COM assert(mgr_ctx->mc_svcs_pool == NULL); 749*7961SNatalie.Li@Sun.COM assert(mgr_ctx->mc_svcs == NULL); 750*7961SNatalie.Li@Sun.COM 751*7961SNatalie.Li@Sun.COM mgr_ctx->mc_svcs_pool = uu_avl_pool_create("smf_svcs_pool", 752*7961SNatalie.Li@Sun.COM sizeof (svcctl_svc_node_t), offsetof(svcctl_svc_node_t, sn_node), 753*7961SNatalie.Li@Sun.COM svcctl_scm_avl_nodecmp, UU_AVL_DEBUG); 754*7961SNatalie.Li@Sun.COM 755*7961SNatalie.Li@Sun.COM if (mgr_ctx->mc_svcs_pool == NULL) 756*7961SNatalie.Li@Sun.COM return (-1); 757*7961SNatalie.Li@Sun.COM 758*7961SNatalie.Li@Sun.COM mgr_ctx->mc_svcs = uu_avl_create(mgr_ctx->mc_svcs_pool, NULL, 0); 759*7961SNatalie.Li@Sun.COM if (mgr_ctx->mc_svcs == NULL) { 760*7961SNatalie.Li@Sun.COM uu_avl_pool_destroy(mgr_ctx->mc_svcs_pool); 761*7961SNatalie.Li@Sun.COM return (-1); 762*7961SNatalie.Li@Sun.COM } 763*7961SNatalie.Li@Sun.COM 764*7961SNatalie.Li@Sun.COM if (scf_walk_fmri(mgr_ctx->mc_scf_hdl, 0, NULL, 765*7961SNatalie.Li@Sun.COM SCF_WALK_MULTIPLE | SCF_WALK_LEGACY, 766*7961SNatalie.Li@Sun.COM svcctl_scm_cb_list_svcinst, mgr_ctx, &exit_status, NULL) != 0) { 767*7961SNatalie.Li@Sun.COM uu_avl_destroy(mgr_ctx->mc_svcs); 768*7961SNatalie.Li@Sun.COM uu_avl_pool_destroy(mgr_ctx->mc_svcs_pool); 769*7961SNatalie.Li@Sun.COM return (-1); 770*7961SNatalie.Li@Sun.COM } 771*7961SNatalie.Li@Sun.COM 772*7961SNatalie.Li@Sun.COM mgr_ctx->mc_scf_numsvcs = uu_avl_numnodes(mgr_ctx->mc_svcs); 773*7961SNatalie.Li@Sun.COM if (mgr_ctx->mc_scf_numsvcs > 0) 774*7961SNatalie.Li@Sun.COM svcctl_scm_bytes_needed(mgr_ctx); 775*7961SNatalie.Li@Sun.COM 776*7961SNatalie.Li@Sun.COM return (0); 777*7961SNatalie.Li@Sun.COM } 778*7961SNatalie.Li@Sun.COM 779*7961SNatalie.Li@Sun.COM /* 780*7961SNatalie.Li@Sun.COM * svcctl_scm_fini 781*7961SNatalie.Li@Sun.COM * 782*7961SNatalie.Li@Sun.COM * Destroy SCM repository per context. 783*7961SNatalie.Li@Sun.COM */ 784*7961SNatalie.Li@Sun.COM void 785*7961SNatalie.Li@Sun.COM svcctl_scm_fini(svcctl_manager_context_t *mgr_ctx) 786*7961SNatalie.Li@Sun.COM { 787*7961SNatalie.Li@Sun.COM uu_avl_walk_t *walk; 788*7961SNatalie.Li@Sun.COM svcctl_svc_node_t *node; 789*7961SNatalie.Li@Sun.COM 790*7961SNatalie.Li@Sun.COM if ((mgr_ctx == NULL) || (mgr_ctx->mc_svcs_pool == NULL) || 791*7961SNatalie.Li@Sun.COM (mgr_ctx->mc_svcs == NULL)) 792*7961SNatalie.Li@Sun.COM return; 793*7961SNatalie.Li@Sun.COM 794*7961SNatalie.Li@Sun.COM if ((walk = 795*7961SNatalie.Li@Sun.COM uu_avl_walk_start(mgr_ctx->mc_svcs, UU_WALK_ROBUST)) == NULL) 796*7961SNatalie.Li@Sun.COM return; 797*7961SNatalie.Li@Sun.COM 798*7961SNatalie.Li@Sun.COM while ((node = uu_avl_walk_next(walk)) != NULL) { 799*7961SNatalie.Li@Sun.COM uu_avl_remove(mgr_ctx->mc_svcs, node); 800*7961SNatalie.Li@Sun.COM free(node->sn_name); 801*7961SNatalie.Li@Sun.COM free(node->sn_fmri); 802*7961SNatalie.Li@Sun.COM free(node->sn_desc); 803*7961SNatalie.Li@Sun.COM free(node->sn_state); 804*7961SNatalie.Li@Sun.COM free(node); 805*7961SNatalie.Li@Sun.COM } 806*7961SNatalie.Li@Sun.COM uu_avl_walk_end(walk); 807*7961SNatalie.Li@Sun.COM uu_avl_destroy(mgr_ctx->mc_svcs); 808*7961SNatalie.Li@Sun.COM uu_avl_pool_destroy(mgr_ctx->mc_svcs_pool); 809*7961SNatalie.Li@Sun.COM mgr_ctx->mc_svcs_pool = NULL; 810*7961SNatalie.Li@Sun.COM mgr_ctx->mc_svcs = NULL; 811*7961SNatalie.Li@Sun.COM } 812