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