blob: 95d1c226b9258491ee27f70a893f0209ac1b2a23 [file] [log] [blame]
xf.li86118912025-03-19 20:07:27 -07001#!/bin/sh
2#
3# update-rc.d Update the links in /etc/rc[0-9S].d/
4#
5# (c) 2003, 2004 Phil Blundell <pb@handhelds.org>
6#
7# SPDX-License-Identifier: GPL-2.0-or-later
8#
9
10initd="/etc/init.d"
11etcd="/etc/rc"
12notreally=0
13force=0
14dostart=0
15verbose=0
16
17usage()
18{
19 cat >&2 <<EOF
20usage: update-rc.d [-n] [-f] [-r <root>] <basename> remove
21 update-rc.d [-n] [-r <root>] [-s] <basename> defaults [NN | sNN kNN]
22 update-rc.d [-n] [-r <root>] [-s] <basename> start|stop NN runlvl [runlvl] [...] .
23 update-rc.d [-n] [-r <root>] [-s] <basename> enable|disable [S|2|3|4|5]
24 -n: not really
25 -f: force
26 -v: verbose
27 -r: alternate root path (default is /)
28 -s: invoke start methods if appropriate to current runlevel
29EOF
30}
31
32checklinks()
33{
34 local i dn fn remove=0
35 if [ "x$1" = "xremove" ]; then
36 echo " Removing any system startup links for $bn ..."
37 remove=1
38 fi
39
40 for i in 0 1 2 3 4 5 6 7 8 9 S; do
41 dn="${etcd}${i}.d"
42 if [ ! -d $dn ]; then
43 continue;
44 fi
45 for f in ${dn}/[SK]??${bn}; do
46 if [ -L $f ]; then
47 if [ $remove -eq 0 ]; then
48 return 1
49 fi
50 echo " $f"
51 if [ $notreally -eq 1 ]; then
52 continue
53 fi
54 rm $f
55 fi
56 done
57 done
58
59 return 0
60}
61
62dolink()
63{
64 startstop=$1
65 lev=`echo $2 | cut -d/ -f1`
66 nn=`echo $2 | cut -d/ -f2`
67 fn="${etcd}${lev}.d/${startstop}${nn}${bn}"
68 [ $verbose -eq 1 ] && echo " $fn -> ../init.d/$bn"
69 if [ $notreally -eq 0 ]; then
70 mkdir -p `dirname $fn`
71 ln -s ../init.d/$bn $fn
72 fi
73 if [ $dostart -eq 1 ] && [ $startstop = "S" ] && [ $lev = $RUNLEVEL ]; then
74 $fn start || true
75 fi
76}
77
78makelinks()
79{
80 if ! checklinks; then
81 echo " System startup links for $initd/$bn already exist."
82 if [ $dostart -eq 1 ] && [ $notreally -eq 0 ] && [ -L ${etcd}${RUNLEVEL}.d/S??${bn} ]; then
83 ${etcd}${RUNLEVEL}.d/S??${bn} restart || true
84 fi
85 exit 0
86 fi
87
88 echo " Adding system startup for $initd/$bn."
89
90 for i in $startlinks; do
91 dolink S $i
92 done
93 for i in $stoplinks; do
94 dolink K $i
95 done
96}
97
98# function to disable/enable init script link of one run level
99# $1 should be K/S, means to disable/enable
100# $2 means which run level to disable/enable
101renamelink()
102{
103 local oldstartstop newstartstop lev oldnn newnn
104 if [ "x$1" = "xS" ]; then
105 oldstartstop="K"
106 newstartstop="S"
107 else
108 oldstartstop="S"
109 newstartstop="K"
110 fi
111
112 lev=$2
113 # modifies existing runlevel links for the script /etc/init.d/name by renaming start links to stop link
114 # or stop link to start link with a sequence number equal to the difference of 100 minus the original sequence number.
115 if ls ${etcd}${lev}.d/${oldstartstop}*${bn} >/dev/null 2>&1; then
116 oldnn=`basename ${etcd}${lev}.d/${oldstartstop}*${bn}|cut -c2-3`
117 newnn=$(printf "%02d" $((100-${oldnn#0})))
118 [ $verbose -eq 1 ] && echo "rename ${etcd}${lev}.d/${oldstartstop}${oldnn}${bn} -> ${etcd}${lev}.d/${newstartstop}${newnn}${bn}"
119 if [ $notreally -eq 0 ];then
120 mv ${etcd}${lev}.d/${oldstartstop}${oldnn}${bn} ${etcd}${lev}.d/${newstartstop}${newnn}${bn}
121 fi
122 if [ $dostart -eq 1 ] && [ $newstartstop = "S" ] && [ $lev = $RUNLEVEL ]; then
123 $fn start || true
124 fi
125 fi
126
127}
128
129# function to disable/enable init script link
130# $1 should be K/S, means to disable/enable
131# $2 run level [S|2|3|4|5], optional, If no start runlevel is
132# specified after the disable or enable keywords
133# the script will attempt to modify links in all start runlevels
134renamelinks()
135{
136 if [ $# -eq 2 ]; then
137 renamelink $1 $2
138 else
139 for i in 2 3 4 5 S; do
140 renamelink $1 $i
141 done
142 fi
143}
144
145while [ $# -gt 0 ]; do
146 case $1 in
147 -n) notreally=1
148 shift
149 continue
150 ;;
151 -v) verbose=1
152 shift
153 continue
154 ;;
155 -f) force=1
156 shift
157 continue
158 ;;
159 -s) dostart=1
160 shift
161 continue
162 ;;
163 -r) shift
164 root=$1
165 initd="${root}${initd}"
166 etcd="${root}${etcd}"
167 shift
168 ;;
169 -h | --help)
170 usage
171 exit 0
172 ;;
173 -*)
174 usage
175 exit 1
176 ;;
177 *)
178 break
179 ;;
180 esac
181done
182
183if [ $# -lt 2 ]; then
184 usage
185 exit 1
186fi
187
188bn=$1
189shift
190
191sn=$initd/$bn
192if [ -L "$sn" -a -n "$root" ]; then
193 if which readlink >/dev/null; then
194 while true; do
195 linksn="$(readlink "$sn")"
196 if [ -z "$linksn" ]; then
197 break
198 fi
199
200 sn="$linksn"
201 case "$sn" in
202 /*) sn="$root$sn" ;;
203 *) sn="$initd/$sn" ;;
204 esac
205 done
206 else
207 echo "update-rc.d: readlink tool not present, cannot check whether \
208 $sn symlink points to a valid file." >&2
209 fi
210fi
211
212if [ $1 != "remove" ]; then
213 if [ ! -f "$sn" ]; then
214 echo "update-rc.d: $initd/$bn: file does not exist" >&2
215 exit 1
216 fi
217else
218 if [ -f "$sn" ]; then
219 if [ $force -eq 1 ]; then
220 echo "update-rc.d: $initd/$bn exists during rc.d purge (continuing)" >&2
221 else
222 echo "update-rc.d: $initd/$bn exists during rc.d purge (use -f to force)" >&2
223 exit 1
224 fi
225 fi
226fi
227
228if [ $dostart -eq 1 ]; then
229 #RUNLEVEL=`sed 's/.*\[\(.*\)\]/\1/' < /proc/1/cmdline`
230 RUNLEVEL=`runlevel | cut -d" " -f2`
231 if [ "x$RUNLEVEL" = "x" ]; then
232 echo "Unable to determine current runlevel" >&2
233 exit 1
234 fi
235fi
236
237case $1 in
238 remove)
239 checklinks "remove"
240 ;;
241
242 defaults)
243 if [ $# -gt 3 ]; then
244 echo "defaults takes only one or two arguments" >&2
245 usage
246 exit 1
247 fi
248 start=20
249 stop=20
250 if [ $# -gt 1 ]; then
251 start=$2
252 stop=$2
253 fi
254 if [ $# -gt 2 ]; then
255 stop=$3
256 fi
257 start=`printf %02d $start`
258 stop=`printf %02d $stop`
259 stoplinks="0/$stop 1/$stop 6/$stop"
260 startlinks="2/$start 3/$start 4/$start 5/$start"
261 makelinks
262 ;;
263
264 start | stop)
265 if [ $# -lt 4 ]
266 then
267 echo "Not enough arguments"
268 usage
269 exit 1
270 fi
271
272 while [ $# -gt 0 ]; do
273 if [ $1 = "start" ]; then
274 letter=S
275 elif [ $1 = "stop" ]; then
276 letter=K
277 else
278 echo "expected start or stop" >&2
279 usage
280 exit 1
281 fi
282 shift
283 NN=`printf %02d $(expr $1 + 0)`
284 shift
285 while [ "x$1" != "x." ]; do
286 if [ $# -eq 0 ]; then
287 echo "action with list of runlevels not terminated by \`.'" >&2
288 exit 1
289 fi
290 level=$1
291 shift
292 case $letter in
293 S) startlinks="$startlinks $level/$NN" ;;
294 K) stoplinks="$stoplinks $level/$NN" ;;
295 esac
296 done
297 shift
298 done
299 makelinks
300 ;;
301
302 enable | disable)
303 if [ $1 = "enable" ]; then
304 letter=S
305 elif [ $1 = "disable" ]; then
306 letter=K
307 else
308 usage
309 exit 1
310 fi
311 shift
312 #
313 if [ $# -gt 0 ]
314 then
315 case $1 in
316 S|2|3|4|5)
317 renamelinks $letter $1
318 ;;
319 *)
320 usage
321 exit 1
322 ;;
323 esac
324 else
325 renamelinks $letter
326 fi
327 ;;
328 *)
329 usage
330 exit 1
331 ;;
332esac