1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
23 * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2015, Joyent, Inc.
25 */
26
27/*
28 * startd.c - the master restarter
29 *
30 * svc.startd comprises two halves.  The graph engine is based in graph.c and
31 * maintains the service dependency graph based on the information in the
32 * repository.  For each service it also tracks the current state and the
33 * restarter responsible for the service.  Based on the graph, events from the
34 * repository (mostly administrative requests from svcadm), and messages from
35 * the restarters, the graph engine makes decisions about how the services
36 * should be manipulated and sends commands to the appropriate restarters.
37 * Communication between the graph engine and the restarters is embodied in
38 * protocol.c.
39 *
40 * The second half of svc.startd is the restarter for services managed by
41 * svc.startd and is primarily contained in restarter.c.  It responds to graph
42 * engine commands by executing methods, updating the repository, and sending
43 * feedback (mostly state updates) to the graph engine.
44 *
45 * Overview of the SMF Architecture
46 *
47 * There are a few different components that make up SMF and are responsible
48 * for different pieces of functionality that are used:
49 *
50 * svc.startd(1M): A daemon that is in charge of starting, stopping, and
51 *     restarting services and instances.
52 * svc.configd(1M): A daemon that manages the repository that stores
53 *     information, property groups, and state of the different services and
54 *     instances.
55 * libscf(3LIB): A C library that provides the glue for communicating,
56 *     accessing, and updating information about services and instances.
57 * svccfg(1M): A utility to add and remove services as well as change the
58 *     properties associated with different services and instances.
59 * svcadm(1M): A utility to control the different instance of a service. You
60 *     can use this to enable and disable them among some other useful things.
61 * svcs(1): A utility that reports on the status of various services on the
62 *     system.
63 *
64 * The following block diagram explains how these components communicate:
65 *
66 * The SMF Block Diagram
67 *                                                       Repository
68 *   This attempts to show       +---------+             +--------+
69 *   the relations between       |         |     SQL     |        |
70 *   the different pieces        | configd |<----------->| SQLite |
71 *   that make SMF work and      |         | Transaction |        |
72 *   users/administrators        +---------+             +--------+
73 *   call into.                   ^      ^
74 *                                |      |
75 *                   door_call(3C)|      | door_call(3C)
76 *                                |      |
77 *                                v      v
78 *      +----------+     +--------+      +--------+      +----------+
79 *      |          |     |        |      |        |      |  svccfg  |
80 *      |  startd  |<--->| libscf |      | libscf |<---->|  svcadm  |
81 *      |          |     | (3LIB) |      | (3LIB) |      |   svcs   |
82 *      +----------+     +--------+      +--------+      +----------+
83 *        ^      ^
84 *        |      | fork(2)/exec(2)
85 *        |      | libcontract(3LIB)
86 *        v      v                           Various System/User services
87 *       +-------------------------------------------------------------------+
88 *       | system/filesystem/local:default      system/coreadm:default       |
89 *       | network/loopback:default             system/zones:default         |
90 *       | milestone/multi-user:default         system/cron:default          |
91 *       | system/console-login:default         network/ssh:default          |
92 *       | system/pfexec:default                system/svc/restarter:default |
93 *       +-------------------------------------------------------------------+
94 *
95 * Chatting with Configd and Sharing Repository Information
96 *
97 * As you run commands with svcs, svccfg, and svcadm, they are all creating a
98 * libscf handle to communicate with configd. As calls are made via libscf they
99 * ultimately go and talk to configd to get information. However, how we
100 * actually are talking to configd is not as straightforward as it appears.
101 *
102 * When configd starts up it creates a door located at
103 * /etc/svc/volatile/repository_door. This door runs the routine called
104 * main_switcher() from usr/src/cmd/svc/configd/maindoor.c. When you first
105 * invoke svc(cfg|s|adm), one of the first things that occurs is creating a
106 * scf_handle_t and binding it to configd by calling scf_handle_bind(). This
107 * function makes a door call to configd and gets returned a new file
108 * descriptor. This file descriptor is itself another door which calls into
109 * configd's client_switcher(). This is the door that is actually used when
110 * getting and fetching properties, and many other useful things.
111 *
112 * svc.startd needs a way to notice the changes that occur to the repository.
113 * For example, if you enabled a service that was not previously running, it's
114 * up to startd to notice that this has happened, check dependencies, and
115 * eventually start up the service. The way it gets these notifications is via
116 * a thread who's sole purpose in life is to call _scf_notify_wait(). This
117 * function acts like poll(2) but for changes that occur in the repository.
118 * Once this thread gets the event, it dispatches the event appropriately.
119 *
120 * The Events of svc.startd
121 *
122 * svc.startd has to handle a lot of complexity. Understanding how you go from
123 * getting the notification that a service was enabled to actually enabling it
124 * is not obvious from a cursory glance. The first thing to keep in mind is
125 * that startd maintains a graph of all the related services and instances so
126 * it can keep track of what is enabled, what dependencies exist, etc. all so
127 * that it can answer the question of what is affected by a change. Internally
128 * there are a lot of different queues for events, threads to process these
129 * queues, and different paths to have events enter these queues. What follows
130 * is a diagram that attempts to explain some of those paths, though it's
131 * important to note that for some of these pieces, such as the graph and
132 * vertex events, there are many additional ways and code paths these threads
133 * and functions can take. And yes, restarter_event_enqueue() is not the same
134 * thing as restarter_queue_event().
135 *
136 *   Threads/Functions                 Queues                  Threads/Functions
137 *
138 * called by various
139 *     +----------------+             +-------+                  +-------------+
140 * --->| graph_protocol | graph_event | graph |   graph_event_   | graph_event |
141 * --->| _send_event()  |------------>| event |----------------->| _thread     |
142 *     +----------------+ _enqueue()  | queue |   dequeue()      +-------------+
143 *                                    +-------+                         |
144 *  _scf_notify_wait()                               vertex_send_event()|
145 *  |                                                                   v
146 *  |  +------------------+                              +--------------------+
147 *  +->| repository_event | vertex_send_event()          | restarter_protocol |
148 *     | _thread          |----------------------------->| _send_event()      |
149 *     +------------------+                              +--------------------+
150 *                                                          |    | out to other
151 *                restarter_                     restarter_ |    | restarters
152 *                event_dequeue() +-----------+  event_     |    | not startd
153 *               +----------------| restarter |<------------+    +------------->
154 *               v                |   event   |  enqueue()
155 *      +-----------------+       |   queue   |             +------------------>
156 *      | restarter_event |       +-----------+             |+----------------->
157 *      | _thread         |                                 ||+---------------->
158 *      +-----------------+                                 ||| start/stop inst
159 *               |               +--------------+       +--------------------+
160 *               |               |   instance   |       | restarter_process_ |
161 *               +-------------->|    event     |------>| events             |
162 *                restarter_     |    queue     |       | per-instance lwp   |
163 *                queue_event()  +--------------+       +--------------------+
164 *                                                          ||| various funcs
165 *                                                          ||| controlling
166 *                                                          ||| instance state
167 *                                                          ||+--------------->
168 *                                                          |+---------------->
169 *                                                          +----------------->
170 *
171 * What's important to take away is that there is a queue for each instance on
172 * the system that handles events related to dealing directly with that
173 * instance and that events can be added to it because of changes to properties
174 * that are made to configd and acted upon asynchronously by startd.
175 *
176 * Error handling
177 *
178 * In general, when svc.startd runs out of memory it reattempts a few times,
179 * sleeping inbetween, before giving up and exiting (see startd_alloc_retry()).
180 * When a repository connection is broken (libscf calls fail with
181 * SCF_ERROR_CONNECTION_BROKEN, librestart and internal functions return
182 * ECONNABORTED), svc.startd calls libscf_rebind_handle(), which coordinates
183 * with the svc.configd-restarting thread, fork_configd_thread(), via
184 * st->st_configd_live_cv, and rebinds the repository handle.  Doing so resets
185 * all libscf state associated with that handle, so functions which do this
186 * should communicate the event to their callers (usually by returning
187 * ECONNRESET) so they may reset their state appropriately.
188 *
189 * External references
190 *
191 * svc.configd generates special security audit events for changes to some
192 * restarter related properties.  See the special_props_list array in
193 * usr/src/cmd/svc/configd/rc_node.c for the properties that cause these audit
194 * events.  If you change the semantics of these propereties within startd, you
195 * will probably need to update rc_node.c
196 */
197
198#include <stdio.h>
199#include <stdio_ext.h>
200#include <sys/mnttab.h>		/* uses FILE * without including stdio.h */
201#include <alloca.h>
202#include <sys/mount.h>
203#include <sys/stat.h>
204#include <sys/types.h>
205#include <sys/wait.h>
206#include <assert.h>
207#include <errno.h>
208#include <fcntl.h>
209#include <ftw.h>
210#include <libintl.h>
211#include <libscf.h>
212#include <libscf_priv.h>
213#include <libuutil.h>
214#include <locale.h>
215#include <poll.h>
216#include <pthread.h>
217#include <signal.h>
218#include <stdarg.h>
219#include <stdlib.h>
220#include <string.h>
221#include <strings.h>
222#include <unistd.h>
223
224#include "startd.h"
225#include "protocol.h"
226
227ssize_t max_scf_name_size;
228ssize_t max_scf_fmri_size;
229ssize_t max_scf_value_size;
230
231mode_t fmask;
232mode_t dmask;
233
234graph_update_t *gu;
235restarter_update_t *ru;
236
237startd_state_t *st;
238
239boolean_t booting_to_single_user = B_FALSE;
240
241const char * const admin_actions[] = {
242    SCF_PROPERTY_DEGRADED,
243    SCF_PROPERTY_MAINT_OFF,
244    SCF_PROPERTY_MAINT_ON,
245    SCF_PROPERTY_MAINT_ON_IMMEDIATE,
246    SCF_PROPERTY_REFRESH,
247    SCF_PROPERTY_RESTART
248};
249
250const int admin_events[NACTIONS] = {
251    RESTARTER_EVENT_TYPE_ADMIN_DEGRADED,
252    RESTARTER_EVENT_TYPE_ADMIN_MAINT_OFF,
253    RESTARTER_EVENT_TYPE_ADMIN_MAINT_ON,
254    RESTARTER_EVENT_TYPE_ADMIN_MAINT_ON_IMMEDIATE,
255    RESTARTER_EVENT_TYPE_ADMIN_REFRESH,
256    RESTARTER_EVENT_TYPE_ADMIN_RESTART
257};
258
259const char * const instance_state_str[] = {
260	"none",
261	"uninitialized",
262	"maintenance",
263	"offline",
264	"disabled",
265	"online",
266	"degraded"
267};
268
269static int finished = 0;
270static int opt_reconfig = 0;
271static uint8_t prop_reconfig = 0;
272
273#define	INITIAL_REBIND_ATTEMPTS	5
274#define	INITIAL_REBIND_DELAY	3
275
276pthread_mutexattr_t mutex_attrs;
277
278#ifdef DEBUG
279const char *
280_umem_debug_init(void)
281{
282	return ("default,verbose");	/* UMEM_DEBUG setting */
283}
284
285const char *
286_umem_logging_init(void)
287{
288	return ("fail,contents");	/* UMEM_LOGGING setting */
289}
290#endif
291
292const char *
293_umem_options_init(void)
294{
295	/*
296	 * To reduce our memory footprint, we set our UMEM_OPTIONS to indicate
297	 * that we do not wish to have per-CPU magazines -- if svc.startd is so
298	 * hot on CPU such that this becomes a scalability problem, there are
299	 * likely deeper things amiss...
300	 */
301	return ("nomagazines");		/* UMEM_OPTIONS setting */
302}
303
304/*
305 * startd_alloc_retry()
306 *   Wrapper for allocation functions.  Retries with a decaying time
307 *   value on failure to allocate, and aborts startd if failure is
308 *   persistent.
309 */
310void *
311startd_alloc_retry(void *f(size_t, int), size_t sz)
312{
313	void *p;
314	uint_t try, msecs;
315
316	p = f(sz, UMEM_DEFAULT);
317	if (p != NULL || sz == 0)
318		return (p);
319
320	msecs = ALLOC_DELAY;
321
322	for (try = 0; p == NULL && try < ALLOC_RETRY; ++try) {
323		(void) poll(NULL, 0, msecs);
324		msecs *= ALLOC_DELAY_MULT;
325		p = f(sz, UMEM_DEFAULT);
326		if (p != NULL)
327			return (p);
328	}
329
330	uu_die("Insufficient memory.\n");
331	/* NOTREACHED */
332}
333
334void *
335safe_realloc(void *p, size_t sz)
336{
337	uint_t try, msecs;
338
339	p = realloc(p, sz);
340	if (p != NULL || sz == 0)
341		return (p);
342
343	msecs = ALLOC_DELAY;
344
345	for (try = 0; errno == EAGAIN && try < ALLOC_RETRY; ++try) {
346		(void) poll(NULL, 0, msecs);
347		p = realloc(p, sz);
348		if (p != NULL)
349			return (p);
350		msecs *= ALLOC_DELAY_MULT;
351	}
352
353	uu_die("Insufficient memory.\n");
354	/* NOTREACHED */
355}
356
357char *
358safe_strdup(const char *s)
359{
360	uint_t try, msecs;
361	char *d;
362
363	d = strdup(s);
364	if (d != NULL)
365		return (d);
366
367	msecs = ALLOC_DELAY;
368
369	for (try = 0;
370	    (errno == EAGAIN || errno == ENOMEM) && try < ALLOC_RETRY;
371	    ++try) {
372		(void) poll(NULL, 0, msecs);
373		d = strdup(s);
374		if (d != NULL)
375			return (d);
376		msecs *= ALLOC_DELAY_MULT;
377	}
378
379	uu_die("Insufficient memory.\n");
380	/* NOTREACHED */
381}
382
383
384void
385startd_free(void *p, size_t sz)
386{
387	umem_free(p, sz);
388}
389
390/*
391 * Creates a uu_list_pool_t with the same retry policy as startd_alloc().
392 * Only returns NULL for UU_ERROR_UNKNOWN_FLAG and UU_ERROR_NOT_SUPPORTED.
393 */
394uu_list_pool_t *
395startd_list_pool_create(const char *name, size_t e, size_t o,
396    uu_compare_fn_t *f, uint32_t flags)
397{
398	uu_list_pool_t *pool;
399	uint_t try, msecs;
400
401	pool = uu_list_pool_create(name, e, o, f, flags);
402	if (pool != NULL)
403		return (pool);
404
405	msecs = ALLOC_DELAY;
406
407	for (try = 0; uu_error() == UU_ERROR_NO_MEMORY && try < ALLOC_RETRY;
408	    ++try) {
409		(void) poll(NULL, 0, msecs);
410		pool = uu_list_pool_create(name, e, o, f, flags);
411		if (pool != NULL)
412			return (pool);
413		msecs *= ALLOC_DELAY_MULT;
414	}
415
416	if (try < ALLOC_RETRY)
417		return (NULL);
418
419	uu_die("Insufficient memory.\n");
420	/* NOTREACHED */
421}
422
423/*
424 * Creates a uu_list_t with the same retry policy as startd_alloc().  Only
425 * returns NULL for UU_ERROR_UNKNOWN_FLAG and UU_ERROR_NOT_SUPPORTED.
426 */
427uu_list_t *
428startd_list_create(uu_list_pool_t *pool, void *parent, uint32_t flags)
429{
430	uu_list_t *list;
431	uint_t try, msecs;
432
433	list = uu_list_create(pool, parent, flags);
434	if (list != NULL)
435		return (list);
436
437	msecs = ALLOC_DELAY;
438
439	for (try = 0; uu_error() == UU_ERROR_NO_MEMORY && try < ALLOC_RETRY;
440	    ++try) {
441		(void) poll(NULL, 0, msecs);
442		list = uu_list_create(pool, parent, flags);
443		if (list != NULL)
444			return (list);
445		msecs *= ALLOC_DELAY_MULT;
446	}
447
448	if (try < ALLOC_RETRY)
449		return (NULL);
450
451	uu_die("Insufficient memory.\n");
452	/* NOTREACHED */
453}
454
455pthread_t
456startd_thread_create(void *(*func)(void *), void *ptr)
457{
458	int err;
459	pthread_t tid;
460
461	err = pthread_create(&tid, NULL, func, ptr);
462	if (err != 0) {
463		assert(err == EAGAIN);
464		uu_die("Could not create thread.\n");
465	}
466
467	err = pthread_detach(tid);
468	assert(err == 0);
469
470	return (tid);
471}
472
473extern int info_events_all;
474
475static int
476read_startd_config(void)
477{
478	scf_handle_t *hndl;
479	scf_instance_t *inst;
480	scf_propertygroup_t *pg;
481	scf_property_t *prop;
482	scf_value_t *val;
483	scf_iter_t *iter, *piter;
484	instance_data_t idata;
485	char *buf, *vbuf;
486	char *startd_options_fmri = uu_msprintf("%s/:properties/options",
487	    SCF_SERVICE_STARTD);
488	char *startd_reconfigure_fmri = uu_msprintf(
489	    "%s/:properties/system/reconfigure", SCF_SERVICE_STARTD);
490	char *env_opts, *lasts, *cp;
491	int bind_fails = 0;
492	int ret = 0, r;
493	uint_t count = 0, msecs = ALLOC_DELAY;
494	size_t sz;
495	ctid_t ctid;
496	uint64_t uint64;
497
498	buf = startd_alloc(max_scf_fmri_size);
499
500	if (startd_options_fmri == NULL || startd_reconfigure_fmri == NULL)
501		uu_die("Allocation failure\n");
502
503	st->st_log_prefix = LOG_PREFIX_EARLY;
504
505	if ((st->st_log_file = getenv("STARTD_DEFAULT_LOG")) == NULL) {
506		st->st_log_file = startd_alloc(strlen(STARTD_DEFAULT_LOG) + 1);
507
508		(void) strcpy(st->st_log_file, STARTD_DEFAULT_LOG);
509	}
510
511	st->st_door_path = getenv("STARTD_ALT_DOOR");
512
513	/*
514	 * Read "options" property group.
515	 */
516	for (hndl = libscf_handle_create_bound(SCF_VERSION); hndl == NULL;
517	    hndl = libscf_handle_create_bound(SCF_VERSION), bind_fails++) {
518		(void) sleep(INITIAL_REBIND_DELAY);
519
520		if (bind_fails > INITIAL_REBIND_ATTEMPTS) {
521			/*
522			 * In the case that we can't bind to the repository
523			 * (which should have been started), we need to allow
524			 * the user into maintenance mode to determine what's
525			 * failed.
526			 */
527			log_framework(LOG_INFO, "Couldn't fetch "
528			    "default settings: %s\n",
529			    scf_strerror(scf_error()));
530
531			ret = -1;
532
533			goto noscfout;
534		}
535	}
536
537	idata.i_fmri = SCF_SERVICE_STARTD;
538	idata.i_state = RESTARTER_STATE_NONE;
539	idata.i_next_state = RESTARTER_STATE_NONE;
540timestamp:
541	switch (r = _restarter_commit_states(hndl, &idata,
542	    RESTARTER_STATE_ONLINE, RESTARTER_STATE_NONE,
543	    restarter_get_str_short(restarter_str_insert_in_graph))) {
544	case 0:
545		break;
546
547	case ENOMEM:
548		++count;
549		if (count < ALLOC_RETRY) {
550			(void) poll(NULL, 0, msecs);
551			msecs *= ALLOC_DELAY_MULT;
552			goto timestamp;
553		}
554
555		uu_die("Insufficient memory.\n");
556		/* NOTREACHED */
557
558	case ECONNABORTED:
559		libscf_handle_rebind(hndl);
560		goto timestamp;
561
562	case ENOENT:
563	case EPERM:
564	case EACCES:
565	case EROFS:
566		log_error(LOG_INFO, "Could set state of %s: %s.\n",
567		    idata.i_fmri, strerror(r));
568		break;
569
570	case EINVAL:
571	default:
572		bad_error("_restarter_commit_states", r);
573	}
574
575	pg = safe_scf_pg_create(hndl);
576	prop = safe_scf_property_create(hndl);
577	val = safe_scf_value_create(hndl);
578	inst = safe_scf_instance_create(hndl);
579
580	/* set startd's restarter properties */
581	if (scf_handle_decode_fmri(hndl, SCF_SERVICE_STARTD, NULL, NULL, inst,
582	    NULL, NULL, SCF_DECODE_FMRI_EXACT) == 0) {
583		(void) libscf_write_start_pid(inst, getpid());
584		ctid = proc_get_ctid();
585		if (ctid != -1) {
586			uint64 = (uint64_t)ctid;
587			(void) libscf_inst_set_count_prop(inst,
588			    SCF_PG_RESTARTER, SCF_PG_RESTARTER_TYPE,
589			    SCF_PG_RESTARTER_FLAGS, SCF_PROPERTY_CONTRACT,
590			    uint64);
591		}
592		(void) libscf_note_method_log(inst, LOG_PREFIX_EARLY,
593		    STARTD_DEFAULT_LOG);
594		(void) libscf_note_method_log(inst, LOG_PREFIX_NORMAL,
595		    STARTD_DEFAULT_LOG);
596	}
597
598	/* Read reconfigure property for recovery. */
599	if (scf_handle_decode_fmri(hndl, startd_reconfigure_fmri, NULL, NULL,
600	    NULL, NULL, prop, 0) != -1 &&
601	    scf_property_get_value(prop, val) == 0)
602		(void) scf_value_get_boolean(val, &prop_reconfig);
603
604	if (scf_handle_decode_fmri(hndl, startd_options_fmri, NULL, NULL, NULL,
605	    pg, NULL, SCF_DECODE_FMRI_TRUNCATE) == -1) {
606		/*
607		 * No configuration options defined.
608		 */
609		if (scf_error() != SCF_ERROR_NOT_FOUND)
610			uu_warn("Couldn't read configuration from 'options' "
611			    "group: %s\n", scf_strerror(scf_error()));
612		goto scfout;
613	}
614
615	/*
616	 * If there is no "options" group defined, then our defaults are fine.
617	 */
618	if (scf_pg_get_name(pg, NULL, 0) < 0)
619		goto scfout;
620
621	/* get info_events_all */
622	info_events_all = libscf_get_info_events_all(pg);
623
624	/* Iterate through. */
625	iter = safe_scf_iter_create(hndl);
626
627	(void) scf_iter_pg_properties(iter, pg);
628
629	piter = safe_scf_iter_create(hndl);
630	vbuf = startd_alloc(max_scf_value_size);
631
632	while ((scf_iter_next_property(iter, prop) == 1)) {
633		scf_type_t ty;
634
635		if (scf_property_get_name(prop, buf, max_scf_fmri_size) < 0)
636			continue;
637
638		if (strcmp(buf, "logging") != 0 &&
639		    strcmp(buf, "boot_messages") != 0)
640			continue;
641
642		if (scf_property_type(prop, &ty) != 0) {
643			switch (scf_error()) {
644			case SCF_ERROR_CONNECTION_BROKEN:
645			default:
646				libscf_handle_rebind(hndl);
647				continue;
648
649			case SCF_ERROR_DELETED:
650				continue;
651
652			case SCF_ERROR_NOT_BOUND:
653			case SCF_ERROR_NOT_SET:
654				bad_error("scf_property_type", scf_error());
655			}
656		}
657
658		if (ty != SCF_TYPE_ASTRING) {
659			uu_warn("property \"options/%s\" is not of type "
660			    "astring; ignored.\n", buf);
661			continue;
662		}
663
664		if (scf_property_get_value(prop, val) != 0) {
665			switch (scf_error()) {
666			case SCF_ERROR_CONNECTION_BROKEN:
667			default:
668				return (ECONNABORTED);
669
670			case SCF_ERROR_DELETED:
671			case SCF_ERROR_NOT_FOUND:
672				return (0);
673
674			case SCF_ERROR_CONSTRAINT_VIOLATED:
675				uu_warn("property \"options/%s\" has multiple "
676				    "values; ignored.\n", buf);
677				continue;
678
679			case SCF_ERROR_PERMISSION_DENIED:
680				uu_warn("property \"options/%s\" cannot be "
681				    "read because startd has insufficient "
682				    "permission; ignored.\n", buf);
683				continue;
684
685			case SCF_ERROR_HANDLE_MISMATCH:
686			case SCF_ERROR_NOT_BOUND:
687			case SCF_ERROR_NOT_SET:
688				bad_error("scf_property_get_value",
689				    scf_error());
690			}
691		}
692
693		if (scf_value_get_astring(val, vbuf, max_scf_value_size) < 0)
694			bad_error("scf_value_get_astring", scf_error());
695
696		if (strcmp("logging", buf) == 0) {
697			if (strcmp("verbose", vbuf) == 0) {
698				st->st_boot_flags = STARTD_BOOT_VERBOSE;
699				st->st_log_level_min = LOG_INFO;
700			} else if (strcmp("debug", vbuf) == 0) {
701				st->st_boot_flags = STARTD_BOOT_VERBOSE;
702				st->st_log_level_min = LOG_DEBUG;
703			} else if (strcmp("quiet", vbuf) == 0) {
704				st->st_log_level_min = LOG_NOTICE;
705			} else {
706				uu_warn("unknown options/logging "
707				    "value '%s' ignored\n", vbuf);
708			}
709
710		} else if (strcmp("boot_messages", buf) == 0) {
711			if (strcmp("quiet", vbuf) == 0) {
712				st->st_boot_flags = STARTD_BOOT_QUIET;
713			} else if (strcmp("verbose", vbuf) == 0) {
714				st->st_boot_flags = STARTD_BOOT_VERBOSE;
715			} else {
716				log_framework(LOG_NOTICE, "unknown "
717				    "options/boot_messages value '%s' "
718				    "ignored\n", vbuf);
719			}
720
721		}
722	}
723
724	startd_free(vbuf, max_scf_value_size);
725	scf_iter_destroy(piter);
726
727	scf_iter_destroy(iter);
728
729scfout:
730	scf_value_destroy(val);
731	scf_pg_destroy(pg);
732	scf_property_destroy(prop);
733	scf_instance_destroy(inst);
734	(void) scf_handle_unbind(hndl);
735	scf_handle_destroy(hndl);
736
737noscfout:
738	startd_free(buf, max_scf_fmri_size);
739	uu_free(startd_options_fmri);
740	uu_free(startd_reconfigure_fmri);
741
742	if (booting_to_single_user) {
743		st->st_subgraph = startd_alloc(max_scf_fmri_size);
744		sz = strlcpy(st->st_subgraph, "milestone/single-user:default",
745		    max_scf_fmri_size);
746		assert(sz < max_scf_fmri_size);
747	}
748
749	/*
750	 * Options passed in as boot arguments override repository defaults.
751	 */
752	env_opts = getenv("SMF_OPTIONS");
753	if (env_opts == NULL)
754		return (ret);
755
756	for (cp = strtok_r(env_opts, ",", &lasts); cp != NULL;
757	    cp = strtok_r(NULL, ",", &lasts)) {
758		if (strcmp(cp, "debug") == 0) {
759			st->st_boot_flags = STARTD_BOOT_VERBOSE;
760			st->st_log_level_min = LOG_DEBUG;
761
762			/* -m debug should send messages to console */
763			st->st_log_flags =
764			    st->st_log_flags | STARTD_LOG_TERMINAL;
765		} else if (strcmp(cp, "verbose") == 0) {
766			st->st_boot_flags = STARTD_BOOT_VERBOSE;
767			st->st_log_level_min = LOG_INFO;
768		} else if (strcmp(cp, "seed") == 0) {
769			uu_warn("SMF option \"%s\" unimplemented.\n", cp);
770		} else if (strcmp(cp, "quiet") == 0) {
771			st->st_log_level_min = LOG_NOTICE;
772		} else if (strncmp(cp, "milestone=",
773		    sizeof ("milestone=") - 1) == 0) {
774			char *mp = cp + sizeof ("milestone=") - 1;
775
776			if (booting_to_single_user)
777				continue;
778
779			if (st->st_subgraph == NULL) {
780				st->st_subgraph =
781				    startd_alloc(max_scf_fmri_size);
782				st->st_subgraph[0] = '\0';
783			}
784
785			if (mp[0] == '\0' || strcmp(mp, "all") == 0) {
786				(void) strcpy(st->st_subgraph, "all");
787			} else if (strcmp(mp, "su") == 0 ||
788			    strcmp(mp, "single-user") == 0) {
789				(void) strcpy(st->st_subgraph,
790				    "milestone/single-user:default");
791			} else if (strcmp(mp, "mu") == 0 ||
792			    strcmp(mp, "multi-user") == 0) {
793				(void) strcpy(st->st_subgraph,
794				    "milestone/multi-user:default");
795			} else if (strcmp(mp, "mus") == 0 ||
796			    strcmp(mp, "multi-user-server") == 0) {
797				(void) strcpy(st->st_subgraph,
798				    "milestone/multi-user-server:default");
799			} else if (strcmp(mp, "none") == 0) {
800				(void) strcpy(st->st_subgraph, "none");
801			} else {
802				log_framework(LOG_NOTICE,
803				    "invalid milestone option value "
804				    "'%s' ignored\n", mp);
805			}
806		} else {
807			uu_warn("Unknown SMF option \"%s\".\n", cp);
808		}
809	}
810
811	return (ret);
812}
813
814/*
815 * void set_boot_env()
816 *
817 * If -r was passed or /reconfigure exists, this is a reconfig
818 * reboot.  We need to make sure that this information is given
819 * to the appropriate services the first time they're started
820 * by setting the system/reconfigure repository property,
821 * as well as pass the _INIT_RECONFIG variable on to the rcS
822 * start method so that legacy services can continue to use it.
823 *
824 * This function must never be called before contract_init(), as
825 * it sets st_initial.  get_startd_config() sets prop_reconfig from
826 * pre-existing repository state.
827 */
828static void
829set_boot_env()
830{
831	struct stat sb;
832	int r;
833
834	/*
835	 * Check if property still is set -- indicates we didn't get
836	 * far enough previously to unset it.  Otherwise, if this isn't
837	 * the first startup, don't re-process /reconfigure or the
838	 * boot flag.
839	 */
840	if (prop_reconfig != 1 && st->st_initial != 1)
841		return;
842
843	/* If /reconfigure exists, also set opt_reconfig. */
844	if (stat("/reconfigure", &sb) != -1)
845		opt_reconfig = 1;
846
847	/* Nothing to do.  Just return. */
848	if (opt_reconfig == 0 && prop_reconfig == 0)
849		return;
850
851	/*
852	 * Set startd's reconfigure property.  This property is
853	 * then cleared by successful completion of the single-user
854	 * milestone.
855	 */
856	if (prop_reconfig != 1) {
857		r = libscf_set_reconfig(1);
858		switch (r) {
859		case 0:
860			break;
861
862		case ENOENT:
863		case EPERM:
864		case EACCES:
865		case EROFS:
866			log_error(LOG_WARNING, "Could not set reconfiguration "
867			    "property: %s\n", strerror(r));
868			break;
869
870		default:
871			bad_error("libscf_set_reconfig", r);
872		}
873	}
874}
875
876static void
877startup(void)
878{
879	ctid_t configd_ctid;
880	int err;
881
882	/*
883	 * Initialize data structures.
884	 */
885	gu = startd_zalloc(sizeof (graph_update_t));
886	ru = startd_zalloc(sizeof (restarter_update_t));
887
888	(void) pthread_cond_init(&st->st_load_cv, NULL);
889	(void) pthread_cond_init(&st->st_configd_live_cv, NULL);
890	(void) pthread_cond_init(&gu->gu_cv, NULL);
891	(void) pthread_cond_init(&gu->gu_freeze_cv, NULL);
892	(void) pthread_cond_init(&ru->restarter_update_cv, NULL);
893	(void) pthread_mutex_init(&st->st_load_lock, &mutex_attrs);
894	(void) pthread_mutex_init(&st->st_configd_live_lock, &mutex_attrs);
895	(void) pthread_mutex_init(&gu->gu_lock, &mutex_attrs);
896	(void) pthread_mutex_init(&gu->gu_freeze_lock, &mutex_attrs);
897	(void) pthread_mutex_init(&ru->restarter_update_lock, &mutex_attrs);
898
899	configd_ctid = contract_init();
900
901	if (configd_ctid != -1)
902		log_framework(LOG_DEBUG, "Existing configd contract %ld; not "
903		    "starting svc.configd\n", configd_ctid);
904
905	/*
906	 * Call utmpx_init() before creating the fork_configd() thread.
907	 */
908	utmpx_init();
909
910	(void) startd_thread_create(fork_configd_thread, (void *)configd_ctid);
911
912	/*
913	 * Await, if necessary, configd's initial arrival.
914	 */
915	MUTEX_LOCK(&st->st_configd_live_lock);
916	while (!st->st_configd_lives) {
917		log_framework(LOG_DEBUG, "Awaiting cv signal on "
918		    "configd_live_cv\n");
919		err = pthread_cond_wait(&st->st_configd_live_cv,
920		    &st->st_configd_live_lock);
921		assert(err == 0);
922	}
923	MUTEX_UNLOCK(&st->st_configd_live_lock);
924
925	wait_init();
926
927	if (read_startd_config())
928		log_framework(LOG_INFO, "svc.configd unable to provide startd "
929		    "optional settings\n");
930
931	log_init();
932	dict_init();
933	timeout_init();
934	restarter_protocol_init();
935	restarter_init();
936
937	/*
938	 * svc.configd is started by fork_configd_thread so repository access is
939	 * available, run early manifest import before continuing with starting
940	 * graph engine and the rest of startd.
941	 */
942	log_framework(LOG_DEBUG, "Calling fork_emi...\n");
943	fork_emi();
944
945	graph_protocol_init();
946	graph_init();
947
948	init_env();
949
950	set_boot_env();
951	restarter_start();
952	graph_engine_start();
953}
954
955static void
956usage(const char *name)
957{
958	uu_warn(gettext("usage: %s [-n]\n"), name);
959	exit(UU_EXIT_USAGE);
960}
961
962static int
963daemonize_start(void)
964{
965	pid_t pid;
966	int fd;
967
968	if ((pid = fork1()) < 0)
969		return (-1);
970
971	if (pid != 0)
972		exit(0);
973
974	(void) close(STDIN_FILENO);
975
976	if ((fd = open("/dev/null", O_RDONLY)) == -1) {
977		uu_warn(gettext("can't connect stdin to /dev/null"));
978	} else if (fd != STDIN_FILENO) {
979		(void) dup2(fd, STDIN_FILENO);
980		startd_close(fd);
981	}
982
983	closefrom(3);
984	(void) dup2(STDERR_FILENO, STDOUT_FILENO);
985
986	(void) setsid();
987	(void) chdir("/");
988
989	/* Use default umask that init handed us, but 022 to create files. */
990	dmask = umask(022);
991	fmask = umask(dmask);
992
993	return (0);
994}
995
996/*ARGSUSED*/
997static void
998die_handler(int sig, siginfo_t *info, void *data)
999{
1000	finished = 1;
1001}
1002
1003int
1004main(int argc, char *argv[])
1005{
1006	int opt;
1007	int daemonize = 1;
1008	struct sigaction act;
1009	sigset_t nullset;
1010	struct stat sb;
1011
1012	(void) uu_setpname(argv[0]);
1013
1014	st = startd_zalloc(sizeof (startd_state_t));
1015
1016	(void) pthread_mutexattr_init(&mutex_attrs);
1017#ifndef	NDEBUG
1018	(void) pthread_mutexattr_settype(&mutex_attrs,
1019	    PTHREAD_MUTEX_ERRORCHECK);
1020#endif
1021
1022	max_scf_name_size = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH);
1023	max_scf_value_size = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH);
1024	max_scf_fmri_size = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH);
1025
1026	if (max_scf_name_size == -1 || max_scf_value_size == -1 ||
1027	    max_scf_value_size == -1)
1028		uu_die("Can't determine repository maximum lengths.\n");
1029
1030	max_scf_name_size++;
1031	max_scf_value_size++;
1032	max_scf_fmri_size++;
1033
1034	st->st_log_flags = STARTD_LOG_FILE | STARTD_LOG_SYSLOG;
1035	st->st_log_level_min = LOG_NOTICE;
1036
1037	while ((opt = getopt(argc, argv, "nrs")) != EOF) {
1038		switch (opt) {
1039		case 'n':
1040			daemonize = 0;
1041			break;
1042		case 'r':			/* reconfiguration boot */
1043			opt_reconfig = 1;
1044			break;
1045		case 's':			/* single-user mode */
1046			booting_to_single_user = B_TRUE;
1047			break;
1048		default:
1049			usage(argv[0]);		/* exits */
1050		}
1051	}
1052
1053	if (optind != argc)
1054		usage(argv[0]);
1055
1056	(void) enable_extended_FILE_stdio(-1, -1);
1057
1058	if (daemonize)
1059		if (daemonize_start() < 0)
1060			uu_die("Can't daemonize\n");
1061
1062	log_init();
1063
1064	if (stat("/etc/svc/volatile/resetting", &sb) != -1) {
1065		log_framework(LOG_NOTICE, "Restarter quiesced.\n");
1066
1067		for (;;)
1068			(void) pause();
1069	}
1070
1071	act.sa_sigaction = &die_handler;
1072	(void) sigfillset(&act.sa_mask);
1073	act.sa_flags = SA_SIGINFO;
1074	(void) sigaction(SIGINT, &act, NULL);
1075	(void) sigaction(SIGTERM, &act, NULL);
1076
1077	startup();
1078
1079	(void) sigemptyset(&nullset);
1080	while (!finished) {
1081		log_framework(LOG_DEBUG, "Main thread paused\n");
1082		(void) sigsuspend(&nullset);
1083	}
1084
1085	(void) log_framework(LOG_DEBUG, "Restarter exiting.\n");
1086	return (0);
1087}
1088