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}