/[baselayout]/branches/baselayout-1_12/sbin/rc-services.sh
Gentoo

Contents of /branches/baselayout-1_12/sbin/rc-services.sh

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2091 - (show annotations) (download) (as text)
Wed Jun 14 21:13:31 2006 UTC (8 years, 5 months ago) by uberlord
File MIME type: text/x-sh
File size: 21553 byte(s)
    {start,stop}_volumes moved to rc and halt.sh respectively.

    net services are now depended upon more correctly.
1 # Copyright 1999-2004 Gentoo Foundation
2 # Distributed under the terms of the GNU General Public License v2
3
4 # RC Dependency and misc service functions
5 RC_GOT_SERVICES="yes"
6
7 [[ ${RC_GOT_FUNCTIONS} != "yes" ]] && source /sbin/functions.sh
8
9 if [[ ${RC_GOT_DEPTREE_INFO} != "yes" ]] ; then
10 # Only try and update if we are root
11 if [[ ${EUID} == "0" ]] && ! /sbin/depscan.sh ; then
12 echo
13 eerror "Error running '/sbin/depscan.sh'!"
14 eerror "Please correct any problems above."
15 exit 1
16 fi
17
18 source "${svcdir}/deptree"
19 if [[ ${RC_GOT_DEPTREE_INFO} != "yes" ]] ; then
20 echo
21 eerror "Dependency info is missing! Please run"
22 eerror " # /sbin/depscan.sh"
23 eerror "to fix this."
24 exit 1
25 fi
26 fi
27
28 #####################
29 # Internal variables
30 #####################
31
32 # The name of the service whose dependency info we currently have
33 rc_name=
34 # The index of the service whose dependency info we currently have
35 rc_index=0
36 # Our dependency types ...
37 rc_ineed=
38 rc_needsme=
39 rc_iuse=
40 rc_usesme=
41 rc_ibefore=
42 rc_iafter=
43 rc_broken=
44 rc_mtime=
45
46 ############
47 # Functions
48 ############
49
50 # bool get_service_index(service, index)
51 #
52 # Print the index of 'service'. 'index' is the current index.
53 #
54 get_service_index() {
55 if [[ -z $1 || -z $2 ]] ; then
56 echo "0"
57 return 1
58 fi
59
60 local x myservice="$1" index="$2"
61
62 # Do we already have the index?
63 if [[ -n ${index} && ${index} -gt 0 \
64 && ${myservice} == "${RC_DEPEND_TREE[${index}]}" ]] ; then
65 echo "${index}"
66 return 0
67 fi
68
69 for (( x=1; x<=${RC_DEPEND_TREE[0]}; x++ )); do
70 index="$(( ${x} * ${rc_index_scale} ))"
71 if [[ ${myservice} == "${RC_DEPEND_TREE[${index}]}" ]] ; then
72 echo "${index}"
73 return 0
74 fi
75 done
76
77 echo "0"
78 return 1
79 }
80
81 # bool get_dep_info(service)
82 #
83 # Set the Dependency variables to contain data for 'service'
84 #
85 get_dep_info() {
86 [[ -z $1 ]] && return 1
87
88 local myservice="$1"
89
90 # We already have the right stuff ...
91 [[ ${myservice} == "${rc_name}" && -n ${rc_mtime} ]] && return 0
92
93 rc_index="$(get_service_index "${myservice}" "${rc_index}")"
94 rc_mtime="${RC_DEPEND_TREE[$((${rc_index} + ${rc_type_mtime}))]}"
95
96 # Verify that we have the correct index (rc_index) ...
97 # [[ ${rc_index} == "0" ]] && return 1
98
99 rc_name="${RC_DEPEND_TREE[${rc_index}]}"
100 rc_ineed="${RC_DEPEND_TREE[$((${rc_index} + ${rc_type_ineed}))]}"
101 rc_needsme="${RC_DEPEND_TREE[$((${rc_index} + ${rc_type_needsme}))]}"
102 rc_iuse="${RC_DEPEND_TREE[$((${rc_index} + ${rc_type_iuse}))]}"
103 rc_usesme="${RC_DEPEND_TREE[$((${rc_index} + ${rc_type_usesme}))]}"
104 rc_ibefore="${RC_DEPEND_TREE[$((${rc_index} + ${rc_type_ibefore}))]}"
105 rc_iafter="${RC_DEPEND_TREE[$((${rc_index} + ${rc_type_iafter}))]}"
106 rc_broken="${RC_DEPEND_TREE[$((${rc_index} + ${rc_type_broken}))]}"
107 rc_mtime="${RC_DEPEND_TREE[$((${rc_index} + ${rc_type_mtime}))]}"
108 return 0
109 }
110
111 # string check_dependency(deptype, service1)
112 #
113 # List all the services that depend on 'service1' of dependency
114 # type 'deptype'
115 #
116 # bool check_dependency(deptype, -t, service1, service2)
117 #
118 # Returns true if 'service2' is a dependency of type 'deptype'
119 # of 'service1'
120 #
121 check_dependency() {
122 [[ -z $1 || -z $2 ]] && return 1
123
124 local x myservice deps
125
126 # Set the dependency variables to relate to 'service1'
127 if [[ $2 == "-t" ]] ; then
128 [[ -z $3 || -z $4 ]] && return 1
129 myservice="$3"
130 else
131 myservice="$2"
132 fi
133
134 if ! get_dep_info "${myservice}" >/dev/null ; then
135 eerror "Could not get dependency info for ${myservice}!" > /dev/stderr
136 eerror "Please run:" > /dev/stderr
137 eerror " # /sbin/depscan.sh" > /dev/stderr
138 eerror "to try and fix this." > /dev/stderr
139 return 1
140 fi
141
142 # Do we have valid info for 'deptype' ?
143 deps="rc_$1"
144 [[ -z ${!deps} ]] && return 1
145
146 if [[ $2 == "-t" && -n $4 ]]; then
147 # Check if 'service1' have 'deptype' dependency on 'service2'
148 for x in ${!deps} ; do
149 [[ ${x} == "$4" ]] && return 0
150 done
151 return 1
152 else
153 # Just list all services that 'service1' have 'deptype' dependency on.
154 echo "${!deps}"
155 return 0
156 fi
157 }
158
159 # Same as for check_dependency, except 'deptype' is set to
160 # 'ineed'. It will return all the services 'service1' NEED's.
161 ineed() {
162 check_dependency ineed "$@"
163 }
164
165 # Same as for check_dependency, except 'deptype' is set to
166 # 'needsme'. It will return all the services that NEED 'service1'.
167 needsme() {
168 check_dependency needsme "$@"
169 }
170
171 # Same as for check_dependency, except 'deptype' is set to
172 # 'iuse'. It will return all the services 'service1' USE's.
173 iuse() {
174 check_dependency iuse "$@"
175 }
176
177 # Same as for check_dependency, except 'deptype' is set to
178 # 'usesme'. It will return all the services that USE 'service1'.
179 usesme() {
180 check_dependency usesme "$@"
181 }
182
183 # Same as for check_dependency, except 'deptype' is set to
184 # 'ibefore'. It will return all the services that are started
185 # *after* 'service1' (iow, it will start 'service1' before the
186 # list of services returned).
187 ibefore() {
188 check_dependency ibefore "$@"
189 }
190
191 # Same as for check_dependency, except 'deptype' is set to
192 # 'iafter'. It will return all the services that are started
193 # *before* 'service1' (iow, it will start 'service1' after the
194 # list of services returned).
195 iafter() {
196 check_dependency iafter "$@"
197 }
198
199 # Same as for check_dependency, except 'deptype' is set to
200 # 'broken'. It will return all the services that 'service1'
201 # NEED, but are not present.
202 broken() {
203 check_dependency broken "$@"
204 }
205
206 # bool is_fake_service(service, runlevel)
207 #
208 # Returns ture if 'service' is a fake service in 'runlevel'.
209 #
210 is_fake_service() {
211 local x fake_services
212
213 [[ -z $1 || -z $2 ]] && return 1
214
215 [[ $2 != "${BOOTLEVEL}" && -e /etc/runlevels/"${BOOTLEVEL}"/.fake ]] && \
216 fake_services="$( < /etc/runlevels/"${BOOTLEVEL}"/.fake )"
217
218 [[ -e /etc/runlevels/"$2"/.fake ]] && \
219 fake_services="${fake_services} $( < /etc/runlevels/"$2"/.fake )"
220
221 for x in ${fake_services} ; do
222 [[ $1 == "${x##*/}" ]] && return 0
223 done
224
225 return 1
226 }
227
228 # bool in_runlevel(service, runlevel)
229 #
230 # Returns true if 'service' is in runlevel 'runlevel'.
231 #
232 in_runlevel() {
233 [[ -z $1 || -z $2 ]] && return 1
234
235 [[ -L "/etc/runlevels/$2/$1" ]] && return 0
236
237 return 1
238 }
239
240 # bool is_runlevel_start()
241 #
242 # Returns true if it is a runlevel change, and we are busy
243 # starting services.
244 #
245 is_runlevel_start() {
246 [[ -d "${svcdir}/softscripts.old" ]]
247 }
248
249 # bool is_runlevel_stop()
250 #
251 # Returns true if it is a runlevel change, and we are busy
252 # stopping services.
253 #
254 is_runlevel_stop() {
255 [[ -d "${svcdir}/softscripts.new" ]]
256 }
257
258 # void save_options(char *option, char *optstring)
259 #
260 # save the settings ("optstring") for "option"
261 #
262 save_options() {
263 local myopts="$1"
264
265 shift
266 if [[ ! -d "${svcdir}/options/${SVCNAME}" ]] ; then
267 mkdir -p -m 0755 "${svcdir}/options/${SVCNAME}"
268 fi
269
270 echo "$*" > "${svcdir}/options/${SVCNAME}/${myopts}"
271 }
272
273 # char *get_options(char *option)
274 #
275 # get the "optstring" for "option" that was saved
276 # by calling the save_options function
277 #
278 get_options() {
279 local svc="${SVCNAME}"
280 [[ -n $2 ]] && svc="$2"
281
282 if [[ -f "${svcdir}/options/${svc}/$1" ]] ; then
283 echo "$(< ${svcdir}/options/${svc}/$1)"
284 fi
285 }
286
287 # void sevice_message([char *type] char *message)
288 #
289 # Print out a service message if we are on parallel
290 service_message() {
291 [[ ${RC_PARALLEL_STARTUP} != "yes" || ${RC_QUIET} == "yes" ]] && return
292
293 local cmd="einfo"
294 case "$1" in
295 1|error|eerror)
296 cmd="eerror"
297 shift
298 ;;
299 ewarn)
300 cmd="ewarn"
301 shift
302 ;;
303 esac
304
305 local r="${RC_QUIET_STDOUT}"
306 RC_QUIET_STDOUT="no"
307 ${cmd} "$@"
308 RC_QUIET_STDOUT="${r}"
309 }
310
311 # bool begin_service( service )
312 #
313 # atomically marks the service as being executed
314 # use like this:
315 #
316 # if begin_service service ; then
317 # whatever is in here can only be executed by one process
318 # end_service service
319 # fi
320 begin_service() {
321 local service="$1"
322 [[ -z ${service} ]] && return 1
323
324 [[ ${START_CRITICAL} == "yes" || ${STOP_CRITICAL} == "yes" ]] && return 0
325
326 mkfifo "${svcdir}/exclusive/${service}" 2> /dev/null
327 }
328
329 # void end_service(service, exitcode)
330 #
331 # stops executing a exclusive region and
332 # wakes up anybody who is waiting for the exclusive region
333 #
334 end_service() {
335 local service="$1" exitstatus="$2"
336 [[ -z ${service} ]] && return
337
338 # if we are doing critical services, there is no fifo
339 [[ ${START_CRITICAL} == "yes" || ${STOP_CRITICAL} == "yes" ]] && return
340
341 if [[ -n ${exitstatus} ]] ; then
342 echo "${exitstatus}" > "${svcdir}/exitcodes/${service}"
343 fi
344
345 # move the fifo to a unique name so no-one is waiting for it
346 local fifo="${svcdir}/exclusive/${service}"
347 if [[ -e ${fifo} ]] ; then
348 local tempname="${fifo}.$$"
349 mv -f "${fifo}" "${tempname}"
350
351 # wake up anybody that was waiting for the fifo
352 touch "${tempname}"
353
354 # We dont need the fifo anymore
355 rm -f "${tempname}"
356 fi
357 }
358
359 # int wait_service(service)
360 #
361 # If a service has started, or a fifo does not exist return 0
362 # Otherwise, wait until we get an exit code via the fifo and return
363 # that instead.
364 wait_service() {
365 local service="$1"
366 local fifo="${svcdir}/exclusive/${service}"
367
368 [[ ${START_CRITICAL} == "yes" || ${STOP_CRITICAL} == "yes" ]] && return 0
369 [[ ! -e ${fifo} ]] && return 0
370
371 # This will block until the service fifo is touched
372 # Otheriwse we don't block
373 # We need to use cat instead of the bash inbuilt < so we don't see errors
374 local tmp="$( cat "${fifo}" 2>/dev/null )"
375 local exitstatus="$( < "${svcdir}/exitcodes/${service}" )"
376
377 return "${exitstatus}"
378 }
379
380 # int start_service(service)
381 #
382 # Start 'service' if it is not already running.
383 #
384 start_service() {
385 local service="$1"
386 [[ -z ${service} ]] && return 1
387
388 if [[ ! -e "/etc/init.d/${service}" ]] ; then
389 mark_service_stopped "${service}"
390 return 1
391 fi
392
393 service_starting "${service}" && return 0
394 service_started "${service}" && return 0
395 service_inactive "${service}" && return 1
396
397 if is_fake_service "${service}" "${SOFTLEVEL}" ; then
398 mark_service_started "${service}"
399 splash "svc_start" "${service}"
400 splash "svc_started" "${service}" "0"
401 return 0
402 fi
403
404 begin_service "${service}" || return 0
405 splash "svc_start" "${service}"
406 if [[ ${RC_PARALLEL_STARTUP} != "yes" || \
407 ${START_CRITICAL} == "yes" ]] ; then
408 # if we can not start the services in parallel
409 # then just start it and return the exit status
410 ( "/etc/init.d/${service}" start )
411 service_started "${service}" || service_inactive "${service}"
412 retval=$?
413 end_service "${service}" "${retval}"
414 splash "svc_started" "${service}" "${retval}"
415 return "${retval}"
416 else
417 # if parallel startup is allowed, start it in background
418 (
419 "/etc/init.d/${service}" start
420 service_started "${service}" || service_inactive "${service}"
421 retval=$?
422 end_service "${service}" "${retval}"
423 splash "svc_started" "${service}" "${retval}"
424 ) &
425 return 0
426 fi
427 }
428
429 # int stop_service(service)
430 #
431 # Stop 'service' if it is not already running.
432 #
433 stop_service() {
434 local service="$1"
435 [[ -z ${service} ]] && return 1
436
437 if [[ ! -e "/etc/init.d/${service}" ]] ; then
438 mark_service_stopped "${service}"
439 return 0
440 fi
441
442 service_stopping "${service}" && return 0
443 service_stopped "${service}" && return 0
444
445 local level="${SOFTLEVEL}"
446 is_runlevel_stop && level="${OLDSOFTLEVEL}"
447
448 if is_fake_service "${service}" "${level}" ; then
449 splash "svc_stop" "${service}"
450 mark_service_stopped "${service}"
451 splash "svc_stopped" "${service}" "0"
452 return 0
453 fi
454
455 begin_service "${service}" || return 0
456
457 splash "svc_stop" "${service}"
458 if [[ ${RC_PARALLEL_STARTUP} != "yes" || \
459 ${STOP_CRITICAL} == "yes" ]] ; then
460 # if we can not start the services in parallel
461 # then just start it and return the exit status
462 ( "/etc/init.d/${service}" stop )
463 service_stopped "${service}"
464 retval=$?
465 end_service "${service}" "${retval}"
466 splash "svc_stopped" "${service}" "${retval}"
467 return "${retval}"
468 else
469 # if parallel startup is allowed, start it in background
470 (
471 ( "/etc/init.d/${service}" stop )
472 service_stopped "${service}"
473 retval=$?
474 end_service "${service}" "${retval}"
475 splash "svc_stopped" "${service}" "${retval}"
476 ) &
477 return 0
478 fi
479 }
480
481 # bool mark_service_coldplugged(service)
482 #
483 # Mark 'service' as coldplugged.
484 #
485 mark_service_coldplugged() {
486 [[ -z $1 ]] && return 1
487
488 ln -snf "/etc/init.d/$1" "${svcdir}/coldplugged/$1"
489 return 0
490 }
491
492 # bool mark_service_starting(service)
493 #
494 # Mark 'service' as starting.
495 #
496 mark_service_starting() {
497 [[ -z $1 ]] && return 1
498
499 ln -sn "/etc/init.d/$1" "${svcdir}/starting/$1" 2>/dev/null || return 1
500
501 [[ -f "${svcdir}/started/$1" ]] && rm -f "${svcdir}/started/$1"
502 [[ -f "${svcdir}/inactive/$1" ]] \
503 && mv "${svcdir}/inactive/$1" "${svcdir}/wasinactive/$1"
504 return 0
505 }
506
507 # bool mark_service_started(service)
508 #
509 # Mark 'service' as started.
510 #
511 mark_service_started() {
512 [[ -z $1 ]] && return 1
513
514 ln -snf "/etc/init.d/$1" "${svcdir}/started/$1"
515
516 rm -f "${svcdir}/starting/$1" "${svcdir}/inactive/$1" \
517 "${svcdir}/wasinactive/$1" "${svcdir}/stopping/$1" \
518 "${svcdir}"/scheduled/*/"$1"
519
520 return 0
521 }
522
523 # bool mark_service_inactive(service)
524 #
525 # Mark service as inactive
526 #
527 mark_service_inactive() {
528 [[ -z $1 ]] && return 1
529
530 ln -snf "/etc/init.d/$1" "${svcdir}/inactive/$1"
531
532 rm -f "${svcdir}/started/$1" "${svcdir}/wasinactive/$1" \
533 "${svcdir}/starting/$1" "${svcdir}/stopping/$1"
534
535 return 0
536 }
537
538 # bool mark_service_stopping(service)
539 #
540 # Mark 'service' as stopping.
541 #
542 mark_service_stopping() {
543 [[ -z $1 ]] && return 1
544
545 ln -sn "/etc/init.d/$1" "${svcdir}/stopping/$1" 2>/dev/null || return 1
546
547 rm -f "${svcdir}/started/$1"
548 [[ -f "${svcdir}/inactive/$1" ]] \
549 && mv "${svcdir}/inactive/$1" "${svcdir}/wasinactive/$1"
550
551 return 0
552 }
553
554 # bool mark_service_stopped(service)
555 #
556 # Mark 'service' as stopped.
557 #
558 mark_service_stopped() {
559 [[ -z $1 ]] && return 1
560
561 rm -Rf "${svcdir}/daemons/$1" "${svcdir}/starting/$1" \
562 "${svcdir}/started/$1" "${svcdir}/inactive/$1" \
563 "${svcdir}/wasinactive/$1" "${svcdir}/stopping/$1" \
564 "${svcdir}/scheduled/$1" "${svcdir}/options/$1" \
565 "${svcdir}/coldplugged/$1"
566
567 return 0
568 }
569
570 # bool test_service_state(char *service, char *state)
571 #
572 # Returns 0 if the service link exists and points to a file, otherwise 1
573 # If 1 then the link is erased if it exists
574 test_service_state() {
575 [[ -z $1 || -z $2 ]] && return 1
576
577 local f="${svcdir}/$2/$1"
578
579 # Service is in the state requested
580 [[ -L ${f} ]] && return 0
581
582 [[ ! -e ${f} ]] && rm -f "${f}"
583 return 1
584 }
585
586 # bool service_coldplugged(service)
587 #
588 # Returns true if 'service' is coldplugged
589 #
590 service_coldplugged() {
591 test_service_state "$1" "coldplugged"
592 }
593
594 # bool service_starting(service)
595 #
596 # Returns true if 'service' is starting
597 #
598 service_starting() {
599 test_service_state "$1" "starting"
600 }
601
602 # bool service_started(service)
603 #
604 # Returns true if 'service' is started
605 #
606 service_started() {
607 test_service_state "$1" "started"
608 }
609
610 # bool service_inactive(service)
611 #
612 # Returns true if 'service' is inactive
613 #
614 service_inactive() {
615 test_service_state "$1" "inactive"
616 }
617
618 # bool service_wasinactive(service)
619 #
620 # Returns true if 'service' is inactive
621 #
622 service_wasinactive() {
623 test_service_state "$1" "wasinactive"
624 }
625
626 # bool service_stopping(service)
627 #
628 # Returns true if 'service' is stopping
629 #
630 service_stopping() {
631 test_service_state "$1" "stopping"
632 }
633
634 # bool service_stopped(service)
635 #
636 # Returns true if 'service' is stopped
637 #
638 service_stopped() {
639 [[ -z $1 ]] && return 1
640
641 service_starting "$1" && return 1
642 service_started "$1" && return 1
643 service_stopping "$1" && return 1
644 service_inactive "$1" && return 1
645
646 return 0
647 }
648
649 # bool mark_service_failed(service)
650 #
651 # Mark service as failed for current runlevel. Note that
652 # this is only valid on runlevel change ...
653 #
654 mark_service_failed() {
655 [[ -z $1 || ! -d "${svcdir}/failed" ]] && return 1
656
657 ln -snf "/etc/init.d/$1" "${svcdir}/failed/$1"
658 }
659
660 # bool service_failed(service)
661 #
662 # Return true if 'service' have failed during this runlevel.
663 #
664 service_failed() {
665 [[ -n $1 && -L "${svcdir}/failed/$1" ]]
666 }
667
668 # bool service_started_daemon(char *interface, char *daemon, int index)
669 # Returns 0 if the service started the given daemon
670 # via start-stop-daemon, otherwise 1.
671 # If index is emtpy, then we don't care what the first daemon launched
672 # was, otherwise the daemon must also be at that index
673 service_started_daemon() {
674 local service="$1" daemon="$2" index="${3:-[0-9]*}"
675 local daemonfile="${svcdir}/daemons/${service}"
676
677 [[ ! -e ${daemonfile} ]] && return 1
678 grep -q '^RC_DAEMONS\['"${index}"'\]="'${daemon}'"$' "${daemonfile}"
679 }
680
681 # bool net_service(service)
682 #
683 # Returns true if 'service' is a service controlling a network interface
684 #
685 net_service() {
686 [[ -n $1 && ${1%%.*} == "net" && ${1#*.} != "$1" ]]
687 }
688
689 # bool is_net_up()
690 #
691 # Return true if service 'net' is considered up, else false.
692 #
693 # Notes for RC_NET_STRICT_CHECKING values:
694 # none net is up without checking anything - usefull for vservers
695 # lo Interface 'lo' is counted and if only it is up, net is up.
696 # no Interface 'lo' is not counted, and net is down even with it up,
697 # so there have to be at least one other interface up.
698 # yes All interfaces must be up.
699 is_net_up() {
700 local netcount=0
701
702 case "${RC_NET_STRICT_CHECKING}" in
703 none)
704 return 0
705 ;;
706 lo)
707 netcount="$(ls -1 "${svcdir}"/started/net.* 2> /dev/null | \
708 egrep -c "\/net\..*$")"
709 ;;
710 *)
711 netcount="$(ls -1 "${svcdir}"/started/net.* 2> /dev/null | \
712 grep -v 'net\.lo' | egrep -c "\/net\..*$")"
713 ;;
714 esac
715
716 # Only worry about net.* services if this is the last one running,
717 # or if RC_NET_STRICT_CHECKING is set ...
718 if [[ ${netcount} -lt 1 || ${RC_NET_STRICT_CHECKING} == "yes" ]] ; then
719 return 1
720 fi
721
722 return 0
723 }
724
725 # bool dependon(service1, service2)
726 #
727 # Does service1 depend (NEED or USE) on service2 ?
728 #
729 dependon() {
730 ineed -t "$1" "$2" || iuse -t "$1" "$2"
731 }
732
733 # string validi(use/after, service)
734 #
735 # This is the main code for valid_after and valid_iuse
736 # No point in writing it twice!
737 valid_i() {
738 local x
739 # Just set to dummy for now (don't know if $svcdir/softlevel exists yet).
740 local mylevel="${BOOTLEVEL}"
741
742 [[ $1 != "after" && $1 != "use" ]] && return 1
743
744 # Cannot be SOFTLEVEL, as we need to know current runlevel
745 [[ -f "${svcdir}/softlevel" ]] && mylevel=$( < "${svcdir}/softlevel" )
746
747 for x in $( i$1 "$2" ) ; do
748 [[ -e "/etc/runlevels/${BOOTLEVEL}/${x}" || \
749 -e "/etc/runlevels/${mylevel}/${x}" || \
750 ${x} == "net" ]] \
751 && echo "${x}"
752 done
753 return 0
754 }
755
756 # string valid_iuse(service)
757 #
758 # This will only give the valid use's for the service
759 # (they must be in the boot or current runlevel)
760 #
761 valid_iuse() {
762 valid_i "use" "$1"
763 }
764
765 #string valid_iafter(service)
766 #
767 # Valid services for current or boot rc level that should start
768 # before 'service'
769 #
770 valid_iafter() {
771 valid_i "after" "$1"
772 }
773
774 # string trace_dependencies(service[s])
775 #
776 # Get and sort the dependencies of given service[s].
777 #
778 trace_dependencies() {
779 local -a services=( "$@" ) net_deps=()
780 local i= j= net_services= x=
781
782 if [[ $1 == -* ]]; then
783 deptype="${1/-/}"
784 if net_service "${SVCNAME}" ; then
785 services=( "net" "${SVCNAME}" )
786 else
787 services=( "${SVCNAME}" )
788 fi
789 fi
790
791 if is_net_up || is_runlevel_stop ; then
792 for x in $(dolisting "${svcdir}/started/net.*") \
793 $(dolisting "${svcdir}/inactive/net.*") ; do
794 net_services="${net_services} ${x##*/}"
795 done
796 else
797 for x in $(dolisting "/etc/runlevels/${BOOTLEVEL}/net.*") \
798 $(dolisting "/etc/runlevels/${SOFTLEVEL}/net.*") ; do
799 net_services="${net_services} ${x##*/}"
800 done
801 fi
802
803 # Cache the generic "net" depends
804 net_deps=( $( ineed net ) $( valid_iuse net ) )
805 if is_runlevel_start || is_runlevel_stop ; then
806 net_deps=( "${net_deps[@]}" $( valid_iafter net ) )
807 fi
808
809 # OK, this is a topological sort
810 # The bonus about doing it in bash is that we can calculate our sort
811 # order as we calculate our dependencies
812 local -a visited sorted
813 visit_service() {
814 local service="$1" dep x
815 local -a deps
816
817 [[ " ${visited[@]} " == *" ${service} "* ]] && return
818 visited=( "${visited[@]}" "${service}" )
819
820 if [[ -n ${deptype} ]] ; then
821 deps=( $( "${deptype}" "${service}" ) )
822 else
823 deps=( $( ineed "${service}" ) $( valid_iuse "${service}" ) )
824 if is_runlevel_start || is_runlevel_stop ; then
825 deps=( "${deps[@]}" $( valid_iafter "${service}" ) )
826 fi
827
828 # If we're a net service, we have to get deps for ourself
829 # and the net service as we're both
830 net_service "${service}" && deps=( "${deps[@]}" "${net_deps[@]}" )
831
832 x=" ${deps[@]} "
833 deps=( "${deps[@]}" ${x// net / ${net_services} } )
834 fi
835
836 services=( "${services[@]}" "${deps[@]}" )
837 for dep in ${deps[@]}; do
838 visit_service "${dep}"
839 done
840 sorted=( "${sorted[@]}" "${service}" )
841 }
842
843 for (( i=0; i<${#services[@]}; i++)); do
844 visit_service "${services[i]}"
845 done
846
847 services=( "${sorted[@]}" )
848
849 if [[ -n ${deptype} ]] ; then
850 # If deptype is set, we do not want the name of this service
851 x=" ${services[@]} "
852 services=( ${x// ${SVCNAME} / } )
853
854 # If its a net service, do not include "net"
855 if net_service "${SVCNAME}" ; then
856 x=" ${services[@]} "
857 sorted=( ${services// net / } )
858 fi
859 fi
860
861 echo "${services[@]}"
862 }
863
864 # bool query_before(service1, service2)
865 #
866 # Return true if 'service2' should be started *before*
867 # service1.
868 #
869 query_before() {
870 local x list
871 local netservice="no"
872
873 [[ -z $1 || -z $2 ]] && return 1
874
875 list="$( trace_dependencies "$1" )"
876
877 net_service "$2" && netservice="yes"
878
879 for x in ${list} ; do
880 [[ ${x} == "$2" ]] && return 0
881
882 # Also match "net" if this is a network service ...
883 [[ ${netservice} == "yes" && ${x} == "net" ]] && return 0
884 done
885
886 return 1
887 }
888
889 # 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