xref: /titanic_52/usr/src/lib/librestart/common/librestart.c (revision 870ad75a2b67a92c3449d93b4fef8a0baa982b4a)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
53ad28c1eSrm88369  * Common Development and Distribution License (the "License").
63ad28c1eSrm88369  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217257d1b4Sraf 
227c478bd9Sstevel@tonic-gate /*
23eb1a3463STruong Nguyen  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #include <librestart.h>
287c478bd9Sstevel@tonic-gate #include <librestart_priv.h>
297c478bd9Sstevel@tonic-gate #include <libscf.h>
307c478bd9Sstevel@tonic-gate #include <libscf_priv.h>
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate #include <assert.h>
337c478bd9Sstevel@tonic-gate #include <ctype.h>
347c478bd9Sstevel@tonic-gate #include <dlfcn.h>
357c478bd9Sstevel@tonic-gate #include <errno.h>
367c478bd9Sstevel@tonic-gate #include <exec_attr.h>
377c478bd9Sstevel@tonic-gate #include <grp.h>
387c478bd9Sstevel@tonic-gate #include <libsysevent.h>
397c478bd9Sstevel@tonic-gate #include <libuutil.h>
407c478bd9Sstevel@tonic-gate #include <limits.h>
417c478bd9Sstevel@tonic-gate #include <link.h>
427c478bd9Sstevel@tonic-gate #include <malloc.h>
437c478bd9Sstevel@tonic-gate #include <pool.h>
447c478bd9Sstevel@tonic-gate #include <priv.h>
457c478bd9Sstevel@tonic-gate #include <project.h>
467c478bd9Sstevel@tonic-gate #include <pthread.h>
477c478bd9Sstevel@tonic-gate #include <pwd.h>
487c478bd9Sstevel@tonic-gate #include <secdb.h>
497c478bd9Sstevel@tonic-gate #include <signal.h>
507c478bd9Sstevel@tonic-gate #include <stdlib.h>
517c478bd9Sstevel@tonic-gate #include <string.h>
527c478bd9Sstevel@tonic-gate #include <syslog.h>
537c478bd9Sstevel@tonic-gate #include <sys/corectl.h>
547c478bd9Sstevel@tonic-gate #include <sys/machelf.h>
557c478bd9Sstevel@tonic-gate #include <sys/task.h>
567c478bd9Sstevel@tonic-gate #include <sys/types.h>
577c478bd9Sstevel@tonic-gate #include <time.h>
587c478bd9Sstevel@tonic-gate #include <unistd.h>
597c478bd9Sstevel@tonic-gate #include <ucontext.h>
607c478bd9Sstevel@tonic-gate 
617c478bd9Sstevel@tonic-gate #define	min(a, b)		((a) > (b) ? (b) : (a))
627c478bd9Sstevel@tonic-gate 
637c478bd9Sstevel@tonic-gate #define	MKW_TRUE	":true"
647c478bd9Sstevel@tonic-gate #define	MKW_KILL	":kill"
657c478bd9Sstevel@tonic-gate #define	MKW_KILL_PROC	":kill_process"
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate #define	ALLOCFAIL	((char *)"Allocation failure.")
687c478bd9Sstevel@tonic-gate #define	RCBROKEN	((char *)"Repository connection broken.")
697c478bd9Sstevel@tonic-gate 
702c65c8b0Srm88369 #define	MAX_COMMIT_RETRIES		10
717c478bd9Sstevel@tonic-gate #define	MAX_COMMIT_RETRY_INT		(5 * 1000000)	/* 5 seconds */
727c478bd9Sstevel@tonic-gate #define	INITIAL_COMMIT_RETRY_INT	(10000)		/* 1/100th second */
737c478bd9Sstevel@tonic-gate 
747c478bd9Sstevel@tonic-gate /*
757c478bd9Sstevel@tonic-gate  * bad_fail() catches bugs in this and lower layers by reporting supposedly
767c478bd9Sstevel@tonic-gate  * impossible function failures.  The NDEBUG case keeps the strings out of the
777c478bd9Sstevel@tonic-gate  * library but still calls abort() so we can root-cause from the coredump.
787c478bd9Sstevel@tonic-gate  */
797c478bd9Sstevel@tonic-gate #ifndef NDEBUG
807c478bd9Sstevel@tonic-gate #define	bad_fail(func, err)	{					\
817c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,						\
827c478bd9Sstevel@tonic-gate 	    "At %s:%d, %s() failed with unexpected error %d.  Aborting.\n", \
837c478bd9Sstevel@tonic-gate 	    __FILE__, __LINE__, (func), (err));				\
847c478bd9Sstevel@tonic-gate 	abort();							\
857c478bd9Sstevel@tonic-gate }
867c478bd9Sstevel@tonic-gate #else
877c478bd9Sstevel@tonic-gate #define	bad_fail(func, err)	abort()
887c478bd9Sstevel@tonic-gate #endif
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate struct restarter_event_handle {
917c478bd9Sstevel@tonic-gate 	char				*reh_restarter_name;
927c478bd9Sstevel@tonic-gate 	char				*reh_delegate_channel_name;
937c478bd9Sstevel@tonic-gate 	evchan_t			*reh_delegate_channel;
947c478bd9Sstevel@tonic-gate 	char				*reh_delegate_subscriber_id;
957c478bd9Sstevel@tonic-gate 	char				*reh_master_channel_name;
967c478bd9Sstevel@tonic-gate 	evchan_t			*reh_master_channel;
977c478bd9Sstevel@tonic-gate 	char				*reh_master_subscriber_id;
987c478bd9Sstevel@tonic-gate 	int				(*reh_handler)(restarter_event_t *);
997c478bd9Sstevel@tonic-gate };
1007c478bd9Sstevel@tonic-gate 
1017c478bd9Sstevel@tonic-gate struct restarter_event {
1027c478bd9Sstevel@tonic-gate 	sysevent_t			*re_sysevent;
1037c478bd9Sstevel@tonic-gate 	restarter_event_type_t		re_type;
1047c478bd9Sstevel@tonic-gate 	char				*re_instance_name;
1057c478bd9Sstevel@tonic-gate 	restarter_event_handle_t	*re_event_handle;
1067c478bd9Sstevel@tonic-gate 	restarter_instance_state_t	re_state;
1077c478bd9Sstevel@tonic-gate 	restarter_instance_state_t	re_next_state;
1087c478bd9Sstevel@tonic-gate };
1097c478bd9Sstevel@tonic-gate 
110*870ad75aSSean Wilcox /*
111*870ad75aSSean Wilcox  * A static no memory error message mc_error_t structure
112*870ad75aSSean Wilcox  * to be used in cases when memory errors are to be returned
113*870ad75aSSean Wilcox  * This avoids the need to attempt to allocate memory for the
114*870ad75aSSean Wilcox  * message, therefore getting into a cycle of no memory failures.
115*870ad75aSSean Wilcox  */
116*870ad75aSSean Wilcox mc_error_t mc_nomem_err = {
117*870ad75aSSean Wilcox 	0, ENOMEM, sizeof ("Out of memory") - 1, "Out of memory"
118*870ad75aSSean Wilcox };
119*870ad75aSSean Wilcox 
1207c478bd9Sstevel@tonic-gate static const char * const allocfail = "Allocation failure.\n";
1217c478bd9Sstevel@tonic-gate static const char * const rcbroken = "Repository connection broken.\n";
1227c478bd9Sstevel@tonic-gate 
1237c478bd9Sstevel@tonic-gate static int method_context_safety = 0;	/* Can safely call pools/projects. */
1247c478bd9Sstevel@tonic-gate 
1257c478bd9Sstevel@tonic-gate int ndebug = 1;
1267c478bd9Sstevel@tonic-gate 
127*870ad75aSSean Wilcox /* PRINTFLIKE3 */
128*870ad75aSSean Wilcox static mc_error_t *
129*870ad75aSSean Wilcox mc_error_create(mc_error_t *e, int type, const char *format, ...)
130*870ad75aSSean Wilcox {
131*870ad75aSSean Wilcox 	mc_error_t	*le;
132*870ad75aSSean Wilcox 	va_list		args;
133*870ad75aSSean Wilcox 	int		size;
134*870ad75aSSean Wilcox 
135*870ad75aSSean Wilcox 	/*
136*870ad75aSSean Wilcox 	 * If the type is ENOMEM and format is NULL, then
137*870ad75aSSean Wilcox 	 * go ahead and return the default nomem error.
138*870ad75aSSean Wilcox 	 * Otherwise, attempt to allocate the memory and if
139*870ad75aSSean Wilcox 	 * that fails then there is no reason to continue.
140*870ad75aSSean Wilcox 	 */
141*870ad75aSSean Wilcox 	if (type == ENOMEM && format == NULL)
142*870ad75aSSean Wilcox 		return (&mc_nomem_err);
143*870ad75aSSean Wilcox 
144*870ad75aSSean Wilcox 	if (e == NULL && (le = malloc(sizeof (mc_error_t))) == NULL)
145*870ad75aSSean Wilcox 		return (&mc_nomem_err);
146*870ad75aSSean Wilcox 	else
147*870ad75aSSean Wilcox 		le = e;
148*870ad75aSSean Wilcox 
149*870ad75aSSean Wilcox 	le->type = type;
150*870ad75aSSean Wilcox 	le->destroy = 1;
151*870ad75aSSean Wilcox 	va_start(args, format);
152*870ad75aSSean Wilcox 	size = vsnprintf(NULL, 0, format, args) + 1;
153*870ad75aSSean Wilcox 	if (size >= RESTARTER_ERRMSGSZ) {
154*870ad75aSSean Wilcox 		if ((le = realloc(e, sizeof (mc_error_t) +
155*870ad75aSSean Wilcox 		    (size - RESTARTER_ERRMSGSZ))) == NULL) {
156*870ad75aSSean Wilcox 			size = RESTARTER_ERRMSGSZ - 1;
157*870ad75aSSean Wilcox 			le = e;
158*870ad75aSSean Wilcox 		}
159*870ad75aSSean Wilcox 	}
160*870ad75aSSean Wilcox 
161*870ad75aSSean Wilcox 	le->size = size;
162*870ad75aSSean Wilcox 	(void) vsnprintf(le->msg, le->size, format, args);
163*870ad75aSSean Wilcox 	va_end(args);
164*870ad75aSSean Wilcox 
165*870ad75aSSean Wilcox 	return (le);
166*870ad75aSSean Wilcox }
167*870ad75aSSean Wilcox 
168*870ad75aSSean Wilcox void
169*870ad75aSSean Wilcox restarter_mc_error_destroy(mc_error_t *mc_err)
170*870ad75aSSean Wilcox {
171*870ad75aSSean Wilcox 	if (mc_err == NULL)
172*870ad75aSSean Wilcox 		return;
173*870ad75aSSean Wilcox 
174*870ad75aSSean Wilcox 	/*
175*870ad75aSSean Wilcox 	 * If the error messages was allocated then free.
176*870ad75aSSean Wilcox 	 */
177*870ad75aSSean Wilcox 	if (mc_err->destroy) {
178*870ad75aSSean Wilcox 		free(mc_err);
179*870ad75aSSean Wilcox 	}
180*870ad75aSSean Wilcox }
181*870ad75aSSean Wilcox 
1827c478bd9Sstevel@tonic-gate static void
1837c478bd9Sstevel@tonic-gate free_restarter_event_handle(struct restarter_event_handle *h)
1847c478bd9Sstevel@tonic-gate {
1857c478bd9Sstevel@tonic-gate 	if (h == NULL)
1867c478bd9Sstevel@tonic-gate 		return;
1877c478bd9Sstevel@tonic-gate 
1887c478bd9Sstevel@tonic-gate 	/*
1897c478bd9Sstevel@tonic-gate 	 * Just free the memory -- don't unbind the sysevent handle,
1907c478bd9Sstevel@tonic-gate 	 * as otherwise events may be lost if this is just a restarter
1917c478bd9Sstevel@tonic-gate 	 * restart.
1927c478bd9Sstevel@tonic-gate 	 */
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate 	if (h->reh_restarter_name != NULL)
1957c478bd9Sstevel@tonic-gate 		free(h->reh_restarter_name);
1967c478bd9Sstevel@tonic-gate 	if (h->reh_delegate_channel_name != NULL)
1977c478bd9Sstevel@tonic-gate 		free(h->reh_delegate_channel_name);
1987c478bd9Sstevel@tonic-gate 	if (h->reh_delegate_subscriber_id != NULL)
1997c478bd9Sstevel@tonic-gate 		free(h->reh_delegate_subscriber_id);
2007c478bd9Sstevel@tonic-gate 	if (h->reh_master_channel_name != NULL)
2017c478bd9Sstevel@tonic-gate 		free(h->reh_master_channel_name);
2027c478bd9Sstevel@tonic-gate 	if (h->reh_master_subscriber_id != NULL)
2037c478bd9Sstevel@tonic-gate 		free(h->reh_master_subscriber_id);
2047c478bd9Sstevel@tonic-gate 
2057c478bd9Sstevel@tonic-gate 	free(h);
2067c478bd9Sstevel@tonic-gate }
2077c478bd9Sstevel@tonic-gate 
2087c478bd9Sstevel@tonic-gate char *
2097c478bd9Sstevel@tonic-gate _restarter_get_channel_name(const char *fmri, int type)
2107c478bd9Sstevel@tonic-gate {
21113d8aaa1SSean Wilcox 	char *name;
2127c478bd9Sstevel@tonic-gate 	char *chan_name = malloc(MAX_CHNAME_LEN);
2137c478bd9Sstevel@tonic-gate 	char prefix_name[3];
21413d8aaa1SSean Wilcox 	int i;
2157c478bd9Sstevel@tonic-gate 
2167c478bd9Sstevel@tonic-gate 	if (chan_name == NULL)
2177c478bd9Sstevel@tonic-gate 		return (NULL);
2187c478bd9Sstevel@tonic-gate 
2197c478bd9Sstevel@tonic-gate 	if (type == RESTARTER_CHANNEL_DELEGATE)
2207c478bd9Sstevel@tonic-gate 		(void) strcpy(prefix_name, "d_");
2217c478bd9Sstevel@tonic-gate 	else if (type == RESTARTER_CHANNEL_MASTER)
2227c478bd9Sstevel@tonic-gate 		(void) strcpy(prefix_name, "m_");
2237c478bd9Sstevel@tonic-gate 	else {
2247c478bd9Sstevel@tonic-gate 		free(chan_name);
2257c478bd9Sstevel@tonic-gate 		return (NULL);
2267c478bd9Sstevel@tonic-gate 	}
2277c478bd9Sstevel@tonic-gate 
22813d8aaa1SSean Wilcox 	/*
22913d8aaa1SSean Wilcox 	 * Create a unique name
23013d8aaa1SSean Wilcox 	 *
23113d8aaa1SSean Wilcox 	 * Use the entire name, using a replacement of the /
23213d8aaa1SSean Wilcox 	 * characters to get a better name.
23313d8aaa1SSean Wilcox 	 *
23413d8aaa1SSean Wilcox 	 * Remove the svc:/ from the beginning as this really
23513d8aaa1SSean Wilcox 	 * isn't going to provide any uniqueness...
23613d8aaa1SSean Wilcox 	 *
23713d8aaa1SSean Wilcox 	 * An fmri name greater than MAX_CHNAME_LEN is going
23813d8aaa1SSean Wilcox 	 * to be rejected as too long for the chan_name below
23913d8aaa1SSean Wilcox 	 * in the snprintf call.
24013d8aaa1SSean Wilcox 	 */
24113d8aaa1SSean Wilcox 	if ((name = strdup(strchr(fmri, '/') + 1)) == NULL) {
24213d8aaa1SSean Wilcox 		free(chan_name);
24313d8aaa1SSean Wilcox 		return (NULL);
24413d8aaa1SSean Wilcox 	}
24513d8aaa1SSean Wilcox 	i = 0;
24613d8aaa1SSean Wilcox 	while (name[i]) {
24713d8aaa1SSean Wilcox 		if (name[i] == '/') {
24813d8aaa1SSean Wilcox 			name[i] = '_';
24913d8aaa1SSean Wilcox 		}
25013d8aaa1SSean Wilcox 
25113d8aaa1SSean Wilcox 		i++;
25213d8aaa1SSean Wilcox 	}
2537c478bd9Sstevel@tonic-gate 
2547c478bd9Sstevel@tonic-gate 	/*
2557c478bd9Sstevel@tonic-gate 	 * Should check for [a-z],[A-Z],[0-9],.,_,-,:
2567c478bd9Sstevel@tonic-gate 	 */
2577c478bd9Sstevel@tonic-gate 
2587c478bd9Sstevel@tonic-gate 	if (snprintf(chan_name, MAX_CHNAME_LEN, "com.sun:scf:%s%s",
2597c478bd9Sstevel@tonic-gate 	    prefix_name, name) > MAX_CHNAME_LEN) {
2607c478bd9Sstevel@tonic-gate 		free(chan_name);
26113d8aaa1SSean Wilcox 		chan_name = NULL;
2627c478bd9Sstevel@tonic-gate 	}
2637c478bd9Sstevel@tonic-gate 
26413d8aaa1SSean Wilcox 	free(name);
2657c478bd9Sstevel@tonic-gate 	return (chan_name);
2667c478bd9Sstevel@tonic-gate }
2677c478bd9Sstevel@tonic-gate 
2687c478bd9Sstevel@tonic-gate int
2697c478bd9Sstevel@tonic-gate cb(sysevent_t *syse, void *cookie)
2707c478bd9Sstevel@tonic-gate {
2717c478bd9Sstevel@tonic-gate 	restarter_event_handle_t *h = (restarter_event_handle_t *)cookie;
2727c478bd9Sstevel@tonic-gate 	restarter_event_t *e;
2737c478bd9Sstevel@tonic-gate 	nvlist_t *attr_list = NULL;
2747c478bd9Sstevel@tonic-gate 	int ret = 0;
2757c478bd9Sstevel@tonic-gate 
2767c478bd9Sstevel@tonic-gate 	e = uu_zalloc(sizeof (restarter_event_t));
2777c478bd9Sstevel@tonic-gate 	if (e == NULL)
2787c478bd9Sstevel@tonic-gate 		uu_die(allocfail);
2797c478bd9Sstevel@tonic-gate 	e->re_event_handle = h;
2807c478bd9Sstevel@tonic-gate 	e->re_sysevent = syse;
2817c478bd9Sstevel@tonic-gate 
2827c478bd9Sstevel@tonic-gate 	if (sysevent_get_attr_list(syse, &attr_list) != 0)
2837c478bd9Sstevel@tonic-gate 		uu_die(allocfail);
2847c478bd9Sstevel@tonic-gate 
2857c478bd9Sstevel@tonic-gate 	if ((nvlist_lookup_uint32(attr_list, RESTARTER_NAME_TYPE,
2867c478bd9Sstevel@tonic-gate 	    &(e->re_type)) != 0) ||
2877c478bd9Sstevel@tonic-gate 	    (nvlist_lookup_string(attr_list,
2887c478bd9Sstevel@tonic-gate 	    RESTARTER_NAME_INSTANCE, &(e->re_instance_name)) != 0)) {
2897c478bd9Sstevel@tonic-gate 		uu_warn("%s: Can't decode nvlist for event %p\n",
2907c478bd9Sstevel@tonic-gate 		    h->reh_restarter_name, (void *)syse);
2917c478bd9Sstevel@tonic-gate 
2927c478bd9Sstevel@tonic-gate 		ret = 0;
2937c478bd9Sstevel@tonic-gate 	} else {
2947c478bd9Sstevel@tonic-gate 		ret = h->reh_handler(e);
2957c478bd9Sstevel@tonic-gate 	}
2967c478bd9Sstevel@tonic-gate 
2977c478bd9Sstevel@tonic-gate 	uu_free(e);
2987c478bd9Sstevel@tonic-gate 	nvlist_free(attr_list);
2997c478bd9Sstevel@tonic-gate 	return (ret);
3007c478bd9Sstevel@tonic-gate }
3017c478bd9Sstevel@tonic-gate 
3027c478bd9Sstevel@tonic-gate /*
3037c478bd9Sstevel@tonic-gate  * restarter_bind_handle(uint32_t, char *, int (*)(restarter_event_t *), int,
3047c478bd9Sstevel@tonic-gate  *     restarter_event_handle_t **)
3057c478bd9Sstevel@tonic-gate  *
3067c478bd9Sstevel@tonic-gate  * Bind to a delegated restarter event channel.
3077c478bd9Sstevel@tonic-gate  * Each delegated restarter gets its own channel for resource management.
3087c478bd9Sstevel@tonic-gate  *
3097c478bd9Sstevel@tonic-gate  * Returns 0 on success or
3107c478bd9Sstevel@tonic-gate  *   ENOTSUP	version mismatch
3117c478bd9Sstevel@tonic-gate  *   EINVAL	restarter_name or event_handle is NULL
3127c478bd9Sstevel@tonic-gate  *   ENOMEM	out of memory, too many channels, or too many subscriptions
3137c478bd9Sstevel@tonic-gate  *   EBUSY	sysevent_evc_bind() could not establish binding
3147c478bd9Sstevel@tonic-gate  *   EFAULT	internal sysevent_evc_bind()/sysevent_evc_subscribe() error
3157c478bd9Sstevel@tonic-gate  *   EMFILE	out of file descriptors
3167c478bd9Sstevel@tonic-gate  *   EPERM	insufficient privilege for sysevent_evc_bind()
3177c478bd9Sstevel@tonic-gate  *   EEXIST	already subscribed
3187c478bd9Sstevel@tonic-gate  */
3197c478bd9Sstevel@tonic-gate int
3207c478bd9Sstevel@tonic-gate restarter_bind_handle(uint32_t version, const char *restarter_name,
3217c478bd9Sstevel@tonic-gate     int (*event_handler)(restarter_event_t *), int flags,
3227c478bd9Sstevel@tonic-gate     restarter_event_handle_t **rehp)
3237c478bd9Sstevel@tonic-gate {
3247c478bd9Sstevel@tonic-gate 	restarter_event_handle_t *h;
3257c478bd9Sstevel@tonic-gate 	size_t sz;
3267c478bd9Sstevel@tonic-gate 	int err;
3277c478bd9Sstevel@tonic-gate 
3287c478bd9Sstevel@tonic-gate 	if (version != RESTARTER_EVENT_VERSION)
3297c478bd9Sstevel@tonic-gate 		return (ENOTSUP);
3307c478bd9Sstevel@tonic-gate 
3317c478bd9Sstevel@tonic-gate 	if (restarter_name == NULL || event_handler == NULL)
3327c478bd9Sstevel@tonic-gate 		return (EINVAL);
3337c478bd9Sstevel@tonic-gate 
3347c478bd9Sstevel@tonic-gate 	if (flags & RESTARTER_FLAG_DEBUG)
3357c478bd9Sstevel@tonic-gate 		ndebug++;
3367c478bd9Sstevel@tonic-gate 
3377c478bd9Sstevel@tonic-gate 	if ((h = uu_zalloc(sizeof (restarter_event_handle_t))) == NULL)
3387c478bd9Sstevel@tonic-gate 		return (ENOMEM);
3397c478bd9Sstevel@tonic-gate 
3407c478bd9Sstevel@tonic-gate 	h->reh_delegate_subscriber_id = malloc(MAX_SUBID_LEN);
3417c478bd9Sstevel@tonic-gate 	h->reh_master_subscriber_id = malloc(MAX_SUBID_LEN);
3427c478bd9Sstevel@tonic-gate 	h->reh_restarter_name = strdup(restarter_name);
3437c478bd9Sstevel@tonic-gate 	if (h->reh_delegate_subscriber_id == NULL ||
3447c478bd9Sstevel@tonic-gate 	    h->reh_master_subscriber_id == NULL ||
3457c478bd9Sstevel@tonic-gate 	    h->reh_restarter_name == NULL) {
3467c478bd9Sstevel@tonic-gate 		free_restarter_event_handle(h);
3477c478bd9Sstevel@tonic-gate 		return (ENOMEM);
3487c478bd9Sstevel@tonic-gate 	}
3497c478bd9Sstevel@tonic-gate 
3507c478bd9Sstevel@tonic-gate 	sz = strlcpy(h->reh_delegate_subscriber_id, "del", MAX_SUBID_LEN);
3517c478bd9Sstevel@tonic-gate 	assert(sz < MAX_SUBID_LEN);
3527c478bd9Sstevel@tonic-gate 	sz = strlcpy(h->reh_master_subscriber_id, "master", MAX_SUBID_LEN);
3537c478bd9Sstevel@tonic-gate 	assert(sz < MAX_SUBID_LEN);
3547c478bd9Sstevel@tonic-gate 
3557c478bd9Sstevel@tonic-gate 	h->reh_delegate_channel_name =
3567c478bd9Sstevel@tonic-gate 	    _restarter_get_channel_name(restarter_name,
3577c478bd9Sstevel@tonic-gate 	    RESTARTER_CHANNEL_DELEGATE);
3587c478bd9Sstevel@tonic-gate 	h->reh_master_channel_name =
3597c478bd9Sstevel@tonic-gate 	    _restarter_get_channel_name(restarter_name,
3607c478bd9Sstevel@tonic-gate 	    RESTARTER_CHANNEL_MASTER);
3617c478bd9Sstevel@tonic-gate 
3627c478bd9Sstevel@tonic-gate 	if (h->reh_delegate_channel_name == NULL ||
3637c478bd9Sstevel@tonic-gate 	    h->reh_master_channel_name == NULL) {
3647c478bd9Sstevel@tonic-gate 		free_restarter_event_handle(h);
3657c478bd9Sstevel@tonic-gate 		return (ENOMEM);
3667c478bd9Sstevel@tonic-gate 	}
3677c478bd9Sstevel@tonic-gate 
3687c478bd9Sstevel@tonic-gate 	if (sysevent_evc_bind(h->reh_delegate_channel_name,
3697c478bd9Sstevel@tonic-gate 	    &h->reh_delegate_channel, EVCH_CREAT|EVCH_HOLD_PEND) != 0) {
3707c478bd9Sstevel@tonic-gate 		err = errno;
3717c478bd9Sstevel@tonic-gate 		assert(err != EINVAL);
3727c478bd9Sstevel@tonic-gate 		assert(err != ENOENT);
3737c478bd9Sstevel@tonic-gate 		free_restarter_event_handle(h);
3747c478bd9Sstevel@tonic-gate 		return (err);
3757c478bd9Sstevel@tonic-gate 	}
3767c478bd9Sstevel@tonic-gate 
3777c478bd9Sstevel@tonic-gate 	if (sysevent_evc_bind(h->reh_master_channel_name,
3787c478bd9Sstevel@tonic-gate 	    &h->reh_master_channel, EVCH_CREAT|EVCH_HOLD_PEND) != 0) {
3797c478bd9Sstevel@tonic-gate 		err = errno;
3807c478bd9Sstevel@tonic-gate 		assert(err != EINVAL);
3817c478bd9Sstevel@tonic-gate 		assert(err != ENOENT);
3827c478bd9Sstevel@tonic-gate 		free_restarter_event_handle(h);
3837c478bd9Sstevel@tonic-gate 		return (err);
3847c478bd9Sstevel@tonic-gate 	}
3857c478bd9Sstevel@tonic-gate 
3867c478bd9Sstevel@tonic-gate 	h->reh_handler = event_handler;
3877c478bd9Sstevel@tonic-gate 
3887c478bd9Sstevel@tonic-gate 	assert(strlen(restarter_name) <= MAX_CLASS_LEN - 1);
3897c478bd9Sstevel@tonic-gate 	assert(strlen(h->reh_delegate_subscriber_id) <= MAX_SUBID_LEN - 1);
3907c478bd9Sstevel@tonic-gate 	assert(strlen(h->reh_master_subscriber_id) <= MAX_SUBID_LEN - 1);
3917c478bd9Sstevel@tonic-gate 
3927c478bd9Sstevel@tonic-gate 	if (sysevent_evc_subscribe(h->reh_delegate_channel,
3937c478bd9Sstevel@tonic-gate 	    h->reh_delegate_subscriber_id, EC_ALL, cb, h, EVCH_SUB_KEEP) != 0) {
3947c478bd9Sstevel@tonic-gate 		err = errno;
3957c478bd9Sstevel@tonic-gate 		assert(err != EINVAL);
3967c478bd9Sstevel@tonic-gate 		free_restarter_event_handle(h);
3977c478bd9Sstevel@tonic-gate 		return (err);
3987c478bd9Sstevel@tonic-gate 	}
3997c478bd9Sstevel@tonic-gate 
4007c478bd9Sstevel@tonic-gate 	*rehp = h;
4017c478bd9Sstevel@tonic-gate 	return (0);
4027c478bd9Sstevel@tonic-gate }
4037c478bd9Sstevel@tonic-gate 
4047c478bd9Sstevel@tonic-gate restarter_event_handle_t *
4057c478bd9Sstevel@tonic-gate restarter_event_get_handle(restarter_event_t *e)
4067c478bd9Sstevel@tonic-gate {
4077c478bd9Sstevel@tonic-gate 	assert(e != NULL && e->re_event_handle != NULL);
4087c478bd9Sstevel@tonic-gate 	return (e->re_event_handle);
4097c478bd9Sstevel@tonic-gate }
4107c478bd9Sstevel@tonic-gate 
4117c478bd9Sstevel@tonic-gate restarter_event_type_t
4127c478bd9Sstevel@tonic-gate restarter_event_get_type(restarter_event_t *e)
4137c478bd9Sstevel@tonic-gate {
4147c478bd9Sstevel@tonic-gate 	assert(e != NULL);
4157c478bd9Sstevel@tonic-gate 	return (e->re_type);
4167c478bd9Sstevel@tonic-gate }
4177c478bd9Sstevel@tonic-gate 
4187c478bd9Sstevel@tonic-gate ssize_t
4197c478bd9Sstevel@tonic-gate restarter_event_get_instance(restarter_event_t *e, char *inst, size_t sz)
4207c478bd9Sstevel@tonic-gate {
4217c478bd9Sstevel@tonic-gate 	assert(e != NULL && inst != NULL);
4227c478bd9Sstevel@tonic-gate 	return ((ssize_t)strlcpy(inst, e->re_instance_name, sz));
4237c478bd9Sstevel@tonic-gate }
4247c478bd9Sstevel@tonic-gate 
4257c478bd9Sstevel@tonic-gate int
4267c478bd9Sstevel@tonic-gate restarter_event_get_current_states(restarter_event_t *e,
4277c478bd9Sstevel@tonic-gate     restarter_instance_state_t *state, restarter_instance_state_t *next_state)
4287c478bd9Sstevel@tonic-gate {
4297c478bd9Sstevel@tonic-gate 	if (e == NULL)
4307c478bd9Sstevel@tonic-gate 		return (-1);
4317c478bd9Sstevel@tonic-gate 	*state = e->re_state;
4327c478bd9Sstevel@tonic-gate 	*next_state = e->re_next_state;
4337c478bd9Sstevel@tonic-gate 	return (0);
4347c478bd9Sstevel@tonic-gate }
4357c478bd9Sstevel@tonic-gate 
4367c478bd9Sstevel@tonic-gate /*
4372c65c8b0Srm88369  * restarter_event_publish_retry() is a wrapper around sysevent_evc_publish().
4382c65c8b0Srm88369  * In case, the event cannot be sent at the first attempt (sysevent_evc_publish
4392c65c8b0Srm88369  * returned EAGAIN - sysevent queue full), this function retries a few time
4402c65c8b0Srm88369  * and return ENOSPC if it reaches the retry limit.
4412c65c8b0Srm88369  *
4422c65c8b0Srm88369  * The arguments to this function map the arguments of sysevent_evc_publish().
4432c65c8b0Srm88369  *
4442c65c8b0Srm88369  * On success, return 0. On error, return
4452c65c8b0Srm88369  *
4462c65c8b0Srm88369  *   EFAULT - internal sysevent_evc_publish() error
4472c65c8b0Srm88369  *   ENOMEM - internal sysevent_evc_publish() error
4482c65c8b0Srm88369  *   EBADF - scp is invalid (sysevent_evc_publish() returned EINVAL)
4492c65c8b0Srm88369  *   ENOSPC - sysevent queue full (sysevent_evc_publish() returned EAGAIN)
4502c65c8b0Srm88369  */
4512c65c8b0Srm88369 int
4522c65c8b0Srm88369 restarter_event_publish_retry(evchan_t *scp, const char *class,
4532c65c8b0Srm88369     const char *subclass, const char *vendor, const char *pub_name,
4542c65c8b0Srm88369     nvlist_t *attr_list, uint32_t flags)
4552c65c8b0Srm88369 {
4562c65c8b0Srm88369 	int retries, ret;
4572c65c8b0Srm88369 	useconds_t retry_int = INITIAL_COMMIT_RETRY_INT;
4582c65c8b0Srm88369 
4592c65c8b0Srm88369 	for (retries = 0; retries < MAX_COMMIT_RETRIES; retries++) {
4602c65c8b0Srm88369 		ret = sysevent_evc_publish(scp, class, subclass, vendor,
4612c65c8b0Srm88369 		    pub_name, attr_list, flags);
4622c65c8b0Srm88369 		if (ret == 0)
4632c65c8b0Srm88369 			break;
4642c65c8b0Srm88369 
4652c65c8b0Srm88369 		switch (ret) {
4662c65c8b0Srm88369 		case EAGAIN:
4672c65c8b0Srm88369 			/* Queue is full */
4682c65c8b0Srm88369 			(void) usleep(retry_int);
4692c65c8b0Srm88369 
4702c65c8b0Srm88369 			retry_int = min(retry_int * 2, MAX_COMMIT_RETRY_INT);
4712c65c8b0Srm88369 			break;
4722c65c8b0Srm88369 
4732c65c8b0Srm88369 		case EINVAL:
4742c65c8b0Srm88369 			ret = EBADF;
4752c65c8b0Srm88369 			/* FALLTHROUGH */
4762c65c8b0Srm88369 
4772c65c8b0Srm88369 		case EFAULT:
4782c65c8b0Srm88369 		case ENOMEM:
4792c65c8b0Srm88369 			return (ret);
4802c65c8b0Srm88369 
4812c65c8b0Srm88369 		case EOVERFLOW:
4822c65c8b0Srm88369 		default:
4832c65c8b0Srm88369 			/* internal error - abort */
4842c65c8b0Srm88369 			bad_fail("sysevent_evc_publish", ret);
4852c65c8b0Srm88369 		}
4862c65c8b0Srm88369 	}
4872c65c8b0Srm88369 
4882c65c8b0Srm88369 	if (retries == MAX_COMMIT_RETRIES)
4892c65c8b0Srm88369 		ret = ENOSPC;
4902c65c8b0Srm88369 
4912c65c8b0Srm88369 	return (ret);
4922c65c8b0Srm88369 }
4932c65c8b0Srm88369 
4942c65c8b0Srm88369 /*
4957c478bd9Sstevel@tonic-gate  * Commit the state, next state, and auxiliary state into the repository.
4967c478bd9Sstevel@tonic-gate  * Let the graph engine know about the state change and error.  On success,
4977c478bd9Sstevel@tonic-gate  * return 0. On error, return
4987c478bd9Sstevel@tonic-gate  *   EINVAL - aux has spaces
4997c478bd9Sstevel@tonic-gate  *	    - inst is invalid or not an instance FMRI
5007c478bd9Sstevel@tonic-gate  *   EPROTO - librestart compiled against different libscf
5017c478bd9Sstevel@tonic-gate  *   ENOMEM - out of memory
5027c478bd9Sstevel@tonic-gate  *	    - repository server out of resources
5037c478bd9Sstevel@tonic-gate  *   ENOTACTIVE - repository server not running
5047c478bd9Sstevel@tonic-gate  *   ECONNABORTED - repository connection established, but then broken
5057c478bd9Sstevel@tonic-gate  *		  - unknown libscf error
5067c478bd9Sstevel@tonic-gate  *   ENOENT - inst does not exist in the repository
5077c478bd9Sstevel@tonic-gate  *   EPERM - insufficient permissions
5087c478bd9Sstevel@tonic-gate  *   EACCESS - backend access denied
5097c478bd9Sstevel@tonic-gate  *   EROFS - backend is readonly
5107c478bd9Sstevel@tonic-gate  *   EFAULT - internal sysevent_evc_publish() error
5117c478bd9Sstevel@tonic-gate  *   EBADF - h is invalid (sysevent_evc_publish() returned EINVAL)
5122c65c8b0Srm88369  *   ENOSPC - sysevent queue full (sysevent_evc_publish() returned EAGAIN)
5137c478bd9Sstevel@tonic-gate  */
5147c478bd9Sstevel@tonic-gate int
5157c478bd9Sstevel@tonic-gate restarter_set_states(restarter_event_handle_t *h, const char *inst,
5167c478bd9Sstevel@tonic-gate     restarter_instance_state_t cur_state,
5177c478bd9Sstevel@tonic-gate     restarter_instance_state_t new_cur_state,
5187c478bd9Sstevel@tonic-gate     restarter_instance_state_t next_state,
5197c478bd9Sstevel@tonic-gate     restarter_instance_state_t new_next_state, restarter_error_t e,
5207c478bd9Sstevel@tonic-gate     const char *aux)
5217c478bd9Sstevel@tonic-gate {
5227c478bd9Sstevel@tonic-gate 	nvlist_t *attr;
5237c478bd9Sstevel@tonic-gate 	scf_handle_t *scf_h;
5247c478bd9Sstevel@tonic-gate 	instance_data_t id;
5257c478bd9Sstevel@tonic-gate 	int ret = 0;
5267c478bd9Sstevel@tonic-gate 	char *p = (char *)aux;
5277c478bd9Sstevel@tonic-gate 
5287c478bd9Sstevel@tonic-gate 	assert(h->reh_master_channel != NULL);
5297c478bd9Sstevel@tonic-gate 	assert(h->reh_master_channel_name != NULL);
5307c478bd9Sstevel@tonic-gate 	assert(h->reh_master_subscriber_id != NULL);
5317c478bd9Sstevel@tonic-gate 
5327c478bd9Sstevel@tonic-gate 	/* Validate format of auxiliary state: no spaces allowed */
533ba91983eSlianep 	if (p != NULL) {
534ba91983eSlianep 		while (*p != '\0') {
5357c478bd9Sstevel@tonic-gate 			if (isspace(*p))
5367c478bd9Sstevel@tonic-gate 				return (EINVAL);
5377c478bd9Sstevel@tonic-gate 			p++;
5387c478bd9Sstevel@tonic-gate 		}
539ba91983eSlianep 	}
5407c478bd9Sstevel@tonic-gate 
5417c478bd9Sstevel@tonic-gate 	if ((scf_h = scf_handle_create(SCF_VERSION)) == NULL) {
5427c478bd9Sstevel@tonic-gate 		switch (scf_error()) {
5437c478bd9Sstevel@tonic-gate 		case SCF_ERROR_VERSION_MISMATCH:
5447c478bd9Sstevel@tonic-gate 			return (EPROTO);
5457c478bd9Sstevel@tonic-gate 
5467c478bd9Sstevel@tonic-gate 		case SCF_ERROR_NO_MEMORY:
5477c478bd9Sstevel@tonic-gate 			return (ENOMEM);
5487c478bd9Sstevel@tonic-gate 
5497c478bd9Sstevel@tonic-gate 		default:
5507c478bd9Sstevel@tonic-gate 			bad_fail("scf_handle_create", scf_error());
5517c478bd9Sstevel@tonic-gate 		}
5527c478bd9Sstevel@tonic-gate 	}
5537c478bd9Sstevel@tonic-gate 
5547c478bd9Sstevel@tonic-gate 	if (scf_handle_bind(scf_h) == -1) {
5557c478bd9Sstevel@tonic-gate 		scf_handle_destroy(scf_h);
5567c478bd9Sstevel@tonic-gate 		switch (scf_error()) {
5577c478bd9Sstevel@tonic-gate 		case SCF_ERROR_NO_SERVER:
5587c478bd9Sstevel@tonic-gate 			return (ENOTACTIVE);
5597c478bd9Sstevel@tonic-gate 
5607c478bd9Sstevel@tonic-gate 		case SCF_ERROR_NO_RESOURCES:
5617c478bd9Sstevel@tonic-gate 			return (ENOMEM);
5627c478bd9Sstevel@tonic-gate 
5637c478bd9Sstevel@tonic-gate 		case SCF_ERROR_INVALID_ARGUMENT:
5647c478bd9Sstevel@tonic-gate 		case SCF_ERROR_IN_USE:
5657c478bd9Sstevel@tonic-gate 		default:
5667c478bd9Sstevel@tonic-gate 			bad_fail("scf_handle_bind", scf_error());
5677c478bd9Sstevel@tonic-gate 		}
5687c478bd9Sstevel@tonic-gate 	}
5697c478bd9Sstevel@tonic-gate 
5707c478bd9Sstevel@tonic-gate 	if (nvlist_alloc(&attr, NV_UNIQUE_NAME, 0) != 0 ||
5717c478bd9Sstevel@tonic-gate 	    nvlist_add_int32(attr, RESTARTER_NAME_STATE, new_cur_state) != 0 ||
5727c478bd9Sstevel@tonic-gate 	    nvlist_add_int32(attr, RESTARTER_NAME_NEXT_STATE, new_next_state)
5737c478bd9Sstevel@tonic-gate 	    != 0 ||
5747c478bd9Sstevel@tonic-gate 	    nvlist_add_int32(attr, RESTARTER_NAME_ERROR, e) != 0 ||
5757c478bd9Sstevel@tonic-gate 	    nvlist_add_string(attr, RESTARTER_NAME_INSTANCE, inst) != 0) {
5767c478bd9Sstevel@tonic-gate 		ret = ENOMEM;
5772c65c8b0Srm88369 	} else {
5787c478bd9Sstevel@tonic-gate 		id.i_fmri = inst;
5797c478bd9Sstevel@tonic-gate 		id.i_state = cur_state;
5807c478bd9Sstevel@tonic-gate 		id.i_next_state = next_state;
5817c478bd9Sstevel@tonic-gate 
5827c478bd9Sstevel@tonic-gate 		ret = _restarter_commit_states(scf_h, &id, new_cur_state,
5837c478bd9Sstevel@tonic-gate 		    new_next_state, aux);
5847c478bd9Sstevel@tonic-gate 
5852c65c8b0Srm88369 		if (ret == 0) {
5862c65c8b0Srm88369 			ret = restarter_event_publish_retry(
5872c65c8b0Srm88369 			    h->reh_master_channel, "master", "state_change",
5882c65c8b0Srm88369 			    "com.sun", "librestart", attr, EVCH_NOSLEEP);
5897c478bd9Sstevel@tonic-gate 		}
5907c478bd9Sstevel@tonic-gate 	}
5917c478bd9Sstevel@tonic-gate 
5927c478bd9Sstevel@tonic-gate 	nvlist_free(attr);
5937c478bd9Sstevel@tonic-gate 	(void) scf_handle_unbind(scf_h);
5947c478bd9Sstevel@tonic-gate 	scf_handle_destroy(scf_h);
5957c478bd9Sstevel@tonic-gate 
5967c478bd9Sstevel@tonic-gate 	return (ret);
5977c478bd9Sstevel@tonic-gate }
5987c478bd9Sstevel@tonic-gate 
5997c478bd9Sstevel@tonic-gate restarter_instance_state_t
6007c478bd9Sstevel@tonic-gate restarter_string_to_state(char *string)
6017c478bd9Sstevel@tonic-gate {
6027c478bd9Sstevel@tonic-gate 	assert(string != NULL);
6037c478bd9Sstevel@tonic-gate 
6047c478bd9Sstevel@tonic-gate 	if (strcmp(string, SCF_STATE_STRING_NONE) == 0)
6057c478bd9Sstevel@tonic-gate 		return (RESTARTER_STATE_NONE);
6067c478bd9Sstevel@tonic-gate 	else if (strcmp(string, SCF_STATE_STRING_UNINIT) == 0)
6077c478bd9Sstevel@tonic-gate 		return (RESTARTER_STATE_UNINIT);
6087c478bd9Sstevel@tonic-gate 	else if (strcmp(string, SCF_STATE_STRING_MAINT) == 0)
6097c478bd9Sstevel@tonic-gate 		return (RESTARTER_STATE_MAINT);
6107c478bd9Sstevel@tonic-gate 	else if (strcmp(string, SCF_STATE_STRING_OFFLINE) == 0)
6117c478bd9Sstevel@tonic-gate 		return (RESTARTER_STATE_OFFLINE);
6127c478bd9Sstevel@tonic-gate 	else if (strcmp(string, SCF_STATE_STRING_DISABLED) == 0)
6137c478bd9Sstevel@tonic-gate 		return (RESTARTER_STATE_DISABLED);
6147c478bd9Sstevel@tonic-gate 	else if (strcmp(string, SCF_STATE_STRING_ONLINE) == 0)
6157c478bd9Sstevel@tonic-gate 		return (RESTARTER_STATE_ONLINE);
6167c478bd9Sstevel@tonic-gate 	else if (strcmp(string, SCF_STATE_STRING_DEGRADED) == 0)
6177c478bd9Sstevel@tonic-gate 		return (RESTARTER_STATE_DEGRADED);
6187c478bd9Sstevel@tonic-gate 	else {
6197c478bd9Sstevel@tonic-gate 		return (RESTARTER_STATE_NONE);
6207c478bd9Sstevel@tonic-gate 	}
6217c478bd9Sstevel@tonic-gate }
6227c478bd9Sstevel@tonic-gate 
6237c478bd9Sstevel@tonic-gate ssize_t
6247c478bd9Sstevel@tonic-gate restarter_state_to_string(restarter_instance_state_t state, char *string,
6257c478bd9Sstevel@tonic-gate     size_t len)
6267c478bd9Sstevel@tonic-gate {
6277c478bd9Sstevel@tonic-gate 	assert(string != NULL);
6287c478bd9Sstevel@tonic-gate 
6297c478bd9Sstevel@tonic-gate 	if (state == RESTARTER_STATE_NONE)
6307c478bd9Sstevel@tonic-gate 		return ((ssize_t)strlcpy(string, SCF_STATE_STRING_NONE, len));
6317c478bd9Sstevel@tonic-gate 	else if (state == RESTARTER_STATE_UNINIT)
6327c478bd9Sstevel@tonic-gate 		return ((ssize_t)strlcpy(string, SCF_STATE_STRING_UNINIT, len));
6337c478bd9Sstevel@tonic-gate 	else if (state == RESTARTER_STATE_MAINT)
6347c478bd9Sstevel@tonic-gate 		return ((ssize_t)strlcpy(string, SCF_STATE_STRING_MAINT, len));
6357c478bd9Sstevel@tonic-gate 	else if (state == RESTARTER_STATE_OFFLINE)
6367c478bd9Sstevel@tonic-gate 		return ((ssize_t)strlcpy(string, SCF_STATE_STRING_OFFLINE,
6377c478bd9Sstevel@tonic-gate 		    len));
6387c478bd9Sstevel@tonic-gate 	else if (state == RESTARTER_STATE_DISABLED)
6397c478bd9Sstevel@tonic-gate 		return ((ssize_t)strlcpy(string, SCF_STATE_STRING_DISABLED,
6407c478bd9Sstevel@tonic-gate 		    len));
6417c478bd9Sstevel@tonic-gate 	else if (state == RESTARTER_STATE_ONLINE)
6427c478bd9Sstevel@tonic-gate 		return ((ssize_t)strlcpy(string, SCF_STATE_STRING_ONLINE, len));
6437c478bd9Sstevel@tonic-gate 	else if (state == RESTARTER_STATE_DEGRADED)
6447c478bd9Sstevel@tonic-gate 		return ((ssize_t)strlcpy(string, SCF_STATE_STRING_DEGRADED,
6457c478bd9Sstevel@tonic-gate 		    len));
6467c478bd9Sstevel@tonic-gate 	else
6477c478bd9Sstevel@tonic-gate 		return ((ssize_t)strlcpy(string, "unknown", len));
6487c478bd9Sstevel@tonic-gate }
6497c478bd9Sstevel@tonic-gate 
6507c478bd9Sstevel@tonic-gate /*
6517c478bd9Sstevel@tonic-gate  * Sets pg to the name property group of s_inst.  If it doesn't exist, it is
6527c478bd9Sstevel@tonic-gate  * added.
6537c478bd9Sstevel@tonic-gate  *
6547c478bd9Sstevel@tonic-gate  * Fails with
6557c478bd9Sstevel@tonic-gate  *   ECONNABORTED - repository disconnection or unknown libscf error
6567c478bd9Sstevel@tonic-gate  *   EBADF - inst is not set
6577c478bd9Sstevel@tonic-gate  *   ECANCELED - inst is deleted
6587c478bd9Sstevel@tonic-gate  *   EPERM - permission is denied
6597c478bd9Sstevel@tonic-gate  *   EACCES - backend denied access
6607c478bd9Sstevel@tonic-gate  *   EROFS - backend readonly
6617c478bd9Sstevel@tonic-gate  */
6627c478bd9Sstevel@tonic-gate static int
6637c478bd9Sstevel@tonic-gate instance_get_or_add_pg(scf_instance_t *inst, const char *name,
6647c478bd9Sstevel@tonic-gate     const char *type, uint32_t flags, scf_propertygroup_t *pg)
6657c478bd9Sstevel@tonic-gate {
6667c478bd9Sstevel@tonic-gate again:
6677c478bd9Sstevel@tonic-gate 	if (scf_instance_get_pg(inst, name, pg) == 0)
6687c478bd9Sstevel@tonic-gate 		return (0);
6697c478bd9Sstevel@tonic-gate 
6707c478bd9Sstevel@tonic-gate 	switch (scf_error()) {
6717c478bd9Sstevel@tonic-gate 	case SCF_ERROR_CONNECTION_BROKEN:
6727c478bd9Sstevel@tonic-gate 	default:
6737c478bd9Sstevel@tonic-gate 		return (ECONNABORTED);
6747c478bd9Sstevel@tonic-gate 
6757c478bd9Sstevel@tonic-gate 	case SCF_ERROR_NOT_SET:
6767c478bd9Sstevel@tonic-gate 		return (EBADF);
6777c478bd9Sstevel@tonic-gate 
6787c478bd9Sstevel@tonic-gate 	case SCF_ERROR_DELETED:
6797c478bd9Sstevel@tonic-gate 		return (ECANCELED);
6807c478bd9Sstevel@tonic-gate 
6817c478bd9Sstevel@tonic-gate 	case SCF_ERROR_NOT_FOUND:
6827c478bd9Sstevel@tonic-gate 		break;
6837c478bd9Sstevel@tonic-gate 
6847c478bd9Sstevel@tonic-gate 	case SCF_ERROR_HANDLE_MISMATCH:
6857c478bd9Sstevel@tonic-gate 	case SCF_ERROR_INVALID_ARGUMENT:
6867c478bd9Sstevel@tonic-gate 		bad_fail("scf_instance_get_pg", scf_error());
6877c478bd9Sstevel@tonic-gate 	}
6887c478bd9Sstevel@tonic-gate 
6897c478bd9Sstevel@tonic-gate 	if (scf_instance_add_pg(inst, name, type, flags, pg) == 0)
6907c478bd9Sstevel@tonic-gate 		return (0);
6917c478bd9Sstevel@tonic-gate 
6927c478bd9Sstevel@tonic-gate 	switch (scf_error()) {
6937c478bd9Sstevel@tonic-gate 	case SCF_ERROR_CONNECTION_BROKEN:
6947c478bd9Sstevel@tonic-gate 	default:
6957c478bd9Sstevel@tonic-gate 		return (ECONNABORTED);
6967c478bd9Sstevel@tonic-gate 
6977c478bd9Sstevel@tonic-gate 	case SCF_ERROR_DELETED:
6987c478bd9Sstevel@tonic-gate 		return (ECANCELED);
6997c478bd9Sstevel@tonic-gate 
7007c478bd9Sstevel@tonic-gate 	case SCF_ERROR_EXISTS:
7017c478bd9Sstevel@tonic-gate 		goto again;
7027c478bd9Sstevel@tonic-gate 
7037c478bd9Sstevel@tonic-gate 	case SCF_ERROR_PERMISSION_DENIED:
7047c478bd9Sstevel@tonic-gate 		return (EPERM);
7057c478bd9Sstevel@tonic-gate 
7067c478bd9Sstevel@tonic-gate 	case SCF_ERROR_BACKEND_ACCESS:
7077c478bd9Sstevel@tonic-gate 		return (EACCES);
7087c478bd9Sstevel@tonic-gate 
7097c478bd9Sstevel@tonic-gate 	case SCF_ERROR_BACKEND_READONLY:
7107c478bd9Sstevel@tonic-gate 		return (EROFS);
7117c478bd9Sstevel@tonic-gate 
7127c478bd9Sstevel@tonic-gate 	case SCF_ERROR_HANDLE_MISMATCH:
7137c478bd9Sstevel@tonic-gate 	case SCF_ERROR_INVALID_ARGUMENT:
7147c478bd9Sstevel@tonic-gate 	case SCF_ERROR_NOT_SET:			/* should be caught above */
7157c478bd9Sstevel@tonic-gate 		bad_fail("scf_instance_add_pg", scf_error());
7167c478bd9Sstevel@tonic-gate 	}
7177c478bd9Sstevel@tonic-gate 
7187c478bd9Sstevel@tonic-gate 	return (0);
7197c478bd9Sstevel@tonic-gate }
7207c478bd9Sstevel@tonic-gate 
7217c478bd9Sstevel@tonic-gate /*
7227c478bd9Sstevel@tonic-gate  * Fails with
7237c478bd9Sstevel@tonic-gate  *   ECONNABORTED
7247c478bd9Sstevel@tonic-gate  *   ECANCELED - pg was deleted
7257c478bd9Sstevel@tonic-gate  */
7267c478bd9Sstevel@tonic-gate static int
7277c478bd9Sstevel@tonic-gate tx_set_value(scf_transaction_t *tx, scf_transaction_entry_t *ent,
7287c478bd9Sstevel@tonic-gate     const char *pname, scf_type_t ty, scf_value_t *val)
7297c478bd9Sstevel@tonic-gate {
7307c478bd9Sstevel@tonic-gate 	int r;
7317c478bd9Sstevel@tonic-gate 
7327c478bd9Sstevel@tonic-gate 	for (;;) {
7337c478bd9Sstevel@tonic-gate 		if (scf_transaction_property_change_type(tx, ent, pname,
7347c478bd9Sstevel@tonic-gate 		    ty) == 0)
7357c478bd9Sstevel@tonic-gate 			break;
7367c478bd9Sstevel@tonic-gate 
7377c478bd9Sstevel@tonic-gate 		switch (scf_error()) {
7387c478bd9Sstevel@tonic-gate 		case SCF_ERROR_CONNECTION_BROKEN:
7397c478bd9Sstevel@tonic-gate 		default:
7407c478bd9Sstevel@tonic-gate 			return (ECONNABORTED);
7417c478bd9Sstevel@tonic-gate 
7427c478bd9Sstevel@tonic-gate 		case SCF_ERROR_DELETED:
7437c478bd9Sstevel@tonic-gate 			return (ECANCELED);
7447c478bd9Sstevel@tonic-gate 
7457c478bd9Sstevel@tonic-gate 		case SCF_ERROR_NOT_FOUND:
7467c478bd9Sstevel@tonic-gate 			break;
7477c478bd9Sstevel@tonic-gate 
7487c478bd9Sstevel@tonic-gate 		case SCF_ERROR_HANDLE_MISMATCH:
7497c478bd9Sstevel@tonic-gate 		case SCF_ERROR_INVALID_ARGUMENT:
7507c478bd9Sstevel@tonic-gate 		case SCF_ERROR_IN_USE:
7517c478bd9Sstevel@tonic-gate 		case SCF_ERROR_NOT_SET:
7527c478bd9Sstevel@tonic-gate 			bad_fail("scf_transaction_property_change_type",
7537c478bd9Sstevel@tonic-gate 			    scf_error());
7547c478bd9Sstevel@tonic-gate 		}
7557c478bd9Sstevel@tonic-gate 
7567c478bd9Sstevel@tonic-gate 		if (scf_transaction_property_new(tx, ent, pname, ty) == 0)
7577c478bd9Sstevel@tonic-gate 			break;
7587c478bd9Sstevel@tonic-gate 
7597c478bd9Sstevel@tonic-gate 		switch (scf_error()) {
7607c478bd9Sstevel@tonic-gate 		case SCF_ERROR_CONNECTION_BROKEN:
7617c478bd9Sstevel@tonic-gate 		default:
7627c478bd9Sstevel@tonic-gate 			return (ECONNABORTED);
7637c478bd9Sstevel@tonic-gate 
7647c478bd9Sstevel@tonic-gate 		case SCF_ERROR_DELETED:
7657c478bd9Sstevel@tonic-gate 			return (ECANCELED);
7667c478bd9Sstevel@tonic-gate 
7677c478bd9Sstevel@tonic-gate 		case SCF_ERROR_EXISTS:
7687c478bd9Sstevel@tonic-gate 			break;
7697c478bd9Sstevel@tonic-gate 
7707c478bd9Sstevel@tonic-gate 		case SCF_ERROR_HANDLE_MISMATCH:
7717c478bd9Sstevel@tonic-gate 		case SCF_ERROR_INVALID_ARGUMENT:
7727c478bd9Sstevel@tonic-gate 		case SCF_ERROR_IN_USE:
7737c478bd9Sstevel@tonic-gate 		case SCF_ERROR_NOT_SET:
7747c478bd9Sstevel@tonic-gate 			bad_fail("scf_transaction_property_new", scf_error());
7757c478bd9Sstevel@tonic-gate 		}
7767c478bd9Sstevel@tonic-gate 	}
7777c478bd9Sstevel@tonic-gate 
7787c478bd9Sstevel@tonic-gate 	r = scf_entry_add_value(ent, val);
7797c478bd9Sstevel@tonic-gate 	assert(r == 0);
7807c478bd9Sstevel@tonic-gate 
7817c478bd9Sstevel@tonic-gate 	return (0);
7827c478bd9Sstevel@tonic-gate }
7837c478bd9Sstevel@tonic-gate 
7847c478bd9Sstevel@tonic-gate /*
7857c478bd9Sstevel@tonic-gate  * Commit new_state, new_next_state, and aux to the repository for id.  If
7867c478bd9Sstevel@tonic-gate  * successful, also set id's state and next-state as given, and return 0.
7877c478bd9Sstevel@tonic-gate  * Fails with
7887c478bd9Sstevel@tonic-gate  *   ENOMEM - out of memory
7897c478bd9Sstevel@tonic-gate  *   ECONNABORTED - repository connection broken
7907c478bd9Sstevel@tonic-gate  *		  - unknown libscf error
7917c478bd9Sstevel@tonic-gate  *   EINVAL - id->i_fmri is invalid or not an instance FMRI
7927c478bd9Sstevel@tonic-gate  *   ENOENT - id->i_fmri does not exist
7937c478bd9Sstevel@tonic-gate  *   EPERM - insufficient permissions
7947c478bd9Sstevel@tonic-gate  *   EACCES - backend access denied
7957c478bd9Sstevel@tonic-gate  *   EROFS - backend is readonly
7967c478bd9Sstevel@tonic-gate  */
7977c478bd9Sstevel@tonic-gate int
7987c478bd9Sstevel@tonic-gate _restarter_commit_states(scf_handle_t *h, instance_data_t *id,
7997c478bd9Sstevel@tonic-gate     restarter_instance_state_t new_state,
8007c478bd9Sstevel@tonic-gate     restarter_instance_state_t new_state_next, const char *aux)
8017c478bd9Sstevel@tonic-gate {
8027c478bd9Sstevel@tonic-gate 	char str_state[MAX_SCF_STATE_STRING_SZ];
8037c478bd9Sstevel@tonic-gate 	char str_new_state[MAX_SCF_STATE_STRING_SZ];
8047c478bd9Sstevel@tonic-gate 	char str_state_next[MAX_SCF_STATE_STRING_SZ];
8057c478bd9Sstevel@tonic-gate 	char str_new_state_next[MAX_SCF_STATE_STRING_SZ];
8067c478bd9Sstevel@tonic-gate 	int ret = 0, r;
8077c478bd9Sstevel@tonic-gate 	struct timeval now;
8087c478bd9Sstevel@tonic-gate 	ssize_t sz;
8097c478bd9Sstevel@tonic-gate 
8107c478bd9Sstevel@tonic-gate 	scf_transaction_t *t = NULL;
8117c478bd9Sstevel@tonic-gate 	scf_transaction_entry_t *t_state = NULL, *t_state_next = NULL;
8127c478bd9Sstevel@tonic-gate 	scf_transaction_entry_t *t_stime = NULL, *t_aux = NULL;
8137c478bd9Sstevel@tonic-gate 	scf_value_t *v_state = NULL, *v_state_next = NULL, *v_stime = NULL;
8147c478bd9Sstevel@tonic-gate 	scf_value_t *v_aux = NULL;
8157c478bd9Sstevel@tonic-gate 	scf_instance_t *s_inst = NULL;
8167c478bd9Sstevel@tonic-gate 	scf_propertygroup_t *pg = NULL;
8177c478bd9Sstevel@tonic-gate 
8187c478bd9Sstevel@tonic-gate 	assert(new_state != RESTARTER_STATE_NONE);
8197c478bd9Sstevel@tonic-gate 
8207c478bd9Sstevel@tonic-gate 	if ((s_inst = scf_instance_create(h)) == NULL ||
8217c478bd9Sstevel@tonic-gate 	    (pg = scf_pg_create(h)) == NULL ||
8227c478bd9Sstevel@tonic-gate 	    (t = scf_transaction_create(h)) == NULL ||
8237c478bd9Sstevel@tonic-gate 	    (t_state = scf_entry_create(h)) == NULL ||
8247c478bd9Sstevel@tonic-gate 	    (t_state_next = scf_entry_create(h)) == NULL ||
8257c478bd9Sstevel@tonic-gate 	    (t_stime = scf_entry_create(h)) == NULL ||
8267c478bd9Sstevel@tonic-gate 	    (t_aux = scf_entry_create(h)) == NULL ||
8277c478bd9Sstevel@tonic-gate 	    (v_state = scf_value_create(h)) == NULL ||
8287c478bd9Sstevel@tonic-gate 	    (v_state_next = scf_value_create(h)) == NULL ||
8297c478bd9Sstevel@tonic-gate 	    (v_stime = scf_value_create(h)) == NULL ||
8307c478bd9Sstevel@tonic-gate 	    (v_aux = scf_value_create(h)) == NULL) {
8317c478bd9Sstevel@tonic-gate 		ret = ENOMEM;
8327c478bd9Sstevel@tonic-gate 		goto out;
8337c478bd9Sstevel@tonic-gate 	}
8347c478bd9Sstevel@tonic-gate 
8357c478bd9Sstevel@tonic-gate 	sz = restarter_state_to_string(new_state, str_new_state,
8367c478bd9Sstevel@tonic-gate 	    sizeof (str_new_state));
8377c478bd9Sstevel@tonic-gate 	assert(sz < sizeof (str_new_state));
8387c478bd9Sstevel@tonic-gate 	sz = restarter_state_to_string(new_state_next, str_new_state_next,
8397c478bd9Sstevel@tonic-gate 	    sizeof (str_new_state_next));
8407c478bd9Sstevel@tonic-gate 	assert(sz < sizeof (str_new_state_next));
8417c478bd9Sstevel@tonic-gate 	sz = restarter_state_to_string(id->i_state, str_state,
8427c478bd9Sstevel@tonic-gate 	    sizeof (str_state));
8437c478bd9Sstevel@tonic-gate 	assert(sz < sizeof (str_state));
8447c478bd9Sstevel@tonic-gate 	sz = restarter_state_to_string(id->i_next_state, str_state_next,
8457c478bd9Sstevel@tonic-gate 	    sizeof (str_state_next));
8467c478bd9Sstevel@tonic-gate 	assert(sz < sizeof (str_state_next));
8477c478bd9Sstevel@tonic-gate 
8487c478bd9Sstevel@tonic-gate 	ret = gettimeofday(&now, NULL);
8497c478bd9Sstevel@tonic-gate 	assert(ret != -1);
8507c478bd9Sstevel@tonic-gate 
8517c478bd9Sstevel@tonic-gate 	if (scf_handle_decode_fmri(h, id->i_fmri, NULL, NULL, s_inst,
8527c478bd9Sstevel@tonic-gate 	    NULL, NULL, SCF_DECODE_FMRI_EXACT) == -1) {
8537c478bd9Sstevel@tonic-gate 		switch (scf_error()) {
8547c478bd9Sstevel@tonic-gate 		case SCF_ERROR_CONNECTION_BROKEN:
8557c478bd9Sstevel@tonic-gate 		default:
8567c478bd9Sstevel@tonic-gate 			ret = ECONNABORTED;
8577c478bd9Sstevel@tonic-gate 			break;
8587c478bd9Sstevel@tonic-gate 
8597c478bd9Sstevel@tonic-gate 		case SCF_ERROR_INVALID_ARGUMENT:
8607c478bd9Sstevel@tonic-gate 		case SCF_ERROR_CONSTRAINT_VIOLATED:
8617c478bd9Sstevel@tonic-gate 			ret = EINVAL;
8627c478bd9Sstevel@tonic-gate 			break;
8637c478bd9Sstevel@tonic-gate 
8647c478bd9Sstevel@tonic-gate 		case SCF_ERROR_NOT_FOUND:
8657c478bd9Sstevel@tonic-gate 			ret = ENOENT;
8667c478bd9Sstevel@tonic-gate 			break;
8677c478bd9Sstevel@tonic-gate 
8687c478bd9Sstevel@tonic-gate 		case SCF_ERROR_HANDLE_MISMATCH:
8697c478bd9Sstevel@tonic-gate 			bad_fail("scf_handle_decode_fmri", scf_error());
8707c478bd9Sstevel@tonic-gate 		}
8717c478bd9Sstevel@tonic-gate 		goto out;
8727c478bd9Sstevel@tonic-gate 	}
8737c478bd9Sstevel@tonic-gate 
8747c478bd9Sstevel@tonic-gate 
8757c478bd9Sstevel@tonic-gate 	if (scf_value_set_astring(v_state, str_new_state) != 0 ||
876eb1a3463STruong Nguyen 	    scf_value_set_astring(v_state_next, str_new_state_next) != 0)
8777c478bd9Sstevel@tonic-gate 		bad_fail("scf_value_set_astring", scf_error());
8787c478bd9Sstevel@tonic-gate 
879eb1a3463STruong Nguyen 	if (aux) {
880eb1a3463STruong Nguyen 		if (scf_value_set_astring(v_aux, aux) != 0)
881eb1a3463STruong Nguyen 			bad_fail("scf_value_set_astring", scf_error());
882eb1a3463STruong Nguyen 	}
883eb1a3463STruong Nguyen 
8847c478bd9Sstevel@tonic-gate 	if (scf_value_set_time(v_stime, now.tv_sec, now.tv_usec * 1000) != 0)
8857c478bd9Sstevel@tonic-gate 		bad_fail("scf_value_set_time", scf_error());
8867c478bd9Sstevel@tonic-gate 
8877c478bd9Sstevel@tonic-gate add_pg:
8887c478bd9Sstevel@tonic-gate 	switch (r = instance_get_or_add_pg(s_inst, SCF_PG_RESTARTER,
8897c478bd9Sstevel@tonic-gate 	    SCF_PG_RESTARTER_TYPE, SCF_PG_RESTARTER_FLAGS, pg)) {
8907c478bd9Sstevel@tonic-gate 	case 0:
8917c478bd9Sstevel@tonic-gate 		break;
8927c478bd9Sstevel@tonic-gate 
8937c478bd9Sstevel@tonic-gate 	case ECONNABORTED:
8947c478bd9Sstevel@tonic-gate 	case EPERM:
8957c478bd9Sstevel@tonic-gate 	case EACCES:
8967c478bd9Sstevel@tonic-gate 	case EROFS:
8977c478bd9Sstevel@tonic-gate 		ret = r;
8987c478bd9Sstevel@tonic-gate 		goto out;
8997c478bd9Sstevel@tonic-gate 
9007c478bd9Sstevel@tonic-gate 	case ECANCELED:
9017c478bd9Sstevel@tonic-gate 		ret = ENOENT;
9027c478bd9Sstevel@tonic-gate 		goto out;
9037c478bd9Sstevel@tonic-gate 
9047c478bd9Sstevel@tonic-gate 	case EBADF:
9057c478bd9Sstevel@tonic-gate 	default:
9067c478bd9Sstevel@tonic-gate 		bad_fail("instance_get_or_add_pg", r);
9077c478bd9Sstevel@tonic-gate 	}
9087c478bd9Sstevel@tonic-gate 
9097c478bd9Sstevel@tonic-gate 	for (;;) {
9107c478bd9Sstevel@tonic-gate 		if (scf_transaction_start(t, pg) != 0) {
9117c478bd9Sstevel@tonic-gate 			switch (scf_error()) {
9127c478bd9Sstevel@tonic-gate 			case SCF_ERROR_CONNECTION_BROKEN:
9137c478bd9Sstevel@tonic-gate 			default:
9147c478bd9Sstevel@tonic-gate 				ret = ECONNABORTED;
9157c478bd9Sstevel@tonic-gate 				goto out;
9167c478bd9Sstevel@tonic-gate 
9177c478bd9Sstevel@tonic-gate 			case SCF_ERROR_NOT_SET:
9187c478bd9Sstevel@tonic-gate 				goto add_pg;
9197c478bd9Sstevel@tonic-gate 
9207c478bd9Sstevel@tonic-gate 			case SCF_ERROR_PERMISSION_DENIED:
9217c478bd9Sstevel@tonic-gate 				ret = EPERM;
9227c478bd9Sstevel@tonic-gate 				goto out;
9237c478bd9Sstevel@tonic-gate 
9247c478bd9Sstevel@tonic-gate 			case SCF_ERROR_BACKEND_ACCESS:
9257c478bd9Sstevel@tonic-gate 				ret = EACCES;
9267c478bd9Sstevel@tonic-gate 				goto out;
9277c478bd9Sstevel@tonic-gate 
9287c478bd9Sstevel@tonic-gate 			case SCF_ERROR_BACKEND_READONLY:
9297c478bd9Sstevel@tonic-gate 				ret = EROFS;
9307c478bd9Sstevel@tonic-gate 				goto out;
9317c478bd9Sstevel@tonic-gate 
9327c478bd9Sstevel@tonic-gate 			case SCF_ERROR_HANDLE_MISMATCH:
9337c478bd9Sstevel@tonic-gate 			case SCF_ERROR_IN_USE:
9347c478bd9Sstevel@tonic-gate 				bad_fail("scf_transaction_start", scf_error());
9357c478bd9Sstevel@tonic-gate 			}
9367c478bd9Sstevel@tonic-gate 		}
9377c478bd9Sstevel@tonic-gate 
9387c478bd9Sstevel@tonic-gate 		if ((r = tx_set_value(t, t_state, SCF_PROPERTY_STATE,
9397c478bd9Sstevel@tonic-gate 		    SCF_TYPE_ASTRING, v_state)) != 0 ||
9407c478bd9Sstevel@tonic-gate 		    (r = tx_set_value(t, t_state_next, SCF_PROPERTY_NEXT_STATE,
9417c478bd9Sstevel@tonic-gate 		    SCF_TYPE_ASTRING, v_state_next)) != 0 ||
9427c478bd9Sstevel@tonic-gate 		    (r = tx_set_value(t, t_stime, SCF_PROPERTY_STATE_TIMESTAMP,
9437c478bd9Sstevel@tonic-gate 		    SCF_TYPE_TIME, v_stime)) != 0) {
9447c478bd9Sstevel@tonic-gate 			switch (r) {
9457c478bd9Sstevel@tonic-gate 			case ECONNABORTED:
9467c478bd9Sstevel@tonic-gate 				ret = ECONNABORTED;
9477c478bd9Sstevel@tonic-gate 				goto out;
9487c478bd9Sstevel@tonic-gate 
9497c478bd9Sstevel@tonic-gate 			case ECANCELED:
9507c478bd9Sstevel@tonic-gate 				scf_transaction_reset(t);
9517c478bd9Sstevel@tonic-gate 				goto add_pg;
9527c478bd9Sstevel@tonic-gate 
9537c478bd9Sstevel@tonic-gate 			default:
9547c478bd9Sstevel@tonic-gate 				bad_fail("tx_set_value", r);
9557c478bd9Sstevel@tonic-gate 			}
9567c478bd9Sstevel@tonic-gate 		}
9577c478bd9Sstevel@tonic-gate 
958eb1a3463STruong Nguyen 		if (aux) {
959eb1a3463STruong Nguyen 			if ((r = tx_set_value(t, t_aux, SCF_PROPERTY_AUX_STATE,
960eb1a3463STruong Nguyen 			    SCF_TYPE_ASTRING, v_aux)) != 0) {
961eb1a3463STruong Nguyen 				switch (r) {
962eb1a3463STruong Nguyen 				case ECONNABORTED:
963eb1a3463STruong Nguyen 					ret = ECONNABORTED;
964eb1a3463STruong Nguyen 					goto out;
965eb1a3463STruong Nguyen 
966eb1a3463STruong Nguyen 				case ECANCELED:
967eb1a3463STruong Nguyen 					scf_transaction_reset(t);
968eb1a3463STruong Nguyen 					goto add_pg;
969eb1a3463STruong Nguyen 
970eb1a3463STruong Nguyen 				default:
971eb1a3463STruong Nguyen 					bad_fail("tx_set_value", r);
972eb1a3463STruong Nguyen 				}
973eb1a3463STruong Nguyen 			}
974eb1a3463STruong Nguyen 		}
975eb1a3463STruong Nguyen 
9767c478bd9Sstevel@tonic-gate 		ret = scf_transaction_commit(t);
9777c478bd9Sstevel@tonic-gate 		if (ret == 1)
9787c478bd9Sstevel@tonic-gate 			break;
9797c478bd9Sstevel@tonic-gate 		if (ret == -1) {
9807c478bd9Sstevel@tonic-gate 			switch (scf_error()) {
9817c478bd9Sstevel@tonic-gate 			case SCF_ERROR_CONNECTION_BROKEN:
9827c478bd9Sstevel@tonic-gate 			default:
9837c478bd9Sstevel@tonic-gate 				ret = ECONNABORTED;
9847c478bd9Sstevel@tonic-gate 				goto out;
9857c478bd9Sstevel@tonic-gate 
9867c478bd9Sstevel@tonic-gate 			case SCF_ERROR_PERMISSION_DENIED:
9877c478bd9Sstevel@tonic-gate 				ret = EPERM;
9887c478bd9Sstevel@tonic-gate 				goto out;
9897c478bd9Sstevel@tonic-gate 
9907c478bd9Sstevel@tonic-gate 			case SCF_ERROR_BACKEND_ACCESS:
9917c478bd9Sstevel@tonic-gate 				ret = EACCES;
9927c478bd9Sstevel@tonic-gate 				goto out;
9937c478bd9Sstevel@tonic-gate 
9947c478bd9Sstevel@tonic-gate 			case SCF_ERROR_BACKEND_READONLY:
9957c478bd9Sstevel@tonic-gate 				ret = EROFS;
9967c478bd9Sstevel@tonic-gate 				goto out;
9977c478bd9Sstevel@tonic-gate 
9987c478bd9Sstevel@tonic-gate 			case SCF_ERROR_NOT_SET:
9997c478bd9Sstevel@tonic-gate 				bad_fail("scf_transaction_commit", scf_error());
10007c478bd9Sstevel@tonic-gate 			}
10017c478bd9Sstevel@tonic-gate 		}
10027c478bd9Sstevel@tonic-gate 
10037c478bd9Sstevel@tonic-gate 		scf_transaction_reset(t);
10047c478bd9Sstevel@tonic-gate 		if (scf_pg_update(pg) == -1) {
10057c478bd9Sstevel@tonic-gate 			switch (scf_error()) {
10067c478bd9Sstevel@tonic-gate 			case SCF_ERROR_CONNECTION_BROKEN:
10077c478bd9Sstevel@tonic-gate 			default:
10087c478bd9Sstevel@tonic-gate 				ret = ECONNABORTED;
10097c478bd9Sstevel@tonic-gate 				goto out;
10107c478bd9Sstevel@tonic-gate 
10117c478bd9Sstevel@tonic-gate 			case SCF_ERROR_NOT_SET:
10127c478bd9Sstevel@tonic-gate 				goto add_pg;
10137c478bd9Sstevel@tonic-gate 			}
10147c478bd9Sstevel@tonic-gate 		}
10157c478bd9Sstevel@tonic-gate 	}
10167c478bd9Sstevel@tonic-gate 
10177c478bd9Sstevel@tonic-gate 	id->i_state = new_state;
10187c478bd9Sstevel@tonic-gate 	id->i_next_state = new_state_next;
10197c478bd9Sstevel@tonic-gate 	ret = 0;
10207c478bd9Sstevel@tonic-gate 
10217c478bd9Sstevel@tonic-gate out:
10227c478bd9Sstevel@tonic-gate 	scf_transaction_destroy(t);
10237c478bd9Sstevel@tonic-gate 	scf_entry_destroy(t_state);
10247c478bd9Sstevel@tonic-gate 	scf_entry_destroy(t_state_next);
10257c478bd9Sstevel@tonic-gate 	scf_entry_destroy(t_stime);
10267c478bd9Sstevel@tonic-gate 	scf_entry_destroy(t_aux);
10277c478bd9Sstevel@tonic-gate 	scf_value_destroy(v_state);
10287c478bd9Sstevel@tonic-gate 	scf_value_destroy(v_state_next);
10297c478bd9Sstevel@tonic-gate 	scf_value_destroy(v_stime);
10307c478bd9Sstevel@tonic-gate 	scf_value_destroy(v_aux);
10317c478bd9Sstevel@tonic-gate 	scf_pg_destroy(pg);
10327c478bd9Sstevel@tonic-gate 	scf_instance_destroy(s_inst);
10337c478bd9Sstevel@tonic-gate 
10347c478bd9Sstevel@tonic-gate 	return (ret);
10357c478bd9Sstevel@tonic-gate }
10367c478bd9Sstevel@tonic-gate 
10377c478bd9Sstevel@tonic-gate /*
10387c478bd9Sstevel@tonic-gate  * Fails with
10397c478bd9Sstevel@tonic-gate  *   EINVAL - type is invalid
10407c478bd9Sstevel@tonic-gate  *   ENOMEM
10417c478bd9Sstevel@tonic-gate  *   ECONNABORTED - repository connection broken
10427c478bd9Sstevel@tonic-gate  *   EBADF - s_inst is not set
10437c478bd9Sstevel@tonic-gate  *   ECANCELED - s_inst is deleted
10447c478bd9Sstevel@tonic-gate  *   EPERM - permission denied
10457c478bd9Sstevel@tonic-gate  *   EACCES - backend access denied
10467c478bd9Sstevel@tonic-gate  *   EROFS - backend readonly
10477c478bd9Sstevel@tonic-gate  */
10487c478bd9Sstevel@tonic-gate int
10497c478bd9Sstevel@tonic-gate restarter_remove_contract(scf_instance_t *s_inst, ctid_t contract_id,
10507c478bd9Sstevel@tonic-gate     restarter_contract_type_t type)
10517c478bd9Sstevel@tonic-gate {
10527c478bd9Sstevel@tonic-gate 	scf_handle_t *h;
10537c478bd9Sstevel@tonic-gate 	scf_transaction_t *t = NULL;
10547c478bd9Sstevel@tonic-gate 	scf_transaction_entry_t *t_cid = NULL;
10557c478bd9Sstevel@tonic-gate 	scf_propertygroup_t *pg = NULL;
10567c478bd9Sstevel@tonic-gate 	scf_property_t *prop = NULL;
10577c478bd9Sstevel@tonic-gate 	scf_value_t *val;
10587c478bd9Sstevel@tonic-gate 	scf_iter_t *iter = NULL;
10597c478bd9Sstevel@tonic-gate 	const char *pname;
10607c478bd9Sstevel@tonic-gate 	int ret = 0, primary;
10617c478bd9Sstevel@tonic-gate 	uint64_t c;
10627c478bd9Sstevel@tonic-gate 
10637c478bd9Sstevel@tonic-gate 	switch (type) {
10647c478bd9Sstevel@tonic-gate 	case RESTARTER_CONTRACT_PRIMARY:
10657c478bd9Sstevel@tonic-gate 		primary = 1;
10667c478bd9Sstevel@tonic-gate 		break;
10677c478bd9Sstevel@tonic-gate 	case RESTARTER_CONTRACT_TRANSIENT:
10687c478bd9Sstevel@tonic-gate 		primary = 0;
10697c478bd9Sstevel@tonic-gate 		break;
10707c478bd9Sstevel@tonic-gate 	default:
10717c478bd9Sstevel@tonic-gate 		return (EINVAL);
10727c478bd9Sstevel@tonic-gate 	}
10737c478bd9Sstevel@tonic-gate 
10747c478bd9Sstevel@tonic-gate 	h = scf_instance_handle(s_inst);
10757c478bd9Sstevel@tonic-gate 
10767c478bd9Sstevel@tonic-gate 	pg = scf_pg_create(h);
10777c478bd9Sstevel@tonic-gate 	prop = scf_property_create(h);
10787c478bd9Sstevel@tonic-gate 	iter = scf_iter_create(h);
10797c478bd9Sstevel@tonic-gate 	t = scf_transaction_create(h);
10807c478bd9Sstevel@tonic-gate 
10817c478bd9Sstevel@tonic-gate 	if (pg == NULL || prop == NULL || iter == NULL || t == NULL) {
10827c478bd9Sstevel@tonic-gate 		ret = ENOMEM;
10837c478bd9Sstevel@tonic-gate 		goto remove_contract_cleanup;
10847c478bd9Sstevel@tonic-gate 	}
10857c478bd9Sstevel@tonic-gate 
10867c478bd9Sstevel@tonic-gate add:
10877c478bd9Sstevel@tonic-gate 	scf_transaction_destroy_children(t);
10887c478bd9Sstevel@tonic-gate 	ret = instance_get_or_add_pg(s_inst, SCF_PG_RESTARTER,
10897c478bd9Sstevel@tonic-gate 	    SCF_PG_RESTARTER_TYPE, SCF_PG_RESTARTER_FLAGS, pg);
10907c478bd9Sstevel@tonic-gate 	if (ret != 0)
10917c478bd9Sstevel@tonic-gate 		goto remove_contract_cleanup;
10927c478bd9Sstevel@tonic-gate 
10937c478bd9Sstevel@tonic-gate 	pname = primary? SCF_PROPERTY_CONTRACT :
10947c478bd9Sstevel@tonic-gate 	    SCF_PROPERTY_TRANSIENT_CONTRACT;
10957c478bd9Sstevel@tonic-gate 
10967c478bd9Sstevel@tonic-gate 	for (;;) {
10977c478bd9Sstevel@tonic-gate 		if (scf_transaction_start(t, pg) != 0) {
10987c478bd9Sstevel@tonic-gate 			switch (scf_error()) {
10997c478bd9Sstevel@tonic-gate 			case SCF_ERROR_CONNECTION_BROKEN:
11007c478bd9Sstevel@tonic-gate 			default:
11017c478bd9Sstevel@tonic-gate 				ret = ECONNABORTED;
11027c478bd9Sstevel@tonic-gate 				goto remove_contract_cleanup;
11037c478bd9Sstevel@tonic-gate 
11047c478bd9Sstevel@tonic-gate 			case SCF_ERROR_DELETED:
11057c478bd9Sstevel@tonic-gate 				goto add;
11067c478bd9Sstevel@tonic-gate 
11077c478bd9Sstevel@tonic-gate 			case SCF_ERROR_PERMISSION_DENIED:
11087c478bd9Sstevel@tonic-gate 				ret = EPERM;
11097c478bd9Sstevel@tonic-gate 				goto remove_contract_cleanup;
11107c478bd9Sstevel@tonic-gate 
11117c478bd9Sstevel@tonic-gate 			case SCF_ERROR_BACKEND_ACCESS:
11127c478bd9Sstevel@tonic-gate 				ret = EACCES;
11137c478bd9Sstevel@tonic-gate 				goto remove_contract_cleanup;
11147c478bd9Sstevel@tonic-gate 
11157c478bd9Sstevel@tonic-gate 			case SCF_ERROR_BACKEND_READONLY:
11167c478bd9Sstevel@tonic-gate 				ret = EROFS;
11177c478bd9Sstevel@tonic-gate 				goto remove_contract_cleanup;
11187c478bd9Sstevel@tonic-gate 
11197c478bd9Sstevel@tonic-gate 			case SCF_ERROR_HANDLE_MISMATCH:
11207c478bd9Sstevel@tonic-gate 			case SCF_ERROR_IN_USE:
11217c478bd9Sstevel@tonic-gate 			case SCF_ERROR_NOT_SET:
11227c478bd9Sstevel@tonic-gate 				bad_fail("scf_transaction_start", scf_error());
11237c478bd9Sstevel@tonic-gate 			}
11247c478bd9Sstevel@tonic-gate 		}
11257c478bd9Sstevel@tonic-gate 
11267c478bd9Sstevel@tonic-gate 		t_cid = scf_entry_create(h);
11277c478bd9Sstevel@tonic-gate 
11287c478bd9Sstevel@tonic-gate 		if (scf_pg_get_property(pg, pname, prop) == 0) {
11297c478bd9Sstevel@tonic-gate replace:
11307c478bd9Sstevel@tonic-gate 			if (scf_transaction_property_change_type(t, t_cid,
11317c478bd9Sstevel@tonic-gate 			    pname, SCF_TYPE_COUNT) != 0) {
11327c478bd9Sstevel@tonic-gate 				switch (scf_error()) {
11337c478bd9Sstevel@tonic-gate 				case SCF_ERROR_CONNECTION_BROKEN:
11347c478bd9Sstevel@tonic-gate 				default:
11357c478bd9Sstevel@tonic-gate 					ret = ECONNABORTED;
11367c478bd9Sstevel@tonic-gate 					goto remove_contract_cleanup;
11377c478bd9Sstevel@tonic-gate 
11387c478bd9Sstevel@tonic-gate 				case SCF_ERROR_DELETED:
11397c478bd9Sstevel@tonic-gate 					scf_entry_destroy(t_cid);
11407c478bd9Sstevel@tonic-gate 					goto add;
11417c478bd9Sstevel@tonic-gate 
11427c478bd9Sstevel@tonic-gate 				case SCF_ERROR_NOT_FOUND:
11437c478bd9Sstevel@tonic-gate 					goto new;
11447c478bd9Sstevel@tonic-gate 
11457c478bd9Sstevel@tonic-gate 				case SCF_ERROR_HANDLE_MISMATCH:
11467c478bd9Sstevel@tonic-gate 				case SCF_ERROR_INVALID_ARGUMENT:
11477c478bd9Sstevel@tonic-gate 				case SCF_ERROR_IN_USE:
11487c478bd9Sstevel@tonic-gate 				case SCF_ERROR_NOT_SET:
11497c478bd9Sstevel@tonic-gate 					bad_fail(
11507c478bd9Sstevel@tonic-gate 					"scf_transaction_property_changetype",
11517c478bd9Sstevel@tonic-gate 					    scf_error());
11527c478bd9Sstevel@tonic-gate 				}
11537c478bd9Sstevel@tonic-gate 			}
11547c478bd9Sstevel@tonic-gate 
11557c478bd9Sstevel@tonic-gate 			if (scf_property_is_type(prop, SCF_TYPE_COUNT) == 0) {
11567c478bd9Sstevel@tonic-gate 				if (scf_iter_property_values(iter, prop) != 0) {
11577c478bd9Sstevel@tonic-gate 					switch (scf_error()) {
11587c478bd9Sstevel@tonic-gate 					case SCF_ERROR_CONNECTION_BROKEN:
11597c478bd9Sstevel@tonic-gate 					default:
11607c478bd9Sstevel@tonic-gate 						ret = ECONNABORTED;
11617c478bd9Sstevel@tonic-gate 						goto remove_contract_cleanup;
11627c478bd9Sstevel@tonic-gate 
11637c478bd9Sstevel@tonic-gate 					case SCF_ERROR_NOT_SET:
11647c478bd9Sstevel@tonic-gate 					case SCF_ERROR_HANDLE_MISMATCH:
11657c478bd9Sstevel@tonic-gate 						bad_fail(
11667c478bd9Sstevel@tonic-gate 						    "scf_iter_property_values",
11677c478bd9Sstevel@tonic-gate 						    scf_error());
11687c478bd9Sstevel@tonic-gate 					}
11697c478bd9Sstevel@tonic-gate 				}
11707c478bd9Sstevel@tonic-gate 
11717c478bd9Sstevel@tonic-gate next_val:
11727c478bd9Sstevel@tonic-gate 				val = scf_value_create(h);
11737c478bd9Sstevel@tonic-gate 				if (val == NULL) {
11747c478bd9Sstevel@tonic-gate 					assert(scf_error() ==
11757c478bd9Sstevel@tonic-gate 					    SCF_ERROR_NO_MEMORY);
11767c478bd9Sstevel@tonic-gate 					ret = ENOMEM;
11777c478bd9Sstevel@tonic-gate 					goto remove_contract_cleanup;
11787c478bd9Sstevel@tonic-gate 				}
11797c478bd9Sstevel@tonic-gate 
11807c478bd9Sstevel@tonic-gate 				ret = scf_iter_next_value(iter, val);
11817c478bd9Sstevel@tonic-gate 				if (ret == -1) {
11827c478bd9Sstevel@tonic-gate 					switch (scf_error()) {
11837c478bd9Sstevel@tonic-gate 					case SCF_ERROR_CONNECTION_BROKEN:
11847c478bd9Sstevel@tonic-gate 						ret = ECONNABORTED;
11857c478bd9Sstevel@tonic-gate 						goto remove_contract_cleanup;
11867c478bd9Sstevel@tonic-gate 
11877c478bd9Sstevel@tonic-gate 					case SCF_ERROR_DELETED:
11887c478bd9Sstevel@tonic-gate 						scf_value_destroy(val);
11897c478bd9Sstevel@tonic-gate 						goto add;
11907c478bd9Sstevel@tonic-gate 
11917c478bd9Sstevel@tonic-gate 					case SCF_ERROR_HANDLE_MISMATCH:
11927c478bd9Sstevel@tonic-gate 					case SCF_ERROR_INVALID_ARGUMENT:
11933eae19d9Swesolows 					case SCF_ERROR_PERMISSION_DENIED:
11947c478bd9Sstevel@tonic-gate 					default:
11957c478bd9Sstevel@tonic-gate 						bad_fail("scf_iter_next_value",
11967c478bd9Sstevel@tonic-gate 						    scf_error());
11977c478bd9Sstevel@tonic-gate 					}
11987c478bd9Sstevel@tonic-gate 				}
11997c478bd9Sstevel@tonic-gate 
12007c478bd9Sstevel@tonic-gate 				if (ret == 1) {
12017c478bd9Sstevel@tonic-gate 					ret = scf_value_get_count(val, &c);
12027c478bd9Sstevel@tonic-gate 					assert(ret == 0);
12037c478bd9Sstevel@tonic-gate 
12047c478bd9Sstevel@tonic-gate 					if (c != contract_id) {
12057c478bd9Sstevel@tonic-gate 						ret = scf_entry_add_value(t_cid,
12067c478bd9Sstevel@tonic-gate 						    val);
12077c478bd9Sstevel@tonic-gate 						assert(ret == 0);
12087c478bd9Sstevel@tonic-gate 					} else {
12097c478bd9Sstevel@tonic-gate 						scf_value_destroy(val);
12107c478bd9Sstevel@tonic-gate 					}
12117c478bd9Sstevel@tonic-gate 
12127c478bd9Sstevel@tonic-gate 					goto next_val;
12137c478bd9Sstevel@tonic-gate 				}
12147c478bd9Sstevel@tonic-gate 
12157c478bd9Sstevel@tonic-gate 				scf_value_destroy(val);
12167c478bd9Sstevel@tonic-gate 			} else {
12177c478bd9Sstevel@tonic-gate 				switch (scf_error()) {
12187c478bd9Sstevel@tonic-gate 				case SCF_ERROR_CONNECTION_BROKEN:
12197c478bd9Sstevel@tonic-gate 				default:
12207c478bd9Sstevel@tonic-gate 					ret = ECONNABORTED;
12217c478bd9Sstevel@tonic-gate 					goto remove_contract_cleanup;
12227c478bd9Sstevel@tonic-gate 
12237c478bd9Sstevel@tonic-gate 				case SCF_ERROR_TYPE_MISMATCH:
12247c478bd9Sstevel@tonic-gate 					break;
12257c478bd9Sstevel@tonic-gate 
12267c478bd9Sstevel@tonic-gate 				case SCF_ERROR_INVALID_ARGUMENT:
12277c478bd9Sstevel@tonic-gate 				case SCF_ERROR_NOT_SET:
12287c478bd9Sstevel@tonic-gate 					bad_fail("scf_property_is_type",
12297c478bd9Sstevel@tonic-gate 					    scf_error());
12307c478bd9Sstevel@tonic-gate 				}
12317c478bd9Sstevel@tonic-gate 			}
12327c478bd9Sstevel@tonic-gate 		} else {
12337c478bd9Sstevel@tonic-gate 			switch (scf_error()) {
12347c478bd9Sstevel@tonic-gate 			case SCF_ERROR_CONNECTION_BROKEN:
12357c478bd9Sstevel@tonic-gate 			default:
12367c478bd9Sstevel@tonic-gate 				ret = ECONNABORTED;
12377c478bd9Sstevel@tonic-gate 				goto remove_contract_cleanup;
12387c478bd9Sstevel@tonic-gate 
12397c478bd9Sstevel@tonic-gate 			case SCF_ERROR_DELETED:
12407c478bd9Sstevel@tonic-gate 				scf_entry_destroy(t_cid);
12417c478bd9Sstevel@tonic-gate 				goto add;
12427c478bd9Sstevel@tonic-gate 
12437c478bd9Sstevel@tonic-gate 			case SCF_ERROR_NOT_FOUND:
12447c478bd9Sstevel@tonic-gate 				break;
12457c478bd9Sstevel@tonic-gate 
12467c478bd9Sstevel@tonic-gate 			case SCF_ERROR_HANDLE_MISMATCH:
12477c478bd9Sstevel@tonic-gate 			case SCF_ERROR_INVALID_ARGUMENT:
12487c478bd9Sstevel@tonic-gate 			case SCF_ERROR_NOT_SET:
12497c478bd9Sstevel@tonic-gate 				bad_fail("scf_pg_get_property", scf_error());
12507c478bd9Sstevel@tonic-gate 			}
12517c478bd9Sstevel@tonic-gate 
12527c478bd9Sstevel@tonic-gate new:
12537c478bd9Sstevel@tonic-gate 			if (scf_transaction_property_new(t, t_cid, pname,
12547c478bd9Sstevel@tonic-gate 			    SCF_TYPE_COUNT) != 0) {
12557c478bd9Sstevel@tonic-gate 				switch (scf_error()) {
12567c478bd9Sstevel@tonic-gate 				case SCF_ERROR_CONNECTION_BROKEN:
12577c478bd9Sstevel@tonic-gate 				default:
12587c478bd9Sstevel@tonic-gate 					ret = ECONNABORTED;
12597c478bd9Sstevel@tonic-gate 					goto remove_contract_cleanup;
12607c478bd9Sstevel@tonic-gate 
12617c478bd9Sstevel@tonic-gate 				case SCF_ERROR_DELETED:
12627c478bd9Sstevel@tonic-gate 					scf_entry_destroy(t_cid);
12637c478bd9Sstevel@tonic-gate 					goto add;
12647c478bd9Sstevel@tonic-gate 
12657c478bd9Sstevel@tonic-gate 				case SCF_ERROR_EXISTS:
12667c478bd9Sstevel@tonic-gate 					goto replace;
12677c478bd9Sstevel@tonic-gate 
12687c478bd9Sstevel@tonic-gate 				case SCF_ERROR_HANDLE_MISMATCH:
12697c478bd9Sstevel@tonic-gate 				case SCF_ERROR_INVALID_ARGUMENT:
12707c478bd9Sstevel@tonic-gate 				case SCF_ERROR_NOT_SET:
12717c478bd9Sstevel@tonic-gate 					bad_fail("scf_transaction_property_new",
12727c478bd9Sstevel@tonic-gate 					    scf_error());
12737c478bd9Sstevel@tonic-gate 				}
12747c478bd9Sstevel@tonic-gate 			}
12757c478bd9Sstevel@tonic-gate 		}
12767c478bd9Sstevel@tonic-gate 
12777c478bd9Sstevel@tonic-gate 		ret = scf_transaction_commit(t);
12787c478bd9Sstevel@tonic-gate 		if (ret == -1) {
12797c478bd9Sstevel@tonic-gate 			switch (scf_error()) {
12807c478bd9Sstevel@tonic-gate 			case SCF_ERROR_CONNECTION_BROKEN:
12817c478bd9Sstevel@tonic-gate 			default:
12827c478bd9Sstevel@tonic-gate 				ret = ECONNABORTED;
12837c478bd9Sstevel@tonic-gate 				goto remove_contract_cleanup;
12847c478bd9Sstevel@tonic-gate 
12857c478bd9Sstevel@tonic-gate 			case SCF_ERROR_DELETED:
12867c478bd9Sstevel@tonic-gate 				goto add;
12877c478bd9Sstevel@tonic-gate 
12887c478bd9Sstevel@tonic-gate 			case SCF_ERROR_PERMISSION_DENIED:
12897c478bd9Sstevel@tonic-gate 				ret = EPERM;
12907c478bd9Sstevel@tonic-gate 				goto remove_contract_cleanup;
12917c478bd9Sstevel@tonic-gate 
12927c478bd9Sstevel@tonic-gate 			case SCF_ERROR_BACKEND_ACCESS:
12937c478bd9Sstevel@tonic-gate 				ret = EACCES;
12947c478bd9Sstevel@tonic-gate 				goto remove_contract_cleanup;
12957c478bd9Sstevel@tonic-gate 
12967c478bd9Sstevel@tonic-gate 			case SCF_ERROR_BACKEND_READONLY:
12977c478bd9Sstevel@tonic-gate 				ret = EROFS;
12987c478bd9Sstevel@tonic-gate 				goto remove_contract_cleanup;
12997c478bd9Sstevel@tonic-gate 
13007c478bd9Sstevel@tonic-gate 			case SCF_ERROR_NOT_SET:
13017c478bd9Sstevel@tonic-gate 				bad_fail("scf_transaction_commit", scf_error());
13027c478bd9Sstevel@tonic-gate 			}
13037c478bd9Sstevel@tonic-gate 		}
13047c478bd9Sstevel@tonic-gate 		if (ret == 1) {
13057c478bd9Sstevel@tonic-gate 			ret = 0;
13067c478bd9Sstevel@tonic-gate 			break;
13077c478bd9Sstevel@tonic-gate 		}
13087c478bd9Sstevel@tonic-gate 
13097c478bd9Sstevel@tonic-gate 		scf_transaction_destroy_children(t);
13107c478bd9Sstevel@tonic-gate 		if (scf_pg_update(pg) == -1) {
13117c478bd9Sstevel@tonic-gate 			switch (scf_error()) {
13127c478bd9Sstevel@tonic-gate 			case SCF_ERROR_CONNECTION_BROKEN:
13137c478bd9Sstevel@tonic-gate 			default:
13147c478bd9Sstevel@tonic-gate 				ret = ECONNABORTED;
13157c478bd9Sstevel@tonic-gate 				goto remove_contract_cleanup;
13167c478bd9Sstevel@tonic-gate 
13177c478bd9Sstevel@tonic-gate 			case SCF_ERROR_DELETED:
13187c478bd9Sstevel@tonic-gate 				goto add;
13197c478bd9Sstevel@tonic-gate 
13207c478bd9Sstevel@tonic-gate 			case SCF_ERROR_NOT_SET:
13217c478bd9Sstevel@tonic-gate 				bad_fail("scf_pg_update", scf_error());
13227c478bd9Sstevel@tonic-gate 			}
13237c478bd9Sstevel@tonic-gate 		}
13247c478bd9Sstevel@tonic-gate 	}
13257c478bd9Sstevel@tonic-gate 
13267c478bd9Sstevel@tonic-gate remove_contract_cleanup:
13277c478bd9Sstevel@tonic-gate 	scf_transaction_destroy_children(t);
13287c478bd9Sstevel@tonic-gate 	scf_transaction_destroy(t);
13297c478bd9Sstevel@tonic-gate 	scf_iter_destroy(iter);
13307c478bd9Sstevel@tonic-gate 	scf_property_destroy(prop);
13317c478bd9Sstevel@tonic-gate 	scf_pg_destroy(pg);
13327c478bd9Sstevel@tonic-gate 
13337c478bd9Sstevel@tonic-gate 	return (ret);
13347c478bd9Sstevel@tonic-gate }
13357c478bd9Sstevel@tonic-gate 
13367c478bd9Sstevel@tonic-gate /*
13377c478bd9Sstevel@tonic-gate  * Fails with
13387c478bd9Sstevel@tonic-gate  *   EINVAL - type is invalid
13397c478bd9Sstevel@tonic-gate  *   ENOMEM
13407c478bd9Sstevel@tonic-gate  *   ECONNABORTED - repository disconnection
13417c478bd9Sstevel@tonic-gate  *   EBADF - s_inst is not set
13427c478bd9Sstevel@tonic-gate  *   ECANCELED - s_inst is deleted
13437c478bd9Sstevel@tonic-gate  *   EPERM
13447c478bd9Sstevel@tonic-gate  *   EACCES
13457c478bd9Sstevel@tonic-gate  *   EROFS
13467c478bd9Sstevel@tonic-gate  */
13477c478bd9Sstevel@tonic-gate int
13487c478bd9Sstevel@tonic-gate restarter_store_contract(scf_instance_t *s_inst, ctid_t contract_id,
13497c478bd9Sstevel@tonic-gate     restarter_contract_type_t type)
13507c478bd9Sstevel@tonic-gate {
13517c478bd9Sstevel@tonic-gate 	scf_handle_t *h;
13527c478bd9Sstevel@tonic-gate 	scf_transaction_t *t = NULL;
13537c478bd9Sstevel@tonic-gate 	scf_transaction_entry_t *t_cid = NULL;
13547c478bd9Sstevel@tonic-gate 	scf_value_t *val;
13557c478bd9Sstevel@tonic-gate 	scf_propertygroup_t *pg = NULL;
13567c478bd9Sstevel@tonic-gate 	scf_property_t *prop = NULL;
13577c478bd9Sstevel@tonic-gate 	scf_iter_t *iter = NULL;
13587c478bd9Sstevel@tonic-gate 	const char *pname;
13597c478bd9Sstevel@tonic-gate 	int ret = 0, primary;
13607c478bd9Sstevel@tonic-gate 
13617c478bd9Sstevel@tonic-gate 	if (type == RESTARTER_CONTRACT_PRIMARY)
13627c478bd9Sstevel@tonic-gate 		primary = 1;
13637c478bd9Sstevel@tonic-gate 	else if (type == RESTARTER_CONTRACT_TRANSIENT)
13647c478bd9Sstevel@tonic-gate 		primary = 0;
13657c478bd9Sstevel@tonic-gate 	else
13667c478bd9Sstevel@tonic-gate 		return (EINVAL);
13677c478bd9Sstevel@tonic-gate 
13687c478bd9Sstevel@tonic-gate 	h = scf_instance_handle(s_inst);
13697c478bd9Sstevel@tonic-gate 
13707c478bd9Sstevel@tonic-gate 	pg = scf_pg_create(h);
13717c478bd9Sstevel@tonic-gate 	prop = scf_property_create(h);
13727c478bd9Sstevel@tonic-gate 	iter = scf_iter_create(h);
13737c478bd9Sstevel@tonic-gate 	t = scf_transaction_create(h);
13747c478bd9Sstevel@tonic-gate 
13757c478bd9Sstevel@tonic-gate 	if (pg == NULL || prop == NULL || iter == NULL || t == NULL) {
13767c478bd9Sstevel@tonic-gate 		ret = ENOMEM;
13777c478bd9Sstevel@tonic-gate 		goto out;
13787c478bd9Sstevel@tonic-gate 	}
13797c478bd9Sstevel@tonic-gate 
13807c478bd9Sstevel@tonic-gate add:
13817c478bd9Sstevel@tonic-gate 	scf_transaction_destroy_children(t);
13827c478bd9Sstevel@tonic-gate 	ret = instance_get_or_add_pg(s_inst, SCF_PG_RESTARTER,
13837c478bd9Sstevel@tonic-gate 	    SCF_PG_RESTARTER_TYPE, SCF_PG_RESTARTER_FLAGS, pg);
13847c478bd9Sstevel@tonic-gate 	if (ret != 0)
13857c478bd9Sstevel@tonic-gate 		goto out;
13867c478bd9Sstevel@tonic-gate 
13877c478bd9Sstevel@tonic-gate 	pname = primary ? SCF_PROPERTY_CONTRACT :
13887c478bd9Sstevel@tonic-gate 	    SCF_PROPERTY_TRANSIENT_CONTRACT;
13897c478bd9Sstevel@tonic-gate 
13907c478bd9Sstevel@tonic-gate 	for (;;) {
13917c478bd9Sstevel@tonic-gate 		if (scf_transaction_start(t, pg) != 0) {
13927c478bd9Sstevel@tonic-gate 			switch (scf_error()) {
13937c478bd9Sstevel@tonic-gate 			case SCF_ERROR_CONNECTION_BROKEN:
13947c478bd9Sstevel@tonic-gate 			default:
13957c478bd9Sstevel@tonic-gate 				ret = ECONNABORTED;
13967c478bd9Sstevel@tonic-gate 				goto out;
13977c478bd9Sstevel@tonic-gate 
13987c478bd9Sstevel@tonic-gate 			case SCF_ERROR_DELETED:
13997c478bd9Sstevel@tonic-gate 				goto add;
14007c478bd9Sstevel@tonic-gate 
14017c478bd9Sstevel@tonic-gate 			case SCF_ERROR_PERMISSION_DENIED:
14027c478bd9Sstevel@tonic-gate 				ret = EPERM;
14037c478bd9Sstevel@tonic-gate 				goto out;
14047c478bd9Sstevel@tonic-gate 
14057c478bd9Sstevel@tonic-gate 			case SCF_ERROR_BACKEND_ACCESS:
14067c478bd9Sstevel@tonic-gate 				ret = EACCES;
14077c478bd9Sstevel@tonic-gate 				goto out;
14087c478bd9Sstevel@tonic-gate 
14097c478bd9Sstevel@tonic-gate 			case SCF_ERROR_BACKEND_READONLY:
14107c478bd9Sstevel@tonic-gate 				ret = EROFS;
14117c478bd9Sstevel@tonic-gate 				goto out;
14127c478bd9Sstevel@tonic-gate 
14137c478bd9Sstevel@tonic-gate 			case SCF_ERROR_HANDLE_MISMATCH:
14147c478bd9Sstevel@tonic-gate 			case SCF_ERROR_IN_USE:
14157c478bd9Sstevel@tonic-gate 			case SCF_ERROR_NOT_SET:
14167c478bd9Sstevel@tonic-gate 				bad_fail("scf_transaction_start", scf_error());
14177c478bd9Sstevel@tonic-gate 			}
14187c478bd9Sstevel@tonic-gate 		}
14197c478bd9Sstevel@tonic-gate 
14207c478bd9Sstevel@tonic-gate 		t_cid = scf_entry_create(h);
14217c478bd9Sstevel@tonic-gate 		if (t_cid == NULL) {
14227c478bd9Sstevel@tonic-gate 			ret = ENOMEM;
14237c478bd9Sstevel@tonic-gate 			goto out;
14247c478bd9Sstevel@tonic-gate 		}
14257c478bd9Sstevel@tonic-gate 
14267c478bd9Sstevel@tonic-gate 		if (scf_pg_get_property(pg, pname, prop) == 0) {
14277c478bd9Sstevel@tonic-gate replace:
14287c478bd9Sstevel@tonic-gate 			if (scf_transaction_property_change_type(t, t_cid,
14297c478bd9Sstevel@tonic-gate 			    pname, SCF_TYPE_COUNT) != 0) {
14307c478bd9Sstevel@tonic-gate 				switch (scf_error()) {
14317c478bd9Sstevel@tonic-gate 				case SCF_ERROR_CONNECTION_BROKEN:
14327c478bd9Sstevel@tonic-gate 				default:
14337c478bd9Sstevel@tonic-gate 					ret = ECONNABORTED;
14347c478bd9Sstevel@tonic-gate 					goto out;
14357c478bd9Sstevel@tonic-gate 
14367c478bd9Sstevel@tonic-gate 				case SCF_ERROR_DELETED:
14377c478bd9Sstevel@tonic-gate 					scf_entry_destroy(t_cid);
14387c478bd9Sstevel@tonic-gate 					goto add;
14397c478bd9Sstevel@tonic-gate 
14407c478bd9Sstevel@tonic-gate 				case SCF_ERROR_NOT_FOUND:
14417c478bd9Sstevel@tonic-gate 					goto new;
14427c478bd9Sstevel@tonic-gate 
14437c478bd9Sstevel@tonic-gate 				case SCF_ERROR_HANDLE_MISMATCH:
14447c478bd9Sstevel@tonic-gate 				case SCF_ERROR_INVALID_ARGUMENT:
14457c478bd9Sstevel@tonic-gate 				case SCF_ERROR_IN_USE:
14467c478bd9Sstevel@tonic-gate 				case SCF_ERROR_NOT_SET:
14477c478bd9Sstevel@tonic-gate 					bad_fail(
14487c478bd9Sstevel@tonic-gate 					"scf_transaction_propert_change_type",
14497c478bd9Sstevel@tonic-gate 					    scf_error());
14507c478bd9Sstevel@tonic-gate 				}
14517c478bd9Sstevel@tonic-gate 			}
14527c478bd9Sstevel@tonic-gate 
14537c478bd9Sstevel@tonic-gate 			if (scf_property_is_type(prop, SCF_TYPE_COUNT) == 0) {
14547c478bd9Sstevel@tonic-gate 				if (scf_iter_property_values(iter, prop) != 0) {
14557c478bd9Sstevel@tonic-gate 					switch (scf_error()) {
14567c478bd9Sstevel@tonic-gate 					case SCF_ERROR_CONNECTION_BROKEN:
14577c478bd9Sstevel@tonic-gate 					default:
14587c478bd9Sstevel@tonic-gate 						ret = ECONNABORTED;
14597c478bd9Sstevel@tonic-gate 						goto out;
14607c478bd9Sstevel@tonic-gate 
14617c478bd9Sstevel@tonic-gate 					case SCF_ERROR_NOT_SET:
14627c478bd9Sstevel@tonic-gate 					case SCF_ERROR_HANDLE_MISMATCH:
14637c478bd9Sstevel@tonic-gate 						bad_fail(
14647c478bd9Sstevel@tonic-gate 						    "scf_iter_property_values",
14657c478bd9Sstevel@tonic-gate 						    scf_error());
14667c478bd9Sstevel@tonic-gate 					}
14677c478bd9Sstevel@tonic-gate 				}
14687c478bd9Sstevel@tonic-gate 
14697c478bd9Sstevel@tonic-gate next_val:
14707c478bd9Sstevel@tonic-gate 				val = scf_value_create(h);
14717c478bd9Sstevel@tonic-gate 				if (val == NULL) {
14727c478bd9Sstevel@tonic-gate 					assert(scf_error() ==
14737c478bd9Sstevel@tonic-gate 					    SCF_ERROR_NO_MEMORY);
14747c478bd9Sstevel@tonic-gate 					ret = ENOMEM;
14757c478bd9Sstevel@tonic-gate 					goto out;
14767c478bd9Sstevel@tonic-gate 				}
14777c478bd9Sstevel@tonic-gate 
14787c478bd9Sstevel@tonic-gate 				ret = scf_iter_next_value(iter, val);
14797c478bd9Sstevel@tonic-gate 				if (ret == -1) {
14807c478bd9Sstevel@tonic-gate 					switch (scf_error()) {
14817c478bd9Sstevel@tonic-gate 					case SCF_ERROR_CONNECTION_BROKEN:
14827c478bd9Sstevel@tonic-gate 					default:
14837c478bd9Sstevel@tonic-gate 						ret = ECONNABORTED;
14847c478bd9Sstevel@tonic-gate 						goto out;
14857c478bd9Sstevel@tonic-gate 
14867c478bd9Sstevel@tonic-gate 					case SCF_ERROR_DELETED:
14877c478bd9Sstevel@tonic-gate 						scf_value_destroy(val);
14887c478bd9Sstevel@tonic-gate 						goto add;
14897c478bd9Sstevel@tonic-gate 
14907c478bd9Sstevel@tonic-gate 					case SCF_ERROR_HANDLE_MISMATCH:
14917c478bd9Sstevel@tonic-gate 					case SCF_ERROR_INVALID_ARGUMENT:
14923eae19d9Swesolows 					case SCF_ERROR_PERMISSION_DENIED:
14937c478bd9Sstevel@tonic-gate 						bad_fail(
14947c478bd9Sstevel@tonic-gate 						    "scf_iter_next_value",
14957c478bd9Sstevel@tonic-gate 						    scf_error());
14967c478bd9Sstevel@tonic-gate 					}
14977c478bd9Sstevel@tonic-gate 				}
14987c478bd9Sstevel@tonic-gate 
14997c478bd9Sstevel@tonic-gate 				if (ret == 1) {
15007c478bd9Sstevel@tonic-gate 					ret = scf_entry_add_value(t_cid, val);
15017c478bd9Sstevel@tonic-gate 					assert(ret == 0);
15027c478bd9Sstevel@tonic-gate 
15037c478bd9Sstevel@tonic-gate 					goto next_val;
15047c478bd9Sstevel@tonic-gate 				}
15057c478bd9Sstevel@tonic-gate 
15067c478bd9Sstevel@tonic-gate 				scf_value_destroy(val);
15077c478bd9Sstevel@tonic-gate 			} else {
15087c478bd9Sstevel@tonic-gate 				switch (scf_error()) {
15097c478bd9Sstevel@tonic-gate 				case SCF_ERROR_CONNECTION_BROKEN:
15107c478bd9Sstevel@tonic-gate 				default:
15117c478bd9Sstevel@tonic-gate 					ret = ECONNABORTED;
15127c478bd9Sstevel@tonic-gate 					goto out;
15137c478bd9Sstevel@tonic-gate 
15147c478bd9Sstevel@tonic-gate 				case SCF_ERROR_TYPE_MISMATCH:
15157c478bd9Sstevel@tonic-gate 					break;
15167c478bd9Sstevel@tonic-gate 
15177c478bd9Sstevel@tonic-gate 				case SCF_ERROR_INVALID_ARGUMENT:
15187c478bd9Sstevel@tonic-gate 				case SCF_ERROR_NOT_SET:
15197c478bd9Sstevel@tonic-gate 					bad_fail("scf_property_is_type",
15207c478bd9Sstevel@tonic-gate 					    scf_error());
15217c478bd9Sstevel@tonic-gate 				}
15227c478bd9Sstevel@tonic-gate 			}
15237c478bd9Sstevel@tonic-gate 		} else {
15247c478bd9Sstevel@tonic-gate 			switch (scf_error()) {
15257c478bd9Sstevel@tonic-gate 			case SCF_ERROR_CONNECTION_BROKEN:
15267c478bd9Sstevel@tonic-gate 			default:
15277c478bd9Sstevel@tonic-gate 				ret = ECONNABORTED;
15287c478bd9Sstevel@tonic-gate 				goto out;
15297c478bd9Sstevel@tonic-gate 
15307c478bd9Sstevel@tonic-gate 			case SCF_ERROR_DELETED:
15317c478bd9Sstevel@tonic-gate 				scf_entry_destroy(t_cid);
15327c478bd9Sstevel@tonic-gate 				goto add;
15337c478bd9Sstevel@tonic-gate 
15347c478bd9Sstevel@tonic-gate 			case SCF_ERROR_NOT_FOUND:
15357c478bd9Sstevel@tonic-gate 				break;
15367c478bd9Sstevel@tonic-gate 
15377c478bd9Sstevel@tonic-gate 			case SCF_ERROR_HANDLE_MISMATCH:
15387c478bd9Sstevel@tonic-gate 			case SCF_ERROR_INVALID_ARGUMENT:
15397c478bd9Sstevel@tonic-gate 			case SCF_ERROR_NOT_SET:
15407c478bd9Sstevel@tonic-gate 				bad_fail("scf_pg_get_property", scf_error());
15417c478bd9Sstevel@tonic-gate 			}
15427c478bd9Sstevel@tonic-gate 
15437c478bd9Sstevel@tonic-gate new:
15447c478bd9Sstevel@tonic-gate 			if (scf_transaction_property_new(t, t_cid, pname,
15457c478bd9Sstevel@tonic-gate 			    SCF_TYPE_COUNT) != 0) {
15467c478bd9Sstevel@tonic-gate 				switch (scf_error()) {
15477c478bd9Sstevel@tonic-gate 				case SCF_ERROR_CONNECTION_BROKEN:
15487c478bd9Sstevel@tonic-gate 				default:
15497c478bd9Sstevel@tonic-gate 					ret = ECONNABORTED;
15507c478bd9Sstevel@tonic-gate 					goto out;
15517c478bd9Sstevel@tonic-gate 
15527c478bd9Sstevel@tonic-gate 				case SCF_ERROR_DELETED:
15537c478bd9Sstevel@tonic-gate 					scf_entry_destroy(t_cid);
15547c478bd9Sstevel@tonic-gate 					goto add;
15557c478bd9Sstevel@tonic-gate 
15567c478bd9Sstevel@tonic-gate 				case SCF_ERROR_EXISTS:
15577c478bd9Sstevel@tonic-gate 					goto replace;
15587c478bd9Sstevel@tonic-gate 
15597c478bd9Sstevel@tonic-gate 				case SCF_ERROR_HANDLE_MISMATCH:
15607c478bd9Sstevel@tonic-gate 				case SCF_ERROR_INVALID_ARGUMENT:
15617c478bd9Sstevel@tonic-gate 				case SCF_ERROR_NOT_SET:
15627c478bd9Sstevel@tonic-gate 					bad_fail("scf_transaction_property_new",
15637c478bd9Sstevel@tonic-gate 					    scf_error());
15647c478bd9Sstevel@tonic-gate 				}
15657c478bd9Sstevel@tonic-gate 			}
15667c478bd9Sstevel@tonic-gate 		}
15677c478bd9Sstevel@tonic-gate 
15687c478bd9Sstevel@tonic-gate 		val = scf_value_create(h);
15697c478bd9Sstevel@tonic-gate 		if (val == NULL) {
15707c478bd9Sstevel@tonic-gate 			assert(scf_error() == SCF_ERROR_NO_MEMORY);
15717c478bd9Sstevel@tonic-gate 			ret = ENOMEM;
15727c478bd9Sstevel@tonic-gate 			goto out;
15737c478bd9Sstevel@tonic-gate 		}
15747c478bd9Sstevel@tonic-gate 
15757c478bd9Sstevel@tonic-gate 		scf_value_set_count(val, contract_id);
15767c478bd9Sstevel@tonic-gate 		ret = scf_entry_add_value(t_cid, val);
15777c478bd9Sstevel@tonic-gate 		assert(ret == 0);
15787c478bd9Sstevel@tonic-gate 
15797c478bd9Sstevel@tonic-gate 		ret = scf_transaction_commit(t);
15807c478bd9Sstevel@tonic-gate 		if (ret == -1) {
15817c478bd9Sstevel@tonic-gate 			switch (scf_error()) {
15827c478bd9Sstevel@tonic-gate 			case SCF_ERROR_CONNECTION_BROKEN:
15837c478bd9Sstevel@tonic-gate 			default:
15847c478bd9Sstevel@tonic-gate 				ret = ECONNABORTED;
15857c478bd9Sstevel@tonic-gate 				goto out;
15867c478bd9Sstevel@tonic-gate 
15877c478bd9Sstevel@tonic-gate 			case SCF_ERROR_DELETED:
15887c478bd9Sstevel@tonic-gate 				goto add;
15897c478bd9Sstevel@tonic-gate 
15907c478bd9Sstevel@tonic-gate 			case SCF_ERROR_PERMISSION_DENIED:
15917c478bd9Sstevel@tonic-gate 				ret = EPERM;
15927c478bd9Sstevel@tonic-gate 				goto out;
15937c478bd9Sstevel@tonic-gate 
15947c478bd9Sstevel@tonic-gate 			case SCF_ERROR_BACKEND_ACCESS:
15957c478bd9Sstevel@tonic-gate 				ret = EACCES;
15967c478bd9Sstevel@tonic-gate 				goto out;
15977c478bd9Sstevel@tonic-gate 
15987c478bd9Sstevel@tonic-gate 			case SCF_ERROR_BACKEND_READONLY:
15997c478bd9Sstevel@tonic-gate 				ret = EROFS;
16007c478bd9Sstevel@tonic-gate 				goto out;
16017c478bd9Sstevel@tonic-gate 
16027c478bd9Sstevel@tonic-gate 			case SCF_ERROR_NOT_SET:
16037c478bd9Sstevel@tonic-gate 				bad_fail("scf_transaction_commit", scf_error());
16047c478bd9Sstevel@tonic-gate 			}
16057c478bd9Sstevel@tonic-gate 		}
16067c478bd9Sstevel@tonic-gate 		if (ret == 1) {
16077c478bd9Sstevel@tonic-gate 			ret = 0;
16087c478bd9Sstevel@tonic-gate 			break;
16097c478bd9Sstevel@tonic-gate 		}
16107c478bd9Sstevel@tonic-gate 
16117c478bd9Sstevel@tonic-gate 		scf_transaction_destroy_children(t);
16127c478bd9Sstevel@tonic-gate 		if (scf_pg_update(pg) == -1) {
16137c478bd9Sstevel@tonic-gate 			switch (scf_error()) {
16147c478bd9Sstevel@tonic-gate 			case SCF_ERROR_CONNECTION_BROKEN:
16157c478bd9Sstevel@tonic-gate 			default:
16167c478bd9Sstevel@tonic-gate 				ret = ECONNABORTED;
16177c478bd9Sstevel@tonic-gate 				goto out;
16187c478bd9Sstevel@tonic-gate 
16197c478bd9Sstevel@tonic-gate 			case SCF_ERROR_DELETED:
16207c478bd9Sstevel@tonic-gate 				goto add;
16217c478bd9Sstevel@tonic-gate 
16227c478bd9Sstevel@tonic-gate 			case SCF_ERROR_NOT_SET:
16237c478bd9Sstevel@tonic-gate 				bad_fail("scf_pg_update", scf_error());
16247c478bd9Sstevel@tonic-gate 			}
16257c478bd9Sstevel@tonic-gate 		}
16267c478bd9Sstevel@tonic-gate 	}
16277c478bd9Sstevel@tonic-gate 
16287c478bd9Sstevel@tonic-gate out:
16297c478bd9Sstevel@tonic-gate 	scf_transaction_destroy_children(t);
16307c478bd9Sstevel@tonic-gate 	scf_transaction_destroy(t);
16317c478bd9Sstevel@tonic-gate 	scf_iter_destroy(iter);
16327c478bd9Sstevel@tonic-gate 	scf_property_destroy(prop);
16337c478bd9Sstevel@tonic-gate 	scf_pg_destroy(pg);
16347c478bd9Sstevel@tonic-gate 
16357c478bd9Sstevel@tonic-gate 	return (ret);
16367c478bd9Sstevel@tonic-gate }
16377c478bd9Sstevel@tonic-gate 
16387c478bd9Sstevel@tonic-gate int
16397c478bd9Sstevel@tonic-gate restarter_rm_libs_loadable()
16407c478bd9Sstevel@tonic-gate {
16417c478bd9Sstevel@tonic-gate 	void *libhndl;
16427c478bd9Sstevel@tonic-gate 
16437c478bd9Sstevel@tonic-gate 	if (method_context_safety)
16447c478bd9Sstevel@tonic-gate 		return (1);
16457c478bd9Sstevel@tonic-gate 
16467c478bd9Sstevel@tonic-gate 	if ((libhndl = dlopen("libpool.so", RTLD_LAZY | RTLD_LOCAL)) == NULL)
16477c478bd9Sstevel@tonic-gate 		return (0);
16487c478bd9Sstevel@tonic-gate 
16497c478bd9Sstevel@tonic-gate 	(void) dlclose(libhndl);
16507c478bd9Sstevel@tonic-gate 
16517c478bd9Sstevel@tonic-gate 	if ((libhndl = dlopen("libproject.so", RTLD_LAZY | RTLD_LOCAL)) == NULL)
16527c478bd9Sstevel@tonic-gate 		return (0);
16537c478bd9Sstevel@tonic-gate 
16547c478bd9Sstevel@tonic-gate 	(void) dlclose(libhndl);
16557c478bd9Sstevel@tonic-gate 
16567c478bd9Sstevel@tonic-gate 	method_context_safety = 1;
16577c478bd9Sstevel@tonic-gate 
16587c478bd9Sstevel@tonic-gate 	return (1);
16597c478bd9Sstevel@tonic-gate }
16607c478bd9Sstevel@tonic-gate 
16617c478bd9Sstevel@tonic-gate static int
16627c478bd9Sstevel@tonic-gate get_astring_val(scf_propertygroup_t *pg, const char *name, char *buf,
16637c478bd9Sstevel@tonic-gate     size_t bufsz, scf_property_t *prop, scf_value_t *val)
16647c478bd9Sstevel@tonic-gate {
16657c478bd9Sstevel@tonic-gate 	ssize_t szret;
16667c478bd9Sstevel@tonic-gate 
166713d8aaa1SSean Wilcox 	if (pg == NULL)
166813d8aaa1SSean Wilcox 		return (-1);
166913d8aaa1SSean Wilcox 
16707c478bd9Sstevel@tonic-gate 	if (scf_pg_get_property(pg, name, prop) != SCF_SUCCESS) {
16717c478bd9Sstevel@tonic-gate 		if (scf_error() == SCF_ERROR_CONNECTION_BROKEN)
16727c478bd9Sstevel@tonic-gate 			uu_die(rcbroken);
16737c478bd9Sstevel@tonic-gate 		return (-1);
16747c478bd9Sstevel@tonic-gate 	}
16757c478bd9Sstevel@tonic-gate 
16767c478bd9Sstevel@tonic-gate 	if (scf_property_get_value(prop, val) != SCF_SUCCESS) {
16777c478bd9Sstevel@tonic-gate 		if (scf_error() == SCF_ERROR_CONNECTION_BROKEN)
16787c478bd9Sstevel@tonic-gate 			uu_die(rcbroken);
16797c478bd9Sstevel@tonic-gate 		return (-1);
16807c478bd9Sstevel@tonic-gate 	}
16817c478bd9Sstevel@tonic-gate 
16827c478bd9Sstevel@tonic-gate 	szret = scf_value_get_astring(val, buf, bufsz);
16837c478bd9Sstevel@tonic-gate 
16847c478bd9Sstevel@tonic-gate 	return (szret >= 0 ? 0 : -1);
16857c478bd9Sstevel@tonic-gate }
16867c478bd9Sstevel@tonic-gate 
1687eb1a3463STruong Nguyen static int
1688eb1a3463STruong Nguyen get_boolean_val(scf_propertygroup_t *pg, const char *name, uint8_t *b,
1689eb1a3463STruong Nguyen     scf_property_t *prop, scf_value_t *val)
1690eb1a3463STruong Nguyen {
1691eb1a3463STruong Nguyen 	if (scf_pg_get_property(pg, name, prop) != SCF_SUCCESS) {
1692eb1a3463STruong Nguyen 		if (scf_error() == SCF_ERROR_CONNECTION_BROKEN)
1693eb1a3463STruong Nguyen 			uu_die(rcbroken);
1694eb1a3463STruong Nguyen 		return (-1);
1695eb1a3463STruong Nguyen 	}
1696eb1a3463STruong Nguyen 
1697eb1a3463STruong Nguyen 	if (scf_property_get_value(prop, val) != SCF_SUCCESS) {
1698eb1a3463STruong Nguyen 		if (scf_error() == SCF_ERROR_CONNECTION_BROKEN)
1699eb1a3463STruong Nguyen 			uu_die(rcbroken);
1700eb1a3463STruong Nguyen 		return (-1);
1701eb1a3463STruong Nguyen 	}
1702eb1a3463STruong Nguyen 
1703eb1a3463STruong Nguyen 	if (scf_value_get_boolean(val, b))
1704eb1a3463STruong Nguyen 		return (-1);
1705eb1a3463STruong Nguyen 
1706eb1a3463STruong Nguyen 	return (0);
1707eb1a3463STruong Nguyen }
1708eb1a3463STruong Nguyen 
17097c478bd9Sstevel@tonic-gate /*
17107c478bd9Sstevel@tonic-gate  * Try to load mcp->pwd, if it isn't already.
17117c478bd9Sstevel@tonic-gate  * Fails with
17127c478bd9Sstevel@tonic-gate  *   ENOMEM - malloc() failed
17137c478bd9Sstevel@tonic-gate  *   ENOENT - no entry found
17147c478bd9Sstevel@tonic-gate  *   EIO - I/O error
17157c478bd9Sstevel@tonic-gate  *   EMFILE - process out of file descriptors
17167c478bd9Sstevel@tonic-gate  *   ENFILE - system out of file handles
17177c478bd9Sstevel@tonic-gate  */
17187c478bd9Sstevel@tonic-gate static int
17197c478bd9Sstevel@tonic-gate lookup_pwd(struct method_context *mcp)
17207c478bd9Sstevel@tonic-gate {
17217c478bd9Sstevel@tonic-gate 	struct passwd *pwdp;
17227c478bd9Sstevel@tonic-gate 
17237c478bd9Sstevel@tonic-gate 	if (mcp->pwbuf != NULL && mcp->pwd.pw_uid == mcp->uid)
17247c478bd9Sstevel@tonic-gate 		return (0);
17257c478bd9Sstevel@tonic-gate 
17267c478bd9Sstevel@tonic-gate 	if (mcp->pwbuf == NULL) {
17277c478bd9Sstevel@tonic-gate 		mcp->pwbufsz = sysconf(_SC_GETPW_R_SIZE_MAX);
17287c478bd9Sstevel@tonic-gate 		assert(mcp->pwbufsz >= 0);
17297c478bd9Sstevel@tonic-gate 		mcp->pwbuf = malloc(mcp->pwbufsz);
17307c478bd9Sstevel@tonic-gate 		if (mcp->pwbuf == NULL)
17317c478bd9Sstevel@tonic-gate 			return (ENOMEM);
17327c478bd9Sstevel@tonic-gate 	}
17337c478bd9Sstevel@tonic-gate 
17347c478bd9Sstevel@tonic-gate 	do {
17357c478bd9Sstevel@tonic-gate 		errno = 0;
17367c478bd9Sstevel@tonic-gate 		pwdp = getpwuid_r(mcp->uid, &mcp->pwd, mcp->pwbuf,
17377c478bd9Sstevel@tonic-gate 		    mcp->pwbufsz);
17387c478bd9Sstevel@tonic-gate 	} while (pwdp == NULL && errno == EINTR);
17397c478bd9Sstevel@tonic-gate 	if (pwdp != NULL)
17407c478bd9Sstevel@tonic-gate 		return (0);
17417c478bd9Sstevel@tonic-gate 
17427c478bd9Sstevel@tonic-gate 	free(mcp->pwbuf);
17437c478bd9Sstevel@tonic-gate 	mcp->pwbuf = NULL;
17447c478bd9Sstevel@tonic-gate 
17457c478bd9Sstevel@tonic-gate 	switch (errno) {
17467c478bd9Sstevel@tonic-gate 	case 0:
17477c478bd9Sstevel@tonic-gate 	default:
17487c478bd9Sstevel@tonic-gate 		/*
17497c478bd9Sstevel@tonic-gate 		 * Until bug 5065780 is fixed, getpwuid_r() can fail with
17507c478bd9Sstevel@tonic-gate 		 * ENOENT, particularly on the miniroot.  Since the
17517c478bd9Sstevel@tonic-gate 		 * documentation is inaccurate, we'll return ENOENT for unknown
17527c478bd9Sstevel@tonic-gate 		 * errors.
17537c478bd9Sstevel@tonic-gate 		 */
17547c478bd9Sstevel@tonic-gate 		return (ENOENT);
17557c478bd9Sstevel@tonic-gate 
17567c478bd9Sstevel@tonic-gate 	case EIO:
17577c478bd9Sstevel@tonic-gate 	case EMFILE:
17587c478bd9Sstevel@tonic-gate 	case ENFILE:
17597c478bd9Sstevel@tonic-gate 		return (errno);
17607c478bd9Sstevel@tonic-gate 
17617c478bd9Sstevel@tonic-gate 	case ERANGE:
17627c478bd9Sstevel@tonic-gate 		bad_fail("getpwuid_r", errno);
17637c478bd9Sstevel@tonic-gate 		/* NOTREACHED */
17647c478bd9Sstevel@tonic-gate 	}
17657c478bd9Sstevel@tonic-gate }
17667c478bd9Sstevel@tonic-gate 
17677c478bd9Sstevel@tonic-gate /*
17687c478bd9Sstevel@tonic-gate  * Get the user id for str.  Returns 0 on success or
17697c478bd9Sstevel@tonic-gate  *   ERANGE	the uid is too big
17707c478bd9Sstevel@tonic-gate  *   EINVAL	the string starts with a digit, but is not a valid uid
17717c478bd9Sstevel@tonic-gate  *   ENOMEM	out of memory
17727c478bd9Sstevel@tonic-gate  *   ENOENT	no passwd entry for str
17737c478bd9Sstevel@tonic-gate  *   EIO	an I/O error has occurred
17747c478bd9Sstevel@tonic-gate  *   EMFILE/ENFILE  out of file descriptors
17757c478bd9Sstevel@tonic-gate  */
17767c478bd9Sstevel@tonic-gate int
17777c478bd9Sstevel@tonic-gate get_uid(const char *str, struct method_context *ci, uid_t *uidp)
17787c478bd9Sstevel@tonic-gate {
17797c478bd9Sstevel@tonic-gate 	if (isdigit(str[0])) {
17807c478bd9Sstevel@tonic-gate 		uid_t uid;
17817c478bd9Sstevel@tonic-gate 		char *cp;
17827c478bd9Sstevel@tonic-gate 
17837c478bd9Sstevel@tonic-gate 		errno = 0;
17847c478bd9Sstevel@tonic-gate 		uid = strtol(str, &cp, 10);
17857c478bd9Sstevel@tonic-gate 
17867c478bd9Sstevel@tonic-gate 		if (uid == 0 && errno != 0) {
17877c478bd9Sstevel@tonic-gate 			assert(errno != EINVAL);
17887c478bd9Sstevel@tonic-gate 			return (errno);
17897c478bd9Sstevel@tonic-gate 		}
17907c478bd9Sstevel@tonic-gate 
17917c478bd9Sstevel@tonic-gate 		for (; *cp != '\0'; ++cp)
17927c478bd9Sstevel@tonic-gate 			if (*cp != ' ' || *cp != '\t')
17937c478bd9Sstevel@tonic-gate 				return (EINVAL);
17947c478bd9Sstevel@tonic-gate 
17957c478bd9Sstevel@tonic-gate 		if (uid > UID_MAX)
17967c478bd9Sstevel@tonic-gate 			return (EINVAL);
17977c478bd9Sstevel@tonic-gate 
17987c478bd9Sstevel@tonic-gate 		*uidp = uid;
17997c478bd9Sstevel@tonic-gate 		return (0);
18007c478bd9Sstevel@tonic-gate 	} else {
18017c478bd9Sstevel@tonic-gate 		struct passwd *pwdp;
18027c478bd9Sstevel@tonic-gate 
18037c478bd9Sstevel@tonic-gate 		if (ci->pwbuf == NULL) {
18047c478bd9Sstevel@tonic-gate 			ci->pwbufsz = sysconf(_SC_GETPW_R_SIZE_MAX);
18057c478bd9Sstevel@tonic-gate 			ci->pwbuf = malloc(ci->pwbufsz);
18067c478bd9Sstevel@tonic-gate 			if (ci->pwbuf == NULL)
18077c478bd9Sstevel@tonic-gate 				return (ENOMEM);
18087c478bd9Sstevel@tonic-gate 		}
18097c478bd9Sstevel@tonic-gate 
18107c478bd9Sstevel@tonic-gate 		do {
18117c478bd9Sstevel@tonic-gate 			errno = 0;
18127c478bd9Sstevel@tonic-gate 			pwdp =
18137c478bd9Sstevel@tonic-gate 			    getpwnam_r(str, &ci->pwd, ci->pwbuf, ci->pwbufsz);
18147c478bd9Sstevel@tonic-gate 		} while (pwdp == NULL && errno == EINTR);
18157c478bd9Sstevel@tonic-gate 
18167c478bd9Sstevel@tonic-gate 		if (pwdp != NULL) {
18177c478bd9Sstevel@tonic-gate 			*uidp = ci->pwd.pw_uid;
18187c478bd9Sstevel@tonic-gate 			return (0);
18197c478bd9Sstevel@tonic-gate 		} else {
18207c478bd9Sstevel@tonic-gate 			free(ci->pwbuf);
18217c478bd9Sstevel@tonic-gate 			ci->pwbuf = NULL;
18227c478bd9Sstevel@tonic-gate 			switch (errno) {
18237c478bd9Sstevel@tonic-gate 			case 0:
18247c478bd9Sstevel@tonic-gate 				return (ENOENT);
18257c478bd9Sstevel@tonic-gate 
18267c478bd9Sstevel@tonic-gate 			case ENOENT:
18277c478bd9Sstevel@tonic-gate 			case EIO:
18287c478bd9Sstevel@tonic-gate 			case EMFILE:
18297c478bd9Sstevel@tonic-gate 			case ENFILE:
18307c478bd9Sstevel@tonic-gate 				return (errno);
18317c478bd9Sstevel@tonic-gate 
18327c478bd9Sstevel@tonic-gate 			case ERANGE:
18337c478bd9Sstevel@tonic-gate 			default:
18347c478bd9Sstevel@tonic-gate 				bad_fail("getpwnam_r", errno);
18357c478bd9Sstevel@tonic-gate 				/* NOTREACHED */
18367c478bd9Sstevel@tonic-gate 			}
18377c478bd9Sstevel@tonic-gate 		}
18387c478bd9Sstevel@tonic-gate 	}
18397c478bd9Sstevel@tonic-gate }
18407c478bd9Sstevel@tonic-gate 
18417c478bd9Sstevel@tonic-gate gid_t
18427c478bd9Sstevel@tonic-gate get_gid(const char *str)
18437c478bd9Sstevel@tonic-gate {
18447c478bd9Sstevel@tonic-gate 	if (isdigit(str[0])) {
18457c478bd9Sstevel@tonic-gate 		gid_t gid;
18467c478bd9Sstevel@tonic-gate 		char *cp;
18477c478bd9Sstevel@tonic-gate 
18487c478bd9Sstevel@tonic-gate 		errno = 0;
18497c478bd9Sstevel@tonic-gate 		gid = strtol(str, &cp, 10);
18507c478bd9Sstevel@tonic-gate 
18517c478bd9Sstevel@tonic-gate 		if (gid == 0 && errno != 0)
1852f48205beScasper 			return ((gid_t)-1);
18537c478bd9Sstevel@tonic-gate 
18547c478bd9Sstevel@tonic-gate 		for (; *cp != '\0'; ++cp)
18557c478bd9Sstevel@tonic-gate 			if (*cp != ' ' || *cp != '\t')
1856f48205beScasper 				return ((gid_t)-1);
18577c478bd9Sstevel@tonic-gate 
18587c478bd9Sstevel@tonic-gate 		return (gid);
18597c478bd9Sstevel@tonic-gate 	} else {
18607c478bd9Sstevel@tonic-gate 		struct group grp, *ret;
18617c478bd9Sstevel@tonic-gate 		char *buffer;
18627c478bd9Sstevel@tonic-gate 		size_t buflen;
18637c478bd9Sstevel@tonic-gate 
18647c478bd9Sstevel@tonic-gate 		buflen = sysconf(_SC_GETGR_R_SIZE_MAX);
18657c478bd9Sstevel@tonic-gate 		buffer = malloc(buflen);
18667c478bd9Sstevel@tonic-gate 		if (buffer == NULL)
18677c478bd9Sstevel@tonic-gate 			uu_die(allocfail);
18687c478bd9Sstevel@tonic-gate 
18697c478bd9Sstevel@tonic-gate 		errno = 0;
18707c478bd9Sstevel@tonic-gate 		ret = getgrnam_r(str, &grp, buffer, buflen);
18717c478bd9Sstevel@tonic-gate 		free(buffer);
18727c478bd9Sstevel@tonic-gate 
1873f48205beScasper 		return (ret == NULL ? (gid_t)-1 : grp.gr_gid);
18747c478bd9Sstevel@tonic-gate 	}
18757c478bd9Sstevel@tonic-gate }
18767c478bd9Sstevel@tonic-gate 
18777c478bd9Sstevel@tonic-gate /*
18787c478bd9Sstevel@tonic-gate  * Fails with
18797c478bd9Sstevel@tonic-gate  *   ENOMEM - out of memory
18807c478bd9Sstevel@tonic-gate  *   ENOENT - no passwd entry
18817c478bd9Sstevel@tonic-gate  *	      no project entry
18827c478bd9Sstevel@tonic-gate  *   EIO - an I/O error occurred
18837c478bd9Sstevel@tonic-gate  *   EMFILE - the process is out of file descriptors
18847c478bd9Sstevel@tonic-gate  *   ENFILE - the system is out of file handles
18857c478bd9Sstevel@tonic-gate  *   ERANGE - the project id is out of range
18867c478bd9Sstevel@tonic-gate  *   EINVAL - str is invalid
18877c478bd9Sstevel@tonic-gate  *   E2BIG - the project entry was too big
18887c478bd9Sstevel@tonic-gate  *   -1 - the name service switch is misconfigured
18897c478bd9Sstevel@tonic-gate  */
18907c478bd9Sstevel@tonic-gate int
18917c478bd9Sstevel@tonic-gate get_projid(const char *str, struct method_context *cip)
18927c478bd9Sstevel@tonic-gate {
18937c478bd9Sstevel@tonic-gate 	int ret;
18947c478bd9Sstevel@tonic-gate 	void *buf;
18957c478bd9Sstevel@tonic-gate 	const size_t bufsz = PROJECT_BUFSZ;
18967c478bd9Sstevel@tonic-gate 	struct project proj, *pp;
18977c478bd9Sstevel@tonic-gate 
18987c478bd9Sstevel@tonic-gate 	if (strcmp(str, ":default") == 0) {
18997c478bd9Sstevel@tonic-gate 		if (cip->uid == 0) {
19007c478bd9Sstevel@tonic-gate 			/* Don't change project for root services */
19017c478bd9Sstevel@tonic-gate 			cip->project = NULL;
19027c478bd9Sstevel@tonic-gate 			return (0);
19037c478bd9Sstevel@tonic-gate 		}
19047c478bd9Sstevel@tonic-gate 
19057c478bd9Sstevel@tonic-gate 		switch (ret = lookup_pwd(cip)) {
19067c478bd9Sstevel@tonic-gate 		case 0:
19077c478bd9Sstevel@tonic-gate 			break;
19087c478bd9Sstevel@tonic-gate 
19097c478bd9Sstevel@tonic-gate 		case ENOMEM:
19107c478bd9Sstevel@tonic-gate 		case ENOENT:
19117c478bd9Sstevel@tonic-gate 		case EIO:
19127c478bd9Sstevel@tonic-gate 		case EMFILE:
19137c478bd9Sstevel@tonic-gate 		case ENFILE:
19147c478bd9Sstevel@tonic-gate 			return (ret);
19157c478bd9Sstevel@tonic-gate 
19167c478bd9Sstevel@tonic-gate 		default:
19177c478bd9Sstevel@tonic-gate 			bad_fail("lookup_pwd", ret);
19187c478bd9Sstevel@tonic-gate 		}
19197c478bd9Sstevel@tonic-gate 
19207c478bd9Sstevel@tonic-gate 		buf = malloc(bufsz);
19217c478bd9Sstevel@tonic-gate 		if (buf == NULL)
19227c478bd9Sstevel@tonic-gate 			return (ENOMEM);
19237c478bd9Sstevel@tonic-gate 
19247c478bd9Sstevel@tonic-gate 		do {
19257c478bd9Sstevel@tonic-gate 			errno = 0;
19267c478bd9Sstevel@tonic-gate 			pp = getdefaultproj(cip->pwd.pw_name, &proj, buf,
19277c478bd9Sstevel@tonic-gate 			    bufsz);
19287c478bd9Sstevel@tonic-gate 		} while (pp == NULL && errno == EINTR);
19297c478bd9Sstevel@tonic-gate 
19307c478bd9Sstevel@tonic-gate 		/* to be continued ... */
19317c478bd9Sstevel@tonic-gate 	} else {
19327c478bd9Sstevel@tonic-gate 		projid_t projid;
19337c478bd9Sstevel@tonic-gate 		char *cp;
19347c478bd9Sstevel@tonic-gate 
19357c478bd9Sstevel@tonic-gate 		if (!isdigit(str[0])) {
19367c478bd9Sstevel@tonic-gate 			cip->project = strdup(str);
19377c478bd9Sstevel@tonic-gate 			return (cip->project != NULL ? 0 : ENOMEM);
19387c478bd9Sstevel@tonic-gate 		}
19397c478bd9Sstevel@tonic-gate 
19407c478bd9Sstevel@tonic-gate 		errno = 0;
19417c478bd9Sstevel@tonic-gate 		projid = strtol(str, &cp, 10);
19427c478bd9Sstevel@tonic-gate 
19437c478bd9Sstevel@tonic-gate 		if (projid == 0 && errno != 0) {
19447c478bd9Sstevel@tonic-gate 			assert(errno == ERANGE);
19457c478bd9Sstevel@tonic-gate 			return (errno);
19467c478bd9Sstevel@tonic-gate 		}
19477c478bd9Sstevel@tonic-gate 
19487c478bd9Sstevel@tonic-gate 		for (; *cp != '\0'; ++cp)
19497c478bd9Sstevel@tonic-gate 			if (*cp != ' ' || *cp != '\t')
19507c478bd9Sstevel@tonic-gate 				return (EINVAL);
19517c478bd9Sstevel@tonic-gate 
19527c478bd9Sstevel@tonic-gate 		if (projid > MAXPROJID)
19537c478bd9Sstevel@tonic-gate 			return (ERANGE);
19547c478bd9Sstevel@tonic-gate 
19557c478bd9Sstevel@tonic-gate 		buf = malloc(bufsz);
19567c478bd9Sstevel@tonic-gate 		if (buf == NULL)
19577c478bd9Sstevel@tonic-gate 			return (ENOMEM);
19587c478bd9Sstevel@tonic-gate 
19597c478bd9Sstevel@tonic-gate 		do {
19607c478bd9Sstevel@tonic-gate 			errno = 0;
19617c478bd9Sstevel@tonic-gate 			pp = getprojbyid(projid, &proj, buf, bufsz);
19627c478bd9Sstevel@tonic-gate 		} while (pp == NULL && errno == EINTR);
19637c478bd9Sstevel@tonic-gate 	}
19647c478bd9Sstevel@tonic-gate 
19657c478bd9Sstevel@tonic-gate 	if (pp) {
19667c478bd9Sstevel@tonic-gate 		cip->project = strdup(pp->pj_name);
19677c478bd9Sstevel@tonic-gate 		free(buf);
19687c478bd9Sstevel@tonic-gate 		return (cip->project != NULL ? 0 : ENOMEM);
19697c478bd9Sstevel@tonic-gate 	}
19707c478bd9Sstevel@tonic-gate 
19717c478bd9Sstevel@tonic-gate 	free(buf);
19727c478bd9Sstevel@tonic-gate 
19737c478bd9Sstevel@tonic-gate 	switch (errno) {
19747c478bd9Sstevel@tonic-gate 	case 0:
19757c478bd9Sstevel@tonic-gate 		return (ENOENT);
19767c478bd9Sstevel@tonic-gate 
19777c478bd9Sstevel@tonic-gate 	case EIO:
19787c478bd9Sstevel@tonic-gate 	case EMFILE:
19797c478bd9Sstevel@tonic-gate 	case ENFILE:
19807c478bd9Sstevel@tonic-gate 		return (errno);
19817c478bd9Sstevel@tonic-gate 
19827c478bd9Sstevel@tonic-gate 	case ERANGE:
19837c478bd9Sstevel@tonic-gate 		return (E2BIG);
19847c478bd9Sstevel@tonic-gate 
19857c478bd9Sstevel@tonic-gate 	default:
19867c478bd9Sstevel@tonic-gate 		return (-1);
19877c478bd9Sstevel@tonic-gate 	}
19887c478bd9Sstevel@tonic-gate }
19897c478bd9Sstevel@tonic-gate 
19907c478bd9Sstevel@tonic-gate /*
19917c478bd9Sstevel@tonic-gate  * Parse the supp_groups property value and populate ci->groups.  Returns
19927c478bd9Sstevel@tonic-gate  * EINVAL (get_gid() failed for one of the components), E2BIG (the property has
19937c478bd9Sstevel@tonic-gate  * more than NGROUPS_MAX-1 groups), or 0 on success.
19947c478bd9Sstevel@tonic-gate  */
19957c478bd9Sstevel@tonic-gate int
19967c478bd9Sstevel@tonic-gate get_groups(char *str, struct method_context *ci)
19977c478bd9Sstevel@tonic-gate {
19987c478bd9Sstevel@tonic-gate 	char *cp, *end, *next;
19997c478bd9Sstevel@tonic-gate 	uint_t i;
20007c478bd9Sstevel@tonic-gate 
20017c478bd9Sstevel@tonic-gate 	const char * const whitespace = " \t";
20027c478bd9Sstevel@tonic-gate 	const char * const illegal = ", \t";
20037c478bd9Sstevel@tonic-gate 
20047c478bd9Sstevel@tonic-gate 	if (str[0] == '\0') {
20057c478bd9Sstevel@tonic-gate 		ci->ngroups = 0;
20067c478bd9Sstevel@tonic-gate 		return (0);
20077c478bd9Sstevel@tonic-gate 	}
20087c478bd9Sstevel@tonic-gate 
20097c478bd9Sstevel@tonic-gate 	for (cp = str, i = 0; *cp != '\0'; ) {
20107c478bd9Sstevel@tonic-gate 		/* skip whitespace */
20117c478bd9Sstevel@tonic-gate 		cp += strspn(cp, whitespace);
20127c478bd9Sstevel@tonic-gate 
20137c478bd9Sstevel@tonic-gate 		/* find the end */
20147c478bd9Sstevel@tonic-gate 		end = cp + strcspn(cp, illegal);
20157c478bd9Sstevel@tonic-gate 
20167c478bd9Sstevel@tonic-gate 		/* skip whitespace after end */
20177c478bd9Sstevel@tonic-gate 		next = end + strspn(end, whitespace);
20187c478bd9Sstevel@tonic-gate 
20197c478bd9Sstevel@tonic-gate 		/* if there's a comma, it separates the fields */
20207c478bd9Sstevel@tonic-gate 		if (*next == ',')
20217c478bd9Sstevel@tonic-gate 			++next;
20227c478bd9Sstevel@tonic-gate 
20237c478bd9Sstevel@tonic-gate 		*end = '\0';
20247c478bd9Sstevel@tonic-gate 
2025f48205beScasper 		if ((ci->groups[i] = get_gid(cp)) == (gid_t)-1) {
20267c478bd9Sstevel@tonic-gate 			ci->ngroups = 0;
20277c478bd9Sstevel@tonic-gate 			return (EINVAL);
20287c478bd9Sstevel@tonic-gate 		}
20297c478bd9Sstevel@tonic-gate 
20307c478bd9Sstevel@tonic-gate 		++i;
20317c478bd9Sstevel@tonic-gate 		if (i > NGROUPS_MAX - 1) {
20327c478bd9Sstevel@tonic-gate 			ci->ngroups = 0;
20337c478bd9Sstevel@tonic-gate 			return (E2BIG);
20347c478bd9Sstevel@tonic-gate 		}
20357c478bd9Sstevel@tonic-gate 
20367c478bd9Sstevel@tonic-gate 		cp = next;
20377c478bd9Sstevel@tonic-gate 	}
20387c478bd9Sstevel@tonic-gate 
20397c478bd9Sstevel@tonic-gate 	ci->ngroups = i;
20407c478bd9Sstevel@tonic-gate 	return (0);
20417c478bd9Sstevel@tonic-gate }
20427c478bd9Sstevel@tonic-gate 
2043*870ad75aSSean Wilcox 
20447c478bd9Sstevel@tonic-gate /*
2045*870ad75aSSean Wilcox  * Return an error message structure containing the error message
2046*870ad75aSSean Wilcox  * with context, and the error so the caller can make a decision
2047*870ad75aSSean Wilcox  * on what to do next.
2048*870ad75aSSean Wilcox  *
2049*870ad75aSSean Wilcox  * Because get_ids uses the mc_error_create() function which can
2050*870ad75aSSean Wilcox  * reallocate the merr, this function must return the merr pointer
2051*870ad75aSSean Wilcox  * in case it was reallocated.
20527c478bd9Sstevel@tonic-gate  */
2053*870ad75aSSean Wilcox static mc_error_t *
205413d8aaa1SSean Wilcox get_profile(scf_propertygroup_t *methpg, scf_propertygroup_t *instpg,
205513d8aaa1SSean Wilcox     scf_property_t *prop, scf_value_t *val, const char *cmdline,
2056*870ad75aSSean Wilcox     struct method_context *ci, mc_error_t *merr)
20577c478bd9Sstevel@tonic-gate {
20587c478bd9Sstevel@tonic-gate 	char *buf = ci->vbuf;
20597c478bd9Sstevel@tonic-gate 	ssize_t buf_sz = ci->vbuf_sz;
20607c478bd9Sstevel@tonic-gate 	char cmd[PATH_MAX];
20617c478bd9Sstevel@tonic-gate 	char *cp, *value;
20627c478bd9Sstevel@tonic-gate 	const char *cmdp;
20637c478bd9Sstevel@tonic-gate 	execattr_t *eap;
2064*870ad75aSSean Wilcox 	mc_error_t *err = merr;
2065*870ad75aSSean Wilcox 	int r;
20667c478bd9Sstevel@tonic-gate 
206713d8aaa1SSean Wilcox 	if (!(get_astring_val(methpg, SCF_PROPERTY_PROFILE, buf, buf_sz, prop,
206813d8aaa1SSean Wilcox 	    val) == 0 || get_astring_val(instpg, SCF_PROPERTY_PROFILE, buf,
206913d8aaa1SSean Wilcox 	    buf_sz, prop, val) == 0))
2070*870ad75aSSean Wilcox 		return (mc_error_create(merr, scf_error(),
2071*870ad75aSSean Wilcox 		    "Method context requires a profile, but the  \"%s\" "
2072*870ad75aSSean Wilcox 		    "property could not be read. scf_error is %s",
2073*870ad75aSSean Wilcox 		    SCF_PROPERTY_PROFILE, scf_strerror(scf_error())));
20747c478bd9Sstevel@tonic-gate 
20757c478bd9Sstevel@tonic-gate 	/* Extract the command from the command line. */
20767c478bd9Sstevel@tonic-gate 	cp = strpbrk(cmdline, " \t");
20777c478bd9Sstevel@tonic-gate 
20787c478bd9Sstevel@tonic-gate 	if (cp == NULL) {
20797c478bd9Sstevel@tonic-gate 		cmdp = cmdline;
20807c478bd9Sstevel@tonic-gate 	} else {
20817c478bd9Sstevel@tonic-gate 		(void) strncpy(cmd, cmdline, cp - cmdline);
20827c478bd9Sstevel@tonic-gate 		cmd[cp - cmdline] = '\0';
20837c478bd9Sstevel@tonic-gate 		cmdp = cmd;
20847c478bd9Sstevel@tonic-gate 	}
20857c478bd9Sstevel@tonic-gate 
20867c478bd9Sstevel@tonic-gate 	/* Require that cmdp[0] == '/'? */
20877c478bd9Sstevel@tonic-gate 
20887c478bd9Sstevel@tonic-gate 	eap = getexecprof(buf, KV_COMMAND, cmdp, GET_ONE);
20897c478bd9Sstevel@tonic-gate 	if (eap == NULL)
2090*870ad75aSSean Wilcox 		return (mc_error_create(merr, ENOENT,
2091*870ad75aSSean Wilcox 		    "Could not find the execution profile \"%s\", "
2092*870ad75aSSean Wilcox 		    "command %s.", buf, cmdp));
20937c478bd9Sstevel@tonic-gate 
20947c478bd9Sstevel@tonic-gate 	/* Based on pfexec.c */
20957c478bd9Sstevel@tonic-gate 
20967c478bd9Sstevel@tonic-gate 	/* Get the euid first so we don't override ci->pwd for the uid. */
20977c478bd9Sstevel@tonic-gate 	if ((value = kva_match(eap->attr, EXECATTR_EUID_KW)) != NULL) {
2098*870ad75aSSean Wilcox 		if ((r = get_uid(value, ci, &ci->euid)) != 0) {
2099f48205beScasper 			ci->euid = (uid_t)-1;
2100*870ad75aSSean Wilcox 			err = mc_error_create(merr, r,
2101*870ad75aSSean Wilcox 			    "Could not interpret profile euid value \"%s\", "
2102*870ad75aSSean Wilcox 			    "from the execution profile \"%s\", error %d.",
2103*870ad75aSSean Wilcox 			    value, buf, r);
21047c478bd9Sstevel@tonic-gate 			goto out;
21057c478bd9Sstevel@tonic-gate 		}
21067c478bd9Sstevel@tonic-gate 	}
21077c478bd9Sstevel@tonic-gate 
21087c478bd9Sstevel@tonic-gate 	if ((value = kva_match(eap->attr, EXECATTR_UID_KW)) != NULL) {
2109*870ad75aSSean Wilcox 		if ((r = get_uid(value, ci, &ci->uid)) != 0) {
2110f48205beScasper 			ci->euid = ci->uid = (uid_t)-1;
2111*870ad75aSSean Wilcox 			err = mc_error_create(merr, r,
2112*870ad75aSSean Wilcox 			    "Could not interpret profile uid value \"%s\", "
2113*870ad75aSSean Wilcox 			    "from the execution profile \"%s\", error %d.",
2114*870ad75aSSean Wilcox 			    value, buf, r);
21157c478bd9Sstevel@tonic-gate 			goto out;
21167c478bd9Sstevel@tonic-gate 		}
21177c478bd9Sstevel@tonic-gate 		ci->euid = ci->uid;
21187c478bd9Sstevel@tonic-gate 	}
21197c478bd9Sstevel@tonic-gate 
21207c478bd9Sstevel@tonic-gate 	if ((value = kva_match(eap->attr, EXECATTR_GID_KW)) != NULL) {
21217c478bd9Sstevel@tonic-gate 		ci->egid = ci->gid = get_gid(value);
2122f48205beScasper 		if (ci->gid == (gid_t)-1) {
2123*870ad75aSSean Wilcox 			err = mc_error_create(merr, EINVAL,
2124*870ad75aSSean Wilcox 			    "Could not interpret profile gid value \"%s\", "
2125*870ad75aSSean Wilcox 			    "from the execution profile \"%s\".", value, buf);
21267c478bd9Sstevel@tonic-gate 			goto out;
21277c478bd9Sstevel@tonic-gate 		}
21287c478bd9Sstevel@tonic-gate 	}
21297c478bd9Sstevel@tonic-gate 
21307c478bd9Sstevel@tonic-gate 	if ((value = kva_match(eap->attr, EXECATTR_EGID_KW)) != NULL) {
21317c478bd9Sstevel@tonic-gate 		ci->egid = get_gid(value);
2132f48205beScasper 		if (ci->egid == (gid_t)-1) {
2133*870ad75aSSean Wilcox 			err = mc_error_create(merr, EINVAL,
2134*870ad75aSSean Wilcox 			    "Could not interpret profile egid value \"%s\", "
2135*870ad75aSSean Wilcox 			    "from the execution profile \"%s\".", value, buf);
21367c478bd9Sstevel@tonic-gate 			goto out;
21377c478bd9Sstevel@tonic-gate 		}
21387c478bd9Sstevel@tonic-gate 	}
21397c478bd9Sstevel@tonic-gate 
21407c478bd9Sstevel@tonic-gate 	if ((value = kva_match(eap->attr, EXECATTR_LPRIV_KW)) != NULL) {
21417c478bd9Sstevel@tonic-gate 		ci->lpriv_set = priv_str_to_set(value, ",", NULL);
21427c478bd9Sstevel@tonic-gate 		if (ci->lpriv_set == NULL) {
21437c478bd9Sstevel@tonic-gate 			if (errno != EINVAL)
2144*870ad75aSSean Wilcox 				err = mc_error_create(merr, ENOMEM,
2145*870ad75aSSean Wilcox 				    ALLOCFAIL);
21467c478bd9Sstevel@tonic-gate 			else
2147*870ad75aSSean Wilcox 				err = mc_error_create(merr, EINVAL,
2148*870ad75aSSean Wilcox 				    "Could not interpret profile "
2149*870ad75aSSean Wilcox 				    "limitprivs value \"%s\", from "
2150*870ad75aSSean Wilcox 				    "the execution profile \"%s\".",
2151*870ad75aSSean Wilcox 				    value, buf);
21527c478bd9Sstevel@tonic-gate 			goto out;
21537c478bd9Sstevel@tonic-gate 		}
21547c478bd9Sstevel@tonic-gate 	}
21557c478bd9Sstevel@tonic-gate 
21567c478bd9Sstevel@tonic-gate 	if ((value = kva_match(eap->attr, EXECATTR_IPRIV_KW)) != NULL) {
21577c478bd9Sstevel@tonic-gate 		ci->priv_set = priv_str_to_set(value, ",", NULL);
21587c478bd9Sstevel@tonic-gate 		if (ci->priv_set == NULL) {
21597c478bd9Sstevel@tonic-gate 			if (errno != EINVAL)
2160*870ad75aSSean Wilcox 				err = mc_error_create(merr, ENOMEM,
2161*870ad75aSSean Wilcox 				    ALLOCFAIL);
21627c478bd9Sstevel@tonic-gate 			else
2163*870ad75aSSean Wilcox 				err = mc_error_create(merr, EINVAL,
2164*870ad75aSSean Wilcox 				    "Could not interpret profile privs value "
2165*870ad75aSSean Wilcox 				    "\"%s\", from the execution profile "
2166*870ad75aSSean Wilcox 				    "\"%s\".", value, buf);
21677c478bd9Sstevel@tonic-gate 			goto out;
21687c478bd9Sstevel@tonic-gate 		}
21697c478bd9Sstevel@tonic-gate 	}
21707c478bd9Sstevel@tonic-gate 
21717c478bd9Sstevel@tonic-gate out:
21727c478bd9Sstevel@tonic-gate 	free_execattr(eap);
21737c478bd9Sstevel@tonic-gate 
2174*870ad75aSSean Wilcox 	return (err);
21757c478bd9Sstevel@tonic-gate }
21767c478bd9Sstevel@tonic-gate 
21777c478bd9Sstevel@tonic-gate /*
2178*870ad75aSSean Wilcox  * Return an error message structure containing the error message
2179*870ad75aSSean Wilcox  * with context, and the error so the caller can make a decision
2180*870ad75aSSean Wilcox  * on what to do next.
2181*870ad75aSSean Wilcox  *
2182*870ad75aSSean Wilcox  * Because get_ids uses the mc_error_create() function which can
2183*870ad75aSSean Wilcox  * reallocate the merr, this function must return the merr pointer
2184*870ad75aSSean Wilcox  * in case it was reallocated.
21857c478bd9Sstevel@tonic-gate  */
2186*870ad75aSSean Wilcox static mc_error_t *
218713d8aaa1SSean Wilcox get_ids(scf_propertygroup_t *methpg, scf_propertygroup_t *instpg,
2188*870ad75aSSean Wilcox     scf_property_t *prop, scf_value_t *val, struct method_context *ci,
2189*870ad75aSSean Wilcox     mc_error_t *merr)
21907c478bd9Sstevel@tonic-gate {
21917c478bd9Sstevel@tonic-gate 	char *vbuf = ci->vbuf;
21927c478bd9Sstevel@tonic-gate 	ssize_t vbuf_sz = ci->vbuf_sz;
21937c478bd9Sstevel@tonic-gate 	int r;
21947c478bd9Sstevel@tonic-gate 
219513d8aaa1SSean Wilcox 	/*
219613d8aaa1SSean Wilcox 	 * This should never happen because the caller should fall through
219713d8aaa1SSean Wilcox 	 * another path of just setting the ids to defaults, instead of
219813d8aaa1SSean Wilcox 	 * attempting to get the ids here.
219913d8aaa1SSean Wilcox 	 */
2200*870ad75aSSean Wilcox 	if (methpg == NULL && instpg == NULL)
2201*870ad75aSSean Wilcox 		return (mc_error_create(merr, ENOENT,
2202*870ad75aSSean Wilcox 		    "No property groups to get ids from."));
220313d8aaa1SSean Wilcox 
220413d8aaa1SSean Wilcox 	if (!(get_astring_val(methpg, SCF_PROPERTY_USER,
220513d8aaa1SSean Wilcox 	    vbuf, vbuf_sz, prop, val) == 0 || get_astring_val(instpg,
220613d8aaa1SSean Wilcox 	    SCF_PROPERTY_USER, vbuf, vbuf_sz, prop,
2207*870ad75aSSean Wilcox 	    val) == 0))
2208*870ad75aSSean Wilcox 		return (mc_error_create(merr, ENOENT,
2209*870ad75aSSean Wilcox 		    "Could not get \"%s\" property.", SCF_PROPERTY_USER));
22107c478bd9Sstevel@tonic-gate 
2211*870ad75aSSean Wilcox 	if ((r = get_uid(vbuf, ci, &ci->uid)) != 0) {
2212f48205beScasper 		ci->uid = (uid_t)-1;
2213*870ad75aSSean Wilcox 		return (mc_error_create(merr, r,
2214*870ad75aSSean Wilcox 		    "Could not interpret \"%s\" property value \"%s\", "
2215*870ad75aSSean Wilcox 		    "error %d.", SCF_PROPERTY_USER, vbuf, r));
22167c478bd9Sstevel@tonic-gate 	}
22177c478bd9Sstevel@tonic-gate 
221813d8aaa1SSean Wilcox 	if (!(get_astring_val(methpg, SCF_PROPERTY_GROUP, vbuf, vbuf_sz, prop,
221913d8aaa1SSean Wilcox 	    val) == 0 || get_astring_val(instpg, SCF_PROPERTY_GROUP, vbuf,
222013d8aaa1SSean Wilcox 	    vbuf_sz, prop, val) == 0)) {
222113d8aaa1SSean Wilcox 		if (scf_error() == SCF_ERROR_NOT_FOUND) {
222213d8aaa1SSean Wilcox 			(void) strcpy(vbuf, ":default");
222313d8aaa1SSean Wilcox 		} else {
2224*870ad75aSSean Wilcox 			return (mc_error_create(merr, ENOENT,
2225*870ad75aSSean Wilcox 			    "Could not get \"%s\" property.",
2226*870ad75aSSean Wilcox 			    SCF_PROPERTY_GROUP));
22277c478bd9Sstevel@tonic-gate 		}
222813d8aaa1SSean Wilcox 	}
22297c478bd9Sstevel@tonic-gate 
22307c478bd9Sstevel@tonic-gate 	if (strcmp(vbuf, ":default") != 0) {
22317c478bd9Sstevel@tonic-gate 		ci->gid = get_gid(vbuf);
2232f48205beScasper 		if (ci->gid == (gid_t)-1) {
2233*870ad75aSSean Wilcox 			return (mc_error_create(merr, ENOENT,
2234*870ad75aSSean Wilcox 			    "Could not interpret \"%s\" property value \"%s\".",
2235*870ad75aSSean Wilcox 			    SCF_PROPERTY_GROUP, vbuf));
22367c478bd9Sstevel@tonic-gate 		}
22377c478bd9Sstevel@tonic-gate 	} else {
22387c478bd9Sstevel@tonic-gate 		switch (r = lookup_pwd(ci)) {
22397c478bd9Sstevel@tonic-gate 		case 0:
22407c478bd9Sstevel@tonic-gate 			ci->gid = ci->pwd.pw_gid;
22417c478bd9Sstevel@tonic-gate 			break;
22427c478bd9Sstevel@tonic-gate 
22437c478bd9Sstevel@tonic-gate 		case ENOENT:
2244f48205beScasper 			ci->gid = (gid_t)-1;
2245*870ad75aSSean Wilcox 			return (mc_error_create(merr, ENOENT,
2246*870ad75aSSean Wilcox 			    "No passwd entry for uid \"%d\".", ci->uid));
22477c478bd9Sstevel@tonic-gate 
22487c478bd9Sstevel@tonic-gate 		case ENOMEM:
2249*870ad75aSSean Wilcox 			return (mc_error_create(merr, ENOMEM,
2250*870ad75aSSean Wilcox 			    "Out of memory."));
22517c478bd9Sstevel@tonic-gate 
22527c478bd9Sstevel@tonic-gate 		case EIO:
22537c478bd9Sstevel@tonic-gate 		case EMFILE:
22547c478bd9Sstevel@tonic-gate 		case ENFILE:
2255*870ad75aSSean Wilcox 			return (mc_error_create(merr, ENFILE,
2256*870ad75aSSean Wilcox 			    "getpwuid_r() failed, error %d.", r));
22577c478bd9Sstevel@tonic-gate 
22587c478bd9Sstevel@tonic-gate 		default:
22597c478bd9Sstevel@tonic-gate 			bad_fail("lookup_pwd", r);
22607c478bd9Sstevel@tonic-gate 		}
22617c478bd9Sstevel@tonic-gate 	}
22627c478bd9Sstevel@tonic-gate 
226313d8aaa1SSean Wilcox 	if (!(get_astring_val(methpg, SCF_PROPERTY_SUPP_GROUPS, vbuf, vbuf_sz,
226413d8aaa1SSean Wilcox 	    prop, val) == 0 || get_astring_val(instpg,
226513d8aaa1SSean Wilcox 	    SCF_PROPERTY_SUPP_GROUPS, vbuf, vbuf_sz, prop, val) == 0)) {
226613d8aaa1SSean Wilcox 		if (scf_error() == SCF_ERROR_NOT_FOUND) {
226713d8aaa1SSean Wilcox 			(void) strcpy(vbuf, ":default");
226813d8aaa1SSean Wilcox 		} else {
2269*870ad75aSSean Wilcox 			return (mc_error_create(merr, ENOENT,
2270*870ad75aSSean Wilcox 			    "Could not get supplemental groups (\"%s\") "
2271*870ad75aSSean Wilcox 			    "property.", SCF_PROPERTY_SUPP_GROUPS));
22727c478bd9Sstevel@tonic-gate 		}
227313d8aaa1SSean Wilcox 	}
22747c478bd9Sstevel@tonic-gate 
22757c478bd9Sstevel@tonic-gate 	if (strcmp(vbuf, ":default") != 0) {
22767c478bd9Sstevel@tonic-gate 		switch (r = get_groups(vbuf, ci)) {
22777c478bd9Sstevel@tonic-gate 		case 0:
22787c478bd9Sstevel@tonic-gate 			break;
22797c478bd9Sstevel@tonic-gate 
22807c478bd9Sstevel@tonic-gate 		case EINVAL:
2281*870ad75aSSean Wilcox 			return (mc_error_create(merr, EINVAL,
2282*870ad75aSSean Wilcox 			    "Could not interpret supplemental groups (\"%s\") "
2283*870ad75aSSean Wilcox 			    "property value \"%s\".", SCF_PROPERTY_SUPP_GROUPS,
2284*870ad75aSSean Wilcox 			    vbuf));
22857c478bd9Sstevel@tonic-gate 
22867c478bd9Sstevel@tonic-gate 		case E2BIG:
2287*870ad75aSSean Wilcox 			return (mc_error_create(merr, E2BIG,
2288*870ad75aSSean Wilcox 			    "Too many supplemental groups values in \"%s\".",
2289*870ad75aSSean Wilcox 			    vbuf));
22907c478bd9Sstevel@tonic-gate 
22917c478bd9Sstevel@tonic-gate 		default:
22927c478bd9Sstevel@tonic-gate 			bad_fail("get_groups", r);
22937c478bd9Sstevel@tonic-gate 		}
22947c478bd9Sstevel@tonic-gate 	} else {
22957c478bd9Sstevel@tonic-gate 		ci->ngroups = -1;
22967c478bd9Sstevel@tonic-gate 	}
22977c478bd9Sstevel@tonic-gate 
229813d8aaa1SSean Wilcox 	if (!(get_astring_val(methpg, SCF_PROPERTY_PRIVILEGES, vbuf, vbuf_sz,
229913d8aaa1SSean Wilcox 	    prop, val) == 0 || get_astring_val(instpg, SCF_PROPERTY_PRIVILEGES,
230013d8aaa1SSean Wilcox 	    vbuf, vbuf_sz, prop, val) == 0)) {
230113d8aaa1SSean Wilcox 		if (scf_error() == SCF_ERROR_NOT_FOUND) {
230213d8aaa1SSean Wilcox 			(void) strcpy(vbuf, ":default");
230313d8aaa1SSean Wilcox 		} else {
2304*870ad75aSSean Wilcox 			return (mc_error_create(merr, ENOENT,
2305*870ad75aSSean Wilcox 			    "Could not get \"%s\" property.",
2306*870ad75aSSean Wilcox 			    SCF_PROPERTY_PRIVILEGES));
23077c478bd9Sstevel@tonic-gate 		}
230813d8aaa1SSean Wilcox 	}
23097c478bd9Sstevel@tonic-gate 
23107c478bd9Sstevel@tonic-gate 	/*
23117c478bd9Sstevel@tonic-gate 	 * For default privs, we need to keep priv_set == NULL, as
23127c478bd9Sstevel@tonic-gate 	 * we use this test elsewhere.
23137c478bd9Sstevel@tonic-gate 	 */
23147c478bd9Sstevel@tonic-gate 	if (strcmp(vbuf, ":default") != 0) {
23157c478bd9Sstevel@tonic-gate 		ci->priv_set = priv_str_to_set(vbuf, ",", NULL);
23167c478bd9Sstevel@tonic-gate 		if (ci->priv_set == NULL) {
23177c478bd9Sstevel@tonic-gate 			if (errno != EINVAL) {
2318*870ad75aSSean Wilcox 				return (mc_error_create(merr, ENOMEM,
2319*870ad75aSSean Wilcox 				    ALLOCFAIL));
23207c478bd9Sstevel@tonic-gate 			} else {
2321*870ad75aSSean Wilcox 				return (mc_error_create(merr, EINVAL,
2322*870ad75aSSean Wilcox 				    "Could not interpret \"%s\" "
2323*870ad75aSSean Wilcox 				    "property value \"%s\".",
2324*870ad75aSSean Wilcox 				    SCF_PROPERTY_PRIVILEGES, vbuf));
23257c478bd9Sstevel@tonic-gate 			}
23267c478bd9Sstevel@tonic-gate 		}
23277c478bd9Sstevel@tonic-gate 	}
23287c478bd9Sstevel@tonic-gate 
232913d8aaa1SSean Wilcox 	if (!(get_astring_val(methpg, SCF_PROPERTY_LIMIT_PRIVILEGES, vbuf,
233013d8aaa1SSean Wilcox 	    vbuf_sz, prop, val) == 0 || get_astring_val(instpg,
233113d8aaa1SSean Wilcox 	    SCF_PROPERTY_LIMIT_PRIVILEGES, vbuf, vbuf_sz, prop, val) == 0)) {
233213d8aaa1SSean Wilcox 		if (scf_error() == SCF_ERROR_NOT_FOUND) {
233313d8aaa1SSean Wilcox 			(void) strcpy(vbuf, ":default");
233413d8aaa1SSean Wilcox 		} else {
2335*870ad75aSSean Wilcox 			return (mc_error_create(merr, ENOENT,
2336*870ad75aSSean Wilcox 			    "Could not get \"%s\" property.",
2337*870ad75aSSean Wilcox 			    SCF_PROPERTY_LIMIT_PRIVILEGES));
23387c478bd9Sstevel@tonic-gate 		}
233913d8aaa1SSean Wilcox 	}
23407c478bd9Sstevel@tonic-gate 
23417c478bd9Sstevel@tonic-gate 	if (strcmp(vbuf, ":default") == 0)
23427c478bd9Sstevel@tonic-gate 		/*
23437c478bd9Sstevel@tonic-gate 		 * L must default to all privileges so root NPA services see
23447c478bd9Sstevel@tonic-gate 		 * iE = all.  "zone" is all privileges available in the current
23457c478bd9Sstevel@tonic-gate 		 * zone, equivalent to "all" in the global zone.
23467c478bd9Sstevel@tonic-gate 		 */
23477c478bd9Sstevel@tonic-gate 		(void) strcpy(vbuf, "zone");
23487c478bd9Sstevel@tonic-gate 
23497c478bd9Sstevel@tonic-gate 	ci->lpriv_set = priv_str_to_set(vbuf, ",", NULL);
23507c478bd9Sstevel@tonic-gate 	if (ci->lpriv_set == NULL) {
2351*870ad75aSSean Wilcox 		if (errno != EINVAL) {
2352*870ad75aSSean Wilcox 			return (mc_error_create(merr, ENOMEM, ALLOCFAIL));
2353*870ad75aSSean Wilcox 		} else {
2354*870ad75aSSean Wilcox 			return (mc_error_create(merr, EINVAL,
2355*870ad75aSSean Wilcox 			    "Could not interpret \"%s\" property value \"%s\".",
2356*870ad75aSSean Wilcox 			    SCF_PROPERTY_LIMIT_PRIVILEGES, vbuf));
23577c478bd9Sstevel@tonic-gate 		}
23587c478bd9Sstevel@tonic-gate 	}
23597c478bd9Sstevel@tonic-gate 
2360*870ad75aSSean Wilcox 	return (merr);
23617c478bd9Sstevel@tonic-gate }
23627c478bd9Sstevel@tonic-gate 
23637c478bd9Sstevel@tonic-gate static int
23647c478bd9Sstevel@tonic-gate get_environment(scf_handle_t *h, scf_propertygroup_t *pg,
23657c478bd9Sstevel@tonic-gate     struct method_context *mcp, scf_property_t *prop, scf_value_t *val)
23667c478bd9Sstevel@tonic-gate {
23677c478bd9Sstevel@tonic-gate 	scf_iter_t *iter;
23687c478bd9Sstevel@tonic-gate 	scf_type_t type;
23697c478bd9Sstevel@tonic-gate 	size_t i = 0;
23707c478bd9Sstevel@tonic-gate 	int ret;
23717c478bd9Sstevel@tonic-gate 
23727c478bd9Sstevel@tonic-gate 	if (scf_pg_get_property(pg, SCF_PROPERTY_ENVIRONMENT, prop) != 0) {
23737c478bd9Sstevel@tonic-gate 		if (scf_error() == SCF_ERROR_NOT_FOUND)
23747c478bd9Sstevel@tonic-gate 			return (ENOENT);
23757c478bd9Sstevel@tonic-gate 		return (scf_error());
23767c478bd9Sstevel@tonic-gate 	}
23777c478bd9Sstevel@tonic-gate 	if (scf_property_type(prop, &type) != 0)
23787c478bd9Sstevel@tonic-gate 		return (scf_error());
23797c478bd9Sstevel@tonic-gate 	if (type != SCF_TYPE_ASTRING)
23807c478bd9Sstevel@tonic-gate 		return (EINVAL);
23817c478bd9Sstevel@tonic-gate 	if ((iter = scf_iter_create(h)) == NULL)
23827c478bd9Sstevel@tonic-gate 		return (scf_error());
23837c478bd9Sstevel@tonic-gate 
23847c478bd9Sstevel@tonic-gate 	if (scf_iter_property_values(iter, prop) != 0) {
23857c478bd9Sstevel@tonic-gate 		ret = scf_error();
23867c478bd9Sstevel@tonic-gate 		scf_iter_destroy(iter);
23877c478bd9Sstevel@tonic-gate 		return (ret);
23887c478bd9Sstevel@tonic-gate 	}
23897c478bd9Sstevel@tonic-gate 
23907c478bd9Sstevel@tonic-gate 	mcp->env_sz = 10;
23917c478bd9Sstevel@tonic-gate 
23927c478bd9Sstevel@tonic-gate 	if ((mcp->env = uu_zalloc(sizeof (*mcp->env) * mcp->env_sz)) == NULL) {
23937c478bd9Sstevel@tonic-gate 		ret = ENOMEM;
23947c478bd9Sstevel@tonic-gate 		goto out;
23957c478bd9Sstevel@tonic-gate 	}
23967c478bd9Sstevel@tonic-gate 
23977c478bd9Sstevel@tonic-gate 	while ((ret = scf_iter_next_value(iter, val)) == 1) {
23987c478bd9Sstevel@tonic-gate 		ret = scf_value_get_as_string(val, mcp->vbuf, mcp->vbuf_sz);
23997c478bd9Sstevel@tonic-gate 		if (ret == -1) {
24007c478bd9Sstevel@tonic-gate 			ret = scf_error();
24017c478bd9Sstevel@tonic-gate 			goto out;
24027c478bd9Sstevel@tonic-gate 		}
24037c478bd9Sstevel@tonic-gate 
24047c478bd9Sstevel@tonic-gate 		if ((mcp->env[i] = strdup(mcp->vbuf)) == NULL) {
24057c478bd9Sstevel@tonic-gate 			ret = ENOMEM;
24067c478bd9Sstevel@tonic-gate 			goto out;
24077c478bd9Sstevel@tonic-gate 		}
24087c478bd9Sstevel@tonic-gate 
24097c478bd9Sstevel@tonic-gate 		if (++i == mcp->env_sz) {
24107c478bd9Sstevel@tonic-gate 			char **env;
24117c478bd9Sstevel@tonic-gate 			mcp->env_sz *= 2;
24127c478bd9Sstevel@tonic-gate 			env = uu_zalloc(sizeof (*mcp->env) * mcp->env_sz);
24137c478bd9Sstevel@tonic-gate 			if (env == NULL) {
24147c478bd9Sstevel@tonic-gate 				ret = ENOMEM;
24157c478bd9Sstevel@tonic-gate 				goto out;
24167c478bd9Sstevel@tonic-gate 			}
24177c478bd9Sstevel@tonic-gate 			(void) memcpy(env, mcp->env,
24187c478bd9Sstevel@tonic-gate 			    sizeof (*mcp->env) * (mcp->env_sz / 2));
24197c478bd9Sstevel@tonic-gate 			free(mcp->env);
24207c478bd9Sstevel@tonic-gate 			mcp->env = env;
24217c478bd9Sstevel@tonic-gate 		}
24227c478bd9Sstevel@tonic-gate 	}
24237c478bd9Sstevel@tonic-gate 
24247c478bd9Sstevel@tonic-gate 	if (ret == -1)
24257c478bd9Sstevel@tonic-gate 		ret = scf_error();
24267c478bd9Sstevel@tonic-gate 
24277c478bd9Sstevel@tonic-gate out:
24287c478bd9Sstevel@tonic-gate 	scf_iter_destroy(iter);
24297c478bd9Sstevel@tonic-gate 	return (ret);
24307c478bd9Sstevel@tonic-gate }
24317c478bd9Sstevel@tonic-gate 
24327c478bd9Sstevel@tonic-gate /*
24337c478bd9Sstevel@tonic-gate  * Fetch method context information from the repository, allocate and fill
2434*870ad75aSSean Wilcox  * a method_context structure, return it in *mcpp, and return NULL.
24357c478bd9Sstevel@tonic-gate  *
243613d8aaa1SSean Wilcox  * If no method_context is defined, original init context is provided, where
243713d8aaa1SSean Wilcox  * the working directory is '/', and uid/gid are 0/0.  But if a method_context
243813d8aaa1SSean Wilcox  * is defined at any level the smf_method(5) method_context defaults are used.
243913d8aaa1SSean Wilcox  *
2440*870ad75aSSean Wilcox  * Return an error message structure containing the error message
2441*870ad75aSSean Wilcox  * with context, and the error so the caller can make a decision
2442*870ad75aSSean Wilcox  * on what to do next.
2443*870ad75aSSean Wilcox  *
2444*870ad75aSSean Wilcox  * Error Types :
2445*870ad75aSSean Wilcox  * 	E2BIG		Too many values or entry is too big
2446*870ad75aSSean Wilcox  * 	EINVAL		Invalid value
2447*870ad75aSSean Wilcox  * 	EIO		an I/O error has occured
2448*870ad75aSSean Wilcox  * 	ENOENT		no entry for value
2449*870ad75aSSean Wilcox  * 	ENOMEM		out of memory
2450*870ad75aSSean Wilcox  * 	ENOTSUP		Version mismatch
2451*870ad75aSSean Wilcox  * 	ERANGE		value is out of range
2452*870ad75aSSean Wilcox  * 	EMFILE/ENFILE	out of file descriptors
2453*870ad75aSSean Wilcox  *
2454*870ad75aSSean Wilcox  * 	SCF_ERROR_BACKEND_ACCESS
2455*870ad75aSSean Wilcox  * 	SCF_ERROR_CONNECTION_BROKEN
2456*870ad75aSSean Wilcox  * 	SCF_ERROR_DELETED
2457*870ad75aSSean Wilcox  * 	SCF_ERROR_CONSTRAINT_VIOLATED
2458*870ad75aSSean Wilcox  * 	SCF_ERROR_HANDLE_DESTROYED
2459*870ad75aSSean Wilcox  * 	SCF_ERROR_INTERNAL
2460*870ad75aSSean Wilcox  * 	SCF_ERROR_INVALID_ARGUMENT
2461*870ad75aSSean Wilcox  * 	SCF_ERROR_NO_MEMORY
2462*870ad75aSSean Wilcox  * 	SCF_ERROR_NO_RESOURCES
2463*870ad75aSSean Wilcox  * 	SCF_ERROR_NOT_BOUND
2464*870ad75aSSean Wilcox  * 	SCF_ERROR_NOT_FOUND
2465*870ad75aSSean Wilcox  * 	SCF_ERROR_NOT_SET
2466*870ad75aSSean Wilcox  * 	SCF_ERROR_TYPE_MISMATCH
2467*870ad75aSSean Wilcox  *
24687c478bd9Sstevel@tonic-gate  */
2469*870ad75aSSean Wilcox mc_error_t *
24707c478bd9Sstevel@tonic-gate restarter_get_method_context(uint_t version, scf_instance_t *inst,
24717c478bd9Sstevel@tonic-gate     scf_snapshot_t *snap, const char *mname, const char *cmdline,
24727c478bd9Sstevel@tonic-gate     struct method_context **mcpp)
24737c478bd9Sstevel@tonic-gate {
24747c478bd9Sstevel@tonic-gate 	scf_handle_t *h;
24757c478bd9Sstevel@tonic-gate 	scf_propertygroup_t *methpg = NULL;
24767c478bd9Sstevel@tonic-gate 	scf_propertygroup_t *instpg = NULL;
24777c478bd9Sstevel@tonic-gate 	scf_propertygroup_t *pg = NULL;
24787c478bd9Sstevel@tonic-gate 	scf_property_t *prop = NULL;
24797c478bd9Sstevel@tonic-gate 	scf_value_t *val = NULL;
24807c478bd9Sstevel@tonic-gate 	scf_type_t ty;
24817c478bd9Sstevel@tonic-gate 	uint8_t use_profile;
2482*870ad75aSSean Wilcox 	int ret = 0;
248313d8aaa1SSean Wilcox 	int mc_used = 0;
2484*870ad75aSSean Wilcox 	mc_error_t *err = NULL;
24857c478bd9Sstevel@tonic-gate 	struct method_context *cip;
24867c478bd9Sstevel@tonic-gate 
2487*870ad75aSSean Wilcox 	if ((err = malloc(sizeof (mc_error_t))) == NULL)
2488*870ad75aSSean Wilcox 		return (mc_error_create(NULL, ENOMEM, NULL));
2489*870ad75aSSean Wilcox 
2490*870ad75aSSean Wilcox 	/* Set the type to zero to track if an error occured. */
2491*870ad75aSSean Wilcox 	err->type = 0;
2492*870ad75aSSean Wilcox 
24937c478bd9Sstevel@tonic-gate 	if (version != RESTARTER_METHOD_CONTEXT_VERSION)
2494*870ad75aSSean Wilcox 		return (mc_error_create(err, ENOTSUP,
2495*870ad75aSSean Wilcox 		    "Invalid client version %d. (Expected %d)",
2496*870ad75aSSean Wilcox 		    version, RESTARTER_METHOD_CONTEXT_VERSION));
24977c478bd9Sstevel@tonic-gate 
24987c478bd9Sstevel@tonic-gate 	/* Get the handle before we allocate anything. */
24997c478bd9Sstevel@tonic-gate 	h = scf_instance_handle(inst);
25007c478bd9Sstevel@tonic-gate 	if (h == NULL)
2501*870ad75aSSean Wilcox 		return (mc_error_create(err, scf_error(),
2502*870ad75aSSean Wilcox 		    scf_strerror(scf_error())));
25037c478bd9Sstevel@tonic-gate 
25047c478bd9Sstevel@tonic-gate 	cip = malloc(sizeof (*cip));
25057c478bd9Sstevel@tonic-gate 	if (cip == NULL)
2506*870ad75aSSean Wilcox 		return (mc_error_create(err, ENOMEM, ALLOCFAIL));
25077c478bd9Sstevel@tonic-gate 
25087c478bd9Sstevel@tonic-gate 	(void) memset(cip, 0, sizeof (*cip));
2509f48205beScasper 	cip->uid = (uid_t)-1;
2510f48205beScasper 	cip->euid = (uid_t)-1;
2511f48205beScasper 	cip->gid = (gid_t)-1;
2512f48205beScasper 	cip->egid = (gid_t)-1;
25137c478bd9Sstevel@tonic-gate 
25147c478bd9Sstevel@tonic-gate 	cip->vbuf_sz = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH);
25157c478bd9Sstevel@tonic-gate 	assert(cip->vbuf_sz >= 0);
25167c478bd9Sstevel@tonic-gate 	cip->vbuf = malloc(cip->vbuf_sz);
25177c478bd9Sstevel@tonic-gate 	if (cip->vbuf == NULL) {
25187c478bd9Sstevel@tonic-gate 		free(cip);
2519*870ad75aSSean Wilcox 		return (mc_error_create(err, ENOMEM, ALLOCFAIL));
25207c478bd9Sstevel@tonic-gate 	}
25217c478bd9Sstevel@tonic-gate 
25227c478bd9Sstevel@tonic-gate 	if ((instpg = scf_pg_create(h)) == NULL ||
25237c478bd9Sstevel@tonic-gate 	    (methpg = scf_pg_create(h)) == NULL ||
25247c478bd9Sstevel@tonic-gate 	    (prop = scf_property_create(h)) == NULL ||
25257c478bd9Sstevel@tonic-gate 	    (val = scf_value_create(h)) == NULL) {
2526*870ad75aSSean Wilcox 		err = mc_error_create(err, scf_error(),
2527*870ad75aSSean Wilcox 		    "Failed to create repository object: %s\n",
2528*870ad75aSSean Wilcox 		    scf_strerror(scf_error()));
25297c478bd9Sstevel@tonic-gate 		goto out;
25307c478bd9Sstevel@tonic-gate 	}
25317c478bd9Sstevel@tonic-gate 
25327c478bd9Sstevel@tonic-gate 	/*
25337c478bd9Sstevel@tonic-gate 	 * The method environment, and the credentials/profile data,
25347c478bd9Sstevel@tonic-gate 	 * may be found either in the pg for the method (methpg),
25357c478bd9Sstevel@tonic-gate 	 * or in the instance/service SCF_PG_METHOD_CONTEXT pg (named
25367c478bd9Sstevel@tonic-gate 	 * instpg below).
25377c478bd9Sstevel@tonic-gate 	 */
25387c478bd9Sstevel@tonic-gate 
25397c478bd9Sstevel@tonic-gate 	if (scf_instance_get_pg_composed(inst, snap, mname, methpg) !=
25407c478bd9Sstevel@tonic-gate 	    SCF_SUCCESS) {
2541*870ad75aSSean Wilcox 		err = mc_error_create(err, scf_error(), "Unable to get the "
2542*870ad75aSSean Wilcox 		    "\"%s\" method, %s", mname, scf_strerror(scf_error()));
25437c478bd9Sstevel@tonic-gate 		goto out;
25447c478bd9Sstevel@tonic-gate 	}
25457c478bd9Sstevel@tonic-gate 
25467c478bd9Sstevel@tonic-gate 	if (scf_instance_get_pg_composed(inst, snap, SCF_PG_METHOD_CONTEXT,
25477c478bd9Sstevel@tonic-gate 	    instpg) != SCF_SUCCESS) {
25487c478bd9Sstevel@tonic-gate 		if (scf_error() != SCF_ERROR_NOT_FOUND) {
2549*870ad75aSSean Wilcox 			err = mc_error_create(err, scf_error(),
2550*870ad75aSSean Wilcox 			    "Unable to retrieve the \"%s\" property group, %s",
2551*870ad75aSSean Wilcox 			    SCF_PG_METHOD_CONTEXT, scf_strerror(scf_error()));
25527c478bd9Sstevel@tonic-gate 			goto out;
25537c478bd9Sstevel@tonic-gate 		}
25547c478bd9Sstevel@tonic-gate 		scf_pg_destroy(instpg);
25557c478bd9Sstevel@tonic-gate 		instpg = NULL;
255613d8aaa1SSean Wilcox 	} else {
255713d8aaa1SSean Wilcox 		mc_used++;
25587c478bd9Sstevel@tonic-gate 	}
25597c478bd9Sstevel@tonic-gate 
25607c478bd9Sstevel@tonic-gate 	ret = get_environment(h, methpg, cip, prop, val);
25617c478bd9Sstevel@tonic-gate 	if (ret == ENOENT && instpg != NULL) {
25627c478bd9Sstevel@tonic-gate 		ret = get_environment(h, instpg, cip, prop, val);
25637c478bd9Sstevel@tonic-gate 	}
25647c478bd9Sstevel@tonic-gate 
25657c478bd9Sstevel@tonic-gate 	switch (ret) {
25667c478bd9Sstevel@tonic-gate 	case 0:
256713d8aaa1SSean Wilcox 		mc_used++;
256813d8aaa1SSean Wilcox 		break;
25697c478bd9Sstevel@tonic-gate 	case ENOENT:
25707c478bd9Sstevel@tonic-gate 		break;
25717c478bd9Sstevel@tonic-gate 	case ENOMEM:
2572*870ad75aSSean Wilcox 		err = mc_error_create(err, ret, "Out of memory.");
25737c478bd9Sstevel@tonic-gate 		goto out;
25747c478bd9Sstevel@tonic-gate 	case EINVAL:
2575*870ad75aSSean Wilcox 		err = mc_error_create(err, ret, "Invalid method environment.");
25767c478bd9Sstevel@tonic-gate 		goto out;
25777c478bd9Sstevel@tonic-gate 	default:
2578*870ad75aSSean Wilcox 		err = mc_error_create(err, ret,
2579*870ad75aSSean Wilcox 		    "Get method environment failed : %s\n", scf_strerror(ret));
25807c478bd9Sstevel@tonic-gate 		goto out;
25817c478bd9Sstevel@tonic-gate 	}
25827c478bd9Sstevel@tonic-gate 
25837c478bd9Sstevel@tonic-gate 	pg = methpg;
25847c478bd9Sstevel@tonic-gate 
25857c478bd9Sstevel@tonic-gate 	ret = scf_pg_get_property(pg, SCF_PROPERTY_USE_PROFILE, prop);
25867c478bd9Sstevel@tonic-gate 	if (ret && scf_error() == SCF_ERROR_NOT_FOUND && instpg != NULL) {
258713d8aaa1SSean Wilcox 		pg = NULL;
258813d8aaa1SSean Wilcox 		ret = scf_pg_get_property(instpg, SCF_PROPERTY_USE_PROFILE,
258913d8aaa1SSean Wilcox 		    prop);
25907c478bd9Sstevel@tonic-gate 	}
25917c478bd9Sstevel@tonic-gate 
25927c478bd9Sstevel@tonic-gate 	if (ret) {
25937c478bd9Sstevel@tonic-gate 		switch (scf_error()) {
25947c478bd9Sstevel@tonic-gate 		case SCF_ERROR_NOT_FOUND:
259513d8aaa1SSean Wilcox 			/* No profile context: use default credentials */
25967c478bd9Sstevel@tonic-gate 			cip->uid = 0;
25977c478bd9Sstevel@tonic-gate 			cip->gid = 0;
259813d8aaa1SSean Wilcox 			break;
25997c478bd9Sstevel@tonic-gate 
26007c478bd9Sstevel@tonic-gate 		case SCF_ERROR_CONNECTION_BROKEN:
2601*870ad75aSSean Wilcox 			err = mc_error_create(err, SCF_ERROR_CONNECTION_BROKEN,
2602*870ad75aSSean Wilcox 			    RCBROKEN);
26037c478bd9Sstevel@tonic-gate 			goto out;
26047c478bd9Sstevel@tonic-gate 
26057c478bd9Sstevel@tonic-gate 		case SCF_ERROR_DELETED:
2606*870ad75aSSean Wilcox 			err = mc_error_create(err, SCF_ERROR_NOT_FOUND,
2607*870ad75aSSean Wilcox 			    "Could not find property group \"%s\"",
2608*870ad75aSSean Wilcox 			    pg == NULL ? SCF_PG_METHOD_CONTEXT : mname);
26097c478bd9Sstevel@tonic-gate 			goto out;
26107c478bd9Sstevel@tonic-gate 
26117c478bd9Sstevel@tonic-gate 		case SCF_ERROR_HANDLE_MISMATCH:
26127c478bd9Sstevel@tonic-gate 		case SCF_ERROR_INVALID_ARGUMENT:
26137c478bd9Sstevel@tonic-gate 		case SCF_ERROR_NOT_SET:
26147c478bd9Sstevel@tonic-gate 		default:
26157c478bd9Sstevel@tonic-gate 			bad_fail("scf_pg_get_property", scf_error());
26167c478bd9Sstevel@tonic-gate 		}
261713d8aaa1SSean Wilcox 	} else {
26187c478bd9Sstevel@tonic-gate 		if (scf_property_type(prop, &ty) != SCF_SUCCESS) {
2619*870ad75aSSean Wilcox 			ret = scf_error();
2620*870ad75aSSean Wilcox 			switch (ret) {
26217c478bd9Sstevel@tonic-gate 			case SCF_ERROR_CONNECTION_BROKEN:
2622*870ad75aSSean Wilcox 				err = mc_error_create(err,
2623*870ad75aSSean Wilcox 				    SCF_ERROR_CONNECTION_BROKEN, RCBROKEN);
26247c478bd9Sstevel@tonic-gate 				break;
26257c478bd9Sstevel@tonic-gate 
26267c478bd9Sstevel@tonic-gate 			case SCF_ERROR_DELETED:
2627*870ad75aSSean Wilcox 				err = mc_error_create(err,
2628*870ad75aSSean Wilcox 				    SCF_ERROR_NOT_FOUND,
2629*870ad75aSSean Wilcox 				    "Could not find property group \"%s\"",
2630*870ad75aSSean Wilcox 				    pg == NULL ? SCF_PG_METHOD_CONTEXT : mname);
26317c478bd9Sstevel@tonic-gate 				break;
26327c478bd9Sstevel@tonic-gate 
26337c478bd9Sstevel@tonic-gate 			case SCF_ERROR_NOT_SET:
26347c478bd9Sstevel@tonic-gate 			default:
2635*870ad75aSSean Wilcox 				bad_fail("scf_property_type", ret);
26367c478bd9Sstevel@tonic-gate 			}
26377c478bd9Sstevel@tonic-gate 
26387c478bd9Sstevel@tonic-gate 			goto out;
26397c478bd9Sstevel@tonic-gate 		}
26407c478bd9Sstevel@tonic-gate 
26417c478bd9Sstevel@tonic-gate 		if (ty != SCF_TYPE_BOOLEAN) {
2642*870ad75aSSean Wilcox 			err = mc_error_create(err,
2643*870ad75aSSean Wilcox 			    SCF_ERROR_TYPE_MISMATCH,
2644*870ad75aSSean Wilcox 			    "\"%s\" property is not boolean in property group "
2645*870ad75aSSean Wilcox 			    "\"%s\".", SCF_PROPERTY_USE_PROFILE,
2646*870ad75aSSean Wilcox 			    pg == NULL ? SCF_PG_METHOD_CONTEXT : mname);
26477c478bd9Sstevel@tonic-gate 			goto out;
26487c478bd9Sstevel@tonic-gate 		}
26497c478bd9Sstevel@tonic-gate 
26507c478bd9Sstevel@tonic-gate 		if (scf_property_get_value(prop, val) != SCF_SUCCESS) {
2651*870ad75aSSean Wilcox 			ret = scf_error();
2652*870ad75aSSean Wilcox 			switch (ret) {
26537c478bd9Sstevel@tonic-gate 			case SCF_ERROR_CONNECTION_BROKEN:
2654*870ad75aSSean Wilcox 				err = mc_error_create(err,
2655*870ad75aSSean Wilcox 				    SCF_ERROR_CONNECTION_BROKEN, RCBROKEN);
26567c478bd9Sstevel@tonic-gate 				break;
26577c478bd9Sstevel@tonic-gate 
26587c478bd9Sstevel@tonic-gate 			case SCF_ERROR_CONSTRAINT_VIOLATED:
2659*870ad75aSSean Wilcox 				err = mc_error_create(err,
2660*870ad75aSSean Wilcox 				    SCF_ERROR_CONSTRAINT_VIOLATED,
2661*870ad75aSSean Wilcox 				    "\"%s\" property has multiple values.",
2662*870ad75aSSean Wilcox 				    SCF_PROPERTY_USE_PROFILE);
26637c478bd9Sstevel@tonic-gate 				break;
26647c478bd9Sstevel@tonic-gate 
26657c478bd9Sstevel@tonic-gate 			case SCF_ERROR_NOT_FOUND:
2666*870ad75aSSean Wilcox 				err = mc_error_create(err,
2667*870ad75aSSean Wilcox 				    SCF_ERROR_NOT_FOUND,
2668*870ad75aSSean Wilcox 				    "\"%s\" property has no values.",
2669*870ad75aSSean Wilcox 				    SCF_PROPERTY_USE_PROFILE);
26707c478bd9Sstevel@tonic-gate 				break;
26717c478bd9Sstevel@tonic-gate 			default:
2672*870ad75aSSean Wilcox 				bad_fail("scf_property_get_value", ret);
26737c478bd9Sstevel@tonic-gate 			}
26747c478bd9Sstevel@tonic-gate 
26757c478bd9Sstevel@tonic-gate 			goto out;
26767c478bd9Sstevel@tonic-gate 		}
26777c478bd9Sstevel@tonic-gate 
267813d8aaa1SSean Wilcox 		mc_used++;
26797c478bd9Sstevel@tonic-gate 		ret = scf_value_get_boolean(val, &use_profile);
26807c478bd9Sstevel@tonic-gate 		assert(ret == SCF_SUCCESS);
26817c478bd9Sstevel@tonic-gate 
26827c478bd9Sstevel@tonic-gate 		/* get ids & privileges */
26837c478bd9Sstevel@tonic-gate 		if (use_profile)
2684*870ad75aSSean Wilcox 			err = get_profile(pg, instpg, prop, val, cmdline,
2685*870ad75aSSean Wilcox 			    cip, err);
26867c478bd9Sstevel@tonic-gate 		else
2687*870ad75aSSean Wilcox 			err = get_ids(pg, instpg, prop, val, cip, err);
268813d8aaa1SSean Wilcox 
2689*870ad75aSSean Wilcox 		if (err->type != 0)
26907c478bd9Sstevel@tonic-gate 			goto out;
269113d8aaa1SSean Wilcox 	}
26927c478bd9Sstevel@tonic-gate 
26937c478bd9Sstevel@tonic-gate 	/* get working directory */
269413d8aaa1SSean Wilcox 	if ((methpg != NULL && scf_pg_get_property(methpg,
269513d8aaa1SSean Wilcox 	    SCF_PROPERTY_WORKING_DIRECTORY, prop) == SCF_SUCCESS) ||
269613d8aaa1SSean Wilcox 	    (instpg != NULL && scf_pg_get_property(instpg,
269713d8aaa1SSean Wilcox 	    SCF_PROPERTY_WORKING_DIRECTORY, prop) == SCF_SUCCESS)) {
269813d8aaa1SSean Wilcox 		if (scf_property_get_value(prop, val) != SCF_SUCCESS) {
2699*870ad75aSSean Wilcox 			ret = scf_error();
2700*870ad75aSSean Wilcox 			switch (ret) {
270113d8aaa1SSean Wilcox 			case SCF_ERROR_CONNECTION_BROKEN:
2702*870ad75aSSean Wilcox 				err = mc_error_create(err, ret, RCBROKEN);
270313d8aaa1SSean Wilcox 				break;
270413d8aaa1SSean Wilcox 
270513d8aaa1SSean Wilcox 			case SCF_ERROR_CONSTRAINT_VIOLATED:
2706*870ad75aSSean Wilcox 				err = mc_error_create(err, ret,
2707*870ad75aSSean Wilcox 				    "\"%s\" property has multiple values.",
2708*870ad75aSSean Wilcox 				    SCF_PROPERTY_WORKING_DIRECTORY);
270913d8aaa1SSean Wilcox 				break;
271013d8aaa1SSean Wilcox 
271113d8aaa1SSean Wilcox 			case SCF_ERROR_NOT_FOUND:
2712*870ad75aSSean Wilcox 				err = mc_error_create(err, ret,
2713*870ad75aSSean Wilcox 				    "\"%s\" property has no values.",
2714*870ad75aSSean Wilcox 				    SCF_PROPERTY_WORKING_DIRECTORY);
271513d8aaa1SSean Wilcox 				break;
271613d8aaa1SSean Wilcox 
271713d8aaa1SSean Wilcox 			default:
2718*870ad75aSSean Wilcox 				bad_fail("scf_property_get_value", ret);
271913d8aaa1SSean Wilcox 			}
272013d8aaa1SSean Wilcox 
27217c478bd9Sstevel@tonic-gate 			goto out;
27227c478bd9Sstevel@tonic-gate 		}
27237c478bd9Sstevel@tonic-gate 
272413d8aaa1SSean Wilcox 		mc_used++;
272513d8aaa1SSean Wilcox 		ret = scf_value_get_astring(val, cip->vbuf, cip->vbuf_sz);
272613d8aaa1SSean Wilcox 		assert(ret != -1);
272713d8aaa1SSean Wilcox 	} else {
2728*870ad75aSSean Wilcox 		ret = scf_error();
2729*870ad75aSSean Wilcox 		switch (ret) {
273013d8aaa1SSean Wilcox 		case SCF_ERROR_NOT_FOUND:
273113d8aaa1SSean Wilcox 			/* okay if missing. */
273213d8aaa1SSean Wilcox 			(void) strcpy(cip->vbuf, ":default");
273313d8aaa1SSean Wilcox 			break;
273413d8aaa1SSean Wilcox 
273513d8aaa1SSean Wilcox 		case SCF_ERROR_CONNECTION_BROKEN:
2736*870ad75aSSean Wilcox 			err = mc_error_create(err, ret, RCBROKEN);
273713d8aaa1SSean Wilcox 			goto out;
273813d8aaa1SSean Wilcox 
273913d8aaa1SSean Wilcox 		case SCF_ERROR_DELETED:
2740*870ad75aSSean Wilcox 			err = mc_error_create(err, ret,
2741*870ad75aSSean Wilcox 			    "Property group could not be found");
274213d8aaa1SSean Wilcox 			goto out;
274313d8aaa1SSean Wilcox 
274413d8aaa1SSean Wilcox 		case SCF_ERROR_HANDLE_MISMATCH:
274513d8aaa1SSean Wilcox 		case SCF_ERROR_INVALID_ARGUMENT:
274613d8aaa1SSean Wilcox 		case SCF_ERROR_NOT_SET:
274713d8aaa1SSean Wilcox 		default:
2748*870ad75aSSean Wilcox 			bad_fail("scf_pg_get_property", ret);
274913d8aaa1SSean Wilcox 		}
275013d8aaa1SSean Wilcox 	}
275113d8aaa1SSean Wilcox 
27527c478bd9Sstevel@tonic-gate 	if (strcmp(cip->vbuf, ":default") == 0 ||
27537c478bd9Sstevel@tonic-gate 	    strcmp(cip->vbuf, ":home") == 0) {
27547c478bd9Sstevel@tonic-gate 		switch (ret = lookup_pwd(cip)) {
27557c478bd9Sstevel@tonic-gate 		case 0:
27567c478bd9Sstevel@tonic-gate 			break;
27577c478bd9Sstevel@tonic-gate 
27587c478bd9Sstevel@tonic-gate 		case ENOMEM:
2759*870ad75aSSean Wilcox 			err = mc_error_create(err, ret, "Out of memory.");
27607c478bd9Sstevel@tonic-gate 			goto out;
27617c478bd9Sstevel@tonic-gate 
27627c478bd9Sstevel@tonic-gate 		case ENOENT:
27637c478bd9Sstevel@tonic-gate 		case EIO:
27647c478bd9Sstevel@tonic-gate 		case EMFILE:
27657c478bd9Sstevel@tonic-gate 		case ENFILE:
2766*870ad75aSSean Wilcox 			err = mc_error_create(err, ret,
2767*870ad75aSSean Wilcox 			    "Could not get passwd entry.");
27687c478bd9Sstevel@tonic-gate 			goto out;
27697c478bd9Sstevel@tonic-gate 
27707c478bd9Sstevel@tonic-gate 		default:
27717c478bd9Sstevel@tonic-gate 			bad_fail("lookup_pwd", ret);
27727c478bd9Sstevel@tonic-gate 		}
27737c478bd9Sstevel@tonic-gate 
27747c478bd9Sstevel@tonic-gate 		cip->working_dir = strdup(cip->pwd.pw_dir);
27757c478bd9Sstevel@tonic-gate 		if (cip->working_dir == NULL) {
2776*870ad75aSSean Wilcox 			err = mc_error_create(err, ENOMEM, ALLOCFAIL);
27777c478bd9Sstevel@tonic-gate 			goto out;
27787c478bd9Sstevel@tonic-gate 		}
27797c478bd9Sstevel@tonic-gate 	} else {
27807c478bd9Sstevel@tonic-gate 		cip->working_dir = strdup(cip->vbuf);
27817c478bd9Sstevel@tonic-gate 		if (cip->working_dir == NULL) {
2782*870ad75aSSean Wilcox 			err = mc_error_create(err, ENOMEM, ALLOCFAIL);
27837c478bd9Sstevel@tonic-gate 			goto out;
27847c478bd9Sstevel@tonic-gate 		}
27857c478bd9Sstevel@tonic-gate 	}
27867c478bd9Sstevel@tonic-gate 
27877c478bd9Sstevel@tonic-gate 	/* get (optional) corefile pattern */
278813d8aaa1SSean Wilcox 	if ((methpg != NULL && scf_pg_get_property(methpg,
278913d8aaa1SSean Wilcox 	    SCF_PROPERTY_COREFILE_PATTERN, prop) == SCF_SUCCESS) ||
279013d8aaa1SSean Wilcox 	    (instpg != NULL && scf_pg_get_property(instpg,
279113d8aaa1SSean Wilcox 	    SCF_PROPERTY_COREFILE_PATTERN, prop) == SCF_SUCCESS)) {
279213d8aaa1SSean Wilcox 		if (scf_property_get_value(prop, val) != SCF_SUCCESS) {
2793*870ad75aSSean Wilcox 			ret = scf_error();
2794*870ad75aSSean Wilcox 			switch (ret) {
279513d8aaa1SSean Wilcox 			case SCF_ERROR_CONNECTION_BROKEN:
2796*870ad75aSSean Wilcox 				err = mc_error_create(err, ret, RCBROKEN);
279713d8aaa1SSean Wilcox 				break;
279813d8aaa1SSean Wilcox 
279913d8aaa1SSean Wilcox 			case SCF_ERROR_CONSTRAINT_VIOLATED:
2800*870ad75aSSean Wilcox 				err = mc_error_create(err, ret,
2801*870ad75aSSean Wilcox 				    "\"%s\" property has multiple values.",
2802*870ad75aSSean Wilcox 				    SCF_PROPERTY_COREFILE_PATTERN);
280313d8aaa1SSean Wilcox 				break;
280413d8aaa1SSean Wilcox 
280513d8aaa1SSean Wilcox 			case SCF_ERROR_NOT_FOUND:
2806*870ad75aSSean Wilcox 				err = mc_error_create(err, ret,
2807*870ad75aSSean Wilcox 				    "\"%s\" property has no values.",
2808*870ad75aSSean Wilcox 				    SCF_PROPERTY_COREFILE_PATTERN);
280913d8aaa1SSean Wilcox 				break;
281013d8aaa1SSean Wilcox 
281113d8aaa1SSean Wilcox 			default:
2812*870ad75aSSean Wilcox 				bad_fail("scf_property_get_value", ret);
28137c478bd9Sstevel@tonic-gate 			}
28147c478bd9Sstevel@tonic-gate 
281513d8aaa1SSean Wilcox 		} else {
281613d8aaa1SSean Wilcox 
281713d8aaa1SSean Wilcox 			ret = scf_value_get_astring(val, cip->vbuf,
281813d8aaa1SSean Wilcox 			    cip->vbuf_sz);
281913d8aaa1SSean Wilcox 			assert(ret != -1);
282013d8aaa1SSean Wilcox 
28217c478bd9Sstevel@tonic-gate 			cip->corefile_pattern = strdup(cip->vbuf);
28227c478bd9Sstevel@tonic-gate 			if (cip->corefile_pattern == NULL) {
2823*870ad75aSSean Wilcox 				err = mc_error_create(err, ENOMEM, ALLOCFAIL);
28247c478bd9Sstevel@tonic-gate 				goto out;
28257c478bd9Sstevel@tonic-gate 			}
282613d8aaa1SSean Wilcox 		}
282713d8aaa1SSean Wilcox 
282813d8aaa1SSean Wilcox 		mc_used++;
28297c478bd9Sstevel@tonic-gate 	} else {
2830*870ad75aSSean Wilcox 		ret = scf_error();
2831*870ad75aSSean Wilcox 		switch (ret) {
28327c478bd9Sstevel@tonic-gate 		case SCF_ERROR_NOT_FOUND:
28337c478bd9Sstevel@tonic-gate 			/* okay if missing. */
28347c478bd9Sstevel@tonic-gate 			break;
28357c478bd9Sstevel@tonic-gate 
28367c478bd9Sstevel@tonic-gate 		case SCF_ERROR_CONNECTION_BROKEN:
2837*870ad75aSSean Wilcox 			err = mc_error_create(err, ret, RCBROKEN);
28387c478bd9Sstevel@tonic-gate 			goto out;
28397c478bd9Sstevel@tonic-gate 
28407c478bd9Sstevel@tonic-gate 		case SCF_ERROR_DELETED:
2841*870ad75aSSean Wilcox 			err = mc_error_create(err, ret,
2842*870ad75aSSean Wilcox 			    "Property group could not be found");
28437c478bd9Sstevel@tonic-gate 			goto out;
28447c478bd9Sstevel@tonic-gate 
28457c478bd9Sstevel@tonic-gate 		case SCF_ERROR_HANDLE_MISMATCH:
28467c478bd9Sstevel@tonic-gate 		case SCF_ERROR_INVALID_ARGUMENT:
28477c478bd9Sstevel@tonic-gate 		case SCF_ERROR_NOT_SET:
28487c478bd9Sstevel@tonic-gate 		default:
2849*870ad75aSSean Wilcox 			bad_fail("scf_pg_get_property", ret);
28507c478bd9Sstevel@tonic-gate 		}
28517c478bd9Sstevel@tonic-gate 	}
28527c478bd9Sstevel@tonic-gate 
28537c478bd9Sstevel@tonic-gate 	if (restarter_rm_libs_loadable()) {
28547c478bd9Sstevel@tonic-gate 		/* get project */
285513d8aaa1SSean Wilcox 		if ((methpg != NULL && scf_pg_get_property(methpg,
285613d8aaa1SSean Wilcox 		    SCF_PROPERTY_PROJECT, prop) == SCF_SUCCESS) ||
285713d8aaa1SSean Wilcox 		    (instpg != NULL && scf_pg_get_property(instpg,
285813d8aaa1SSean Wilcox 		    SCF_PROPERTY_PROJECT, prop) == SCF_SUCCESS)) {
285913d8aaa1SSean Wilcox 			if (scf_property_get_value(prop, val) != SCF_SUCCESS) {
2860*870ad75aSSean Wilcox 				ret = scf_error();
2861*870ad75aSSean Wilcox 				switch (ret) {
286213d8aaa1SSean Wilcox 				case SCF_ERROR_CONNECTION_BROKEN:
2863*870ad75aSSean Wilcox 					err = mc_error_create(err, ret,
2864*870ad75aSSean Wilcox 					    RCBROKEN);
286513d8aaa1SSean Wilcox 					break;
286613d8aaa1SSean Wilcox 
286713d8aaa1SSean Wilcox 				case SCF_ERROR_CONSTRAINT_VIOLATED:
2868*870ad75aSSean Wilcox 					err = mc_error_create(err, ret,
2869*870ad75aSSean Wilcox 					    "\"%s\" property has multiple "
2870*870ad75aSSean Wilcox 					    "values.", SCF_PROPERTY_PROJECT);
287113d8aaa1SSean Wilcox 					break;
287213d8aaa1SSean Wilcox 
287313d8aaa1SSean Wilcox 				case SCF_ERROR_NOT_FOUND:
2874*870ad75aSSean Wilcox 					err = mc_error_create(err, ret,
2875*870ad75aSSean Wilcox 					    "\"%s\" property has no values.",
2876*870ad75aSSean Wilcox 					    SCF_PROPERTY_PROJECT);
287713d8aaa1SSean Wilcox 					break;
287813d8aaa1SSean Wilcox 
287913d8aaa1SSean Wilcox 				default:
2880*870ad75aSSean Wilcox 					bad_fail("scf_property_get_value", ret);
288113d8aaa1SSean Wilcox 				}
288213d8aaa1SSean Wilcox 
288313d8aaa1SSean Wilcox 				(void) strcpy(cip->vbuf, ":default");
288413d8aaa1SSean Wilcox 			} else {
288513d8aaa1SSean Wilcox 				ret = scf_value_get_astring(val, cip->vbuf,
288613d8aaa1SSean Wilcox 				    cip->vbuf_sz);
288713d8aaa1SSean Wilcox 				assert(ret != -1);
288813d8aaa1SSean Wilcox 			}
288913d8aaa1SSean Wilcox 
289013d8aaa1SSean Wilcox 			mc_used++;
289113d8aaa1SSean Wilcox 		} else {
289213d8aaa1SSean Wilcox 			(void) strcpy(cip->vbuf, ":default");
28937c478bd9Sstevel@tonic-gate 		}
28947c478bd9Sstevel@tonic-gate 
28957c478bd9Sstevel@tonic-gate 		switch (ret = get_projid(cip->vbuf, cip)) {
28967c478bd9Sstevel@tonic-gate 		case 0:
28977c478bd9Sstevel@tonic-gate 			break;
28987c478bd9Sstevel@tonic-gate 
28997c478bd9Sstevel@tonic-gate 		case ENOMEM:
2900*870ad75aSSean Wilcox 			err = mc_error_create(err, ret, "Out of memory.");
29017c478bd9Sstevel@tonic-gate 			goto out;
29027c478bd9Sstevel@tonic-gate 
29037c478bd9Sstevel@tonic-gate 		case ENOENT:
2904*870ad75aSSean Wilcox 			err = mc_error_create(err, ret,
2905*870ad75aSSean Wilcox 			    "Missing passwd or project entry for \"%s\".",
2906*870ad75aSSean Wilcox 			    cip->vbuf);
29077c478bd9Sstevel@tonic-gate 			goto out;
29087c478bd9Sstevel@tonic-gate 
29097c478bd9Sstevel@tonic-gate 		case EIO:
2910*870ad75aSSean Wilcox 			err = mc_error_create(err, ret, "I/O error.");
29117c478bd9Sstevel@tonic-gate 			goto out;
29127c478bd9Sstevel@tonic-gate 
29137c478bd9Sstevel@tonic-gate 		case EMFILE:
29147c478bd9Sstevel@tonic-gate 		case ENFILE:
2915*870ad75aSSean Wilcox 			err = mc_error_create(err, ret,
2916*870ad75aSSean Wilcox 			    "Out of file descriptors.");
29177c478bd9Sstevel@tonic-gate 			goto out;
29187c478bd9Sstevel@tonic-gate 
29197c478bd9Sstevel@tonic-gate 		case -1:
2920*870ad75aSSean Wilcox 			err = mc_error_create(err, ret,
2921*870ad75aSSean Wilcox 			    "Name service switch is misconfigured.");
29227c478bd9Sstevel@tonic-gate 			goto out;
29237c478bd9Sstevel@tonic-gate 
29247c478bd9Sstevel@tonic-gate 		case ERANGE:
2925*870ad75aSSean Wilcox 		case E2BIG:
2926*870ad75aSSean Wilcox 			err = mc_error_create(err, ret,
2927*870ad75aSSean Wilcox 			    "Project ID \"%s\" too big.", cip->vbuf);
29287c478bd9Sstevel@tonic-gate 			goto out;
29297c478bd9Sstevel@tonic-gate 
29307c478bd9Sstevel@tonic-gate 		case EINVAL:
2931*870ad75aSSean Wilcox 			err = mc_error_create(err, ret,
2932*870ad75aSSean Wilcox 			    "Project ID \"%s\" is invalid.", cip->vbuf);
29337c478bd9Sstevel@tonic-gate 			goto out;
29347c478bd9Sstevel@tonic-gate 
29357c478bd9Sstevel@tonic-gate 		default:
29367c478bd9Sstevel@tonic-gate 			bad_fail("get_projid", ret);
29377c478bd9Sstevel@tonic-gate 		}
29387c478bd9Sstevel@tonic-gate 
29397c478bd9Sstevel@tonic-gate 		/* get resource pool */
294013d8aaa1SSean Wilcox 		if ((methpg != NULL && scf_pg_get_property(methpg,
294113d8aaa1SSean Wilcox 		    SCF_PROPERTY_RESOURCE_POOL, prop) == SCF_SUCCESS) ||
294213d8aaa1SSean Wilcox 		    (instpg != NULL && scf_pg_get_property(instpg,
294313d8aaa1SSean Wilcox 		    SCF_PROPERTY_RESOURCE_POOL, prop) == SCF_SUCCESS)) {
294413d8aaa1SSean Wilcox 			if (scf_property_get_value(prop, val) != SCF_SUCCESS) {
2945*870ad75aSSean Wilcox 				ret = scf_error();
2946*870ad75aSSean Wilcox 				switch (ret) {
294713d8aaa1SSean Wilcox 				case SCF_ERROR_CONNECTION_BROKEN:
2948*870ad75aSSean Wilcox 					err = mc_error_create(err, ret,
2949*870ad75aSSean Wilcox 					    RCBROKEN);
295013d8aaa1SSean Wilcox 					break;
295113d8aaa1SSean Wilcox 
295213d8aaa1SSean Wilcox 				case SCF_ERROR_CONSTRAINT_VIOLATED:
2953*870ad75aSSean Wilcox 					err = mc_error_create(err, ret,
2954*870ad75aSSean Wilcox 					    "\"%s\" property has multiple "
2955*870ad75aSSean Wilcox 					    "values.",
2956*870ad75aSSean Wilcox 					    SCF_PROPERTY_RESOURCE_POOL);
295713d8aaa1SSean Wilcox 					break;
295813d8aaa1SSean Wilcox 
295913d8aaa1SSean Wilcox 				case SCF_ERROR_NOT_FOUND:
2960*870ad75aSSean Wilcox 					err = mc_error_create(err, ret,
2961*870ad75aSSean Wilcox 					    "\"%s\" property has no "
2962*870ad75aSSean Wilcox 					    "values.",
2963*870ad75aSSean Wilcox 					    SCF_PROPERTY_RESOURCE_POOL);
296413d8aaa1SSean Wilcox 					break;
296513d8aaa1SSean Wilcox 
296613d8aaa1SSean Wilcox 				default:
2967*870ad75aSSean Wilcox 					bad_fail("scf_property_get_value", ret);
296813d8aaa1SSean Wilcox 				}
296913d8aaa1SSean Wilcox 
297013d8aaa1SSean Wilcox 				(void) strcpy(cip->vbuf, ":default");
297113d8aaa1SSean Wilcox 			} else {
297213d8aaa1SSean Wilcox 				ret = scf_value_get_astring(val, cip->vbuf,
297313d8aaa1SSean Wilcox 				    cip->vbuf_sz);
297413d8aaa1SSean Wilcox 				assert(ret != -1);
297513d8aaa1SSean Wilcox 			}
297613d8aaa1SSean Wilcox 
297713d8aaa1SSean Wilcox 			mc_used++;
297813d8aaa1SSean Wilcox 		} else {
2979*870ad75aSSean Wilcox 			ret = scf_error();
2980*870ad75aSSean Wilcox 			switch (ret) {
298113d8aaa1SSean Wilcox 			case SCF_ERROR_NOT_FOUND:
298213d8aaa1SSean Wilcox 				/* okay if missing. */
298313d8aaa1SSean Wilcox 				(void) strcpy(cip->vbuf, ":default");
298413d8aaa1SSean Wilcox 				break;
298513d8aaa1SSean Wilcox 
298613d8aaa1SSean Wilcox 			case SCF_ERROR_CONNECTION_BROKEN:
2987*870ad75aSSean Wilcox 				err = mc_error_create(err, ret, RCBROKEN);
29887c478bd9Sstevel@tonic-gate 				goto out;
298913d8aaa1SSean Wilcox 
299013d8aaa1SSean Wilcox 			case SCF_ERROR_DELETED:
2991*870ad75aSSean Wilcox 				err = mc_error_create(err, ret,
2992*870ad75aSSean Wilcox 				    "property group could not be found.");
299313d8aaa1SSean Wilcox 				goto out;
299413d8aaa1SSean Wilcox 
299513d8aaa1SSean Wilcox 			case SCF_ERROR_HANDLE_MISMATCH:
299613d8aaa1SSean Wilcox 			case SCF_ERROR_INVALID_ARGUMENT:
299713d8aaa1SSean Wilcox 			case SCF_ERROR_NOT_SET:
299813d8aaa1SSean Wilcox 			default:
2999*870ad75aSSean Wilcox 				bad_fail("scf_pg_get_property", ret);
300013d8aaa1SSean Wilcox 			}
30017c478bd9Sstevel@tonic-gate 		}
30027c478bd9Sstevel@tonic-gate 
30037c478bd9Sstevel@tonic-gate 		if (strcmp(cip->vbuf, ":default") != 0) {
30047c478bd9Sstevel@tonic-gate 			cip->resource_pool = strdup(cip->vbuf);
30057c478bd9Sstevel@tonic-gate 			if (cip->resource_pool == NULL) {
3006*870ad75aSSean Wilcox 				err = mc_error_create(err, ENOMEM, ALLOCFAIL);
30077c478bd9Sstevel@tonic-gate 				goto out;
30087c478bd9Sstevel@tonic-gate 			}
30097c478bd9Sstevel@tonic-gate 		}
30107c478bd9Sstevel@tonic-gate 	}
30117c478bd9Sstevel@tonic-gate 
301213d8aaa1SSean Wilcox 	/*
301313d8aaa1SSean Wilcox 	 * A method_context was not used for any configurable
301413d8aaa1SSean Wilcox 	 * elements or attributes, so reset and use the simple
301513d8aaa1SSean Wilcox 	 * defaults that provide historic init behavior.
301613d8aaa1SSean Wilcox 	 */
301713d8aaa1SSean Wilcox 	if (mc_used == 0) {
301813d8aaa1SSean Wilcox 		(void) memset(cip, 0, sizeof (*cip));
301913d8aaa1SSean Wilcox 		cip->uid = 0;
302013d8aaa1SSean Wilcox 		cip->gid = 0;
302113d8aaa1SSean Wilcox 		cip->euid = (uid_t)-1;
302213d8aaa1SSean Wilcox 		cip->egid = (gid_t)-1;
302313d8aaa1SSean Wilcox 	}
302413d8aaa1SSean Wilcox 
30257c478bd9Sstevel@tonic-gate 	*mcpp = cip;
30267c478bd9Sstevel@tonic-gate 
30277c478bd9Sstevel@tonic-gate out:
30287c478bd9Sstevel@tonic-gate 	(void) scf_value_destroy(val);
30297c478bd9Sstevel@tonic-gate 	scf_property_destroy(prop);
30307c478bd9Sstevel@tonic-gate 	scf_pg_destroy(instpg);
30317c478bd9Sstevel@tonic-gate 	scf_pg_destroy(methpg);
30327c478bd9Sstevel@tonic-gate 
30337c478bd9Sstevel@tonic-gate 	if (cip->pwbuf != NULL)
30347c478bd9Sstevel@tonic-gate 		free(cip->pwbuf);
30357c478bd9Sstevel@tonic-gate 	free(cip->vbuf);
30367c478bd9Sstevel@tonic-gate 
3037*870ad75aSSean Wilcox 	if (err->type != 0) {
30387c478bd9Sstevel@tonic-gate 		restarter_free_method_context(cip);
3039*870ad75aSSean Wilcox 	} else {
3040*870ad75aSSean Wilcox 		restarter_mc_error_destroy(err);
3041*870ad75aSSean Wilcox 		err = NULL;
3042*870ad75aSSean Wilcox 	}
30437c478bd9Sstevel@tonic-gate 
3044*870ad75aSSean Wilcox 	return (err);
30457c478bd9Sstevel@tonic-gate }
30467c478bd9Sstevel@tonic-gate 
30477c478bd9Sstevel@tonic-gate /*
30487c478bd9Sstevel@tonic-gate  * Modify the current process per the given method_context.  On success, returns
30497c478bd9Sstevel@tonic-gate  * 0.  Note that the environment is not modified by this function to include the
30507c478bd9Sstevel@tonic-gate  * environment variables in cip->env.
30517c478bd9Sstevel@tonic-gate  *
30527c478bd9Sstevel@tonic-gate  * On failure, sets *fp to NULL or the name of the function which failed,
30537c478bd9Sstevel@tonic-gate  * and returns one of the following error codes.  The words in parentheses are
30547c478bd9Sstevel@tonic-gate  * the values to which *fp may be set for the error case.
30557c478bd9Sstevel@tonic-gate  *   ENOMEM - malloc() failed
30567c478bd9Sstevel@tonic-gate  *   EIO - an I/O error occurred (getpwuid_r, chdir)
30577c478bd9Sstevel@tonic-gate  *   EMFILE - process is out of file descriptors (getpwuid_r)
30587c478bd9Sstevel@tonic-gate  *   ENFILE - system is out of file handles (getpwuid_r)
30597c478bd9Sstevel@tonic-gate  *   EINVAL - gid or egid is out of range (setregid)
30607c478bd9Sstevel@tonic-gate  *	      ngroups is too big (setgroups)
30617c478bd9Sstevel@tonic-gate  *	      project's project id is bad (setproject)
30627c478bd9Sstevel@tonic-gate  *	      uid or euid is out of range (setreuid)
30633ad28c1eSrm88369  *	      poolname is invalid (pool_set_binding)
30647c478bd9Sstevel@tonic-gate  *   EPERM - insufficient privilege (setregid, initgroups, setgroups, setppriv,
30657c478bd9Sstevel@tonic-gate  *	         setproject, setreuid, settaskid)
30667c478bd9Sstevel@tonic-gate  *   ENOENT - uid has a passwd entry but no shadow entry
30677c478bd9Sstevel@tonic-gate  *	      working_dir does not exist (chdir)
30687c478bd9Sstevel@tonic-gate  *	      uid has no passwd entry
30697c478bd9Sstevel@tonic-gate  *	      the pool could not be found (pool_set_binding)
30707c478bd9Sstevel@tonic-gate  *   EFAULT - lpriv_set or priv_set has a bad address (setppriv)
30717c478bd9Sstevel@tonic-gate  *	      working_dir has a bad address (chdir)
30727c478bd9Sstevel@tonic-gate  *   EACCES - could not access working_dir (chdir)
30737c478bd9Sstevel@tonic-gate  *	      in a TASK_FINAL task (setproject, settaskid)
30747c478bd9Sstevel@tonic-gate  *	      no resource pool accepting default binding exists (setproject)
30757c478bd9Sstevel@tonic-gate  *   ELOOP - too many symbolic links in working_dir (chdir)
30767c478bd9Sstevel@tonic-gate  *   ENAMETOOLONG - working_dir is too long (chdir)
30777c478bd9Sstevel@tonic-gate  *   ENOLINK - working_dir is on an inaccessible remote machine (chdir)
30787c478bd9Sstevel@tonic-gate  *   ENOTDIR - working_dir is not a directory (chdir)
30797c478bd9Sstevel@tonic-gate  *   ESRCH - uid is not a user of project (setproject)
30807c478bd9Sstevel@tonic-gate  *	     project is invalid (setproject)
30817c478bd9Sstevel@tonic-gate  *	     the resource pool specified for project is unknown (setproject)
30827c478bd9Sstevel@tonic-gate  *   EBADF - the configuration for the pool is invalid (pool_set_binding)
30837c478bd9Sstevel@tonic-gate  *   -1 - core_set_process_path() failed (core_set_process_path)
30847c478bd9Sstevel@tonic-gate  *	  a resource control assignment failed (setproject)
30857c478bd9Sstevel@tonic-gate  *	  a system error occurred during pool_set_binding (pool_set_binding)
30867c478bd9Sstevel@tonic-gate  */
30877c478bd9Sstevel@tonic-gate int
30887c478bd9Sstevel@tonic-gate restarter_set_method_context(struct method_context *cip, const char **fp)
30897c478bd9Sstevel@tonic-gate {
30907c478bd9Sstevel@tonic-gate 	pid_t mypid = -1;
30917c478bd9Sstevel@tonic-gate 	int r, ret;
30927c478bd9Sstevel@tonic-gate 
30937c478bd9Sstevel@tonic-gate 	cip->pwbuf = NULL;
30947c478bd9Sstevel@tonic-gate 	*fp = NULL;
30957c478bd9Sstevel@tonic-gate 
3096f48205beScasper 	if (cip->gid != (gid_t)-1) {
30977c478bd9Sstevel@tonic-gate 		if (setregid(cip->gid,
3098f48205beScasper 		    cip->egid != (gid_t)-1 ? cip->egid : cip->gid) != 0) {
30997c478bd9Sstevel@tonic-gate 			*fp = "setregid";
31007c478bd9Sstevel@tonic-gate 
31017c478bd9Sstevel@tonic-gate 			ret = errno;
31027c478bd9Sstevel@tonic-gate 			assert(ret == EINVAL || ret == EPERM);
31037c478bd9Sstevel@tonic-gate 			goto out;
31047c478bd9Sstevel@tonic-gate 		}
31057c478bd9Sstevel@tonic-gate 	} else {
31067c478bd9Sstevel@tonic-gate 		if (cip->pwbuf == NULL) {
31077c478bd9Sstevel@tonic-gate 			switch (ret = lookup_pwd(cip)) {
31087c478bd9Sstevel@tonic-gate 			case 0:
31097c478bd9Sstevel@tonic-gate 				break;
31107c478bd9Sstevel@tonic-gate 
31117c478bd9Sstevel@tonic-gate 			case ENOMEM:
31127c478bd9Sstevel@tonic-gate 			case ENOENT:
31137c478bd9Sstevel@tonic-gate 				*fp = NULL;
31147c478bd9Sstevel@tonic-gate 				goto out;
31157c478bd9Sstevel@tonic-gate 
31167c478bd9Sstevel@tonic-gate 			case EIO:
31177c478bd9Sstevel@tonic-gate 			case EMFILE:
31187c478bd9Sstevel@tonic-gate 			case ENFILE:
31197c478bd9Sstevel@tonic-gate 				*fp = "getpwuid_r";
31207c478bd9Sstevel@tonic-gate 				goto out;
31217c478bd9Sstevel@tonic-gate 
31227c478bd9Sstevel@tonic-gate 			default:
31237c478bd9Sstevel@tonic-gate 				bad_fail("lookup_pwd", ret);
31247c478bd9Sstevel@tonic-gate 			}
31257c478bd9Sstevel@tonic-gate 		}
31267c478bd9Sstevel@tonic-gate 
31277c478bd9Sstevel@tonic-gate 		if (setregid(cip->pwd.pw_gid,
3128f48205beScasper 		    cip->egid != (gid_t)-1 ?
3129f48205beScasper 		    cip->egid : cip->pwd.pw_gid) != 0) {
31307c478bd9Sstevel@tonic-gate 			*fp = "setregid";
31317c478bd9Sstevel@tonic-gate 
31327c478bd9Sstevel@tonic-gate 			ret = errno;
31337c478bd9Sstevel@tonic-gate 			assert(ret == EINVAL || ret == EPERM);
31347c478bd9Sstevel@tonic-gate 			goto out;
31357c478bd9Sstevel@tonic-gate 		}
31367c478bd9Sstevel@tonic-gate 	}
31377c478bd9Sstevel@tonic-gate 
31387c478bd9Sstevel@tonic-gate 	if (cip->ngroups == -1) {
31397c478bd9Sstevel@tonic-gate 		if (cip->pwbuf == NULL) {
31407c478bd9Sstevel@tonic-gate 			switch (ret = lookup_pwd(cip)) {
31417c478bd9Sstevel@tonic-gate 			case 0:
31427c478bd9Sstevel@tonic-gate 				break;
31437c478bd9Sstevel@tonic-gate 
31447c478bd9Sstevel@tonic-gate 			case ENOMEM:
31457c478bd9Sstevel@tonic-gate 			case ENOENT:
31467c478bd9Sstevel@tonic-gate 				*fp = NULL;
31477c478bd9Sstevel@tonic-gate 				goto out;
31487c478bd9Sstevel@tonic-gate 
31497c478bd9Sstevel@tonic-gate 			case EIO:
31507c478bd9Sstevel@tonic-gate 			case EMFILE:
31517c478bd9Sstevel@tonic-gate 			case ENFILE:
31527c478bd9Sstevel@tonic-gate 				*fp = "getpwuid_r";
31537c478bd9Sstevel@tonic-gate 				goto out;
31547c478bd9Sstevel@tonic-gate 
31557c478bd9Sstevel@tonic-gate 			default:
31567c478bd9Sstevel@tonic-gate 				bad_fail("lookup_pwd", ret);
31577c478bd9Sstevel@tonic-gate 			}
31587c478bd9Sstevel@tonic-gate 		}
31597c478bd9Sstevel@tonic-gate 
31607c478bd9Sstevel@tonic-gate 		/* Ok if cip->gid == -1 */
31617c478bd9Sstevel@tonic-gate 		if (initgroups(cip->pwd.pw_name, cip->gid) != 0) {
31627c478bd9Sstevel@tonic-gate 			*fp = "initgroups";
31637c478bd9Sstevel@tonic-gate 			ret = errno;
31647c478bd9Sstevel@tonic-gate 			assert(ret == EPERM);
31657c478bd9Sstevel@tonic-gate 			goto out;
31667c478bd9Sstevel@tonic-gate 		}
31677c478bd9Sstevel@tonic-gate 	} else if (cip->ngroups > 0 &&
31687c478bd9Sstevel@tonic-gate 	    setgroups(cip->ngroups, cip->groups) != 0) {
31697c478bd9Sstevel@tonic-gate 		*fp = "setgroups";
31707c478bd9Sstevel@tonic-gate 
31717c478bd9Sstevel@tonic-gate 		ret = errno;
31727c478bd9Sstevel@tonic-gate 		assert(ret == EINVAL || ret == EPERM);
31737c478bd9Sstevel@tonic-gate 		goto out;
31747c478bd9Sstevel@tonic-gate 	}
31757c478bd9Sstevel@tonic-gate 
31767c478bd9Sstevel@tonic-gate 	if (cip->corefile_pattern != NULL) {
31777c478bd9Sstevel@tonic-gate 		mypid = getpid();
31787c478bd9Sstevel@tonic-gate 
31797c478bd9Sstevel@tonic-gate 		if (core_set_process_path(cip->corefile_pattern,
31807c478bd9Sstevel@tonic-gate 		    strlen(cip->corefile_pattern) + 1, mypid) != 0) {
31817c478bd9Sstevel@tonic-gate 			*fp = "core_set_process_path";
31827c478bd9Sstevel@tonic-gate 			ret = -1;
31837c478bd9Sstevel@tonic-gate 			goto out;
31847c478bd9Sstevel@tonic-gate 		}
31857c478bd9Sstevel@tonic-gate 	}
31867c478bd9Sstevel@tonic-gate 
31877c478bd9Sstevel@tonic-gate 	if (restarter_rm_libs_loadable()) {
31887c478bd9Sstevel@tonic-gate 		if (cip->project == NULL) {
31897c478bd9Sstevel@tonic-gate 			if (settaskid(getprojid(), TASK_NORMAL) == -1) {
31907c478bd9Sstevel@tonic-gate 				switch (errno) {
31917c478bd9Sstevel@tonic-gate 				case EACCES:
31927c478bd9Sstevel@tonic-gate 				case EPERM:
31937c478bd9Sstevel@tonic-gate 					*fp = "settaskid";
31947c478bd9Sstevel@tonic-gate 					ret = errno;
31957c478bd9Sstevel@tonic-gate 					goto out;
31967c478bd9Sstevel@tonic-gate 
31977c478bd9Sstevel@tonic-gate 				case EINVAL:
31987c478bd9Sstevel@tonic-gate 				default:
31997c478bd9Sstevel@tonic-gate 					bad_fail("settaskid", errno);
32007c478bd9Sstevel@tonic-gate 				}
32017c478bd9Sstevel@tonic-gate 			}
32027c478bd9Sstevel@tonic-gate 		} else {
32037c478bd9Sstevel@tonic-gate 			switch (ret = lookup_pwd(cip)) {
32047c478bd9Sstevel@tonic-gate 			case 0:
32057c478bd9Sstevel@tonic-gate 				break;
32067c478bd9Sstevel@tonic-gate 
32077c478bd9Sstevel@tonic-gate 			case ENOMEM:
32087c478bd9Sstevel@tonic-gate 			case ENOENT:
32097c478bd9Sstevel@tonic-gate 				*fp = NULL;
32107c478bd9Sstevel@tonic-gate 				goto out;
32117c478bd9Sstevel@tonic-gate 
32127c478bd9Sstevel@tonic-gate 			case EIO:
32137c478bd9Sstevel@tonic-gate 			case EMFILE:
32147c478bd9Sstevel@tonic-gate 			case ENFILE:
32157c478bd9Sstevel@tonic-gate 				*fp = "getpwuid_r";
32167c478bd9Sstevel@tonic-gate 				goto out;
32177c478bd9Sstevel@tonic-gate 
32187c478bd9Sstevel@tonic-gate 			default:
32197c478bd9Sstevel@tonic-gate 				bad_fail("lookup_pwd", ret);
32207c478bd9Sstevel@tonic-gate 			}
32217c478bd9Sstevel@tonic-gate 
32227c478bd9Sstevel@tonic-gate 			*fp = "setproject";
32237c478bd9Sstevel@tonic-gate 
32247c478bd9Sstevel@tonic-gate 			switch (setproject(cip->project, cip->pwd.pw_name,
32257c478bd9Sstevel@tonic-gate 			    TASK_NORMAL)) {
32267c478bd9Sstevel@tonic-gate 			case 0:
32277c478bd9Sstevel@tonic-gate 				break;
32287c478bd9Sstevel@tonic-gate 
32297c478bd9Sstevel@tonic-gate 			case SETPROJ_ERR_TASK:
32307c478bd9Sstevel@tonic-gate 			case SETPROJ_ERR_POOL:
32317c478bd9Sstevel@tonic-gate 				ret = errno;
32327c478bd9Sstevel@tonic-gate 				goto out;
32337c478bd9Sstevel@tonic-gate 
32347c478bd9Sstevel@tonic-gate 			default:
32357c478bd9Sstevel@tonic-gate 				ret = -1;
32367c478bd9Sstevel@tonic-gate 				goto out;
32377c478bd9Sstevel@tonic-gate 			}
32387c478bd9Sstevel@tonic-gate 		}
32397c478bd9Sstevel@tonic-gate 
32407c478bd9Sstevel@tonic-gate 		if (cip->resource_pool != NULL) {
32417c478bd9Sstevel@tonic-gate 			if (mypid == -1)
32427c478bd9Sstevel@tonic-gate 				mypid = getpid();
32437c478bd9Sstevel@tonic-gate 
32447c478bd9Sstevel@tonic-gate 			*fp = "pool_set_binding";
32457c478bd9Sstevel@tonic-gate 
32467c478bd9Sstevel@tonic-gate 			if (pool_set_binding(cip->resource_pool, P_PID,
32477c478bd9Sstevel@tonic-gate 			    mypid) != PO_SUCCESS) {
32487c478bd9Sstevel@tonic-gate 				switch (pool_error()) {
32493ad28c1eSrm88369 				case POE_INVALID_SEARCH:
32507c478bd9Sstevel@tonic-gate 					ret = ENOENT;
32517c478bd9Sstevel@tonic-gate 					break;
32527c478bd9Sstevel@tonic-gate 
32533ad28c1eSrm88369 				case POE_BADPARAM:
32543ad28c1eSrm88369 					ret = EINVAL;
32553ad28c1eSrm88369 					break;
32563ad28c1eSrm88369 
32577c478bd9Sstevel@tonic-gate 				case POE_INVALID_CONF:
32587c478bd9Sstevel@tonic-gate 					ret = EBADF;
32597c478bd9Sstevel@tonic-gate 					break;
32607c478bd9Sstevel@tonic-gate 
32617c478bd9Sstevel@tonic-gate 				case POE_SYSTEM:
32627c478bd9Sstevel@tonic-gate 					ret = -1;
32637c478bd9Sstevel@tonic-gate 					break;
32647c478bd9Sstevel@tonic-gate 
32657c478bd9Sstevel@tonic-gate 				default:
32667c478bd9Sstevel@tonic-gate 					bad_fail("pool_set_binding",
32677c478bd9Sstevel@tonic-gate 					    pool_error());
32687c478bd9Sstevel@tonic-gate 				}
32697c478bd9Sstevel@tonic-gate 
32707c478bd9Sstevel@tonic-gate 				goto out;
32717c478bd9Sstevel@tonic-gate 			}
32727c478bd9Sstevel@tonic-gate 		}
32737c478bd9Sstevel@tonic-gate 	}
32747c478bd9Sstevel@tonic-gate 
32757c478bd9Sstevel@tonic-gate 	/*
32762a3221a4Svp157776 	 * Now, we have to assume our ID. If the UID is 0, we want it to be
32772a3221a4Svp157776 	 * privilege-aware, otherwise the limit set gets used instead of E/P.
32787c478bd9Sstevel@tonic-gate 	 * We can do this by setting P as well, which keeps
32797c478bd9Sstevel@tonic-gate 	 * PA status (see priv_can_clear_PA()).
32807c478bd9Sstevel@tonic-gate 	 */
32817c478bd9Sstevel@tonic-gate 
328213d8aaa1SSean Wilcox 	*fp = "setppriv";
328313d8aaa1SSean Wilcox 
328413d8aaa1SSean Wilcox 	if (cip->lpriv_set != NULL) {
328513d8aaa1SSean Wilcox 		if (setppriv(PRIV_SET, PRIV_LIMIT, cip->lpriv_set) != 0) {
328613d8aaa1SSean Wilcox 			ret = errno;
328713d8aaa1SSean Wilcox 			assert(ret == EFAULT || ret == EPERM);
328813d8aaa1SSean Wilcox 			goto out;
328913d8aaa1SSean Wilcox 		}
329013d8aaa1SSean Wilcox 	}
329113d8aaa1SSean Wilcox 	if (cip->priv_set != NULL) {
329213d8aaa1SSean Wilcox 		if (setppriv(PRIV_SET, PRIV_INHERITABLE, cip->priv_set) != 0) {
329313d8aaa1SSean Wilcox 			ret = errno;
329413d8aaa1SSean Wilcox 			assert(ret == EFAULT || ret == EPERM);
329513d8aaa1SSean Wilcox 			goto out;
329613d8aaa1SSean Wilcox 		}
329713d8aaa1SSean Wilcox 	}
329813d8aaa1SSean Wilcox 
329913d8aaa1SSean Wilcox 	/*
330013d8aaa1SSean Wilcox 	 * If the limit privset is already set, then must be privilege
330113d8aaa1SSean Wilcox 	 * aware.  Otherwise, don't assume anything, and force privilege
330213d8aaa1SSean Wilcox 	 * aware status.
330313d8aaa1SSean Wilcox 	 */
330413d8aaa1SSean Wilcox 
330513d8aaa1SSean Wilcox 	if (cip->lpriv_set == NULL && cip->priv_set != NULL) {
330613d8aaa1SSean Wilcox 		ret = setpflags(PRIV_AWARE, 1);
330713d8aaa1SSean Wilcox 		assert(ret == 0);
330813d8aaa1SSean Wilcox 	}
330913d8aaa1SSean Wilcox 
33107c478bd9Sstevel@tonic-gate 	*fp = "setreuid";
3311f48205beScasper 	if (setreuid(cip->uid,
3312f48205beScasper 	    cip->euid != (uid_t)-1 ? cip->euid : cip->uid) != 0) {
33137c478bd9Sstevel@tonic-gate 		ret = errno;
33147c478bd9Sstevel@tonic-gate 		assert(ret == EINVAL || ret == EPERM);
33157c478bd9Sstevel@tonic-gate 		goto out;
33167c478bd9Sstevel@tonic-gate 	}
33177c478bd9Sstevel@tonic-gate 
33187c478bd9Sstevel@tonic-gate 	*fp = "setppriv";
33197c478bd9Sstevel@tonic-gate 	if (cip->priv_set != NULL) {
33207c478bd9Sstevel@tonic-gate 		if (setppriv(PRIV_SET, PRIV_PERMITTED, cip->priv_set) != 0) {
33217c478bd9Sstevel@tonic-gate 			ret = errno;
33227c478bd9Sstevel@tonic-gate 			assert(ret == EFAULT || ret == EPERM);
33237c478bd9Sstevel@tonic-gate 			goto out;
33247c478bd9Sstevel@tonic-gate 		}
33257c478bd9Sstevel@tonic-gate 	}
33267c478bd9Sstevel@tonic-gate 
33272a3221a4Svp157776 	/*
33282a3221a4Svp157776 	 * The last thing to do is chdir to the specified working directory.
33292a3221a4Svp157776 	 * This should come after the uid switching as only the user might
33302a3221a4Svp157776 	 * have access to the specified directory.
33312a3221a4Svp157776 	 */
33322a3221a4Svp157776 	if (cip->working_dir != NULL) {
33333eae19d9Swesolows 		do {
33342a3221a4Svp157776 			r = chdir(cip->working_dir);
33353eae19d9Swesolows 		} while (r != 0 && errno == EINTR);
33362a3221a4Svp157776 		if (r != 0) {
33372a3221a4Svp157776 			*fp = "chdir";
33382a3221a4Svp157776 			ret = errno;
33392a3221a4Svp157776 			goto out;
33402a3221a4Svp157776 		}
33412a3221a4Svp157776 	}
33422a3221a4Svp157776 
33437c478bd9Sstevel@tonic-gate 	ret = 0;
33447c478bd9Sstevel@tonic-gate out:
33457c478bd9Sstevel@tonic-gate 	free(cip->pwbuf);
33467c478bd9Sstevel@tonic-gate 	cip->pwbuf = NULL;
33477c478bd9Sstevel@tonic-gate 	return (ret);
33487c478bd9Sstevel@tonic-gate }
33497c478bd9Sstevel@tonic-gate 
33507c478bd9Sstevel@tonic-gate void
33517c478bd9Sstevel@tonic-gate restarter_free_method_context(struct method_context *mcp)
33527c478bd9Sstevel@tonic-gate {
33537c478bd9Sstevel@tonic-gate 	size_t i;
33547c478bd9Sstevel@tonic-gate 
33557c478bd9Sstevel@tonic-gate 	if (mcp->lpriv_set != NULL)
33567c478bd9Sstevel@tonic-gate 		priv_freeset(mcp->lpriv_set);
33577c478bd9Sstevel@tonic-gate 	if (mcp->priv_set != NULL)
33587c478bd9Sstevel@tonic-gate 		priv_freeset(mcp->priv_set);
33597c478bd9Sstevel@tonic-gate 
33607c478bd9Sstevel@tonic-gate 	if (mcp->env != NULL) {
33617c478bd9Sstevel@tonic-gate 		for (i = 0; i < mcp->env_sz; i++)
33627c478bd9Sstevel@tonic-gate 			free(mcp->env[i]);
33637c478bd9Sstevel@tonic-gate 		free(mcp->env);
33647c478bd9Sstevel@tonic-gate 	}
33657c478bd9Sstevel@tonic-gate 
33667c478bd9Sstevel@tonic-gate 	free(mcp->working_dir);
33677c478bd9Sstevel@tonic-gate 	free(mcp->corefile_pattern);
33687c478bd9Sstevel@tonic-gate 	free(mcp->project);
33697c478bd9Sstevel@tonic-gate 	free(mcp->resource_pool);
33707c478bd9Sstevel@tonic-gate 	free(mcp);
33717c478bd9Sstevel@tonic-gate }
33727c478bd9Sstevel@tonic-gate 
33737c478bd9Sstevel@tonic-gate /*
33747c478bd9Sstevel@tonic-gate  * Method keyword functions
33757c478bd9Sstevel@tonic-gate  */
33767c478bd9Sstevel@tonic-gate 
33777c478bd9Sstevel@tonic-gate int
33787c478bd9Sstevel@tonic-gate restarter_is_null_method(const char *meth)
33797c478bd9Sstevel@tonic-gate {
33807c478bd9Sstevel@tonic-gate 	return (strcmp(meth, MKW_TRUE) == 0);
33817c478bd9Sstevel@tonic-gate }
33827c478bd9Sstevel@tonic-gate 
33837c478bd9Sstevel@tonic-gate static int
33847c478bd9Sstevel@tonic-gate is_kill_method(const char *method, const char *kill_str,
33857c478bd9Sstevel@tonic-gate     size_t kill_str_len)
33867c478bd9Sstevel@tonic-gate {
33877c478bd9Sstevel@tonic-gate 	const char *cp;
33887c478bd9Sstevel@tonic-gate 	int sig;
33897c478bd9Sstevel@tonic-gate 
33907c478bd9Sstevel@tonic-gate 	if (strncmp(method, kill_str, kill_str_len) != 0 ||
33917c478bd9Sstevel@tonic-gate 	    (method[kill_str_len] != '\0' &&
33927c478bd9Sstevel@tonic-gate 	    !isspace(method[kill_str_len])))
33937c478bd9Sstevel@tonic-gate 		return (-1);
33947c478bd9Sstevel@tonic-gate 
33957c478bd9Sstevel@tonic-gate 	cp = method + kill_str_len;
33967c478bd9Sstevel@tonic-gate 	while (*cp != '\0' && isspace(*cp))
33977c478bd9Sstevel@tonic-gate 		++cp;
33987c478bd9Sstevel@tonic-gate 
33997c478bd9Sstevel@tonic-gate 	if (*cp == '\0')
34007c478bd9Sstevel@tonic-gate 		return (SIGTERM);
34017c478bd9Sstevel@tonic-gate 
34027c478bd9Sstevel@tonic-gate 	if (*cp != '-')
34037c478bd9Sstevel@tonic-gate 		return (-1);
34047c478bd9Sstevel@tonic-gate 
34057c478bd9Sstevel@tonic-gate 	return (str2sig(cp + 1, &sig) == 0 ? sig : -1);
34067c478bd9Sstevel@tonic-gate }
34077c478bd9Sstevel@tonic-gate 
34087c478bd9Sstevel@tonic-gate int
34097c478bd9Sstevel@tonic-gate restarter_is_kill_proc_method(const char *method)
34107c478bd9Sstevel@tonic-gate {
34117c478bd9Sstevel@tonic-gate 	return (is_kill_method(method, MKW_KILL_PROC,
34127c478bd9Sstevel@tonic-gate 	    sizeof (MKW_KILL_PROC) - 1));
34137c478bd9Sstevel@tonic-gate }
34147c478bd9Sstevel@tonic-gate 
34157c478bd9Sstevel@tonic-gate int
34167c478bd9Sstevel@tonic-gate restarter_is_kill_method(const char *method)
34177c478bd9Sstevel@tonic-gate {
34187c478bd9Sstevel@tonic-gate 	return (is_kill_method(method, MKW_KILL, sizeof (MKW_KILL) - 1));
34197c478bd9Sstevel@tonic-gate }
34207c478bd9Sstevel@tonic-gate 
34217c478bd9Sstevel@tonic-gate /*
34227c478bd9Sstevel@tonic-gate  * Stubs for now.
34237c478bd9Sstevel@tonic-gate  */
34247c478bd9Sstevel@tonic-gate 
34257c478bd9Sstevel@tonic-gate /* ARGSUSED */
34267c478bd9Sstevel@tonic-gate int
34277c478bd9Sstevel@tonic-gate restarter_event_get_enabled(restarter_event_t *e)
34287c478bd9Sstevel@tonic-gate {
34297c478bd9Sstevel@tonic-gate 	return (-1);
34307c478bd9Sstevel@tonic-gate }
34317c478bd9Sstevel@tonic-gate 
34327c478bd9Sstevel@tonic-gate /* ARGSUSED */
34337c478bd9Sstevel@tonic-gate uint64_t
34347c478bd9Sstevel@tonic-gate restarter_event_get_seq(restarter_event_t *e)
34357c478bd9Sstevel@tonic-gate {
34367c478bd9Sstevel@tonic-gate 	return (-1);
34377c478bd9Sstevel@tonic-gate }
34387c478bd9Sstevel@tonic-gate 
34397c478bd9Sstevel@tonic-gate /* ARGSUSED */
34407c478bd9Sstevel@tonic-gate void
34417c478bd9Sstevel@tonic-gate restarter_event_get_time(restarter_event_t *e, hrtime_t *time)
34427c478bd9Sstevel@tonic-gate {
34437c478bd9Sstevel@tonic-gate }
3444eb1a3463STruong Nguyen 
3445eb1a3463STruong Nguyen /*
3446eb1a3463STruong Nguyen  * Check for and validate fmri specified in restarter_actions/auxiliary_fmri
3447eb1a3463STruong Nguyen  * 0 - Success
3448eb1a3463STruong Nguyen  * 1 - Failure
3449eb1a3463STruong Nguyen  */
3450eb1a3463STruong Nguyen int
3451eb1a3463STruong Nguyen restarter_inst_validate_ractions_aux_fmri(scf_instance_t *inst)
3452eb1a3463STruong Nguyen {
3453eb1a3463STruong Nguyen 	scf_handle_t *h;
3454eb1a3463STruong Nguyen 	scf_propertygroup_t *pg;
3455eb1a3463STruong Nguyen 	scf_property_t *prop;
3456eb1a3463STruong Nguyen 	scf_value_t *val;
3457eb1a3463STruong Nguyen 	char *aux_fmri;
3458eb1a3463STruong Nguyen 	size_t size = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH);
3459eb1a3463STruong Nguyen 	int ret = 1;
3460eb1a3463STruong Nguyen 
3461eb1a3463STruong Nguyen 	if ((aux_fmri = malloc(size)) == NULL)
3462eb1a3463STruong Nguyen 		return (1);
3463eb1a3463STruong Nguyen 
3464eb1a3463STruong Nguyen 	h = scf_instance_handle(inst);
3465eb1a3463STruong Nguyen 
3466eb1a3463STruong Nguyen 	pg = scf_pg_create(h);
3467eb1a3463STruong Nguyen 	prop = scf_property_create(h);
3468eb1a3463STruong Nguyen 	val = scf_value_create(h);
3469eb1a3463STruong Nguyen 	if (pg == NULL || prop == NULL || val == NULL)
3470eb1a3463STruong Nguyen 		goto out;
3471eb1a3463STruong Nguyen 
3472eb1a3463STruong Nguyen 	if (instance_get_or_add_pg(inst, SCF_PG_RESTARTER_ACTIONS,
3473eb1a3463STruong Nguyen 	    SCF_PG_RESTARTER_ACTIONS_TYPE, SCF_PG_RESTARTER_ACTIONS_FLAGS,
3474eb1a3463STruong Nguyen 	    pg) != SCF_SUCCESS)
3475eb1a3463STruong Nguyen 		goto out;
3476eb1a3463STruong Nguyen 
3477eb1a3463STruong Nguyen 	if (get_astring_val(pg, SCF_PROPERTY_AUX_FMRI, aux_fmri, size,
3478eb1a3463STruong Nguyen 	    prop, val) != SCF_SUCCESS)
3479eb1a3463STruong Nguyen 		goto out;
3480eb1a3463STruong Nguyen 
3481eb1a3463STruong Nguyen 	if (scf_parse_fmri(aux_fmri, NULL, NULL, NULL, NULL, NULL,
3482eb1a3463STruong Nguyen 	    NULL) != SCF_SUCCESS)
3483eb1a3463STruong Nguyen 		goto out;
3484eb1a3463STruong Nguyen 
3485eb1a3463STruong Nguyen 	ret = 0;
3486eb1a3463STruong Nguyen 
3487eb1a3463STruong Nguyen out:
3488eb1a3463STruong Nguyen 	free(aux_fmri);
3489eb1a3463STruong Nguyen 	scf_value_destroy(val);
3490eb1a3463STruong Nguyen 	scf_property_destroy(prop);
3491eb1a3463STruong Nguyen 	scf_pg_destroy(pg);
3492eb1a3463STruong Nguyen 	return (ret);
3493eb1a3463STruong Nguyen }
3494eb1a3463STruong Nguyen 
3495eb1a3463STruong Nguyen /*
3496eb1a3463STruong Nguyen  * Get instance's boolean value in restarter_actions/auxiliary_tty
3497eb1a3463STruong Nguyen  * Return -1 on failure
3498eb1a3463STruong Nguyen  */
3499eb1a3463STruong Nguyen int
3500eb1a3463STruong Nguyen restarter_inst_ractions_from_tty(scf_instance_t *inst)
3501eb1a3463STruong Nguyen {
3502eb1a3463STruong Nguyen 	scf_handle_t *h;
3503eb1a3463STruong Nguyen 	scf_propertygroup_t *pg;
3504eb1a3463STruong Nguyen 	scf_property_t *prop;
3505eb1a3463STruong Nguyen 	scf_value_t *val;
3506eb1a3463STruong Nguyen 	uint8_t	has_tty;
3507eb1a3463STruong Nguyen 	int ret = -1;
3508eb1a3463STruong Nguyen 
3509eb1a3463STruong Nguyen 	h = scf_instance_handle(inst);
3510eb1a3463STruong Nguyen 	pg = scf_pg_create(h);
3511eb1a3463STruong Nguyen 	prop = scf_property_create(h);
3512eb1a3463STruong Nguyen 	val = scf_value_create(h);
3513eb1a3463STruong Nguyen 	if (pg == NULL || prop == NULL || val == NULL)
3514eb1a3463STruong Nguyen 		goto out;
3515eb1a3463STruong Nguyen 
3516eb1a3463STruong Nguyen 	if (instance_get_or_add_pg(inst, SCF_PG_RESTARTER_ACTIONS,
3517eb1a3463STruong Nguyen 	    SCF_PG_RESTARTER_ACTIONS_TYPE, SCF_PG_RESTARTER_ACTIONS_FLAGS,
3518eb1a3463STruong Nguyen 	    pg) != SCF_SUCCESS)
3519eb1a3463STruong Nguyen 		goto out;
3520eb1a3463STruong Nguyen 
3521eb1a3463STruong Nguyen 	if (get_boolean_val(pg, SCF_PROPERTY_AUX_TTY, &has_tty, prop,
3522eb1a3463STruong Nguyen 	    val) != SCF_SUCCESS)
3523eb1a3463STruong Nguyen 		goto out;
3524eb1a3463STruong Nguyen 
3525eb1a3463STruong Nguyen 	ret = has_tty;
3526eb1a3463STruong Nguyen 
3527eb1a3463STruong Nguyen out:
3528eb1a3463STruong Nguyen 	scf_value_destroy(val);
3529eb1a3463STruong Nguyen 	scf_property_destroy(prop);
3530eb1a3463STruong Nguyen 	scf_pg_destroy(pg);
3531eb1a3463STruong Nguyen 	return (ret);
3532eb1a3463STruong Nguyen }
3533eb1a3463STruong Nguyen 
3534eb1a3463STruong Nguyen static int
3535eb1a3463STruong Nguyen restarter_inst_set_astring_prop(scf_instance_t *inst, const char *pgname,
3536eb1a3463STruong Nguyen     const char *pgtype, uint32_t pgflags, const char *pname, const char *str)
3537eb1a3463STruong Nguyen {
3538eb1a3463STruong Nguyen 	scf_handle_t *h;
3539eb1a3463STruong Nguyen 	scf_propertygroup_t *pg;
3540eb1a3463STruong Nguyen 	scf_transaction_t *t;
3541eb1a3463STruong Nguyen 	scf_transaction_entry_t *e;
3542eb1a3463STruong Nguyen 	scf_value_t *v;
3543eb1a3463STruong Nguyen 	int ret = 1, r;
3544eb1a3463STruong Nguyen 
3545eb1a3463STruong Nguyen 	h = scf_instance_handle(inst);
3546eb1a3463STruong Nguyen 
3547eb1a3463STruong Nguyen 	pg = scf_pg_create(h);
3548eb1a3463STruong Nguyen 	t = scf_transaction_create(h);
3549eb1a3463STruong Nguyen 	e = scf_entry_create(h);
3550eb1a3463STruong Nguyen 	v = scf_value_create(h);
3551eb1a3463STruong Nguyen 	if (pg == NULL || t == NULL || e == NULL || v == NULL)
3552eb1a3463STruong Nguyen 		goto out;
3553eb1a3463STruong Nguyen 
3554eb1a3463STruong Nguyen 	if (instance_get_or_add_pg(inst, pgname, pgtype, pgflags, pg))
3555eb1a3463STruong Nguyen 		goto out;
3556eb1a3463STruong Nguyen 
3557eb1a3463STruong Nguyen 	if (scf_value_set_astring(v, str) != SCF_SUCCESS)
3558eb1a3463STruong Nguyen 		goto out;
3559eb1a3463STruong Nguyen 
3560eb1a3463STruong Nguyen 	for (;;) {
3561eb1a3463STruong Nguyen 		if (scf_transaction_start(t, pg) != 0)
3562eb1a3463STruong Nguyen 			goto out;
3563eb1a3463STruong Nguyen 
3564eb1a3463STruong Nguyen 		if (tx_set_value(t, e, pname, SCF_TYPE_ASTRING, v) != 0)
3565eb1a3463STruong Nguyen 			goto out;
3566eb1a3463STruong Nguyen 
3567eb1a3463STruong Nguyen 		if ((r = scf_transaction_commit(t)) == 1)
3568eb1a3463STruong Nguyen 			break;
3569eb1a3463STruong Nguyen 
3570eb1a3463STruong Nguyen 		if (r == -1)
3571eb1a3463STruong Nguyen 			goto out;
3572eb1a3463STruong Nguyen 
3573eb1a3463STruong Nguyen 		scf_transaction_reset(t);
3574eb1a3463STruong Nguyen 		if (scf_pg_update(pg) == -1)
3575eb1a3463STruong Nguyen 			goto out;
3576eb1a3463STruong Nguyen 	}
3577eb1a3463STruong Nguyen 	ret = 0;
3578eb1a3463STruong Nguyen 
3579eb1a3463STruong Nguyen out:
3580eb1a3463STruong Nguyen 	scf_transaction_destroy(t);
3581eb1a3463STruong Nguyen 	scf_entry_destroy(e);
3582eb1a3463STruong Nguyen 	scf_value_destroy(v);
3583eb1a3463STruong Nguyen 	scf_pg_destroy(pg);
3584eb1a3463STruong Nguyen 
3585eb1a3463STruong Nguyen 	return (ret);
3586eb1a3463STruong Nguyen }
3587eb1a3463STruong Nguyen 
3588eb1a3463STruong Nguyen int
3589eb1a3463STruong Nguyen restarter_inst_set_aux_fmri(scf_instance_t *inst)
3590eb1a3463STruong Nguyen {
3591eb1a3463STruong Nguyen 	scf_handle_t *h;
3592eb1a3463STruong Nguyen 	scf_propertygroup_t *pg;
3593eb1a3463STruong Nguyen 	scf_property_t *prop;
3594eb1a3463STruong Nguyen 	scf_value_t *val;
3595eb1a3463STruong Nguyen 	char *aux_fmri;
3596eb1a3463STruong Nguyen 	size_t size = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH);
3597eb1a3463STruong Nguyen 	int ret = 1;
3598eb1a3463STruong Nguyen 
3599eb1a3463STruong Nguyen 	if ((aux_fmri = malloc(size)) == NULL)
3600eb1a3463STruong Nguyen 		return (1);
3601eb1a3463STruong Nguyen 
3602eb1a3463STruong Nguyen 	h = scf_instance_handle(inst);
3603eb1a3463STruong Nguyen 
3604eb1a3463STruong Nguyen 	pg = scf_pg_create(h);
3605eb1a3463STruong Nguyen 	prop = scf_property_create(h);
3606eb1a3463STruong Nguyen 	val = scf_value_create(h);
3607eb1a3463STruong Nguyen 	if (pg == NULL || prop == NULL || val == NULL)
3608eb1a3463STruong Nguyen 		goto out;
3609eb1a3463STruong Nguyen 
3610eb1a3463STruong Nguyen 	/*
3611eb1a3463STruong Nguyen 	 * Get auxiliary_fmri value from restarter_actions pg
3612eb1a3463STruong Nguyen 	 */
3613eb1a3463STruong Nguyen 	if (instance_get_or_add_pg(inst, SCF_PG_RESTARTER_ACTIONS,
3614eb1a3463STruong Nguyen 	    SCF_PG_RESTARTER_ACTIONS_TYPE, SCF_PG_RESTARTER_ACTIONS_FLAGS,
3615eb1a3463STruong Nguyen 	    pg) != SCF_SUCCESS)
3616eb1a3463STruong Nguyen 		goto out;
3617eb1a3463STruong Nguyen 
3618eb1a3463STruong Nguyen 	if (get_astring_val(pg, SCF_PROPERTY_AUX_FMRI, aux_fmri, size,
3619eb1a3463STruong Nguyen 	    prop, val) != SCF_SUCCESS)
3620eb1a3463STruong Nguyen 		goto out;
3621eb1a3463STruong Nguyen 
3622eb1a3463STruong Nguyen 	/*
3623eb1a3463STruong Nguyen 	 * Populate restarter/auxiliary_fmri with the obtained fmri.
3624eb1a3463STruong Nguyen 	 */
3625eb1a3463STruong Nguyen 	ret = restarter_inst_set_astring_prop(inst, SCF_PG_RESTARTER,
3626eb1a3463STruong Nguyen 	    SCF_PG_RESTARTER_TYPE, SCF_PG_RESTARTER_FLAGS,
3627eb1a3463STruong Nguyen 	    SCF_PROPERTY_AUX_FMRI, aux_fmri);
3628eb1a3463STruong Nguyen 
3629eb1a3463STruong Nguyen out:
3630eb1a3463STruong Nguyen 	free(aux_fmri);
3631eb1a3463STruong Nguyen 	scf_value_destroy(val);
3632eb1a3463STruong Nguyen 	scf_property_destroy(prop);
3633eb1a3463STruong Nguyen 	scf_pg_destroy(pg);
3634eb1a3463STruong Nguyen 	return (ret);
3635eb1a3463STruong Nguyen }
3636eb1a3463STruong Nguyen 
3637eb1a3463STruong Nguyen int
3638eb1a3463STruong Nguyen restarter_inst_reset_aux_fmri(scf_instance_t *inst)
3639eb1a3463STruong Nguyen {
3640eb1a3463STruong Nguyen 	return (scf_instance_delete_prop(inst,
3641eb1a3463STruong Nguyen 	    SCF_PG_RESTARTER, SCF_PROPERTY_AUX_FMRI));
3642eb1a3463STruong Nguyen }
3643eb1a3463STruong Nguyen 
3644eb1a3463STruong Nguyen int
3645eb1a3463STruong Nguyen restarter_inst_reset_ractions_aux_fmri(scf_instance_t *inst)
3646eb1a3463STruong Nguyen {
3647eb1a3463STruong Nguyen 	return (scf_instance_delete_prop(inst,
3648eb1a3463STruong Nguyen 	    SCF_PG_RESTARTER_ACTIONS, SCF_PROPERTY_AUX_FMRI));
3649eb1a3463STruong Nguyen }
3650