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