/[baselayout]/trunk/sbin/runscript.sh
Gentoo

Contents of /trunk/sbin/runscript.sh

Parent Directory Parent Directory | Revision Log Revision Log


Revision 345 - (show annotations) (download) (as text)
Sun Apr 6 16:28:27 2003 UTC (16 years ago) by azarah
File MIME type: text/x-sh
File size: 14852 byte(s)
various fixes; moved .c files to src

1 #!/bin/bash
2 # Copyright 1999-2003 Gentoo Technologies, Inc.
3 # Distributed under the terms of the GNU General Public License v2
4 # $Header$
5
6
7 source /sbin/functions.sh
8 source /sbin/rc-daemon.sh
9
10 # State variables
11 svcpause="no"
12 svcrestart="no"
13
14 myscript="$1"
15 if [ -L "$1" ]
16 then
17 myservice="$(readlink "$1")"
18 else
19 myservice="$1"
20 fi
21
22 myservice="${myservice##*/}"
23 mylevel="$(cat "${svcdir}/softlevel")"
24
25
26 # Set $IFACE to the name of the network interface if it is a 'net.*' script
27 IFACE=""
28 NETSERVICE=""
29 if [ "${myservice%%.*}" = "net" -a "${myservice##*.}" != "${myservice}" ]
30 then
31 IFACE="${myservice##*.}"
32 NETSERVICE="yes"
33 fi
34
35 # Source configuration files.
36 # (1) Source /etc/conf.d/basic to get common configuration.
37 # (2) Source /etc/conf.d/${myservice} to get initscript-specific
38 # configuration (if it exists).
39 # (3) Source /etc/conf.d/net if it is a net.* service
40 # (4) Source /etc/rc.conf to pick up potentially overriding
41 # configuration, if the system administrator chose to put it
42 # there (if it exists).
43
44 [ -e /etc/conf.d/basic ] && source /etc/conf.d/basic
45
46 [ -e "/etc/conf.d/${myservice}" ] && source "/etc/conf.d/${myservice}"
47
48 [ -e /etc/conf.d/net ] && \
49 [ "${myservice%%.*}" = "net" ] && \
50 [ "${myservice##*.}" != "${myservice}" ] && source /etc/conf.d/net
51
52 [ -e /etc/rc.conf ] && source /etc/rc.conf
53
54 usage() {
55 local IFS="|"
56 myline="Usage: ${myservice} { $* "
57 echo
58 eerror "${myline}}"
59 eerror " ${myservice} without arguments for full help"
60 }
61
62 stop() {
63 # Return success so the symlink gets removed
64 return 0
65 }
66
67 start() {
68 eerror "ERROR: \"${myservice}\" does not have a start function."
69 # Return failure so the symlink doesn't get created
70 return 1
71 }
72
73 restart() {
74 svc_restart || return $?
75 }
76
77 status() {
78 # Dummy function
79 return 0
80 }
81
82 svc_stop() {
83 local x=""
84 local mydep=""
85 local mydeps=""
86 local retval=0
87 local ordservice=""
88
89 if [ ! -L "${svcdir}/started/${myservice}" ]
90 then
91 if [ "${RC_QUIET_STDOUT}" != "yes" ]
92 then
93 eerror "ERROR: \"${myservice}\" has not yet been started."
94 return 1
95 else
96 return 0
97 fi
98 fi
99
100 # Do not try to stop if it had already failed to do so on runlevel change
101 if [ -L "${svcdir}/failed/${myservice}" -a -d "${svcdir}/softscripts.new" ]
102 then
103 exit 1
104 fi
105
106 # Remove symlink to prevent recursion
107 rm -f "${svcdir}/started/${myservice}"
108
109 if [ -L "/etc/init.d/boot/${myservice}" ]
110 then
111 ewarn "WARNING: you are stopping a boot service."
112 fi
113 if [ "${NETSERVICE}" = "yes" ]
114 then
115 # A net.* service
116 if [ -L "/etc/runlevels/boot/${myservice}" -o \
117 -L "/etc/runlevels/${mylevel}/${myservice}" ]
118 then
119 local netcount="$(ls -1 "${svcdir}"/started/net.* 2> /dev/null | \
120 grep -v 'net\.lo' | egrep -c "\/net\.[[:alnum:]]+$")"
121
122 # Only worry about net.* services if this is the last one running,
123 # or if RC_NET_STRICT_CHECKING is set ...
124 if [ "${netcount}" -lt 1 -o "${RC_NET_STRICT_CHECKING}" = "yes" ]
125 then
126 mydeps="net"
127 fi
128 fi
129
130 mydeps="${mydeps} ${myservice}"
131 else
132 mydeps="${myservice}"
133 fi
134 if [ "${svcpause}" = "yes" ]
135 then
136 mydeps=""
137 fi
138 for mydep in ${mydeps}
139 do
140 # Do not stop a service if it 'use' the current sevice, or on rc change
141 # and it should be started 'after' this service ...
142 if [ -d "${svcdir}/need/${mydep}" ] || \
143 ([ -d "${svcdir}/softscripts.new" -a -d "${svcdir}/after/${mydep}" ])
144 then
145 # On rc change, stop all services "after $myservice" first
146 if [ -d "${svcdir}/softscripts.new" ]
147 then
148 local servicelist="$(dolisting "${svcdir}/need/${mydep}/") \
149 $(dolisting "${svcdir}/after/${mydep}/")"
150 else
151 local servicelist="$(dolisting "${svcdir}/need/${mydep}/")"
152 fi
153 for x in ${servicelist}
154 do
155 if [ ! -L "${x}" ]
156 then
157 continue
158 fi
159 if [ ! -L "${svcdir}/started/${x##*/}" ]
160 then
161 # Service not currently running, continue
162 continue
163 fi
164 if [ -L "${svcdir}/before/${x}/${mydep}" -a \
165 -L "${svcdir}/softscripts.new/${x}" ]
166 then
167 continue
168 fi
169 "${x}" stop
170 if [ "$?" -ne 0 ]
171 then
172 # If we are halting the system, try and get it down as
173 # clean as possible, else do not stop our service if
174 # a dependent service did not stop.
175 if [ "${SOFTLEVEL}" != "reboot" -a \
176 "${SOFTLEVEL}" != "shutdown" -a \
177 -L "${svcdir}/need/${mydep}/${x}" ]
178 then
179 retval=1
180 fi
181 break
182 fi
183 done
184 fi
185 done
186
187 if [ "${retval}" -ne 0 ]
188 then
189 eerror "ERROR: problems stopping dependent services."
190 eerror " \"${myservice}\" is still up."
191 else
192 # Now that deps are stopped, stop our service
193 stop
194 retval="$?"
195 fi
196
197 if [ "${retval}" -ne 0 ]
198 then
199 # Did we fail to stop? create symlink to stop multible attempts at
200 # runlevel change. Note this is only used at runlevel change ...
201 if [ -d "${svcdir}/failed" ]
202 then
203 ln -snf "/etc/init.d/${myservice}" "${svcdir}/failed/${myservice}"
204 fi
205 # If we are halting the system, do it as cleanly as possible
206 if [ "${SOFTLEVEL}" != "reboot" -a "${SOFTLEVEL}" != "shutdown" ]
207 then
208 ln -snf "/etc/init.d/${myservice}" "${svcdir}/started/${myservice}"
209 fi
210 fi
211
212 return "${retval}"
213 }
214
215 svc_start() {
216 local retval=0
217 local startfail="no"
218 local x=""
219 local y=""
220 local myserv=""
221 local ordservice=""
222
223 if [ ! -L "${svcdir}/started/${myservice}" ]
224 then
225 # Do not try to start if i have done so already on runlevel change
226 if [ -L "${svcdir}/failed/${myservice}" -a -d "${svcdir}/softscripts.old" ]
227 then
228 exit 1
229 fi
230
231 # Link first to prevent possible recursion
232 ln -snf "/etc/init.d/${myservice}" "${svcdir}/started/${myservice}"
233
234 # On rc change, start all services "before $myservice" first
235 if [ -d "${svcdir}/softscripts.old" ]
236 then
237 startupservices="$(ineed "${myservice}") \
238 $(valid_iuse "${myservice}") \
239 $(valid_iafter "${myservice}")"
240 else
241 startupservices="$(ineed "${myservice}") \
242 $(valid_iuse "${myservice}")"
243 fi
244
245 # Start dependencies, if any
246 for x in ${startupservices}
247 do
248 if [ "${x}" = "net" -a "${NETSERVICE}" != "yes" ]
249 then
250 local netservlist="$(dolisting "/etc/runlevels/boot/net.*") \
251 $(dolisting "/etc/runlevels/${mylevel}/net.*")"
252
253 for y in ${netservlist}
254 do
255 myserv="${y##*/}"
256 if [ ! -L "${svcdir}/started/${myserv}" ]
257 then
258 /etc/init.d/"${myserv}" start
259
260 # A 'need' dependency is critical for startup
261 if [ "$?" -ne 0 -a -L "${svcdir}/need/${x}/${myservice}" ]
262 then
263 local netcount="$(ls -1 ${svcdir}/started/net.* 2> /dev/null | \
264 grep -v 'net\.lo' | egrep -c "\/net\.[[:alnum:]]+$")"
265
266 # Only worry about a net.* service if we do not have one
267 # up and running already, or if RC_NET_SCTRICT_CHECKING
268 # is set ....
269 if [ "${netcount}" -lt 1 -o "${RC_NET_STRICT_CHECKING}" = "yes" ]
270 then
271 startfail="yes"
272 fi
273 fi
274 fi
275 done
276
277 elif [ "${x}" != "net" ]
278 then
279 if [ ! -L "${svcdir}/started/${x}" ]
280 then
281 /etc/init.d/"${x}" start
282
283 # A 'need' dependacy is critical for startup
284 if [ "$?" -ne 0 -a -L "${svcdir}/need/${x}/${myservice}" ]
285 then
286 startfail="yes"
287 fi
288 fi
289 fi
290 done
291
292 if [ "${startfail}" = "yes" ]
293 then
294 eerror "ERROR: Problem starting needed services."
295 eerror " \"${myservice}\" was not started."
296 retval=1
297 fi
298
299 # Start service
300 if [ -d "${svcdir}/broken/${myservice}" -a "${retval}" -eq 0 ]
301 then
302 eerror "ERROR: Some services needed are missing. Run"
303 eerror " './${myservice} broken' for a list of those"
304 eerror " services. \"${myservice}\" was not started."
305 retval=1
306 elif [ ! -d "${svcdir}/broken/${myservice}" -a "${retval}" -eq 0 ]
307 then
308 start
309 retval="$?"
310 fi
311
312 if [ "${retval}" -ne 0 -a -d "${svcdir}/failed" ]
313 then
314 ln -snf "/etc/init.d/${myservice}" "${svcdir}/failed/${myservice}"
315 fi
316
317 # Remove link if service didn't start; but only if we're not booting
318 # if we're booting, we need to continue and do our best to get the
319 # system up.
320 if [ "${retval}" -ne 0 -a "${SOFTLEVEL}" != "boot" ]
321 then
322 rm -f "${svcdir}/started/${myservice}"
323 fi
324 return "${retval}"
325 else
326 if [ "${RC_QUIET_STDOUT}" != "yes" ]
327 then
328 ewarn "WARNING: \"${myservice}\" has already been started."
329 fi
330
331 return 0
332 fi
333 }
334
335 svc_restart() {
336 if [ -L "${svcdir}/started/${myservice}" ]
337 then
338 svc_stop || return "$?"
339 sleep 1
340 fi
341
342 svc_start || return "$?"
343 }
344
345 svc_status() {
346 # The basic idea here is to have some sort of consistant
347 # output in the status() function which scripts can use
348 # as an generic means to detect status. Any other output
349 # should thus be formatted in the custom status() function
350 # to work with the printed " * status: foo".
351
352 if [ -L "${svcdir}/started/${myservice}" ]
353 then
354 if [ "${RC_QUIET_STDOUT}" != "yes" ]
355 then
356 einfo "status: started"
357 else
358 return 0
359 fi
360 else
361 if [ "${RC_QUIET_STDOUT}" != "yes" ]
362 then
363 eerror "status: stopped"
364 else
365 return 1
366 fi
367 fi
368
369 status
370 }
371
372 wrap_rcscript "${myscript}" || {
373 eerror "ERROR: \"${myscript}\" has syntax errors in it; not executing..."
374 exit 1
375 }
376
377 # set *after* wrap_rcscript, else we get duplicates.
378 opts="start stop restart"
379
380 source "${myscript}"
381
382 # make sure whe have valid $opts
383 if [ -z "${opts}" ]
384 then
385 opts="start stop restart"
386 fi
387
388 # does $1 depend on $2 ?
389 dependon() {
390 if [ -L "${svcdir}/need/$2/$1" -o -L "${svcdir}/use/$2/$1" ]
391 then
392 return 0
393 else
394 return 1
395 fi
396 }
397
398 needsme() {
399 local x=""
400 if [ -d "${svcdir}/need/$1" ]
401 then
402 for x in $(dolisting "${svcdir}/need/$1/")
403 do
404 if [ ! -L "${x}" ]
405 then
406 continue
407 fi
408 echo "${x##*/}"
409 done
410 fi
411 }
412
413 usesme() {
414 local x=""
415 if [ -d "${svcdir}/use/$1" ]
416 then
417 for x in $(dolisting "${svcdir}/use/$1/")
418 do
419 if [ ! -L "${x}" ]
420 then
421 continue
422 fi
423 echo "${x##*/}"
424 done
425 fi
426 }
427
428 ineed() {
429 local x=""
430 local z=""
431 for x in $(dolisting "${svcdir}"/need/*/"$1")
432 do
433 if [ ! -L "${x}" ]
434 then
435 continue
436 fi
437 z="${x%/*}"
438 echo "${z##*/}"
439 done
440 }
441
442 # This will give all the use's of the service, even if not in current or boot
443 # runlevels
444 iuse() {
445 local x=""
446 local z=""
447 for x in $(dolisting "${svcdir}"/use/*/"$1")
448 do
449 if [ ! -L "${x}" ]
450 then
451 continue
452 fi
453 z="${x%/*}"
454 echo "${z##*/}"
455 done
456 }
457
458 # This will only give the valid use's for the service (they must be in the boot
459 # or current runlevel)
460 valid_iuse() {
461 local x=""
462 local y=""
463 for x in $(iuse "$1")
464 do
465 if [ -e "/etc/runlevels/boot/${x}" -o \
466 -e "/etc/runlevels/${mylevel}/${x}" ]
467 then
468 z="${x%/*}"
469 echo "${z##*/}"
470 fi
471 done
472 }
473
474 # List of services that should start before $1 on rc change
475 iafter() {
476 local x=""
477 local z=""
478 for x in $(dolisting "${svcdir}"/after/*/"$1")
479 do
480 if [ ! -L ${x} ]
481 then
482 continue
483 fi
484 z="${x%/*}"
485 echo "${z##*/}"
486 done
487 }
488
489 # Valid services for current or boot rc level that should start
490 # before $1
491 valid_iafter() {
492 local x=""
493 local y=""
494 for x in $(iafter "$1")
495 do
496 if [ -e "/etc/runlevels/boot/${x}" -o \
497 -e "/etc/runlevels/${mylevel}/${x}" ]
498 then
499 z="${x%/*}"
500 echo "${z##*/}"
501 fi
502 done
503 }
504
505 # List broken dependencies of type 'need'
506 broken() {
507 local x=""
508 if [ -d "${svcdir}/broken/$1" ]
509 then
510 for x in $(dolisting "${svcdir}/broken/$1/")
511 do
512 if [ ! -f "${x}" ]
513 then
514 continue
515 fi
516 echo "${x##*/}"
517 done
518 fi
519 }
520
521 # Call this with "needsme", "ineed", "usesme", "iuse" or "broken" as first arg
522 query() {
523 local deps=""
524 local x=""
525 install -d -m0755 "${svcdir}/depcheck/$$"
526 if [ "$1" = "ineed" -a ! -L "${svcdir}/started/${myservice}" ]
527 then
528 ewarn "WARNING: \"${myservice}\" not running."
529 ewarn " NEED info may not be accurate."
530 fi
531 if [ "$1" = "iuse" -a ! -L "${svcdir}/started/${myservice}" ]
532 then
533 ewarn "WARNING: \"${myservice}\" not running."
534 ewarn " USE info may not be accurate."
535 fi
536
537 deps="${myservice}"
538 while [ -n "${deps}" ]
539 do
540 deps="$($1 ${deps})"
541 for x in ${deps}
542 do
543 if [ ! -e "${svcdir}/depcheck/$$/${x}" ]
544 then
545 touch "${svcdir}/depcheck/$$/${x}"
546 fi
547 done
548 done
549 for x in $(dolisting "${svcdir}/depcheck/$$/")
550 do
551 if [ ! -e "${x}" ]
552 then
553 continue
554 fi
555 echo "${x##*/}"
556 done
557 rm -rf "${svcdir}/depcheck"
558 }
559
560 svc_homegrown() {
561 local arg="$1"
562 local x=""
563 # Walk through the list of available options, looking for the
564 # requested one.
565 for x in ${opts}
566 do
567 if [ "${x}" = "${arg}" ]
568 then
569 if typeset -F "${x}" &>/dev/null
570 then
571 # Run the homegrown function
572 "${x}"
573 return $?
574 else
575 # This is a weak error message
576 ewarn "WARNING: function \"${x}\" doesn't exist."
577 # Do not quote this ....
578 usage ${opts}
579 exit 1
580 fi
581 fi
582 done
583 # If we're here, then the function wasn't in $opts. This is
584 # the same error message that used to be in the case statement
585 # before homegrown functions were supported.
586 eerror "ERROR: wrong args. ( "${arg}" / $* )"
587 # Do not quote this either ...
588 usage ${opts}
589 exit 1
590 }
591
592 shift
593 if [ "$#" -lt 1 ]
594 then
595 eerror "ERROR: not enough args."
596 usage ${opts}
597 exit 1
598 fi
599 for arg in $*
600 do
601 case "${arg}" in
602 --quiet)
603 RC_QUIET_STDOUT="yes"
604 ;;
605 # We check this in functions.sh ...
606 # --nocolor)
607 # RC_NOCOLOR="yes"
608 # ;;
609 esac
610 done
611 for arg in $*
612 do
613 case "${arg}" in
614 stop)
615 svc_stop
616 ;;
617 start)
618 svc_start
619 ;;
620 needsme|ineed|usesme|iuse|broken)
621 query "${arg}"
622 ;;
623 status)
624 svc_status
625 ;;
626 zap)
627 if [ -e "${svcdir}/started/${myservice}" ]
628 then
629 einfo "Manually resetting ${myservice} to stopped state."
630 rm -f "${svcdir}/started/${myservice}"
631 fi
632 ;;
633 restart)
634 svcrestart="yes"
635
636 # Create a snapshot of started services
637 rm -rf "${svcdir}"/snapshot/*
638 cp -a "${svcdir}"/started/* "${svcdir}/snapshot/"
639
640 # Simple way to try and detect if the service use svc_{start,stop}
641 # to restart if it have a custom restart() funtion.
642 if [ -n "$(egrep '^[[:space:]]*restart[[:space:]]*()' "/etc/init.d/${myservice}")" ]
643 then
644 if [ -z "$(egrep 'svc_stop' "/etc/init.d/${myservice}")" -o \
645 -z "$(egrep 'svc_start' "/etc/init.d/${myservice}")" ]
646 then
647 echo
648 ewarn "Please use 'svc_stop; svc_start' and not 'start; stop' to"
649 ewarn "restart the service in its custom 'restart()' function."
650 ewarn "Run ${myservice} without arguments for more info."
651 echo
652 svc_restart
653 else
654 restart
655 fi
656 else
657 restart
658 fi
659
660 # Restart dependencies as well
661 if [ -L "${svcdir}/started/${myservice}" ]
662 then
663 for x in $(dolisting "${svcdir}/snapshot/")
664 do
665 if [ ! -L "${svcdir}/started/${x##*/}" ]
666 then
667 "${x}" start
668 fi
669 done
670 fi
671 svcrestart="no"
672 ;;
673 pause)
674 svcpause="yes"
675 svc_stop
676 svcpause="no"
677 ;;
678 --quiet|--nocolor)
679 ;;
680 *)
681 # Allow for homegrown functions
682 svc_homegrown ${arg}
683 ;;
684 esac
685 done
686
687
688 # vim:ts=4

Properties

Name Value
svn:eol-style native
svn:executable *
svn:keywords Author Date Id Revision

  ViewVC Help
Powered by ViewVC 1.1.20