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