1#!/sbin/sh 2# 3# CDDL HEADER START 4# 5# The contents of this file are subject to the terms of the 6# Common Development and Distribution License (the "License"). 7# You may not use this file except in compliance with the License. 8# 9# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10# or http://www.opensolaris.org/os/licensing. 11# See the License for the specific language governing permissions 12# and limitations under the License. 13# 14# When distributing Covered Code, include this CDDL HEADER in each 15# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16# If applicable, add the following below this CDDL HEADER, with the 17# fields enclosed by brackets "[]" replaced with your own identifying 18# information: Portions Copyright [yyyy] [name of copyright owner] 19# 20# CDDL HEADER END 21# 22# Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23# Use is subject to license terms. 24# 25# Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T 26# All Rights Reserved 27 28# 29# Copyright 2017, OmniTI Computer Consulting, Inc. All rights reserved. 30# 31 32# Sequence performed to change the init state of a machine. Only allows 33# transitions to states 0,1,5,6,s,S (i.e.: down or administrative states). 34 35# This procedure checks to see if you are permitted and allows an 36# interactive shutdown. The actual change of state, killing of 37# processes and such are performed by the new init state, say 0, 38# and its /sbin/rc0. 39 40usage() { 41 echo "Usage: $0 [ -y ] [ -g<grace> ] [ -i<initstate> ] [ message ]" 42 exit 1 43} 44 45notify() { 46 /usr/sbin/wall -a <<-! 47 $* 48 ! 49 # We used to do rwall here if showmounts had any output, but 50 # rwall is a potential security hole, and it could block this, so 51 # we don't bother with it anymore. 52} 53 54nologin=/etc/nologin 55 56# Set the PATH so that to guarentee behavior of shell built in commands 57# (such as echo). 58 59PATH=/usr/sbin:/usr/bin:/sbin 60 61# Initial sanity checks: 62# Make sure /usr is mounted 63# Check the user id (only root can run shutdown) 64 65if [ ! -d /usr/bin ] 66then 67 echo "$0: /usr is not mounted. Mount /usr or use init to shutdown." 68 exit 1 69fi 70 71if [ -x /usr/bin/id ] 72then 73 eval `/usr/bin/id | /usr/bin/sed 's/[^a-z0-9=].*//'` 74 if [ "${uid:=0}" -ne 0 ] 75 then 76 echo "$0: Only root can run $0" 77 exit 2 78 fi 79else 80 echo "$0: can't check user id." 81 exit 2 82fi 83 84# Get options (defaults immediately below): 85 86grace=60 87askconfirmation=yes 88initstate=s 89 90while getopts g:i:y? c 91do 92 case $c in 93 g) 94 case $OPTARG in 95 *[!0-9]* ) 96 echo "$0: -g requires a numeric option" 97 usage 98 ;; 99 [0-9]* ) 100 grace=$OPTARG 101 ;; 102 esac 103 ;; 104 i) 105 case $OPTARG in 106 [Ss0156]) 107 initstate=$OPTARG 108 ;; 109 [234abcqQ]) 110 echo "$0: Initstate $OPTARG is not for system shutdown" 111 exit 1 112 ;; 113 *) 114 echo "$0: $OPTARG is not a valid initstate" 115 usage 116 ;; 117 esac 118 ;; 119 y) 120 askconfirmation= 121 ;; 122 \?) usage 123 ;; 124 esac 125done 126shift $(($OPTIND - 1)) 127 128echo '\nShutdown started. \c' 129/usr/bin/date 130echo 131 132NODENAME=`uname -n` 133 134cd / 135 136trap "rm $nologin >/dev/null 2>&1 ;exit 1" 1 2 15 137 138# If other users are on the system (and any grace period is given), warn them. 139 140for i in 7200 3600 1800 1200 600 300 120 60 30 10; do 141 if [ ${grace} -gt $i ] 142 then 143 hours=$((${grace} / 3600)) 144 minutes=$((${grace} % 3600 / 60)) 145 seconds=$((${grace} % 60)) 146 time="" 147 if [ ${hours} -gt 1 ] 148 then 149 time="${hours} hours " 150 elif [ ${hours} -eq 1 ] 151 then 152 time="1 hour " 153 fi 154 if [ ${minutes} -gt 1 ] 155 then 156 time="${time}${minutes} minutes " 157 elif [ ${minutes} -eq 1 ] 158 then 159 time="${time}1 minute " 160 fi 161 if [ ${hours} -eq 0 -a ${seconds} -gt 0 ] 162 then 163 if [ ${seconds} -eq 1 ] 164 then 165 time="${time}${seconds} second" 166 else 167 time="${time}${seconds} seconds" 168 fi 169 fi 170 171 (notify \ 172"The system ${NODENAME} will be shut down in ${time} 173$*") 174 175 rm $nologin >/dev/null 2>&1 176 cat > $nologin <<-! 177 178 NO LOGINS: System going down in ${time} 179 $* 180 181 ! 182 183 /usr/bin/sleep $((${grace} - $i)) 184 grace=$i 185 fi 186done 187 188# Confirm that we really want to shutdown. 189 190if [ ${askconfirmation} ] 191then 192 echo "Do you want to continue? (y or n): \c" 193 read b 194 if [ "$b" != "y" ] 195 then 196 notify "False Alarm: The system ${NODENAME} will not be brought down." 197 echo 'Shutdown aborted.' 198 rm $nologin >/dev/null 2>&1 199 exit 1 200 fi 201fi 202 203# Final shutdown message, and sleep away the final 10 seconds (or less). 204 205(notify \ 206"THE SYSTEM ${NODENAME} IS BEING SHUT DOWN NOW ! ! ! 207Log off now or risk your files being damaged 208$*") 209 210if [ ${grace} -gt 0 ] 211then 212 /usr/bin/sleep ${grace} 213fi 214 215# Go to the requested initstate. 216 217 218echo "Changing to init state $initstate - please wait" 219 220# We might be racing with a system that's still booting. 221# Before starting init, check to see if smf(5) is running. The easiest way 222# to do this is to check for the existence of the repository service door. 223 224i=0 225# Try three times, sleeping one second each time... 226while [ ! -e /etc/svc/volatile/repository_door -a $i -lt 3 ]; do 227 sleep 1 228 i=$(($i + 1)) 229done 230 231if [ ! -e /etc/svc/volatile/repository_door ]; then 232 notify "Could not find repository door, init-state change may fail!" 233fi 234 235/sbin/init ${initstate} 236