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 
  30 #       Sequence performed to change the init state of a machine.  Only allows
  31 #       transitions to states 0,1,5,6,s,S (i.e.: down or administrative states).
  32 
  33 #       This procedure checks to see if you are permitted and allows an
  34 #       interactive shutdown.  The actual change of state, killing of
  35 #       processes and such are performed by the new init state, say 0,
  36 #       and its /sbin/rc0.
  37 
  38 usage() {
  39         echo "Usage: $0 [ -y ] [ -g<grace> ] [ -i<initstate> ] [ message ]"
  40         exit 1
  41 }
  42 
  43 notify() {
  44         /usr/sbin/wall -a <<-!
  45         $*
  46         !
  47         if [ -x /usr/sbin/showmount -a -x /usr/sbin/rwall ]
  48         then
  49                 remotes=`/usr/sbin/showmount`
  50                 if [ "X${remotes}" != "X" ]
  51                 then
  52                         /usr/sbin/rwall -q ${remotes} <<-!
  53                         $*
  54                         !
  55                 fi
  56         fi
  57 }
  58 
  59 nologin=/etc/nologin
  60 
  61 # Set the PATH so that to guarentee behavior of shell built in commands
  62 # (such as echo).
  63 
  64 PATH=/usr/sbin:/usr/bin:/sbin
  65 
  66 # Initial sanity checks:
  67 #       Make sure /usr is mounted
  68 #       Check the user id (only root can run shutdown)
  69 
  70 if [ ! -d /usr/bin ]
  71 then
  72         echo "$0:  /usr is not mounted.  Mount /usr or use init to shutdown."
  73         exit 1
  74 fi
  75 
  76 if [ -x /usr/bin/id ]
  77 then
  78         eval `/usr/bin/id  |  /usr/bin/sed 's/[^a-z0-9=].*//'`
  79         if [ "${uid:=0}" -ne 0 ]
  80         then
  81                 echo "$0:  Only root can run $0"
  82                 exit 2
  83         fi
  84 else
  85         echo "$0:  can't check user id."
  86         exit 2
  87 fi
  88 
  89 # Get options (defaults immediately below):
  90 
  91 grace=60
  92 askconfirmation=yes
  93 initstate=s
  94 
  95 while getopts g:i:y? c
  96 do
  97         case $c in
  98         g)
  99                 case $OPTARG in
 100                 *[!0-9]* )
 101                         echo "$0: -g requires a numeric option"
 102                         usage
 103                         ;;
 104                 [0-9]* )
 105                         grace=$OPTARG
 106                         ;;
 107                 esac
 108                 ;;
 109         i)
 110                 case $OPTARG in
 111                 [Ss0156])
 112                         initstate=$OPTARG
 113                         ;;
 114                 [234abcqQ])
 115                         echo "$0: Initstate $OPTARG is not for system shutdown"
 116                         exit 1
 117                         ;;
 118                 *)
 119                         echo "$0: $OPTARG is not a valid initstate"
 120                         usage
 121                         ;;
 122                 esac
 123                 ;;
 124         y)
 125                 askconfirmation=
 126                 ;;
 127         \?)     usage
 128                 ;;
 129         esac
 130 done
 131 shift `expr $OPTIND - 1`
 132 
 133 echo '\nShutdown started.    \c'
 134 /usr/bin/date
 135 echo
 136 
 137 NODENAME=`uname -n`
 138 
 139 cd /
 140 
 141 trap "rm $nologin >/dev/null 2>&1 ;exit 1"  1 2 15
 142 
 143 # If other users are on the system (and any grace period is given), warn them.
 144 
 145 for i in 7200 3600 1800 1200 600 300 120 60 30 10; do
 146         if [ ${grace} -gt $i ]
 147         then
 148                 hours=`/usr/bin/expr ${grace} / 3600`
 149                 minutes=`/usr/bin/expr ${grace} % 3600 / 60`
 150                 seconds=`/usr/bin/expr ${grace} % 60`
 151                 time=""
 152                 if [ ${hours} -gt 1 ]
 153                 then
 154                         time="${hours} hours "
 155                 elif [ ${hours} -eq 1 ]
 156                 then
 157                         time="1 hour "
 158                 fi
 159                 if [ ${minutes} -gt 1 ]
 160                 then
 161                         time="${time}${minutes} minutes "
 162                 elif [ ${minutes} -eq 1 ]
 163                 then
 164                         time="${time}1 minute "
 165                 fi
 166                 if [ ${hours} -eq 0 -a ${seconds} -gt 0 ]
 167                 then
 168                         if [ ${seconds} -eq 1 ]
 169                         then
 170                                 time="${time}${seconds} second"
 171                         else
 172                                 time="${time}${seconds} seconds"
 173                         fi
 174                 fi
 175 
 176                 (notify \
 177 "The system ${NODENAME} will be shut down in ${time}
 178 $*") &
 179 
 180 pid1=$!
 181 
 182                 rm $nologin >/dev/null 2>&1
 183                 cat > $nologin <<-!
 184 
 185                         NO LOGINS: System going down in ${time}
 186                         $*
 187 
 188                 !
 189 
 190                 /usr/bin/sleep `/usr/bin/expr ${grace} - $i`
 191                 grace=$i
 192         fi
 193 done
 194 
 195 # Confirm that we really want to shutdown.
 196 
 197 if [ ${askconfirmation} ]
 198 then
 199         echo "Do you want to continue? (y or n):   \c"
 200         read b
 201         if [ "$b" != "y" ]
 202         then
 203                 notify "False Alarm:  The system ${NODENAME} will not be brought down."
 204                 echo 'Shutdown aborted.'
 205                 rm $nologin >/dev/null 2>&1
 206                 exit 1
 207         fi
 208 fi
 209 
 210 # Final shutdown message, and sleep away the final 10 seconds (or less).
 211 
 212 (notify \
 213 "THE SYSTEM ${NODENAME} IS BEING SHUT DOWN NOW ! ! !
 214 Log off now or risk your files being damaged
 215 $*") &
 216 
 217 pid2=$!
 218 
 219 if [ ${grace} -gt 0 ]
 220 then
 221         /usr/bin/sleep ${grace}
 222 fi
 223 
 224 # Go to the requested initstate.
 225 
 226 
 227 echo "Changing to init state $initstate - please wait"
 228 
 229 if [ "$pid1" ] || [ "$pid2" ]
 230 then
 231         /usr/bin/kill $pid1 $pid2 > /dev/null 2>&1
 232 fi
 233 
 234 /sbin/init ${initstate}