1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate /* 31*7c478bd9Sstevel@tonic-gate * University Copyright- Copyright (c) 1982, 1986, 1988 32*7c478bd9Sstevel@tonic-gate * The Regents of the University of California 33*7c478bd9Sstevel@tonic-gate * All Rights Reserved 34*7c478bd9Sstevel@tonic-gate * 35*7c478bd9Sstevel@tonic-gate * University Acknowledgment- Portions of this document are derived from 36*7c478bd9Sstevel@tonic-gate * software developed by the University of California, Berkeley, and its 37*7c478bd9Sstevel@tonic-gate * contributors. 38*7c478bd9Sstevel@tonic-gate */ 39*7c478bd9Sstevel@tonic-gate 40*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 41*7c478bd9Sstevel@tonic-gate 42*7c478bd9Sstevel@tonic-gate /* 43*7c478bd9Sstevel@tonic-gate * Common code for halt(1M), poweroff(1M), and reboot(1M). We use 44*7c478bd9Sstevel@tonic-gate * argv[0] to determine which behavior to exhibit. 45*7c478bd9Sstevel@tonic-gate */ 46*7c478bd9Sstevel@tonic-gate 47*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 48*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 49*7c478bd9Sstevel@tonic-gate #include <sys/uadmin.h> 50*7c478bd9Sstevel@tonic-gate #include <alloca.h> 51*7c478bd9Sstevel@tonic-gate #include <assert.h> 52*7c478bd9Sstevel@tonic-gate #include <errno.h> 53*7c478bd9Sstevel@tonic-gate #include <fcntl.h> 54*7c478bd9Sstevel@tonic-gate #include <libgen.h> 55*7c478bd9Sstevel@tonic-gate #include <libscf.h> 56*7c478bd9Sstevel@tonic-gate #include <locale.h> 57*7c478bd9Sstevel@tonic-gate #include <libintl.h> 58*7c478bd9Sstevel@tonic-gate #include <syslog.h> 59*7c478bd9Sstevel@tonic-gate #include <signal.h> 60*7c478bd9Sstevel@tonic-gate #include <strings.h> 61*7c478bd9Sstevel@tonic-gate #include <unistd.h> 62*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 63*7c478bd9Sstevel@tonic-gate #include <stdio.h> 64*7c478bd9Sstevel@tonic-gate #include <strings.h> 65*7c478bd9Sstevel@tonic-gate #include <time.h> 66*7c478bd9Sstevel@tonic-gate #include <utmpx.h> 67*7c478bd9Sstevel@tonic-gate #include <pwd.h> 68*7c478bd9Sstevel@tonic-gate #include <zone.h> 69*7c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 70*7c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 71*7c478bd9Sstevel@tonic-gate #endif 72*7c478bd9Sstevel@tonic-gate 73*7c478bd9Sstevel@tonic-gate extern int audit_halt_setup(int, char **); 74*7c478bd9Sstevel@tonic-gate extern int audit_halt_success(void); 75*7c478bd9Sstevel@tonic-gate extern int audit_halt_fail(void); 76*7c478bd9Sstevel@tonic-gate 77*7c478bd9Sstevel@tonic-gate extern int audit_reboot_setup(void); 78*7c478bd9Sstevel@tonic-gate extern int audit_reboot_success(void); 79*7c478bd9Sstevel@tonic-gate extern int audit_reboot_fail(void); 80*7c478bd9Sstevel@tonic-gate 81*7c478bd9Sstevel@tonic-gate typedef struct ctidlist_struct { 82*7c478bd9Sstevel@tonic-gate ctid_t ctid; 83*7c478bd9Sstevel@tonic-gate struct ctidlist_struct *next; 84*7c478bd9Sstevel@tonic-gate } ctidlist_t; 85*7c478bd9Sstevel@tonic-gate 86*7c478bd9Sstevel@tonic-gate static ctidlist_t *ctidlist = NULL; 87*7c478bd9Sstevel@tonic-gate static ctid_t startdct = -1; 88*7c478bd9Sstevel@tonic-gate 89*7c478bd9Sstevel@tonic-gate #define FMRI_STARTD_CONTRACT \ 90*7c478bd9Sstevel@tonic-gate "svc:/system/svc/restarter:default/:properties/restarter/contract" 91*7c478bd9Sstevel@tonic-gate 92*7c478bd9Sstevel@tonic-gate static void 93*7c478bd9Sstevel@tonic-gate stop_startd() 94*7c478bd9Sstevel@tonic-gate { 95*7c478bd9Sstevel@tonic-gate ctid_t ctid; 96*7c478bd9Sstevel@tonic-gate 97*7c478bd9Sstevel@tonic-gate scf_handle_t *h; 98*7c478bd9Sstevel@tonic-gate scf_property_t *prop = NULL; 99*7c478bd9Sstevel@tonic-gate scf_value_t *val = NULL; 100*7c478bd9Sstevel@tonic-gate uint64_t uint64; 101*7c478bd9Sstevel@tonic-gate int ret; 102*7c478bd9Sstevel@tonic-gate 103*7c478bd9Sstevel@tonic-gate h = scf_handle_create(SCF_VERSION); 104*7c478bd9Sstevel@tonic-gate if (h == NULL) 105*7c478bd9Sstevel@tonic-gate return; 106*7c478bd9Sstevel@tonic-gate 107*7c478bd9Sstevel@tonic-gate ret = scf_handle_bind(h); 108*7c478bd9Sstevel@tonic-gate if (ret) { 109*7c478bd9Sstevel@tonic-gate scf_handle_destroy(h); 110*7c478bd9Sstevel@tonic-gate return; 111*7c478bd9Sstevel@tonic-gate } 112*7c478bd9Sstevel@tonic-gate 113*7c478bd9Sstevel@tonic-gate prop = scf_property_create(h); 114*7c478bd9Sstevel@tonic-gate val = scf_value_create(h); 115*7c478bd9Sstevel@tonic-gate 116*7c478bd9Sstevel@tonic-gate if (!(prop && val)) 117*7c478bd9Sstevel@tonic-gate goto out; 118*7c478bd9Sstevel@tonic-gate 119*7c478bd9Sstevel@tonic-gate ret = scf_handle_decode_fmri(h, FMRI_STARTD_CONTRACT, 120*7c478bd9Sstevel@tonic-gate NULL, NULL, NULL, NULL, prop, SCF_DECODE_FMRI_EXACT); 121*7c478bd9Sstevel@tonic-gate if (ret) 122*7c478bd9Sstevel@tonic-gate goto out; 123*7c478bd9Sstevel@tonic-gate 124*7c478bd9Sstevel@tonic-gate ret = scf_property_is_type(prop, SCF_TYPE_COUNT); 125*7c478bd9Sstevel@tonic-gate if (ret) 126*7c478bd9Sstevel@tonic-gate goto out; 127*7c478bd9Sstevel@tonic-gate 128*7c478bd9Sstevel@tonic-gate ret = scf_property_get_value(prop, val); 129*7c478bd9Sstevel@tonic-gate if (ret) 130*7c478bd9Sstevel@tonic-gate goto out; 131*7c478bd9Sstevel@tonic-gate 132*7c478bd9Sstevel@tonic-gate ret = scf_value_get_count(val, &uint64); 133*7c478bd9Sstevel@tonic-gate if (ret) 134*7c478bd9Sstevel@tonic-gate goto out; 135*7c478bd9Sstevel@tonic-gate 136*7c478bd9Sstevel@tonic-gate ctid = (ctid_t)uint64; 137*7c478bd9Sstevel@tonic-gate startdct = ctid; 138*7c478bd9Sstevel@tonic-gate (void) sigsend(P_CTID, ctid, SIGSTOP); 139*7c478bd9Sstevel@tonic-gate 140*7c478bd9Sstevel@tonic-gate out: 141*7c478bd9Sstevel@tonic-gate if (prop) 142*7c478bd9Sstevel@tonic-gate scf_property_destroy(prop); 143*7c478bd9Sstevel@tonic-gate if (val) 144*7c478bd9Sstevel@tonic-gate scf_value_destroy(val); 145*7c478bd9Sstevel@tonic-gate 146*7c478bd9Sstevel@tonic-gate (void) scf_handle_unbind(h); 147*7c478bd9Sstevel@tonic-gate scf_handle_destroy(h); 148*7c478bd9Sstevel@tonic-gate } 149*7c478bd9Sstevel@tonic-gate 150*7c478bd9Sstevel@tonic-gate static void 151*7c478bd9Sstevel@tonic-gate continue_startd() 152*7c478bd9Sstevel@tonic-gate { 153*7c478bd9Sstevel@tonic-gate if (startdct != -1) 154*7c478bd9Sstevel@tonic-gate (void) sigsend(P_CTID, startdct, SIGCONT); 155*7c478bd9Sstevel@tonic-gate } 156*7c478bd9Sstevel@tonic-gate 157*7c478bd9Sstevel@tonic-gate #define FMRI_RESTARTER_PROP "/:properties/general/restarter" 158*7c478bd9Sstevel@tonic-gate #define FMRI_CONTRACT_PROP "/:properties/restarter/contract" 159*7c478bd9Sstevel@tonic-gate 160*7c478bd9Sstevel@tonic-gate static int 161*7c478bd9Sstevel@tonic-gate save_ctid(ctid_t ctid) 162*7c478bd9Sstevel@tonic-gate { 163*7c478bd9Sstevel@tonic-gate ctidlist_t *next; 164*7c478bd9Sstevel@tonic-gate 165*7c478bd9Sstevel@tonic-gate for (next = ctidlist; next != NULL; next = next->next) 166*7c478bd9Sstevel@tonic-gate if (next->ctid == ctid) 167*7c478bd9Sstevel@tonic-gate return (-1); 168*7c478bd9Sstevel@tonic-gate 169*7c478bd9Sstevel@tonic-gate next = (ctidlist_t *)malloc(sizeof (ctidlist_t)); 170*7c478bd9Sstevel@tonic-gate if (next == NULL) 171*7c478bd9Sstevel@tonic-gate return (-1); 172*7c478bd9Sstevel@tonic-gate 173*7c478bd9Sstevel@tonic-gate next->ctid = ctid; 174*7c478bd9Sstevel@tonic-gate next->next = ctidlist; 175*7c478bd9Sstevel@tonic-gate ctidlist = next; 176*7c478bd9Sstevel@tonic-gate return (0); 177*7c478bd9Sstevel@tonic-gate } 178*7c478bd9Sstevel@tonic-gate 179*7c478bd9Sstevel@tonic-gate static void 180*7c478bd9Sstevel@tonic-gate stop_delegates() 181*7c478bd9Sstevel@tonic-gate { 182*7c478bd9Sstevel@tonic-gate ctid_t ctid; 183*7c478bd9Sstevel@tonic-gate scf_handle_t *h; 184*7c478bd9Sstevel@tonic-gate scf_scope_t *sc = NULL; 185*7c478bd9Sstevel@tonic-gate scf_service_t *svc = NULL; 186*7c478bd9Sstevel@tonic-gate scf_instance_t *inst = NULL; 187*7c478bd9Sstevel@tonic-gate scf_snapshot_t *snap = NULL; 188*7c478bd9Sstevel@tonic-gate scf_snapshot_t *isnap = NULL; 189*7c478bd9Sstevel@tonic-gate scf_propertygroup_t *pg = NULL; 190*7c478bd9Sstevel@tonic-gate scf_property_t *prop = NULL; 191*7c478bd9Sstevel@tonic-gate scf_value_t *val = NULL; 192*7c478bd9Sstevel@tonic-gate scf_iter_t *siter = NULL; 193*7c478bd9Sstevel@tonic-gate scf_iter_t *iiter = NULL; 194*7c478bd9Sstevel@tonic-gate char *fmri; 195*7c478bd9Sstevel@tonic-gate ssize_t length; 196*7c478bd9Sstevel@tonic-gate 197*7c478bd9Sstevel@tonic-gate uint64_t uint64; 198*7c478bd9Sstevel@tonic-gate ssize_t bytes; 199*7c478bd9Sstevel@tonic-gate int ret; 200*7c478bd9Sstevel@tonic-gate 201*7c478bd9Sstevel@tonic-gate length = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH); 202*7c478bd9Sstevel@tonic-gate if (length <= 0) 203*7c478bd9Sstevel@tonic-gate return; 204*7c478bd9Sstevel@tonic-gate 205*7c478bd9Sstevel@tonic-gate length++; 206*7c478bd9Sstevel@tonic-gate fmri = alloca(length * sizeof (char)); 207*7c478bd9Sstevel@tonic-gate 208*7c478bd9Sstevel@tonic-gate h = scf_handle_create(SCF_VERSION); 209*7c478bd9Sstevel@tonic-gate if (!h) 210*7c478bd9Sstevel@tonic-gate return; 211*7c478bd9Sstevel@tonic-gate 212*7c478bd9Sstevel@tonic-gate ret = scf_handle_bind(h); 213*7c478bd9Sstevel@tonic-gate if (ret) { 214*7c478bd9Sstevel@tonic-gate scf_handle_destroy(h); 215*7c478bd9Sstevel@tonic-gate return; 216*7c478bd9Sstevel@tonic-gate } 217*7c478bd9Sstevel@tonic-gate 218*7c478bd9Sstevel@tonic-gate sc = scf_scope_create(h); 219*7c478bd9Sstevel@tonic-gate svc = scf_service_create(h); 220*7c478bd9Sstevel@tonic-gate inst = scf_instance_create(h); 221*7c478bd9Sstevel@tonic-gate snap = scf_snapshot_create(h); 222*7c478bd9Sstevel@tonic-gate pg = scf_pg_create(h); 223*7c478bd9Sstevel@tonic-gate prop = scf_property_create(h); 224*7c478bd9Sstevel@tonic-gate val = scf_value_create(h); 225*7c478bd9Sstevel@tonic-gate siter = scf_iter_create(h); 226*7c478bd9Sstevel@tonic-gate iiter = scf_iter_create(h); 227*7c478bd9Sstevel@tonic-gate 228*7c478bd9Sstevel@tonic-gate if (!(sc && svc && inst && snap && 229*7c478bd9Sstevel@tonic-gate pg && prop && val && siter && iiter)) 230*7c478bd9Sstevel@tonic-gate goto out; 231*7c478bd9Sstevel@tonic-gate 232*7c478bd9Sstevel@tonic-gate ret = scf_handle_get_scope(h, SCF_SCOPE_LOCAL, sc); 233*7c478bd9Sstevel@tonic-gate if (ret) 234*7c478bd9Sstevel@tonic-gate goto out; 235*7c478bd9Sstevel@tonic-gate 236*7c478bd9Sstevel@tonic-gate ret = scf_iter_scope_services(siter, sc); 237*7c478bd9Sstevel@tonic-gate if (ret) 238*7c478bd9Sstevel@tonic-gate goto out; 239*7c478bd9Sstevel@tonic-gate 240*7c478bd9Sstevel@tonic-gate while (scf_iter_next_service(siter, svc) == 1) { 241*7c478bd9Sstevel@tonic-gate 242*7c478bd9Sstevel@tonic-gate ret = scf_iter_service_instances(iiter, svc); 243*7c478bd9Sstevel@tonic-gate if (ret) 244*7c478bd9Sstevel@tonic-gate continue; 245*7c478bd9Sstevel@tonic-gate 246*7c478bd9Sstevel@tonic-gate while (scf_iter_next_instance(iiter, inst) == 1) { 247*7c478bd9Sstevel@tonic-gate 248*7c478bd9Sstevel@tonic-gate ret = scf_instance_get_snapshot(inst, "running", snap); 249*7c478bd9Sstevel@tonic-gate if (ret) 250*7c478bd9Sstevel@tonic-gate isnap = NULL; 251*7c478bd9Sstevel@tonic-gate else 252*7c478bd9Sstevel@tonic-gate isnap = snap; 253*7c478bd9Sstevel@tonic-gate 254*7c478bd9Sstevel@tonic-gate ret = scf_instance_get_pg_composed(inst, isnap, 255*7c478bd9Sstevel@tonic-gate SCF_PG_GENERAL, pg); 256*7c478bd9Sstevel@tonic-gate if (ret) 257*7c478bd9Sstevel@tonic-gate continue; 258*7c478bd9Sstevel@tonic-gate 259*7c478bd9Sstevel@tonic-gate ret = scf_pg_get_property(pg, "restarter", prop); 260*7c478bd9Sstevel@tonic-gate if (ret) 261*7c478bd9Sstevel@tonic-gate continue; 262*7c478bd9Sstevel@tonic-gate 263*7c478bd9Sstevel@tonic-gate ret = scf_property_is_type(prop, SCF_TYPE_ASTRING); 264*7c478bd9Sstevel@tonic-gate if (ret) 265*7c478bd9Sstevel@tonic-gate continue; 266*7c478bd9Sstevel@tonic-gate 267*7c478bd9Sstevel@tonic-gate ret = scf_property_get_value(prop, val); 268*7c478bd9Sstevel@tonic-gate if (ret) 269*7c478bd9Sstevel@tonic-gate continue; 270*7c478bd9Sstevel@tonic-gate 271*7c478bd9Sstevel@tonic-gate bytes = scf_value_get_astring(val, fmri, length); 272*7c478bd9Sstevel@tonic-gate if (bytes <= 0 || bytes >= length) 273*7c478bd9Sstevel@tonic-gate continue; 274*7c478bd9Sstevel@tonic-gate 275*7c478bd9Sstevel@tonic-gate if (strlcat(fmri, FMRI_CONTRACT_PROP, length) >= 276*7c478bd9Sstevel@tonic-gate length) 277*7c478bd9Sstevel@tonic-gate continue; 278*7c478bd9Sstevel@tonic-gate 279*7c478bd9Sstevel@tonic-gate ret = scf_handle_decode_fmri(h, fmri, NULL, NULL, 280*7c478bd9Sstevel@tonic-gate NULL, NULL, prop, SCF_DECODE_FMRI_EXACT); 281*7c478bd9Sstevel@tonic-gate if (ret) 282*7c478bd9Sstevel@tonic-gate continue; 283*7c478bd9Sstevel@tonic-gate 284*7c478bd9Sstevel@tonic-gate ret = scf_property_is_type(prop, SCF_TYPE_COUNT); 285*7c478bd9Sstevel@tonic-gate if (ret) 286*7c478bd9Sstevel@tonic-gate continue; 287*7c478bd9Sstevel@tonic-gate 288*7c478bd9Sstevel@tonic-gate ret = scf_property_get_value(prop, val); 289*7c478bd9Sstevel@tonic-gate if (ret) 290*7c478bd9Sstevel@tonic-gate continue; 291*7c478bd9Sstevel@tonic-gate 292*7c478bd9Sstevel@tonic-gate ret = scf_value_get_count(val, &uint64); 293*7c478bd9Sstevel@tonic-gate if (ret) 294*7c478bd9Sstevel@tonic-gate continue; 295*7c478bd9Sstevel@tonic-gate 296*7c478bd9Sstevel@tonic-gate ctid = (ctid_t)uint64; 297*7c478bd9Sstevel@tonic-gate if (save_ctid(ctid) == 0) { 298*7c478bd9Sstevel@tonic-gate (void) sigsend(P_CTID, ctid, SIGSTOP); 299*7c478bd9Sstevel@tonic-gate } 300*7c478bd9Sstevel@tonic-gate } 301*7c478bd9Sstevel@tonic-gate } 302*7c478bd9Sstevel@tonic-gate out: 303*7c478bd9Sstevel@tonic-gate if (sc) 304*7c478bd9Sstevel@tonic-gate scf_scope_destroy(sc); 305*7c478bd9Sstevel@tonic-gate if (svc) 306*7c478bd9Sstevel@tonic-gate scf_service_destroy(svc); 307*7c478bd9Sstevel@tonic-gate if (inst) 308*7c478bd9Sstevel@tonic-gate scf_instance_destroy(inst); 309*7c478bd9Sstevel@tonic-gate if (snap) 310*7c478bd9Sstevel@tonic-gate scf_snapshot_destroy(snap); 311*7c478bd9Sstevel@tonic-gate if (pg) 312*7c478bd9Sstevel@tonic-gate scf_pg_destroy(pg); 313*7c478bd9Sstevel@tonic-gate if (prop) 314*7c478bd9Sstevel@tonic-gate scf_property_destroy(prop); 315*7c478bd9Sstevel@tonic-gate if (val) 316*7c478bd9Sstevel@tonic-gate scf_value_destroy(val); 317*7c478bd9Sstevel@tonic-gate if (siter) 318*7c478bd9Sstevel@tonic-gate scf_iter_destroy(siter); 319*7c478bd9Sstevel@tonic-gate if (iiter) 320*7c478bd9Sstevel@tonic-gate scf_iter_destroy(iiter); 321*7c478bd9Sstevel@tonic-gate 322*7c478bd9Sstevel@tonic-gate (void) scf_handle_unbind(h); 323*7c478bd9Sstevel@tonic-gate scf_handle_destroy(h); 324*7c478bd9Sstevel@tonic-gate } 325*7c478bd9Sstevel@tonic-gate 326*7c478bd9Sstevel@tonic-gate static void 327*7c478bd9Sstevel@tonic-gate continue_delegates() 328*7c478bd9Sstevel@tonic-gate { 329*7c478bd9Sstevel@tonic-gate ctidlist_t *next; 330*7c478bd9Sstevel@tonic-gate for (next = ctidlist; next != NULL; next = next->next) 331*7c478bd9Sstevel@tonic-gate (void) sigsend(P_CTID, next->ctid, SIGCONT); 332*7c478bd9Sstevel@tonic-gate } 333*7c478bd9Sstevel@tonic-gate 334*7c478bd9Sstevel@tonic-gate static void 335*7c478bd9Sstevel@tonic-gate stop_restarters() 336*7c478bd9Sstevel@tonic-gate { 337*7c478bd9Sstevel@tonic-gate stop_startd(); 338*7c478bd9Sstevel@tonic-gate stop_delegates(); 339*7c478bd9Sstevel@tonic-gate } 340*7c478bd9Sstevel@tonic-gate 341*7c478bd9Sstevel@tonic-gate static void 342*7c478bd9Sstevel@tonic-gate continue_restarters() 343*7c478bd9Sstevel@tonic-gate { 344*7c478bd9Sstevel@tonic-gate continue_startd(); 345*7c478bd9Sstevel@tonic-gate continue_delegates(); 346*7c478bd9Sstevel@tonic-gate } 347*7c478bd9Sstevel@tonic-gate 348*7c478bd9Sstevel@tonic-gate /* 349*7c478bd9Sstevel@tonic-gate * Copy an array of strings into buf, separated by spaces. Returns 0 on 350*7c478bd9Sstevel@tonic-gate * success. 351*7c478bd9Sstevel@tonic-gate */ 352*7c478bd9Sstevel@tonic-gate static int 353*7c478bd9Sstevel@tonic-gate gather_args(char **args, char *buf, size_t buf_sz) 354*7c478bd9Sstevel@tonic-gate { 355*7c478bd9Sstevel@tonic-gate if (strlcpy(buf, *args, buf_sz) >= buf_sz) 356*7c478bd9Sstevel@tonic-gate return (-1); 357*7c478bd9Sstevel@tonic-gate 358*7c478bd9Sstevel@tonic-gate for (++args; *args != NULL; ++args) { 359*7c478bd9Sstevel@tonic-gate if (strlcat(buf, " ", buf_sz) >= buf_sz) 360*7c478bd9Sstevel@tonic-gate return (-1); 361*7c478bd9Sstevel@tonic-gate if (strlcat(buf, *args, buf_sz) >= buf_sz) 362*7c478bd9Sstevel@tonic-gate return (-1); 363*7c478bd9Sstevel@tonic-gate } 364*7c478bd9Sstevel@tonic-gate 365*7c478bd9Sstevel@tonic-gate return (0); 366*7c478bd9Sstevel@tonic-gate } 367*7c478bd9Sstevel@tonic-gate 368*7c478bd9Sstevel@tonic-gate int 369*7c478bd9Sstevel@tonic-gate main(int argc, char *argv[]) 370*7c478bd9Sstevel@tonic-gate { 371*7c478bd9Sstevel@tonic-gate char *cmdname = basename(argv[0]); 372*7c478bd9Sstevel@tonic-gate char *ttyn = ttyname(STDERR_FILENO); 373*7c478bd9Sstevel@tonic-gate 374*7c478bd9Sstevel@tonic-gate int qflag = 0, needlog = 1, nosync = 0; 375*7c478bd9Sstevel@tonic-gate uintptr_t mdep = NULL; 376*7c478bd9Sstevel@tonic-gate int cmd, fcn, c, aval, r; 377*7c478bd9Sstevel@tonic-gate const char *usage; 378*7c478bd9Sstevel@tonic-gate zoneid_t zoneid = getzoneid(); 379*7c478bd9Sstevel@tonic-gate pid_t init_pid = 1; 380*7c478bd9Sstevel@tonic-gate 381*7c478bd9Sstevel@tonic-gate char bootargs_buf[257]; /* uadmin()'s buffer is 257 bytes. */ 382*7c478bd9Sstevel@tonic-gate 383*7c478bd9Sstevel@tonic-gate const char * const resetting = "/etc/svc/volatile/resetting"; 384*7c478bd9Sstevel@tonic-gate 385*7c478bd9Sstevel@tonic-gate 386*7c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 387*7c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 388*7c478bd9Sstevel@tonic-gate 389*7c478bd9Sstevel@tonic-gate if (strcmp(cmdname, "halt") == 0) { 390*7c478bd9Sstevel@tonic-gate (void) audit_halt_setup(argc, argv); 391*7c478bd9Sstevel@tonic-gate usage = gettext("usage: %s [ -dlnqy ]\n"); 392*7c478bd9Sstevel@tonic-gate cmd = A_SHUTDOWN; 393*7c478bd9Sstevel@tonic-gate fcn = AD_HALT; 394*7c478bd9Sstevel@tonic-gate } else if (strcmp(cmdname, "poweroff") == 0) { 395*7c478bd9Sstevel@tonic-gate (void) audit_halt_setup(argc, argv); 396*7c478bd9Sstevel@tonic-gate usage = gettext("usage: %s [ -dlnqy ]\n"); 397*7c478bd9Sstevel@tonic-gate cmd = A_SHUTDOWN; 398*7c478bd9Sstevel@tonic-gate fcn = AD_POWEROFF; 399*7c478bd9Sstevel@tonic-gate } else if (strcmp(cmdname, "reboot") == 0) { 400*7c478bd9Sstevel@tonic-gate (void) audit_reboot_setup(); 401*7c478bd9Sstevel@tonic-gate usage = gettext("usage: %s [ -dlnq ] [ boot args ]\n"); 402*7c478bd9Sstevel@tonic-gate cmd = A_SHUTDOWN; 403*7c478bd9Sstevel@tonic-gate fcn = AD_BOOT; 404*7c478bd9Sstevel@tonic-gate } else { 405*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 406*7c478bd9Sstevel@tonic-gate gettext("%s: not installed properly\n"), cmdname); 407*7c478bd9Sstevel@tonic-gate return (1); 408*7c478bd9Sstevel@tonic-gate } 409*7c478bd9Sstevel@tonic-gate 410*7c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, "dlnqy")) != EOF) { 411*7c478bd9Sstevel@tonic-gate switch (c) { 412*7c478bd9Sstevel@tonic-gate case 'd': 413*7c478bd9Sstevel@tonic-gate if (zoneid == GLOBAL_ZONEID) 414*7c478bd9Sstevel@tonic-gate cmd = A_DUMP; 415*7c478bd9Sstevel@tonic-gate else { 416*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 417*7c478bd9Sstevel@tonic-gate gettext("%s: -d only valid from global" 418*7c478bd9Sstevel@tonic-gate " zone\n"), cmdname); 419*7c478bd9Sstevel@tonic-gate return (1); 420*7c478bd9Sstevel@tonic-gate } 421*7c478bd9Sstevel@tonic-gate break; 422*7c478bd9Sstevel@tonic-gate case 'l': 423*7c478bd9Sstevel@tonic-gate needlog = 0; 424*7c478bd9Sstevel@tonic-gate break; 425*7c478bd9Sstevel@tonic-gate case 'n': 426*7c478bd9Sstevel@tonic-gate nosync = 1; 427*7c478bd9Sstevel@tonic-gate break; 428*7c478bd9Sstevel@tonic-gate case 'q': 429*7c478bd9Sstevel@tonic-gate qflag = 1; 430*7c478bd9Sstevel@tonic-gate break; 431*7c478bd9Sstevel@tonic-gate case 'y': 432*7c478bd9Sstevel@tonic-gate ttyn = NULL; 433*7c478bd9Sstevel@tonic-gate break; 434*7c478bd9Sstevel@tonic-gate default: 435*7c478bd9Sstevel@tonic-gate /* 436*7c478bd9Sstevel@tonic-gate * TRANSLATION_NOTE 437*7c478bd9Sstevel@tonic-gate * Don't translate the words "halt" or "reboot" 438*7c478bd9Sstevel@tonic-gate */ 439*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, usage, cmdname); 440*7c478bd9Sstevel@tonic-gate return (1); 441*7c478bd9Sstevel@tonic-gate } 442*7c478bd9Sstevel@tonic-gate } 443*7c478bd9Sstevel@tonic-gate 444*7c478bd9Sstevel@tonic-gate argc -= optind; 445*7c478bd9Sstevel@tonic-gate argv += optind; 446*7c478bd9Sstevel@tonic-gate 447*7c478bd9Sstevel@tonic-gate if (argc != 0) { 448*7c478bd9Sstevel@tonic-gate if (fcn != AD_BOOT) { 449*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, usage, cmdname); 450*7c478bd9Sstevel@tonic-gate return (1); 451*7c478bd9Sstevel@tonic-gate } 452*7c478bd9Sstevel@tonic-gate 453*7c478bd9Sstevel@tonic-gate /* Gather the arguments into bootargs_buf. */ 454*7c478bd9Sstevel@tonic-gate if (gather_args(argv, bootargs_buf, sizeof (bootargs_buf)) != 455*7c478bd9Sstevel@tonic-gate 0) { 456*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 457*7c478bd9Sstevel@tonic-gate gettext("%s: Boot arguments too long.\n"), cmdname); 458*7c478bd9Sstevel@tonic-gate return (1); 459*7c478bd9Sstevel@tonic-gate } 460*7c478bd9Sstevel@tonic-gate mdep = (uintptr_t)bootargs_buf; 461*7c478bd9Sstevel@tonic-gate } 462*7c478bd9Sstevel@tonic-gate 463*7c478bd9Sstevel@tonic-gate if (geteuid() != 0) { 464*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 465*7c478bd9Sstevel@tonic-gate gettext("%s: permission denied\n"), cmdname); 466*7c478bd9Sstevel@tonic-gate goto fail; 467*7c478bd9Sstevel@tonic-gate } 468*7c478bd9Sstevel@tonic-gate 469*7c478bd9Sstevel@tonic-gate if (fcn != AD_BOOT && ttyn != NULL && 470*7c478bd9Sstevel@tonic-gate strncmp(ttyn, "/dev/term/", strlen("/dev/term/")) == 0) { 471*7c478bd9Sstevel@tonic-gate /* 472*7c478bd9Sstevel@tonic-gate * TRANSLATION_NOTE 473*7c478bd9Sstevel@tonic-gate * Don't translate ``halt -y'' 474*7c478bd9Sstevel@tonic-gate */ 475*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 476*7c478bd9Sstevel@tonic-gate gettext("%s: dangerous on a dialup;"), cmdname); 477*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 478*7c478bd9Sstevel@tonic-gate gettext("use ``%s -y'' if you are really sure\n"), cmdname); 479*7c478bd9Sstevel@tonic-gate goto fail; 480*7c478bd9Sstevel@tonic-gate } 481*7c478bd9Sstevel@tonic-gate 482*7c478bd9Sstevel@tonic-gate if (needlog) { 483*7c478bd9Sstevel@tonic-gate char *user = getlogin(); 484*7c478bd9Sstevel@tonic-gate struct passwd *pw; 485*7c478bd9Sstevel@tonic-gate 486*7c478bd9Sstevel@tonic-gate openlog(cmdname, 0, LOG_AUTH); 487*7c478bd9Sstevel@tonic-gate if (user == NULL && (pw = getpwuid(getuid())) != NULL) 488*7c478bd9Sstevel@tonic-gate user = pw->pw_name; 489*7c478bd9Sstevel@tonic-gate if (user == NULL) 490*7c478bd9Sstevel@tonic-gate user = "root"; 491*7c478bd9Sstevel@tonic-gate syslog(LOG_CRIT, "%sed by %s", cmdname, user); 492*7c478bd9Sstevel@tonic-gate } 493*7c478bd9Sstevel@tonic-gate 494*7c478bd9Sstevel@tonic-gate /* 495*7c478bd9Sstevel@tonic-gate * We must assume success and log it before auditd is terminated. 496*7c478bd9Sstevel@tonic-gate */ 497*7c478bd9Sstevel@tonic-gate if (fcn == AD_BOOT) 498*7c478bd9Sstevel@tonic-gate aval = audit_reboot_success(); 499*7c478bd9Sstevel@tonic-gate else 500*7c478bd9Sstevel@tonic-gate aval = audit_halt_success(); 501*7c478bd9Sstevel@tonic-gate 502*7c478bd9Sstevel@tonic-gate if (aval == -1) { 503*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 504*7c478bd9Sstevel@tonic-gate gettext("%s: can't turn off auditd\n"), cmdname); 505*7c478bd9Sstevel@tonic-gate if (needlog) 506*7c478bd9Sstevel@tonic-gate (void) sleep(5); /* Give syslogd time to record this */ 507*7c478bd9Sstevel@tonic-gate } 508*7c478bd9Sstevel@tonic-gate 509*7c478bd9Sstevel@tonic-gate (void) signal(SIGHUP, SIG_IGN); /* for remote connections */ 510*7c478bd9Sstevel@tonic-gate 511*7c478bd9Sstevel@tonic-gate if (zone_getattr(getzoneid(), ZONE_ATTR_INITPID, &init_pid, 512*7c478bd9Sstevel@tonic-gate sizeof (init_pid)) != sizeof (init_pid)) { 513*7c478bd9Sstevel@tonic-gate assert(errno == ESRCH); 514*7c478bd9Sstevel@tonic-gate init_pid = -1; 515*7c478bd9Sstevel@tonic-gate } 516*7c478bd9Sstevel@tonic-gate 517*7c478bd9Sstevel@tonic-gate /* sync boot archive in the global zone */ 518*7c478bd9Sstevel@tonic-gate if (getzoneid() == GLOBAL_ZONEID && !nosync) { 519*7c478bd9Sstevel@tonic-gate (void) system("/sbin/bootadm -a update_all"); 520*7c478bd9Sstevel@tonic-gate } 521*7c478bd9Sstevel@tonic-gate 522*7c478bd9Sstevel@tonic-gate /* 523*7c478bd9Sstevel@tonic-gate * If we're not forcing a crash dump, mark the system as quiescing for 524*7c478bd9Sstevel@tonic-gate * smf(5)'s benefit, and idle the init process. 525*7c478bd9Sstevel@tonic-gate */ 526*7c478bd9Sstevel@tonic-gate if (cmd != A_DUMP) { 527*7c478bd9Sstevel@tonic-gate if (init_pid != -1 && kill(init_pid, SIGTSTP) == -1) { 528*7c478bd9Sstevel@tonic-gate /* 529*7c478bd9Sstevel@tonic-gate * TRANSLATION_NOTE 530*7c478bd9Sstevel@tonic-gate * Don't translate the word "init" 531*7c478bd9Sstevel@tonic-gate */ 532*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 533*7c478bd9Sstevel@tonic-gate gettext("%s: can't idle init\n"), cmdname); 534*7c478bd9Sstevel@tonic-gate 535*7c478bd9Sstevel@tonic-gate goto fail; 536*7c478bd9Sstevel@tonic-gate } 537*7c478bd9Sstevel@tonic-gate 538*7c478bd9Sstevel@tonic-gate if (creat(resetting, 0755) == -1) 539*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 540*7c478bd9Sstevel@tonic-gate gettext("%s: could not create %s.\n"), 541*7c478bd9Sstevel@tonic-gate cmdname, resetting); 542*7c478bd9Sstevel@tonic-gate 543*7c478bd9Sstevel@tonic-gate /* 544*7c478bd9Sstevel@tonic-gate * Stop all restarters so they do not try to restart services 545*7c478bd9Sstevel@tonic-gate * that are terminated. 546*7c478bd9Sstevel@tonic-gate */ 547*7c478bd9Sstevel@tonic-gate stop_restarters(); 548*7c478bd9Sstevel@tonic-gate } 549*7c478bd9Sstevel@tonic-gate 550*7c478bd9Sstevel@tonic-gate /* 551*7c478bd9Sstevel@tonic-gate * Make sure we don't get stopped by a jobcontrol shell 552*7c478bd9Sstevel@tonic-gate * once we start killing everybody. 553*7c478bd9Sstevel@tonic-gate */ 554*7c478bd9Sstevel@tonic-gate (void) signal(SIGTSTP, SIG_IGN); 555*7c478bd9Sstevel@tonic-gate (void) signal(SIGTTIN, SIG_IGN); 556*7c478bd9Sstevel@tonic-gate (void) signal(SIGTTOU, SIG_IGN); 557*7c478bd9Sstevel@tonic-gate (void) signal(SIGTERM, SIG_IGN); 558*7c478bd9Sstevel@tonic-gate 559*7c478bd9Sstevel@tonic-gate /* 560*7c478bd9Sstevel@tonic-gate * If we're not forcing a crash dump, give everyone 5 seconds to 561*7c478bd9Sstevel@tonic-gate * handle a SIGTERM and clean up properly. 562*7c478bd9Sstevel@tonic-gate */ 563*7c478bd9Sstevel@tonic-gate if (cmd != A_DUMP) { 564*7c478bd9Sstevel@tonic-gate (void) kill(-1, SIGTERM); 565*7c478bd9Sstevel@tonic-gate (void) sleep(5); 566*7c478bd9Sstevel@tonic-gate } 567*7c478bd9Sstevel@tonic-gate 568*7c478bd9Sstevel@tonic-gate if (!qflag && !nosync) { 569*7c478bd9Sstevel@tonic-gate struct utmpx wtmpx; 570*7c478bd9Sstevel@tonic-gate 571*7c478bd9Sstevel@tonic-gate bzero(&wtmpx, sizeof (struct utmpx)); 572*7c478bd9Sstevel@tonic-gate (void) strcpy(wtmpx.ut_line, "~"); 573*7c478bd9Sstevel@tonic-gate (void) time(&wtmpx.ut_tv.tv_sec); 574*7c478bd9Sstevel@tonic-gate 575*7c478bd9Sstevel@tonic-gate if (cmd == A_DUMP) 576*7c478bd9Sstevel@tonic-gate (void) strcpy(wtmpx.ut_name, "crash dump"); 577*7c478bd9Sstevel@tonic-gate else 578*7c478bd9Sstevel@tonic-gate (void) strcpy(wtmpx.ut_name, "shutdown"); 579*7c478bd9Sstevel@tonic-gate 580*7c478bd9Sstevel@tonic-gate (void) updwtmpx(WTMPX_FILE, &wtmpx); 581*7c478bd9Sstevel@tonic-gate sync(); 582*7c478bd9Sstevel@tonic-gate } 583*7c478bd9Sstevel@tonic-gate 584*7c478bd9Sstevel@tonic-gate if (cmd == A_DUMP && nosync != 0) 585*7c478bd9Sstevel@tonic-gate (void) uadmin(A_DUMP, AD_NOSYNC, NULL); 586*7c478bd9Sstevel@tonic-gate 587*7c478bd9Sstevel@tonic-gate (void) uadmin(cmd, fcn, mdep); 588*7c478bd9Sstevel@tonic-gate perror(cmdname); 589*7c478bd9Sstevel@tonic-gate 590*7c478bd9Sstevel@tonic-gate do 591*7c478bd9Sstevel@tonic-gate r = remove(resetting); 592*7c478bd9Sstevel@tonic-gate while (r != 0 && errno == EINTR); 593*7c478bd9Sstevel@tonic-gate if (r != 0 && errno != ENOENT) 594*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: could not remove %s.\n"), 595*7c478bd9Sstevel@tonic-gate cmdname, resetting); 596*7c478bd9Sstevel@tonic-gate 597*7c478bd9Sstevel@tonic-gate continue_restarters(); 598*7c478bd9Sstevel@tonic-gate 599*7c478bd9Sstevel@tonic-gate if (init_pid != -1) 600*7c478bd9Sstevel@tonic-gate /* tell init to restate current level */ 601*7c478bd9Sstevel@tonic-gate (void) kill(init_pid, SIGHUP); 602*7c478bd9Sstevel@tonic-gate 603*7c478bd9Sstevel@tonic-gate fail: 604*7c478bd9Sstevel@tonic-gate if (fcn == AD_BOOT) 605*7c478bd9Sstevel@tonic-gate (void) audit_reboot_fail(); 606*7c478bd9Sstevel@tonic-gate else 607*7c478bd9Sstevel@tonic-gate (void) audit_halt_fail(); 608*7c478bd9Sstevel@tonic-gate 609*7c478bd9Sstevel@tonic-gate return (1); 610*7c478bd9Sstevel@tonic-gate } 611