2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License (the "License").
2N/A * You may not use this file except in compliance with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A */
2N/A
2N/A/*
2N/A * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
2N/A */
2N/A
2N/A/*
2N/A * ==============================================
2N/A * Name Service Switch libscf to python interface
2N/A * ==============================================
2N/A */
2N/A
2N/A/* Python specific includes */
2N/A#include <Python.h>
2N/A#include <structmember.h>
2N/A
2N/A/* libscf and other includes */
2N/A#include <libscf.h>
2N/A#include <stdlib.h>
2N/A#include <string.h>
2N/A
2N/A/*
2N/A * ===================================
2N/A * Nssscf Method structure definitions
2N/A * ===================================
2N/A */
2N/A
2N/Astatic PyObject *NssscfError;
2N/A
2N/Atypedef struct {
2N/A PyObject_HEAD
2N/A /* Nssscf Type-specific fields go here. */
2N/A PyObject *service; /* python service object (name) */
2N/A scf_handle_t *handle; /* smf handle */
2N/A scf_scope_t *scope; /* smf scope */
2N/A scf_service_t *svc; /* smf service handle */
2N/A scf_instance_t *inst; /* instance handle */
2N/A} Nssscf_t;
2N/A
2N/A/*
2N/A * =======================
2N/A * Nssscf helper functions
2N/A * =======================
2N/A */
2N/Astatic char **__strlist_add(char **list, const char *str);
2N/Astatic int __strlist_len(char **list);
2N/Astatic void __strlist_free(char **list);
2N/A
2N/Astatic char *__getscf_svcname(PyObject *service);
2N/Astatic char *__getscf_instname(Nssscf_t *self);
2N/Astatic char *__getscf_instfmri(Nssscf_t *self);
2N/Astatic char *__getscf_inststate(Nssscf_t *self);
2N/Astatic int __setscf_svc(Nssscf_t *self, PyObject *service);
2N/A
2N/A#define FREE_INSTANCE() { if (instance) free((void *)instance); }
2N/A
2N/Astatic PyObject *Nssscf_ns1_convert(Nssscf_t *, PyObject *, PyObject *);
2N/A
2N/A/*
2N/A * ==========================
2N/A * Nssscf Instance management
2N/A * ==========================
2N/A */
2N/A
2N/Astatic void
2N/ANssscf_dealloc(Nssscf_t *self)
2N/A{
2N/A /* libscf instance cleanup */
2N/A if (self->inst != NULL) {
2N/A scf_instance_destroy(self->inst);
2N/A self->inst = NULL;
2N/A }
2N/A if (self->svc != NULL) {
2N/A scf_service_destroy(self->svc);
2N/A self->svc = NULL;
2N/A }
2N/A if (self->scope != NULL) {
2N/A scf_scope_destroy(self->scope);
2N/A self->scope = NULL;
2N/A }
2N/A if (self->handle != NULL) {
2N/A scf_handle_destroy(self->handle);
2N/A self->handle = NULL;
2N/A }
2N/A
2N/A Py_XDECREF(self->service);
2N/A self->ob_type->tp_free((PyObject *)self);
2N/A}
2N/A
2N/Astatic PyObject *
2N/ANssscf_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
2N/A{
2N/A Nssscf_t *self;
2N/A scf_handle_t *h;
2N/A scf_scope_t *s;
2N/A scf_service_t *v;
2N/A scf_instance_t *i;
2N/A
2N/A self = (Nssscf_t *)type->tp_alloc(type, 0);
2N/A if (self != NULL) {
2N/A self->service = PyString_FromString("");
2N/A if (self->service == NULL) {
2N/A Py_DECREF(self);
2N/A return (NULL);
2N/A }
2N/A }
2N/A /* libscf instance generic setup */
2N/A h = scf_handle_create(SCF_VERSION);
2N/A s = scf_scope_create(h);
2N/A v = scf_service_create(h);
2N/A i = scf_instance_create(h);
2N/A if (h == NULL || s == NULL || v == NULL || i == NULL ||
2N/A scf_handle_bind(h) == -1 ||
2N/A scf_handle_get_scope(h, SCF_SCOPE_LOCAL, s) == -1) {
2N/A if (i != NULL)
2N/A scf_instance_destroy(i);
2N/A if (v != NULL)
2N/A scf_service_destroy(v);
2N/A if (s != NULL)
2N/A scf_scope_destroy(s);
2N/A if (h != NULL)
2N/A scf_handle_destroy(h);
2N/A Py_DECREF(self->service);
2N/A Py_DECREF(self);
2N/A return (NULL);
2N/A }
2N/A self->handle = h;
2N/A self->scope = s;
2N/A self->svc = v;
2N/A self->inst = i;
2N/A
2N/A return ((PyObject *)self);
2N/A}
2N/A
2N/Astatic int
2N/ANssscf_init(Nssscf_t *self, PyObject *args, PyObject *kwds)
2N/A{
2N/A PyObject *service = NULL;
2N/A PyObject *tmp;
2N/A static char *kwlist[] = {"service", NULL};
2N/A
2N/A if (! PyArg_ParseTupleAndKeywords(args, kwds, "|S", kwlist, &service))
2N/A return (-1);
2N/A
2N/A if (service) {
2N/A /* libscf instance specific init */
2N/A if (__setscf_svc(self, service) < 0)
2N/A return (-1);
2N/A /* python specific */
2N/A tmp = self->service;
2N/A Py_INCREF(service);
2N/A self->service = service;
2N/A Py_DECREF(tmp);
2N/A }
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * ================================
2N/A * Nssscf Instance member functions
2N/A * ================================
2N/A */
2N/A
2N/Astatic PyObject *
2N/ANssscf_getservice(Nssscf_t *self, void *closure)
2N/A{
2N/A Py_INCREF(self->service);
2N/A return (self->service);
2N/A}
2N/A
2N/Astatic int
2N/ANssscf_setservice(Nssscf_t *self, PyObject *value, void *closure)
2N/A{
2N/A PyObject *tmp;
2N/A
2N/A if (value == NULL) {
2N/A PyErr_SetString(PyExc_TypeError,
2N/A "Cannot delete the service attribute");
2N/A return (-1);
2N/A }
2N/A
2N/A if (! PyString_Check(value)) {
2N/A PyErr_SetString(PyExc_TypeError,
2N/A "The service attribute value must be a string");
2N/A return (-1);
2N/A }
2N/A
2N/A /* libscf instance specific init */
2N/A if (__setscf_svc(self, value) < 0) {
2N/A PyErr_SetString(NssscfError, "invalid SMF service");
2N/A return (-1);
2N/A }
2N/A tmp = self->service;
2N/A Py_INCREF(value);
2N/A self->service = value;
2N/A Py_DECREF(tmp);
2N/A
2N/A /* re-set any libscf instance specific init */
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * =======================
2N/A * Nssscf Instance methods
2N/A * =======================
2N/A */
2N/A
2N/A /* Get Operations */
2N/A/*
2N/A * Get all Service Property groups
2N/A * IN: nothing
2N/A * OUT: Tuple of property group names and types
2N/A */
2N/A
2N/Astatic PyObject *
2N/ANssscf_get_svcpgs(Nssscf_t *self, PyObject *args)
2N/A{
2N/A scf_propertygroup_t *pg = NULL;
2N/A scf_iter_t *iter = NULL;
2N/A PyObject *pytuple = NULL;
2N/A PyObject *pylist = NULL;
2N/A PyObject *pyobject = NULL;
2N/A char **nmlist = NULL;
2N/A char **tplist = NULL;
2N/A int nmlen, tplen, listlen, l;
2N/A char *pgname, *pgtype;
2N/A PyObject *ret = NULL;
2N/A
2N/A if ((iter = scf_iter_create(self->handle)) == NULL) {
2N/A PyErr_SetString(NssscfError, "Cannot create iterator");
2N/A return (NULL);
2N/A }
2N/A if (scf_iter_service_pgs(iter, self->svc) < 0) {
2N/A scf_iter_destroy(iter);
2N/A PyErr_SetString(NssscfError, "Cannot create pg iterator");
2N/A return (NULL);
2N/A }
2N/A if ((pg = scf_pg_create(self->handle)) == NULL) {
2N/A scf_iter_destroy(iter);
2N/A PyErr_SetString(NssscfError, "Cannot create pg handle");
2N/A return (NULL);
2N/A }
2N/A nmlen = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) + 1;
2N/A if ((pgname = (char *)malloc(nmlen)) == NULL) {
2N/A scf_pg_destroy(pg);
2N/A scf_iter_destroy(iter);
2N/A PyErr_SetString(NssscfError, "Memory Error");
2N/A return (NULL);
2N/A }
2N/A tplen = scf_limit(SCF_LIMIT_MAX_PG_TYPE_LENGTH) + 1;
2N/A if ((pgtype = (char *)malloc(tplen)) == NULL) {
2N/A free((void *)pgname);
2N/A scf_pg_destroy(pg);
2N/A scf_iter_destroy(iter);
2N/A PyErr_SetString(NssscfError, "Memory Error");
2N/A return (NULL);
2N/A }
2N/A while (scf_iter_next_pg(iter, pg) > 0) {
2N/A if (scf_pg_get_name(pg, pgname, nmlen) < 0)
2N/A continue;
2N/A if (scf_pg_get_type(pg, pgtype, tplen) < 0)
2N/A continue;
2N/A nmlist = __strlist_add(nmlist, pgname);
2N/A tplist = __strlist_add(tplist, pgtype);
2N/A }
2N/A if ((listlen = __strlist_len(nmlist)) > 0) {
2N/A if ((pylist = PyList_New(0)) == NULL) {
2N/A PyErr_SetString(NssscfError,
2N/A "Unable to build Property group tuple");
2N/A ret = NULL;
2N/A goto err;
2N/A }
2N/A for (l = 0; l < listlen; l++) {
2N/A pyobject = Py_BuildValue("(ss)", nmlist[l], tplist[l]);
2N/A if (pyobject == NULL) {
2N/A PyErr_SetString(NssscfError,
2N/A "Unable to build Property group tuple");
2N/A ret = NULL;
2N/A goto err;
2N/A }
2N/A if (PyList_Append(pylist, pyobject) < 0) {
2N/A PyErr_SetString(NssscfError,
2N/A "Unable to build Property group tuple");
2N/A ret = NULL;
2N/A goto err;
2N/A }
2N/A Py_DECREF(pyobject);
2N/A pyobject = NULL;
2N/A }
2N/A pytuple = PyList_AsTuple(pylist);
2N/A Py_DECREF(pylist);
2N/A pylist = NULL;
2N/A } else {
2N/A pytuple = Py_BuildValue("()");
2N/A }
2N/A ret = pytuple;
2N/Aerr:
2N/A /* ErrStrings (if any) should be set by now */
2N/A if (pyobject)
2N/A Py_DECREF(pyobject);
2N/A if (pylist)
2N/A Py_DECREF(pylist);
2N/A if (pgname)
2N/A free((void *)pgname);
2N/A if (pgtype)
2N/A free((void *)pgtype);
2N/A __strlist_free(nmlist);
2N/A __strlist_free(tplist);
2N/A scf_pg_destroy(pg);
2N/A scf_iter_destroy(iter);
2N/A return (ret);
2N/A}
2N/A
2N/A/*
2N/A * Get all Properties for a Property group
2N/A * IN: arg1=pg
2N/A * OUT: Tuple of properties and types
2N/A */
2N/A
2N/Astatic PyObject *
2N/ANssscf_get_pgprops(Nssscf_t *self, PyObject *args)
2N/A{
2N/A char *instance = __getscf_instname(self);
2N/A char *instnm;
2N/A const char *pgname;
2N/A scf_iter_t *iter = NULL;
2N/A scf_propertygroup_t *pg_handle = NULL;
2N/A scf_property_t *prop_handle = NULL;
2N/A PyObject *pytuple = NULL;
2N/A PyObject *pylist = NULL;
2N/A PyObject *pyobject = NULL;
2N/A char **nmlist = NULL;
2N/A char **tplist = NULL;
2N/A int nmlen, listlen, l;
2N/A char *prname = NULL;
2N/A scf_type_t prtype;
2N/A PyObject *ret = NULL;
2N/A const char *tpname;
2N/A
2N/A /* get args */
2N/A if (!PyArg_ParseTuple(args, "s", &pgname)) {
2N/A FREE_INSTANCE();
2N/A PyErr_SetString(PyExc_ValueError,
2N/A "Property group argument must be a string");
2N/A return (NULL);
2N/A }
2N/A /* alloc temp storage */
2N/A if ((iter = scf_iter_create(self->handle)) == NULL) {
2N/A FREE_INSTANCE();
2N/A PyErr_SetString(NssscfError, "Cannot create iterator");
2N/A return (NULL);
2N/A }
2N/A if ((pg_handle = scf_pg_create(self->handle)) == NULL) {
2N/A scf_iter_destroy(iter);
2N/A FREE_INSTANCE();
2N/A PyErr_SetString(NssscfError, "Cannot create pg handle");
2N/A return (NULL);
2N/A }
2N/A if ((prop_handle = scf_property_create(self->handle)) == NULL) {
2N/A scf_pg_destroy(pg_handle);
2N/A scf_iter_destroy(iter);
2N/A FREE_INSTANCE();
2N/A PyErr_SetString(NssscfError, "Cannot create property handle");
2N/A return (NULL);
2N/A }
2N/A nmlen = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) + 1;
2N/A if ((prname = (char *)malloc(nmlen)) == NULL) {
2N/A scf_property_destroy(prop_handle);
2N/A scf_pg_destroy(pg_handle);
2N/A scf_iter_destroy(iter);
2N/A FREE_INSTANCE();
2N/A PyErr_SetString(NssscfError, "Memory Error");
2N/A return (NULL);
2N/A }
2N/A /* get property group from service */
2N/A if (instance == NULL) {
2N/A if (scf_service_get_pg(self->svc, pgname, pg_handle) != 0) {
2N/A PyErr_SetString(NssscfError,
2N/A "Property group does not exist");
2N/A ret = NULL;
2N/A goto err;
2N/A }
2N/A } else {
2N/A instnm = strrchr(instance, ':');
2N/A if (instnm == NULL) {
2N/A PyErr_SetString(NssscfError,
2N/A "Service is not an instance");
2N/A ret = NULL;
2N/A goto err;
2N/A }
2N/A instnm++;
2N/A if (scf_service_get_instance(self->svc,
2N/A instnm, self->inst) < 0) {
2N/A PyErr_SetString(NssscfError,
2N/A "Service is not an instance");
2N/A ret = NULL;
2N/A goto err;
2N/A }
2N/A if (scf_instance_get_pg_composed(self->inst, NULL,
2N/A pgname, pg_handle) != 0) {
2N/A PyErr_SetString(NssscfError,
2N/A "Property group does not exist");
2N/A ret = NULL;
2N/A goto err;
2N/A }
2N/A }
2N/A if (scf_iter_pg_properties(iter, pg_handle) < 0) {
2N/A PyErr_SetString(NssscfError,
2N/A "Cannot create property iterator");
2N/A ret = NULL;
2N/A goto err;
2N/A }
2N/A
2N/A /* setup and iterate properties in property group */
2N/A while (scf_iter_next_property(iter, prop_handle) > 0) {
2N/A if (scf_property_get_name(prop_handle, prname, nmlen) < 0)
2N/A continue;
2N/A if (scf_property_type(prop_handle, &prtype) < 0)
2N/A continue;
2N/A nmlist = __strlist_add(nmlist, prname);
2N/A tpname = scf_type_to_string(prtype);
2N/A tplist = __strlist_add(tplist, tpname);
2N/A }
2N/A if ((listlen = __strlist_len(nmlist)) > 0) {
2N/A if ((pylist = PyList_New(0)) == NULL) {
2N/A PyErr_SetString(NssscfError,
2N/A "Unable to build Property tuple");
2N/A ret = NULL;
2N/A goto err;
2N/A }
2N/A for (l = 0; l < listlen; l++) {
2N/A pyobject = Py_BuildValue("(ss)", nmlist[l], tplist[l]);
2N/A if (pyobject == NULL) {
2N/A PyErr_SetString(NssscfError,
2N/A "Unable to build Property tuple");
2N/A ret = NULL;
2N/A goto err;
2N/A }
2N/A if (PyList_Append(pylist, pyobject) < 0) {
2N/A PyErr_SetString(NssscfError,
2N/A "Unable to build Property tuple");
2N/A ret = NULL;
2N/A goto err;
2N/A }
2N/A Py_DECREF(pyobject);
2N/A pyobject = NULL;
2N/A }
2N/A pytuple = PyList_AsTuple(pylist);
2N/A Py_DECREF(pylist);
2N/A pylist = NULL;
2N/A } else {
2N/A pytuple = Py_BuildValue("()");
2N/A }
2N/A ret = pytuple;
2N/Aerr:
2N/A /* ErrStrings (if any) should be set by now */
2N/A if (pyobject)
2N/A Py_DECREF(pyobject);
2N/A if (pylist)
2N/A Py_DECREF(pylist);
2N/A if (prname)
2N/A free((void *)prname);
2N/A FREE_INSTANCE();
2N/A __strlist_free(nmlist);
2N/A __strlist_free(tplist);
2N/A scf_property_destroy(prop_handle);
2N/A scf_pg_destroy(pg_handle);
2N/A scf_iter_destroy(iter);
2N/A return (ret);
2N/A}
2N/A
2N/A/*
2N/A * Get all Property Values for a pg/property
2N/A * IN: arg1=pg, arg2=prop
2N/A * OUT: Tuple of properties and types
2N/A */
2N/A
2N/Astatic PyObject *
2N/ANssscf_get_propvals(Nssscf_t *self, PyObject *args)
2N/A{
2N/A char *instance = __getscf_instfmri(self);
2N/A char *instnm;
2N/A const char *pgname, *prname;
2N/A scf_iter_t *iter = NULL;
2N/A scf_propertygroup_t *pg_handle = NULL;
2N/A scf_property_t *prop_handle = NULL;
2N/A scf_value_t *value_handle = NULL;
2N/A PyObject *pytuple = NULL;
2N/A PyObject *pylist = NULL;
2N/A PyObject *pyobject = NULL;
2N/A char **vallist = NULL;
2N/A int listlen, l;
2N/A char *buf = NULL;
2N/A int buflen;
2N/A PyObject *ret = NULL;
2N/A
2N/A /* get args */
2N/A if (!PyArg_ParseTuple(args, "ss", &pgname, &prname)) {
2N/A FREE_INSTANCE();
2N/A PyErr_SetString(PyExc_ValueError,
2N/A "Property group and property names must be strings");
2N/A return (NULL);
2N/A }
2N/A /* alloc temp storage */
2N/A if ((iter = scf_iter_create(self->handle)) == NULL) {
2N/A FREE_INSTANCE();
2N/A PyErr_SetString(NssscfError, "Cannot create iterator");
2N/A return (NULL);
2N/A }
2N/A if ((pg_handle = scf_pg_create(self->handle)) == NULL) {
2N/A scf_iter_destroy(iter);
2N/A FREE_INSTANCE();
2N/A PyErr_SetString(NssscfError, "Cannot create pg handle");
2N/A return (NULL);
2N/A }
2N/A if ((prop_handle = scf_property_create(self->handle)) == NULL) {
2N/A scf_pg_destroy(pg_handle);
2N/A scf_iter_destroy(iter);
2N/A FREE_INSTANCE();
2N/A PyErr_SetString(NssscfError, "Cannot create property handle");
2N/A return (NULL);
2N/A }
2N/A if ((value_handle = scf_value_create(self->handle)) == NULL) {
2N/A scf_property_destroy(prop_handle);
2N/A scf_pg_destroy(pg_handle);
2N/A scf_iter_destroy(iter);
2N/A FREE_INSTANCE();
2N/A PyErr_SetString(NssscfError, "Cannot create value handle");
2N/A return (NULL);
2N/A }
2N/A buflen = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH) + 1;
2N/A if ((buf = (char *)malloc(buflen)) == NULL) {
2N/A scf_value_destroy(value_handle);
2N/A scf_property_destroy(prop_handle);
2N/A scf_pg_destroy(pg_handle);
2N/A scf_iter_destroy(iter);
2N/A FREE_INSTANCE();
2N/A PyErr_SetString(NssscfError, "Memory Error");
2N/A return (NULL);
2N/A }
2N/A /* Always get composed properties using instance name */
2N/A if (instance == NULL) {
2N/A PyErr_SetString(NssscfError, "Uninitialized service name");
2N/A ret = NULL;
2N/A goto err;
2N/A } else {
2N/A instnm = strrchr(instance, ':');
2N/A if (instnm == NULL) {
2N/A PyErr_SetString(NssscfError,
2N/A "Instance name missing");
2N/A ret = NULL;
2N/A goto err;
2N/A }
2N/A instnm++;
2N/A if (scf_service_get_instance(self->svc,
2N/A instnm, self->inst) < 0) {
2N/A PyErr_SetString(NssscfError,
2N/A "Could not get service instance");
2N/A ret = NULL;
2N/A goto err;
2N/A }
2N/A if (scf_instance_get_pg_composed(self->inst, NULL,
2N/A pgname, pg_handle) != 0) {
2N/A PyErr_SetString(NssscfError,
2N/A "Composed property group does not exist");
2N/A ret = NULL;
2N/A goto err;
2N/A }
2N/A }
2N/A /* get property from property group */
2N/A if (scf_pg_get_property(pg_handle, prname, prop_handle) != 0) {
2N/A PyErr_SetString(NssscfError, "Property does not exist");
2N/A ret = NULL;
2N/A goto err;
2N/A }
2N/A if (scf_iter_property_values(iter, prop_handle) < 0) {
2N/A PyErr_SetString(NssscfError,
2N/A "Cannot create property value iterator");
2N/A ret = NULL;
2N/A goto err;
2N/A }
2N/A
2N/A /* setup and iterate properties in property group */
2N/A while (scf_iter_next_value(iter, value_handle) > 0) {
2N/A if (scf_value_get_as_string(value_handle, buf, buflen) < 0)
2N/A continue;
2N/A vallist = __strlist_add(vallist, buf);
2N/A }
2N/A if ((listlen = __strlist_len(vallist)) > 0) {
2N/A if ((pylist = PyList_New(0)) == NULL) {
2N/A PyErr_SetString(NssscfError,
2N/A "Unable to build Property tuple");
2N/A ret = NULL;
2N/A goto err;
2N/A }
2N/A for (l = 0; l < listlen; l++) {
2N/A pyobject = Py_BuildValue("s", vallist[l]);
2N/A if (pyobject == NULL) {
2N/A PyErr_SetString(NssscfError,
2N/A "Unable to build Property tuple");
2N/A ret = NULL;
2N/A goto err;
2N/A }
2N/A if (PyList_Append(pylist, pyobject) < 0) {
2N/A PyErr_SetString(NssscfError,
2N/A "Unable to build Property tuple");
2N/A ret = NULL;
2N/A goto err;
2N/A }
2N/A Py_DECREF(pyobject);
2N/A pyobject = NULL;
2N/A }
2N/A pytuple = PyList_AsTuple(pylist);
2N/A Py_DECREF(pylist);
2N/A pylist = NULL;
2N/A } else {
2N/A pytuple = Py_BuildValue("()");
2N/A }
2N/A ret = pytuple;
2N/Aerr:
2N/A /* ErrStrings (if any) should be set by now */
2N/A if (pyobject)
2N/A Py_DECREF(pyobject);
2N/A if (pylist)
2N/A Py_DECREF(pylist);
2N/A if (buf)
2N/A free((void *)buf);
2N/A FREE_INSTANCE();
2N/A __strlist_free(vallist);
2N/A scf_value_destroy(value_handle);
2N/A scf_property_destroy(prop_handle);
2N/A scf_pg_destroy(pg_handle);
2N/A scf_iter_destroy(iter);
2N/A return (ret);
2N/A}
2N/A
2N/A/*
2N/A * Get Service Property state
2N/A * IN: nothing
2N/A * OUT: String of current property state
2N/A */
2N/A
2N/Astatic PyObject *
2N/ANssscf_getstate(Nssscf_t *self, PyObject *args)
2N/A{
2N/A char *state = __getscf_inststate(self);
2N/A PyObject *pyobject = NULL;
2N/A
2N/A if (state == NULL) {
2N/A PyErr_SetString(NssscfError, "Service is not an instance");
2N/A return (NULL);
2N/A }
2N/A pyobject = Py_BuildValue("s", state);
2N/A free((void *)state);
2N/A return (pyobject);
2N/A}
2N/A
2N/A/*
2N/A * Get Service instance fmri
2N/A * IN: nothing
2N/A * OUT: String of current instance fmri
2N/A */
2N/A
2N/Astatic PyObject *
2N/ANssscf_getinstfmri(Nssscf_t *self, PyObject *args)
2N/A{
2N/A char *instance = __getscf_instfmri(self);
2N/A PyObject *pyobject = NULL;
2N/A
2N/A if (instance == NULL) {
2N/A PyErr_SetString(NssscfError, "Service is not an instance");
2N/A return (NULL);
2N/A }
2N/A pyobject = Py_BuildValue("s", instance);
2N/A FREE_INSTANCE();
2N/A return (pyobject);
2N/A}
2N/A
2N/A /* Test Operations */
2N/A/*
2N/A * Check Service state
2N/A * IN: nothing
2N/A * OUT: True/False
2N/A */
2N/A
2N/Astatic PyObject *
2N/ANssscf_isenabled(Nssscf_t *self, PyObject *args)
2N/A{
2N/A char *state = __getscf_inststate(self);
2N/A int enabled = 0;
2N/A
2N/A if (state == NULL) {
2N/A PyErr_SetString(NssscfError, "Service is not an instance");
2N/A return (NULL);
2N/A }
2N/A if (strcmp(state, SCF_STATE_STRING_ONLINE) == 0)
2N/A enabled++;
2N/A free((void *)state);
2N/A if (enabled) {
2N/A Py_RETURN_TRUE;
2N/A }
2N/A Py_RETURN_FALSE;
2N/A}
2N/A
2N/A/*
2N/A * Test to see if a property group exists in the service
2N/A * IN: args is a property group string
2N/A * OUT: True/False
2N/A */
2N/Astatic PyObject *
2N/ANssscf_pgexists(Nssscf_t *self, PyObject *args)
2N/A{
2N/A char *instance = __getscf_instname(self);
2N/A char *instnm;
2N/A scf_propertygroup_t *pg_handle;
2N/A const char *pg;
2N/A int ret;
2N/A
2N/A if (!PyArg_ParseTuple(args, "s", &pg)) {
2N/A FREE_INSTANCE();
2N/A PyErr_SetString(PyExc_ValueError,
2N/A "The argument must be a string");
2N/A return (NULL);
2N/A }
2N/A /* do work */
2N/A pg_handle = scf_pg_create(self->handle);
2N/A if (instance == NULL) {
2N/A ret = scf_service_get_pg(self->svc, pg, pg_handle);
2N/A } else {
2N/A instnm = strrchr(instance, ':');
2N/A if (instnm == NULL) {
2N/A free((void *)instance);
2N/A scf_pg_destroy(pg_handle);
2N/A PyErr_SetString(NssscfError,
2N/A "Service is not an instance");
2N/A return (NULL);
2N/A }
2N/A instnm++;
2N/A if (scf_service_get_instance(self->svc,
2N/A instnm, self->inst) < 0) {
2N/A free((void *)instance);
2N/A scf_pg_destroy(pg_handle);
2N/A PyErr_SetString(NssscfError,
2N/A "Service is not an instance");
2N/A return (NULL);
2N/A }
2N/A ret = scf_instance_get_pg(self->inst, pg, pg_handle);
2N/A }
2N/A if (ret == 0) {
2N/A /* ensure we have the most recent pg */
2N/A (void) scf_pg_update(pg_handle);
2N/A }
2N/A scf_pg_destroy(pg_handle);
2N/A FREE_INSTANCE();
2N/A if (ret == 0) {
2N/A Py_RETURN_TRUE;
2N/A }
2N/A Py_RETURN_FALSE;
2N/A}
2N/A
2N/A /* Add/Modify/Delete Operations */
2N/A/*
2N/A * Create a property group given a name and type
2N/A * IN: arg1 is a property group name, arg2 is the type
2N/A * OUT: True/False
2N/A */
2N/Astatic PyObject *
2N/ANssscf_add_pg(Nssscf_t *self, PyObject *args)
2N/A{
2N/A char *instance = __getscf_instname(self);
2N/A char *instnm;
2N/A scf_propertygroup_t *pg_handle;
2N/A const char *pg, *pgtype;
2N/A int ret;
2N/A
2N/A if (!PyArg_ParseTuple(args, "ss", &pg, &pgtype)) {
2N/A FREE_INSTANCE();
2N/A PyErr_SetString(PyExc_ValueError,
2N/A "The arguments must be strings");
2N/A return (NULL);
2N/A }
2N/A /* do work */
2N/A pg_handle = scf_pg_create(self->handle);
2N/A if (instance == NULL) {
2N/A ret = scf_service_add_pg(self->svc, pg, pgtype,
2N/A 0, pg_handle);
2N/A } else {
2N/A instnm = strrchr(instance, ':');
2N/A if (instnm == NULL) {
2N/A FREE_INSTANCE();
2N/A scf_pg_destroy(pg_handle);
2N/A PyErr_SetString(NssscfError,
2N/A "Service is not an instance");
2N/A return (NULL);
2N/A }
2N/A instnm++;
2N/A if (scf_service_get_instance(self->svc,
2N/A instnm, self->inst) < 0) {
2N/A FREE_INSTANCE();
2N/A scf_pg_destroy(pg_handle);
2N/A PyErr_SetString(NssscfError,
2N/A "Service is not an instance");
2N/A return (NULL);
2N/A }
2N/A ret = scf_instance_add_pg(self->inst, pg, pgtype,
2N/A 0, pg_handle);
2N/A }
2N/A scf_pg_destroy(pg_handle);
2N/A FREE_INSTANCE();
2N/A if (ret == 0) {
2N/A Py_RETURN_TRUE;
2N/A }
2N/A Py_RETURN_FALSE;
2N/A}
2N/A
2N/A/*
2N/A * Delete a property group and it's contents
2N/A * IN: arg is a property group string
2N/A * OUT: True/False
2N/A */
2N/Astatic PyObject *
2N/ANssscf_delete_pg(Nssscf_t *self, PyObject *args)
2N/A{
2N/A char *instance = __getscf_instname(self);
2N/A char *instnm;
2N/A scf_propertygroup_t *pg_handle;
2N/A const char *pg;
2N/A int ret;
2N/A
2N/A if (!PyArg_ParseTuple(args, "s", &pg)) {
2N/A FREE_INSTANCE();
2N/A PyErr_SetString(PyExc_ValueError,
2N/A "The argument must be a string");
2N/A return (NULL);
2N/A }
2N/A /* do work */
2N/A pg_handle = scf_pg_create(self->handle);
2N/A if (instance == NULL) {
2N/A ret = scf_service_get_pg(self->svc, pg, pg_handle);
2N/A } else {
2N/A instnm = strrchr(instance, ':');
2N/A if (instnm == NULL) {
2N/A FREE_INSTANCE();
2N/A PyErr_SetString(NssscfError,
2N/A "Service is not an instance");
2N/A return (NULL);
2N/A }
2N/A instnm++;
2N/A if (scf_service_get_instance(self->svc,
2N/A instnm, self->inst) < 0) {
2N/A FREE_INSTANCE();
2N/A scf_pg_destroy(pg_handle);
2N/A PyErr_SetString(NssscfError,
2N/A "Service is not an instance");
2N/A return (NULL);
2N/A }
2N/A ret = scf_instance_get_pg(self->inst, pg, pg_handle);
2N/A }
2N/A if (ret == 0) {
2N/A ret = scf_pg_delete(pg_handle);
2N/A } else {
2N/A ret = 0; /* true if no property group exists */
2N/A }
2N/A scf_pg_destroy(pg_handle);
2N/A FREE_INSTANCE();
2N/A if (ret == 0) {
2N/A Py_RETURN_TRUE;
2N/A }
2N/A Py_RETURN_FALSE;
2N/A}
2N/A
2N/A/*
2N/A * Delcust (delete customizations) on a service and instance property group
2N/A * IN: arg is a property group string
2N/A * OUT: True/False
2N/A */
2N/Astatic PyObject *
2N/ANssscf_delcust_pg(Nssscf_t *self, PyObject *args)
2N/A{
2N/A char *instance = __getscf_instfmri(self);
2N/A char *instnm = NULL;
2N/A scf_propertygroup_t *pg_handle;
2N/A const char *pg;
2N/A int ret;
2N/A
2N/A if (!PyArg_ParseTuple(args, "s", &pg)) {
2N/A PyErr_SetString(PyExc_ValueError,
2N/A "The argument must be a string");
2N/A return (NULL);
2N/A }
2N/A /* do instance work - for effect */
2N/A if (instance != NULL) {
2N/A instnm = strrchr(instance, ':');
2N/A if (instnm != NULL) {
2N/A instnm++;
2N/A if (scf_service_get_instance(self->svc,
2N/A instnm, self->inst) == 0) {
2N/A pg_handle = scf_pg_create(self->handle);
2N/A if (scf_instance_get_pg(self->inst,
2N/A pg, pg_handle) == 0) {
2N/A /* delete it if possible */
2N/A (void) scf_pg_delcust(pg_handle);
2N/A }
2N/A scf_pg_destroy(pg_handle);
2N/A }
2N/A }
2N/A }
2N/A /* do service work */
2N/A pg_handle = scf_pg_create(self->handle);
2N/A ret = scf_service_get_pg(self->svc, pg, pg_handle);
2N/A if (ret == 0) {
2N/A ret = scf_pg_delcust(pg_handle);
2N/A } else {
2N/A ret = 0; /* true if no property group exists */
2N/A }
2N/A scf_pg_destroy(pg_handle);
2N/A if (ret == 0) {
2N/A Py_RETURN_TRUE;
2N/A }
2N/A Py_RETURN_FALSE;
2N/A}
2N/A
2N/A/*
2N/A * Create or add a property value given a name, type and value
2N/A * IN: arg1 is a property group name, arg2 is the property
2N/A * arg3 is the type and arg4 is the value. Value may be either
2N/A * a string or a tuple/list of strings. The property is
2N/A * created if it does not previously exist.
2N/A * OUT: True or Exception
2N/A */
2N/Astatic PyObject *
2N/ANssscf_set_propvalue(Nssscf_t *self, PyObject *args)
2N/A{
2N/A char *instance = __getscf_instname(self);
2N/A char *instnm;
2N/A scf_propertygroup_t *pg_handle = NULL;
2N/A scf_property_t *prop_handle = NULL;
2N/A scf_value_t *value_handle = NULL;
2N/A scf_transaction_t *tx = NULL;
2N/A scf_transaction_entry_t *ent = NULL;
2N/A scf_type_t ptype;
2N/A const char *pgname, *propname, *proptype;
2N/A PyObject *obj = NULL;
2N/A PyObject *item;
2N/A char *value, **vallist = NULL;
2N/A int n, i;
2N/A int badadd = 0;
2N/A int new_prop = 0;
2N/A int ret = -1; /* fail by default */
2N/A
2N/A if (!PyArg_ParseTuple(args, "sssO",
2N/A &pgname, &propname, &proptype, &obj)) {
2N/A FREE_INSTANCE();
2N/A PyErr_SetString(PyExc_ValueError, "Invalid arguments");
2N/A return (NULL);
2N/A }
2N/A /* examine obj for string or sequence */
2N/A if (obj == NULL) {
2N/A FREE_INSTANCE();
2N/A PyErr_SetString(PyExc_ValueError, "Invalid arguments");
2N/A return (NULL);
2N/A } else if (PyString_Check(obj)) {
2N/A value = PyString_AsString(obj);
2N/A vallist = __strlist_add(vallist, value);
2N/A } else if (PyTuple_Check(obj) || PyList_Check(obj)) {
2N/A if ((n = PySequence_Length(obj)) > 0) {
2N/A for (i = 0; i < n; i++) {
2N/A item = PySequence_GetItem(obj, i);
2N/A if (item == NULL) {
2N/A PyErr_SetString(PyExc_ValueError,
2N/A "Invalid tuple");
2N/A badadd = -1;
2N/A break;
2N/A }
2N/A if (!PyString_Check(item)) {
2N/A PyErr_SetString(PyExc_ValueError,
2N/A "Tuple value not a string");
2N/A badadd = -1;
2N/A break;
2N/A }
2N/A value = PyString_AsString(item);
2N/A vallist = __strlist_add(vallist, value);
2N/A }
2N/A }
2N/A } else {
2N/A FREE_INSTANCE();
2N/A PyErr_SetString(PyExc_ValueError,
2N/A "The value must be a string or tuple of strings");
2N/A return (NULL);
2N/A }
2N/A if (vallist == NULL || badadd) {
2N/A __strlist_free(vallist);
2N/A FREE_INSTANCE();
2N/A PyErr_SetString(PyExc_ValueError,
2N/A "The value must be a string or tuple of strings");
2N/A return (NULL);
2N/A }
2N/A /* do work */
2N/A if ((pg_handle = scf_pg_create(self->handle)) == NULL) {
2N/A __strlist_free(vallist);
2N/A FREE_INSTANCE();
2N/A PyErr_SetString(NssscfError, "Cannot create pg handle");
2N/A return (NULL);
2N/A }
2N/A if ((prop_handle = scf_property_create(self->handle)) == NULL) {
2N/A scf_pg_destroy(pg_handle);
2N/A __strlist_free(vallist);
2N/A FREE_INSTANCE();
2N/A PyErr_SetString(NssscfError, "Cannot create property handle");
2N/A return (NULL);
2N/A }
2N/A /* get property group from service */
2N/A if (instance == NULL) {
2N/A if (scf_service_get_pg(self->svc, pgname, pg_handle) != 0) {
2N/A PyErr_SetString(NssscfError,
2N/A "Property group does not exist");
2N/A ret = -1;
2N/A goto err;
2N/A }
2N/A } else {
2N/A instnm = strrchr(instance, ':');
2N/A if (instnm == NULL) {
2N/A PyErr_SetString(NssscfError,
2N/A "Service is not an instance");
2N/A ret = -1;
2N/A goto err;
2N/A }
2N/A instnm++;
2N/A if (scf_service_get_instance(self->svc,
2N/A instnm, self->inst) < 0) {
2N/A PyErr_SetString(NssscfError,
2N/A "Service is not an instance");
2N/A ret = -1;
2N/A goto err;
2N/A }
2N/A if (scf_instance_get_pg_composed(self->inst, NULL,
2N/A pgname, pg_handle) != 0) {
2N/A PyErr_SetString(NssscfError,
2N/A "Property group does not exist");
2N/A ret = -1;
2N/A goto err;
2N/A }
2N/A }
2N/A /* get property from property group */
2N/A if (scf_pg_get_property(pg_handle, propname, prop_handle) != 0) {
2N/A if (scf_error() == SCF_ERROR_NOT_FOUND)
2N/A new_prop = 1;
2N/A else {
2N/A PyErr_SetString(NssscfError,
2N/A "Get property error");
2N/A ret = -1;
2N/A goto err;
2N/A }
2N/A }
2N/A /* setup transaction */
2N/A if ((tx = scf_transaction_create(self->handle)) == NULL ||
2N/A (ent = scf_entry_create(self->handle)) == NULL) {
2N/A PyErr_SetString(NssscfError,
2N/A "Could not create transaction or transaction entry");
2N/A ret = -1;
2N/A goto err;
2N/A }
2N/A if (scf_transaction_start(tx, pg_handle) == -1) {
2N/A PyErr_SetString(NssscfError,
2N/A "Could not start transaction");
2N/A ret = -1;
2N/A goto err;
2N/A }
2N/A /* setup/create property */
2N/A ptype = scf_string_to_type(proptype);
2N/A if (ptype == SCF_TYPE_INVALID) {
2N/A PyErr_SetString(NssscfError,
2N/A "Invalid property type");
2N/A ret = -1;
2N/A goto err;
2N/A }
2N/A if (new_prop) {
2N/A if (scf_transaction_property_new(tx, ent, propname,
2N/A ptype) == -1) {
2N/A PyErr_SetString(NssscfError,
2N/A "Could not create new property transaction");
2N/A ret = -1;
2N/A goto err;
2N/A }
2N/A } else if (scf_transaction_property_change(tx, ent, propname,
2N/A ptype) == -1) {
2N/A PyErr_SetString(NssscfError,
2N/A "Could not create change property transaction");
2N/A ret = -1;
2N/A goto err;
2N/A }
2N/A
2N/A /* add value(s) */
2N/A for (i = 0; vallist[i] != NULL; i++) {
2N/A if ((value_handle = scf_value_create(self->handle)) == NULL) {
2N/A PyErr_SetString(NssscfError,
2N/A "Cannot create value handle");
2N/A ret = -1;
2N/A goto err;
2N/A }
2N/A if (scf_value_set_from_string(value_handle,
2N/A ptype, vallist[i]) == -1) {
2N/A PyErr_SetString(NssscfError,
2N/A "Cannot create value string");
2N/A ret = -1;
2N/A goto err;
2N/A }
2N/A if (scf_entry_add_value(ent, value_handle) != 0) {
2N/A PyErr_SetString(NssscfError,
2N/A "Cannot add string to entry");
2N/A ret = -1;
2N/A goto err;
2N/A }
2N/A }
2N/A
2N/A /* commit */
2N/A if (scf_transaction_commit(tx) > 0) {
2N/A ret = 0; /* Successful commit */
2N/A } else {
2N/A PyErr_SetString(NssscfError,
2N/A "Cannot commit values to property");
2N/A ret = -1;
2N/A }
2N/A scf_transaction_reset(tx);
2N/A scf_entry_destroy_children(ent);
2N/A if (scf_pg_update(pg_handle) == -1) {
2N/A PyErr_SetString(NssscfError,
2N/A "Property group update failure");
2N/A ret = -1;
2N/A }
2N/Aerr:
2N/A scf_transaction_destroy(tx);
2N/A scf_value_destroy(value_handle);
2N/A scf_property_destroy(prop_handle);
2N/A scf_pg_destroy(pg_handle);
2N/A __strlist_free(vallist);
2N/A FREE_INSTANCE();
2N/A if (ret == 0) {
2N/A Py_RETURN_TRUE;
2N/A }
2N/A return (NULL);
2N/A}
2N/A
2N/A /* Admin Operations */
2N/A/*
2N/A * Generic Service state changer
2N/A * IN: fmri and new state (fmri defaults to fmri:default if not an instance)
2N/A * OUT: True/False
2N/A */
2N/A
2N/Atypedef enum {
2N/A OP_ENABLE, OP_DISABLE, OP_REFRESH, OP_RESTART,
2N/A OP_MAINTAIN, OP_DEGRADE, OP_RESTORE
2N/A} nssscf_state_t;
2N/A
2N/Astatic PyObject *
2N/ANssscf_change_state(Nssscf_t *self, nssscf_state_t state)
2N/A{
2N/A char *instance = __getscf_instfmri(self);
2N/A int success;
2N/A
2N/A if (instance == NULL) {
2N/A PyErr_SetString(NssscfError, "Service is not an instance");
2N/A return (NULL);
2N/A }
2N/A switch (state) {
2N/A case OP_ENABLE:
2N/A success = smf_enable_instance(instance, 0);
2N/A break;
2N/A case OP_DISABLE:
2N/A success = smf_disable_instance(instance, 0);
2N/A break;
2N/A case OP_REFRESH:
2N/A success = smf_refresh_instance(instance);
2N/A break;
2N/A case OP_RESTART:
2N/A success = smf_restart_instance(instance);
2N/A break;
2N/A case OP_MAINTAIN:
2N/A success = smf_maintain_instance(instance, SMF_IMMEDIATE);
2N/A break;
2N/A case OP_DEGRADE:
2N/A success = smf_degrade_instance(instance, SMF_IMMEDIATE);
2N/A break;
2N/A case OP_RESTORE:
2N/A success = smf_restore_instance(instance);
2N/A break;
2N/A default:
2N/A success = 0;
2N/A }
2N/A
2N/A FREE_INSTANCE();
2N/A if (success == 0) {
2N/A Py_RETURN_TRUE;
2N/A }
2N/A Py_RETURN_FALSE;
2N/A}
2N/A
2N/Astatic PyObject *
2N/ANssscf_inst_enable(Nssscf_t *self, PyObject *args)
2N/A{
2N/A return (Nssscf_change_state(self, OP_ENABLE));
2N/A}
2N/A
2N/Astatic PyObject *
2N/ANssscf_inst_disable(Nssscf_t *self, PyObject *args)
2N/A{
2N/A return (Nssscf_change_state(self, OP_DISABLE));
2N/A}
2N/A
2N/Astatic PyObject *
2N/ANssscf_inst_refresh(Nssscf_t *self, PyObject *args)
2N/A{
2N/A return (Nssscf_change_state(self, OP_REFRESH));
2N/A}
2N/A
2N/Astatic PyObject *
2N/ANssscf_inst_restart(Nssscf_t *self, PyObject *args)
2N/A{
2N/A return (Nssscf_change_state(self, OP_RESTART));
2N/A}
2N/A
2N/Astatic PyObject *
2N/ANssscf_inst_maintain(Nssscf_t *self, PyObject *args)
2N/A{
2N/A return (Nssscf_change_state(self, OP_MAINTAIN));
2N/A}
2N/A
2N/Astatic PyObject *
2N/ANssscf_inst_degrade(Nssscf_t *self, PyObject *args)
2N/A{
2N/A return (Nssscf_change_state(self, OP_DEGRADE));
2N/A}
2N/A
2N/Astatic PyObject *
2N/ANssscf_inst_restore(Nssscf_t *self, PyObject *args)
2N/A{
2N/A return (Nssscf_change_state(self, OP_RESTORE));
2N/A}
2N/A
2N/Astatic PyObject *
2N/ANssscf_inst_validate(Nssscf_t *self, PyObject *args)
2N/A{
2N/A PyObject *pytuple = NULL;
2N/A char *instance = __getscf_instfmri(self);
2N/A scf_tmpl_errors_t *errs = NULL;
2N/A char *msg = NULL;
2N/A int success;
2N/A
2N/A if (instance == NULL) {
2N/A PyErr_SetString(NssscfError, "Service is not an instance");
2N/A return (NULL);
2N/A }
2N/A success = scf_tmpl_validate_fmri(self->handle, instance,
2N/A NULL, &errs, SCF_TMPL_VALIDATE_FLAG_CURRENT);
2N/A
2N/A if (success == 1 && errs != NULL) {
2N/A scf_tmpl_error_t *err = NULL;
2N/A size_t len = 256; /* initial error buffer size */
2N/A
2N/A msg = (char *)malloc(len);
2N/A while ((err = scf_tmpl_next_error(errs)) != NULL) {
2N/A int ret;
2N/A
2N/A if ((ret = scf_tmpl_strerror(err, msg, len,
2N/A 0)) >= len) {
2N/A len = ret + 1;
2N/A msg = realloc(msg, len);
2N/A if (msg == NULL) {
2N/A PyErr_SetString(NssscfError,
2N/A "Out of memory.\n");
2N/A Py_RETURN_FALSE;
2N/A }
2N/A (void) scf_tmpl_strerror(err, msg, len, 0);
2N/A }
2N/A }
2N/A }
2N/A if (errs != NULL)
2N/A scf_tmpl_errors_destroy(errs);
2N/A FREE_INSTANCE();
2N/A if (success == 0) {
2N/A pytuple = Py_BuildValue("(is)", 0, NULL);
2N/A } else {
2N/A if (msg) {
2N/A pytuple = Py_BuildValue("(is)", -1, msg);
2N/A free(msg);
2N/A } else {
2N/A PyErr_SetString(NssscfError,
2N/A "Unknown Validate Error.\n");
2N/A Py_RETURN_FALSE;
2N/A }
2N/A }
2N/A return (pytuple);
2N/A}
2N/A
2N/A/*
2N/A * =====================================
2N/A * Nssscf Instance structure definitions
2N/A * =====================================
2N/A */
2N/A
2N/Astatic PyGetSetDef Nssscf_getseters[] = {
2N/A { "service", (getter)Nssscf_getservice, (setter)Nssscf_setservice,
2N/A "service name", NULL },
2N/A {NULL} /* Sentinel */
2N/A};
2N/A
2N/Astatic PyMemberDef Nssscf_members[] = {
2N/A {NULL} /* Sentinel */
2N/A};
2N/A
2N/Astatic PyMethodDef Nssscf_methods[] = {
2N/A /* Get Operations */
2N/A { "get_service_pgs", (PyCFunction)Nssscf_get_svcpgs, METH_NOARGS,
2N/A "Get the list of the services property groups" },
2N/A { "get_properties", (PyCFunction)Nssscf_get_pgprops, METH_VARARGS,
2N/A "Get list of properties for a property group (arg1)" },
2N/A { "get_prop_values", (PyCFunction)Nssscf_get_propvals, METH_VARARGS,
2N/A "Get values for property group, property (arg1, arg2)" },
2N/A { "get_state", (PyCFunction)Nssscf_getstate, METH_NOARGS,
2N/A "Get Service state" },
2N/A { "get_instfmri", (PyCFunction)Nssscf_getinstfmri, METH_NOARGS,
2N/A "Get Service instance FMRI. (May be identical to service name)" },
2N/A /* Test Operations */
2N/A { "is_enabled", (PyCFunction)Nssscf_isenabled, METH_NOARGS,
2N/A "Check if service is enabled" },
2N/A { "pg_exists", (PyCFunction)Nssscf_pgexists, METH_VARARGS,
2N/A "True/False if property group (arg1) exists" },
2N/A /* Add/Modify/Delete Operations */
2N/A { "add_pg", (PyCFunction)Nssscf_add_pg, METH_VARARGS,
2N/A "Add a property group given a pgname and pgtype (arg1,arg2)" },
2N/A { "set_propvalue", (PyCFunction)Nssscf_set_propvalue, METH_VARARGS,
2N/A "Set pg/prop to value(s): pg, name type, value or (value...)" },
2N/A { "delete_pg", (PyCFunction)Nssscf_delete_pg, METH_VARARGS,
2N/A "Delete a property group [and it's contents]. (arg1)" },
2N/A { "delcust_pg", (PyCFunction)Nssscf_delcust_pg, METH_VARARGS,
2N/A "Delete customizations on a service property group. (arg1)" },
2N/A /* Admin Operations */
2N/A { "enable", (PyCFunction)Nssscf_inst_enable, METH_NOARGS,
2N/A "Enable service instance" },
2N/A { "disable", (PyCFunction)Nssscf_inst_disable, METH_NOARGS,
2N/A "Disable service instance" },
2N/A { "refresh", (PyCFunction)Nssscf_inst_refresh, METH_NOARGS,
2N/A "Refresh service instance" },
2N/A { "restart", (PyCFunction)Nssscf_inst_restart, METH_NOARGS,
2N/A "Restart service instance" },
2N/A { "maintain", (PyCFunction)Nssscf_inst_maintain, METH_NOARGS,
2N/A "Immediately send service instance to maintenance state" },
2N/A { "degrade", (PyCFunction)Nssscf_inst_degrade, METH_NOARGS,
2N/A "Immediately send service instance to degraded state" },
2N/A { "restore", (PyCFunction)Nssscf_inst_restore, METH_NOARGS,
2N/A "Restore service instance" },
2N/A { "validate", (PyCFunction)Nssscf_inst_validate, METH_NOARGS,
2N/A "Validate current service instance configuration" },
2N/A {NULL} /* Sentinel */
2N/A};
2N/A
2N/Astatic PyTypeObject nssscf_NssscfType = {
2N/A PyObject_HEAD_INIT(NULL)
2N/A 0, /* ob_size */
2N/A "nssscf.Nssscf", /* tp_name */
2N/A sizeof (Nssscf_t), /* tp_basicsize */
2N/A 0, /* tp_itemsize */
2N/A (destructor)Nssscf_dealloc, /* tp_dealloc */
2N/A 0, /* tp_print */
2N/A 0, /* tp_getattr */
2N/A 0, /* tp_setattr */
2N/A 0, /* tp_compare */
2N/A 0, /* tp_repr */
2N/A 0, /* tp_as_number */
2N/A 0, /* tp_as_sequence */
2N/A 0, /* tp_as_mapping */
2N/A 0, /* tp_hash */
2N/A 0, /* tp_call */
2N/A 0, /* tp_str */
2N/A 0, /* tp_getattro */
2N/A 0, /* tp_setattro */
2N/A 0, /* tp_as_buffer */
2N/A Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
2N/A "Nssscf objects", /* tp_doc */
2N/A 0, /* tp_traverse */
2N/A 0, /* tp_clear */
2N/A 0, /* tp_richcompare */
2N/A 0, /* tp_weaklistoffset */
2N/A 0, /* tp_iter */
2N/A 0, /* tp_iternext */
2N/A Nssscf_methods, /* tp_methods */
2N/A Nssscf_members, /* tp_members */
2N/A Nssscf_getseters, /* tp_getset */
2N/A 0, /* tp_base */
2N/A 0, /* tp_dict */
2N/A 0, /* tp_descr_get */
2N/A 0, /* tp_descr_set */
2N/A 0, /* tp_dictoffset */
2N/A (initproc)Nssscf_init, /* tp_init */
2N/A 0, /* tp_alloc */
2N/A Nssscf_new, /* tp_new */
2N/A};
2N/A
2N/A/*
2N/A * =============================
2N/A * Nssscf library Initialization
2N/A * =============================
2N/A */
2N/A
2N/Astatic PyMethodDef NssscfMethods[] = {
2N/A { "ns1_convert", (PyCFunction)Nssscf_ns1_convert, METH_VARARGS,
2N/A "SUNW Project Private" },
2N/A { NULL, NULL, 0, NULL } /* Sentinel */
2N/A};
2N/A
2N/APyMODINIT_FUNC
2N/Ainitnssscf(void)
2N/A{
2N/A PyObject *m;
2N/A
2N/A if (PyType_Ready(&nssscf_NssscfType) < 0)
2N/A return;
2N/A
2N/A m = Py_InitModule("nssscf", NssscfMethods);
2N/A if (m == NULL)
2N/A return;
2N/A
2N/A /* Create Nsscf Exception */
2N/A NssscfError = PyErr_NewException("nssscf.error", NULL, NULL);
2N/A Py_INCREF(NssscfError);
2N/A (void) PyModule_AddObject(m, "error", NssscfError);
2N/A
2N/A /* Create Nssscf Module */
2N/A Py_INCREF(&nssscf_NssscfType);
2N/A (void) PyModule_AddObject(m, "Nssscf", (PyObject *)&nssscf_NssscfType);
2N/A}
2N/A
2N/A
2N/A/*
2N/A * ===============================
2N/A * Nssscf library helper functions
2N/A * ===============================
2N/A */
2N/A
2N/Astatic int
2N/A__strlist_len(char **list)
2N/A{
2N/A int count = 0;
2N/A
2N/A if (list == NULL)
2N/A return (0);
2N/A for (; *list != NULL; count++, list++)
2N/A ;
2N/A return (count);
2N/A}
2N/A
2N/Astatic char **
2N/A__strlist_add(char **list, const char *string)
2N/A{
2N/A int len;
2N/A char *s, **nl;
2N/A
2N/A if (string == NULL)
2N/A return (list);
2N/A if ((s = strdup(string)) == NULL)
2N/A return (list);
2N/A if (list == NULL) {
2N/A nl = (char **)calloc(2, sizeof (char *));
2N/A if (nl == NULL) {
2N/A free((void *)s);
2N/A return (NULL);
2N/A }
2N/A nl[0] = s;
2N/A return (nl);
2N/A }
2N/A len = __strlist_len(list);
2N/A nl = (char **) realloc((void *)list, sizeof (char *) * (len + 2));
2N/A if (nl == NULL)
2N/A return (NULL);
2N/A nl[len] = s;
2N/A nl[len+1] = NULL;
2N/A return (nl);
2N/A}
2N/A
2N/Astatic void __strlist_free(char **list)
2N/A{
2N/A char **nl;
2N/A if (list == NULL)
2N/A return;
2N/A for (nl = list; *nl != NULL; nl++)
2N/A free((void *)(*nl));
2N/A free((void *)list);
2N/A}
2N/A
2N/A/*
2N/A * Get the full AS-IS service name. [svc:/]service[:instance]
2N/A * caller must prune if/as needed. Caller must free string.
2N/A */
2N/A
2N/Astatic char *
2N/A__getscf_svcname(PyObject *service)
2N/A{
2N/A char *svcstr = NULL;
2N/A char *svcn;
2N/A
2N/A if ((svcstr = PyString_AsString(service)) == NULL)
2N/A return (NULL);
2N/A if (*svcstr == '\0')
2N/A return (NULL);
2N/A if ((svcn = strdup(svcstr)) == NULL)
2N/A return (NULL);
2N/A return (svcn);
2N/A}
2N/A
2N/A/*
2N/A * Get the service name if it is an instance, NULL otherwise
2N/A * Caller must free string.
2N/A */
2N/Astatic char *
2N/A__getscf_instname(Nssscf_t *self)
2N/A{
2N/A char *svcname, *svcn;
2N/A
2N/A if ((svcn = __getscf_svcname(self->service)) == NULL)
2N/A return (NULL);
2N/A svcname = svcn;
2N/A if (strncmp("svc:/", svcname, 5) == 0)
2N/A svcname += 5; /* trim svc:/ if provided */
2N/A if (strchr(svcname, ':') != NULL)
2N/A return (svcn); /* service has an instance name */
2N/A free((void *)svcn); /* free strdup storage */
2N/A return (NULL);
2N/A}
2N/A
2N/A/*
2N/A * Get the service name if it is not and instance, append :default
2N/A * to it's name. Caller must free string.
2N/A */
2N/Astatic char *
2N/A__getscf_instfmri(Nssscf_t *self)
2N/A{
2N/A char *svcname, *svcn;
2N/A int newlen;
2N/A
2N/A if ((svcn = __getscf_svcname(self->service)) == NULL)
2N/A return (NULL);
2N/A svcname = svcn;
2N/A if (strncmp("svc:/", svcname, 5) == 0)
2N/A svcname += 5; /* trim svc:/ if provided */
2N/A if (strchr(svcname, ':') != NULL)
2N/A return (svcn); /* service is an instance name */
2N/A newlen = strlen(svcn) + 8 + 1; /* svcn + ":default" + NUL */
2N/A if ((svcname = realloc(svcn, newlen)) == NULL)
2N/A return (NULL); /* storage problem return NULL */
2N/A (void) strlcat(svcname, ":default", newlen);
2N/A return (svcname);
2N/A}
2N/A
2N/A/*
2N/A * Sets the Python instance's smf service handle
2N/A */
2N/Astatic int
2N/A__setscf_svc(Nssscf_t *self, PyObject *service)
2N/A{
2N/A char *svcname, *svcn, *inst;
2N/A int ret;
2N/A
2N/A if ((svcn = __getscf_svcname(service)) == NULL)
2N/A return (-1);
2N/A svcname = svcn;
2N/A if (strncmp("svc:/", svcname, 5) == 0)
2N/A svcname += 5; /* trim svc:/ if provided */
2N/A if ((inst = strchr(svcname, ':')) != NULL) {
2N/A *inst = '\0'; /* trim instance if provided */
2N/A }
2N/A ret = scf_scope_get_service(self->scope, svcname, self->svc);
2N/A free((void *)svcn); /* free strdup storage */
2N/A return (ret);
2N/A}
2N/A
2N/A/*
2N/A * Given a service name, if it is an instance, return the
2N/A * current state. If service is not aninstance try fmri:default'
2N/A * NULL otherwise
2N/A * Caller must free string.
2N/A */
2N/Astatic char *
2N/A__getscf_inststate(Nssscf_t *self)
2N/A{
2N/A char *instance = __getscf_instfmri(self);
2N/A char *state;
2N/A
2N/A if (instance == NULL) {
2N/A PyErr_SetString(NssscfError, "Service is not an instance");
2N/A return (NULL);
2N/A }
2N/A state = smf_get_state(instance);
2N/A FREE_INSTANCE();
2N/A return (state);
2N/A}
2N/A
2N/A/*
2N/A * NS1 encrypt/decrypt APIs
2N/A */
2N/A
2N/A#include "ns_crypt.c"
2N/A
2N/Astatic PyObject *
2N/ANssscf_ns1_convert(Nssscf_t *self, PyObject *args, PyObject *kwds)
2N/A{
2N/A const char *input;
2N/A char *output;
2N/A PyObject *ret = NULL;
2N/A if (!PyArg_ParseTuple(args, "s", &input)) {
2N/A PyErr_SetString(PyExc_ValueError,
2N/A "Argument must be a string");
2N/A return (NULL);
2N/A }
2N/A if (strncmp("{NS1}", input, 5) == 0) { /* decode */
2N/A output = dvalue((char *)input);
2N/A } else { /* encode */
2N/A output = evalue((char *)input);
2N/A }
2N/A if (output == NULL) {
2N/A PyErr_SetString(PyExc_ValueError,
2N/A "Illegal value");
2N/A return (NULL);
2N/A }
2N/A ret = Py_BuildValue("s", output);
2N/A free(output);
2N/A return (ret);
2N/A}