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  * Copyright 2012 Joshua M. Clulow <josh@sysmgr.org>
  23  */
  24 
  25 #include <stdio.h>
  26 #include <stdlib.h>
  27 #include <unistd.h>
  28 #include <string.h>
  29 #include <err.h>
  30 
  31 #include <libscf.h>
  32 
  33 #include "cron_scf.h"
  34 
  35 extern void *xmalloc(size_t); /* from funcs.c */
  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         size_t 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 #ifdef DEBUG
  61         if (getenv("SMF_TEST_FMRI") != NULL) {
  62                 printf("DEBUG: smf test mode engaged\n");
  63                 fmri = strdup(getenv("SMF_TEST_FMRI"));
  64                 goto have_fmri;
  65         }
  66 #endif /* DEBUG */
  67 
  68         fmrisz = scf_myname(scf, NULL, 0);
  69         if (fmrisz == -1) {
  70                 if (scf_error() == SCF_ERROR_NOT_SET) {
  71                         rc = -2;
  72                 }
  73                 goto cleanup1;
  74         }
  75         fmri = xmalloc(fmrisz + 1);
  76         fmrisz = scf_myname(scf, fmri, fmrisz + 1);
  77         if (fmrisz == -1)
  78                 goto cleanup2;
  79 
  80 have_fmri:
  81 
  82         if ((inst = scf_instance_create(scf)) == NULL ||
  83             (pg = scf_pg_create(scf)) == NULL)
  84                 goto cleanup3;
  85 
  86         if (scf_handle_decode_fmri(scf, fmri, NULL, NULL, inst,
  87             NULL, NULL, SCF_DECODE_FMRI_EXACT) != 0)
  88                 goto cleanup3;
  89 
  90         if (scf_instance_get_pg_composed(inst, NULL, "config", pg) != 0)
  91                 goto cleanup3;
  92 
  93         return (0);
  94 
  95 cleanup3:
  96         if (pg != NULL) {
  97                 scf_pg_destroy(pg);
  98                 pg = NULL;
  99         }
 100         if (inst != NULL) {
 101                 scf_instance_destroy(inst);
 102                 inst = NULL;
 103         }
 104 cleanup2:
 105         free(fmri);
 106         fmri = NULL;
 107 cleanup1:
 108         (void) scf_handle_unbind(scf);
 109 cleanup0:
 110         (void) scf_handle_destroy(scf);
 111         scf = NULL;
 112         return (rc);
 113 }
 114 
 115 void
 116 fini_scf(void)
 117 {
 118         (void) scf_pg_destroy(pg);
 119         pg = NULL;
 120         (void) scf_instance_destroy(inst);
 121         inst = NULL;
 122         free(fmri);
 123         fmri = NULL;
 124         (void) scf_handle_unbind(scf);
 125         (void) scf_handle_destroy(scf);
 126         scf = NULL;
 127 }
 128 
 129 /*
 130  * Fetch the boolean value of a property from the 'config' property
 131  * group in our smf(5) instance.
 132  * Returns:
 133  *   <0 on failure
 134  *    0 if found and false
 135  *    1 if found and true
 136  */
 137 int
 138 get_config_boolean(char *name)
 139 {
 140         scf_property_t *prop = NULL;
 141         scf_value_t *val = NULL;
 142         uint8_t out;
 143         int rc = -1;
 144 
 145         prop = scf_property_create(scf);
 146         val = scf_value_create(scf);
 147         if (prop == NULL || val == NULL)
 148                 goto cleanup0;
 149 
 150         if (scf_pg_get_property(pg, name, prop) != 0)
 151                 goto cleanup0;
 152 
 153         if (scf_property_is_type(prop, SCF_TYPE_BOOLEAN) != 0)
 154                 goto cleanup0;
 155 
 156         if (scf_property_get_value(prop, val) != 0)
 157                 goto cleanup0;
 158 
 159         if (scf_value_get_boolean(val, &out) != 0)
 160                 goto cleanup0;
 161 
 162         rc = out;
 163 
 164 cleanup0:
 165         if (val != NULL)
 166                 scf_value_destroy(val);
 167         if (prop != NULL)
 168                 scf_property_destroy(prop);
 169 
 170         return (rc);
 171 }