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 
  40 usage() {
  41         echo "Usage: $0 [ -y ] [ -g<grace> ] [ -i<initstate> ] [ message ]"
  42         exit 1
  43 }
  44 
  45 notify() {
  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 
  54 nologin=/etc/nologin
  55 
  56 # Set the PATH so that to guarentee behavior of shell built in commands
  57 # (such as echo).
  58 
  59 PATH=/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 
  65 if [ ! -d /usr/bin ]
  66 then
  67         echo "$0:  /usr is not mounted.  Mount /usr or use init to shutdown."
  68         exit 1
  69 fi
  70 
  71 if [ -x /usr/bin/id ]
  72 then
  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
  79 else
  80         echo "$0:  can't check user id."
  81         exit 2
  82 fi
  83 
  84 # Get options (defaults immediately below):
  85 
  86 grace=60
  87 askconfirmation=yes
  88 initstate=s
  89 
  90 while getopts g:i:y? c
  91 do
  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
 125 done
 126 shift $(($OPTIND - 1))
 127 
 128 echo '\nShutdown started.    \c'
 129 /usr/bin/date
 130 echo
 131 
 132 NODENAME=`uname -n`
 133 
 134 cd /
 135 
 136 trap "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 
 140 for 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
 186 done
 187 
 188 # Confirm that we really want to shutdown.
 189 
 190 if [ ${askconfirmation} ]
 191 then
 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
 201 fi
 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 ! ! !
 207 Log off now or risk your files being damaged
 208 $*")
 209 
 210 if [ ${grace} -gt 0 ]
 211 then
 212         /usr/bin/sleep ${grace}
 213 fi
 214 
 215 # Go to the requested initstate.
 216 
 217 
 218 echo "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 
 224 i=0
 225 # Try three times, sleeping one second each time...
 226 while [ ! -e /etc/svc/volatile/repository_door -a $i -lt 3 ]; do
 227         sleep 1
 228         i=$(($i + 1))
 229 done
 230 
 231 if [ ! -e /etc/svc/volatile/repository_door ]; then
 232         notify "Could not find repository door, init-state change may fail!"
 233 fi
 234 
 235 /sbin/init ${initstate}