/[baselayout]/trunk/sbin/rc-services.sh
Gentoo

Contents of /trunk/sbin/rc-services.sh

Parent Directory Parent Directory | Revision Log Revision Log


Revision 484 - (show annotations) (download) (as text)
Wed Apr 21 17:09:18 2004 UTC (15 years, 2 months ago) by vapier
File MIME type: text/x-sh
File size: 15333 byte(s)
update copyright years

1 # Copyright 1999-2004 Gentoo Technologies, Inc.
2 # Distributed under the terms of the GNU General Public License v2
3 # $Header$
4
5 # RC Dependency and misc service functions
6
7 RC_GOT_SERVICES="yes"
8
9 [ "${RC_GOT_FUNCTIONS}" != "yes" ] && source /sbin/functions.sh
10 [ "${RC_GOT_DEPTREE_INFO}" != "yes" -a -f "${svcdir}/deptree" ] \
11 && source "${svcdir}/deptree"
12
13 if [ "${RC_GOT_DEPTREE_INFO}" != "yes" ]
14 then
15 if ! /sbin/depscan.sh
16 then
17 echo
18 eerror "Error running '/sbin/depscan.sh'!"
19 eerror "Please correct any problems above."
20
21 exit 1
22 fi
23
24 source "${svcdir}/deptree"
25
26 if [ "${RC_GOT_DEPTREE_INFO}" != "yes" ]
27 then
28 echo
29 eerror "Dependency info is missing! Please run"
30 echo
31 eerror " # /sbin/depscan.sh"
32 echo
33 eerror "to fix this."
34
35 exit 1
36 fi
37 fi
38
39
40 #####################
41 # Internal variables
42 #####################
43
44 # The name of the service whose dependency info we currently have
45 rc_name=
46 # The index of the service whose dependency info we currently have
47 rc_index=0
48 # Our dependency types ...
49 rc_ineed=
50 rc_needsme=
51 rc_iuse=
52 rc_usesme=
53 rc_ibefore=
54 rc_iafter=
55 rc_broken=
56 rc_parallel=
57 rc_mtime=
58
59 ############
60 # Functions
61 ############
62
63 # boot check_mtime(service, mtime)
64 #
65 # Return 0 if 'service's mtime is the same as 'mtime'
66 #
67 check_mtime() {
68 # This one have no 'mtime' ...
69 [ "$1" = "net" ] && return 0
70
71 [ -z "$1" -o -z "$2" ] && return 1
72
73 # Do not fail if there is no script, as virtuals
74 # will then not work ...
75 if [ -e "/etc/init.d/$1" -a -x "/bin/stat" ] && \
76 [ "$(stat -c "%Y" "/etc/init.d/$1" 2>/dev/null)" -ne "$2" ]
77 then
78 return 1
79 fi
80
81 return 0
82 }
83
84 # bool get_service_index(service, index)
85 #
86 # Print the index of 'service'. 'index' is the current index.
87 #
88 get_service_index() {
89 local x=1
90 local index="$2"
91 local myservice="$1"
92
93 if [ -z "$1" -o -z "$2" ]
94 then
95 echo "0"
96 return 1
97 fi
98
99 # Do we already have the index?
100 if [ -n "${index}" ] && [ "${index}" -gt 0 -a \
101 "${myservice}" = "${RC_DEPEND_TREE[${index}]}" ]
102 then
103 echo "${index}"
104 return 0
105 fi
106
107 while [ "${x}" -le "${RC_DEPEND_TREE[0]}" ]
108 do
109 index=$((${x} * ${rc_index_scale}))
110
111 if [ "${myservice}" = "${RC_DEPEND_TREE[${index}]}" ]
112 then
113 echo "${index}"
114 return 0
115 fi
116
117 let "x += 1"
118 done
119
120 echo "0"
121 return 1
122 }
123
124 # bool get_dep_info(service)
125 #
126 # Set the Dependency variables to contain data for 'service'
127 #
128 get_dep_info() {
129 local myservice="$1"
130
131 [ -z "$1" ] && return 1
132
133 # We already have the right stuff ...
134 if [ "${myservice}" = "${rc_name}" -a -n "${rc_mtime}" ] && \
135 check_mtime "${myservice}" "${rc_mtime}"
136 then
137 return 0
138 fi
139
140 rc_index="`get_service_index "${myservice}" "${rc_index}"`"
141 rc_mtime="${RC_DEPEND_TREE[$((${rc_index} + ${rc_type_mtime}))]}"
142
143 # Does the stored mtime match that of the current rc-script?
144 if ! check_mtime "${myservice}" "${rc_mtime}"
145 then
146 # Nope, check if we already ran depscan.sh
147 source "${svcdir}/deptree"
148 rc_index="`get_service_index "${myservice}" "${rc_index}"`"
149 rc_mtime="${RC_DEPEND_TREE[$((${rc_index} + ${rc_type_mtime}))]}"
150
151 # Do we have it now?
152 if ! check_mtime "${myservice}" "${rc_mtime}"
153 then
154 # Not? So run depscan.sh ...
155 einfo "Re-caching dependency info (mtimes differ)..." &>/dev/stderr
156 if ! /sbin/depscan.sh &>/dev/null
157 then
158 return 1
159 else
160 # We want to check if we got the dep info later on ...
161 unset RC_GOT_DEPTREE_INFO
162 source "${svcdir}/deptree"
163 # Everything "OK" ?
164 [ "${RC_GOT_DEPTREE_INFO}" != "yes" ] && return 1
165 fi
166
167 rc_index="`get_service_index "${myservice}" "${rc_index}"`"
168 fi
169 fi
170
171 # Verify that we have the correct index (rc_index) ...
172 [ "${rc_index}" -eq 0 ] && return 1
173
174 rc_name="${RC_DEPEND_TREE[${rc_index}]}"
175 rc_ineed="${RC_DEPEND_TREE[$((${rc_index} + ${rc_type_ineed}))]}"
176 rc_needsme="${RC_DEPEND_TREE[$((${rc_index} + ${rc_type_needsme}))]}"
177 rc_iuse="${RC_DEPEND_TREE[$((${rc_index} + ${rc_type_iuse}))]}"
178 rc_usesme="${RC_DEPEND_TREE[$((${rc_index} + ${rc_type_usesme}))]}"
179 rc_ibefore="${RC_DEPEND_TREE[$((${rc_index} + ${rc_type_ibefore}))]}"
180 rc_iafter="${RC_DEPEND_TREE[$((${rc_index} + ${rc_type_iafter}))]}"
181 rc_broken="${RC_DEPEND_TREE[$((${rc_index} + ${rc_type_broken}))]}"
182 rc_parallel="${RC_DEPEND_TREE[$((${rc_index} + ${rc_type_parallel}))]}"
183 rc_mtime="${RC_DEPEND_TREE[$((${rc_index} + ${rc_type_mtime}))]}"
184
185 return 0
186 }
187
188 # string check_dependency(deptype, service1)
189 #
190 # List all the services that depend on 'service1' of dependency
191 # type 'deptype'
192 #
193 # bool check_dependency(deptype, -t, service1, service2)
194 #
195 # Returns true if 'service2' is a dependency of type 'deptype'
196 # of 'service1'
197 #
198 check_dependency() {
199 local x=
200 local myservice=
201
202 [ -z "$1" -o -z "$2" ] && return 1
203
204 # Set the dependency variables to relate to 'service1'
205 if [ "$2" = "-t" ]
206 then
207 [ -z "$3" -o -z "$4" ] && return 1
208
209 myservice="$3"
210 else
211 myservice="$2"
212 fi
213
214 get_dep_info "${myservice}" >/dev/null || {
215 eerror "Could not get dependency info for \"${myservice}\"!" > /dev/stderr
216 eerror "Please run:" > /dev/stderr
217 echo > /dev/stderr
218 eerror " # /sbin/depscan.sh" > /dev/stderr
219 echo > /dev/stderr
220 eerror "to try and fix this." > /dev/stderr
221 return 1
222 }
223
224 # Do we have valid info for 'deptype' ?
225 [ -z "$(eval echo \${rc_$1})" ] && return 1
226
227 if [ "$2" = "-t" -a -n "$4" ]
228 then
229 # Check if 'service1' have 'deptype' dependency on 'service2'
230 for x in $(eval echo \${rc_$1})
231 do
232 [ "${x}" = "$4" ] && return 0
233 done
234 else
235 # Just list all services that 'service1' have 'deptype' dependency on.
236 eval echo "\${rc_$1}"
237
238 return 0
239 fi
240
241 return 1
242 }
243
244 # Same as for check_dependency, except 'deptype' is set to
245 # 'ineed'. It will return all the services 'service1' NEED's.
246 ineed() {
247 [ -z "$1" ] && return 1
248
249 check_dependency ineed $*
250
251 return $?
252 }
253
254 # Same as for check_dependency, except 'deptype' is set to
255 # 'needsme'. It will return all the services that NEED 'service1'.
256 needsme() {
257 [ -z "$1" ] && return 1
258
259 check_dependency needsme $*
260
261 return $?
262 }
263
264 # Same as for check_dependency, except 'deptype' is set to
265 # 'iuse'. It will return all the services 'service1' USE's.
266 iuse() {
267 [ -z "$1" ] && return 1
268
269 check_dependency iuse $*
270
271 return $?
272 }
273
274 # Same as for check_dependency, except 'deptype' is set to
275 # 'usesme'. It will return all the services that USE 'service1'.
276 usesme() {
277 [ -z "$1" ] && return 1
278
279 check_dependency usesme $*
280
281 return $?
282 }
283
284 # Same as for check_dependency, except 'deptype' is set to
285 # 'ibefore'. It will return all the services that are started
286 # *after* 'service1' (iow, it will start 'service1' before the
287 # list of services returned).
288 ibefore() {
289 [ -z "$1" ] && return 1
290
291 check_dependency ibefore $*
292
293 return $?
294 }
295
296 # Same as for check_dependency, except 'deptype' is set to
297 # 'iafter'. It will return all the services that are started
298 # *before* 'service1' (iow, it will start 'service1' after the
299 # list of services returned).
300 iafter() {
301 [ -z "$1" ] && return 1
302
303 check_dependency iafter $*
304
305 return $?
306 }
307
308 # Same as for check_dependency, except 'deptype' is set to
309 # 'broken'. It will return all the services that 'service1'
310 # NEED, but are not present.
311 broken() {
312 [ -z "$1" ] && return 1
313
314 check_dependency broken $*
315
316 return $?
317 }
318
319 # bool iparallel(service)
320 #
321 # Returns true if the service can be started in parallel.
322 #
323 iparallel() {
324 [ -z "$1" ] && return 1
325
326 if check_dependency parallel -t "$1" "no"
327 then
328 return 1
329 fi
330
331 return 0
332 }
333
334 # bool is_fake_service(service, runlevel)
335 #
336 # Returns ture if 'service' is a fake service in 'runlevel'.
337 #
338 is_fake_service() {
339 local x=
340 local fake_services=
341
342 [ -z "$1" -o -z "$2" ] && return 1
343
344 if [ "$2" != "${BOOTLEVEL}" -a \
345 -e "/etc/runlevels/${BOOTLEVEL}/.fake" ]
346 then
347 fake_services="$(< /etc/runlevels/${BOOTLEVEL}/.fake)"
348 fi
349
350 if [ -e "/etc/runlevels/$2/.fake" ]
351 then
352 fake_services="${fake_services} $(< /etc/runlevels/$2/.fake)"
353 fi
354
355 for x in ${fake_services}
356 do
357 if [ "$1" = "${x##*/}" ]
358 then
359 return 0
360 fi
361 done
362
363 return 1
364 }
365
366 # bool in_runlevel(service, runlevel)
367 #
368 # Returns true if 'service' is in runlevel 'runlevel'.
369 #
370 in_runlevel() {
371 [ -z "$1" -o -z "$2" ] && return 1
372
373 [ -L "/etc/runlevels/$2/$1" ] && return 0
374
375 return 1
376 }
377
378 # bool is_runlevel_start()
379 #
380 # Returns true if it is a runlevel change, and we are busy
381 # starting services.
382 #
383 is_runlevel_start() {
384 [ -d "${svcdir}/softscripts.old" ] && return 0
385
386 return 1
387 }
388
389 # bool is_runlevel_stop()
390 #
391 # Returns true if it is a runlevel change, and we are busy
392 # stopping services.
393 #
394 is_runlevel_stop() {
395 [ -d "${svcdir}/softscripts.new" ] && return 0
396
397 return 1
398 }
399
400 # int start_service(service)
401 #
402 # Start 'service' if it is not already running.
403 #
404 start_service() {
405 [ -z "$1" ] && return 1
406
407 if ! service_started "$1"
408 then
409 if is_fake_service "$1" "${SOFTLEVEL}"
410 then
411 mark_service_started "$1"
412 else
413 (. /sbin/runscript.sh "/etc/init.d/$1" start)
414
415 return $?
416 fi
417 fi
418
419 return 0
420 }
421
422 # int stop_service(service)
423 #
424 # Stop 'service' if it is not already running.
425 #
426 stop_service() {
427 [ -z "$1" ] && return 1
428
429 if service_started "$1"
430 then
431 if is_runlevel_stop
432 then
433 if is_fake_service "$1" "${OLDSOFTLEVEL}"
434 then
435 mark_service_stopped "$1"
436
437 return 0
438 fi
439 else
440 if is_fake_service "$1" "${SOFTLEVEL}"
441 then
442 mark_service_stopped "$1"
443
444 return 0
445 fi
446 fi
447
448 (. /sbin/runscript.sh "/etc/init.d/$1" stop)
449
450 return $?
451 fi
452
453 return 0
454 }
455
456 # bool mark_service_started(service)
457 #
458 # Mark 'service' as started.
459 #
460 mark_service_started() {
461 [ -z "$1" ] && return 1
462
463 ln -snf "/etc/init.d/$1" "${svcdir}/started/$1"
464
465 return $?
466 }
467
468 # bool mark_service_stopped(service)
469 #
470 # Mark 'service' as stopped.
471 #
472 mark_service_stopped() {
473 [ -z "$1" ] && return 1
474
475 rm -f "${svcdir}/started/$1"
476
477 return $?
478 }
479
480 # bool service_started(service)
481 #
482 # Returns true if 'service' is started
483 #
484 service_started() {
485 [ -z "$1" ] && return 1
486
487 if [ -L "${svcdir}/started/$1" ]
488 then
489 if [ ! -e "${svcdir}/started/$1" ]
490 then
491 rm -f "${svcdir}/started/$1"
492
493 return 1
494 fi
495 return 0
496 fi
497
498 return 1
499 }
500
501 # bool mark_service_failed(service)
502 #
503 # Mark service as failed for current runlevel. Note that
504 # this is only valid on runlevel change ...
505 #
506 mark_service_failed() {
507 [ -z "$1" ] && return 1
508
509 if [ -d "${svcdir}/failed" ]
510 then
511 ln -snf "/etc/init.d/$1" "${svcdir}/failed/$1"
512 return $?
513 fi
514
515 return 1
516 }
517
518 # bool service_failed(service)
519 #
520 # Return true if 'service' have failed during this runlevel.
521 #
522 service_failed() {
523 [ -z "$1" ] && return 1
524
525 if [ -L "${svcdir}/failed/$1" ]
526 then
527 return 0
528 fi
529
530 return 1
531 }
532
533 # bool net_service(service)
534 #
535 # Returns true if 'service' is a service controlling a network interface
536 #
537 net_service() {
538 [ -z "$1" ] && return 1
539
540 if [ "${1%%.*}" = "net" -a "${1##*.}" != "$1" ]
541 then
542 return 0
543 fi
544
545 return 0
546 }
547
548 # void schedule_service_startup(service)
549 #
550 # Schedule 'service' for startup, in parallel if possible.
551 #
552 schedule_service_startup() {
553 local count=0
554 local current_job=
555
556 if [ "${RC_PARALLEL_STARTUP}" = "yes" ]
557 then
558 set -m +b
559
560 if [ "$(jobs | grep -c "Running")" -gt 0 ]
561 then
562 if [ "$(jobs | grep -c "Running")" -eq 1 ]
563 then
564 if [ -n "$(jobs)" ]
565 then
566 current_job="$(jobs | awk '/Running/ { print $4}')"
567 fi
568
569 # Wait if we cannot start this service with the already running
570 # one (running one might start this one ...).
571 query_before "$1" "${current_job}" && wait
572
573 elif [ "$(jobs | grep -c "Running")" -ge 2 ]
574 then
575 count="$(jobs | grep -c "Running")"
576
577 # Wait until we have only one service running
578 while [ "${count}" -gt 1 ]
579 do
580 count="$(jobs | grep -c "Running")"
581 done
582
583 if [ -n "$(jobs)" ]
584 then
585 current_job="$(jobs | awk '/Running/ { print $4}')"
586 fi
587
588 # Wait if we cannot start this service with the already running
589 # one (running one might start this one ...).
590 query_before "$1" "${current_job}" && wait
591 fi
592 fi
593
594 if iparallel "$1"
595 then
596 eval start_service "$1" \&
597 else
598 # Do not start with any service running if we cannot start
599 # this service in parallel ...
600 # wait
601
602 start_service "$1"
603 fi
604 else
605 start_service "$1"
606 fi
607
608 # We do not need to check the return value here, as svc_{start,stop}() do
609 # their own error handling ...
610 return 0
611 }
612
613 # bool dependon(service1, service2)
614 #
615 # Does service1 depend (NEED or USE) on service2 ?
616 #
617 dependon() {
618 [ -z "$1" -o -z "$2" ] && return 1
619
620 if ineed -t "$1" "$2" || iuse -t "$1" "$2"
621 then
622 return 0
623 fi
624
625 return 1
626 }
627
628 # string valid_iuse(service)
629 #
630 # This will only give the valid use's for the service
631 # (they must be in the boot or current runlevel)
632 #
633 valid_iuse() {
634 local x=
635 local y=
636
637 for x in $(iuse "$1")
638 do
639 if [ -e "/etc/runlevels/${BOOTLEVEL}/${x}" -o \
640 -e "/etc/runlevels/${mylevel}/${x}" -o \
641 ${x} = "net" ]
642 then
643 echo "${x}"
644 fi
645 done
646
647 return 0
648 }
649
650 # string valid_iafter(service)
651 #
652 # Valid services for current or boot rc level that should start
653 # before 'service'
654 #
655 valid_iafter() {
656 local x=
657
658 for x in $(iafter "$1")
659 do
660 if [ -e "/etc/runlevels/${BOOTLEVEL}/${x}" -o \
661 -e "/etc/runlevels/${mylevel}/${x}" -o \
662 ${x} = "net" ]
663 then
664 echo "${x}"
665 fi
666 done
667
668 return 0
669 }
670
671 # void trace_depend(deptype, service, deplist)
672 #
673 # Trace the dependency tree of 'service' for type 'deptype', and
674 # modify 'deplist' with the info.
675 #
676 trace_depend() {
677 local x=
678 local y=
679 local add=
680
681 [ -z "$1" -o -z "$2" -o -z "$3" ] && return 1
682
683 # Build the list of services that 'deptype' on this one
684 for x in "$("$1" "$2")"
685 do
686 add="yes"
687
688 for y in $(eval echo "\${$3}")
689 do
690 [ "${x}" = "${y}" ] && add="no"
691 done
692
693 [ "${add}" = "yes" ] && eval $(echo "$3=\"\${$3} ${x}\"")
694
695 # Recurse to build a complete list ...
696 trace_depend "$1" "${x}" "$3"
697 done
698
699 return 0
700 }
701
702 # string list_depend_trace(deptype)
703 #
704 # Return resulting list of services for a trace of
705 # type 'deptype' for $myservice
706 #
707 list_depend_trace() {
708 local x=
709 local list=
710
711 [ -z "$1" ] && return 1
712
713 trace_depend "$1" "${myservice}" "list"
714
715 for x in ${list}
716 do
717 echo "${x}"
718 done
719
720 return 0
721 }
722
723 # bool query_before(service1, service2)
724 #
725 # Return true if 'service2' should be started *before*
726 # service1.
727 #
728 query_before() {
729 local x=
730 local list=
731 local netservice="no"
732
733 [ -z "$1" -o -z "$2" ] && return 1
734
735 trace_depend "ineed" "$1" "list"
736
737 for x in $1 ${list}
738 do
739 trace_depend "iuse" "${x}" "list"
740 done
741
742 for x in $1 ${list}
743 do
744 trace_depend "iafter" "${x}" "list"
745 done
746
747 net_service "$2" && netservice="yes"
748
749 for x in ${list}
750 do
751 [ "${x}" = "$2" ] && return 0
752
753 # Also match "net" if this is a network service ...
754 [ "${netservice}" = "yes" -a "${x}" = "net" ] && return 0
755 done
756
757 return 1
758 }
759
760 # bool query_after(service1, service2)
761 #
762 # Return true if 'service2' should be started *after*
763 # service1.
764 #
765 query_after() {
766 local x=
767 local list=
768 local netservice="no"
769
770 [ -z "$1" -o -z "$2" ] && return 1
771
772 trace_depend "needsme" "$1" "list"
773
774 for x in $1 ${list}
775 do
776 trace_depend "usesme" "${x}" "list"
777 done
778
779 for x in $1 ${list}
780 do
781 trace_depend "ibefore" "${x}" "list"
782 done
783
784 net_service "$2" && netservice="yes"
785
786 for x in ${list}
787 do
788 [ "${x}" = "$2" ] && return 0
789
790 # Also match "net" if this is a network service ...
791 [ "${netservice}" = "yes" -a "${x}" = "net" ] && return 0
792 done
793
794 return 1
795 }
796
797
798 # 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