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