1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2012 Joshua M. Clulow <josh@sysmgr.org>
  24  */
  25 
  26 #include <stdio.h>
  27 #include <stdlib.h>
  28 #include <unistd.h>
  29 #include <string.h>
  30 #include <err.h>
  31 #include <limits.h>
  32 #include <libscf.h>
  33 
  34 #include "utils.h"
  35 #include "scf.h"
  36 
  37 static char *fmri;
  38 static scf_handle_t *scf;
  39 static scf_instance_t *inst;
  40 static scf_propertygroup_t *pg;
  41 
  42 /*
  43  * Initialise our connection to smf(5).  Returns:
  44  *    0 on success
  45  *   <0 for any failure
  46  *   -2 if we believe we're not actually running under smf(5)
  47  */
  48 int
  49 init_scf(void)
  50 {
  51         int rc = -1;
  52         int fmrisz;
  53 
  54         scf = scf_handle_create(SCF_VERSION);
  55         if (scf == NULL)
  56                 return (-1);
  57         if (scf_handle_bind(scf) != 0)
  58                 goto cleanup0;
  59 
  60         if (getenv("SMF_TEST_FMRI") != NULL) {
  61                 fprintf(stderr, "DEBUG: smf test mode engaged\n");
  62                 fmri = strdup(getenv("SMF_TEST_FMRI"));
  63                 goto have_fmri;
  64         }
  65 
  66         fmrisz = scf_myname(scf, NULL, 0);
  67         if (fmrisz == -1) {
  68                 if (scf_error() == SCF_ERROR_NOT_SET) {
  69                         rc = -2;
  70                 }
  71                 goto cleanup1;
  72         }
  73         fmri = xmalloc(fmrisz + 1);
  74         fmrisz = scf_myname(scf, fmri, fmrisz + 1);
  75         if (fmrisz == -1)
  76                 goto cleanup2;
  77 
  78 have_fmri:
  79 
  80         if ((inst = scf_instance_create(scf)) == NULL ||
  81             (pg = scf_pg_create(scf)) == NULL)
  82                 goto cleanup3;
  83 
  84         if (scf_handle_decode_fmri(scf, fmri, NULL, NULL, inst,
  85             NULL, NULL, SCF_DECODE_FMRI_EXACT) != 0)
  86                 goto cleanup3;
  87 
  88         if (scf_instance_get_pg_composed(inst, NULL, "config", pg) != 0)
  89                 goto cleanup3;
  90 
  91         return (0);
  92 
  93 cleanup3:
  94         if (pg != NULL) {
  95                 scf_pg_destroy(pg);
  96                 pg = NULL;
  97         }
  98         if (inst != NULL) {
  99                 scf_instance_destroy(inst);
 100                 inst = NULL;
 101         }
 102 cleanup2:
 103         free(fmri);
 104         fmri = NULL;
 105 cleanup1:
 106         (void) scf_handle_unbind(scf);
 107 cleanup0:
 108         (void) scf_handle_destroy(scf);
 109         scf = NULL;
 110         return (rc);
 111 }
 112 
 113 void
 114 fini_scf(void)
 115 {
 116         (void) scf_pg_destroy(pg);
 117         pg = NULL;
 118         (void) scf_instance_destroy(inst);
 119         inst = NULL;
 120         free(fmri);
 121         fmri = NULL;
 122         (void) scf_handle_unbind(scf);
 123         (void) scf_handle_destroy(scf);
 124         scf = NULL;
 125 }
 126 
 127 /*
 128  * Fetch the boolean value of a property from the 'config' property
 129  * group in our smf(5) instance.
 130  * Returns:
 131  *   <0 on failure
 132  *    0 if found and false
 133  *    1 if found and true
 134  */
 135 int
 136 get_config_boolean(char *name)
 137 {
 138         scf_property_t *prop = NULL;
 139         scf_value_t *val = NULL;
 140         uint8_t out;
 141         int rc = -1;
 142 
 143         prop = scf_property_create(scf);
 144         val = scf_value_create(scf);
 145         if (prop == NULL || val == NULL)
 146                 goto cleanup0;
 147 
 148         if (scf_pg_get_property(pg, name, prop) != 0)
 149                 goto cleanup0;
 150 
 151         if (scf_property_is_type(prop, SCF_TYPE_BOOLEAN) != 0)
 152                 goto cleanup0;
 153 
 154         if (scf_property_get_value(prop, val) != 0)
 155                 goto cleanup0;
 156 
 157         if (scf_value_get_boolean(val, &out) != 0)
 158                 goto cleanup0;
 159 
 160         rc = out;
 161 
 162 cleanup0:
 163         if (val != NULL)
 164                 scf_value_destroy(val);
 165         if (prop != NULL)
 166                 scf_property_destroy(prop);
 167 
 168         return (rc);
 169 }
 170 
 171 /*
 172  * Fetch the boolean value of a property from the 'config' property
 173  * group in our smf(5) instance.
 174  * Returns:
 175  *   NULL on failure
 176  *   a NUL-terminated string value on success, caller to free
 177  */
 178 char *
 179 get_config_string(char *name)
 180 {
 181         scf_property_t *prop = NULL;
 182         scf_value_t *val = NULL;
 183         char out[PATH_MAX];
 184         char *rc = NULL;
 185 
 186         prop = scf_property_create(scf);
 187         val = scf_value_create(scf);
 188         if (prop == NULL || val == NULL)
 189                 goto cleanup0;
 190 
 191         if (scf_pg_get_property(pg, name, prop) != 0)
 192                 goto cleanup0;
 193 
 194         if (scf_property_is_type(prop, SCF_TYPE_ASTRING) != 0)
 195                 goto cleanup0;
 196 
 197         if (scf_property_get_value(prop, val) != 0)
 198                 goto cleanup0;
 199 
 200         if (scf_value_get_astring(val, out, sizeof (out)) == -1)
 201                 goto cleanup0;
 202 
 203         rc = xstrdup(out);
 204 
 205 cleanup0:
 206         if (val != NULL)
 207                 scf_value_destroy(val);
 208         if (prop != NULL)
 209                 scf_property_destroy(prop);
 210 
 211         return (rc);
 212 }