1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include <librestart.h> 30*7c478bd9Sstevel@tonic-gate #include <librestart_priv.h> 31*7c478bd9Sstevel@tonic-gate #include <libscf.h> 32*7c478bd9Sstevel@tonic-gate #include <libscf_priv.h> 33*7c478bd9Sstevel@tonic-gate 34*7c478bd9Sstevel@tonic-gate #include <assert.h> 35*7c478bd9Sstevel@tonic-gate #include <ctype.h> 36*7c478bd9Sstevel@tonic-gate #include <dlfcn.h> 37*7c478bd9Sstevel@tonic-gate #include <errno.h> 38*7c478bd9Sstevel@tonic-gate #include <exec_attr.h> 39*7c478bd9Sstevel@tonic-gate #include <grp.h> 40*7c478bd9Sstevel@tonic-gate #include <libsysevent.h> 41*7c478bd9Sstevel@tonic-gate #include <libuutil.h> 42*7c478bd9Sstevel@tonic-gate #include <limits.h> 43*7c478bd9Sstevel@tonic-gate #include <link.h> 44*7c478bd9Sstevel@tonic-gate #include <malloc.h> 45*7c478bd9Sstevel@tonic-gate #include <pool.h> 46*7c478bd9Sstevel@tonic-gate #include <priv.h> 47*7c478bd9Sstevel@tonic-gate #include <project.h> 48*7c478bd9Sstevel@tonic-gate #include <pthread.h> 49*7c478bd9Sstevel@tonic-gate #include <pwd.h> 50*7c478bd9Sstevel@tonic-gate #include <secdb.h> 51*7c478bd9Sstevel@tonic-gate #include <signal.h> 52*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 53*7c478bd9Sstevel@tonic-gate #include <string.h> 54*7c478bd9Sstevel@tonic-gate #include <syslog.h> 55*7c478bd9Sstevel@tonic-gate #include <sys/corectl.h> 56*7c478bd9Sstevel@tonic-gate #include <sys/machelf.h> 57*7c478bd9Sstevel@tonic-gate #include <sys/task.h> 58*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 59*7c478bd9Sstevel@tonic-gate #include <time.h> 60*7c478bd9Sstevel@tonic-gate #include <unistd.h> 61*7c478bd9Sstevel@tonic-gate 62*7c478bd9Sstevel@tonic-gate #define walkcontext _walkcontext 63*7c478bd9Sstevel@tonic-gate #include <ucontext.h> 64*7c478bd9Sstevel@tonic-gate 65*7c478bd9Sstevel@tonic-gate #define min(a, b) ((a) > (b) ? (b) : (a)) 66*7c478bd9Sstevel@tonic-gate 67*7c478bd9Sstevel@tonic-gate #define MKW_TRUE ":true" 68*7c478bd9Sstevel@tonic-gate #define MKW_KILL ":kill" 69*7c478bd9Sstevel@tonic-gate #define MKW_KILL_PROC ":kill_process" 70*7c478bd9Sstevel@tonic-gate 71*7c478bd9Sstevel@tonic-gate #define ALLOCFAIL ((char *)"Allocation failure.") 72*7c478bd9Sstevel@tonic-gate #define RCBROKEN ((char *)"Repository connection broken.") 73*7c478bd9Sstevel@tonic-gate 74*7c478bd9Sstevel@tonic-gate #define MAX_COMMIT_RETRIES 20 75*7c478bd9Sstevel@tonic-gate #define MAX_COMMIT_RETRY_INT (5 * 1000000) /* 5 seconds */ 76*7c478bd9Sstevel@tonic-gate #define INITIAL_COMMIT_RETRY_INT (10000) /* 1/100th second */ 77*7c478bd9Sstevel@tonic-gate 78*7c478bd9Sstevel@tonic-gate /* 79*7c478bd9Sstevel@tonic-gate * bad_fail() catches bugs in this and lower layers by reporting supposedly 80*7c478bd9Sstevel@tonic-gate * impossible function failures. The NDEBUG case keeps the strings out of the 81*7c478bd9Sstevel@tonic-gate * library but still calls abort() so we can root-cause from the coredump. 82*7c478bd9Sstevel@tonic-gate */ 83*7c478bd9Sstevel@tonic-gate #ifndef NDEBUG 84*7c478bd9Sstevel@tonic-gate #define bad_fail(func, err) { \ 85*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, \ 86*7c478bd9Sstevel@tonic-gate "At %s:%d, %s() failed with unexpected error %d. Aborting.\n", \ 87*7c478bd9Sstevel@tonic-gate __FILE__, __LINE__, (func), (err)); \ 88*7c478bd9Sstevel@tonic-gate abort(); \ 89*7c478bd9Sstevel@tonic-gate } 90*7c478bd9Sstevel@tonic-gate #else 91*7c478bd9Sstevel@tonic-gate #define bad_fail(func, err) abort() 92*7c478bd9Sstevel@tonic-gate #endif 93*7c478bd9Sstevel@tonic-gate 94*7c478bd9Sstevel@tonic-gate struct restarter_event_handle { 95*7c478bd9Sstevel@tonic-gate char *reh_restarter_name; 96*7c478bd9Sstevel@tonic-gate char *reh_delegate_channel_name; 97*7c478bd9Sstevel@tonic-gate evchan_t *reh_delegate_channel; 98*7c478bd9Sstevel@tonic-gate char *reh_delegate_subscriber_id; 99*7c478bd9Sstevel@tonic-gate char *reh_master_channel_name; 100*7c478bd9Sstevel@tonic-gate evchan_t *reh_master_channel; 101*7c478bd9Sstevel@tonic-gate char *reh_master_subscriber_id; 102*7c478bd9Sstevel@tonic-gate int (*reh_handler)(restarter_event_t *); 103*7c478bd9Sstevel@tonic-gate }; 104*7c478bd9Sstevel@tonic-gate 105*7c478bd9Sstevel@tonic-gate struct restarter_event { 106*7c478bd9Sstevel@tonic-gate sysevent_t *re_sysevent; 107*7c478bd9Sstevel@tonic-gate restarter_event_type_t re_type; 108*7c478bd9Sstevel@tonic-gate char *re_instance_name; 109*7c478bd9Sstevel@tonic-gate restarter_event_handle_t *re_event_handle; 110*7c478bd9Sstevel@tonic-gate restarter_instance_state_t re_state; 111*7c478bd9Sstevel@tonic-gate restarter_instance_state_t re_next_state; 112*7c478bd9Sstevel@tonic-gate }; 113*7c478bd9Sstevel@tonic-gate 114*7c478bd9Sstevel@tonic-gate static const char * const allocfail = "Allocation failure.\n"; 115*7c478bd9Sstevel@tonic-gate static const char * const rcbroken = "Repository connection broken.\n"; 116*7c478bd9Sstevel@tonic-gate 117*7c478bd9Sstevel@tonic-gate static int method_context_safety = 0; /* Can safely call pools/projects. */ 118*7c478bd9Sstevel@tonic-gate 119*7c478bd9Sstevel@tonic-gate int ndebug = 1; 120*7c478bd9Sstevel@tonic-gate 121*7c478bd9Sstevel@tonic-gate static void 122*7c478bd9Sstevel@tonic-gate free_restarter_event_handle(struct restarter_event_handle *h) 123*7c478bd9Sstevel@tonic-gate { 124*7c478bd9Sstevel@tonic-gate if (h == NULL) 125*7c478bd9Sstevel@tonic-gate return; 126*7c478bd9Sstevel@tonic-gate 127*7c478bd9Sstevel@tonic-gate /* 128*7c478bd9Sstevel@tonic-gate * Just free the memory -- don't unbind the sysevent handle, 129*7c478bd9Sstevel@tonic-gate * as otherwise events may be lost if this is just a restarter 130*7c478bd9Sstevel@tonic-gate * restart. 131*7c478bd9Sstevel@tonic-gate */ 132*7c478bd9Sstevel@tonic-gate 133*7c478bd9Sstevel@tonic-gate if (h->reh_restarter_name != NULL) 134*7c478bd9Sstevel@tonic-gate free(h->reh_restarter_name); 135*7c478bd9Sstevel@tonic-gate if (h->reh_delegate_channel_name != NULL) 136*7c478bd9Sstevel@tonic-gate free(h->reh_delegate_channel_name); 137*7c478bd9Sstevel@tonic-gate if (h->reh_delegate_subscriber_id != NULL) 138*7c478bd9Sstevel@tonic-gate free(h->reh_delegate_subscriber_id); 139*7c478bd9Sstevel@tonic-gate if (h->reh_master_channel_name != NULL) 140*7c478bd9Sstevel@tonic-gate free(h->reh_master_channel_name); 141*7c478bd9Sstevel@tonic-gate if (h->reh_master_subscriber_id != NULL) 142*7c478bd9Sstevel@tonic-gate free(h->reh_master_subscriber_id); 143*7c478bd9Sstevel@tonic-gate 144*7c478bd9Sstevel@tonic-gate free(h); 145*7c478bd9Sstevel@tonic-gate } 146*7c478bd9Sstevel@tonic-gate 147*7c478bd9Sstevel@tonic-gate static const char * 148*7c478bd9Sstevel@tonic-gate last_part(const char *fmri) 149*7c478bd9Sstevel@tonic-gate { 150*7c478bd9Sstevel@tonic-gate char *last_part; 151*7c478bd9Sstevel@tonic-gate 152*7c478bd9Sstevel@tonic-gate last_part = strrchr(fmri, '/'); 153*7c478bd9Sstevel@tonic-gate last_part++; 154*7c478bd9Sstevel@tonic-gate assert(last_part != NULL); 155*7c478bd9Sstevel@tonic-gate 156*7c478bd9Sstevel@tonic-gate return (last_part); 157*7c478bd9Sstevel@tonic-gate } 158*7c478bd9Sstevel@tonic-gate 159*7c478bd9Sstevel@tonic-gate char * 160*7c478bd9Sstevel@tonic-gate _restarter_get_channel_name(const char *fmri, int type) 161*7c478bd9Sstevel@tonic-gate { 162*7c478bd9Sstevel@tonic-gate const char *name; 163*7c478bd9Sstevel@tonic-gate char *chan_name = malloc(MAX_CHNAME_LEN); 164*7c478bd9Sstevel@tonic-gate char prefix_name[3]; 165*7c478bd9Sstevel@tonic-gate 166*7c478bd9Sstevel@tonic-gate if (chan_name == NULL) 167*7c478bd9Sstevel@tonic-gate return (NULL); 168*7c478bd9Sstevel@tonic-gate 169*7c478bd9Sstevel@tonic-gate if (type == RESTARTER_CHANNEL_DELEGATE) 170*7c478bd9Sstevel@tonic-gate (void) strcpy(prefix_name, "d_"); 171*7c478bd9Sstevel@tonic-gate else if (type == RESTARTER_CHANNEL_MASTER) 172*7c478bd9Sstevel@tonic-gate (void) strcpy(prefix_name, "m_"); 173*7c478bd9Sstevel@tonic-gate else { 174*7c478bd9Sstevel@tonic-gate free(chan_name); 175*7c478bd9Sstevel@tonic-gate return (NULL); 176*7c478bd9Sstevel@tonic-gate } 177*7c478bd9Sstevel@tonic-gate 178*7c478bd9Sstevel@tonic-gate name = last_part(fmri); 179*7c478bd9Sstevel@tonic-gate 180*7c478bd9Sstevel@tonic-gate /* 181*7c478bd9Sstevel@tonic-gate * Should check for [a-z],[A-Z],[0-9],.,_,-,: 182*7c478bd9Sstevel@tonic-gate */ 183*7c478bd9Sstevel@tonic-gate 184*7c478bd9Sstevel@tonic-gate if (snprintf(chan_name, MAX_CHNAME_LEN, "com.sun:scf:%s%s", 185*7c478bd9Sstevel@tonic-gate prefix_name, name) > MAX_CHNAME_LEN) { 186*7c478bd9Sstevel@tonic-gate free(chan_name); 187*7c478bd9Sstevel@tonic-gate return (NULL); 188*7c478bd9Sstevel@tonic-gate } 189*7c478bd9Sstevel@tonic-gate 190*7c478bd9Sstevel@tonic-gate return (chan_name); 191*7c478bd9Sstevel@tonic-gate } 192*7c478bd9Sstevel@tonic-gate 193*7c478bd9Sstevel@tonic-gate int 194*7c478bd9Sstevel@tonic-gate cb(sysevent_t *syse, void *cookie) 195*7c478bd9Sstevel@tonic-gate { 196*7c478bd9Sstevel@tonic-gate restarter_event_handle_t *h = (restarter_event_handle_t *)cookie; 197*7c478bd9Sstevel@tonic-gate restarter_event_t *e; 198*7c478bd9Sstevel@tonic-gate nvlist_t *attr_list = NULL; 199*7c478bd9Sstevel@tonic-gate int ret = 0; 200*7c478bd9Sstevel@tonic-gate 201*7c478bd9Sstevel@tonic-gate e = uu_zalloc(sizeof (restarter_event_t)); 202*7c478bd9Sstevel@tonic-gate if (e == NULL) 203*7c478bd9Sstevel@tonic-gate uu_die(allocfail); 204*7c478bd9Sstevel@tonic-gate e->re_event_handle = h; 205*7c478bd9Sstevel@tonic-gate e->re_sysevent = syse; 206*7c478bd9Sstevel@tonic-gate 207*7c478bd9Sstevel@tonic-gate if (sysevent_get_attr_list(syse, &attr_list) != 0) 208*7c478bd9Sstevel@tonic-gate uu_die(allocfail); 209*7c478bd9Sstevel@tonic-gate 210*7c478bd9Sstevel@tonic-gate if ((nvlist_lookup_uint32(attr_list, RESTARTER_NAME_TYPE, 211*7c478bd9Sstevel@tonic-gate &(e->re_type)) != 0) || 212*7c478bd9Sstevel@tonic-gate (nvlist_lookup_string(attr_list, 213*7c478bd9Sstevel@tonic-gate RESTARTER_NAME_INSTANCE, &(e->re_instance_name)) != 0)) { 214*7c478bd9Sstevel@tonic-gate uu_warn("%s: Can't decode nvlist for event %p\n", 215*7c478bd9Sstevel@tonic-gate h->reh_restarter_name, (void *)syse); 216*7c478bd9Sstevel@tonic-gate 217*7c478bd9Sstevel@tonic-gate ret = 0; 218*7c478bd9Sstevel@tonic-gate } else { 219*7c478bd9Sstevel@tonic-gate ret = h->reh_handler(e); 220*7c478bd9Sstevel@tonic-gate } 221*7c478bd9Sstevel@tonic-gate 222*7c478bd9Sstevel@tonic-gate uu_free(e); 223*7c478bd9Sstevel@tonic-gate nvlist_free(attr_list); 224*7c478bd9Sstevel@tonic-gate return (ret); 225*7c478bd9Sstevel@tonic-gate } 226*7c478bd9Sstevel@tonic-gate 227*7c478bd9Sstevel@tonic-gate /* 228*7c478bd9Sstevel@tonic-gate * restarter_bind_handle(uint32_t, char *, int (*)(restarter_event_t *), int, 229*7c478bd9Sstevel@tonic-gate * restarter_event_handle_t **) 230*7c478bd9Sstevel@tonic-gate * 231*7c478bd9Sstevel@tonic-gate * Bind to a delegated restarter event channel. 232*7c478bd9Sstevel@tonic-gate * Each delegated restarter gets its own channel for resource management. 233*7c478bd9Sstevel@tonic-gate * 234*7c478bd9Sstevel@tonic-gate * Returns 0 on success or 235*7c478bd9Sstevel@tonic-gate * ENOTSUP version mismatch 236*7c478bd9Sstevel@tonic-gate * EINVAL restarter_name or event_handle is NULL 237*7c478bd9Sstevel@tonic-gate * ENOMEM out of memory, too many channels, or too many subscriptions 238*7c478bd9Sstevel@tonic-gate * EBUSY sysevent_evc_bind() could not establish binding 239*7c478bd9Sstevel@tonic-gate * EFAULT internal sysevent_evc_bind()/sysevent_evc_subscribe() error 240*7c478bd9Sstevel@tonic-gate * EMFILE out of file descriptors 241*7c478bd9Sstevel@tonic-gate * EPERM insufficient privilege for sysevent_evc_bind() 242*7c478bd9Sstevel@tonic-gate * EEXIST already subscribed 243*7c478bd9Sstevel@tonic-gate */ 244*7c478bd9Sstevel@tonic-gate int 245*7c478bd9Sstevel@tonic-gate restarter_bind_handle(uint32_t version, const char *restarter_name, 246*7c478bd9Sstevel@tonic-gate int (*event_handler)(restarter_event_t *), int flags, 247*7c478bd9Sstevel@tonic-gate restarter_event_handle_t **rehp) 248*7c478bd9Sstevel@tonic-gate { 249*7c478bd9Sstevel@tonic-gate restarter_event_handle_t *h; 250*7c478bd9Sstevel@tonic-gate size_t sz; 251*7c478bd9Sstevel@tonic-gate int err; 252*7c478bd9Sstevel@tonic-gate 253*7c478bd9Sstevel@tonic-gate if (version != RESTARTER_EVENT_VERSION) 254*7c478bd9Sstevel@tonic-gate return (ENOTSUP); 255*7c478bd9Sstevel@tonic-gate 256*7c478bd9Sstevel@tonic-gate if (restarter_name == NULL || event_handler == NULL) 257*7c478bd9Sstevel@tonic-gate return (EINVAL); 258*7c478bd9Sstevel@tonic-gate 259*7c478bd9Sstevel@tonic-gate if (flags & RESTARTER_FLAG_DEBUG) 260*7c478bd9Sstevel@tonic-gate ndebug++; 261*7c478bd9Sstevel@tonic-gate 262*7c478bd9Sstevel@tonic-gate if ((h = uu_zalloc(sizeof (restarter_event_handle_t))) == NULL) 263*7c478bd9Sstevel@tonic-gate return (ENOMEM); 264*7c478bd9Sstevel@tonic-gate 265*7c478bd9Sstevel@tonic-gate h->reh_delegate_subscriber_id = malloc(MAX_SUBID_LEN); 266*7c478bd9Sstevel@tonic-gate h->reh_master_subscriber_id = malloc(MAX_SUBID_LEN); 267*7c478bd9Sstevel@tonic-gate h->reh_restarter_name = strdup(restarter_name); 268*7c478bd9Sstevel@tonic-gate if (h->reh_delegate_subscriber_id == NULL || 269*7c478bd9Sstevel@tonic-gate h->reh_master_subscriber_id == NULL || 270*7c478bd9Sstevel@tonic-gate h->reh_restarter_name == NULL) { 271*7c478bd9Sstevel@tonic-gate free_restarter_event_handle(h); 272*7c478bd9Sstevel@tonic-gate return (ENOMEM); 273*7c478bd9Sstevel@tonic-gate } 274*7c478bd9Sstevel@tonic-gate 275*7c478bd9Sstevel@tonic-gate sz = strlcpy(h->reh_delegate_subscriber_id, "del", MAX_SUBID_LEN); 276*7c478bd9Sstevel@tonic-gate assert(sz < MAX_SUBID_LEN); 277*7c478bd9Sstevel@tonic-gate sz = strlcpy(h->reh_master_subscriber_id, "master", MAX_SUBID_LEN); 278*7c478bd9Sstevel@tonic-gate assert(sz < MAX_SUBID_LEN); 279*7c478bd9Sstevel@tonic-gate 280*7c478bd9Sstevel@tonic-gate h->reh_delegate_channel_name = 281*7c478bd9Sstevel@tonic-gate _restarter_get_channel_name(restarter_name, 282*7c478bd9Sstevel@tonic-gate RESTARTER_CHANNEL_DELEGATE); 283*7c478bd9Sstevel@tonic-gate h->reh_master_channel_name = 284*7c478bd9Sstevel@tonic-gate _restarter_get_channel_name(restarter_name, 285*7c478bd9Sstevel@tonic-gate RESTARTER_CHANNEL_MASTER); 286*7c478bd9Sstevel@tonic-gate 287*7c478bd9Sstevel@tonic-gate if (h->reh_delegate_channel_name == NULL || 288*7c478bd9Sstevel@tonic-gate h->reh_master_channel_name == NULL) { 289*7c478bd9Sstevel@tonic-gate free_restarter_event_handle(h); 290*7c478bd9Sstevel@tonic-gate return (ENOMEM); 291*7c478bd9Sstevel@tonic-gate } 292*7c478bd9Sstevel@tonic-gate 293*7c478bd9Sstevel@tonic-gate if (sysevent_evc_bind(h->reh_delegate_channel_name, 294*7c478bd9Sstevel@tonic-gate &h->reh_delegate_channel, EVCH_CREAT|EVCH_HOLD_PEND) != 0) { 295*7c478bd9Sstevel@tonic-gate err = errno; 296*7c478bd9Sstevel@tonic-gate assert(err != EINVAL); 297*7c478bd9Sstevel@tonic-gate assert(err != ENOENT); 298*7c478bd9Sstevel@tonic-gate free_restarter_event_handle(h); 299*7c478bd9Sstevel@tonic-gate return (err); 300*7c478bd9Sstevel@tonic-gate } 301*7c478bd9Sstevel@tonic-gate 302*7c478bd9Sstevel@tonic-gate if (sysevent_evc_bind(h->reh_master_channel_name, 303*7c478bd9Sstevel@tonic-gate &h->reh_master_channel, EVCH_CREAT|EVCH_HOLD_PEND) != 0) { 304*7c478bd9Sstevel@tonic-gate err = errno; 305*7c478bd9Sstevel@tonic-gate assert(err != EINVAL); 306*7c478bd9Sstevel@tonic-gate assert(err != ENOENT); 307*7c478bd9Sstevel@tonic-gate free_restarter_event_handle(h); 308*7c478bd9Sstevel@tonic-gate return (err); 309*7c478bd9Sstevel@tonic-gate } 310*7c478bd9Sstevel@tonic-gate 311*7c478bd9Sstevel@tonic-gate h->reh_handler = event_handler; 312*7c478bd9Sstevel@tonic-gate 313*7c478bd9Sstevel@tonic-gate assert(strlen(restarter_name) <= MAX_CLASS_LEN - 1); 314*7c478bd9Sstevel@tonic-gate assert(strlen(h->reh_delegate_subscriber_id) <= MAX_SUBID_LEN - 1); 315*7c478bd9Sstevel@tonic-gate assert(strlen(h->reh_master_subscriber_id) <= MAX_SUBID_LEN - 1); 316*7c478bd9Sstevel@tonic-gate 317*7c478bd9Sstevel@tonic-gate if (sysevent_evc_subscribe(h->reh_delegate_channel, 318*7c478bd9Sstevel@tonic-gate h->reh_delegate_subscriber_id, EC_ALL, cb, h, EVCH_SUB_KEEP) != 0) { 319*7c478bd9Sstevel@tonic-gate err = errno; 320*7c478bd9Sstevel@tonic-gate assert(err != EINVAL); 321*7c478bd9Sstevel@tonic-gate free_restarter_event_handle(h); 322*7c478bd9Sstevel@tonic-gate return (err); 323*7c478bd9Sstevel@tonic-gate } 324*7c478bd9Sstevel@tonic-gate 325*7c478bd9Sstevel@tonic-gate *rehp = h; 326*7c478bd9Sstevel@tonic-gate return (0); 327*7c478bd9Sstevel@tonic-gate } 328*7c478bd9Sstevel@tonic-gate 329*7c478bd9Sstevel@tonic-gate void 330*7c478bd9Sstevel@tonic-gate restarter_unbind_handle(restarter_event_handle_t *h) 331*7c478bd9Sstevel@tonic-gate { 332*7c478bd9Sstevel@tonic-gate free_restarter_event_handle(h); 333*7c478bd9Sstevel@tonic-gate } 334*7c478bd9Sstevel@tonic-gate 335*7c478bd9Sstevel@tonic-gate restarter_event_handle_t * 336*7c478bd9Sstevel@tonic-gate restarter_event_get_handle(restarter_event_t *e) 337*7c478bd9Sstevel@tonic-gate { 338*7c478bd9Sstevel@tonic-gate assert(e != NULL && e->re_event_handle != NULL); 339*7c478bd9Sstevel@tonic-gate return (e->re_event_handle); 340*7c478bd9Sstevel@tonic-gate } 341*7c478bd9Sstevel@tonic-gate 342*7c478bd9Sstevel@tonic-gate restarter_event_type_t 343*7c478bd9Sstevel@tonic-gate restarter_event_get_type(restarter_event_t *e) 344*7c478bd9Sstevel@tonic-gate { 345*7c478bd9Sstevel@tonic-gate assert(e != NULL); 346*7c478bd9Sstevel@tonic-gate return (e->re_type); 347*7c478bd9Sstevel@tonic-gate } 348*7c478bd9Sstevel@tonic-gate 349*7c478bd9Sstevel@tonic-gate ssize_t 350*7c478bd9Sstevel@tonic-gate restarter_event_get_instance(restarter_event_t *e, char *inst, size_t sz) 351*7c478bd9Sstevel@tonic-gate { 352*7c478bd9Sstevel@tonic-gate assert(e != NULL && inst != NULL); 353*7c478bd9Sstevel@tonic-gate return ((ssize_t)strlcpy(inst, e->re_instance_name, sz)); 354*7c478bd9Sstevel@tonic-gate } 355*7c478bd9Sstevel@tonic-gate 356*7c478bd9Sstevel@tonic-gate int 357*7c478bd9Sstevel@tonic-gate restarter_event_get_current_states(restarter_event_t *e, 358*7c478bd9Sstevel@tonic-gate restarter_instance_state_t *state, restarter_instance_state_t *next_state) 359*7c478bd9Sstevel@tonic-gate { 360*7c478bd9Sstevel@tonic-gate if (e == NULL) 361*7c478bd9Sstevel@tonic-gate return (-1); 362*7c478bd9Sstevel@tonic-gate *state = e->re_state; 363*7c478bd9Sstevel@tonic-gate *next_state = e->re_next_state; 364*7c478bd9Sstevel@tonic-gate return (0); 365*7c478bd9Sstevel@tonic-gate } 366*7c478bd9Sstevel@tonic-gate 367*7c478bd9Sstevel@tonic-gate /* 368*7c478bd9Sstevel@tonic-gate * Commit the state, next state, and auxiliary state into the repository. 369*7c478bd9Sstevel@tonic-gate * Let the graph engine know about the state change and error. On success, 370*7c478bd9Sstevel@tonic-gate * return 0. On error, return 371*7c478bd9Sstevel@tonic-gate * EINVAL - aux has spaces 372*7c478bd9Sstevel@tonic-gate * - inst is invalid or not an instance FMRI 373*7c478bd9Sstevel@tonic-gate * EPROTO - librestart compiled against different libscf 374*7c478bd9Sstevel@tonic-gate * ENOMEM - out of memory 375*7c478bd9Sstevel@tonic-gate * - repository server out of resources 376*7c478bd9Sstevel@tonic-gate * ENOTACTIVE - repository server not running 377*7c478bd9Sstevel@tonic-gate * ECONNABORTED - repository connection established, but then broken 378*7c478bd9Sstevel@tonic-gate * - unknown libscf error 379*7c478bd9Sstevel@tonic-gate * ENOENT - inst does not exist in the repository 380*7c478bd9Sstevel@tonic-gate * EPERM - insufficient permissions 381*7c478bd9Sstevel@tonic-gate * EACCESS - backend access denied 382*7c478bd9Sstevel@tonic-gate * EROFS - backend is readonly 383*7c478bd9Sstevel@tonic-gate * EFAULT - internal sysevent_evc_publish() error 384*7c478bd9Sstevel@tonic-gate * EBADF - h is invalid (sysevent_evc_publish() returned EINVAL) 385*7c478bd9Sstevel@tonic-gate */ 386*7c478bd9Sstevel@tonic-gate int 387*7c478bd9Sstevel@tonic-gate restarter_set_states(restarter_event_handle_t *h, const char *inst, 388*7c478bd9Sstevel@tonic-gate restarter_instance_state_t cur_state, 389*7c478bd9Sstevel@tonic-gate restarter_instance_state_t new_cur_state, 390*7c478bd9Sstevel@tonic-gate restarter_instance_state_t next_state, 391*7c478bd9Sstevel@tonic-gate restarter_instance_state_t new_next_state, restarter_error_t e, 392*7c478bd9Sstevel@tonic-gate const char *aux) 393*7c478bd9Sstevel@tonic-gate { 394*7c478bd9Sstevel@tonic-gate nvlist_t *attr; 395*7c478bd9Sstevel@tonic-gate scf_handle_t *scf_h; 396*7c478bd9Sstevel@tonic-gate instance_data_t id; 397*7c478bd9Sstevel@tonic-gate useconds_t retry_int = INITIAL_COMMIT_RETRY_INT; 398*7c478bd9Sstevel@tonic-gate int retries; 399*7c478bd9Sstevel@tonic-gate int ret = 0; 400*7c478bd9Sstevel@tonic-gate char *p = (char *)aux; 401*7c478bd9Sstevel@tonic-gate 402*7c478bd9Sstevel@tonic-gate assert(h->reh_master_channel != NULL); 403*7c478bd9Sstevel@tonic-gate assert(h->reh_master_channel_name != NULL); 404*7c478bd9Sstevel@tonic-gate assert(h->reh_master_subscriber_id != NULL); 405*7c478bd9Sstevel@tonic-gate 406*7c478bd9Sstevel@tonic-gate /* Validate format of auxiliary state: no spaces allowed */ 407*7c478bd9Sstevel@tonic-gate while (p != NULL) { 408*7c478bd9Sstevel@tonic-gate if (isspace(*p)) 409*7c478bd9Sstevel@tonic-gate return (EINVAL); 410*7c478bd9Sstevel@tonic-gate p++; 411*7c478bd9Sstevel@tonic-gate } 412*7c478bd9Sstevel@tonic-gate 413*7c478bd9Sstevel@tonic-gate if ((scf_h = scf_handle_create(SCF_VERSION)) == NULL) { 414*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 415*7c478bd9Sstevel@tonic-gate case SCF_ERROR_VERSION_MISMATCH: 416*7c478bd9Sstevel@tonic-gate return (EPROTO); 417*7c478bd9Sstevel@tonic-gate 418*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NO_MEMORY: 419*7c478bd9Sstevel@tonic-gate return (ENOMEM); 420*7c478bd9Sstevel@tonic-gate 421*7c478bd9Sstevel@tonic-gate default: 422*7c478bd9Sstevel@tonic-gate bad_fail("scf_handle_create", scf_error()); 423*7c478bd9Sstevel@tonic-gate } 424*7c478bd9Sstevel@tonic-gate } 425*7c478bd9Sstevel@tonic-gate 426*7c478bd9Sstevel@tonic-gate if (scf_handle_bind(scf_h) == -1) { 427*7c478bd9Sstevel@tonic-gate scf_handle_destroy(scf_h); 428*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 429*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NO_SERVER: 430*7c478bd9Sstevel@tonic-gate return (ENOTACTIVE); 431*7c478bd9Sstevel@tonic-gate 432*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NO_RESOURCES: 433*7c478bd9Sstevel@tonic-gate return (ENOMEM); 434*7c478bd9Sstevel@tonic-gate 435*7c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 436*7c478bd9Sstevel@tonic-gate case SCF_ERROR_IN_USE: 437*7c478bd9Sstevel@tonic-gate default: 438*7c478bd9Sstevel@tonic-gate bad_fail("scf_handle_bind", scf_error()); 439*7c478bd9Sstevel@tonic-gate } 440*7c478bd9Sstevel@tonic-gate } 441*7c478bd9Sstevel@tonic-gate 442*7c478bd9Sstevel@tonic-gate if (nvlist_alloc(&attr, NV_UNIQUE_NAME, 0) != 0 || 443*7c478bd9Sstevel@tonic-gate nvlist_add_int32(attr, RESTARTER_NAME_STATE, new_cur_state) != 0 || 444*7c478bd9Sstevel@tonic-gate nvlist_add_int32(attr, RESTARTER_NAME_NEXT_STATE, new_next_state) 445*7c478bd9Sstevel@tonic-gate != 0 || 446*7c478bd9Sstevel@tonic-gate nvlist_add_int32(attr, RESTARTER_NAME_ERROR, e) != 0 || 447*7c478bd9Sstevel@tonic-gate nvlist_add_string(attr, RESTARTER_NAME_INSTANCE, inst) != 0) { 448*7c478bd9Sstevel@tonic-gate ret = ENOMEM; 449*7c478bd9Sstevel@tonic-gate goto errout; 450*7c478bd9Sstevel@tonic-gate } 451*7c478bd9Sstevel@tonic-gate 452*7c478bd9Sstevel@tonic-gate id.i_fmri = inst; 453*7c478bd9Sstevel@tonic-gate id.i_state = cur_state; 454*7c478bd9Sstevel@tonic-gate id.i_next_state = next_state; 455*7c478bd9Sstevel@tonic-gate 456*7c478bd9Sstevel@tonic-gate ret = _restarter_commit_states(scf_h, &id, new_cur_state, 457*7c478bd9Sstevel@tonic-gate new_next_state, aux); 458*7c478bd9Sstevel@tonic-gate if (ret != 0) 459*7c478bd9Sstevel@tonic-gate goto errout; 460*7c478bd9Sstevel@tonic-gate 461*7c478bd9Sstevel@tonic-gate for (retries = 0; retries < MAX_COMMIT_RETRIES; retries++) { 462*7c478bd9Sstevel@tonic-gate ret = sysevent_evc_publish(h->reh_master_channel, "master", 463*7c478bd9Sstevel@tonic-gate "state_change", "com.sun", "librestart", attr, 464*7c478bd9Sstevel@tonic-gate EVCH_NOSLEEP); 465*7c478bd9Sstevel@tonic-gate if (ret == 0) 466*7c478bd9Sstevel@tonic-gate break; 467*7c478bd9Sstevel@tonic-gate 468*7c478bd9Sstevel@tonic-gate switch (ret) { 469*7c478bd9Sstevel@tonic-gate case EAGAIN: 470*7c478bd9Sstevel@tonic-gate /* Queue is full */ 471*7c478bd9Sstevel@tonic-gate (void) usleep(retry_int); 472*7c478bd9Sstevel@tonic-gate 473*7c478bd9Sstevel@tonic-gate retry_int = min(retry_int * 2, MAX_COMMIT_RETRY_INT); 474*7c478bd9Sstevel@tonic-gate break; 475*7c478bd9Sstevel@tonic-gate 476*7c478bd9Sstevel@tonic-gate case EFAULT: 477*7c478bd9Sstevel@tonic-gate case ENOMEM: 478*7c478bd9Sstevel@tonic-gate goto errout; 479*7c478bd9Sstevel@tonic-gate 480*7c478bd9Sstevel@tonic-gate case EINVAL: 481*7c478bd9Sstevel@tonic-gate ret = EBADF; 482*7c478bd9Sstevel@tonic-gate goto errout; 483*7c478bd9Sstevel@tonic-gate 484*7c478bd9Sstevel@tonic-gate case EOVERFLOW: 485*7c478bd9Sstevel@tonic-gate default: 486*7c478bd9Sstevel@tonic-gate bad_fail("sysevent_evc_publish", ret); 487*7c478bd9Sstevel@tonic-gate } 488*7c478bd9Sstevel@tonic-gate } 489*7c478bd9Sstevel@tonic-gate 490*7c478bd9Sstevel@tonic-gate errout: 491*7c478bd9Sstevel@tonic-gate nvlist_free(attr); 492*7c478bd9Sstevel@tonic-gate (void) scf_handle_unbind(scf_h); 493*7c478bd9Sstevel@tonic-gate scf_handle_destroy(scf_h); 494*7c478bd9Sstevel@tonic-gate 495*7c478bd9Sstevel@tonic-gate return (ret); 496*7c478bd9Sstevel@tonic-gate } 497*7c478bd9Sstevel@tonic-gate 498*7c478bd9Sstevel@tonic-gate restarter_instance_state_t 499*7c478bd9Sstevel@tonic-gate restarter_string_to_state(char *string) 500*7c478bd9Sstevel@tonic-gate { 501*7c478bd9Sstevel@tonic-gate assert(string != NULL); 502*7c478bd9Sstevel@tonic-gate 503*7c478bd9Sstevel@tonic-gate if (strcmp(string, SCF_STATE_STRING_NONE) == 0) 504*7c478bd9Sstevel@tonic-gate return (RESTARTER_STATE_NONE); 505*7c478bd9Sstevel@tonic-gate else if (strcmp(string, SCF_STATE_STRING_UNINIT) == 0) 506*7c478bd9Sstevel@tonic-gate return (RESTARTER_STATE_UNINIT); 507*7c478bd9Sstevel@tonic-gate else if (strcmp(string, SCF_STATE_STRING_MAINT) == 0) 508*7c478bd9Sstevel@tonic-gate return (RESTARTER_STATE_MAINT); 509*7c478bd9Sstevel@tonic-gate else if (strcmp(string, SCF_STATE_STRING_OFFLINE) == 0) 510*7c478bd9Sstevel@tonic-gate return (RESTARTER_STATE_OFFLINE); 511*7c478bd9Sstevel@tonic-gate else if (strcmp(string, SCF_STATE_STRING_DISABLED) == 0) 512*7c478bd9Sstevel@tonic-gate return (RESTARTER_STATE_DISABLED); 513*7c478bd9Sstevel@tonic-gate else if (strcmp(string, SCF_STATE_STRING_ONLINE) == 0) 514*7c478bd9Sstevel@tonic-gate return (RESTARTER_STATE_ONLINE); 515*7c478bd9Sstevel@tonic-gate else if (strcmp(string, SCF_STATE_STRING_DEGRADED) == 0) 516*7c478bd9Sstevel@tonic-gate return (RESTARTER_STATE_DEGRADED); 517*7c478bd9Sstevel@tonic-gate else { 518*7c478bd9Sstevel@tonic-gate return (RESTARTER_STATE_NONE); 519*7c478bd9Sstevel@tonic-gate } 520*7c478bd9Sstevel@tonic-gate } 521*7c478bd9Sstevel@tonic-gate 522*7c478bd9Sstevel@tonic-gate ssize_t 523*7c478bd9Sstevel@tonic-gate restarter_state_to_string(restarter_instance_state_t state, char *string, 524*7c478bd9Sstevel@tonic-gate size_t len) 525*7c478bd9Sstevel@tonic-gate { 526*7c478bd9Sstevel@tonic-gate assert(string != NULL); 527*7c478bd9Sstevel@tonic-gate 528*7c478bd9Sstevel@tonic-gate if (state == RESTARTER_STATE_NONE) 529*7c478bd9Sstevel@tonic-gate return ((ssize_t)strlcpy(string, SCF_STATE_STRING_NONE, len)); 530*7c478bd9Sstevel@tonic-gate else if (state == RESTARTER_STATE_UNINIT) 531*7c478bd9Sstevel@tonic-gate return ((ssize_t)strlcpy(string, SCF_STATE_STRING_UNINIT, len)); 532*7c478bd9Sstevel@tonic-gate else if (state == RESTARTER_STATE_MAINT) 533*7c478bd9Sstevel@tonic-gate return ((ssize_t)strlcpy(string, SCF_STATE_STRING_MAINT, len)); 534*7c478bd9Sstevel@tonic-gate else if (state == RESTARTER_STATE_OFFLINE) 535*7c478bd9Sstevel@tonic-gate return ((ssize_t)strlcpy(string, SCF_STATE_STRING_OFFLINE, 536*7c478bd9Sstevel@tonic-gate len)); 537*7c478bd9Sstevel@tonic-gate else if (state == RESTARTER_STATE_DISABLED) 538*7c478bd9Sstevel@tonic-gate return ((ssize_t)strlcpy(string, SCF_STATE_STRING_DISABLED, 539*7c478bd9Sstevel@tonic-gate len)); 540*7c478bd9Sstevel@tonic-gate else if (state == RESTARTER_STATE_ONLINE) 541*7c478bd9Sstevel@tonic-gate return ((ssize_t)strlcpy(string, SCF_STATE_STRING_ONLINE, len)); 542*7c478bd9Sstevel@tonic-gate else if (state == RESTARTER_STATE_DEGRADED) 543*7c478bd9Sstevel@tonic-gate return ((ssize_t)strlcpy(string, SCF_STATE_STRING_DEGRADED, 544*7c478bd9Sstevel@tonic-gate len)); 545*7c478bd9Sstevel@tonic-gate else 546*7c478bd9Sstevel@tonic-gate return ((ssize_t)strlcpy(string, "unknown", len)); 547*7c478bd9Sstevel@tonic-gate } 548*7c478bd9Sstevel@tonic-gate 549*7c478bd9Sstevel@tonic-gate /* 550*7c478bd9Sstevel@tonic-gate * Sets pg to the name property group of s_inst. If it doesn't exist, it is 551*7c478bd9Sstevel@tonic-gate * added. 552*7c478bd9Sstevel@tonic-gate * 553*7c478bd9Sstevel@tonic-gate * Fails with 554*7c478bd9Sstevel@tonic-gate * ECONNABORTED - repository disconnection or unknown libscf error 555*7c478bd9Sstevel@tonic-gate * EBADF - inst is not set 556*7c478bd9Sstevel@tonic-gate * ECANCELED - inst is deleted 557*7c478bd9Sstevel@tonic-gate * EPERM - permission is denied 558*7c478bd9Sstevel@tonic-gate * EACCES - backend denied access 559*7c478bd9Sstevel@tonic-gate * EROFS - backend readonly 560*7c478bd9Sstevel@tonic-gate */ 561*7c478bd9Sstevel@tonic-gate static int 562*7c478bd9Sstevel@tonic-gate instance_get_or_add_pg(scf_instance_t *inst, const char *name, 563*7c478bd9Sstevel@tonic-gate const char *type, uint32_t flags, scf_propertygroup_t *pg) 564*7c478bd9Sstevel@tonic-gate { 565*7c478bd9Sstevel@tonic-gate again: 566*7c478bd9Sstevel@tonic-gate if (scf_instance_get_pg(inst, name, pg) == 0) 567*7c478bd9Sstevel@tonic-gate return (0); 568*7c478bd9Sstevel@tonic-gate 569*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 570*7c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 571*7c478bd9Sstevel@tonic-gate default: 572*7c478bd9Sstevel@tonic-gate return (ECONNABORTED); 573*7c478bd9Sstevel@tonic-gate 574*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 575*7c478bd9Sstevel@tonic-gate return (EBADF); 576*7c478bd9Sstevel@tonic-gate 577*7c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 578*7c478bd9Sstevel@tonic-gate return (ECANCELED); 579*7c478bd9Sstevel@tonic-gate 580*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 581*7c478bd9Sstevel@tonic-gate break; 582*7c478bd9Sstevel@tonic-gate 583*7c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 584*7c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 585*7c478bd9Sstevel@tonic-gate bad_fail("scf_instance_get_pg", scf_error()); 586*7c478bd9Sstevel@tonic-gate } 587*7c478bd9Sstevel@tonic-gate 588*7c478bd9Sstevel@tonic-gate if (scf_instance_add_pg(inst, name, type, flags, pg) == 0) 589*7c478bd9Sstevel@tonic-gate return (0); 590*7c478bd9Sstevel@tonic-gate 591*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 592*7c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 593*7c478bd9Sstevel@tonic-gate default: 594*7c478bd9Sstevel@tonic-gate return (ECONNABORTED); 595*7c478bd9Sstevel@tonic-gate 596*7c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 597*7c478bd9Sstevel@tonic-gate return (ECANCELED); 598*7c478bd9Sstevel@tonic-gate 599*7c478bd9Sstevel@tonic-gate case SCF_ERROR_EXISTS: 600*7c478bd9Sstevel@tonic-gate goto again; 601*7c478bd9Sstevel@tonic-gate 602*7c478bd9Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 603*7c478bd9Sstevel@tonic-gate return (EPERM); 604*7c478bd9Sstevel@tonic-gate 605*7c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS: 606*7c478bd9Sstevel@tonic-gate return (EACCES); 607*7c478bd9Sstevel@tonic-gate 608*7c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 609*7c478bd9Sstevel@tonic-gate return (EROFS); 610*7c478bd9Sstevel@tonic-gate 611*7c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 612*7c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 613*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: /* should be caught above */ 614*7c478bd9Sstevel@tonic-gate bad_fail("scf_instance_add_pg", scf_error()); 615*7c478bd9Sstevel@tonic-gate } 616*7c478bd9Sstevel@tonic-gate 617*7c478bd9Sstevel@tonic-gate return (0); 618*7c478bd9Sstevel@tonic-gate } 619*7c478bd9Sstevel@tonic-gate 620*7c478bd9Sstevel@tonic-gate /* 621*7c478bd9Sstevel@tonic-gate * Fails with 622*7c478bd9Sstevel@tonic-gate * ECONNABORTED 623*7c478bd9Sstevel@tonic-gate * ECANCELED - pg was deleted 624*7c478bd9Sstevel@tonic-gate */ 625*7c478bd9Sstevel@tonic-gate static int 626*7c478bd9Sstevel@tonic-gate tx_set_value(scf_transaction_t *tx, scf_transaction_entry_t *ent, 627*7c478bd9Sstevel@tonic-gate const char *pname, scf_type_t ty, scf_value_t *val) 628*7c478bd9Sstevel@tonic-gate { 629*7c478bd9Sstevel@tonic-gate int r; 630*7c478bd9Sstevel@tonic-gate 631*7c478bd9Sstevel@tonic-gate for (;;) { 632*7c478bd9Sstevel@tonic-gate if (scf_transaction_property_change_type(tx, ent, pname, 633*7c478bd9Sstevel@tonic-gate ty) == 0) 634*7c478bd9Sstevel@tonic-gate break; 635*7c478bd9Sstevel@tonic-gate 636*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 637*7c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 638*7c478bd9Sstevel@tonic-gate default: 639*7c478bd9Sstevel@tonic-gate return (ECONNABORTED); 640*7c478bd9Sstevel@tonic-gate 641*7c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 642*7c478bd9Sstevel@tonic-gate return (ECANCELED); 643*7c478bd9Sstevel@tonic-gate 644*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 645*7c478bd9Sstevel@tonic-gate break; 646*7c478bd9Sstevel@tonic-gate 647*7c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 648*7c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 649*7c478bd9Sstevel@tonic-gate case SCF_ERROR_IN_USE: 650*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 651*7c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_property_change_type", 652*7c478bd9Sstevel@tonic-gate scf_error()); 653*7c478bd9Sstevel@tonic-gate } 654*7c478bd9Sstevel@tonic-gate 655*7c478bd9Sstevel@tonic-gate if (scf_transaction_property_new(tx, ent, pname, ty) == 0) 656*7c478bd9Sstevel@tonic-gate break; 657*7c478bd9Sstevel@tonic-gate 658*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 659*7c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 660*7c478bd9Sstevel@tonic-gate default: 661*7c478bd9Sstevel@tonic-gate return (ECONNABORTED); 662*7c478bd9Sstevel@tonic-gate 663*7c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 664*7c478bd9Sstevel@tonic-gate return (ECANCELED); 665*7c478bd9Sstevel@tonic-gate 666*7c478bd9Sstevel@tonic-gate case SCF_ERROR_EXISTS: 667*7c478bd9Sstevel@tonic-gate break; 668*7c478bd9Sstevel@tonic-gate 669*7c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 670*7c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 671*7c478bd9Sstevel@tonic-gate case SCF_ERROR_IN_USE: 672*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 673*7c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_property_new", scf_error()); 674*7c478bd9Sstevel@tonic-gate } 675*7c478bd9Sstevel@tonic-gate } 676*7c478bd9Sstevel@tonic-gate 677*7c478bd9Sstevel@tonic-gate r = scf_entry_add_value(ent, val); 678*7c478bd9Sstevel@tonic-gate assert(r == 0); 679*7c478bd9Sstevel@tonic-gate 680*7c478bd9Sstevel@tonic-gate return (0); 681*7c478bd9Sstevel@tonic-gate } 682*7c478bd9Sstevel@tonic-gate 683*7c478bd9Sstevel@tonic-gate /* 684*7c478bd9Sstevel@tonic-gate * Commit new_state, new_next_state, and aux to the repository for id. If 685*7c478bd9Sstevel@tonic-gate * successful, also set id's state and next-state as given, and return 0. 686*7c478bd9Sstevel@tonic-gate * Fails with 687*7c478bd9Sstevel@tonic-gate * ENOMEM - out of memory 688*7c478bd9Sstevel@tonic-gate * ECONNABORTED - repository connection broken 689*7c478bd9Sstevel@tonic-gate * - unknown libscf error 690*7c478bd9Sstevel@tonic-gate * EINVAL - id->i_fmri is invalid or not an instance FMRI 691*7c478bd9Sstevel@tonic-gate * ENOENT - id->i_fmri does not exist 692*7c478bd9Sstevel@tonic-gate * EPERM - insufficient permissions 693*7c478bd9Sstevel@tonic-gate * EACCES - backend access denied 694*7c478bd9Sstevel@tonic-gate * EROFS - backend is readonly 695*7c478bd9Sstevel@tonic-gate */ 696*7c478bd9Sstevel@tonic-gate int 697*7c478bd9Sstevel@tonic-gate _restarter_commit_states(scf_handle_t *h, instance_data_t *id, 698*7c478bd9Sstevel@tonic-gate restarter_instance_state_t new_state, 699*7c478bd9Sstevel@tonic-gate restarter_instance_state_t new_state_next, const char *aux) 700*7c478bd9Sstevel@tonic-gate { 701*7c478bd9Sstevel@tonic-gate char str_state[MAX_SCF_STATE_STRING_SZ]; 702*7c478bd9Sstevel@tonic-gate char str_new_state[MAX_SCF_STATE_STRING_SZ]; 703*7c478bd9Sstevel@tonic-gate char str_state_next[MAX_SCF_STATE_STRING_SZ]; 704*7c478bd9Sstevel@tonic-gate char str_new_state_next[MAX_SCF_STATE_STRING_SZ]; 705*7c478bd9Sstevel@tonic-gate int ret = 0, r; 706*7c478bd9Sstevel@tonic-gate struct timeval now; 707*7c478bd9Sstevel@tonic-gate ssize_t sz; 708*7c478bd9Sstevel@tonic-gate char *default_aux = "none"; 709*7c478bd9Sstevel@tonic-gate 710*7c478bd9Sstevel@tonic-gate scf_transaction_t *t = NULL; 711*7c478bd9Sstevel@tonic-gate scf_transaction_entry_t *t_state = NULL, *t_state_next = NULL; 712*7c478bd9Sstevel@tonic-gate scf_transaction_entry_t *t_stime = NULL, *t_aux = NULL; 713*7c478bd9Sstevel@tonic-gate scf_value_t *v_state = NULL, *v_state_next = NULL, *v_stime = NULL; 714*7c478bd9Sstevel@tonic-gate scf_value_t *v_aux = NULL; 715*7c478bd9Sstevel@tonic-gate scf_instance_t *s_inst = NULL; 716*7c478bd9Sstevel@tonic-gate scf_propertygroup_t *pg = NULL; 717*7c478bd9Sstevel@tonic-gate 718*7c478bd9Sstevel@tonic-gate assert(new_state != RESTARTER_STATE_NONE); 719*7c478bd9Sstevel@tonic-gate 720*7c478bd9Sstevel@tonic-gate /* If aux state is unset, set aux to a default string. */ 721*7c478bd9Sstevel@tonic-gate if (aux == NULL) 722*7c478bd9Sstevel@tonic-gate aux = default_aux; 723*7c478bd9Sstevel@tonic-gate 724*7c478bd9Sstevel@tonic-gate if ((s_inst = scf_instance_create(h)) == NULL || 725*7c478bd9Sstevel@tonic-gate (pg = scf_pg_create(h)) == NULL || 726*7c478bd9Sstevel@tonic-gate (t = scf_transaction_create(h)) == NULL || 727*7c478bd9Sstevel@tonic-gate (t_state = scf_entry_create(h)) == NULL || 728*7c478bd9Sstevel@tonic-gate (t_state_next = scf_entry_create(h)) == NULL || 729*7c478bd9Sstevel@tonic-gate (t_stime = scf_entry_create(h)) == NULL || 730*7c478bd9Sstevel@tonic-gate (t_aux = scf_entry_create(h)) == NULL || 731*7c478bd9Sstevel@tonic-gate (v_state = scf_value_create(h)) == NULL || 732*7c478bd9Sstevel@tonic-gate (v_state_next = scf_value_create(h)) == NULL || 733*7c478bd9Sstevel@tonic-gate (v_stime = scf_value_create(h)) == NULL || 734*7c478bd9Sstevel@tonic-gate (v_aux = scf_value_create(h)) == NULL) { 735*7c478bd9Sstevel@tonic-gate ret = ENOMEM; 736*7c478bd9Sstevel@tonic-gate goto out; 737*7c478bd9Sstevel@tonic-gate } 738*7c478bd9Sstevel@tonic-gate 739*7c478bd9Sstevel@tonic-gate sz = restarter_state_to_string(new_state, str_new_state, 740*7c478bd9Sstevel@tonic-gate sizeof (str_new_state)); 741*7c478bd9Sstevel@tonic-gate assert(sz < sizeof (str_new_state)); 742*7c478bd9Sstevel@tonic-gate sz = restarter_state_to_string(new_state_next, str_new_state_next, 743*7c478bd9Sstevel@tonic-gate sizeof (str_new_state_next)); 744*7c478bd9Sstevel@tonic-gate assert(sz < sizeof (str_new_state_next)); 745*7c478bd9Sstevel@tonic-gate sz = restarter_state_to_string(id->i_state, str_state, 746*7c478bd9Sstevel@tonic-gate sizeof (str_state)); 747*7c478bd9Sstevel@tonic-gate assert(sz < sizeof (str_state)); 748*7c478bd9Sstevel@tonic-gate sz = restarter_state_to_string(id->i_next_state, str_state_next, 749*7c478bd9Sstevel@tonic-gate sizeof (str_state_next)); 750*7c478bd9Sstevel@tonic-gate assert(sz < sizeof (str_state_next)); 751*7c478bd9Sstevel@tonic-gate 752*7c478bd9Sstevel@tonic-gate ret = gettimeofday(&now, NULL); 753*7c478bd9Sstevel@tonic-gate assert(ret != -1); 754*7c478bd9Sstevel@tonic-gate 755*7c478bd9Sstevel@tonic-gate if (scf_handle_decode_fmri(h, id->i_fmri, NULL, NULL, s_inst, 756*7c478bd9Sstevel@tonic-gate NULL, NULL, SCF_DECODE_FMRI_EXACT) == -1) { 757*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 758*7c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 759*7c478bd9Sstevel@tonic-gate default: 760*7c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 761*7c478bd9Sstevel@tonic-gate break; 762*7c478bd9Sstevel@tonic-gate 763*7c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 764*7c478bd9Sstevel@tonic-gate case SCF_ERROR_CONSTRAINT_VIOLATED: 765*7c478bd9Sstevel@tonic-gate ret = EINVAL; 766*7c478bd9Sstevel@tonic-gate break; 767*7c478bd9Sstevel@tonic-gate 768*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 769*7c478bd9Sstevel@tonic-gate ret = ENOENT; 770*7c478bd9Sstevel@tonic-gate break; 771*7c478bd9Sstevel@tonic-gate 772*7c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 773*7c478bd9Sstevel@tonic-gate bad_fail("scf_handle_decode_fmri", scf_error()); 774*7c478bd9Sstevel@tonic-gate } 775*7c478bd9Sstevel@tonic-gate goto out; 776*7c478bd9Sstevel@tonic-gate } 777*7c478bd9Sstevel@tonic-gate 778*7c478bd9Sstevel@tonic-gate 779*7c478bd9Sstevel@tonic-gate if (scf_value_set_astring(v_state, str_new_state) != 0 || 780*7c478bd9Sstevel@tonic-gate scf_value_set_astring(v_state_next, str_new_state_next) != 0 || 781*7c478bd9Sstevel@tonic-gate scf_value_set_astring(v_aux, aux) != 0) 782*7c478bd9Sstevel@tonic-gate bad_fail("scf_value_set_astring", scf_error()); 783*7c478bd9Sstevel@tonic-gate 784*7c478bd9Sstevel@tonic-gate if (scf_value_set_time(v_stime, now.tv_sec, now.tv_usec * 1000) != 0) 785*7c478bd9Sstevel@tonic-gate bad_fail("scf_value_set_time", scf_error()); 786*7c478bd9Sstevel@tonic-gate 787*7c478bd9Sstevel@tonic-gate add_pg: 788*7c478bd9Sstevel@tonic-gate switch (r = instance_get_or_add_pg(s_inst, SCF_PG_RESTARTER, 789*7c478bd9Sstevel@tonic-gate SCF_PG_RESTARTER_TYPE, SCF_PG_RESTARTER_FLAGS, pg)) { 790*7c478bd9Sstevel@tonic-gate case 0: 791*7c478bd9Sstevel@tonic-gate break; 792*7c478bd9Sstevel@tonic-gate 793*7c478bd9Sstevel@tonic-gate case ECONNABORTED: 794*7c478bd9Sstevel@tonic-gate case EPERM: 795*7c478bd9Sstevel@tonic-gate case EACCES: 796*7c478bd9Sstevel@tonic-gate case EROFS: 797*7c478bd9Sstevel@tonic-gate ret = r; 798*7c478bd9Sstevel@tonic-gate goto out; 799*7c478bd9Sstevel@tonic-gate 800*7c478bd9Sstevel@tonic-gate case ECANCELED: 801*7c478bd9Sstevel@tonic-gate ret = ENOENT; 802*7c478bd9Sstevel@tonic-gate goto out; 803*7c478bd9Sstevel@tonic-gate 804*7c478bd9Sstevel@tonic-gate case EBADF: 805*7c478bd9Sstevel@tonic-gate default: 806*7c478bd9Sstevel@tonic-gate bad_fail("instance_get_or_add_pg", r); 807*7c478bd9Sstevel@tonic-gate } 808*7c478bd9Sstevel@tonic-gate 809*7c478bd9Sstevel@tonic-gate for (;;) { 810*7c478bd9Sstevel@tonic-gate if (scf_transaction_start(t, pg) != 0) { 811*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 812*7c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 813*7c478bd9Sstevel@tonic-gate default: 814*7c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 815*7c478bd9Sstevel@tonic-gate goto out; 816*7c478bd9Sstevel@tonic-gate 817*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 818*7c478bd9Sstevel@tonic-gate goto add_pg; 819*7c478bd9Sstevel@tonic-gate 820*7c478bd9Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 821*7c478bd9Sstevel@tonic-gate ret = EPERM; 822*7c478bd9Sstevel@tonic-gate goto out; 823*7c478bd9Sstevel@tonic-gate 824*7c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS: 825*7c478bd9Sstevel@tonic-gate ret = EACCES; 826*7c478bd9Sstevel@tonic-gate goto out; 827*7c478bd9Sstevel@tonic-gate 828*7c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 829*7c478bd9Sstevel@tonic-gate ret = EROFS; 830*7c478bd9Sstevel@tonic-gate goto out; 831*7c478bd9Sstevel@tonic-gate 832*7c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 833*7c478bd9Sstevel@tonic-gate case SCF_ERROR_IN_USE: 834*7c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_start", scf_error()); 835*7c478bd9Sstevel@tonic-gate } 836*7c478bd9Sstevel@tonic-gate } 837*7c478bd9Sstevel@tonic-gate 838*7c478bd9Sstevel@tonic-gate if ((r = tx_set_value(t, t_state, SCF_PROPERTY_STATE, 839*7c478bd9Sstevel@tonic-gate SCF_TYPE_ASTRING, v_state)) != 0 || 840*7c478bd9Sstevel@tonic-gate (r = tx_set_value(t, t_state_next, SCF_PROPERTY_NEXT_STATE, 841*7c478bd9Sstevel@tonic-gate SCF_TYPE_ASTRING, v_state_next)) != 0 || 842*7c478bd9Sstevel@tonic-gate (r = tx_set_value(t, t_aux, SCF_PROPERTY_AUX_STATE, 843*7c478bd9Sstevel@tonic-gate SCF_TYPE_ASTRING, v_aux)) != 0 || 844*7c478bd9Sstevel@tonic-gate (r = tx_set_value(t, t_stime, SCF_PROPERTY_STATE_TIMESTAMP, 845*7c478bd9Sstevel@tonic-gate SCF_TYPE_TIME, v_stime)) != 0) { 846*7c478bd9Sstevel@tonic-gate switch (r) { 847*7c478bd9Sstevel@tonic-gate case ECONNABORTED: 848*7c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 849*7c478bd9Sstevel@tonic-gate goto out; 850*7c478bd9Sstevel@tonic-gate 851*7c478bd9Sstevel@tonic-gate case ECANCELED: 852*7c478bd9Sstevel@tonic-gate scf_transaction_reset(t); 853*7c478bd9Sstevel@tonic-gate goto add_pg; 854*7c478bd9Sstevel@tonic-gate 855*7c478bd9Sstevel@tonic-gate default: 856*7c478bd9Sstevel@tonic-gate bad_fail("tx_set_value", r); 857*7c478bd9Sstevel@tonic-gate } 858*7c478bd9Sstevel@tonic-gate } 859*7c478bd9Sstevel@tonic-gate 860*7c478bd9Sstevel@tonic-gate ret = scf_transaction_commit(t); 861*7c478bd9Sstevel@tonic-gate if (ret == 1) 862*7c478bd9Sstevel@tonic-gate break; 863*7c478bd9Sstevel@tonic-gate if (ret == -1) { 864*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 865*7c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 866*7c478bd9Sstevel@tonic-gate default: 867*7c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 868*7c478bd9Sstevel@tonic-gate goto out; 869*7c478bd9Sstevel@tonic-gate 870*7c478bd9Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 871*7c478bd9Sstevel@tonic-gate ret = EPERM; 872*7c478bd9Sstevel@tonic-gate goto out; 873*7c478bd9Sstevel@tonic-gate 874*7c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS: 875*7c478bd9Sstevel@tonic-gate ret = EACCES; 876*7c478bd9Sstevel@tonic-gate goto out; 877*7c478bd9Sstevel@tonic-gate 878*7c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 879*7c478bd9Sstevel@tonic-gate ret = EROFS; 880*7c478bd9Sstevel@tonic-gate goto out; 881*7c478bd9Sstevel@tonic-gate 882*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 883*7c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_commit", scf_error()); 884*7c478bd9Sstevel@tonic-gate } 885*7c478bd9Sstevel@tonic-gate } 886*7c478bd9Sstevel@tonic-gate 887*7c478bd9Sstevel@tonic-gate scf_transaction_reset(t); 888*7c478bd9Sstevel@tonic-gate if (scf_pg_update(pg) == -1) { 889*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 890*7c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 891*7c478bd9Sstevel@tonic-gate default: 892*7c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 893*7c478bd9Sstevel@tonic-gate goto out; 894*7c478bd9Sstevel@tonic-gate 895*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 896*7c478bd9Sstevel@tonic-gate goto add_pg; 897*7c478bd9Sstevel@tonic-gate } 898*7c478bd9Sstevel@tonic-gate } 899*7c478bd9Sstevel@tonic-gate } 900*7c478bd9Sstevel@tonic-gate 901*7c478bd9Sstevel@tonic-gate id->i_state = new_state; 902*7c478bd9Sstevel@tonic-gate id->i_next_state = new_state_next; 903*7c478bd9Sstevel@tonic-gate ret = 0; 904*7c478bd9Sstevel@tonic-gate 905*7c478bd9Sstevel@tonic-gate out: 906*7c478bd9Sstevel@tonic-gate scf_transaction_destroy(t); 907*7c478bd9Sstevel@tonic-gate scf_entry_destroy(t_state); 908*7c478bd9Sstevel@tonic-gate scf_entry_destroy(t_state_next); 909*7c478bd9Sstevel@tonic-gate scf_entry_destroy(t_stime); 910*7c478bd9Sstevel@tonic-gate scf_entry_destroy(t_aux); 911*7c478bd9Sstevel@tonic-gate scf_value_destroy(v_state); 912*7c478bd9Sstevel@tonic-gate scf_value_destroy(v_state_next); 913*7c478bd9Sstevel@tonic-gate scf_value_destroy(v_stime); 914*7c478bd9Sstevel@tonic-gate scf_value_destroy(v_aux); 915*7c478bd9Sstevel@tonic-gate scf_pg_destroy(pg); 916*7c478bd9Sstevel@tonic-gate scf_instance_destroy(s_inst); 917*7c478bd9Sstevel@tonic-gate 918*7c478bd9Sstevel@tonic-gate return (ret); 919*7c478bd9Sstevel@tonic-gate } 920*7c478bd9Sstevel@tonic-gate 921*7c478bd9Sstevel@tonic-gate /* 922*7c478bd9Sstevel@tonic-gate * Fails with 923*7c478bd9Sstevel@tonic-gate * EINVAL - type is invalid 924*7c478bd9Sstevel@tonic-gate * ENOMEM 925*7c478bd9Sstevel@tonic-gate * ECONNABORTED - repository connection broken 926*7c478bd9Sstevel@tonic-gate * EBADF - s_inst is not set 927*7c478bd9Sstevel@tonic-gate * ECANCELED - s_inst is deleted 928*7c478bd9Sstevel@tonic-gate * EPERM - permission denied 929*7c478bd9Sstevel@tonic-gate * EACCES - backend access denied 930*7c478bd9Sstevel@tonic-gate * EROFS - backend readonly 931*7c478bd9Sstevel@tonic-gate */ 932*7c478bd9Sstevel@tonic-gate int 933*7c478bd9Sstevel@tonic-gate restarter_remove_contract(scf_instance_t *s_inst, ctid_t contract_id, 934*7c478bd9Sstevel@tonic-gate restarter_contract_type_t type) 935*7c478bd9Sstevel@tonic-gate { 936*7c478bd9Sstevel@tonic-gate scf_handle_t *h; 937*7c478bd9Sstevel@tonic-gate scf_transaction_t *t = NULL; 938*7c478bd9Sstevel@tonic-gate scf_transaction_entry_t *t_cid = NULL; 939*7c478bd9Sstevel@tonic-gate scf_propertygroup_t *pg = NULL; 940*7c478bd9Sstevel@tonic-gate scf_property_t *prop = NULL; 941*7c478bd9Sstevel@tonic-gate scf_value_t *val; 942*7c478bd9Sstevel@tonic-gate scf_iter_t *iter = NULL; 943*7c478bd9Sstevel@tonic-gate const char *pname; 944*7c478bd9Sstevel@tonic-gate int ret = 0, primary; 945*7c478bd9Sstevel@tonic-gate uint64_t c; 946*7c478bd9Sstevel@tonic-gate 947*7c478bd9Sstevel@tonic-gate switch (type) { 948*7c478bd9Sstevel@tonic-gate case RESTARTER_CONTRACT_PRIMARY: 949*7c478bd9Sstevel@tonic-gate primary = 1; 950*7c478bd9Sstevel@tonic-gate break; 951*7c478bd9Sstevel@tonic-gate case RESTARTER_CONTRACT_TRANSIENT: 952*7c478bd9Sstevel@tonic-gate primary = 0; 953*7c478bd9Sstevel@tonic-gate break; 954*7c478bd9Sstevel@tonic-gate default: 955*7c478bd9Sstevel@tonic-gate return (EINVAL); 956*7c478bd9Sstevel@tonic-gate } 957*7c478bd9Sstevel@tonic-gate 958*7c478bd9Sstevel@tonic-gate h = scf_instance_handle(s_inst); 959*7c478bd9Sstevel@tonic-gate 960*7c478bd9Sstevel@tonic-gate pg = scf_pg_create(h); 961*7c478bd9Sstevel@tonic-gate prop = scf_property_create(h); 962*7c478bd9Sstevel@tonic-gate iter = scf_iter_create(h); 963*7c478bd9Sstevel@tonic-gate t = scf_transaction_create(h); 964*7c478bd9Sstevel@tonic-gate 965*7c478bd9Sstevel@tonic-gate if (pg == NULL || prop == NULL || iter == NULL || t == NULL) { 966*7c478bd9Sstevel@tonic-gate ret = ENOMEM; 967*7c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 968*7c478bd9Sstevel@tonic-gate } 969*7c478bd9Sstevel@tonic-gate 970*7c478bd9Sstevel@tonic-gate add: 971*7c478bd9Sstevel@tonic-gate scf_transaction_destroy_children(t); 972*7c478bd9Sstevel@tonic-gate ret = instance_get_or_add_pg(s_inst, SCF_PG_RESTARTER, 973*7c478bd9Sstevel@tonic-gate SCF_PG_RESTARTER_TYPE, SCF_PG_RESTARTER_FLAGS, pg); 974*7c478bd9Sstevel@tonic-gate if (ret != 0) 975*7c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 976*7c478bd9Sstevel@tonic-gate 977*7c478bd9Sstevel@tonic-gate pname = primary? SCF_PROPERTY_CONTRACT : 978*7c478bd9Sstevel@tonic-gate SCF_PROPERTY_TRANSIENT_CONTRACT; 979*7c478bd9Sstevel@tonic-gate 980*7c478bd9Sstevel@tonic-gate for (;;) { 981*7c478bd9Sstevel@tonic-gate if (scf_transaction_start(t, pg) != 0) { 982*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 983*7c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 984*7c478bd9Sstevel@tonic-gate default: 985*7c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 986*7c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 987*7c478bd9Sstevel@tonic-gate 988*7c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 989*7c478bd9Sstevel@tonic-gate goto add; 990*7c478bd9Sstevel@tonic-gate 991*7c478bd9Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 992*7c478bd9Sstevel@tonic-gate ret = EPERM; 993*7c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 994*7c478bd9Sstevel@tonic-gate 995*7c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS: 996*7c478bd9Sstevel@tonic-gate ret = EACCES; 997*7c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 998*7c478bd9Sstevel@tonic-gate 999*7c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 1000*7c478bd9Sstevel@tonic-gate ret = EROFS; 1001*7c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 1002*7c478bd9Sstevel@tonic-gate 1003*7c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 1004*7c478bd9Sstevel@tonic-gate case SCF_ERROR_IN_USE: 1005*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 1006*7c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_start", scf_error()); 1007*7c478bd9Sstevel@tonic-gate } 1008*7c478bd9Sstevel@tonic-gate } 1009*7c478bd9Sstevel@tonic-gate 1010*7c478bd9Sstevel@tonic-gate t_cid = scf_entry_create(h); 1011*7c478bd9Sstevel@tonic-gate 1012*7c478bd9Sstevel@tonic-gate if (scf_pg_get_property(pg, pname, prop) == 0) { 1013*7c478bd9Sstevel@tonic-gate replace: 1014*7c478bd9Sstevel@tonic-gate if (scf_transaction_property_change_type(t, t_cid, 1015*7c478bd9Sstevel@tonic-gate pname, SCF_TYPE_COUNT) != 0) { 1016*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 1017*7c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 1018*7c478bd9Sstevel@tonic-gate default: 1019*7c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 1020*7c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 1021*7c478bd9Sstevel@tonic-gate 1022*7c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 1023*7c478bd9Sstevel@tonic-gate scf_entry_destroy(t_cid); 1024*7c478bd9Sstevel@tonic-gate goto add; 1025*7c478bd9Sstevel@tonic-gate 1026*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 1027*7c478bd9Sstevel@tonic-gate goto new; 1028*7c478bd9Sstevel@tonic-gate 1029*7c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 1030*7c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 1031*7c478bd9Sstevel@tonic-gate case SCF_ERROR_IN_USE: 1032*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 1033*7c478bd9Sstevel@tonic-gate bad_fail( 1034*7c478bd9Sstevel@tonic-gate "scf_transaction_property_changetype", 1035*7c478bd9Sstevel@tonic-gate scf_error()); 1036*7c478bd9Sstevel@tonic-gate } 1037*7c478bd9Sstevel@tonic-gate } 1038*7c478bd9Sstevel@tonic-gate 1039*7c478bd9Sstevel@tonic-gate if (scf_property_is_type(prop, SCF_TYPE_COUNT) == 0) { 1040*7c478bd9Sstevel@tonic-gate if (scf_iter_property_values(iter, prop) != 0) { 1041*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 1042*7c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 1043*7c478bd9Sstevel@tonic-gate default: 1044*7c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 1045*7c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 1046*7c478bd9Sstevel@tonic-gate 1047*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 1048*7c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 1049*7c478bd9Sstevel@tonic-gate bad_fail( 1050*7c478bd9Sstevel@tonic-gate "scf_iter_property_values", 1051*7c478bd9Sstevel@tonic-gate scf_error()); 1052*7c478bd9Sstevel@tonic-gate } 1053*7c478bd9Sstevel@tonic-gate } 1054*7c478bd9Sstevel@tonic-gate 1055*7c478bd9Sstevel@tonic-gate next_val: 1056*7c478bd9Sstevel@tonic-gate val = scf_value_create(h); 1057*7c478bd9Sstevel@tonic-gate if (val == NULL) { 1058*7c478bd9Sstevel@tonic-gate assert(scf_error() == 1059*7c478bd9Sstevel@tonic-gate SCF_ERROR_NO_MEMORY); 1060*7c478bd9Sstevel@tonic-gate ret = ENOMEM; 1061*7c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 1062*7c478bd9Sstevel@tonic-gate } 1063*7c478bd9Sstevel@tonic-gate 1064*7c478bd9Sstevel@tonic-gate ret = scf_iter_next_value(iter, val); 1065*7c478bd9Sstevel@tonic-gate if (ret == -1) { 1066*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 1067*7c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 1068*7c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 1069*7c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 1070*7c478bd9Sstevel@tonic-gate 1071*7c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 1072*7c478bd9Sstevel@tonic-gate scf_value_destroy(val); 1073*7c478bd9Sstevel@tonic-gate goto add; 1074*7c478bd9Sstevel@tonic-gate 1075*7c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 1076*7c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 1077*7c478bd9Sstevel@tonic-gate default: 1078*7c478bd9Sstevel@tonic-gate bad_fail("scf_iter_next_value", 1079*7c478bd9Sstevel@tonic-gate scf_error()); 1080*7c478bd9Sstevel@tonic-gate } 1081*7c478bd9Sstevel@tonic-gate } 1082*7c478bd9Sstevel@tonic-gate 1083*7c478bd9Sstevel@tonic-gate if (ret == 1) { 1084*7c478bd9Sstevel@tonic-gate ret = scf_value_get_count(val, &c); 1085*7c478bd9Sstevel@tonic-gate assert(ret == 0); 1086*7c478bd9Sstevel@tonic-gate 1087*7c478bd9Sstevel@tonic-gate if (c != contract_id) { 1088*7c478bd9Sstevel@tonic-gate ret = scf_entry_add_value(t_cid, 1089*7c478bd9Sstevel@tonic-gate val); 1090*7c478bd9Sstevel@tonic-gate assert(ret == 0); 1091*7c478bd9Sstevel@tonic-gate } else { 1092*7c478bd9Sstevel@tonic-gate scf_value_destroy(val); 1093*7c478bd9Sstevel@tonic-gate } 1094*7c478bd9Sstevel@tonic-gate 1095*7c478bd9Sstevel@tonic-gate goto next_val; 1096*7c478bd9Sstevel@tonic-gate } 1097*7c478bd9Sstevel@tonic-gate 1098*7c478bd9Sstevel@tonic-gate scf_value_destroy(val); 1099*7c478bd9Sstevel@tonic-gate } else { 1100*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 1101*7c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 1102*7c478bd9Sstevel@tonic-gate default: 1103*7c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 1104*7c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 1105*7c478bd9Sstevel@tonic-gate 1106*7c478bd9Sstevel@tonic-gate case SCF_ERROR_TYPE_MISMATCH: 1107*7c478bd9Sstevel@tonic-gate break; 1108*7c478bd9Sstevel@tonic-gate 1109*7c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 1110*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 1111*7c478bd9Sstevel@tonic-gate bad_fail("scf_property_is_type", 1112*7c478bd9Sstevel@tonic-gate scf_error()); 1113*7c478bd9Sstevel@tonic-gate } 1114*7c478bd9Sstevel@tonic-gate } 1115*7c478bd9Sstevel@tonic-gate } else { 1116*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 1117*7c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 1118*7c478bd9Sstevel@tonic-gate default: 1119*7c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 1120*7c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 1121*7c478bd9Sstevel@tonic-gate 1122*7c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 1123*7c478bd9Sstevel@tonic-gate scf_entry_destroy(t_cid); 1124*7c478bd9Sstevel@tonic-gate goto add; 1125*7c478bd9Sstevel@tonic-gate 1126*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 1127*7c478bd9Sstevel@tonic-gate break; 1128*7c478bd9Sstevel@tonic-gate 1129*7c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 1130*7c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 1131*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 1132*7c478bd9Sstevel@tonic-gate bad_fail("scf_pg_get_property", scf_error()); 1133*7c478bd9Sstevel@tonic-gate } 1134*7c478bd9Sstevel@tonic-gate 1135*7c478bd9Sstevel@tonic-gate new: 1136*7c478bd9Sstevel@tonic-gate if (scf_transaction_property_new(t, t_cid, pname, 1137*7c478bd9Sstevel@tonic-gate SCF_TYPE_COUNT) != 0) { 1138*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 1139*7c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 1140*7c478bd9Sstevel@tonic-gate default: 1141*7c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 1142*7c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 1143*7c478bd9Sstevel@tonic-gate 1144*7c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 1145*7c478bd9Sstevel@tonic-gate scf_entry_destroy(t_cid); 1146*7c478bd9Sstevel@tonic-gate goto add; 1147*7c478bd9Sstevel@tonic-gate 1148*7c478bd9Sstevel@tonic-gate case SCF_ERROR_EXISTS: 1149*7c478bd9Sstevel@tonic-gate goto replace; 1150*7c478bd9Sstevel@tonic-gate 1151*7c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 1152*7c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 1153*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 1154*7c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_property_new", 1155*7c478bd9Sstevel@tonic-gate scf_error()); 1156*7c478bd9Sstevel@tonic-gate } 1157*7c478bd9Sstevel@tonic-gate } 1158*7c478bd9Sstevel@tonic-gate } 1159*7c478bd9Sstevel@tonic-gate 1160*7c478bd9Sstevel@tonic-gate ret = scf_transaction_commit(t); 1161*7c478bd9Sstevel@tonic-gate if (ret == -1) { 1162*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 1163*7c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 1164*7c478bd9Sstevel@tonic-gate default: 1165*7c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 1166*7c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 1167*7c478bd9Sstevel@tonic-gate 1168*7c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 1169*7c478bd9Sstevel@tonic-gate goto add; 1170*7c478bd9Sstevel@tonic-gate 1171*7c478bd9Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 1172*7c478bd9Sstevel@tonic-gate ret = EPERM; 1173*7c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 1174*7c478bd9Sstevel@tonic-gate 1175*7c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS: 1176*7c478bd9Sstevel@tonic-gate ret = EACCES; 1177*7c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 1178*7c478bd9Sstevel@tonic-gate 1179*7c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 1180*7c478bd9Sstevel@tonic-gate ret = EROFS; 1181*7c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 1182*7c478bd9Sstevel@tonic-gate 1183*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 1184*7c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_commit", scf_error()); 1185*7c478bd9Sstevel@tonic-gate } 1186*7c478bd9Sstevel@tonic-gate } 1187*7c478bd9Sstevel@tonic-gate if (ret == 1) { 1188*7c478bd9Sstevel@tonic-gate ret = 0; 1189*7c478bd9Sstevel@tonic-gate break; 1190*7c478bd9Sstevel@tonic-gate } 1191*7c478bd9Sstevel@tonic-gate 1192*7c478bd9Sstevel@tonic-gate scf_transaction_destroy_children(t); 1193*7c478bd9Sstevel@tonic-gate if (scf_pg_update(pg) == -1) { 1194*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 1195*7c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 1196*7c478bd9Sstevel@tonic-gate default: 1197*7c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 1198*7c478bd9Sstevel@tonic-gate goto remove_contract_cleanup; 1199*7c478bd9Sstevel@tonic-gate 1200*7c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 1201*7c478bd9Sstevel@tonic-gate goto add; 1202*7c478bd9Sstevel@tonic-gate 1203*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 1204*7c478bd9Sstevel@tonic-gate bad_fail("scf_pg_update", scf_error()); 1205*7c478bd9Sstevel@tonic-gate } 1206*7c478bd9Sstevel@tonic-gate } 1207*7c478bd9Sstevel@tonic-gate } 1208*7c478bd9Sstevel@tonic-gate 1209*7c478bd9Sstevel@tonic-gate remove_contract_cleanup: 1210*7c478bd9Sstevel@tonic-gate scf_transaction_destroy_children(t); 1211*7c478bd9Sstevel@tonic-gate scf_transaction_destroy(t); 1212*7c478bd9Sstevel@tonic-gate scf_iter_destroy(iter); 1213*7c478bd9Sstevel@tonic-gate scf_property_destroy(prop); 1214*7c478bd9Sstevel@tonic-gate scf_pg_destroy(pg); 1215*7c478bd9Sstevel@tonic-gate 1216*7c478bd9Sstevel@tonic-gate return (ret); 1217*7c478bd9Sstevel@tonic-gate } 1218*7c478bd9Sstevel@tonic-gate 1219*7c478bd9Sstevel@tonic-gate /* 1220*7c478bd9Sstevel@tonic-gate * Fails with 1221*7c478bd9Sstevel@tonic-gate * EINVAL - type is invalid 1222*7c478bd9Sstevel@tonic-gate * ENOMEM 1223*7c478bd9Sstevel@tonic-gate * ECONNABORTED - repository disconnection 1224*7c478bd9Sstevel@tonic-gate * EBADF - s_inst is not set 1225*7c478bd9Sstevel@tonic-gate * ECANCELED - s_inst is deleted 1226*7c478bd9Sstevel@tonic-gate * EPERM 1227*7c478bd9Sstevel@tonic-gate * EACCES 1228*7c478bd9Sstevel@tonic-gate * EROFS 1229*7c478bd9Sstevel@tonic-gate */ 1230*7c478bd9Sstevel@tonic-gate int 1231*7c478bd9Sstevel@tonic-gate restarter_store_contract(scf_instance_t *s_inst, ctid_t contract_id, 1232*7c478bd9Sstevel@tonic-gate restarter_contract_type_t type) 1233*7c478bd9Sstevel@tonic-gate { 1234*7c478bd9Sstevel@tonic-gate scf_handle_t *h; 1235*7c478bd9Sstevel@tonic-gate scf_transaction_t *t = NULL; 1236*7c478bd9Sstevel@tonic-gate scf_transaction_entry_t *t_cid = NULL; 1237*7c478bd9Sstevel@tonic-gate scf_value_t *val; 1238*7c478bd9Sstevel@tonic-gate scf_propertygroup_t *pg = NULL; 1239*7c478bd9Sstevel@tonic-gate scf_property_t *prop = NULL; 1240*7c478bd9Sstevel@tonic-gate scf_iter_t *iter = NULL; 1241*7c478bd9Sstevel@tonic-gate const char *pname; 1242*7c478bd9Sstevel@tonic-gate int ret = 0, primary; 1243*7c478bd9Sstevel@tonic-gate 1244*7c478bd9Sstevel@tonic-gate if (type == RESTARTER_CONTRACT_PRIMARY) 1245*7c478bd9Sstevel@tonic-gate primary = 1; 1246*7c478bd9Sstevel@tonic-gate else if (type == RESTARTER_CONTRACT_TRANSIENT) 1247*7c478bd9Sstevel@tonic-gate primary = 0; 1248*7c478bd9Sstevel@tonic-gate else 1249*7c478bd9Sstevel@tonic-gate return (EINVAL); 1250*7c478bd9Sstevel@tonic-gate 1251*7c478bd9Sstevel@tonic-gate h = scf_instance_handle(s_inst); 1252*7c478bd9Sstevel@tonic-gate 1253*7c478bd9Sstevel@tonic-gate pg = scf_pg_create(h); 1254*7c478bd9Sstevel@tonic-gate prop = scf_property_create(h); 1255*7c478bd9Sstevel@tonic-gate iter = scf_iter_create(h); 1256*7c478bd9Sstevel@tonic-gate t = scf_transaction_create(h); 1257*7c478bd9Sstevel@tonic-gate 1258*7c478bd9Sstevel@tonic-gate if (pg == NULL || prop == NULL || iter == NULL || t == NULL) { 1259*7c478bd9Sstevel@tonic-gate ret = ENOMEM; 1260*7c478bd9Sstevel@tonic-gate goto out; 1261*7c478bd9Sstevel@tonic-gate } 1262*7c478bd9Sstevel@tonic-gate 1263*7c478bd9Sstevel@tonic-gate add: 1264*7c478bd9Sstevel@tonic-gate scf_transaction_destroy_children(t); 1265*7c478bd9Sstevel@tonic-gate ret = instance_get_or_add_pg(s_inst, SCF_PG_RESTARTER, 1266*7c478bd9Sstevel@tonic-gate SCF_PG_RESTARTER_TYPE, SCF_PG_RESTARTER_FLAGS, pg); 1267*7c478bd9Sstevel@tonic-gate if (ret != 0) 1268*7c478bd9Sstevel@tonic-gate goto out; 1269*7c478bd9Sstevel@tonic-gate 1270*7c478bd9Sstevel@tonic-gate pname = primary ? SCF_PROPERTY_CONTRACT : 1271*7c478bd9Sstevel@tonic-gate SCF_PROPERTY_TRANSIENT_CONTRACT; 1272*7c478bd9Sstevel@tonic-gate 1273*7c478bd9Sstevel@tonic-gate for (;;) { 1274*7c478bd9Sstevel@tonic-gate if (scf_transaction_start(t, pg) != 0) { 1275*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 1276*7c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 1277*7c478bd9Sstevel@tonic-gate default: 1278*7c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 1279*7c478bd9Sstevel@tonic-gate goto out; 1280*7c478bd9Sstevel@tonic-gate 1281*7c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 1282*7c478bd9Sstevel@tonic-gate goto add; 1283*7c478bd9Sstevel@tonic-gate 1284*7c478bd9Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 1285*7c478bd9Sstevel@tonic-gate ret = EPERM; 1286*7c478bd9Sstevel@tonic-gate goto out; 1287*7c478bd9Sstevel@tonic-gate 1288*7c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS: 1289*7c478bd9Sstevel@tonic-gate ret = EACCES; 1290*7c478bd9Sstevel@tonic-gate goto out; 1291*7c478bd9Sstevel@tonic-gate 1292*7c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 1293*7c478bd9Sstevel@tonic-gate ret = EROFS; 1294*7c478bd9Sstevel@tonic-gate goto out; 1295*7c478bd9Sstevel@tonic-gate 1296*7c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 1297*7c478bd9Sstevel@tonic-gate case SCF_ERROR_IN_USE: 1298*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 1299*7c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_start", scf_error()); 1300*7c478bd9Sstevel@tonic-gate } 1301*7c478bd9Sstevel@tonic-gate } 1302*7c478bd9Sstevel@tonic-gate 1303*7c478bd9Sstevel@tonic-gate t_cid = scf_entry_create(h); 1304*7c478bd9Sstevel@tonic-gate if (t_cid == NULL) { 1305*7c478bd9Sstevel@tonic-gate ret = ENOMEM; 1306*7c478bd9Sstevel@tonic-gate goto out; 1307*7c478bd9Sstevel@tonic-gate } 1308*7c478bd9Sstevel@tonic-gate 1309*7c478bd9Sstevel@tonic-gate if (scf_pg_get_property(pg, pname, prop) == 0) { 1310*7c478bd9Sstevel@tonic-gate replace: 1311*7c478bd9Sstevel@tonic-gate if (scf_transaction_property_change_type(t, t_cid, 1312*7c478bd9Sstevel@tonic-gate pname, SCF_TYPE_COUNT) != 0) { 1313*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 1314*7c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 1315*7c478bd9Sstevel@tonic-gate default: 1316*7c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 1317*7c478bd9Sstevel@tonic-gate goto out; 1318*7c478bd9Sstevel@tonic-gate 1319*7c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 1320*7c478bd9Sstevel@tonic-gate scf_entry_destroy(t_cid); 1321*7c478bd9Sstevel@tonic-gate goto add; 1322*7c478bd9Sstevel@tonic-gate 1323*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 1324*7c478bd9Sstevel@tonic-gate goto new; 1325*7c478bd9Sstevel@tonic-gate 1326*7c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 1327*7c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 1328*7c478bd9Sstevel@tonic-gate case SCF_ERROR_IN_USE: 1329*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 1330*7c478bd9Sstevel@tonic-gate bad_fail( 1331*7c478bd9Sstevel@tonic-gate "scf_transaction_propert_change_type", 1332*7c478bd9Sstevel@tonic-gate scf_error()); 1333*7c478bd9Sstevel@tonic-gate } 1334*7c478bd9Sstevel@tonic-gate } 1335*7c478bd9Sstevel@tonic-gate 1336*7c478bd9Sstevel@tonic-gate if (scf_property_is_type(prop, SCF_TYPE_COUNT) == 0) { 1337*7c478bd9Sstevel@tonic-gate if (scf_iter_property_values(iter, prop) != 0) { 1338*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 1339*7c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 1340*7c478bd9Sstevel@tonic-gate default: 1341*7c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 1342*7c478bd9Sstevel@tonic-gate goto out; 1343*7c478bd9Sstevel@tonic-gate 1344*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 1345*7c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 1346*7c478bd9Sstevel@tonic-gate bad_fail( 1347*7c478bd9Sstevel@tonic-gate "scf_iter_property_values", 1348*7c478bd9Sstevel@tonic-gate scf_error()); 1349*7c478bd9Sstevel@tonic-gate } 1350*7c478bd9Sstevel@tonic-gate } 1351*7c478bd9Sstevel@tonic-gate 1352*7c478bd9Sstevel@tonic-gate next_val: 1353*7c478bd9Sstevel@tonic-gate val = scf_value_create(h); 1354*7c478bd9Sstevel@tonic-gate if (val == NULL) { 1355*7c478bd9Sstevel@tonic-gate assert(scf_error() == 1356*7c478bd9Sstevel@tonic-gate SCF_ERROR_NO_MEMORY); 1357*7c478bd9Sstevel@tonic-gate ret = ENOMEM; 1358*7c478bd9Sstevel@tonic-gate goto out; 1359*7c478bd9Sstevel@tonic-gate } 1360*7c478bd9Sstevel@tonic-gate 1361*7c478bd9Sstevel@tonic-gate ret = scf_iter_next_value(iter, val); 1362*7c478bd9Sstevel@tonic-gate if (ret == -1) { 1363*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 1364*7c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 1365*7c478bd9Sstevel@tonic-gate default: 1366*7c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 1367*7c478bd9Sstevel@tonic-gate goto out; 1368*7c478bd9Sstevel@tonic-gate 1369*7c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 1370*7c478bd9Sstevel@tonic-gate scf_value_destroy(val); 1371*7c478bd9Sstevel@tonic-gate goto add; 1372*7c478bd9Sstevel@tonic-gate 1373*7c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 1374*7c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 1375*7c478bd9Sstevel@tonic-gate bad_fail( 1376*7c478bd9Sstevel@tonic-gate "scf_iter_next_value", 1377*7c478bd9Sstevel@tonic-gate scf_error()); 1378*7c478bd9Sstevel@tonic-gate } 1379*7c478bd9Sstevel@tonic-gate } 1380*7c478bd9Sstevel@tonic-gate 1381*7c478bd9Sstevel@tonic-gate if (ret == 1) { 1382*7c478bd9Sstevel@tonic-gate ret = scf_entry_add_value(t_cid, val); 1383*7c478bd9Sstevel@tonic-gate assert(ret == 0); 1384*7c478bd9Sstevel@tonic-gate 1385*7c478bd9Sstevel@tonic-gate goto next_val; 1386*7c478bd9Sstevel@tonic-gate } 1387*7c478bd9Sstevel@tonic-gate 1388*7c478bd9Sstevel@tonic-gate scf_value_destroy(val); 1389*7c478bd9Sstevel@tonic-gate } else { 1390*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 1391*7c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 1392*7c478bd9Sstevel@tonic-gate default: 1393*7c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 1394*7c478bd9Sstevel@tonic-gate goto out; 1395*7c478bd9Sstevel@tonic-gate 1396*7c478bd9Sstevel@tonic-gate case SCF_ERROR_TYPE_MISMATCH: 1397*7c478bd9Sstevel@tonic-gate break; 1398*7c478bd9Sstevel@tonic-gate 1399*7c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 1400*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 1401*7c478bd9Sstevel@tonic-gate bad_fail("scf_property_is_type", 1402*7c478bd9Sstevel@tonic-gate scf_error()); 1403*7c478bd9Sstevel@tonic-gate } 1404*7c478bd9Sstevel@tonic-gate } 1405*7c478bd9Sstevel@tonic-gate } else { 1406*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 1407*7c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 1408*7c478bd9Sstevel@tonic-gate default: 1409*7c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 1410*7c478bd9Sstevel@tonic-gate goto out; 1411*7c478bd9Sstevel@tonic-gate 1412*7c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 1413*7c478bd9Sstevel@tonic-gate scf_entry_destroy(t_cid); 1414*7c478bd9Sstevel@tonic-gate goto add; 1415*7c478bd9Sstevel@tonic-gate 1416*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 1417*7c478bd9Sstevel@tonic-gate break; 1418*7c478bd9Sstevel@tonic-gate 1419*7c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 1420*7c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 1421*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 1422*7c478bd9Sstevel@tonic-gate bad_fail("scf_pg_get_property", scf_error()); 1423*7c478bd9Sstevel@tonic-gate } 1424*7c478bd9Sstevel@tonic-gate 1425*7c478bd9Sstevel@tonic-gate new: 1426*7c478bd9Sstevel@tonic-gate if (scf_transaction_property_new(t, t_cid, pname, 1427*7c478bd9Sstevel@tonic-gate SCF_TYPE_COUNT) != 0) { 1428*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 1429*7c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 1430*7c478bd9Sstevel@tonic-gate default: 1431*7c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 1432*7c478bd9Sstevel@tonic-gate goto out; 1433*7c478bd9Sstevel@tonic-gate 1434*7c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 1435*7c478bd9Sstevel@tonic-gate scf_entry_destroy(t_cid); 1436*7c478bd9Sstevel@tonic-gate goto add; 1437*7c478bd9Sstevel@tonic-gate 1438*7c478bd9Sstevel@tonic-gate case SCF_ERROR_EXISTS: 1439*7c478bd9Sstevel@tonic-gate goto replace; 1440*7c478bd9Sstevel@tonic-gate 1441*7c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 1442*7c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 1443*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 1444*7c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_property_new", 1445*7c478bd9Sstevel@tonic-gate scf_error()); 1446*7c478bd9Sstevel@tonic-gate } 1447*7c478bd9Sstevel@tonic-gate } 1448*7c478bd9Sstevel@tonic-gate } 1449*7c478bd9Sstevel@tonic-gate 1450*7c478bd9Sstevel@tonic-gate val = scf_value_create(h); 1451*7c478bd9Sstevel@tonic-gate if (val == NULL) { 1452*7c478bd9Sstevel@tonic-gate assert(scf_error() == SCF_ERROR_NO_MEMORY); 1453*7c478bd9Sstevel@tonic-gate ret = ENOMEM; 1454*7c478bd9Sstevel@tonic-gate goto out; 1455*7c478bd9Sstevel@tonic-gate } 1456*7c478bd9Sstevel@tonic-gate 1457*7c478bd9Sstevel@tonic-gate scf_value_set_count(val, contract_id); 1458*7c478bd9Sstevel@tonic-gate ret = scf_entry_add_value(t_cid, val); 1459*7c478bd9Sstevel@tonic-gate assert(ret == 0); 1460*7c478bd9Sstevel@tonic-gate 1461*7c478bd9Sstevel@tonic-gate ret = scf_transaction_commit(t); 1462*7c478bd9Sstevel@tonic-gate if (ret == -1) { 1463*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 1464*7c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 1465*7c478bd9Sstevel@tonic-gate default: 1466*7c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 1467*7c478bd9Sstevel@tonic-gate goto out; 1468*7c478bd9Sstevel@tonic-gate 1469*7c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 1470*7c478bd9Sstevel@tonic-gate goto add; 1471*7c478bd9Sstevel@tonic-gate 1472*7c478bd9Sstevel@tonic-gate case SCF_ERROR_PERMISSION_DENIED: 1473*7c478bd9Sstevel@tonic-gate ret = EPERM; 1474*7c478bd9Sstevel@tonic-gate goto out; 1475*7c478bd9Sstevel@tonic-gate 1476*7c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_ACCESS: 1477*7c478bd9Sstevel@tonic-gate ret = EACCES; 1478*7c478bd9Sstevel@tonic-gate goto out; 1479*7c478bd9Sstevel@tonic-gate 1480*7c478bd9Sstevel@tonic-gate case SCF_ERROR_BACKEND_READONLY: 1481*7c478bd9Sstevel@tonic-gate ret = EROFS; 1482*7c478bd9Sstevel@tonic-gate goto out; 1483*7c478bd9Sstevel@tonic-gate 1484*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 1485*7c478bd9Sstevel@tonic-gate bad_fail("scf_transaction_commit", scf_error()); 1486*7c478bd9Sstevel@tonic-gate } 1487*7c478bd9Sstevel@tonic-gate } 1488*7c478bd9Sstevel@tonic-gate if (ret == 1) { 1489*7c478bd9Sstevel@tonic-gate ret = 0; 1490*7c478bd9Sstevel@tonic-gate break; 1491*7c478bd9Sstevel@tonic-gate } 1492*7c478bd9Sstevel@tonic-gate 1493*7c478bd9Sstevel@tonic-gate scf_transaction_destroy_children(t); 1494*7c478bd9Sstevel@tonic-gate if (scf_pg_update(pg) == -1) { 1495*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 1496*7c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 1497*7c478bd9Sstevel@tonic-gate default: 1498*7c478bd9Sstevel@tonic-gate ret = ECONNABORTED; 1499*7c478bd9Sstevel@tonic-gate goto out; 1500*7c478bd9Sstevel@tonic-gate 1501*7c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 1502*7c478bd9Sstevel@tonic-gate goto add; 1503*7c478bd9Sstevel@tonic-gate 1504*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 1505*7c478bd9Sstevel@tonic-gate bad_fail("scf_pg_update", scf_error()); 1506*7c478bd9Sstevel@tonic-gate } 1507*7c478bd9Sstevel@tonic-gate } 1508*7c478bd9Sstevel@tonic-gate } 1509*7c478bd9Sstevel@tonic-gate 1510*7c478bd9Sstevel@tonic-gate out: 1511*7c478bd9Sstevel@tonic-gate scf_transaction_destroy_children(t); 1512*7c478bd9Sstevel@tonic-gate scf_transaction_destroy(t); 1513*7c478bd9Sstevel@tonic-gate scf_iter_destroy(iter); 1514*7c478bd9Sstevel@tonic-gate scf_property_destroy(prop); 1515*7c478bd9Sstevel@tonic-gate scf_pg_destroy(pg); 1516*7c478bd9Sstevel@tonic-gate 1517*7c478bd9Sstevel@tonic-gate return (ret); 1518*7c478bd9Sstevel@tonic-gate } 1519*7c478bd9Sstevel@tonic-gate 1520*7c478bd9Sstevel@tonic-gate int 1521*7c478bd9Sstevel@tonic-gate restarter_rm_libs_loadable() 1522*7c478bd9Sstevel@tonic-gate { 1523*7c478bd9Sstevel@tonic-gate void *libhndl; 1524*7c478bd9Sstevel@tonic-gate 1525*7c478bd9Sstevel@tonic-gate if (method_context_safety) 1526*7c478bd9Sstevel@tonic-gate return (1); 1527*7c478bd9Sstevel@tonic-gate 1528*7c478bd9Sstevel@tonic-gate if ((libhndl = dlopen("libpool.so", RTLD_LAZY | RTLD_LOCAL)) == NULL) 1529*7c478bd9Sstevel@tonic-gate return (0); 1530*7c478bd9Sstevel@tonic-gate 1531*7c478bd9Sstevel@tonic-gate (void) dlclose(libhndl); 1532*7c478bd9Sstevel@tonic-gate 1533*7c478bd9Sstevel@tonic-gate if ((libhndl = dlopen("libproject.so", RTLD_LAZY | RTLD_LOCAL)) == NULL) 1534*7c478bd9Sstevel@tonic-gate return (0); 1535*7c478bd9Sstevel@tonic-gate 1536*7c478bd9Sstevel@tonic-gate (void) dlclose(libhndl); 1537*7c478bd9Sstevel@tonic-gate 1538*7c478bd9Sstevel@tonic-gate method_context_safety = 1; 1539*7c478bd9Sstevel@tonic-gate 1540*7c478bd9Sstevel@tonic-gate return (1); 1541*7c478bd9Sstevel@tonic-gate } 1542*7c478bd9Sstevel@tonic-gate 1543*7c478bd9Sstevel@tonic-gate 1544*7c478bd9Sstevel@tonic-gate static int 1545*7c478bd9Sstevel@tonic-gate get_astring_val(scf_propertygroup_t *pg, const char *name, char *buf, 1546*7c478bd9Sstevel@tonic-gate size_t bufsz, scf_property_t *prop, scf_value_t *val) 1547*7c478bd9Sstevel@tonic-gate { 1548*7c478bd9Sstevel@tonic-gate ssize_t szret; 1549*7c478bd9Sstevel@tonic-gate 1550*7c478bd9Sstevel@tonic-gate if (scf_pg_get_property(pg, name, prop) != SCF_SUCCESS) { 1551*7c478bd9Sstevel@tonic-gate if (scf_error() == SCF_ERROR_CONNECTION_BROKEN) 1552*7c478bd9Sstevel@tonic-gate uu_die(rcbroken); 1553*7c478bd9Sstevel@tonic-gate return (-1); 1554*7c478bd9Sstevel@tonic-gate } 1555*7c478bd9Sstevel@tonic-gate 1556*7c478bd9Sstevel@tonic-gate if (scf_property_get_value(prop, val) != SCF_SUCCESS) { 1557*7c478bd9Sstevel@tonic-gate if (scf_error() == SCF_ERROR_CONNECTION_BROKEN) 1558*7c478bd9Sstevel@tonic-gate uu_die(rcbroken); 1559*7c478bd9Sstevel@tonic-gate return (-1); 1560*7c478bd9Sstevel@tonic-gate } 1561*7c478bd9Sstevel@tonic-gate 1562*7c478bd9Sstevel@tonic-gate szret = scf_value_get_astring(val, buf, bufsz); 1563*7c478bd9Sstevel@tonic-gate 1564*7c478bd9Sstevel@tonic-gate return (szret >= 0 ? 0 : -1); 1565*7c478bd9Sstevel@tonic-gate } 1566*7c478bd9Sstevel@tonic-gate 1567*7c478bd9Sstevel@tonic-gate /* 1568*7c478bd9Sstevel@tonic-gate * Try to load mcp->pwd, if it isn't already. 1569*7c478bd9Sstevel@tonic-gate * Fails with 1570*7c478bd9Sstevel@tonic-gate * ENOMEM - malloc() failed 1571*7c478bd9Sstevel@tonic-gate * ENOENT - no entry found 1572*7c478bd9Sstevel@tonic-gate * EIO - I/O error 1573*7c478bd9Sstevel@tonic-gate * EMFILE - process out of file descriptors 1574*7c478bd9Sstevel@tonic-gate * ENFILE - system out of file handles 1575*7c478bd9Sstevel@tonic-gate */ 1576*7c478bd9Sstevel@tonic-gate static int 1577*7c478bd9Sstevel@tonic-gate lookup_pwd(struct method_context *mcp) 1578*7c478bd9Sstevel@tonic-gate { 1579*7c478bd9Sstevel@tonic-gate struct passwd *pwdp; 1580*7c478bd9Sstevel@tonic-gate 1581*7c478bd9Sstevel@tonic-gate if (mcp->pwbuf != NULL && mcp->pwd.pw_uid == mcp->uid) 1582*7c478bd9Sstevel@tonic-gate return (0); 1583*7c478bd9Sstevel@tonic-gate 1584*7c478bd9Sstevel@tonic-gate if (mcp->pwbuf == NULL) { 1585*7c478bd9Sstevel@tonic-gate mcp->pwbufsz = sysconf(_SC_GETPW_R_SIZE_MAX); 1586*7c478bd9Sstevel@tonic-gate assert(mcp->pwbufsz >= 0); 1587*7c478bd9Sstevel@tonic-gate mcp->pwbuf = malloc(mcp->pwbufsz); 1588*7c478bd9Sstevel@tonic-gate if (mcp->pwbuf == NULL) 1589*7c478bd9Sstevel@tonic-gate return (ENOMEM); 1590*7c478bd9Sstevel@tonic-gate } 1591*7c478bd9Sstevel@tonic-gate 1592*7c478bd9Sstevel@tonic-gate do { 1593*7c478bd9Sstevel@tonic-gate errno = 0; 1594*7c478bd9Sstevel@tonic-gate pwdp = getpwuid_r(mcp->uid, &mcp->pwd, mcp->pwbuf, 1595*7c478bd9Sstevel@tonic-gate mcp->pwbufsz); 1596*7c478bd9Sstevel@tonic-gate } while (pwdp == NULL && errno == EINTR); 1597*7c478bd9Sstevel@tonic-gate if (pwdp != NULL) 1598*7c478bd9Sstevel@tonic-gate return (0); 1599*7c478bd9Sstevel@tonic-gate 1600*7c478bd9Sstevel@tonic-gate free(mcp->pwbuf); 1601*7c478bd9Sstevel@tonic-gate mcp->pwbuf = NULL; 1602*7c478bd9Sstevel@tonic-gate 1603*7c478bd9Sstevel@tonic-gate switch (errno) { 1604*7c478bd9Sstevel@tonic-gate case 0: 1605*7c478bd9Sstevel@tonic-gate default: 1606*7c478bd9Sstevel@tonic-gate /* 1607*7c478bd9Sstevel@tonic-gate * Until bug 5065780 is fixed, getpwuid_r() can fail with 1608*7c478bd9Sstevel@tonic-gate * ENOENT, particularly on the miniroot. Since the 1609*7c478bd9Sstevel@tonic-gate * documentation is inaccurate, we'll return ENOENT for unknown 1610*7c478bd9Sstevel@tonic-gate * errors. 1611*7c478bd9Sstevel@tonic-gate */ 1612*7c478bd9Sstevel@tonic-gate return (ENOENT); 1613*7c478bd9Sstevel@tonic-gate 1614*7c478bd9Sstevel@tonic-gate case EIO: 1615*7c478bd9Sstevel@tonic-gate case EMFILE: 1616*7c478bd9Sstevel@tonic-gate case ENFILE: 1617*7c478bd9Sstevel@tonic-gate return (errno); 1618*7c478bd9Sstevel@tonic-gate 1619*7c478bd9Sstevel@tonic-gate case ERANGE: 1620*7c478bd9Sstevel@tonic-gate bad_fail("getpwuid_r", errno); 1621*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 1622*7c478bd9Sstevel@tonic-gate } 1623*7c478bd9Sstevel@tonic-gate } 1624*7c478bd9Sstevel@tonic-gate 1625*7c478bd9Sstevel@tonic-gate /* 1626*7c478bd9Sstevel@tonic-gate * Get the user id for str. Returns 0 on success or 1627*7c478bd9Sstevel@tonic-gate * ERANGE the uid is too big 1628*7c478bd9Sstevel@tonic-gate * EINVAL the string starts with a digit, but is not a valid uid 1629*7c478bd9Sstevel@tonic-gate * ENOMEM out of memory 1630*7c478bd9Sstevel@tonic-gate * ENOENT no passwd entry for str 1631*7c478bd9Sstevel@tonic-gate * EIO an I/O error has occurred 1632*7c478bd9Sstevel@tonic-gate * EMFILE/ENFILE out of file descriptors 1633*7c478bd9Sstevel@tonic-gate */ 1634*7c478bd9Sstevel@tonic-gate int 1635*7c478bd9Sstevel@tonic-gate get_uid(const char *str, struct method_context *ci, uid_t *uidp) 1636*7c478bd9Sstevel@tonic-gate { 1637*7c478bd9Sstevel@tonic-gate if (isdigit(str[0])) { 1638*7c478bd9Sstevel@tonic-gate uid_t uid; 1639*7c478bd9Sstevel@tonic-gate char *cp; 1640*7c478bd9Sstevel@tonic-gate 1641*7c478bd9Sstevel@tonic-gate errno = 0; 1642*7c478bd9Sstevel@tonic-gate uid = strtol(str, &cp, 10); 1643*7c478bd9Sstevel@tonic-gate 1644*7c478bd9Sstevel@tonic-gate if (uid == 0 && errno != 0) { 1645*7c478bd9Sstevel@tonic-gate assert(errno != EINVAL); 1646*7c478bd9Sstevel@tonic-gate return (errno); 1647*7c478bd9Sstevel@tonic-gate } 1648*7c478bd9Sstevel@tonic-gate 1649*7c478bd9Sstevel@tonic-gate for (; *cp != '\0'; ++cp) 1650*7c478bd9Sstevel@tonic-gate if (*cp != ' ' || *cp != '\t') 1651*7c478bd9Sstevel@tonic-gate return (EINVAL); 1652*7c478bd9Sstevel@tonic-gate 1653*7c478bd9Sstevel@tonic-gate if (uid > UID_MAX) 1654*7c478bd9Sstevel@tonic-gate return (EINVAL); 1655*7c478bd9Sstevel@tonic-gate 1656*7c478bd9Sstevel@tonic-gate *uidp = uid; 1657*7c478bd9Sstevel@tonic-gate return (0); 1658*7c478bd9Sstevel@tonic-gate } else { 1659*7c478bd9Sstevel@tonic-gate struct passwd *pwdp; 1660*7c478bd9Sstevel@tonic-gate 1661*7c478bd9Sstevel@tonic-gate if (ci->pwbuf == NULL) { 1662*7c478bd9Sstevel@tonic-gate ci->pwbufsz = sysconf(_SC_GETPW_R_SIZE_MAX); 1663*7c478bd9Sstevel@tonic-gate ci->pwbuf = malloc(ci->pwbufsz); 1664*7c478bd9Sstevel@tonic-gate if (ci->pwbuf == NULL) 1665*7c478bd9Sstevel@tonic-gate return (ENOMEM); 1666*7c478bd9Sstevel@tonic-gate } 1667*7c478bd9Sstevel@tonic-gate 1668*7c478bd9Sstevel@tonic-gate do { 1669*7c478bd9Sstevel@tonic-gate errno = 0; 1670*7c478bd9Sstevel@tonic-gate pwdp = 1671*7c478bd9Sstevel@tonic-gate getpwnam_r(str, &ci->pwd, ci->pwbuf, ci->pwbufsz); 1672*7c478bd9Sstevel@tonic-gate } while (pwdp == NULL && errno == EINTR); 1673*7c478bd9Sstevel@tonic-gate 1674*7c478bd9Sstevel@tonic-gate if (pwdp != NULL) { 1675*7c478bd9Sstevel@tonic-gate *uidp = ci->pwd.pw_uid; 1676*7c478bd9Sstevel@tonic-gate return (0); 1677*7c478bd9Sstevel@tonic-gate } else { 1678*7c478bd9Sstevel@tonic-gate free(ci->pwbuf); 1679*7c478bd9Sstevel@tonic-gate ci->pwbuf = NULL; 1680*7c478bd9Sstevel@tonic-gate switch (errno) { 1681*7c478bd9Sstevel@tonic-gate case 0: 1682*7c478bd9Sstevel@tonic-gate return (ENOENT); 1683*7c478bd9Sstevel@tonic-gate 1684*7c478bd9Sstevel@tonic-gate case ENOENT: 1685*7c478bd9Sstevel@tonic-gate case EIO: 1686*7c478bd9Sstevel@tonic-gate case EMFILE: 1687*7c478bd9Sstevel@tonic-gate case ENFILE: 1688*7c478bd9Sstevel@tonic-gate return (errno); 1689*7c478bd9Sstevel@tonic-gate 1690*7c478bd9Sstevel@tonic-gate case ERANGE: 1691*7c478bd9Sstevel@tonic-gate default: 1692*7c478bd9Sstevel@tonic-gate bad_fail("getpwnam_r", errno); 1693*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 1694*7c478bd9Sstevel@tonic-gate } 1695*7c478bd9Sstevel@tonic-gate } 1696*7c478bd9Sstevel@tonic-gate } 1697*7c478bd9Sstevel@tonic-gate } 1698*7c478bd9Sstevel@tonic-gate 1699*7c478bd9Sstevel@tonic-gate gid_t 1700*7c478bd9Sstevel@tonic-gate get_gid(const char *str) 1701*7c478bd9Sstevel@tonic-gate { 1702*7c478bd9Sstevel@tonic-gate if (isdigit(str[0])) { 1703*7c478bd9Sstevel@tonic-gate gid_t gid; 1704*7c478bd9Sstevel@tonic-gate char *cp; 1705*7c478bd9Sstevel@tonic-gate 1706*7c478bd9Sstevel@tonic-gate errno = 0; 1707*7c478bd9Sstevel@tonic-gate gid = strtol(str, &cp, 10); 1708*7c478bd9Sstevel@tonic-gate 1709*7c478bd9Sstevel@tonic-gate if (gid == 0 && errno != 0) 1710*7c478bd9Sstevel@tonic-gate return (-1); 1711*7c478bd9Sstevel@tonic-gate 1712*7c478bd9Sstevel@tonic-gate for (; *cp != '\0'; ++cp) 1713*7c478bd9Sstevel@tonic-gate if (*cp != ' ' || *cp != '\t') 1714*7c478bd9Sstevel@tonic-gate return (-1); 1715*7c478bd9Sstevel@tonic-gate 1716*7c478bd9Sstevel@tonic-gate return (gid); 1717*7c478bd9Sstevel@tonic-gate } else { 1718*7c478bd9Sstevel@tonic-gate struct group grp, *ret; 1719*7c478bd9Sstevel@tonic-gate char *buffer; 1720*7c478bd9Sstevel@tonic-gate size_t buflen; 1721*7c478bd9Sstevel@tonic-gate 1722*7c478bd9Sstevel@tonic-gate buflen = sysconf(_SC_GETGR_R_SIZE_MAX); 1723*7c478bd9Sstevel@tonic-gate buffer = malloc(buflen); 1724*7c478bd9Sstevel@tonic-gate if (buffer == NULL) 1725*7c478bd9Sstevel@tonic-gate uu_die(allocfail); 1726*7c478bd9Sstevel@tonic-gate 1727*7c478bd9Sstevel@tonic-gate errno = 0; 1728*7c478bd9Sstevel@tonic-gate ret = getgrnam_r(str, &grp, buffer, buflen); 1729*7c478bd9Sstevel@tonic-gate free(buffer); 1730*7c478bd9Sstevel@tonic-gate 1731*7c478bd9Sstevel@tonic-gate return (ret == NULL ? -1 : grp.gr_gid); 1732*7c478bd9Sstevel@tonic-gate } 1733*7c478bd9Sstevel@tonic-gate } 1734*7c478bd9Sstevel@tonic-gate 1735*7c478bd9Sstevel@tonic-gate /* 1736*7c478bd9Sstevel@tonic-gate * Fails with 1737*7c478bd9Sstevel@tonic-gate * ENOMEM - out of memory 1738*7c478bd9Sstevel@tonic-gate * ENOENT - no passwd entry 1739*7c478bd9Sstevel@tonic-gate * no project entry 1740*7c478bd9Sstevel@tonic-gate * EIO - an I/O error occurred 1741*7c478bd9Sstevel@tonic-gate * EMFILE - the process is out of file descriptors 1742*7c478bd9Sstevel@tonic-gate * ENFILE - the system is out of file handles 1743*7c478bd9Sstevel@tonic-gate * ERANGE - the project id is out of range 1744*7c478bd9Sstevel@tonic-gate * EINVAL - str is invalid 1745*7c478bd9Sstevel@tonic-gate * E2BIG - the project entry was too big 1746*7c478bd9Sstevel@tonic-gate * -1 - the name service switch is misconfigured 1747*7c478bd9Sstevel@tonic-gate */ 1748*7c478bd9Sstevel@tonic-gate int 1749*7c478bd9Sstevel@tonic-gate get_projid(const char *str, struct method_context *cip) 1750*7c478bd9Sstevel@tonic-gate { 1751*7c478bd9Sstevel@tonic-gate int ret; 1752*7c478bd9Sstevel@tonic-gate void *buf; 1753*7c478bd9Sstevel@tonic-gate const size_t bufsz = PROJECT_BUFSZ; 1754*7c478bd9Sstevel@tonic-gate struct project proj, *pp; 1755*7c478bd9Sstevel@tonic-gate 1756*7c478bd9Sstevel@tonic-gate if (strcmp(str, ":default") == 0) { 1757*7c478bd9Sstevel@tonic-gate if (cip->uid == 0) { 1758*7c478bd9Sstevel@tonic-gate /* Don't change project for root services */ 1759*7c478bd9Sstevel@tonic-gate cip->project = NULL; 1760*7c478bd9Sstevel@tonic-gate return (0); 1761*7c478bd9Sstevel@tonic-gate } 1762*7c478bd9Sstevel@tonic-gate 1763*7c478bd9Sstevel@tonic-gate switch (ret = lookup_pwd(cip)) { 1764*7c478bd9Sstevel@tonic-gate case 0: 1765*7c478bd9Sstevel@tonic-gate break; 1766*7c478bd9Sstevel@tonic-gate 1767*7c478bd9Sstevel@tonic-gate case ENOMEM: 1768*7c478bd9Sstevel@tonic-gate case ENOENT: 1769*7c478bd9Sstevel@tonic-gate case EIO: 1770*7c478bd9Sstevel@tonic-gate case EMFILE: 1771*7c478bd9Sstevel@tonic-gate case ENFILE: 1772*7c478bd9Sstevel@tonic-gate return (ret); 1773*7c478bd9Sstevel@tonic-gate 1774*7c478bd9Sstevel@tonic-gate default: 1775*7c478bd9Sstevel@tonic-gate bad_fail("lookup_pwd", ret); 1776*7c478bd9Sstevel@tonic-gate } 1777*7c478bd9Sstevel@tonic-gate 1778*7c478bd9Sstevel@tonic-gate buf = malloc(bufsz); 1779*7c478bd9Sstevel@tonic-gate if (buf == NULL) 1780*7c478bd9Sstevel@tonic-gate return (ENOMEM); 1781*7c478bd9Sstevel@tonic-gate 1782*7c478bd9Sstevel@tonic-gate do { 1783*7c478bd9Sstevel@tonic-gate errno = 0; 1784*7c478bd9Sstevel@tonic-gate pp = getdefaultproj(cip->pwd.pw_name, &proj, buf, 1785*7c478bd9Sstevel@tonic-gate bufsz); 1786*7c478bd9Sstevel@tonic-gate } while (pp == NULL && errno == EINTR); 1787*7c478bd9Sstevel@tonic-gate 1788*7c478bd9Sstevel@tonic-gate /* to be continued ... */ 1789*7c478bd9Sstevel@tonic-gate } else { 1790*7c478bd9Sstevel@tonic-gate projid_t projid; 1791*7c478bd9Sstevel@tonic-gate char *cp; 1792*7c478bd9Sstevel@tonic-gate 1793*7c478bd9Sstevel@tonic-gate if (!isdigit(str[0])) { 1794*7c478bd9Sstevel@tonic-gate cip->project = strdup(str); 1795*7c478bd9Sstevel@tonic-gate return (cip->project != NULL ? 0 : ENOMEM); 1796*7c478bd9Sstevel@tonic-gate } 1797*7c478bd9Sstevel@tonic-gate 1798*7c478bd9Sstevel@tonic-gate errno = 0; 1799*7c478bd9Sstevel@tonic-gate projid = strtol(str, &cp, 10); 1800*7c478bd9Sstevel@tonic-gate 1801*7c478bd9Sstevel@tonic-gate if (projid == 0 && errno != 0) { 1802*7c478bd9Sstevel@tonic-gate assert(errno == ERANGE); 1803*7c478bd9Sstevel@tonic-gate return (errno); 1804*7c478bd9Sstevel@tonic-gate } 1805*7c478bd9Sstevel@tonic-gate 1806*7c478bd9Sstevel@tonic-gate for (; *cp != '\0'; ++cp) 1807*7c478bd9Sstevel@tonic-gate if (*cp != ' ' || *cp != '\t') 1808*7c478bd9Sstevel@tonic-gate return (EINVAL); 1809*7c478bd9Sstevel@tonic-gate 1810*7c478bd9Sstevel@tonic-gate if (projid > MAXPROJID) 1811*7c478bd9Sstevel@tonic-gate return (ERANGE); 1812*7c478bd9Sstevel@tonic-gate 1813*7c478bd9Sstevel@tonic-gate buf = malloc(bufsz); 1814*7c478bd9Sstevel@tonic-gate if (buf == NULL) 1815*7c478bd9Sstevel@tonic-gate return (ENOMEM); 1816*7c478bd9Sstevel@tonic-gate 1817*7c478bd9Sstevel@tonic-gate do { 1818*7c478bd9Sstevel@tonic-gate errno = 0; 1819*7c478bd9Sstevel@tonic-gate pp = getprojbyid(projid, &proj, buf, bufsz); 1820*7c478bd9Sstevel@tonic-gate } while (pp == NULL && errno == EINTR); 1821*7c478bd9Sstevel@tonic-gate } 1822*7c478bd9Sstevel@tonic-gate 1823*7c478bd9Sstevel@tonic-gate if (pp) { 1824*7c478bd9Sstevel@tonic-gate cip->project = strdup(pp->pj_name); 1825*7c478bd9Sstevel@tonic-gate free(buf); 1826*7c478bd9Sstevel@tonic-gate return (cip->project != NULL ? 0 : ENOMEM); 1827*7c478bd9Sstevel@tonic-gate } 1828*7c478bd9Sstevel@tonic-gate 1829*7c478bd9Sstevel@tonic-gate free(buf); 1830*7c478bd9Sstevel@tonic-gate 1831*7c478bd9Sstevel@tonic-gate switch (errno) { 1832*7c478bd9Sstevel@tonic-gate case 0: 1833*7c478bd9Sstevel@tonic-gate return (ENOENT); 1834*7c478bd9Sstevel@tonic-gate 1835*7c478bd9Sstevel@tonic-gate case EIO: 1836*7c478bd9Sstevel@tonic-gate case EMFILE: 1837*7c478bd9Sstevel@tonic-gate case ENFILE: 1838*7c478bd9Sstevel@tonic-gate return (errno); 1839*7c478bd9Sstevel@tonic-gate 1840*7c478bd9Sstevel@tonic-gate case ERANGE: 1841*7c478bd9Sstevel@tonic-gate return (E2BIG); 1842*7c478bd9Sstevel@tonic-gate 1843*7c478bd9Sstevel@tonic-gate default: 1844*7c478bd9Sstevel@tonic-gate return (-1); 1845*7c478bd9Sstevel@tonic-gate } 1846*7c478bd9Sstevel@tonic-gate } 1847*7c478bd9Sstevel@tonic-gate 1848*7c478bd9Sstevel@tonic-gate /* 1849*7c478bd9Sstevel@tonic-gate * Parse the supp_groups property value and populate ci->groups. Returns 1850*7c478bd9Sstevel@tonic-gate * EINVAL (get_gid() failed for one of the components), E2BIG (the property has 1851*7c478bd9Sstevel@tonic-gate * more than NGROUPS_MAX-1 groups), or 0 on success. 1852*7c478bd9Sstevel@tonic-gate */ 1853*7c478bd9Sstevel@tonic-gate int 1854*7c478bd9Sstevel@tonic-gate get_groups(char *str, struct method_context *ci) 1855*7c478bd9Sstevel@tonic-gate { 1856*7c478bd9Sstevel@tonic-gate char *cp, *end, *next; 1857*7c478bd9Sstevel@tonic-gate uint_t i; 1858*7c478bd9Sstevel@tonic-gate 1859*7c478bd9Sstevel@tonic-gate const char * const whitespace = " \t"; 1860*7c478bd9Sstevel@tonic-gate const char * const illegal = ", \t"; 1861*7c478bd9Sstevel@tonic-gate 1862*7c478bd9Sstevel@tonic-gate if (str[0] == '\0') { 1863*7c478bd9Sstevel@tonic-gate ci->ngroups = 0; 1864*7c478bd9Sstevel@tonic-gate return (0); 1865*7c478bd9Sstevel@tonic-gate } 1866*7c478bd9Sstevel@tonic-gate 1867*7c478bd9Sstevel@tonic-gate for (cp = str, i = 0; *cp != '\0'; ) { 1868*7c478bd9Sstevel@tonic-gate /* skip whitespace */ 1869*7c478bd9Sstevel@tonic-gate cp += strspn(cp, whitespace); 1870*7c478bd9Sstevel@tonic-gate 1871*7c478bd9Sstevel@tonic-gate /* find the end */ 1872*7c478bd9Sstevel@tonic-gate end = cp + strcspn(cp, illegal); 1873*7c478bd9Sstevel@tonic-gate 1874*7c478bd9Sstevel@tonic-gate /* skip whitespace after end */ 1875*7c478bd9Sstevel@tonic-gate next = end + strspn(end, whitespace); 1876*7c478bd9Sstevel@tonic-gate 1877*7c478bd9Sstevel@tonic-gate /* if there's a comma, it separates the fields */ 1878*7c478bd9Sstevel@tonic-gate if (*next == ',') 1879*7c478bd9Sstevel@tonic-gate ++next; 1880*7c478bd9Sstevel@tonic-gate 1881*7c478bd9Sstevel@tonic-gate *end = '\0'; 1882*7c478bd9Sstevel@tonic-gate 1883*7c478bd9Sstevel@tonic-gate if ((ci->groups[i] = get_gid(cp)) == -1) { 1884*7c478bd9Sstevel@tonic-gate ci->ngroups = 0; 1885*7c478bd9Sstevel@tonic-gate return (EINVAL); 1886*7c478bd9Sstevel@tonic-gate } 1887*7c478bd9Sstevel@tonic-gate 1888*7c478bd9Sstevel@tonic-gate ++i; 1889*7c478bd9Sstevel@tonic-gate if (i > NGROUPS_MAX - 1) { 1890*7c478bd9Sstevel@tonic-gate ci->ngroups = 0; 1891*7c478bd9Sstevel@tonic-gate return (E2BIG); 1892*7c478bd9Sstevel@tonic-gate } 1893*7c478bd9Sstevel@tonic-gate 1894*7c478bd9Sstevel@tonic-gate cp = next; 1895*7c478bd9Sstevel@tonic-gate } 1896*7c478bd9Sstevel@tonic-gate 1897*7c478bd9Sstevel@tonic-gate ci->ngroups = i; 1898*7c478bd9Sstevel@tonic-gate return (0); 1899*7c478bd9Sstevel@tonic-gate } 1900*7c478bd9Sstevel@tonic-gate 1901*7c478bd9Sstevel@tonic-gate /* 1902*7c478bd9Sstevel@tonic-gate * Eventually, we will return a structured error in the case of 1903*7c478bd9Sstevel@tonic-gate * retryable or abortable failures such as memory allocation errors and 1904*7c478bd9Sstevel@tonic-gate * repository connection failures. For now, these failures are just 1905*7c478bd9Sstevel@tonic-gate * encoded in the failure string. 1906*7c478bd9Sstevel@tonic-gate */ 1907*7c478bd9Sstevel@tonic-gate static const char * 1908*7c478bd9Sstevel@tonic-gate get_profile(scf_propertygroup_t *pg, scf_property_t *prop, scf_value_t *val, 1909*7c478bd9Sstevel@tonic-gate const char *cmdline, struct method_context *ci) 1910*7c478bd9Sstevel@tonic-gate { 1911*7c478bd9Sstevel@tonic-gate char *buf = ci->vbuf; 1912*7c478bd9Sstevel@tonic-gate ssize_t buf_sz = ci->vbuf_sz; 1913*7c478bd9Sstevel@tonic-gate char cmd[PATH_MAX]; 1914*7c478bd9Sstevel@tonic-gate char *cp, *value; 1915*7c478bd9Sstevel@tonic-gate const char *cmdp; 1916*7c478bd9Sstevel@tonic-gate execattr_t *eap; 1917*7c478bd9Sstevel@tonic-gate char *errstr = NULL; 1918*7c478bd9Sstevel@tonic-gate 1919*7c478bd9Sstevel@tonic-gate if (get_astring_val(pg, SCF_PROPERTY_PROFILE, buf, buf_sz, prop, val) != 1920*7c478bd9Sstevel@tonic-gate 0) 1921*7c478bd9Sstevel@tonic-gate return ("Could not get profile property."); 1922*7c478bd9Sstevel@tonic-gate 1923*7c478bd9Sstevel@tonic-gate /* Extract the command from the command line. */ 1924*7c478bd9Sstevel@tonic-gate cp = strpbrk(cmdline, " \t"); 1925*7c478bd9Sstevel@tonic-gate 1926*7c478bd9Sstevel@tonic-gate if (cp == NULL) { 1927*7c478bd9Sstevel@tonic-gate cmdp = cmdline; 1928*7c478bd9Sstevel@tonic-gate } else { 1929*7c478bd9Sstevel@tonic-gate (void) strncpy(cmd, cmdline, cp - cmdline); 1930*7c478bd9Sstevel@tonic-gate cmd[cp - cmdline] = '\0'; 1931*7c478bd9Sstevel@tonic-gate cmdp = cmd; 1932*7c478bd9Sstevel@tonic-gate } 1933*7c478bd9Sstevel@tonic-gate 1934*7c478bd9Sstevel@tonic-gate /* Require that cmdp[0] == '/'? */ 1935*7c478bd9Sstevel@tonic-gate 1936*7c478bd9Sstevel@tonic-gate eap = getexecprof(buf, KV_COMMAND, cmdp, GET_ONE); 1937*7c478bd9Sstevel@tonic-gate if (eap == NULL) 1938*7c478bd9Sstevel@tonic-gate return ("Could not find profile."); 1939*7c478bd9Sstevel@tonic-gate 1940*7c478bd9Sstevel@tonic-gate /* Based on pfexec.c */ 1941*7c478bd9Sstevel@tonic-gate 1942*7c478bd9Sstevel@tonic-gate /* Get the euid first so we don't override ci->pwd for the uid. */ 1943*7c478bd9Sstevel@tonic-gate if ((value = kva_match(eap->attr, EXECATTR_EUID_KW)) != NULL) { 1944*7c478bd9Sstevel@tonic-gate if (get_uid(value, ci, &ci->euid) != 0) { 1945*7c478bd9Sstevel@tonic-gate ci->euid = -1; 1946*7c478bd9Sstevel@tonic-gate errstr = "Could not interpret profile euid."; 1947*7c478bd9Sstevel@tonic-gate goto out; 1948*7c478bd9Sstevel@tonic-gate } 1949*7c478bd9Sstevel@tonic-gate } 1950*7c478bd9Sstevel@tonic-gate 1951*7c478bd9Sstevel@tonic-gate if ((value = kva_match(eap->attr, EXECATTR_UID_KW)) != NULL) { 1952*7c478bd9Sstevel@tonic-gate if (get_uid(value, ci, &ci->uid) != 0) { 1953*7c478bd9Sstevel@tonic-gate ci->euid = ci->uid = -1; 1954*7c478bd9Sstevel@tonic-gate errstr = "Could not interpret profile uid."; 1955*7c478bd9Sstevel@tonic-gate goto out; 1956*7c478bd9Sstevel@tonic-gate } 1957*7c478bd9Sstevel@tonic-gate ci->euid = ci->uid; 1958*7c478bd9Sstevel@tonic-gate } 1959*7c478bd9Sstevel@tonic-gate 1960*7c478bd9Sstevel@tonic-gate if ((value = kva_match(eap->attr, EXECATTR_GID_KW)) != NULL) { 1961*7c478bd9Sstevel@tonic-gate ci->egid = ci->gid = get_gid(value); 1962*7c478bd9Sstevel@tonic-gate if (ci->gid == -1) { 1963*7c478bd9Sstevel@tonic-gate errstr = "Could not interpret profile gid."; 1964*7c478bd9Sstevel@tonic-gate goto out; 1965*7c478bd9Sstevel@tonic-gate } 1966*7c478bd9Sstevel@tonic-gate } 1967*7c478bd9Sstevel@tonic-gate 1968*7c478bd9Sstevel@tonic-gate if ((value = kva_match(eap->attr, EXECATTR_EGID_KW)) != NULL) { 1969*7c478bd9Sstevel@tonic-gate ci->egid = get_gid(value); 1970*7c478bd9Sstevel@tonic-gate if (ci->egid == -1) { 1971*7c478bd9Sstevel@tonic-gate errstr = "Could not interpret profile egid."; 1972*7c478bd9Sstevel@tonic-gate goto out; 1973*7c478bd9Sstevel@tonic-gate } 1974*7c478bd9Sstevel@tonic-gate } 1975*7c478bd9Sstevel@tonic-gate 1976*7c478bd9Sstevel@tonic-gate if ((value = kva_match(eap->attr, EXECATTR_LPRIV_KW)) != NULL) { 1977*7c478bd9Sstevel@tonic-gate ci->lpriv_set = priv_str_to_set(value, ",", NULL); 1978*7c478bd9Sstevel@tonic-gate if (ci->lpriv_set == NULL) { 1979*7c478bd9Sstevel@tonic-gate if (errno != EINVAL) 1980*7c478bd9Sstevel@tonic-gate errstr = ALLOCFAIL; 1981*7c478bd9Sstevel@tonic-gate else 1982*7c478bd9Sstevel@tonic-gate errstr = "Could not interpret profile " 1983*7c478bd9Sstevel@tonic-gate "limitprivs."; 1984*7c478bd9Sstevel@tonic-gate goto out; 1985*7c478bd9Sstevel@tonic-gate } 1986*7c478bd9Sstevel@tonic-gate } 1987*7c478bd9Sstevel@tonic-gate 1988*7c478bd9Sstevel@tonic-gate if ((value = kva_match(eap->attr, EXECATTR_IPRIV_KW)) != NULL) { 1989*7c478bd9Sstevel@tonic-gate ci->priv_set = priv_str_to_set(value, ",", NULL); 1990*7c478bd9Sstevel@tonic-gate if (ci->priv_set == NULL) { 1991*7c478bd9Sstevel@tonic-gate if (errno != EINVAL) 1992*7c478bd9Sstevel@tonic-gate errstr = ALLOCFAIL; 1993*7c478bd9Sstevel@tonic-gate else 1994*7c478bd9Sstevel@tonic-gate errstr = "Could not interpret profile privs."; 1995*7c478bd9Sstevel@tonic-gate goto out; 1996*7c478bd9Sstevel@tonic-gate } 1997*7c478bd9Sstevel@tonic-gate } 1998*7c478bd9Sstevel@tonic-gate 1999*7c478bd9Sstevel@tonic-gate out: 2000*7c478bd9Sstevel@tonic-gate free_execattr(eap); 2001*7c478bd9Sstevel@tonic-gate 2002*7c478bd9Sstevel@tonic-gate return (errstr); 2003*7c478bd9Sstevel@tonic-gate } 2004*7c478bd9Sstevel@tonic-gate 2005*7c478bd9Sstevel@tonic-gate /* 2006*7c478bd9Sstevel@tonic-gate * Eventually, we will return a structured error in the case of 2007*7c478bd9Sstevel@tonic-gate * retryable or abortable failures such as memory allocation errors and 2008*7c478bd9Sstevel@tonic-gate * repository connection failures. For now, these failures are just 2009*7c478bd9Sstevel@tonic-gate * encoded in the failure string. 2010*7c478bd9Sstevel@tonic-gate */ 2011*7c478bd9Sstevel@tonic-gate static const char * 2012*7c478bd9Sstevel@tonic-gate get_ids(scf_propertygroup_t *pg, scf_property_t *prop, scf_value_t *val, 2013*7c478bd9Sstevel@tonic-gate struct method_context *ci) 2014*7c478bd9Sstevel@tonic-gate { 2015*7c478bd9Sstevel@tonic-gate const char *errstr = NULL; 2016*7c478bd9Sstevel@tonic-gate char *vbuf = ci->vbuf; 2017*7c478bd9Sstevel@tonic-gate ssize_t vbuf_sz = ci->vbuf_sz; 2018*7c478bd9Sstevel@tonic-gate int r; 2019*7c478bd9Sstevel@tonic-gate 2020*7c478bd9Sstevel@tonic-gate if (get_astring_val(pg, SCF_PROPERTY_USER, vbuf, vbuf_sz, prop, val) != 2021*7c478bd9Sstevel@tonic-gate 0) { 2022*7c478bd9Sstevel@tonic-gate errstr = "Could not get user property."; 2023*7c478bd9Sstevel@tonic-gate goto out; 2024*7c478bd9Sstevel@tonic-gate } 2025*7c478bd9Sstevel@tonic-gate 2026*7c478bd9Sstevel@tonic-gate if (get_uid(vbuf, ci, &ci->uid) != 0) { 2027*7c478bd9Sstevel@tonic-gate ci->uid = -1; 2028*7c478bd9Sstevel@tonic-gate errstr = "Could not interpret user property."; 2029*7c478bd9Sstevel@tonic-gate goto out; 2030*7c478bd9Sstevel@tonic-gate } 2031*7c478bd9Sstevel@tonic-gate 2032*7c478bd9Sstevel@tonic-gate if (get_astring_val(pg, SCF_PROPERTY_GROUP, vbuf, vbuf_sz, prop, val) != 2033*7c478bd9Sstevel@tonic-gate 0) { 2034*7c478bd9Sstevel@tonic-gate errstr = "Could not get group property."; 2035*7c478bd9Sstevel@tonic-gate goto out; 2036*7c478bd9Sstevel@tonic-gate } 2037*7c478bd9Sstevel@tonic-gate 2038*7c478bd9Sstevel@tonic-gate if (strcmp(vbuf, ":default") != 0) { 2039*7c478bd9Sstevel@tonic-gate ci->gid = get_gid(vbuf); 2040*7c478bd9Sstevel@tonic-gate if (ci->gid == -1) { 2041*7c478bd9Sstevel@tonic-gate errstr = "Could not interpret group property."; 2042*7c478bd9Sstevel@tonic-gate goto out; 2043*7c478bd9Sstevel@tonic-gate } 2044*7c478bd9Sstevel@tonic-gate } else { 2045*7c478bd9Sstevel@tonic-gate switch (r = lookup_pwd(ci)) { 2046*7c478bd9Sstevel@tonic-gate case 0: 2047*7c478bd9Sstevel@tonic-gate ci->gid = ci->pwd.pw_gid; 2048*7c478bd9Sstevel@tonic-gate break; 2049*7c478bd9Sstevel@tonic-gate 2050*7c478bd9Sstevel@tonic-gate case ENOENT: 2051*7c478bd9Sstevel@tonic-gate ci->gid = -1; 2052*7c478bd9Sstevel@tonic-gate errstr = "No passwd entry."; 2053*7c478bd9Sstevel@tonic-gate goto out; 2054*7c478bd9Sstevel@tonic-gate 2055*7c478bd9Sstevel@tonic-gate case ENOMEM: 2056*7c478bd9Sstevel@tonic-gate errstr = "Out of memory."; 2057*7c478bd9Sstevel@tonic-gate goto out; 2058*7c478bd9Sstevel@tonic-gate 2059*7c478bd9Sstevel@tonic-gate case EIO: 2060*7c478bd9Sstevel@tonic-gate case EMFILE: 2061*7c478bd9Sstevel@tonic-gate case ENFILE: 2062*7c478bd9Sstevel@tonic-gate errstr = "getpwuid_r() failed."; 2063*7c478bd9Sstevel@tonic-gate goto out; 2064*7c478bd9Sstevel@tonic-gate 2065*7c478bd9Sstevel@tonic-gate default: 2066*7c478bd9Sstevel@tonic-gate bad_fail("lookup_pwd", r); 2067*7c478bd9Sstevel@tonic-gate } 2068*7c478bd9Sstevel@tonic-gate } 2069*7c478bd9Sstevel@tonic-gate 2070*7c478bd9Sstevel@tonic-gate if (get_astring_val(pg, SCF_PROPERTY_SUPP_GROUPS, vbuf, vbuf_sz, prop, 2071*7c478bd9Sstevel@tonic-gate val) != 0) { 2072*7c478bd9Sstevel@tonic-gate errstr = "Could not get supplemental groups property."; 2073*7c478bd9Sstevel@tonic-gate goto out; 2074*7c478bd9Sstevel@tonic-gate } 2075*7c478bd9Sstevel@tonic-gate 2076*7c478bd9Sstevel@tonic-gate if (strcmp(vbuf, ":default") != 0) { 2077*7c478bd9Sstevel@tonic-gate switch (r = get_groups(vbuf, ci)) { 2078*7c478bd9Sstevel@tonic-gate case 0: 2079*7c478bd9Sstevel@tonic-gate break; 2080*7c478bd9Sstevel@tonic-gate 2081*7c478bd9Sstevel@tonic-gate case EINVAL: 2082*7c478bd9Sstevel@tonic-gate errstr = 2083*7c478bd9Sstevel@tonic-gate "Could not interpret supplemental groups property."; 2084*7c478bd9Sstevel@tonic-gate goto out; 2085*7c478bd9Sstevel@tonic-gate 2086*7c478bd9Sstevel@tonic-gate case E2BIG: 2087*7c478bd9Sstevel@tonic-gate errstr = "Too many supplemental groups."; 2088*7c478bd9Sstevel@tonic-gate goto out; 2089*7c478bd9Sstevel@tonic-gate 2090*7c478bd9Sstevel@tonic-gate default: 2091*7c478bd9Sstevel@tonic-gate bad_fail("get_groups", r); 2092*7c478bd9Sstevel@tonic-gate } 2093*7c478bd9Sstevel@tonic-gate } else { 2094*7c478bd9Sstevel@tonic-gate ci->ngroups = -1; 2095*7c478bd9Sstevel@tonic-gate } 2096*7c478bd9Sstevel@tonic-gate 2097*7c478bd9Sstevel@tonic-gate if (get_astring_val(pg, SCF_PROPERTY_PRIVILEGES, vbuf, vbuf_sz, prop, 2098*7c478bd9Sstevel@tonic-gate val) != 0) { 2099*7c478bd9Sstevel@tonic-gate errstr = "Could not get privileges property."; 2100*7c478bd9Sstevel@tonic-gate goto out; 2101*7c478bd9Sstevel@tonic-gate } 2102*7c478bd9Sstevel@tonic-gate 2103*7c478bd9Sstevel@tonic-gate /* 2104*7c478bd9Sstevel@tonic-gate * For default privs, we need to keep priv_set == NULL, as 2105*7c478bd9Sstevel@tonic-gate * we use this test elsewhere. 2106*7c478bd9Sstevel@tonic-gate */ 2107*7c478bd9Sstevel@tonic-gate if (strcmp(vbuf, ":default") != 0) { 2108*7c478bd9Sstevel@tonic-gate ci->priv_set = priv_str_to_set(vbuf, ",", NULL); 2109*7c478bd9Sstevel@tonic-gate if (ci->priv_set == NULL) { 2110*7c478bd9Sstevel@tonic-gate if (errno != EINVAL) { 2111*7c478bd9Sstevel@tonic-gate errstr = ALLOCFAIL; 2112*7c478bd9Sstevel@tonic-gate } else { 2113*7c478bd9Sstevel@tonic-gate errstr = "Could not interpret privileges " 2114*7c478bd9Sstevel@tonic-gate "property."; 2115*7c478bd9Sstevel@tonic-gate } 2116*7c478bd9Sstevel@tonic-gate goto out; 2117*7c478bd9Sstevel@tonic-gate } 2118*7c478bd9Sstevel@tonic-gate } 2119*7c478bd9Sstevel@tonic-gate 2120*7c478bd9Sstevel@tonic-gate if (get_astring_val(pg, SCF_PROPERTY_LIMIT_PRIVILEGES, vbuf, vbuf_sz, 2121*7c478bd9Sstevel@tonic-gate prop, val) != 0) { 2122*7c478bd9Sstevel@tonic-gate errstr = "Could not get limit_privileges property."; 2123*7c478bd9Sstevel@tonic-gate goto out; 2124*7c478bd9Sstevel@tonic-gate } 2125*7c478bd9Sstevel@tonic-gate 2126*7c478bd9Sstevel@tonic-gate if (strcmp(vbuf, ":default") == 0) 2127*7c478bd9Sstevel@tonic-gate /* 2128*7c478bd9Sstevel@tonic-gate * L must default to all privileges so root NPA services see 2129*7c478bd9Sstevel@tonic-gate * iE = all. "zone" is all privileges available in the current 2130*7c478bd9Sstevel@tonic-gate * zone, equivalent to "all" in the global zone. 2131*7c478bd9Sstevel@tonic-gate */ 2132*7c478bd9Sstevel@tonic-gate (void) strcpy(vbuf, "zone"); 2133*7c478bd9Sstevel@tonic-gate 2134*7c478bd9Sstevel@tonic-gate ci->lpriv_set = priv_str_to_set(vbuf, ",", NULL); 2135*7c478bd9Sstevel@tonic-gate if (ci->lpriv_set == NULL) { 2136*7c478bd9Sstevel@tonic-gate if (errno != EINVAL) 2137*7c478bd9Sstevel@tonic-gate errstr = ALLOCFAIL; 2138*7c478bd9Sstevel@tonic-gate else { 2139*7c478bd9Sstevel@tonic-gate errstr = "Could not interpret limit_privileges " 2140*7c478bd9Sstevel@tonic-gate "property."; 2141*7c478bd9Sstevel@tonic-gate } 2142*7c478bd9Sstevel@tonic-gate goto out; 2143*7c478bd9Sstevel@tonic-gate } 2144*7c478bd9Sstevel@tonic-gate 2145*7c478bd9Sstevel@tonic-gate out: 2146*7c478bd9Sstevel@tonic-gate return (errstr); 2147*7c478bd9Sstevel@tonic-gate } 2148*7c478bd9Sstevel@tonic-gate 2149*7c478bd9Sstevel@tonic-gate static int 2150*7c478bd9Sstevel@tonic-gate get_environment(scf_handle_t *h, scf_propertygroup_t *pg, 2151*7c478bd9Sstevel@tonic-gate struct method_context *mcp, scf_property_t *prop, scf_value_t *val) 2152*7c478bd9Sstevel@tonic-gate { 2153*7c478bd9Sstevel@tonic-gate scf_iter_t *iter; 2154*7c478bd9Sstevel@tonic-gate scf_type_t type; 2155*7c478bd9Sstevel@tonic-gate size_t i = 0; 2156*7c478bd9Sstevel@tonic-gate int ret; 2157*7c478bd9Sstevel@tonic-gate 2158*7c478bd9Sstevel@tonic-gate if (scf_pg_get_property(pg, SCF_PROPERTY_ENVIRONMENT, prop) != 0) { 2159*7c478bd9Sstevel@tonic-gate if (scf_error() == SCF_ERROR_NOT_FOUND) 2160*7c478bd9Sstevel@tonic-gate return (ENOENT); 2161*7c478bd9Sstevel@tonic-gate return (scf_error()); 2162*7c478bd9Sstevel@tonic-gate } 2163*7c478bd9Sstevel@tonic-gate if (scf_property_type(prop, &type) != 0) 2164*7c478bd9Sstevel@tonic-gate return (scf_error()); 2165*7c478bd9Sstevel@tonic-gate if (type != SCF_TYPE_ASTRING) 2166*7c478bd9Sstevel@tonic-gate return (EINVAL); 2167*7c478bd9Sstevel@tonic-gate if ((iter = scf_iter_create(h)) == NULL) 2168*7c478bd9Sstevel@tonic-gate return (scf_error()); 2169*7c478bd9Sstevel@tonic-gate 2170*7c478bd9Sstevel@tonic-gate if (scf_iter_property_values(iter, prop) != 0) { 2171*7c478bd9Sstevel@tonic-gate ret = scf_error(); 2172*7c478bd9Sstevel@tonic-gate scf_iter_destroy(iter); 2173*7c478bd9Sstevel@tonic-gate return (ret); 2174*7c478bd9Sstevel@tonic-gate } 2175*7c478bd9Sstevel@tonic-gate 2176*7c478bd9Sstevel@tonic-gate mcp->env_sz = 10; 2177*7c478bd9Sstevel@tonic-gate 2178*7c478bd9Sstevel@tonic-gate if ((mcp->env = uu_zalloc(sizeof (*mcp->env) * mcp->env_sz)) == NULL) { 2179*7c478bd9Sstevel@tonic-gate ret = ENOMEM; 2180*7c478bd9Sstevel@tonic-gate goto out; 2181*7c478bd9Sstevel@tonic-gate } 2182*7c478bd9Sstevel@tonic-gate 2183*7c478bd9Sstevel@tonic-gate while ((ret = scf_iter_next_value(iter, val)) == 1) { 2184*7c478bd9Sstevel@tonic-gate ret = scf_value_get_as_string(val, mcp->vbuf, mcp->vbuf_sz); 2185*7c478bd9Sstevel@tonic-gate if (ret == -1) { 2186*7c478bd9Sstevel@tonic-gate ret = scf_error(); 2187*7c478bd9Sstevel@tonic-gate goto out; 2188*7c478bd9Sstevel@tonic-gate } 2189*7c478bd9Sstevel@tonic-gate 2190*7c478bd9Sstevel@tonic-gate if ((mcp->env[i] = strdup(mcp->vbuf)) == NULL) { 2191*7c478bd9Sstevel@tonic-gate ret = ENOMEM; 2192*7c478bd9Sstevel@tonic-gate goto out; 2193*7c478bd9Sstevel@tonic-gate } 2194*7c478bd9Sstevel@tonic-gate 2195*7c478bd9Sstevel@tonic-gate if (++i == mcp->env_sz) { 2196*7c478bd9Sstevel@tonic-gate char **env; 2197*7c478bd9Sstevel@tonic-gate mcp->env_sz *= 2; 2198*7c478bd9Sstevel@tonic-gate env = uu_zalloc(sizeof (*mcp->env) * mcp->env_sz); 2199*7c478bd9Sstevel@tonic-gate if (env == NULL) { 2200*7c478bd9Sstevel@tonic-gate ret = ENOMEM; 2201*7c478bd9Sstevel@tonic-gate goto out; 2202*7c478bd9Sstevel@tonic-gate } 2203*7c478bd9Sstevel@tonic-gate (void) memcpy(env, mcp->env, 2204*7c478bd9Sstevel@tonic-gate sizeof (*mcp->env) * (mcp->env_sz / 2)); 2205*7c478bd9Sstevel@tonic-gate free(mcp->env); 2206*7c478bd9Sstevel@tonic-gate mcp->env = env; 2207*7c478bd9Sstevel@tonic-gate } 2208*7c478bd9Sstevel@tonic-gate } 2209*7c478bd9Sstevel@tonic-gate 2210*7c478bd9Sstevel@tonic-gate if (ret == -1) 2211*7c478bd9Sstevel@tonic-gate ret = scf_error(); 2212*7c478bd9Sstevel@tonic-gate 2213*7c478bd9Sstevel@tonic-gate out: 2214*7c478bd9Sstevel@tonic-gate scf_iter_destroy(iter); 2215*7c478bd9Sstevel@tonic-gate return (ret); 2216*7c478bd9Sstevel@tonic-gate } 2217*7c478bd9Sstevel@tonic-gate 2218*7c478bd9Sstevel@tonic-gate /* 2219*7c478bd9Sstevel@tonic-gate * Fetch method context information from the repository, allocate and fill 2220*7c478bd9Sstevel@tonic-gate * a method_context structure, return it in *mcpp, and return NULL. On error, 2221*7c478bd9Sstevel@tonic-gate * return a human-readable string which indicates the error. 2222*7c478bd9Sstevel@tonic-gate * 2223*7c478bd9Sstevel@tonic-gate * Eventually, we will return a structured error in the case of 2224*7c478bd9Sstevel@tonic-gate * retryable or abortable failures such as memory allocation errors and 2225*7c478bd9Sstevel@tonic-gate * repository connection failures. For now, these failures are just 2226*7c478bd9Sstevel@tonic-gate * encoded in the failure string. 2227*7c478bd9Sstevel@tonic-gate */ 2228*7c478bd9Sstevel@tonic-gate const char * 2229*7c478bd9Sstevel@tonic-gate restarter_get_method_context(uint_t version, scf_instance_t *inst, 2230*7c478bd9Sstevel@tonic-gate scf_snapshot_t *snap, const char *mname, const char *cmdline, 2231*7c478bd9Sstevel@tonic-gate struct method_context **mcpp) 2232*7c478bd9Sstevel@tonic-gate { 2233*7c478bd9Sstevel@tonic-gate scf_handle_t *h; 2234*7c478bd9Sstevel@tonic-gate scf_propertygroup_t *methpg = NULL; 2235*7c478bd9Sstevel@tonic-gate scf_propertygroup_t *instpg = NULL; 2236*7c478bd9Sstevel@tonic-gate scf_propertygroup_t *pg = NULL; 2237*7c478bd9Sstevel@tonic-gate scf_property_t *prop = NULL; 2238*7c478bd9Sstevel@tonic-gate scf_value_t *val = NULL; 2239*7c478bd9Sstevel@tonic-gate scf_type_t ty; 2240*7c478bd9Sstevel@tonic-gate uint8_t use_profile; 2241*7c478bd9Sstevel@tonic-gate int ret; 2242*7c478bd9Sstevel@tonic-gate const char *errstr = NULL; 2243*7c478bd9Sstevel@tonic-gate struct method_context *cip; 2244*7c478bd9Sstevel@tonic-gate 2245*7c478bd9Sstevel@tonic-gate 2246*7c478bd9Sstevel@tonic-gate if (version != RESTARTER_METHOD_CONTEXT_VERSION) 2247*7c478bd9Sstevel@tonic-gate return ("Unknown method_context version."); 2248*7c478bd9Sstevel@tonic-gate 2249*7c478bd9Sstevel@tonic-gate /* Get the handle before we allocate anything. */ 2250*7c478bd9Sstevel@tonic-gate h = scf_instance_handle(inst); 2251*7c478bd9Sstevel@tonic-gate if (h == NULL) 2252*7c478bd9Sstevel@tonic-gate return (scf_strerror(scf_error())); 2253*7c478bd9Sstevel@tonic-gate 2254*7c478bd9Sstevel@tonic-gate cip = malloc(sizeof (*cip)); 2255*7c478bd9Sstevel@tonic-gate if (cip == NULL) 2256*7c478bd9Sstevel@tonic-gate return (ALLOCFAIL); 2257*7c478bd9Sstevel@tonic-gate 2258*7c478bd9Sstevel@tonic-gate (void) memset(cip, 0, sizeof (*cip)); 2259*7c478bd9Sstevel@tonic-gate cip->uid = -1; 2260*7c478bd9Sstevel@tonic-gate cip->euid = -1; 2261*7c478bd9Sstevel@tonic-gate cip->gid = -1; 2262*7c478bd9Sstevel@tonic-gate cip->egid = -1; 2263*7c478bd9Sstevel@tonic-gate 2264*7c478bd9Sstevel@tonic-gate cip->vbuf_sz = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH); 2265*7c478bd9Sstevel@tonic-gate assert(cip->vbuf_sz >= 0); 2266*7c478bd9Sstevel@tonic-gate cip->vbuf = malloc(cip->vbuf_sz); 2267*7c478bd9Sstevel@tonic-gate if (cip->vbuf == NULL) { 2268*7c478bd9Sstevel@tonic-gate free(cip); 2269*7c478bd9Sstevel@tonic-gate return (ALLOCFAIL); 2270*7c478bd9Sstevel@tonic-gate } 2271*7c478bd9Sstevel@tonic-gate 2272*7c478bd9Sstevel@tonic-gate if ((instpg = scf_pg_create(h)) == NULL || 2273*7c478bd9Sstevel@tonic-gate (methpg = scf_pg_create(h)) == NULL || 2274*7c478bd9Sstevel@tonic-gate (prop = scf_property_create(h)) == NULL || 2275*7c478bd9Sstevel@tonic-gate (val = scf_value_create(h)) == NULL) { 2276*7c478bd9Sstevel@tonic-gate errstr = ALLOCFAIL; 2277*7c478bd9Sstevel@tonic-gate goto out; 2278*7c478bd9Sstevel@tonic-gate } 2279*7c478bd9Sstevel@tonic-gate 2280*7c478bd9Sstevel@tonic-gate /* 2281*7c478bd9Sstevel@tonic-gate * The method environment, and the credentials/profile data, 2282*7c478bd9Sstevel@tonic-gate * may be found either in the pg for the method (methpg), 2283*7c478bd9Sstevel@tonic-gate * or in the instance/service SCF_PG_METHOD_CONTEXT pg (named 2284*7c478bd9Sstevel@tonic-gate * instpg below). 2285*7c478bd9Sstevel@tonic-gate */ 2286*7c478bd9Sstevel@tonic-gate 2287*7c478bd9Sstevel@tonic-gate if (scf_instance_get_pg_composed(inst, snap, mname, methpg) != 2288*7c478bd9Sstevel@tonic-gate SCF_SUCCESS) { 2289*7c478bd9Sstevel@tonic-gate errstr = scf_strerror(scf_error()); 2290*7c478bd9Sstevel@tonic-gate goto out; 2291*7c478bd9Sstevel@tonic-gate } 2292*7c478bd9Sstevel@tonic-gate 2293*7c478bd9Sstevel@tonic-gate if (scf_instance_get_pg_composed(inst, snap, SCF_PG_METHOD_CONTEXT, 2294*7c478bd9Sstevel@tonic-gate instpg) != SCF_SUCCESS) { 2295*7c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_NOT_FOUND) { 2296*7c478bd9Sstevel@tonic-gate errstr = scf_strerror(scf_error()); 2297*7c478bd9Sstevel@tonic-gate goto out; 2298*7c478bd9Sstevel@tonic-gate } 2299*7c478bd9Sstevel@tonic-gate scf_pg_destroy(instpg); 2300*7c478bd9Sstevel@tonic-gate instpg = NULL; 2301*7c478bd9Sstevel@tonic-gate } 2302*7c478bd9Sstevel@tonic-gate 2303*7c478bd9Sstevel@tonic-gate ret = get_environment(h, methpg, cip, prop, val); 2304*7c478bd9Sstevel@tonic-gate if (ret == ENOENT && instpg != NULL) { 2305*7c478bd9Sstevel@tonic-gate ret = get_environment(h, instpg, cip, prop, val); 2306*7c478bd9Sstevel@tonic-gate } 2307*7c478bd9Sstevel@tonic-gate 2308*7c478bd9Sstevel@tonic-gate switch (ret) { 2309*7c478bd9Sstevel@tonic-gate case 0: 2310*7c478bd9Sstevel@tonic-gate case ENOENT: 2311*7c478bd9Sstevel@tonic-gate break; 2312*7c478bd9Sstevel@tonic-gate case ENOMEM: 2313*7c478bd9Sstevel@tonic-gate errstr = "Out of memory."; 2314*7c478bd9Sstevel@tonic-gate goto out; 2315*7c478bd9Sstevel@tonic-gate case EINVAL: 2316*7c478bd9Sstevel@tonic-gate errstr = "Invalid method environment."; 2317*7c478bd9Sstevel@tonic-gate goto out; 2318*7c478bd9Sstevel@tonic-gate default: 2319*7c478bd9Sstevel@tonic-gate errstr = scf_strerror(ret); 2320*7c478bd9Sstevel@tonic-gate goto out; 2321*7c478bd9Sstevel@tonic-gate } 2322*7c478bd9Sstevel@tonic-gate 2323*7c478bd9Sstevel@tonic-gate pg = methpg; 2324*7c478bd9Sstevel@tonic-gate 2325*7c478bd9Sstevel@tonic-gate ret = scf_pg_get_property(pg, SCF_PROPERTY_USE_PROFILE, prop); 2326*7c478bd9Sstevel@tonic-gate if (ret && scf_error() == SCF_ERROR_NOT_FOUND && instpg != NULL) { 2327*7c478bd9Sstevel@tonic-gate pg = instpg; 2328*7c478bd9Sstevel@tonic-gate ret = scf_pg_get_property(pg, SCF_PROPERTY_USE_PROFILE, prop); 2329*7c478bd9Sstevel@tonic-gate } 2330*7c478bd9Sstevel@tonic-gate 2331*7c478bd9Sstevel@tonic-gate if (ret) { 2332*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 2333*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 2334*7c478bd9Sstevel@tonic-gate /* No context: use defaults */ 2335*7c478bd9Sstevel@tonic-gate cip->uid = 0; 2336*7c478bd9Sstevel@tonic-gate cip->gid = 0; 2337*7c478bd9Sstevel@tonic-gate *mcpp = cip; 2338*7c478bd9Sstevel@tonic-gate goto out; 2339*7c478bd9Sstevel@tonic-gate 2340*7c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 2341*7c478bd9Sstevel@tonic-gate errstr = RCBROKEN; 2342*7c478bd9Sstevel@tonic-gate goto out; 2343*7c478bd9Sstevel@tonic-gate 2344*7c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 2345*7c478bd9Sstevel@tonic-gate errstr = "\"use_profile\" property deleted."; 2346*7c478bd9Sstevel@tonic-gate goto out; 2347*7c478bd9Sstevel@tonic-gate 2348*7c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 2349*7c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 2350*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 2351*7c478bd9Sstevel@tonic-gate default: 2352*7c478bd9Sstevel@tonic-gate bad_fail("scf_pg_get_property", scf_error()); 2353*7c478bd9Sstevel@tonic-gate } 2354*7c478bd9Sstevel@tonic-gate } 2355*7c478bd9Sstevel@tonic-gate 2356*7c478bd9Sstevel@tonic-gate if (scf_property_type(prop, &ty) != SCF_SUCCESS) { 2357*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 2358*7c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 2359*7c478bd9Sstevel@tonic-gate errstr = RCBROKEN; 2360*7c478bd9Sstevel@tonic-gate break; 2361*7c478bd9Sstevel@tonic-gate 2362*7c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 2363*7c478bd9Sstevel@tonic-gate errstr = "\"use profile\" property deleted."; 2364*7c478bd9Sstevel@tonic-gate break; 2365*7c478bd9Sstevel@tonic-gate 2366*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 2367*7c478bd9Sstevel@tonic-gate default: 2368*7c478bd9Sstevel@tonic-gate bad_fail("scf_property_type", scf_error()); 2369*7c478bd9Sstevel@tonic-gate } 2370*7c478bd9Sstevel@tonic-gate 2371*7c478bd9Sstevel@tonic-gate goto out; 2372*7c478bd9Sstevel@tonic-gate } 2373*7c478bd9Sstevel@tonic-gate 2374*7c478bd9Sstevel@tonic-gate if (ty != SCF_TYPE_BOOLEAN) { 2375*7c478bd9Sstevel@tonic-gate errstr = "\"use profile\" property is not boolean."; 2376*7c478bd9Sstevel@tonic-gate goto out; 2377*7c478bd9Sstevel@tonic-gate } 2378*7c478bd9Sstevel@tonic-gate 2379*7c478bd9Sstevel@tonic-gate if (scf_property_get_value(prop, val) != SCF_SUCCESS) { 2380*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 2381*7c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 2382*7c478bd9Sstevel@tonic-gate errstr = RCBROKEN; 2383*7c478bd9Sstevel@tonic-gate break; 2384*7c478bd9Sstevel@tonic-gate 2385*7c478bd9Sstevel@tonic-gate case SCF_ERROR_CONSTRAINT_VIOLATED: 2386*7c478bd9Sstevel@tonic-gate errstr = 2387*7c478bd9Sstevel@tonic-gate "\"use profile\" property has multiple values."; 2388*7c478bd9Sstevel@tonic-gate break; 2389*7c478bd9Sstevel@tonic-gate 2390*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 2391*7c478bd9Sstevel@tonic-gate errstr = "\"use profile\" property has no values."; 2392*7c478bd9Sstevel@tonic-gate break; 2393*7c478bd9Sstevel@tonic-gate 2394*7c478bd9Sstevel@tonic-gate default: 2395*7c478bd9Sstevel@tonic-gate bad_fail("scf_property_get_value", scf_error()); 2396*7c478bd9Sstevel@tonic-gate } 2397*7c478bd9Sstevel@tonic-gate 2398*7c478bd9Sstevel@tonic-gate goto out; 2399*7c478bd9Sstevel@tonic-gate } 2400*7c478bd9Sstevel@tonic-gate 2401*7c478bd9Sstevel@tonic-gate ret = scf_value_get_boolean(val, &use_profile); 2402*7c478bd9Sstevel@tonic-gate assert(ret == SCF_SUCCESS); 2403*7c478bd9Sstevel@tonic-gate 2404*7c478bd9Sstevel@tonic-gate /* get ids & privileges */ 2405*7c478bd9Sstevel@tonic-gate if (use_profile) 2406*7c478bd9Sstevel@tonic-gate errstr = get_profile(pg, prop, val, cmdline, cip); 2407*7c478bd9Sstevel@tonic-gate else 2408*7c478bd9Sstevel@tonic-gate errstr = get_ids(pg, prop, val, cip); 2409*7c478bd9Sstevel@tonic-gate if (errstr != NULL) 2410*7c478bd9Sstevel@tonic-gate goto out; 2411*7c478bd9Sstevel@tonic-gate 2412*7c478bd9Sstevel@tonic-gate /* get working directory */ 2413*7c478bd9Sstevel@tonic-gate if (get_astring_val(pg, SCF_PROPERTY_WORKING_DIRECTORY, cip->vbuf, 2414*7c478bd9Sstevel@tonic-gate cip->vbuf_sz, prop, val) != 0) { 2415*7c478bd9Sstevel@tonic-gate errstr = "Could not get value for working directory."; 2416*7c478bd9Sstevel@tonic-gate goto out; 2417*7c478bd9Sstevel@tonic-gate } 2418*7c478bd9Sstevel@tonic-gate 2419*7c478bd9Sstevel@tonic-gate if (strcmp(cip->vbuf, ":default") == 0 || 2420*7c478bd9Sstevel@tonic-gate strcmp(cip->vbuf, ":home") == 0) { 2421*7c478bd9Sstevel@tonic-gate switch (ret = lookup_pwd(cip)) { 2422*7c478bd9Sstevel@tonic-gate case 0: 2423*7c478bd9Sstevel@tonic-gate break; 2424*7c478bd9Sstevel@tonic-gate 2425*7c478bd9Sstevel@tonic-gate case ENOMEM: 2426*7c478bd9Sstevel@tonic-gate errstr = "Out of memory."; 2427*7c478bd9Sstevel@tonic-gate goto out; 2428*7c478bd9Sstevel@tonic-gate 2429*7c478bd9Sstevel@tonic-gate case ENOENT: 2430*7c478bd9Sstevel@tonic-gate case EIO: 2431*7c478bd9Sstevel@tonic-gate case EMFILE: 2432*7c478bd9Sstevel@tonic-gate case ENFILE: 2433*7c478bd9Sstevel@tonic-gate errstr = "Could not get passwd entry."; 2434*7c478bd9Sstevel@tonic-gate goto out; 2435*7c478bd9Sstevel@tonic-gate 2436*7c478bd9Sstevel@tonic-gate default: 2437*7c478bd9Sstevel@tonic-gate bad_fail("lookup_pwd", ret); 2438*7c478bd9Sstevel@tonic-gate } 2439*7c478bd9Sstevel@tonic-gate 2440*7c478bd9Sstevel@tonic-gate cip->working_dir = strdup(cip->pwd.pw_dir); 2441*7c478bd9Sstevel@tonic-gate if (cip->working_dir == NULL) { 2442*7c478bd9Sstevel@tonic-gate errstr = ALLOCFAIL; 2443*7c478bd9Sstevel@tonic-gate goto out; 2444*7c478bd9Sstevel@tonic-gate } 2445*7c478bd9Sstevel@tonic-gate } else { 2446*7c478bd9Sstevel@tonic-gate cip->working_dir = strdup(cip->vbuf); 2447*7c478bd9Sstevel@tonic-gate if (cip->working_dir == NULL) { 2448*7c478bd9Sstevel@tonic-gate errstr = ALLOCFAIL; 2449*7c478bd9Sstevel@tonic-gate goto out; 2450*7c478bd9Sstevel@tonic-gate } 2451*7c478bd9Sstevel@tonic-gate } 2452*7c478bd9Sstevel@tonic-gate 2453*7c478bd9Sstevel@tonic-gate /* get (optional) corefile pattern */ 2454*7c478bd9Sstevel@tonic-gate if (scf_pg_get_property(pg, SCF_PROPERTY_COREFILE_PATTERN, prop) == 2455*7c478bd9Sstevel@tonic-gate SCF_SUCCESS) { 2456*7c478bd9Sstevel@tonic-gate if (get_astring_val(pg, SCF_PROPERTY_COREFILE_PATTERN, 2457*7c478bd9Sstevel@tonic-gate cip->vbuf, cip->vbuf_sz, prop, val) != 0) { 2458*7c478bd9Sstevel@tonic-gate errstr = "Could not get value for corefile pattern."; 2459*7c478bd9Sstevel@tonic-gate goto out; 2460*7c478bd9Sstevel@tonic-gate } 2461*7c478bd9Sstevel@tonic-gate 2462*7c478bd9Sstevel@tonic-gate cip->corefile_pattern = strdup(cip->vbuf); 2463*7c478bd9Sstevel@tonic-gate if (cip->corefile_pattern == NULL) { 2464*7c478bd9Sstevel@tonic-gate errstr = ALLOCFAIL; 2465*7c478bd9Sstevel@tonic-gate goto out; 2466*7c478bd9Sstevel@tonic-gate } 2467*7c478bd9Sstevel@tonic-gate } else { 2468*7c478bd9Sstevel@tonic-gate switch (scf_error()) { 2469*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 2470*7c478bd9Sstevel@tonic-gate /* okay if missing. */ 2471*7c478bd9Sstevel@tonic-gate break; 2472*7c478bd9Sstevel@tonic-gate 2473*7c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 2474*7c478bd9Sstevel@tonic-gate errstr = RCBROKEN; 2475*7c478bd9Sstevel@tonic-gate goto out; 2476*7c478bd9Sstevel@tonic-gate 2477*7c478bd9Sstevel@tonic-gate case SCF_ERROR_DELETED: 2478*7c478bd9Sstevel@tonic-gate errstr = "\"corefile_pattern\" property deleted."; 2479*7c478bd9Sstevel@tonic-gate goto out; 2480*7c478bd9Sstevel@tonic-gate 2481*7c478bd9Sstevel@tonic-gate case SCF_ERROR_HANDLE_MISMATCH: 2482*7c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 2483*7c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_SET: 2484*7c478bd9Sstevel@tonic-gate default: 2485*7c478bd9Sstevel@tonic-gate bad_fail("scf_pg_get_property", scf_error()); 2486*7c478bd9Sstevel@tonic-gate } 2487*7c478bd9Sstevel@tonic-gate } 2488*7c478bd9Sstevel@tonic-gate 2489*7c478bd9Sstevel@tonic-gate if (restarter_rm_libs_loadable()) { 2490*7c478bd9Sstevel@tonic-gate /* get project */ 2491*7c478bd9Sstevel@tonic-gate if (get_astring_val(pg, SCF_PROPERTY_PROJECT, cip->vbuf, 2492*7c478bd9Sstevel@tonic-gate cip->vbuf_sz, prop, val) != 0) { 2493*7c478bd9Sstevel@tonic-gate errstr = "Could not get project."; 2494*7c478bd9Sstevel@tonic-gate goto out; 2495*7c478bd9Sstevel@tonic-gate } 2496*7c478bd9Sstevel@tonic-gate 2497*7c478bd9Sstevel@tonic-gate switch (ret = get_projid(cip->vbuf, cip)) { 2498*7c478bd9Sstevel@tonic-gate case 0: 2499*7c478bd9Sstevel@tonic-gate break; 2500*7c478bd9Sstevel@tonic-gate 2501*7c478bd9Sstevel@tonic-gate case ENOMEM: 2502*7c478bd9Sstevel@tonic-gate errstr = "Out of memory."; 2503*7c478bd9Sstevel@tonic-gate goto out; 2504*7c478bd9Sstevel@tonic-gate 2505*7c478bd9Sstevel@tonic-gate case ENOENT: 2506*7c478bd9Sstevel@tonic-gate errstr = "Missing passwd or project entry."; 2507*7c478bd9Sstevel@tonic-gate goto out; 2508*7c478bd9Sstevel@tonic-gate 2509*7c478bd9Sstevel@tonic-gate case EIO: 2510*7c478bd9Sstevel@tonic-gate errstr = "I/O error."; 2511*7c478bd9Sstevel@tonic-gate goto out; 2512*7c478bd9Sstevel@tonic-gate 2513*7c478bd9Sstevel@tonic-gate case EMFILE: 2514*7c478bd9Sstevel@tonic-gate case ENFILE: 2515*7c478bd9Sstevel@tonic-gate errstr = "Out of file descriptors."; 2516*7c478bd9Sstevel@tonic-gate goto out; 2517*7c478bd9Sstevel@tonic-gate 2518*7c478bd9Sstevel@tonic-gate case -1: 2519*7c478bd9Sstevel@tonic-gate errstr = "Name service switch is misconfigured."; 2520*7c478bd9Sstevel@tonic-gate goto out; 2521*7c478bd9Sstevel@tonic-gate 2522*7c478bd9Sstevel@tonic-gate case ERANGE: 2523*7c478bd9Sstevel@tonic-gate errstr = "Project ID too big."; 2524*7c478bd9Sstevel@tonic-gate goto out; 2525*7c478bd9Sstevel@tonic-gate 2526*7c478bd9Sstevel@tonic-gate case EINVAL: 2527*7c478bd9Sstevel@tonic-gate errstr = "Project ID is invalid."; 2528*7c478bd9Sstevel@tonic-gate goto out; 2529*7c478bd9Sstevel@tonic-gate 2530*7c478bd9Sstevel@tonic-gate case E2BIG: 2531*7c478bd9Sstevel@tonic-gate errstr = "Project entry is too big."; 2532*7c478bd9Sstevel@tonic-gate goto out; 2533*7c478bd9Sstevel@tonic-gate 2534*7c478bd9Sstevel@tonic-gate default: 2535*7c478bd9Sstevel@tonic-gate bad_fail("get_projid", ret); 2536*7c478bd9Sstevel@tonic-gate } 2537*7c478bd9Sstevel@tonic-gate 2538*7c478bd9Sstevel@tonic-gate /* get resource pool */ 2539*7c478bd9Sstevel@tonic-gate if (get_astring_val(pg, SCF_PROPERTY_RESOURCE_POOL, cip->vbuf, 2540*7c478bd9Sstevel@tonic-gate cip->vbuf_sz, prop, val) != 0) { 2541*7c478bd9Sstevel@tonic-gate errstr = "Could not get value of resource pool."; 2542*7c478bd9Sstevel@tonic-gate goto out; 2543*7c478bd9Sstevel@tonic-gate } 2544*7c478bd9Sstevel@tonic-gate 2545*7c478bd9Sstevel@tonic-gate if (strcmp(cip->vbuf, ":default") != 0) { 2546*7c478bd9Sstevel@tonic-gate cip->resource_pool = strdup(cip->vbuf); 2547*7c478bd9Sstevel@tonic-gate if (cip->resource_pool == NULL) { 2548*7c478bd9Sstevel@tonic-gate errstr = ALLOCFAIL; 2549*7c478bd9Sstevel@tonic-gate goto out; 2550*7c478bd9Sstevel@tonic-gate } 2551*7c478bd9Sstevel@tonic-gate } 2552*7c478bd9Sstevel@tonic-gate } 2553*7c478bd9Sstevel@tonic-gate 2554*7c478bd9Sstevel@tonic-gate *mcpp = cip; 2555*7c478bd9Sstevel@tonic-gate 2556*7c478bd9Sstevel@tonic-gate out: 2557*7c478bd9Sstevel@tonic-gate (void) scf_value_destroy(val); 2558*7c478bd9Sstevel@tonic-gate scf_property_destroy(prop); 2559*7c478bd9Sstevel@tonic-gate scf_pg_destroy(instpg); 2560*7c478bd9Sstevel@tonic-gate scf_pg_destroy(methpg); 2561*7c478bd9Sstevel@tonic-gate 2562*7c478bd9Sstevel@tonic-gate if (cip->pwbuf != NULL) 2563*7c478bd9Sstevel@tonic-gate free(cip->pwbuf); 2564*7c478bd9Sstevel@tonic-gate free(cip->vbuf); 2565*7c478bd9Sstevel@tonic-gate 2566*7c478bd9Sstevel@tonic-gate if (errstr != NULL) 2567*7c478bd9Sstevel@tonic-gate restarter_free_method_context(cip); 2568*7c478bd9Sstevel@tonic-gate 2569*7c478bd9Sstevel@tonic-gate return (errstr); 2570*7c478bd9Sstevel@tonic-gate } 2571*7c478bd9Sstevel@tonic-gate 2572*7c478bd9Sstevel@tonic-gate /* 2573*7c478bd9Sstevel@tonic-gate * Modify the current process per the given method_context. On success, returns 2574*7c478bd9Sstevel@tonic-gate * 0. Note that the environment is not modified by this function to include the 2575*7c478bd9Sstevel@tonic-gate * environment variables in cip->env. 2576*7c478bd9Sstevel@tonic-gate * 2577*7c478bd9Sstevel@tonic-gate * On failure, sets *fp to NULL or the name of the function which failed, 2578*7c478bd9Sstevel@tonic-gate * and returns one of the following error codes. The words in parentheses are 2579*7c478bd9Sstevel@tonic-gate * the values to which *fp may be set for the error case. 2580*7c478bd9Sstevel@tonic-gate * ENOMEM - malloc() failed 2581*7c478bd9Sstevel@tonic-gate * EIO - an I/O error occurred (getpwuid_r, chdir) 2582*7c478bd9Sstevel@tonic-gate * EMFILE - process is out of file descriptors (getpwuid_r) 2583*7c478bd9Sstevel@tonic-gate * ENFILE - system is out of file handles (getpwuid_r) 2584*7c478bd9Sstevel@tonic-gate * EINVAL - gid or egid is out of range (setregid) 2585*7c478bd9Sstevel@tonic-gate * ngroups is too big (setgroups) 2586*7c478bd9Sstevel@tonic-gate * project's project id is bad (setproject) 2587*7c478bd9Sstevel@tonic-gate * uid or euid is out of range (setreuid) 2588*7c478bd9Sstevel@tonic-gate * EPERM - insufficient privilege (setregid, initgroups, setgroups, setppriv, 2589*7c478bd9Sstevel@tonic-gate * setproject, setreuid, settaskid) 2590*7c478bd9Sstevel@tonic-gate * ENOENT - uid has a passwd entry but no shadow entry 2591*7c478bd9Sstevel@tonic-gate * working_dir does not exist (chdir) 2592*7c478bd9Sstevel@tonic-gate * uid has no passwd entry 2593*7c478bd9Sstevel@tonic-gate * the pool could not be found (pool_set_binding) 2594*7c478bd9Sstevel@tonic-gate * EFAULT - lpriv_set or priv_set has a bad address (setppriv) 2595*7c478bd9Sstevel@tonic-gate * working_dir has a bad address (chdir) 2596*7c478bd9Sstevel@tonic-gate * EACCES - could not access working_dir (chdir) 2597*7c478bd9Sstevel@tonic-gate * in a TASK_FINAL task (setproject, settaskid) 2598*7c478bd9Sstevel@tonic-gate * no resource pool accepting default binding exists (setproject) 2599*7c478bd9Sstevel@tonic-gate * ELOOP - too many symbolic links in working_dir (chdir) 2600*7c478bd9Sstevel@tonic-gate * ENAMETOOLONG - working_dir is too long (chdir) 2601*7c478bd9Sstevel@tonic-gate * ENOLINK - working_dir is on an inaccessible remote machine (chdir) 2602*7c478bd9Sstevel@tonic-gate * ENOTDIR - working_dir is not a directory (chdir) 2603*7c478bd9Sstevel@tonic-gate * ESRCH - uid is not a user of project (setproject) 2604*7c478bd9Sstevel@tonic-gate * project is invalid (setproject) 2605*7c478bd9Sstevel@tonic-gate * the resource pool specified for project is unknown (setproject) 2606*7c478bd9Sstevel@tonic-gate * EBADF - the configuration for the pool is invalid (pool_set_binding) 2607*7c478bd9Sstevel@tonic-gate * -1 - core_set_process_path() failed (core_set_process_path) 2608*7c478bd9Sstevel@tonic-gate * a resource control assignment failed (setproject) 2609*7c478bd9Sstevel@tonic-gate * a system error occurred during pool_set_binding (pool_set_binding) 2610*7c478bd9Sstevel@tonic-gate */ 2611*7c478bd9Sstevel@tonic-gate int 2612*7c478bd9Sstevel@tonic-gate restarter_set_method_context(struct method_context *cip, const char **fp) 2613*7c478bd9Sstevel@tonic-gate { 2614*7c478bd9Sstevel@tonic-gate pid_t mypid = -1; 2615*7c478bd9Sstevel@tonic-gate int r, ret; 2616*7c478bd9Sstevel@tonic-gate 2617*7c478bd9Sstevel@tonic-gate cip->pwbuf = NULL; 2618*7c478bd9Sstevel@tonic-gate *fp = NULL; 2619*7c478bd9Sstevel@tonic-gate 2620*7c478bd9Sstevel@tonic-gate if (cip->gid != -1) { 2621*7c478bd9Sstevel@tonic-gate if (setregid(cip->gid, 2622*7c478bd9Sstevel@tonic-gate cip->egid != -1 ? cip->egid : cip->gid) != 0) { 2623*7c478bd9Sstevel@tonic-gate *fp = "setregid"; 2624*7c478bd9Sstevel@tonic-gate 2625*7c478bd9Sstevel@tonic-gate ret = errno; 2626*7c478bd9Sstevel@tonic-gate assert(ret == EINVAL || ret == EPERM); 2627*7c478bd9Sstevel@tonic-gate goto out; 2628*7c478bd9Sstevel@tonic-gate } 2629*7c478bd9Sstevel@tonic-gate } else { 2630*7c478bd9Sstevel@tonic-gate if (cip->pwbuf == NULL) { 2631*7c478bd9Sstevel@tonic-gate switch (ret = lookup_pwd(cip)) { 2632*7c478bd9Sstevel@tonic-gate case 0: 2633*7c478bd9Sstevel@tonic-gate break; 2634*7c478bd9Sstevel@tonic-gate 2635*7c478bd9Sstevel@tonic-gate case ENOMEM: 2636*7c478bd9Sstevel@tonic-gate case ENOENT: 2637*7c478bd9Sstevel@tonic-gate *fp = NULL; 2638*7c478bd9Sstevel@tonic-gate goto out; 2639*7c478bd9Sstevel@tonic-gate 2640*7c478bd9Sstevel@tonic-gate case EIO: 2641*7c478bd9Sstevel@tonic-gate case EMFILE: 2642*7c478bd9Sstevel@tonic-gate case ENFILE: 2643*7c478bd9Sstevel@tonic-gate *fp = "getpwuid_r"; 2644*7c478bd9Sstevel@tonic-gate goto out; 2645*7c478bd9Sstevel@tonic-gate 2646*7c478bd9Sstevel@tonic-gate default: 2647*7c478bd9Sstevel@tonic-gate bad_fail("lookup_pwd", ret); 2648*7c478bd9Sstevel@tonic-gate } 2649*7c478bd9Sstevel@tonic-gate } 2650*7c478bd9Sstevel@tonic-gate 2651*7c478bd9Sstevel@tonic-gate if (setregid(cip->pwd.pw_gid, 2652*7c478bd9Sstevel@tonic-gate cip->egid != -1 ? cip->egid : cip->pwd.pw_gid) != 0) { 2653*7c478bd9Sstevel@tonic-gate *fp = "setregid"; 2654*7c478bd9Sstevel@tonic-gate 2655*7c478bd9Sstevel@tonic-gate ret = errno; 2656*7c478bd9Sstevel@tonic-gate assert(ret == EINVAL || ret == EPERM); 2657*7c478bd9Sstevel@tonic-gate goto out; 2658*7c478bd9Sstevel@tonic-gate } 2659*7c478bd9Sstevel@tonic-gate } 2660*7c478bd9Sstevel@tonic-gate 2661*7c478bd9Sstevel@tonic-gate if (cip->ngroups == -1) { 2662*7c478bd9Sstevel@tonic-gate if (cip->pwbuf == NULL) { 2663*7c478bd9Sstevel@tonic-gate switch (ret = lookup_pwd(cip)) { 2664*7c478bd9Sstevel@tonic-gate case 0: 2665*7c478bd9Sstevel@tonic-gate break; 2666*7c478bd9Sstevel@tonic-gate 2667*7c478bd9Sstevel@tonic-gate case ENOMEM: 2668*7c478bd9Sstevel@tonic-gate case ENOENT: 2669*7c478bd9Sstevel@tonic-gate *fp = NULL; 2670*7c478bd9Sstevel@tonic-gate goto out; 2671*7c478bd9Sstevel@tonic-gate 2672*7c478bd9Sstevel@tonic-gate case EIO: 2673*7c478bd9Sstevel@tonic-gate case EMFILE: 2674*7c478bd9Sstevel@tonic-gate case ENFILE: 2675*7c478bd9Sstevel@tonic-gate *fp = "getpwuid_r"; 2676*7c478bd9Sstevel@tonic-gate goto out; 2677*7c478bd9Sstevel@tonic-gate 2678*7c478bd9Sstevel@tonic-gate default: 2679*7c478bd9Sstevel@tonic-gate bad_fail("lookup_pwd", ret); 2680*7c478bd9Sstevel@tonic-gate } 2681*7c478bd9Sstevel@tonic-gate } 2682*7c478bd9Sstevel@tonic-gate 2683*7c478bd9Sstevel@tonic-gate /* Ok if cip->gid == -1 */ 2684*7c478bd9Sstevel@tonic-gate if (initgroups(cip->pwd.pw_name, cip->gid) != 0) { 2685*7c478bd9Sstevel@tonic-gate *fp = "initgroups"; 2686*7c478bd9Sstevel@tonic-gate ret = errno; 2687*7c478bd9Sstevel@tonic-gate assert(ret == EPERM); 2688*7c478bd9Sstevel@tonic-gate goto out; 2689*7c478bd9Sstevel@tonic-gate } 2690*7c478bd9Sstevel@tonic-gate } else if (cip->ngroups > 0 && 2691*7c478bd9Sstevel@tonic-gate setgroups(cip->ngroups, cip->groups) != 0) { 2692*7c478bd9Sstevel@tonic-gate *fp = "setgroups"; 2693*7c478bd9Sstevel@tonic-gate 2694*7c478bd9Sstevel@tonic-gate ret = errno; 2695*7c478bd9Sstevel@tonic-gate assert(ret == EINVAL || ret == EPERM); 2696*7c478bd9Sstevel@tonic-gate goto out; 2697*7c478bd9Sstevel@tonic-gate } 2698*7c478bd9Sstevel@tonic-gate 2699*7c478bd9Sstevel@tonic-gate *fp = "setppriv"; 2700*7c478bd9Sstevel@tonic-gate 2701*7c478bd9Sstevel@tonic-gate if (cip->lpriv_set != NULL) { 2702*7c478bd9Sstevel@tonic-gate if (setppriv(PRIV_SET, PRIV_LIMIT, cip->lpriv_set) != 0) { 2703*7c478bd9Sstevel@tonic-gate ret = errno; 2704*7c478bd9Sstevel@tonic-gate assert(ret == EFAULT || ret == EPERM); 2705*7c478bd9Sstevel@tonic-gate goto out; 2706*7c478bd9Sstevel@tonic-gate } 2707*7c478bd9Sstevel@tonic-gate } 2708*7c478bd9Sstevel@tonic-gate if (cip->priv_set != NULL) { 2709*7c478bd9Sstevel@tonic-gate if (setppriv(PRIV_SET, PRIV_INHERITABLE, cip->priv_set) != 0) { 2710*7c478bd9Sstevel@tonic-gate ret = errno; 2711*7c478bd9Sstevel@tonic-gate assert(ret == EFAULT || ret == EPERM); 2712*7c478bd9Sstevel@tonic-gate goto out; 2713*7c478bd9Sstevel@tonic-gate } 2714*7c478bd9Sstevel@tonic-gate } 2715*7c478bd9Sstevel@tonic-gate 2716*7c478bd9Sstevel@tonic-gate if (cip->working_dir != NULL) { 2717*7c478bd9Sstevel@tonic-gate do 2718*7c478bd9Sstevel@tonic-gate r = chdir(cip->working_dir); 2719*7c478bd9Sstevel@tonic-gate while (r != 0 && errno == EINTR); 2720*7c478bd9Sstevel@tonic-gate if (r != 0) { 2721*7c478bd9Sstevel@tonic-gate *fp = "chdir"; 2722*7c478bd9Sstevel@tonic-gate ret = errno; 2723*7c478bd9Sstevel@tonic-gate goto out; 2724*7c478bd9Sstevel@tonic-gate } 2725*7c478bd9Sstevel@tonic-gate } 2726*7c478bd9Sstevel@tonic-gate 2727*7c478bd9Sstevel@tonic-gate if (cip->corefile_pattern != NULL) { 2728*7c478bd9Sstevel@tonic-gate mypid = getpid(); 2729*7c478bd9Sstevel@tonic-gate 2730*7c478bd9Sstevel@tonic-gate if (core_set_process_path(cip->corefile_pattern, 2731*7c478bd9Sstevel@tonic-gate strlen(cip->corefile_pattern) + 1, mypid) != 0) { 2732*7c478bd9Sstevel@tonic-gate *fp = "core_set_process_path"; 2733*7c478bd9Sstevel@tonic-gate ret = -1; 2734*7c478bd9Sstevel@tonic-gate goto out; 2735*7c478bd9Sstevel@tonic-gate } 2736*7c478bd9Sstevel@tonic-gate } 2737*7c478bd9Sstevel@tonic-gate 2738*7c478bd9Sstevel@tonic-gate if (restarter_rm_libs_loadable()) { 2739*7c478bd9Sstevel@tonic-gate if (cip->project == NULL) { 2740*7c478bd9Sstevel@tonic-gate if (settaskid(getprojid(), TASK_NORMAL) == -1) { 2741*7c478bd9Sstevel@tonic-gate switch (errno) { 2742*7c478bd9Sstevel@tonic-gate case EACCES: 2743*7c478bd9Sstevel@tonic-gate case EPERM: 2744*7c478bd9Sstevel@tonic-gate *fp = "settaskid"; 2745*7c478bd9Sstevel@tonic-gate ret = errno; 2746*7c478bd9Sstevel@tonic-gate goto out; 2747*7c478bd9Sstevel@tonic-gate 2748*7c478bd9Sstevel@tonic-gate case EINVAL: 2749*7c478bd9Sstevel@tonic-gate default: 2750*7c478bd9Sstevel@tonic-gate bad_fail("settaskid", errno); 2751*7c478bd9Sstevel@tonic-gate } 2752*7c478bd9Sstevel@tonic-gate } 2753*7c478bd9Sstevel@tonic-gate } else { 2754*7c478bd9Sstevel@tonic-gate switch (ret = lookup_pwd(cip)) { 2755*7c478bd9Sstevel@tonic-gate case 0: 2756*7c478bd9Sstevel@tonic-gate break; 2757*7c478bd9Sstevel@tonic-gate 2758*7c478bd9Sstevel@tonic-gate case ENOMEM: 2759*7c478bd9Sstevel@tonic-gate case ENOENT: 2760*7c478bd9Sstevel@tonic-gate *fp = NULL; 2761*7c478bd9Sstevel@tonic-gate goto out; 2762*7c478bd9Sstevel@tonic-gate 2763*7c478bd9Sstevel@tonic-gate case EIO: 2764*7c478bd9Sstevel@tonic-gate case EMFILE: 2765*7c478bd9Sstevel@tonic-gate case ENFILE: 2766*7c478bd9Sstevel@tonic-gate *fp = "getpwuid_r"; 2767*7c478bd9Sstevel@tonic-gate goto out; 2768*7c478bd9Sstevel@tonic-gate 2769*7c478bd9Sstevel@tonic-gate default: 2770*7c478bd9Sstevel@tonic-gate bad_fail("lookup_pwd", ret); 2771*7c478bd9Sstevel@tonic-gate } 2772*7c478bd9Sstevel@tonic-gate 2773*7c478bd9Sstevel@tonic-gate *fp = "setproject"; 2774*7c478bd9Sstevel@tonic-gate 2775*7c478bd9Sstevel@tonic-gate switch (setproject(cip->project, cip->pwd.pw_name, 2776*7c478bd9Sstevel@tonic-gate TASK_NORMAL)) { 2777*7c478bd9Sstevel@tonic-gate case 0: 2778*7c478bd9Sstevel@tonic-gate break; 2779*7c478bd9Sstevel@tonic-gate 2780*7c478bd9Sstevel@tonic-gate case SETPROJ_ERR_TASK: 2781*7c478bd9Sstevel@tonic-gate case SETPROJ_ERR_POOL: 2782*7c478bd9Sstevel@tonic-gate ret = errno; 2783*7c478bd9Sstevel@tonic-gate goto out; 2784*7c478bd9Sstevel@tonic-gate 2785*7c478bd9Sstevel@tonic-gate default: 2786*7c478bd9Sstevel@tonic-gate ret = -1; 2787*7c478bd9Sstevel@tonic-gate goto out; 2788*7c478bd9Sstevel@tonic-gate } 2789*7c478bd9Sstevel@tonic-gate } 2790*7c478bd9Sstevel@tonic-gate 2791*7c478bd9Sstevel@tonic-gate if (cip->resource_pool != NULL) { 2792*7c478bd9Sstevel@tonic-gate if (mypid == -1) 2793*7c478bd9Sstevel@tonic-gate mypid = getpid(); 2794*7c478bd9Sstevel@tonic-gate 2795*7c478bd9Sstevel@tonic-gate *fp = "pool_set_binding"; 2796*7c478bd9Sstevel@tonic-gate 2797*7c478bd9Sstevel@tonic-gate if (pool_set_binding(cip->resource_pool, P_PID, 2798*7c478bd9Sstevel@tonic-gate mypid) != PO_SUCCESS) { 2799*7c478bd9Sstevel@tonic-gate switch (pool_error()) { 2800*7c478bd9Sstevel@tonic-gate case POE_BADPARAM: 2801*7c478bd9Sstevel@tonic-gate ret = ENOENT; 2802*7c478bd9Sstevel@tonic-gate break; 2803*7c478bd9Sstevel@tonic-gate 2804*7c478bd9Sstevel@tonic-gate case POE_INVALID_CONF: 2805*7c478bd9Sstevel@tonic-gate ret = EBADF; 2806*7c478bd9Sstevel@tonic-gate break; 2807*7c478bd9Sstevel@tonic-gate 2808*7c478bd9Sstevel@tonic-gate case POE_SYSTEM: 2809*7c478bd9Sstevel@tonic-gate ret = -1; 2810*7c478bd9Sstevel@tonic-gate break; 2811*7c478bd9Sstevel@tonic-gate 2812*7c478bd9Sstevel@tonic-gate default: 2813*7c478bd9Sstevel@tonic-gate bad_fail("pool_set_binding", 2814*7c478bd9Sstevel@tonic-gate pool_error()); 2815*7c478bd9Sstevel@tonic-gate } 2816*7c478bd9Sstevel@tonic-gate 2817*7c478bd9Sstevel@tonic-gate goto out; 2818*7c478bd9Sstevel@tonic-gate } 2819*7c478bd9Sstevel@tonic-gate } 2820*7c478bd9Sstevel@tonic-gate } 2821*7c478bd9Sstevel@tonic-gate 2822*7c478bd9Sstevel@tonic-gate /* 2823*7c478bd9Sstevel@tonic-gate * The last thing we must do is assume our ID. 2824*7c478bd9Sstevel@tonic-gate * If the UID is 0, we want it to be privilege-aware, 2825*7c478bd9Sstevel@tonic-gate * otherwise the limit set gets used instead of E/P. 2826*7c478bd9Sstevel@tonic-gate * We can do this by setting P as well, which keeps 2827*7c478bd9Sstevel@tonic-gate * PA status (see priv_can_clear_PA()). 2828*7c478bd9Sstevel@tonic-gate */ 2829*7c478bd9Sstevel@tonic-gate 2830*7c478bd9Sstevel@tonic-gate *fp = "setreuid"; 2831*7c478bd9Sstevel@tonic-gate if (setreuid(cip->uid, cip->euid != -1 ? cip->euid : cip->uid) != 0) { 2832*7c478bd9Sstevel@tonic-gate ret = errno; 2833*7c478bd9Sstevel@tonic-gate assert(ret == EINVAL || ret == EPERM); 2834*7c478bd9Sstevel@tonic-gate goto out; 2835*7c478bd9Sstevel@tonic-gate } 2836*7c478bd9Sstevel@tonic-gate 2837*7c478bd9Sstevel@tonic-gate *fp = "setppriv"; 2838*7c478bd9Sstevel@tonic-gate if (cip->priv_set != NULL) { 2839*7c478bd9Sstevel@tonic-gate if (setppriv(PRIV_SET, PRIV_PERMITTED, cip->priv_set) != 0) { 2840*7c478bd9Sstevel@tonic-gate ret = errno; 2841*7c478bd9Sstevel@tonic-gate assert(ret == EFAULT || ret == EPERM); 2842*7c478bd9Sstevel@tonic-gate goto out; 2843*7c478bd9Sstevel@tonic-gate } 2844*7c478bd9Sstevel@tonic-gate } 2845*7c478bd9Sstevel@tonic-gate 2846*7c478bd9Sstevel@tonic-gate ret = 0; 2847*7c478bd9Sstevel@tonic-gate out: 2848*7c478bd9Sstevel@tonic-gate free(cip->pwbuf); 2849*7c478bd9Sstevel@tonic-gate cip->pwbuf = NULL; 2850*7c478bd9Sstevel@tonic-gate return (ret); 2851*7c478bd9Sstevel@tonic-gate } 2852*7c478bd9Sstevel@tonic-gate 2853*7c478bd9Sstevel@tonic-gate void 2854*7c478bd9Sstevel@tonic-gate restarter_free_method_context(struct method_context *mcp) 2855*7c478bd9Sstevel@tonic-gate { 2856*7c478bd9Sstevel@tonic-gate size_t i; 2857*7c478bd9Sstevel@tonic-gate 2858*7c478bd9Sstevel@tonic-gate if (mcp->lpriv_set != NULL) 2859*7c478bd9Sstevel@tonic-gate priv_freeset(mcp->lpriv_set); 2860*7c478bd9Sstevel@tonic-gate if (mcp->priv_set != NULL) 2861*7c478bd9Sstevel@tonic-gate priv_freeset(mcp->priv_set); 2862*7c478bd9Sstevel@tonic-gate 2863*7c478bd9Sstevel@tonic-gate if (mcp->env != NULL) { 2864*7c478bd9Sstevel@tonic-gate for (i = 0; i < mcp->env_sz; i++) 2865*7c478bd9Sstevel@tonic-gate free(mcp->env[i]); 2866*7c478bd9Sstevel@tonic-gate free(mcp->env); 2867*7c478bd9Sstevel@tonic-gate } 2868*7c478bd9Sstevel@tonic-gate 2869*7c478bd9Sstevel@tonic-gate free(mcp->working_dir); 2870*7c478bd9Sstevel@tonic-gate free(mcp->corefile_pattern); 2871*7c478bd9Sstevel@tonic-gate free(mcp->project); 2872*7c478bd9Sstevel@tonic-gate free(mcp->resource_pool); 2873*7c478bd9Sstevel@tonic-gate free(mcp); 2874*7c478bd9Sstevel@tonic-gate } 2875*7c478bd9Sstevel@tonic-gate 2876*7c478bd9Sstevel@tonic-gate /* 2877*7c478bd9Sstevel@tonic-gate * Method keyword functions 2878*7c478bd9Sstevel@tonic-gate */ 2879*7c478bd9Sstevel@tonic-gate 2880*7c478bd9Sstevel@tonic-gate int 2881*7c478bd9Sstevel@tonic-gate restarter_is_null_method(const char *meth) 2882*7c478bd9Sstevel@tonic-gate { 2883*7c478bd9Sstevel@tonic-gate return (strcmp(meth, MKW_TRUE) == 0); 2884*7c478bd9Sstevel@tonic-gate } 2885*7c478bd9Sstevel@tonic-gate 2886*7c478bd9Sstevel@tonic-gate static int 2887*7c478bd9Sstevel@tonic-gate is_kill_method(const char *method, const char *kill_str, 2888*7c478bd9Sstevel@tonic-gate size_t kill_str_len) 2889*7c478bd9Sstevel@tonic-gate { 2890*7c478bd9Sstevel@tonic-gate const char *cp; 2891*7c478bd9Sstevel@tonic-gate int sig; 2892*7c478bd9Sstevel@tonic-gate 2893*7c478bd9Sstevel@tonic-gate if (strncmp(method, kill_str, kill_str_len) != 0 || 2894*7c478bd9Sstevel@tonic-gate (method[kill_str_len] != '\0' && 2895*7c478bd9Sstevel@tonic-gate !isspace(method[kill_str_len]))) 2896*7c478bd9Sstevel@tonic-gate return (-1); 2897*7c478bd9Sstevel@tonic-gate 2898*7c478bd9Sstevel@tonic-gate cp = method + kill_str_len; 2899*7c478bd9Sstevel@tonic-gate while (*cp != '\0' && isspace(*cp)) 2900*7c478bd9Sstevel@tonic-gate ++cp; 2901*7c478bd9Sstevel@tonic-gate 2902*7c478bd9Sstevel@tonic-gate if (*cp == '\0') 2903*7c478bd9Sstevel@tonic-gate return (SIGTERM); 2904*7c478bd9Sstevel@tonic-gate 2905*7c478bd9Sstevel@tonic-gate if (*cp != '-') 2906*7c478bd9Sstevel@tonic-gate return (-1); 2907*7c478bd9Sstevel@tonic-gate 2908*7c478bd9Sstevel@tonic-gate return (str2sig(cp + 1, &sig) == 0 ? sig : -1); 2909*7c478bd9Sstevel@tonic-gate } 2910*7c478bd9Sstevel@tonic-gate 2911*7c478bd9Sstevel@tonic-gate int 2912*7c478bd9Sstevel@tonic-gate restarter_is_kill_proc_method(const char *method) 2913*7c478bd9Sstevel@tonic-gate { 2914*7c478bd9Sstevel@tonic-gate return (is_kill_method(method, MKW_KILL_PROC, 2915*7c478bd9Sstevel@tonic-gate sizeof (MKW_KILL_PROC) - 1)); 2916*7c478bd9Sstevel@tonic-gate } 2917*7c478bd9Sstevel@tonic-gate 2918*7c478bd9Sstevel@tonic-gate int 2919*7c478bd9Sstevel@tonic-gate restarter_is_kill_method(const char *method) 2920*7c478bd9Sstevel@tonic-gate { 2921*7c478bd9Sstevel@tonic-gate return (is_kill_method(method, MKW_KILL, sizeof (MKW_KILL) - 1)); 2922*7c478bd9Sstevel@tonic-gate } 2923*7c478bd9Sstevel@tonic-gate 2924*7c478bd9Sstevel@tonic-gate /* 2925*7c478bd9Sstevel@tonic-gate * Stubs for now. 2926*7c478bd9Sstevel@tonic-gate */ 2927*7c478bd9Sstevel@tonic-gate 2928*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 2929*7c478bd9Sstevel@tonic-gate int 2930*7c478bd9Sstevel@tonic-gate restarter_event_get_enabled(restarter_event_t *e) 2931*7c478bd9Sstevel@tonic-gate { 2932*7c478bd9Sstevel@tonic-gate return (-1); 2933*7c478bd9Sstevel@tonic-gate } 2934*7c478bd9Sstevel@tonic-gate 2935*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 2936*7c478bd9Sstevel@tonic-gate uint64_t 2937*7c478bd9Sstevel@tonic-gate restarter_event_get_seq(restarter_event_t *e) 2938*7c478bd9Sstevel@tonic-gate { 2939*7c478bd9Sstevel@tonic-gate return (-1); 2940*7c478bd9Sstevel@tonic-gate } 2941*7c478bd9Sstevel@tonic-gate 2942*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 2943*7c478bd9Sstevel@tonic-gate void 2944*7c478bd9Sstevel@tonic-gate restarter_event_get_time(restarter_event_t *e, hrtime_t *time) 2945*7c478bd9Sstevel@tonic-gate { 2946*7c478bd9Sstevel@tonic-gate } 2947