/[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 2165 - (show annotations) (download) (as text)
Tue Jul 18 11:06:40 2006 UTC (8 years, 2 months ago) by uberlord
File MIME type: text/x-sh
File size: 22204 byte(s)
    Report services scheduled to be started by another service as
    started OK for splash.
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 || service_scheduled "${service}"
413 retval=$?
414 end_service "${service}" "${retval}"
415 splash "svc_started" "${service}" "${retval}"
416 return "${retval}"
417 else
418 # if parallel startup is allowed, start it in background
419 (
420 "/etc/init.d/${service}" start
421 service_started "${service}" || service_inactive "${service}" \
422 || service_scheduled "${service}"
423 retval=$?
424 end_service "${service}" "${retval}"
425 splash "svc_started" "${service}" "${retval}"
426 ) &
427 return 0
428 fi
429 }
430
431 # int stop_service(service)
432 #
433 # Stop 'service' if it is not already running.
434 #
435 stop_service() {
436 local service="$1"
437 [[ -z ${service} ]] && return 1
438
439 if [[ ! -e "/etc/init.d/${service}" ]] ; then
440 mark_service_stopped "${service}"
441 return 0
442 fi
443
444 service_stopping "${service}" && return 0
445 service_stopped "${service}" && return 0
446
447 local level="${SOFTLEVEL}"
448 is_runlevel_stop && level="${OLDSOFTLEVEL}"
449
450 if is_fake_service "${service}" "${level}" ; then
451 splash "svc_stop" "${service}"
452 mark_service_stopped "${service}"
453 splash "svc_stopped" "${service}" "0"
454 return 0
455 fi
456
457 begin_service "${service}" || return 0
458
459 splash "svc_stop" "${service}"
460 if [[ ${RC_PARALLEL_STARTUP} != "yes" || \
461 ${STOP_CRITICAL} == "yes" ]] ; then
462 # if we can not start the services in parallel
463 # then just start it and return the exit status
464 ( "/etc/init.d/${service}" stop )
465 service_stopped "${service}"
466 retval=$?
467 end_service "${service}" "${retval}"
468 splash "svc_stopped" "${service}" "${retval}"
469 return "${retval}"
470 else
471 # if parallel startup is allowed, start it in background
472 (
473 ( "/etc/init.d/${service}" stop )
474 service_stopped "${service}"
475 retval=$?
476 end_service "${service}" "${retval}"
477 splash "svc_stopped" "${service}" "${retval}"
478 ) &
479 return 0
480 fi
481 }
482
483 # bool mark_service_coldplugged(service)
484 #
485 # Mark 'service' as coldplugged.
486 #
487 mark_service_coldplugged() {
488 [[ -z $1 ]] && return 1
489
490 ln -snf "/etc/init.d/$1" "${svcdir}/coldplugged/$1"
491 return 0
492 }
493
494 # bool mark_service_starting(service)
495 #
496 # Mark 'service' as starting.
497 #
498 mark_service_starting() {
499 [[ -z $1 ]] && return 1
500
501 ln -sn "/etc/init.d/$1" "${svcdir}/starting/$1" 2>/dev/null || return 1
502
503 [[ -f "${svcdir}/started/$1" ]] && rm -f "${svcdir}/started/$1"
504 [[ -f "${svcdir}/inactive/$1" ]] \
505 && mv "${svcdir}/inactive/$1" "${svcdir}/wasinactive/$1"
506 return 0
507 }
508
509 # bool mark_service_started(service)
510 #
511 # Mark 'service' as started.
512 #
513 mark_service_started() {
514 [[ -z $1 ]] && return 1
515
516 ln -snf "/etc/init.d/$1" "${svcdir}/started/$1"
517
518 rm -f "${svcdir}/starting/$1" "${svcdir}/inactive/$1" \
519 "${svcdir}/wasinactive/$1" "${svcdir}/stopping/$1" \
520 "${svcdir}"/scheduled/*/"$1"
521
522 return 0
523 }
524
525 # bool mark_service_inactive(service)
526 #
527 # Mark service as inactive
528 #
529 mark_service_inactive() {
530 [[ -z $1 ]] && return 1
531
532 ln -snf "/etc/init.d/$1" "${svcdir}/inactive/$1"
533
534 rm -f "${svcdir}/started/$1" "${svcdir}/wasinactive/$1" \
535 "${svcdir}/starting/$1" "${svcdir}/stopping/$1"
536
537 return 0
538 }
539
540 # bool mark_service_stopping(service)
541 #
542 # Mark 'service' as stopping.
543 #
544 mark_service_stopping() {
545 [[ -z $1 ]] && return 1
546
547 ln -sn "/etc/init.d/$1" "${svcdir}/stopping/$1" 2>/dev/null || return 1
548
549 rm -f "${svcdir}/started/$1"
550 [[ -f "${svcdir}/inactive/$1" ]] \
551 && mv "${svcdir}/inactive/$1" "${svcdir}/wasinactive/$1"
552
553 return 0
554 }
555
556 # bool mark_service_stopped(service)
557 #
558 # Mark 'service' as stopped.
559 #
560 mark_service_stopped() {
561 [[ -z $1 ]] && return 1
562
563 rm -Rf "${svcdir}/daemons/$1" "${svcdir}/starting/$1" \
564 "${svcdir}/started/$1" "${svcdir}/inactive/$1" \
565 "${svcdir}/wasinactive/$1" "${svcdir}/stopping/$1" \
566 "${svcdir}/scheduled/$1" "${svcdir}/options/$1" \
567 "${svcdir}/coldplugged/$1"
568
569 return 0
570 }
571
572 # bool test_service_state(char *service, char *state)
573 #
574 # Returns 0 if the service link exists and points to a file, otherwise 1
575 # If 1 then the link is erased if it exists
576 test_service_state() {
577 [[ -z $1 || -z $2 ]] && return 1
578
579 local f="${svcdir}/$2/$1"
580
581 # Service is in the state requested
582 [[ -L ${f} ]] && return 0
583
584 [[ ! -e ${f} ]] && rm -f "${f}"
585 return 1
586 }
587
588 # bool service_coldplugged(service)
589 #
590 # Returns true if 'service' is coldplugged
591 #
592 service_coldplugged() {
593 test_service_state "$1" "coldplugged"
594 }
595
596 # bool service_starting(service)
597 #
598 # Returns true if 'service' is starting
599 #
600 service_starting() {
601 test_service_state "$1" "starting"
602 }
603
604 # bool service_started(service)
605 #
606 # Returns true if 'service' is started
607 #
608 service_started() {
609 test_service_state "$1" "started"
610 }
611
612 # bool service_inactive(service)
613 #
614 # Returns true if 'service' is inactive
615 #
616 service_inactive() {
617 test_service_state "$1" "inactive"
618 }
619
620 # bool service_wasinactive(service)
621 #
622 # Returns true if 'service' is inactive
623 #
624 service_wasinactive() {
625 test_service_state "$1" "wasinactive"
626 }
627
628 # bool service_stopping(service)
629 #
630 # Returns true if 'service' is stopping
631 #
632 service_stopping() {
633 test_service_state "$1" "stopping"
634 }
635
636 # bool service_stopped(service)
637 #
638 # Returns true if 'service' is stopped
639 #
640 service_stopped() {
641 [[ -z $1 ]] && return 1
642
643 service_starting "$1" && return 1
644 service_started "$1" && return 1
645 service_stopping "$1" && return 1
646 service_inactive "$1" && return 1
647
648 return 0
649 }
650
651 # char service_scheduled_by(service)
652 #
653 # Returns a list of services which will try and start 'service' when they
654 # are started
655 #
656 service_scheduled_by() {
657 [[ -z $1 ]] && return 1
658
659 local x= s= r=
660 for x in $(dolisting "${svcdir}/scheduled/*/$1") ; do
661 s="${x%/*}"
662 r="${r} ${s##*/}"
663 done
664
665 echo "${r:1}"
666 }
667
668 # bool service_scheduled()
669 #
670 # Returns true if 'service' is scheduled to be started by another service
671 #
672 service_scheduled() {
673 [[ -n $(service_scheduled_by "$@") ]]
674 }
675
676 # bool mark_service_failed(service)
677 #
678 # Mark service as failed for current runlevel. Note that
679 # this is only valid on runlevel change ...
680 #
681 mark_service_failed() {
682 [[ -z $1 || ! -d "${svcdir}/failed" ]] && return 1
683
684 ln -snf "/etc/init.d/$1" "${svcdir}/failed/$1"
685 }
686
687 # bool service_failed(service)
688 #
689 # Return true if 'service' have failed during this runlevel.
690 #
691 service_failed() {
692 [[ -n $1 && -L "${svcdir}/failed/$1" ]]
693 }
694
695 # bool service_started_daemon(char *interface, char *daemon, int index)
696 # Returns 0 if the service started the given daemon
697 # via start-stop-daemon, otherwise 1.
698 # If index is emtpy, then we don't care what the first daemon launched
699 # was, otherwise the daemon must also be at that index
700 service_started_daemon() {
701 local service="$1" daemon="$2" index="${3:-[0-9]*}"
702 local daemonfile="${svcdir}/daemons/${service}"
703
704 [[ ! -e ${daemonfile} ]] && return 1
705 grep -q '^RC_DAEMONS\['"${index}"'\]="'${daemon}'"$' "${daemonfile}"
706 }
707
708 # bool net_service(service)
709 #
710 # Returns true if 'service' is a service controlling a network interface
711 #
712 net_service() {
713 [[ -n $1 && ${1%%.*} == "net" && ${1#*.} != "$1" ]]
714 }
715
716 # bool is_net_up(char *exclude)
717 #
718 # Return true if service 'net' is considered up, else false.
719 #
720 # Notes for RC_NET_STRICT_CHECKING values:
721 # none net is up without checking anything - usefull for vservers
722 # lo Interface 'lo' is counted and if only it is up, net is up.
723 # no Interface 'lo' is not counted, and net is down even with it up,
724 # so there have to be at least one other interface up.
725 # yes All interfaces must be up.
726 is_net_up() {
727 local x=
728
729 case "${RC_NET_STRICT_CHECKING}" in
730 none)
731 return 0
732 ;;
733 lo)
734 service_started "net.lo"
735 return $?
736 ;;
737 yes)
738 for x in $(dolisting "/etc/runlevels/${BOOTLEVEL}/net.*") \
739 $(dolisting "/etc/runlevels/${SOFTLEVEL}/net.*") ; do
740 local y="${x##*/}"
741 [[ ${y} == "$1" ]] && return 1
742 service_started "${y}" || return 1
743 done
744 return 0
745 ;;
746 *)
747 for x in $(dolisting "${svcdir}/started/net.*") ; do
748 local y="${x##*/}"
749 [[ ${y} == "$1" ]] && continue
750 [[ ${y} != "net.lo" ]] && return 0
751 done
752 return 1
753 ;;
754 esac
755 }
756
757 # bool dependon(service1, service2)
758 #
759 # Does service1 depend (NEED or USE) on service2 ?
760 #
761 dependon() {
762 ineed -t "$1" "$2" || iuse -t "$1" "$2"
763 }
764
765 # string validi(use/after, service)
766 #
767 # This is the main code for valid_after and valid_iuse
768 # No point in writing it twice!
769 valid_i() {
770 local x
771 # Just set to dummy for now (don't know if $svcdir/softlevel exists yet).
772 local mylevel="${BOOTLEVEL}"
773
774 [[ $1 != "after" && $1 != "use" ]] && return 1
775
776 # Cannot be SOFTLEVEL, as we need to know current runlevel
777 [[ -f "${svcdir}/softlevel" ]] && mylevel=$( < "${svcdir}/softlevel" )
778
779 for x in $( i$1 "$2" ) ; do
780 [[ -e "/etc/runlevels/${BOOTLEVEL}/${x}" || \
781 -e "/etc/runlevels/${mylevel}/${x}" || \
782 ${x} == "net" ]] \
783 && echo "${x}"
784 done
785 return 0
786 }
787
788 # string valid_iuse(service)
789 #
790 # This will only give the valid use's for the service
791 # (they must be in the boot or current runlevel)
792 #
793 valid_iuse() {
794 valid_i "use" "$1"
795 }
796
797 #string valid_iafter(service)
798 #
799 # Valid services for current or boot rc level that should start
800 # before 'service'
801 #
802 valid_iafter() {
803 valid_i "after" "$1"
804 }
805
806 # string trace_dependencies(service[s])
807 #
808 # Get and sort the dependencies of given service[s].
809 #
810 trace_dependencies() {
811 local -a services=( "$@" ) net_deps=()
812 local i= j= net_services= x=
813
814 if [[ $1 == -* ]]; then
815 deptype="${1/-/}"
816 if net_service "${SVCNAME}" ; then
817 services=( "net" "${SVCNAME}" )
818 else
819 services=( "${SVCNAME}" )
820 fi
821 fi
822
823 if is_net_up || is_runlevel_stop ; then
824 for x in $(dolisting "${svcdir}/started/net.*") \
825 $(dolisting "${svcdir}/inactive/net.*") ; do
826 net_services="${net_services} ${x##*/}"
827 done
828 else
829 for x in $(dolisting "/etc/runlevels/${BOOTLEVEL}/net.*") \
830 $(dolisting "/etc/runlevels/${SOFTLEVEL}/net.*") \
831 $(dolisting "/etc/runlevels/coldplugged/net.*") ; do
832 net_services="${net_services} ${x##*/}"
833 done
834 fi
835
836 # Cache the generic "net" depends
837 net_deps=( $( ineed net ) $( valid_iuse net ) )
838 if is_runlevel_start || is_runlevel_stop ; then
839 net_deps=( "${net_deps[@]}" $( valid_iafter net ) )
840 fi
841
842 # OK, this is a topological sort
843 # The bonus about doing it in bash is that we can calculate our sort
844 # order as we calculate our dependencies
845 local -a visited sorted
846 visit_service() {
847 local service="$1" dep x
848 local -a deps
849
850 [[ " ${visited[@]} " == *" ${service} "* ]] && return
851 visited=( "${visited[@]}" "${service}" )
852
853 if [[ -n ${deptype} ]] ; then
854 deps=( $( "${deptype}" "${service}" ) )
855 else
856 deps=( $( ineed "${service}" ) $( valid_iuse "${service}" ) )
857 if is_runlevel_start || is_runlevel_stop ; then
858 deps=( "${deps[@]}" $( valid_iafter "${service}" ) )
859 fi
860
861 # If we're a net service, we have to get deps for ourself
862 # and the net service as we're both
863 net_service "${service}" && deps=( "${deps[@]}" "${net_deps[@]}" )
864
865 x=" ${deps[@]} "
866 deps=( "${deps[@]}" ${x// net / ${net_services} } )
867 fi
868
869 services=( "${services[@]}" "${deps[@]}" )
870 for dep in ${deps[@]}; do
871 visit_service "${dep}"
872 done
873 sorted=( "${sorted[@]}" "${service}" )
874 }
875
876 for (( i=0; i<${#services[@]}; i++)); do
877 visit_service "${services[i]}"
878 done
879
880 services=( "${sorted[@]}" )
881
882 if [[ -n ${deptype} ]] ; then
883 # If deptype is set, we do not want the name of this service
884 x=" ${services[@]} "
885 services=( ${x// ${SVCNAME} / } )
886
887 # If its a net service, do not include "net"
888 if net_service "${SVCNAME}" ; then
889 x=" ${services[@]} "
890 sorted=( ${services// net / } )
891 fi
892 fi
893
894 echo "${services[@]}"
895 }
896
897 # bool query_before(service1, service2)
898 #
899 # Return true if 'service2' should be started *before*
900 # service1.
901 #
902 query_before() {
903 local x list
904 local netservice="no"
905
906 [[ -z $1 || -z $2 ]] && return 1
907
908 list="$( trace_dependencies "$1" )"
909
910 net_service "$2" && netservice="yes"
911
912 for x in ${list} ; do
913 [[ ${x} == "$2" ]] && return 0
914
915 # Also match "net" if this is a network service ...
916 [[ ${netservice} == "yes" && ${x} == "net" ]] && return 0
917 done
918
919 return 1
920 }
921
922 # 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