Codebase list insserv / 5e4264b
Import Debian changes 1.11.0-1 insserv (1.11.0-1) unstable; urgency=low * New upstream version. - Drop patches 20_path_at_runtime, 21_overrides, 32_debian_nolsb, 33_debian_localok, 38_debuginfo, 40_nosusescript, 41_debiandefault, 42_redundantlvl, 43_shutdown, 44_reportloopmemb, 45_loopsarefatal and 46_complete_removal merged upstream. - Updated insserv(8) manual page for Debian (Closes: #462064). - Correct path to insserv.conf in test suite to keep it working. - A lot faster (Closes: #462211). * New example script make-testsuite useful to generate a test script demonstrating a problem. * Added override files for guidedog and puppet. * Removed override file for atd and lvm2, as the packages now include the LSB header. Petter Reinholdtsen authored 16 years ago Dmitry Bogatov committed 5 years ago
33 changed file(s) with 1462 addition(s) and 2378 deletion(s). Raw diff Collapse all Expand all
0 -------------------------------------------------------------------
1 Wed Jan 30 17:49:55 CET 2008 - werner@suse.de
2
3 - New version 1.11.0 of insserv
4 - Code cleanup, update copyrights, and manual pages
5 - Use __attribute__ of gcc for better function management
6 - Use __attribute__ of gcc for alignment of list_t pointers
7 - Some preparation listing.c for kill link sorting (TODO)
8
9 -------------------------------------------------------------------
10 Thu Jan 24 18:59:14 CET 2008 - werner@suse.de
11
12 - Add and integrate many patches from Debian svn tree done by
13 Petter Reinholdtsen
14 * Make it possible to set the path at runtime, to make it easier
15 to write test suites
16 * Support for reading LSB headers info from override directroy
17 * Accept script names like 'rc.local' for Debian build
18 * Use other defaults on Debian systems (start, stop levels)
19 * Put redundant level informations in one API
20 * Fix the handling of stop scripts and the shutdown sequence
21 on Debian systems
22 * Better loop report
23 * Make loops fatal if not forced
24 - Clean the API for listing the services
25
026 -------------------------------------------------------------------
127 Wed Oct 10 12:39:25 CEST 2007 - werner@suse.de
228
44 #
55
66 INITDIR = /etc/init.d
7 #INITDIR = /sbin/init.d
87 INSCONF = /etc/insserv.conf
98 #DESTDIR = /tmp/root
10 #DEBUG = -DDEBUG=1
9 #DEBUG = -DDEBUG=1 -Wpacked
1110 #LOOPS = -DIGNORE_LOOPS=1
1211 DEBUG =
1312 ISSUSE = -DSUSE
1413 DESTDIR =
15 VERSION = 1.10.0
14 VERSION = 1.11.0
1615 DATE = $(shell date +'%d%b%y' | tr '[:lower:]' '[:upper:]')
1716
1817 #
1918 # Architecture
2019 #
21 ARCH = $(shell uname -m | sed 's@\(i\)[34567]\(86\)@\13\2@')
22 #
23 # egcs used with -O2 includes -fno-force-mem which is/was buggy (1998/10/08)
24 #
2520 ifdef RPM_OPT_FLAGS
2621 COPTS = -g $(RPM_OPT_FLAGS)
2722 else
23 ARCH = $(shell uname -i)
2824 ifeq ($(ARCH),i386)
29 COPTS = -O2 -mcpu=i486 -fomit-frame-pointer -fschedule-insns2
25 COPTS = -O2 -mcpu=i586 -mtune=i686
3026 else
31 COPTS = -O2 -fomit-frame-pointer -fschedule-insns2
27 COPTS = -O2
3228 endif
3329 endif
3430 CFLAGS = -Wall $(COPTS) $(DEBUG) $(LOOPS) -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 \
3531 $(ISSUSE) -DINITDIR=\"$(INITDIR)\" -DINSCONF=\"$(INSCONF)\" -pipe
36 CLOOP = -funroll-loops
32 CLOOP = -falign-loops=0
3733 CC = gcc
3834 RM = rm -f
3935 MKDIR = mkdir -p
4743 INSTCONFLAGS = -c -m 0644
4844 INSTCON = install $(INSTDOCFLAGS)
4945 LINK = ln -sf
50
5146 #
5247 SDOCDIR = $(DESTDIR)/usr/share/man/man8
5348 SBINDIR = $(DESTDIR)/sbin
5752 #
5853 #
5954 #
60 TODO = insserv
55 TODO = insserv insserv.8
6156
6257 all: $(TODO)
6358
64 listing.o: listing.c listing.h
59 listing.o: listing.c listing.h .system
6560 $(CC) $(CFLAGS) $(CLOOP) -c $<
6661
67 insserv: insserv.c listing.o
68 $(CC) $(CFLAGS) $(CLOOP) -o $@ $^
62 insserv.o: insserv.c listing.h .system
63 $(CC) $(CFLAGS) $(CLOOP) -c $<
64
65 insserv: insserv.o listing.o
66 $(CC) $(CFLAGS) -Wl,-O,3,--relax -o $@ $^
67
68 ifeq ($(ISSUSE),-DSUSE)
69 insserv.8: insserv.8.in .system
70 sed -r '\!@@(ELSE|NOT)_SUSE@@!,\!@@END_SUSE@@!d;\!@@(BEGIN|END)_SUSE@@!d' < $< > $@
71 else
72 insserv.8: insserv.8.in .system
73 sed -r '\!@@BEGIN_SUSE@@!,\!@@(ELSE|END)_SUSE@@!d;\!@@(NOT|END)_SUSE@@!d' < $< > $@
74 endif
75
76 .system: SYSTEM=$(shell cat .system 2> /dev/null)
77 .system: .force
78 @test "$(SYSTEM)" = "$(ISSUSE)$(DEBUG)" || echo "$(ISSUSE)$(DEBUG)" > .system
79
80 .force:
6981
7082 clean:
71 $(RM) *.o *~ insserv .depend.*
83 $(RM) *.o *~ $(TODO) .depend.*
84
85 -include .depend.listing .depend.insserv
86
87 .depend.listing:
88 @$(CC) $(CFLAGS) -M listing.c >$@ 2>/dev/null
89
90 .depend.insserv:
91 @$(CC) $(CFLAGS) -M insserv.c >$@ 2>/dev/null
7292
7393 install: $(TODO)
7494 $(MKDIR) $(SBINDIR)
7595 $(MKDIR) $(SDOCDIR)
7696 $(MKDIR) $(CONFDIR)
97 ifeq ($(ISSUSE),-DSUSE)
7798 $(MKDIR) $(LSBDIR)
7899 $(MKDIR) $(DESTDIR)/usr/lib
79100 $(MKDIR) $(USRLSBDIR)
101 endif
80102 $(INSTBIN) insserv $(SBINDIR)/
81103 $(INSTDOC) insserv.8 $(SDOCDIR)/
82104 $(INSTCON) insserv.conf $(CONFDIR)/
105 ifeq ($(ISSUSE),-DSUSE)
83106 $(INSTCON) init-functions $(LSBDIR)/
84107 $(INSTSRP) install_initd $(USRLSBDIR)/
85108 $(INSTSRP) remove_initd $(USRLSBDIR)/
109 endif
86110
87111 #
88112 # Make distribution
93117 Makefile \
94118 listing.c \
95119 listing.h \
96 insserv.8 \
120 insserv.8.in \
97121 insserv.c \
98122 insserv.conf \
99123 init-functions \
118142 Platforms: Linux with System VR2 or higher boot scheme\n\
119143 Copying-policy: GPL\n\
120144 End' | sed 's@^ @@g;s@^x@@g' > insserv-$(VERSION).lsm
121 cp $(FILES) insserv-$(VERSION)
122 tar -c -zf insserv-$(VERSION).tar.gz insserv-$(VERSION)/
145 cp -p $(FILES) insserv-$(VERSION)/
146 tar -cps -zf insserv-$(VERSION).tar.gz insserv-$(VERSION)/
123147 $(RMDIR) insserv-$(VERSION)
124148 set -- `gzip -l insserv-$(VERSION).tar.gz | tail -1` ; \
125149 sed "s:@UNKNOWN:$$1:" < insserv-$(VERSION).lsm > \
0 insserv (1.11.0-1) unstable; urgency=low
1
2 * New upstream version.
3 - Drop patches 20_path_at_runtime, 21_overrides, 32_debian_nolsb,
4 33_debian_localok, 38_debuginfo, 40_nosusescript,
5 41_debiandefault, 42_redundantlvl, 43_shutdown,
6 44_reportloopmemb, 45_loopsarefatal and 46_complete_removal
7 merged upstream.
8 - Updated insserv(8) manual page for Debian (Closes: #462064).
9 - Correct path to insserv.conf in test suite to keep it working.
10 - A lot faster (Closes: #462211).
11 * New example script make-testsuite useful to generate a test script
12 demonstrating a problem.
13 * Added override files for guidedog and puppet.
14 * Removed override file for atd and lvm2, as the packages now include
15 the LSB header.
16
17 -- Petter Reinholdtsen <pere@debian.org> Thu, 31 Jan 2008 09:05:07 +0100
18
019 insserv (1.10.0-6) unstable; urgency=low
120
221 * Implement support for preseeding insserv, to make it possible to
11 # to track which scripts and packages are missing a bug report.
22 # Format:
33 # scriptname bin-pkgname src-pkgname btsnumber
4 aime aime aime #459550
54 alamin-server alamin-server alamin #460051
65 anacron anacron anacron #448223
76 and and and #460052
87 apt-proxy apt-proxy apt-proxy 460908
98 arpwatch arpwatch arpwatch #460248
10 atd at at #376780
119 bacula-director bacula-director-common bacula #460252
1210 bacula-fd bacula-fd bacula #460252
1311 bacula-sd bacula-sd bacula #460252
3230 gdomap gnustep-base-runtime gnustep-base #460224
3331 greylist greylistd greylistd #460151
3432 guarddog guarddog guarddog #460298
33 guidedog guidedog guidedog #462714
34 honeyd honeyd honeyd #462454
3535 hostname.dhcp nfsbooted nfsbooted #458859
3636 hpoj hpoj hpoj #459450
37 hpsockd hpsockd hpsockd #462716
38 hyperestraier hyperestraier hyperestraier #462713
3739 icecast2 icecast2 icecast2 #460853
3840 irqbalance irqbalance irqbalance #458461
3941 jabber jabber jabber #460855
4042 lastfmsubmitd lastfmsubmitd lastfmsubmitd #460206
4143 libpam-devperm libpam-devperm pam-devperm #458466
4244 lirc lirc lirc #460212
43 lvm2 lvm2 lvm2 #426108
45 lokkit lokkit gnome-lokkit #462754
4446 mbmon mbmon xmbmon #460243
4547 monit monit monit #460299
4648 mountfix nfsbooted nfsbooted #458859
5254 nstxcd nstx nstx #457756
5355 nstxd nstx nstx #457756
5456 ntop ntop ntop #460225
57 oidentd oidentd oidentd #462212
5558 openhpid openhpid openhpi #460216
59 portsentry portsentry portsentry #462220
5660 pptpd pptpd pptp #458476
61 puppet puppet puppet #462915
62 puppetmaster puppetmaster puppet #462915
5763 pure-ftpd pure-ftpd pure-ftpd #460303
5864 pure-ftpd-ldap pure-ftpd-ldap pure-ftpd #460303
5965 pure-ftpd-mysql pure-ftpd-mysql pure-ftpd #460303
6066 pure-ftpd-postgresql pure-ftpd-postgresql pure-ftpd #460303
6167 racoon racoon racoon #458488
68 realtime realtime-lsm realtime-lsm #462918
6269 scsitools-pre.sh scsitools scsitools #458649
6370 scsitools.sh scsitools scsitools #458649
6471 setkey ipsec-tools ipsec-tools #458488
72 slpd slpd openslp #462219
6573 smartmontools smartmontools smartmontools #458391
6674 snmptrapfmt snmptrapfmt snmptrapfmt #457752
6775 spamassassin spamassassin spamassassin #451762
6876 sqwebmail sqwebmail courier #458433
6977 swapd swapd swapd #458624
78 tpconfig tpconfig tpconfig #462214
7079 vsftpd vsftpd vsftpd #460211
80 wdm wdm wdm #462213
7181 xpilot-ng-server xpilot-ng-server xpilot-ng #460522
0 #!/bin/sh
1 #
2 # Extract key information from the current to try to generate a test
3 # suite script to demonstrate detected bugs.
4
5 echo "cat <<'EOF' > \$tmpdir\$insconf"
6 grep -v '#' /etc/insserv.conf |grep -v '^$'
7 echo "EOF"
8
9 for f in /etc/init.d/*; do
10 name=$(basename $f)
11 case $name in
12 README|rc|rcS|skeleton)
13 ;;
14 *)
15 echo "addscript $name <<EOF"
16 sed -n -r '/^### BEGIN INIT INFO/, /END INIT INFO/p' < $f
17 echo "EOF"
18 echo
19 ;;
20 esac
21 done
22
23 cd /etc
24 for f in rc?.d/*; do
25 case $f in
26 */README)
27 ;;
28 *)
29 echo ln -s $(readlink $f) $f
30 ;;
31 esac
32 done
+0
-8
debian/overrides/atd less more
0 ### BEGIN INIT INFO
1 # Provides: atd
2 # Required-Start: $remote_fs $syslog $time
3 # Required-Stop: $remote_fs $syslog $time
4 # Default-Start: 2 3 4 5
5 # Default-Stop: 0 1 6
6 ### END INIT INFO
7 # Reported to BTS as #335307, #376780
0 ### BEGIN INIT INFO
1 # Provides: guidedog
2 # Required-Start: $remote_fs
3 # Required-Stop:
4 # Default-Start: S
5 # Default-Stop:
6 ### END INIT INFO
7 # Reported to BTS as #462714
+0
-12
debian/overrides/lvm2 less more
0 ### BEGIN INIT INFO
1 # Provides: lvm2 lvm
2 # Required-Start: mountdevsubfs
3 # Required-Stop:
4 # Should-Start: udev devfsd raid2 mdadm cryptdisks-early
5 # Should-Stop: reboot halt umountroot
6 # X-Start-Before checkfs mountall
7 # X-Stop-after umountfs
8 # Default-Start: S
9 # Default-Stop: 0 6
10 ### END INIT INFO
11 # Reported to BTS as #426108
0 ### BEGIN INIT INFO
1 # Provides: puppet
2 # Required-Start: $remote_fs $syslog
3 # Required-Stop: $remote_fs $syslog
4 # Should-Start: puppetmaster
5 # Default-Start: 2 3 4 5
6 # Default-Stop: 0 1 6
7 ### END INIT INFO
8 # Reported to BTS as #?
00 10_nosuse
1 20_path_at_runtime
2 21_overrides
31 31_debian_conf
4 32_debian_nolsb
5 33_debian_localok
6 #34_debian_fixedscripts
7 38_debuginfo
8 40_nosusescript
9 41_debiandefault
10 42_redundantlvl
11 43_shutdown
12 44_reportloopmemb
13 45_loopsarefatal
14 46_complete_removal
+0
-143
debian/patches/20_path_at_runtime.dpatch less more
0 #! /bin/sh /usr/share/dpatch/dpatch-run
1 ## 20_path_at_runtime.dpatch by Petter Reinholdtsen
2 ## Updated for insserv v1.10 by PEtter Reinholdtsen
3
4 Make it possible to set the path at runtime, to make it easier to
5 write test suites.
6
7 @DPATCH@
8 diff -urNad insserv-1.10.0~/insserv.8 insserv-1.10.0/insserv.8
9 --- insserv-1.10.0~/insserv.8 2008-01-07 17:21:15.000000000 +0100
10 +++ insserv-1.10.0/insserv.8 2008-01-07 17:21:36.000000000 +0100
11 @@ -15,16 +15,22 @@
12 .\"
13 .B insserv
14 .RB [ \-v ]
15 +.RB [ \-c\ <config> ]
16 +.RB [ \-p\ <path> ]
17 .RB [ \-d ]
18 .RB [ \-f ]
19 .RI [[ / ] path/to/init.d/ ] script \ ...
20 .PP
21 .B insserv
22 .RB [ \-v ]
23 +.RB [ \-c\ <config> ]
24 +.RB [ \-p\ <path> ]
25 .RI [[ / ] path/to/init.d/ ] script [ ,start=<lvl1> [ ,<lvl2> ]]\ ...
26 .PP
27 .B insserv
28 .RB [ \-v ]
29 +.RB [ \-c\ <config> ]
30 +.RB [ \-p\ <path> ]
31 .B \-r
32 .RB [ \-d ]
33 .RB [ \-f ]
34 @@ -168,12 +174,19 @@
35 this facility will be grouped into one starting order.
36 .\"
37 .SH OPTIONS
38 -Currently there are only four options for
39 +Currently there are only five options for
40 .BR insserv .
41 .TP
42 .BR \-v ,\ \-\-verbose
43 Write out what is currently going on.
44 .TP
45 +.BR \-c\ <config>,\ \-\-config\ <config>
46 +Specify path to the insserv.conf file and the insserv.conf.d
47 +directory. Useful for testing.
48 +.TP
49 +.BR \-p\ <path>,\ \-\-path\ <path>
50 +Specify path to init.d directory. Useful for testing.
51 +.TP
52 .BR \-n ,\ \-\-dryrun
53 Do not update symlinks.
54 .TP
55 diff -urNad insserv-1.10.0~/insserv.c insserv-1.10.0/insserv.c
56 --- insserv-1.10.0~/insserv.c 2008-01-07 17:21:15.000000000 +0100
57 +++ insserv-1.10.0/insserv.c 2008-01-07 17:24:45.000000000 +0100
58 @@ -1582,19 +1582,19 @@
59 return 1;
60 }
61
62 -static void scan_conf()
63 +static void scan_conf(const char *file)
64 {
65 struct dirent** namelist = (struct dirent**)0;
66 char path[PATH_MAX+1];
67 int n;
68
69 - n = snprintf(&path[0], sizeof(path), "%s%s", root ? root : "", INSCONF);
70 + n = snprintf(&path[0], sizeof(path), "%s%s", root ? root : "", file);
71 if (n >= sizeof(path) || n < 0)
72 error("snprintf(): %s\n", strerror(errno));
73
74 scan_conf_file(path);
75
76 - n = snprintf(&path[0], sizeof(path), "%s%s.d", root ? root : "", INSCONF);
77 + n = snprintf(&path[0], sizeof(path), "%s%s.d", root ? root : "", file);
78 if (n >= sizeof(path) || n < 0)
79 error("snprintf(): %s\n", strerror(errno));
80
81 @@ -1666,10 +1666,12 @@
82 static struct option long_options[] =
83 {
84 {"verbose", 0, (int*)0, 'v'},
85 + {"config", 1, (int*)0, 'c'},
86 {"dryrun", 0, (int*)0, 'n'},
87 {"default", 0, (int*)0, 'd'},
88 {"remove", 0, (int*)0, 'r'},
89 {"force", 0, (int*)0, 'f'},
90 + {"path", 1, (int*)0, 'p'},
91 {"help", 0, (int*)0, 'h'},
92 { 0, 0, (int*)0, 0 },
93 };
94 @@ -1682,6 +1684,8 @@
95 printf(" -r, --remove Remove the listed scripts from all runlevels.\n");
96 printf(" -f, --force Ignore if a required service is missed.\n");
97 printf(" -v, --verbose Provide information on what is being done.\n");
98 + printf(" -p <path>, --path <path> Path to replace " INITDIR ".\n");
99 + printf(" -c <config>, --config <config> Path to config file.\n");
100 printf(" -n, --dryrun Do not change the system, only talk about it.\n");
101 printf(" -d, --default Use default runlevels a defined in the scripts\n");
102 }
103 @@ -1697,6 +1701,7 @@
104 struct stat st_script;
105 char * argr[argc];
106 char * path = INITDIR;
107 + char * insconf = INSCONF;
108 int runlevel, c;
109 boolean del = false;
110 boolean defaults = false;
111 @@ -1707,8 +1712,11 @@
112 for (c = 0; c < argc; c++)
113 argr[c] = (char*)0;
114
115 - while ((c = getopt_long(argc, argv, "dfrhvn", long_options, (int *)0)) != -1) {
116 + while ((c = getopt_long(argc, argv, "c:dfrhvnp:", long_options, (int *)0)) != -1) {
117 switch (c) {
118 + case 'c':
119 + insconf = optarg;
120 + break;
121 case 'd':
122 defaults = true;
123 break;
124 @@ -1725,6 +1733,9 @@
125 verbose = true;
126 dryrun = true;
127 break;
128 + case 'p':
129 + path = optarg;
130 + break;
131 case '?':
132 error("For help use: %s -h\n", myname);
133 case 'h':
134 @@ -1833,7 +1844,7 @@
135 /*
136 * Scan and set our configuration for virtual services.
137 */
138 - scan_conf();
139 + scan_conf(insconf);
140
141 /*
142 * Initialize the regular scanner for the scripts.
+0
-327
debian/patches/21_overrides.dpatch less more
0 #! /bin/sh /usr/share/dpatch/dpatch-run
1 ## 21_overrides.dpatch by Petter Reinholdtsen <pere@hungry.com>
2 ## Updated for insserv v1.10 by PEtter Reinholdtsen
3 ##
4 ## All lines beginning with `## DP:' are a description of the patch.
5 ## DP: Implement support for reading LSB init.d header info from override
6 ## DP: files.
7
8 @DPATCH@
9 diff -urNad insserv-1.10.0~/insserv.c insserv-1.10.0/insserv.c
10 --- insserv-1.10.0~/insserv.c 2008-01-07 17:37:09.000000000 +0100
11 +++ insserv-1.10.0/insserv.c 2008-01-07 17:40:25.000000000 +0100
12 @@ -25,6 +25,7 @@
13 #include <fcntl.h>
14 #include <sys/stat.h>
15 #include <sys/types.h>
16 +#include <sys/param.h>
17 #include <dirent.h>
18 #include <regex.h>
19 #include <errno.h>
20 @@ -41,6 +42,9 @@
21 #ifndef INITDIR
22 # define INITDIR "/etc/init.d"
23 #endif
24 +#ifndef OVERRIDEDIR
25 +# define OVERRIDEDIR "/etc/insserv/overrides"
26 +#endif
27 #ifndef INSCONF
28 # define INSCONF "/etc/insserv.conf"
29 #endif
30 @@ -1047,7 +1051,21 @@
31 regcompiler(&reg.desc, DESCRIPTION, REG_EXTENDED|REG_ICASE|REG_NEWLINE);
32 }
33
34 -static boolean scan_script_defaults(const char *const path)
35 +static inline void scan_script_reset(void)
36 +{
37 + xreset(script_inf.provides);
38 + xreset(script_inf.required_start);
39 + xreset(script_inf.required_stop);
40 + xreset(script_inf.should_start);
41 + xreset(script_inf.should_stop);
42 + xreset(script_inf.start_before);
43 + xreset(script_inf.stop_after);
44 + xreset(script_inf.default_start);
45 + xreset(script_inf.default_stop);
46 + xreset(script_inf.description);
47 +}
48 +
49 +static boolean scan_lsb_headers(const char *const path)
50 {
51 regmatch_t subloc[SUBNUM_SHD+1], *val = &subloc[SUBNUM-1], *shl = &subloc[SUBNUM_SHD-1];
52 FILE *script;
53 @@ -1071,25 +1089,18 @@
54 if (!script)
55 error("fopen(%s): %s\n", path, strerror(errno));
56
57 - /* Reset old results */
58 - xreset(provides);
59 - xreset(required_start);
60 - xreset(required_stop);
61 - xreset(should_start);
62 - xreset(should_stop);
63 - xreset(start_before);
64 - xreset(stop_after);
65 - xreset(default_start);
66 - xreset(default_stop);
67 - xreset(description);
68 -
69 #define COMMON_ARGS buf, SUBNUM, subloc, 0
70 #define COMMON_SHD_ARGS buf, SUBNUM_SHD, subloc, 0
71 while (fgets(buf, sizeof(buf), script)) {
72
73 /* Skip scanning above from LSB magic start */
74 - if (!begin && !(begin = strstr(buf, "### BEGIN INIT INFO")))
75 + if (!begin) {
76 + if ( (begin = strstr(buf, "### BEGIN INIT INFO")) ) {
77 + /* Let the latest LSB header override the one found earlier */
78 + scan_script_reset();
79 + }
80 continue;
81 + }
82
83 if (!provides && regexecutor(&reg.prov, COMMON_ARGS) == true) {
84 if (val->rm_so < val->rm_eo) {
85 @@ -1218,7 +1229,96 @@
86 #undef default_start
87 #undef default_stop
88 #undef description
89 + return ret;
90 +}
91 +
92 +/*
93 + * Follow symlinks, return the basename of the file pointed to by
94 + * symlinks or the basename of the current path if no symlink.
95 + */
96 +static char *scriptname(const char *path)
97 +{
98 + struct stat st;
99 + unsigned int deep = 0;
100 + char linkbuf[PATH_MAX+1];
101 + char *script = xstrdup(path);
102 +
103 + strncpy(linkbuf, script, sizeof(linkbuf)-1);
104 + linkbuf[PATH_MAX] = '\0';
105 +
106 + do {
107 + struct stat;
108 + int linklen;
109 +
110 + if (deep++ > MAXSYMLINKS) {
111 + errno = EMLINK;
112 + warn("Can not determine script name for %s: %s\n",
113 + path, strerror(errno));
114 + break;
115 + }
116 +
117 + if (lstat(script, &st) < 0) {
118 + warn("Can not stat %s: %s\n", script, strerror(errno));
119 + break;
120 + }
121 +
122 + if (!S_ISLNK(st.st_mode))
123 + break;
124 +
125 + if ((linklen = readlink(script, linkbuf, sizeof(linkbuf)-1)) < 0)
126 + break;
127 + linkbuf[linklen] = '\0';
128 +
129 + free(script);
130 + script = xstrdup(linkbuf);
131 +
132 + } while (1);
133 +
134 + free(script);
135 + script = xstrdup(basename(linkbuf));
136 +
137 + return script;
138 +}
139 +
140 +static boolean load_overrides(const char *const dir,
141 + const char *const name)
142 +{
143 + boolean ret = 0;
144
145 + char fullpath[PATH_MAX+1];
146 + snprintf(fullpath, sizeof(fullpath), "%s/%s", dir, name);
147 + struct stat statbuf;
148 + if (0 == stat(fullpath, &statbuf) && S_ISREG(statbuf.st_mode)) {
149 + ret = scan_lsb_headers(fullpath);
150 + }
151 + return ret;
152 +}
153 +
154 +#define FOUND_LSB_HEADER 0x01
155 +#define FOUND_LSB_DEFAULT 0x02
156 +#define FOUND_LSB_OVERRIDE 0x02
157 +
158 +static boolean scan_script_defaults(const char *const path, const char *const override_path)
159 +{
160 + int ret = 0;
161 + char *name = scriptname(path);
162 +
163 + /* Reset old results */
164 + scan_script_reset();
165 +
166 + /* Replace with headers from the script itself */
167 + ret |= scan_lsb_headers(path);
168 +
169 + if (!ret)
170 + /* Load values if the override file exist */
171 + ret |= load_overrides("/usr/share/insserv/overrides", name);
172 +
173 +
174 + /* Allow host-specific overrides to replace the content in the
175 + init.d scripts */
176 + ret |= load_overrides(override_path, name);
177 +
178 + free(name);
179 return ret;
180 }
181
182 @@ -1286,7 +1386,7 @@
183 /*
184 * Scan current service structure
185 */
186 -static void scan_script_locations(const char *const path, char ** const iargv, const int icnt)
187 +static void scan_script_locations(const char *const path, const char *const override_path, char ** const iargv, const int icnt)
188 {
189 int runlevel;
190
191 @@ -1330,10 +1430,12 @@
192 continue;
193 }
194
195 - lsb = scan_script_defaults(d->d_name);
196 + lsb = scan_script_defaults(d->d_name, override_path);
197 +
198 if (!script_inf.provides || script_inf.provides == empty)
199 script_inf.provides = xstrdup(ptr);
200
201 +
202 begin = script_inf.provides;
203 while ((token = strsep(&begin, delimeter)) && *token) {
204 serv_t * service = (serv_t*)0;
205 @@ -1349,6 +1451,15 @@
206
207 if (!lsb)
208 service->opts |= SERV_NOTLSB;
209 + if (! (lsb & FOUND_LSB_HEADER) ) {
210 + if (! (lsb & (FOUND_LSB_DEFAULT | FOUND_LSB_OVERRIDE) ))
211 + warn("warning: script '%s' missing LSB tags and overrides\n",
212 + d->d_name);
213 + else
214 + warn("warning: script '%s' missing LSB tags\n",
215 + d->d_name);
216 + }
217 +
218 if (script_inf.required_start && script_inf.required_start != empty) {
219 rememberreq(service, REQ_MUST, script_inf.required_start);
220 requiresv(token, script_inf.required_start);
221 @@ -1433,16 +1544,7 @@
222 }
223 #endif /* not SUSE */
224
225 - xreset(script_inf.provides);
226 - xreset(script_inf.required_start);
227 - xreset(script_inf.required_stop);
228 - xreset(script_inf.should_start);
229 - xreset(script_inf.should_stop);
230 - xreset(script_inf.start_before);
231 - xreset(script_inf.stop_after);
232 - xreset(script_inf.default_start);
233 - xreset(script_inf.default_stop);
234 - xreset(script_inf.description);
235 + scan_script_reset();
236 }
237 popd();
238 closedir(rcdir);
239 @@ -1672,6 +1774,7 @@
240 {"remove", 0, (int*)0, 'r'},
241 {"force", 0, (int*)0, 'f'},
242 {"path", 1, (int*)0, 'p'},
243 + {"override",1, (int*)0, 'o'},
244 {"help", 0, (int*)0, 'h'},
245 { 0, 0, (int*)0, 0 },
246 };
247 @@ -1685,6 +1788,7 @@
248 printf(" -f, --force Ignore if a required service is missed.\n");
249 printf(" -v, --verbose Provide information on what is being done.\n");
250 printf(" -p <path>, --path <path> Path to replace " INITDIR ".\n");
251 + printf(" -o <path>, --override <path> Path to replace " OVERRIDEDIR ".\n");
252 printf(" -c <config>, --config <config> Path to config file.\n");
253 printf(" -n, --dryrun Do not change the system, only talk about it.\n");
254 printf(" -d, --default Use default runlevels a defined in the scripts\n");
255 @@ -1701,6 +1805,7 @@
256 struct stat st_script;
257 char * argr[argc];
258 char * path = INITDIR;
259 + char * override_path = OVERRIDEDIR;
260 char * insconf = INSCONF;
261 int runlevel, c;
262 boolean del = false;
263 @@ -1712,7 +1817,7 @@
264 for (c = 0; c < argc; c++)
265 argr[c] = (char*)0;
266
267 - while ((c = getopt_long(argc, argv, "c:dfrhvnp:", long_options, (int *)0)) != -1) {
268 + while ((c = getopt_long(argc, argv, "c:dfrhvno:p:", long_options, (int *)0)) != -1) {
269 switch (c) {
270 case 'c':
271 insconf = optarg;
272 @@ -1736,6 +1841,9 @@
273 case 'p':
274 path = optarg;
275 break;
276 + case 'o':
277 + override_path = optarg;
278 + break;
279 case '?':
280 error("For help use: %s -h\n", myname);
281 case 'h':
282 @@ -1858,7 +1966,7 @@
283 #if 0
284 if (!defaults)
285 #endif
286 - scan_script_locations(path, (del ? argv : (char**)0), argc);
287 + scan_script_locations(path, override_path, (del ? argv : (char**)0), argc);
288
289 if ((initdir = opendir(path)) == (DIR*)0)
290 error("can not opendir(%s): %s\n", path, strerror(errno));
291 @@ -1945,7 +2053,16 @@
292 }
293
294 /* main scanner for LSB comment in current script */
295 - lsb = scan_script_defaults(d->d_name);
296 + lsb = scan_script_defaults(d->d_name, override_path);
297 +
298 + if (! (lsb & FOUND_LSB_HEADER) ) {
299 + if (! (lsb & (FOUND_LSB_DEFAULT | FOUND_LSB_OVERRIDE) ))
300 + warn("warning: script '%s' missing LSB tags and overrides\n",
301 + d->d_name);
302 + else
303 + warn("warning: script '%s' missing LSB tags\n",
304 + d->d_name);
305 + }
306
307 /* Common script ... */
308 if (!strcmp(d->d_name, "halt")) {
309 @@ -2297,16 +2414,7 @@
310 service->opts |= SERV_NOTLSB;
311 }
312 /* Reset remaining pointers */
313 - xreset(script_inf.provides);
314 - xreset(script_inf.required_start);
315 - xreset(script_inf.required_stop);
316 - xreset(script_inf.should_start);
317 - xreset(script_inf.should_stop);
318 - xreset(script_inf.start_before);
319 - xreset(script_inf.stop_after);
320 - xreset(script_inf.default_start);
321 - xreset(script_inf.default_stop);
322 - xreset(script_inf.description);
323 + scan_script_reset();
324
325 /*
326 * Free the regular scanner for the scripts.
+0
-34
debian/patches/32_debian_nolsb.dpatch less more
0 #! /bin/sh /usr/share/dpatch/dpatch-run
1 ## 32_debian_nolsb.dpatch
2 ## by Petter Reinholdtsen <pere@hungry.com>
3 ##
4 ## All lines beginning with `## DP:' are a description of the patch.
5 ## DP: Make sure to not install the LSB init.d include file and
6 ## DP: functions. These are in other packages on debian.
7
8 @DPATCH@
9 diff -urNad insserv~/Makefile insserv/Makefile
10 --- insserv~/Makefile 2008-01-04 11:22:01.000000000 +0100
11 +++ insserv/Makefile 2008-01-04 11:22:01.000000000 +0100
12 @@ -75,15 +75,15 @@
13 $(MKDIR) $(SBINDIR)
14 $(MKDIR) $(SDOCDIR)
15 $(MKDIR) $(CONFDIR)
16 - $(MKDIR) $(LSBDIR)
17 - $(MKDIR) $(DESTDIR)/usr/lib
18 - $(MKDIR) $(USRLSBDIR)
19 +# $(MKDIR) $(LSBDIR)
20 +# $(MKDIR) $(DESTDIR)/usr/lib
21 +# $(MKDIR) $(USRLSBDIR)
22 $(INSTBIN) insserv $(SBINDIR)/
23 $(INSTDOC) insserv.8 $(SDOCDIR)/
24 $(INSTCON) insserv.conf $(CONFDIR)/
25 - $(INSTCON) init-functions $(LSBDIR)/
26 - $(INSTSRP) install_initd $(USRLSBDIR)/
27 - $(INSTSRP) remove_initd $(USRLSBDIR)/
28 +# $(INSTCON) init-functions $(LSBDIR)/
29 +# $(INSTSRP) install_initd $(USRLSBDIR)/
30 +# $(INSTSRP) remove_initd $(USRLSBDIR)/
31
32 #
33 # Make distribution
+0
-32
debian/patches/33_debian_localok.dpatch less more
0 #! /bin/sh /usr/share/dpatch/dpatch-run
1 ## 33_debian_localok.dpatch
2 ## by Petter Reinholdtsen <pere@hungry.com>
3
4 Accept script names like 'rc.local', introduced in initscripts version
5 2.86.ds1-15.
6
7 @DPATCH@
8 diff -urNad insserv~/insserv.8 insserv/insserv.8
9 --- insserv~/insserv.8 2008-01-04 11:22:02.000000000 +0100
10 +++ insserv/insserv.8 2008-01-04 11:22:02.000000000 +0100
11 @@ -269,7 +269,6 @@
12 .sp 1
13 .in +1l
14 .nf
15 - *.local
16 *.rpm*
17 *.ba*
18 *.old
19 diff -urNad insserv~/insserv.c insserv/insserv.c
20 --- insserv~/insserv.c 2008-01-04 11:22:02.000000000 +0100
21 +++ insserv/insserv.c 2008-01-04 11:22:02.000000000 +0100
22 @@ -1545,8 +1545,7 @@
23 const char* end;
24 if ((end = strrchr(d->d_name, '.'))) {
25 end++;
26 - if (!strcmp(end, "local") ||
27 - !strncmp(end, "rpm", 3) || /* .rpmorig, .rpmnew, .rmpsave, ... */
28 + if (!strncmp(end, "rpm", 3) || /* .rpmorig, .rpmnew, .rmpsave, ... */
29 !strncmp(end, "ba", 2) || /* .bak, .backup, ... */
30 !strcmp(end, "old") ||
31 !strcmp(end, "new") ||
+0
-25
debian/patches/38_debuginfo.dpatch less more
0 #! /bin/sh /usr/share/dpatch/dpatch-run
1 ## 38_debuginfo.dpatch by Petter Reinholdtsen <pere@hungry.com>
2
3 Change debug output to print symbolic runlevel names as wellas a hex
4 value with the bit pattern representing the runlevels.
5
6 @DPATCH@
7 --- insserv-1.08.0.orig/listing.c
8 +++ insserv-1.08.0/listing.c
9 @@ -410,11 +410,11 @@
10 list_for_each(tmp, d_start) {
11 dir_t * dir = getdir(tmp);
12 if (dir->script)
13 - fprintf(stderr, "%.2d %s 0x%.2x (%s)\n",
14 - dir->order, dir->script, dir->lvl, dir->name);
15 + fprintf(stderr, "%.2d %s 0x%.2x '%s' (%s)\n",
16 + dir->order, dir->script, dir->lvl, lvl2str(dir->lvl), dir->name);
17 else
18 - fprintf(stderr, "%.2d %s 0x%.2x (%%%s)\n",
19 - dir->order, dir->name, dir->lvl, *dir->name == '$' ? "system" : "guessed");
20 + fprintf(stderr, "%.2d %s 0x%.2x '%s' (%%%s)\n",
21 + dir->order, dir->name, dir->lvl, lvl2str(dir->lvl), *dir->name == '$' ? "system" : "guessed");
22 }
23 }
24 #endif
+0
-42
debian/patches/40_nosusescript.dpatch less more
0 #! /bin/sh /usr/share/dpatch/dpatch-run
1 ## 40_nonsusescript.dpatch by Petter Reinholdtsen <pere@hungry.com>
2
3 Make sure the 'single' script is not inserted into runlevel S, and
4 avoid fixing the sequence number for a lot of scripts used in SuSe.
5
6 @DPATCH@
7 diff -urNad insserv~/insserv.c insserv/insserv.c
8 --- insserv~/insserv.c 2008-01-04 11:22:05.000000000 +0100
9 +++ insserv/insserv.c 2008-01-04 11:22:05.000000000 +0100
10 @@ -1926,6 +1926,7 @@
11 /* main scanner for LSB comment in current script */
12 lsb = scan_script_defaults(d->d_name, override_path);
13
14 +#ifdef SUSE
15 /* Common script ... */
16 if (!strcmp(d->d_name, "halt")) {
17 makeprov("halt", d->d_name);
18 @@ -1952,6 +1953,7 @@
19 rememberreq(serv, REQ_SHLD, "kbd");
20 continue;
21 }
22 +#endif /* SUSE */
23
24 /*
25 * Oops, no comment found, guess one
26 @@ -2289,6 +2291,7 @@
27
28 expand_conf();
29
30 +#ifdef SUSE
31 /*
32 * Set initial order of some services
33 */
34 @@ -2300,6 +2303,7 @@
35 setorder("serial", 10, false); setlsb("serial");
36 setorder("gpm", 20, false); setlsb("gpm");
37 setorder("boot.setup", 20, false);
38 +#endif /* SUSE */
39
40 /*
41 * Set virtual dependencies for already enabled none LSB scripts.
+0
-85
debian/patches/41_debiandefault.dpatch less more
0 #! /bin/sh /usr/share/dpatch/dpatch-run
1 ## 41_debiandefault.dpatch by Petter Reinholdtsen <pere@hungry.com>
2
3 Start scripts in runlevel 2345 on non-suse systems, and stop them in
4 runlevel 016.
5
6 @DPATCH@
7 diff -urNad insserv~/insserv.c insserv/insserv.c
8 --- insserv~/insserv.c 2008-01-07 18:45:21.000000000 +0100
9 +++ insserv/insserv.c 2008-01-07 18:46:03.000000000 +0100
10 @@ -39,6 +39,15 @@
11 static const int map_runlevel_to_seek(const int runlevel);
12 #endif /* not SUSE */
13
14 +#ifdef SUSE
15 +#define DEFAULT_START_LVL "3 5"
16 +#else
17 +/* for Debian*/
18 +#define DEFAULT_START_LVL "2 3 4 5"
19 +#define DEFAULT_STOP_LVL "0 1 6"
20 +#define DEFAULT_DEPENDENCY "$remote_fs $syslog"
21 +#endif
22 +
23 #ifndef INITDIR
24 # define INITDIR "/etc/init.d"
25 #endif
26 @@ -1435,6 +1444,14 @@
27 if (!script_inf.provides || script_inf.provides == empty)
28 script_inf.provides = xstrdup(ptr);
29
30 +#ifndef SUSE
31 + if (!lsb) {
32 + script_inf.required_start = xstrdup(DEFAULT_DEPENDENCY);
33 + script_inf.required_stop = xstrdup(DEFAULT_DEPENDENCY);
34 + script_inf.default_start = xstrdup(DEFAULT_START_LVL);
35 + script_inf.default_stop = xstrdup(DEFAULT_STOP_LVL);
36 + }
37 +#endif /* not SUSE */
38
39 begin = script_inf.provides;
40 while ((token = strsep(&script_inf.provides, delimeter)) && *token) {
41 @@ -2040,6 +2057,15 @@
42 }
43 #endif /* SUSE */
44
45 +#ifndef SUSE
46 + if (!lsb) {
47 + script_inf.required_start = xstrdup(DEFAULT_DEPENDENCY);
48 + script_inf.required_stop = xstrdup(DEFAULT_DEPENDENCY);
49 + script_inf.default_start = xstrdup(DEFAULT_START_LVL);
50 + script_inf.default_stop = xstrdup(DEFAULT_STOP_LVL);
51 + }
52 +#endif /* not SUSE */
53 +
54 /*
55 * Oops, no comment found, guess one
56 */
57 @@ -2247,7 +2273,7 @@
58 /*
59 * Ahh ... set default multiuser with network
60 */
61 - script_inf.default_start = xstrdup("3 5");
62 + script_inf.default_start = xstrdup(DEFAULT_START_LVL);
63 }
64 #ifndef SUSE
65 /*
66 @@ -2293,15 +2319,12 @@
67 free(begin);
68 }
69
70 -#ifdef SUSE
71 /* Ahh ... set default multiuser with network */
72 if (!script_inf.default_start || script_inf.default_start == empty)
73 - script_inf.default_start = xstrdup("3 5");
74 -#else /* not SUSE */
75 - if (!script_inf.default_start || script_inf.default_start == empty)
76 - script_inf.default_start = xstrdup("2 3 4 5"); /* for Debian*/
77 + script_inf.default_start = xstrdup(DEFAULT_START_LVL);
78 +#ifndef SUSE
79 if (!script_inf.default_stop || script_inf.default_start == empty)
80 - script_inf.default_stop = xstrdup("S 0 1 6"); /* for Debian*/
81 + script_inf.default_stop = xstrdup(DEFAULT_STOP_LVL);
82 #endif /* not SUSE */
83
84 if (chkfor(d->d_name, argv, argc) && !defaults) {
+0
-256
debian/patches/42_redundantlvl.dpatch less more
0 #! /bin/sh /usr/share/dpatch/dpatch-run
1 ## 42_redundantlvl.dpatch by Petter Reinholdtsen <pere@hungry.com>
2
3 Rewrite most locations with hardcoded information about levels to use
4 the runlevel_locations array to fetch the information instead. This
5 reduces the redundancy and make it easier to keep the level settings
6 in sync across the code.
7
8 The runlevel_locations array is extended to include the runlevel kode
9 in it.
10
11 @DPATCH@
12 diff -urNad insserv~/insserv.c insserv/insserv.c
13 --- insserv~/insserv.c 2008-01-07 22:50:18.000000000 +0100
14 +++ insserv/insserv.c 2008-01-07 22:50:19.000000000 +0100
15 @@ -34,8 +34,8 @@
16 #include "listing.h"
17
18 static const char *map_runlevel_to_location(const int runlevel);
19 +const int map_runlevel_to_lvl (const int runlevel);
20 #ifndef SUSE
21 -static const int map_runlevel_to_lvl (const int runlevel);
22 static const int map_runlevel_to_seek(const int runlevel);
23 #endif /* not SUSE */
24
25 @@ -475,22 +475,7 @@
26 if (serv->order < order)
27 serv->order = order;
28
29 - switch (runlvl) {
30 - case 0: serv->lvls |= LVL_HALT; break;
31 - case 1: serv->lvls |= LVL_ONE; break;
32 - case 2: serv->lvls |= LVL_TWO; break;
33 - case 3: serv->lvls |= LVL_THREE; break;
34 - case 4: serv->lvls |= LVL_FOUR; break;
35 - case 5: serv->lvls |= LVL_FIVE; break;
36 - case 6: serv->lvls |= LVL_REBOOT; break;
37 -#ifdef SUSE
38 - case 7: serv->lvls |= LVL_SINGLE; break;
39 - case 8: serv->lvls |= LVL_BOOT; break;
40 -#else /* not SUSE */
41 - case 7: serv->lvls |= LVL_BOOT; break;
42 -#endif /* not SUSE */
43 - default: break;
44 - }
45 + serv->lvls |= map_runlevel_to_lvl(runlvl);
46
47 return serv;
48 }
49 @@ -1349,45 +1334,82 @@
50 char *location;
51 const int lvl;
52 const int seek;
53 + char key;
54 } runlevel_locations[] = {
55 #ifdef SUSE /* SuSE's SystemV link scheme */
56 - {"rc0.d/", LVL_HALT, LVL_NORM},
57 - {"rc1.d/", LVL_ONE, LVL_NORM}, /* runlevel 1 switch over to single user mode */
58 - {"rc2.d/", LVL_TWO, LVL_NORM},
59 - {"rc3.d/", LVL_THREE, LVL_NORM},
60 - {"rc4.d/", LVL_FOUR, LVL_NORM},
61 - {"rc5.d/", LVL_FIVE, LVL_NORM},
62 - {"rc6.d/", LVL_REBOOT, LVL_NORM},
63 - {"rcS.d/", LVL_SINGLE, LVL_NORM}, /* runlevel S is for single user mode */
64 - {"boot.d/", LVL_BOOT, LVL_BOOT}, /* runlevel B is for system initialization */
65 + {"rc0.d/", LVL_HALT, LVL_NORM, '0'},
66 + {"rc1.d/", LVL_ONE, LVL_NORM, '1'}, /* runlevel 1 switch over to single user mode */
67 + {"rc2.d/", LVL_TWO, LVL_NORM, '2'},
68 + {"rc3.d/", LVL_THREE, LVL_NORM, '3'},
69 + {"rc4.d/", LVL_FOUR, LVL_NORM, '4'},
70 + {"rc5.d/", LVL_FIVE, LVL_NORM, '5'},
71 + {"rc6.d/", LVL_REBOOT, LVL_NORM, '6'},
72 + {"rcS.d/", LVL_SINGLE, LVL_NORM, 'S'}, /* runlevel S is for single user mode */
73 + {"boot.d/", LVL_BOOT, LVL_BOOT, 'B'}, /* runlevel B is for system initialization */
74 #else /* not SUSE (actually, Debian) */
75 - {"../rc0.d/", LVL_HALT, LVL_NORM},
76 - {"../rc1.d/", LVL_ONE, LVL_NORM}, /* runlevel 1 switch over to single user mode */
77 - {"../rc2.d/", LVL_TWO, LVL_NORM},
78 - {"../rc3.d/", LVL_THREE, LVL_NORM},
79 - {"../rc4.d/", LVL_FOUR, LVL_NORM},
80 - {"../rc5.d/", LVL_FIVE, LVL_NORM},
81 - {"../rc6.d/", LVL_REBOOT, LVL_NORM},
82 - {"../rcS.d/", LVL_BOOT, LVL_BOOT}, /* runlevel S is for system initialization */
83 + {"../rc0.d/", LVL_HALT, LVL_NORM, '0'},
84 + {"../rc1.d/", LVL_ONE, LVL_NORM, '1'}, /* runlevel 1 switch over to single user mode */
85 + {"../rc2.d/", LVL_TWO, LVL_NORM, '2'},
86 + {"../rc3.d/", LVL_THREE, LVL_NORM, '3'},
87 + {"../rc4.d/", LVL_FOUR, LVL_NORM, '4'},
88 + {"../rc5.d/", LVL_FIVE, LVL_NORM, '5'},
89 + {"../rc6.d/", LVL_REBOOT, LVL_NORM, '6'},
90 + {"../rcS.d/", LVL_BOOT, LVL_BOOT, 'S'}, /* runlevel S is for system initialization */
91 /* On e.g. Debian there exist no boot.d */
92 #endif /* not SUSE */
93 };
94
95 #define RUNLEVLES (sizeof(runlevel_locations)/sizeof(runlevel_locations[0]))
96
97 +const int map_has_runlevels(void)
98 +{
99 + return RUNLEVLES;
100 +}
101 +
102 +const char map_runlevel_to_key(const int runlevel)
103 +{
104 + if (runlevel >= RUNLEVLES) {
105 + warn("Wrong runlevel %d\n", runlevel);
106 + }
107 + return runlevel_locations[runlevel].key;
108 +}
109 +
110 +const int map_key_to_lvl(const char key)
111 +{
112 + int runlevel;
113 + const char uckey = toupper(key);
114 + for (runlevel = 0; runlevel < RUNLEVLES; runlevel++) {
115 + if (uckey == runlevel_locations[runlevel].key)
116 + return runlevel_locations[runlevel].lvl;
117 + }
118 + warn("Wrong runlevel key '%c'\n", uckey);
119 + return 0;
120 +}
121 +
122 static const char *map_runlevel_to_location(const int runlevel)
123 {
124 + if (runlevel >= RUNLEVLES) {
125 + warn("Wrong runlevel %d\n", runlevel);
126 + }
127 return runlevel_locations[runlevel].location;
128 }
129
130 -#ifndef SUSE
131 -static const int map_runlevel_to_lvl(const int runlevel)
132 +const int map_runlevel_to_lvl(const int runlevel)
133 {
134 + if (runlevel >= RUNLEVLES) {
135 + warn("Wrong runlevel %d\n", runlevel);
136 + return 0;
137 + }
138 return runlevel_locations[runlevel].lvl;
139 }
140
141 +#ifndef SUSE
142 static const int map_runlevel_to_seek(const int runlevel)
143 {
144 + if (runlevel >= RUNLEVLES) {
145 + warn("Wrong runlevel %d\n", runlevel);
146 + return LVL_NORM;
147 + }
148 return runlevel_locations[runlevel].seek;
149 }
150 #endif /* not SUSE */
151 diff -urNad insserv~/listing.c insserv/listing.c
152 --- insserv~/listing.c 2008-01-07 22:50:18.000000000 +0100
153 +++ insserv/listing.c 2008-01-07 22:50:42.000000000 +0100
154 @@ -58,6 +58,10 @@
155 #define DIR_LOOP 0x00000002
156 #define DIR_ISACTIVE 0x00000004
157
158 +/* From insserv.c */
159 +extern const int map_has_runlevels(void);
160 +extern const int map_runlevel_to_lvl (const int runlevel);
161 +extern const int map_key_to_lvl(const char key);
162 /*
163 * Provide or find a service dir, set initial states and
164 * link it into the maintaining if a new one.
165 @@ -428,24 +432,7 @@
166 boolean ret = false;
167 unsigned int lvl = 0;
168
169 - switch (runlevel) {
170 - case 0: lvl = LVL_HALT; break;
171 - case 1: lvl = LVL_ONE; break;
172 - case 2: lvl = LVL_TWO; break;
173 - case 3: lvl = LVL_THREE; break;
174 - case 4: lvl = LVL_FOUR; break;
175 - case 5: lvl = LVL_FIVE; break;
176 - case 6: lvl = LVL_REBOOT; break;
177 -#ifdef SUSE
178 - case 7: lvl = LVL_SINGLE; break;
179 - case 8: lvl = LVL_BOOT; break;
180 -#else
181 - case 7: lvl = LVL_BOOT; break;
182 -#endif /* not SUSE */
183 -
184 - default:
185 - warn("Wrong runlevel %d\n", runlevel);
186 - }
187 + lvl = map_runlevel_to_lvl (runlevel);
188
189 list_for_each(tmp, d_start) {
190 dir_t * dir = getdir(tmp);
191 @@ -480,23 +467,7 @@
192 if (!*script)
193 tmp = d_start->next;
194
195 - switch (runlevel) {
196 - case 0: lvl = LVL_HALT; break;
197 - case 1: lvl = LVL_ONE; break;
198 - case 2: lvl = LVL_TWO; break;
199 - case 3: lvl = LVL_THREE; break;
200 - case 4: lvl = LVL_FOUR; break;
201 - case 5: lvl = LVL_FIVE; break;
202 - case 6: lvl = LVL_REBOOT; break;
203 -#ifdef SUSE
204 - case 7: lvl = LVL_SINGLE; break;
205 - case 8: lvl = LVL_BOOT; break;
206 -#else
207 - case 7: lvl = LVL_BOOT; break;
208 -#endif /* not SUSE */
209 - default:
210 - warn("Wrong runlevel %d\n", runlevel);
211 - }
212 + lvl = map_runlevel_to_lvl (runlevel);
213
214 do {
215 ret = false;
216 @@ -575,7 +546,6 @@
217 unsigned int str2lvl(const char * lvl)
218 {
219 char * token, *tmp = strdupa(lvl);
220 - int num;
221 unsigned int ret = 0;
222
223 if (!tmp)
224 @@ -587,30 +557,7 @@
225 if (!strpbrk(token, "0123456sSbB"))
226 continue;
227
228 - if (*token == 'S' || *token == 's')
229 - num = 7;
230 - else if (*token == 'B' || *token == 'b')
231 - num = 8;
232 - else
233 - num = atoi(token);
234 -
235 - switch (num) {
236 - case 0: ret |= LVL_HALT; break;
237 - case 1: ret |= LVL_ONE; break;
238 - case 2: ret |= LVL_TWO; break;
239 - case 3: ret |= LVL_THREE; break;
240 - case 4: ret |= LVL_FOUR; break;
241 - case 5: ret |= LVL_FIVE; break;
242 - case 6: ret |= LVL_REBOOT; break;
243 -#ifdef SUSE
244 - case 7: ret |= LVL_SINGLE; break;
245 - case 8: ret |= LVL_BOOT; break;
246 -#else
247 - case 7: ret |= LVL_BOOT; break;
248 -#endif /* not SUSE */
249 - default:
250 - warn("Wrong runlevel %d\n", num);
251 - }
252 + ret |= map_key_to_lvl(*token);
253 }
254
255 return ret;
+0
-114
debian/patches/43_shutdown.dpatch less more
0 #! /bin/sh /usr/share/dpatch/dpatch-run
1 ## 43_shutdown.dpatch by Otavio Salvador and Petter Reinholdtsen
2 ## Updated for insserv v1.10 by PEtter Reinholdtsen
3
4 Fix the handling of stop scripts and the shutdown sequence.
5
6 @DPATCH@
7 diff -urNad insserv~/insserv.c insserv/insserv.c
8 --- insserv~/insserv.c 2008-01-07 18:24:26.000000000 +0100
9 +++ insserv/insserv.c 2008-01-07 18:24:34.000000000 +0100
10 @@ -468,14 +468,19 @@
11 /*
12 * This helps us to work out the current symbolic link structure
13 */
14 -static serv_t * current_structure(const char *const this, const char order, const int runlvl)
15 +static serv_t * current_structure(const char *const this, const char order, const int runlvl, const char type)
16 {
17 serv_t * serv = addserv(this);
18
19 if (serv->order < order)
20 serv->order = order;
21
22 - serv->lvls |= map_runlevel_to_lvl(runlvl);
23 + if ('S' == type)
24 + serv->lvls |= map_runlevel_to_lvl(runlvl);
25 +#ifndef SUSE
26 + else
27 + serv->lvlk |= map_runlevel_to_lvl(runlvl);
28 +#endif /* SUSE */
29
30 return serv;
31 }
32 @@ -1437,15 +1442,17 @@
33 while ((d = readdir(rcdir)) != (struct dirent*)0) {
34 char * ptr = d->d_name;
35 char order = 0;
36 + char type;
37 char* begin = (char*)0; /* Remember address of ptr handled by strsep() */
38 boolean lsb;
39
40 -#ifdef SUSE
41 - if (*ptr != 'S')
42 -#else
43 - if (*ptr != 'S' && *ptr != 'K')
44 + if (*ptr != 'S'
45 +#ifndef SUSE
46 + && *ptr != 'K'
47 #endif
48 + )
49 continue;
50 + type = *ptr;
51 ptr++;
52
53 if (strspn(ptr, "0123456789") < 2)
54 @@ -1480,7 +1487,7 @@
55 warn("script %s provides system facility %s, skipped!\n", d->d_name, token);
56 continue;
57 }
58 - service = current_structure(token, order, runlevel);
59 + service = current_structure(token, order, runlevel, type);
60
61 if (service->opts & SERV_KNOWN)
62 continue;
63 @@ -2393,7 +2400,10 @@
64 */
65 if (script_inf.default_stop && script_inf.default_stop != empty) {
66 if (service && !del)
67 + {
68 service->lvlk = str2lvl(script_inf.default_stop);
69 + runlevels(token, script_inf.default_stop);
70 + }
71 }
72 #endif /* not SUSE */
73 }
74 @@ -2674,10 +2684,14 @@
75 }
76
77 while (listscripts(&script, seek)) {
78 - const boolean stop = notincluded(script, runlevel);
79 const boolean this = chkfor(script, argv, argc);
80 - const char mode = (stop ? 'K' : 'S');
81 serv_t *serv = findserv(getprovides(script));
82 + const boolean stop = (notincluded(script, runlevel)
83 +#ifndef SUSE
84 + || (serv->lvlk & lvl))
85 +#endif /* not SUSE */
86 + ;
87 + const char mode = (stop ? 'K' : 'S');
88 int order = getorder(script);
89 boolean found;
90 char * clink;
91 @@ -2700,6 +2714,10 @@
92 order = (maxorder + 1) - order;
93 }
94
95 + if (!(serv->lvls & lvl) && !(serv->lvlk & lvl))
96 + continue; /* We aren't suppose to be on this runlevel */
97 +
98 +
99 sprintf(olink, "../init.d/%s", script);
100 sprintf(nlink, "%c%.2d%s", mode, order, script);
101
102 diff -urNad insserv~/listing.c insserv/listing.c
103 --- insserv~/listing.c 2008-01-07 18:24:26.000000000 +0100
104 +++ insserv/listing.c 2008-01-07 18:24:34.000000000 +0100
105 @@ -536,7 +536,7 @@
106 {
107 dir_t * dir = providedir(this);
108
109 - dir->lvl = str2lvl(lvl);
110 + dir->lvl |= str2lvl(lvl);
111 }
112
113 /*
+0
-119
debian/patches/44_reportloopmemb.dpatch less more
0 #! /bin/sh /usr/share/dpatch/dpatch-run
1 ## 45_reportloopmemb.dpatch by Petter Reinholdtsen
2
3 Try to make the loop reports a bit more verbose, listing the scripts
4 that are believed to be members of the loop. I'm not sure it will
5 report only the correct scripts, nor how it will work with several
6 loops present in the dependency graph.
7
8 @DPATCH@
9 diff -urNad insserv~/listing.c insserv/listing.c
10 --- insserv~/listing.c 2008-01-04 11:22:12.000000000 +0100
11 +++ insserv/listing.c 2008-01-04 11:22:12.000000000 +0100
12 @@ -57,6 +57,7 @@
13 #define DIR_SCAN 0x00000001
14 #define DIR_LOOP 0x00000002
15 #define DIR_ISACTIVE 0x00000004
16 +#define DIR_LOOPREPORT 0x00000008
17
18 /* From insserv.c */
19 extern const int map_has_runlevels(void);
20 @@ -197,11 +198,12 @@
21 #define loop_check(a) \
22 ((a) && (a)->flags & DIR_LOOP)
23
24 -static void __follow (dir_t * dir, dir_t * skip, const int level)
25 +static int __follow (dir_t * dir, dir_t * skip, const int level, int reportloop)
26 {
27 dir_t * tmp;
28 register int deep = level; /* Link depth, maybe we're called recursive */
29 register int loop;
30 + int hitloop = 0;
31 static boolean warned = false;
32
33 if (dir->flags & DIR_SCAN) {
34 @@ -213,7 +215,7 @@
35 if (!remembernode(dir))
36 loop_warn_one(dir);
37 }
38 - return;
39 + return hitloop;
40 }
41
42 if (deep < dir->minord) /* Default order deep of this tree is higher */
43 @@ -223,7 +225,7 @@
44 if (!warned)
45 warn("Max recursions depth %d reached\n", MAX_DEEP);
46 warned = true;
47 - return;
48 + return hitloop;
49 }
50
51 for (loop = 0, tmp = dir; tmp; loop++, tmp = getlinkdir(&(tmp->link))) {
52 @@ -293,23 +295,33 @@
53 if (!remembernode(skip) || !remembernode(tmp))
54 loop_warn_two(skip, tmp);
55 recursion = false;
56 + hitloop++;
57 break; /* Loop detected, stop recursion */
58 }
59
60 - __follow(target, tmp, deep); /* The inner recursion */
61 -
62 + hitloop |= __follow(target, tmp, deep, reportloop); /* The inner recursion */
63 /* Just for the case an inner recursion was stopped */
64 if (loop_check(target) || loop_check(tmp) || loop_check(skip)) {
65 recursion = false;
66 + hitloop++;
67 break; /* Loop detected, stop recursion */
68 }
69 +
70 + if (hitloop)
71 + break;
72 }
73
74 tmp->flags &= ~DIR_SCAN; /* Remove loop detection mark */
75
76 + if (hitloop && reportloop && !(tmp->flags & DIR_LOOPREPORT)) {
77 + warn(" loop involving service %s at depth %d\n", tmp->name, level);
78 + tmp->flags |= DIR_LOOPREPORT;
79 + }
80 +
81 if (!recursion)
82 break; /* Loop detected, stop recursion */
83 }
84 + return hitloop;
85 }
86
87 #undef loop_warn_two
88 @@ -319,10 +331,10 @@
89 /*
90 * Helper for follow_all: start with depth one.
91 */
92 -inline static void follow(dir_t * dir)
93 +inline static void follow(dir_t * dir, int reportloop)
94 {
95 /* Link depth starts here with one */
96 - __follow(dir, NULL, dir->minord);
97 + __follow(dir, NULL, dir->minord, reportloop);
98 }
99
100 /*
101 @@ -386,7 +398,7 @@
102 * Follow all scripts and calculate the main ordering.
103 */
104 list_for_each(tmp, d_start)
105 - follow(getdir(tmp));
106 + follow(getdir(tmp), 1);
107
108 /*
109 * Guess order of not installed scripts in comparision
110 @@ -618,7 +630,7 @@
111 /*
112 * Follow the script and re-calculate the ordering.
113 */
114 - __follow(dir, NULL, dir->minord);
115 + __follow(dir, NULL, dir->minord, 0);
116
117 /*
118 * Guess order of not installed scripts in comparision
+0
-58
debian/patches/45_loopsarefatal.dpatch less more
0 #! /bin/sh /usr/share/dpatch/dpatch-run
1 ## 45_loopsarefatal.dpatch by Petter Reinholdtsen
2
3 To avoid introducing broken boot and shutdown sequences, it is
4 important that no loops are detected when inserting a script. This
5 patch is a naive fix to make sure any loop detected is a fatal error.
6 The alternative is a broken boot or shutdown sequence.
7
8 It will also report "fake loops" as described in #458582 as fatal, but
9 that is intentional as these fake loops also confuse insserv to a
10 point where its generated boot and shutdown sequence is broken.
11
12 @DPATCH@
13 diff -urNad insserv~/insserv.c insserv/insserv.c
14 --- insserv~/insserv.c 2008-01-05 10:17:45.000000000 +0100
15 +++ insserv/insserv.c 2008-01-05 10:18:31.000000000 +0100
16 @@ -2385,6 +2385,9 @@
17 */
18 follow_all();
19
20 + if (is_loop_detected())
21 + error("exiting now!\n");
22 +
23 /*
24 * Re-order some well known scripts to get
25 * a more stable order collection.
26 diff -urNad insserv~/listing.c insserv/listing.c
27 --- insserv~/listing.c 2008-01-05 10:17:45.000000000 +0100
28 +++ insserv/listing.c 2008-01-05 10:17:45.000000000 +0100
29 @@ -415,6 +415,17 @@
30 }
31 }
32
33 +boolean is_loop_detected(void)
34 +{
35 + list_t *tmp;
36 + list_for_each(tmp, d_start) {
37 + dir_t * dir = getdir(tmp);
38 + if (dir->flags & DIR_LOOPREPORT)
39 + return true;
40 + }
41 + return false;
42 +}
43 +
44 /*
45 * For debuging: show all services
46 */
47 diff -urNad insserv~/listing.h insserv/listing.h
48 --- insserv~/listing.h 2008-01-05 10:17:43.000000000 +0100
49 +++ insserv/listing.h 2008-01-05 10:17:45.000000000 +0100
50 @@ -88,6 +88,7 @@
51 extern const char * getprovides(const char * script);
52 extern boolean listscripts(const char ** script, const int lvl);
53 extern int maxorder;
54 +extern boolean is_loop_detected(void);
55
56 /*
57 * Common short cuts
+0
-43
debian/patches/46_complete_removal.dpatch less more
0 #! /bin/sh /usr/share/dpatch/dpatch-run
1 ## 46_complete_removal.dpatch by Petter Reinholdtsen
2
3 Make sure symlink removal removes all symlinks, not just the ones in
4 rulevels listed in default-start and default-stop. Solves debian bug
5 #460034. Based on patch and feedback from Kel Modderman.
6
7 @DPATCH@
8 diff -urNad insserv~/insserv.c insserv/insserv.c
9 --- insserv~/insserv.c 2008-01-19 14:38:06.000000000 +0100
10 +++ insserv/insserv.c 2008-01-19 14:39:48.000000000 +0100
11 @@ -1460,8 +1460,15 @@
12 order = atoi(ptr);
13 ptr += 2;
14
15 +/*
16 + * Make sure removal removes all existing symlinks by disabling this
17 + * for the non-SUSE case. No idea if why this is needed for the SUSE
18 + * case. [Petter Reinholdtsen 2008-01-19]
19 + */
20 +#ifdef SUSE
21 if (iargv && chkfor(ptr, iargv, icnt))
22 continue; /* ignore scripts if removed later */
23 +#endif
24
25 if (stat(d->d_name, &st_script) < 0) {
26 xremove(d->d_name); /* dangling sym link */
27 @@ -1491,6 +1498,15 @@
28 }
29 service = current_structure(token, order, runlevel, type);
30
31 +/*
32 + * Break out here (and not above), as the rest of this loop is not
33 + * used during removals. [Petter Reinholdtsen 2008-01-19]
34 + */
35 +#ifndef SUSE
36 + if (iargv && chkfor(ptr, iargv, icnt))
37 + break;
38 +#endif /* not SUSE */
39 +
40 if (service->opts & SERV_KNOWN)
41 continue;
42 service->opts |= (SERV_KNOWN|SERV_ENABLED);
+0
-219
debian/patches/51_fakeloop_thinko.dpatch less more
0 #! /bin/sh /usr/share/dpatch/dpatch-run
1 ## 51_fakeloop_thinko.dpatch by Petter Reinholdtsen
2
3 Patch from Werner Fink to try to fix the problem with fake loops.
4
5 @DPATCH@
6 --- insserv-1.10.0/insserv.c
7 +++ insserv-1.10.0/insserv.c 2008-01-07 17:13:27.696866603 +0100
8 @@ -1335,7 +1335,7 @@ static void scan_script_locations(const
9 script_inf.provides = xstrdup(ptr);
10
11 begin = script_inf.provides;
12 - while ((token = strsep(&script_inf.provides, delimeter)) && *token) {
13 + while ((token = strsep(&begin, delimeter)) && *token) {
14 serv_t * service = (serv_t*)0;
15 if (*token == '$') {
16 warn("script %s provides system facility %s, skipped!\n", d->d_name, token);
17 @@ -1360,26 +1360,66 @@ static void scan_script_locations(const
18 if (script_inf.start_before && script_inf.start_before != empty) {
19 reversereq(service, token, script_inf.start_before);
20 }
21 + }
22 #ifndef SUSE
23 - /*
24 - * required_stop and should_stop arn't used in SuSE Linux.
25 - * Note: Sorting is done symetrical in stop and start!
26 - * The stop_order is given by max_order + 1 - start_order.
27 - */
28 - if (script_inf.required_stop && script_inf.required_stop != empty) {
29 - rememberreq(service, REQ_MUST, script_inf.required_stop);
30 - requiresv(token, script_inf.required_stop);
31 - }
32 - if (script_inf.should_stop && script_inf.should_stop != empty) {
33 - rememberreq(service, REQ_SHLD, script_inf.should_stop);
34 - requiresv(token, script_inf.should_stop);
35 + /*
36 + * required_stop and should_stop arn't used in SuSE Linux.
37 + * Note: Sorting is done symetrical in stop and start!
38 + * The stop_order is given by max_order + 1 - start_order.
39 + */
40 + begin = script_inf.required_stop;
41 + while ((token = strsep(&begin, delimeter)) && *token) {
42 + serv_t * service = (serv_t*)0;
43 + if (*token == '$') {
44 + warn("script %s provides system facility %s, skipped!\n", d->d_name, token);
45 + continue;
46 }
47 - if (script_inf.stop_after && script_inf.stop_after != empty) {
48 - reversereq(service, token, script_inf.stop_after);
49 + if (!(service = findserv(token)))
50 + service = addserv(token);
51 + if (!service)
52 + continue;
53 +
54 + if (script_inf.provides && script_inf.provides != empty) {
55 + rememberreq(service, REQ_MUST, script_inf.provides);
56 + requiresv(token, script_inf.provides);
57 }
58 -#endif /* not SUSE */
59 }
60 - script_inf.provides = begin;
61 +
62 + begin = script_inf.required_stop;
63 + while ((token = strsep(&begin, delimeter)) && *token) {
64 + serv_t * service = (serv_t*)0;
65 + if (*token == '$') {
66 + warn("script %s provides system facility %s, skipped!\n", d->d_name, token);
67 + continue;
68 + }
69 + if (!(service = findserv(token)))
70 + service = addserv(token);
71 + if (!service)
72 + continue;
73 +
74 + if (script_inf.provides && script_inf.provides != empty) {
75 + rememberreq(service, REQ_SHLD, script_inf.provides);
76 + requiresv(token, script_inf.provides);
77 + }
78 + }
79 +
80 + begin = script_inf.stop_after;
81 + while ((token = strsep(&begin, delimeter)) && *token) {
82 + serv_t * service = (serv_t*)0;
83 + if (*token == '$') {
84 + warn("script %s provides system facility %s, skipped!\n", d->d_name, token);
85 + continue;
86 + }
87 + if (!(service = findserv(token)))
88 + service = addserv(token);
89 + if (!service)
90 + continue;
91 +
92 + if (script_inf.provides && script_inf.provides != empty) {
93 + reversereq(service, token, script_inf.provides);
94 + }
95 + }
96 +#endif /* not SUSE */
97
98 xreset(script_inf.provides);
99 xreset(script_inf.required_start);
100 @@ -1981,7 +2021,7 @@ int main (int argc, char *argv[])
101 char * provides = xstrdup(script_inf.provides);
102
103 begin = provides;
104 - while ((token = strsep(&provides, delimeter)) && *token) {
105 + while ((token = strsep(&begin, delimeter)) && *token) {
106
107 if (*token == '$') {
108 warn("script %s provides system facility %s, skipped!\n", d->d_name, token);
109 @@ -2016,7 +2056,7 @@ int main (int argc, char *argv[])
110 boolean known = (service->opts & SERV_KNOWN);
111 service->opts |= SERV_KNOWN;
112
113 - if ((!provides || !*provides) && (count > 1)) { /* Last token */
114 + if ((!begin || !*begin) && (count > 1)) { /* Last token */
115 const char * script = getscript(service->name);
116
117 if (script) {
118 @@ -2046,30 +2086,12 @@ int main (int argc, char *argv[])
119 rememberreq(service, REQ_SHLD, script_inf.should_start);
120 requiresv(token, script_inf.should_start);
121 }
122 -#ifndef SUSE
123 - /*
124 - * required_stop and should_stop arn't used in SuSE Linux.
125 - * Note: Sorting is done symetrical in stop and start!
126 - * The stop order is given by max order - start order.
127 - */
128 - if (script_inf.required_stop && script_inf.required_stop != empty) {
129 - rememberreq(service, REQ_MUST, script_inf.required_stop);
130 - requiresv(token, script_inf.required_stop);
131 - }
132 - if (script_inf.should_stop && script_inf.should_stop != empty) {
133 - rememberreq(service, REQ_SHLD, script_inf.should_stop);
134 - requiresv(token, script_inf.should_stop);
135 - }
136 -#endif /* not SUSE */
137 }
138 +
139 if (script_inf.start_before && script_inf.start_before != empty) {
140 reversereq(service, token, script_inf.start_before);
141 }
142 -#ifndef SUSE
143 - if (script_inf.stop_after && script_inf.stop_after != empty) {
144 - reversereq(service, token, script_inf.stop_after);
145 - }
146 -#endif /* not SUSE */
147 +
148 /*
149 * Use information from symbolic link structure to
150 * check if all services are around for this script.
151 @@ -2161,7 +2183,66 @@ int main (int argc, char *argv[])
152 #endif /* not SUSE */
153 }
154 }
155 - free(begin);
156 +#ifndef SUSE
157 + /*
158 + * required_stop and should_stop arn't used in SuSE Linux.
159 + * Note: Sorting is done symetrical in stop and start!
160 + * The stop order is given by max order - start order.
161 + */
162 + begin = script_inf.required_stop;
163 + while ((token = strsep(&begin, delimeter)) && *token) {
164 + serv_t * this = (serv_t*)0;
165 + if (*token == '$') {
166 + warn("script %s provides system facility %s, skipped!\n", d->d_name, token);
167 + continue;
168 + }
169 + if (!(this = findserv(token)))
170 + this = addserv(token);
171 + if (!this)
172 + continue;
173 +
174 + if (provides && provides != empty) {
175 + rememberreq(this, REQ_MUST, provides);
176 + requiresv(token, provides);
177 + }
178 + }
179 +
180 + begin = script_inf.should_stop;
181 + while ((token = strsep(&begin, delimeter)) && *token) {
182 + serv_t * this = (serv_t*)0;
183 + if (*token == '$') {
184 + warn("script %s provides system facility %s, skipped!\n", d->d_name, token);
185 + continue;
186 + }
187 + if (!(this = findserv(token)))
188 + this = addserv(token);
189 + if (!this)
190 + continue;
191 +
192 + if (provides && provides != empty) {
193 + rememberreq(this, REQ_SHLD, provides);
194 + requiresv(token, provides);
195 + }
196 + }
197 +
198 + begin = script_inf.stop_after;
199 + while ((token = strsep(&begin, delimeter)) && *token) {
200 + serv_t * this = (serv_t*)0;
201 + if (*token == '$') {
202 + warn("script %s provides system facility %s, skipped!\n", d->d_name, token);
203 + continue;
204 + }
205 + if (!(this = findserv(token)))
206 + this = addserv(token);
207 + if (!this)
208 + continue;
209 +
210 + if (provides && provides != empty) {
211 + reversereq(this, token, provides);
212 + }
213 + }
214 +#endif /* not SUSE */
215 + free(provides);
216 }
217
218 #ifdef SUSE
5757
5858 $(INSTALL_DATA) debian/overrides/* $(DESTDIR)$(pkgdatadir)/overrides/.
5959 $(INSTALL) debian/check-initd-order $(DESTDIR)$(pkgdatadir)/.
60 $(INSTALL) debian/make-testsuite $(DESTDIR)$(pkgdatadir)/.
6061 $(INSTALL) debian/update-bootsystem-insserv $(DESTDIR)$(sbindir)/.
6162 $(INSTALL) debian/update-rc.d-insserv $(DESTDIR)$(sbindir)/.
6263
22 basedir=$(dirname $0)
33 . $basedir/testsuite-common
44
5 if head -1 debian/changelog | grep UNRELEASED ; then
5 if head -1 debian/changelog | grep -q UNRELEASED ; then
66 severity=check
77 else
88 severity=test
2727 echo "info: test normal boot sequence scripts, and their order"
2828 echo
2929
30 cat <<'EOF' > $tmpdir$insconf
30 cat <<'EOF' > $insconf
3131 $local_fs +mountall +umountfs
3232 $network +networking +ifupdown
3333 $named +named +dnsmasq +lwresd +bind9 $network
546546
547547 echo
548548 echo "info: test handling of 'fake' loops using reverse depends"
549 echo "warning: This test should be fatal, but is non-fatal until a fix is found."
549550 echo
550551
551552 rm -rf $initddir
647648
648649 echo
649650 echo "info: test if script removal removes all symlinks."
650 echo "warning: This test should be fatal, but is non-fatal until a fix is found."
651651 echo
652652 # This test check that the common way to update the runlevels used by
653653 # a given script is working. It simulates these calls to update-rc.d:
66
77 insserv=`pwd`/insserv
88 # Relative to $tmpdir
9 insconf=/etc/insserv.conf
9 insconf=$tmpdir/etc/insserv.conf
1010 overridedir=$tmpdir/etc/insserv/override
1111
1212 retval=0
+0
-29
insserv-1.10.0.lsm less more
0 Begin3
1 \
2 Title: insserv tool for boot scripts
3 \
4 Version: 1.10.0
5 \
6 Entered-date: 10OCT07
7 \
8 Description: Used for enabling of installed boot scripts
9 \
10 by scanning comment headers which are LSB conform.
11 \
12 Keywords: boot service control, LSB
13 \
14 Author: Werner Fink <werner@suse.de>
15 \
16 Maintained-by: Werner Fink <werner@suse.de>
17 \
18 Primary-site: sunsite.unc.edu /pub/Linux/system/daemons/init
19 \
20 @UNKNOWN insserv-1.10.0.tar.gz
21 \
22 Alternate-site: ftp.suse.com /pub/projects/init
23 \
24 Platforms: Linux with System VR2 or higher boot scheme
25 \
26 Copying-policy: GPL
27 \
28 End
0 Begin3
1 \
2 Title: insserv tool for boot scripts
3 \
4 Version: 1.11.0
5 \
6 Entered-date: 30JAN08
7 \
8 Description: Used for enabling of installed boot scripts
9 \
10 by scanning comment headers which are LSB conform.
11 \
12 Keywords: boot service control, LSB
13 \
14 Author: Werner Fink <werner@suse.de>
15 \
16 Maintained-by: Werner Fink <werner@suse.de>
17 \
18 Primary-site: sunsite.unc.edu /pub/Linux/system/daemons/init
19 \
20 @UNKNOWN insserv-1.11.0.tar.gz
21 \
22 Alternate-site: ftp.suse.com /pub/projects/init
23 \
24 Platforms: Linux with System VR2 or higher boot scheme
25 \
26 Copying-policy: GPL
27 \
28 End
+0
-330
insserv.8 less more
0 .\"
1 .\" Copyright 2000-2002 Werner Fink, 2000-2002 SuSE GmbH Nuernberg, Germany.
2 .\"
3 .\" This program is free software; you can redistribute it and/or modify
4 .\" it under the terms of the GNU General Public License as published by
5 .\" the Free Software Foundation; either version 2 of the License, or
6 .\" (at your option) any later version.
7 .\"
8 .TH INSSERV 8 "Aug 28, 2003" "Version 1.00" "The SuSE boot concept"
9 .UC 8
10 .OS SuSE Linux
11 .SH NAME
12 Insserv \- Enable an installed system init script
13 .SH SYNOPSIS
14 .\"
15 .B insserv
16 .RB [ \-v ]
17 .RB [ \-d ]
18 .RB [ \-f ]
19 .RI [[ / ] path/to/init.d/ ] script \ ...
20 .PP
21 .B insserv
22 .RB [ \-v ]
23 .RI [[ / ] path/to/init.d/ ] script [ ,start=<lvl1> [ ,<lvl2> ]]\ ...
24 .PP
25 .B insserv
26 .RB [ \-v ]
27 .B \-r
28 .RB [ \-d ]
29 .RB [ \-f ]
30 .RI [[ / ] path/to/init.d/ ] script \ ...
31 .PP
32 .B insserv
33 .B \-h
34 .PP
35 .RB /usr/lib/lsb/install_initd
36 .RI [[ / ] path/to/init.d/script ]
37 .PP
38 .RB /usr/lib/lsb/remove_initd
39 .RI [[ / ] path/to/init.d/script ]
40 .SH DESCRIPTION
41 .B insserv
42 enables an installed system init script (`boot script')
43 by reading the comment header of the script, e.g.:
44 .sp 1
45 .in +1l
46 .nf
47 ### BEGIN INIT INFO
48 # Provides: boot_facility_1 [ boot_facility_2 ...]
49 # Required-Start: boot_facility_1 [ boot_facility_2 ...]
50 # Required-Stop: boot_facility_1 [ boot_facility_2 ...]
51 # Should-Start: boot_facility_1 [ boot_facility_2 ...]
52 # Should-Stop: boot_facility_1 [ boot_facility_2 ...]
53 # X-Start-Before: boot_facility_1 [ boot_facility_2 ...]
54 # X-Stop-After: boot_facility_1 [ boot_facility_2 ...]
55 # Default-Start: run_level_1 [ run_level_2 ...]
56 # Default-Stop: run_level_1 [ run_level_2 ...]
57 # Description: multiline_description
58 ### END INIT INFO
59 .fi
60 .in -1l
61 .sp 1
62 and calculating the dependencies between all scripts.
63 Please note, that the
64 .BR Required-Stop,
65 .BR Should-Stop ,
66 .BR X-Stop-After,
67 and
68 .B Default\-Stop
69 are ignored in SuSE Linux, because the SuSE boot script concept
70 uses a differential link scheme (see
71 .IR init.d (7)).
72 The optional
73 .B X\-Start\-Before
74 keyword implies that the script using this keyword
75 should be started
76 .B before
77 the specified service names. This implies that those
78 services now depend on the specifying script.
79 With known dependencies and runlevel(s)
80 .B insserv
81 sets and reorders the corresponding symbolic links
82 of the concerned runlevels directories (see
83 .IR init.d (7)).
84 Known runlevels are:
85 .sp 1
86 .in +1l
87 .nf
88 \fB0\fR\ used for System halt
89 \fB1\fR\ used for single user mode
90 \fB2\fR\ used for local multiuser without remote network
91 \fB3\fR\ used for full multiuser with network
92 \fB4\fR\ reserved for local use
93 \fB5\fR\ used for full multiuser with network and xdm
94 \fB6\fR\ used for System reboot
95 \fBS\fR\ used during boot into single user mode
96 \fBB\fR\ used during boot before any other runlevel
97 .fi
98 .in -1l
99 .sp 1
100 .PP
101 .B insserv
102 scans for
103 .B System Facilities
104 in the configuration file
105 .I /etc/insserv.conf
106 and each file in the directory
107 .IR /etc/insserv.conf.d/ .
108 Each line which begins with
109 .B $
110 and a following name defines a system facility
111 accordingly to the Linux Standard Base Specification (LSB),
112 All names followed by such a system facility
113 will declare the required dependencies of the facility.
114 Here is an example for
115 .IR /etc/insserv.conf :
116 .sp 1
117 .in +1l
118 .nf
119 # All local filesystems are mounted
120 # (done during boot phase)
121 $local_fs boot
122
123 # Low level networking
124 $network network route
125
126 # Named is operational
127 $named named
128
129 # All remote filesystems are mounted
130 # (in some cases /usr may be remote).
131 $remote_fs $local_fs nfs
132
133 # System logger is operational
134 $syslog syslog
135
136 # All network daemons are running
137 $netdaemons portmap inetd
138
139 # Services which need to be interactive
140 <interactive> boot.crypto
141 .fi
142 .in -1l
143 .sp 1
144 Names starting with a `+' sign are marked as optional.
145 If the service with the name after the plus sign is
146 available it will be used, if not available it is
147 ignored silently. Words beginning with
148 .B <
149 and ending with
150 .B >
151 are keywords. Currently
152 .B <interactive>
153 is the only know keyword for marking a service
154 as an interactive one, e.g. a service which requires
155 a passphrase or password input during boot
156 or runlevel change.
157 .P
158 Beside the defined
159 .B System Facilities
160 in the configuration file
161 .IR /etc/insserv.conf ,
162 .B insserv
163 also knows the special facility
164 .BR $all .
165 This facility indicates that a service should be inserted
166 at the end of all services. Clearly all services using
167 this facility will be grouped into one starting order.
168 .\"
169 .SH OPTIONS
170 Currently there are only four options for
171 .BR insserv .
172 .TP
173 .BR \-v ,\ \-\-verbose
174 Write out what is currently going on.
175 .TP
176 .BR \-n ,\ \-\-dryrun
177 Do not update symlinks.
178 .TP
179 .BR \-r ,\ \-\-remove
180 Remove the listed scripts from all runlevels.
181 .TP
182 .BR \-d ,\ \-\-default
183 Use default runlevels a defined in the scripts.
184 This may restore an edited runlevel link scheme.
185 .TP
186 .BR \-f ,\ \-\-force
187 Ignore if a required service is missed.
188 .TP
189 .BR \-h ,\ \-\-help
190 Print out short usage message.
191 .PP
192 But you may use the argument syntax described in the
193 following section.
194 .SH ARGUMENTS
195 .TP
196 .RI [[ / ] path/to/init.d/ ]
197 Relative or absolute path to the init scripts base directory.
198 For the SuSE Linux boot concept, this defaults to
199 .I /etc/init.d/
200 in compliance with the LSB specification.
201 In this case
202 .B insserv
203 does not add or remove a script to the runlevels
204 declared in the script headers, but may re\-order the
205 runlevels if the order of the currently enabled scripts
206 has changed (see option
207 .BR \-d ).
208 Note that if a relative path is used
209 .B insserv
210 has to be called from the root directory.
211 .TP
212 .RI [[ / ] path/to/init.d/ ] script\ ...
213 List of scripts which have to be added to
214 the runlevels. If a path is used it
215 should point to the absolute or relative
216 location of the boot scripts.
217 .B insserv
218 checks for the existence of these scripts.
219 For the runlevels the information found in
220 the script is used.
221 .TP
222 .RI [[ / ] path/to/init.d/ ] script [ ,start=<lvl1> [ ,<lvl2> ]]\ ...
223 List of scripts which have to be added to
224 the specified runlevels to be started with.
225 You may use this extension to overwrite the default values
226 for start and stop runlevels of the script.
227 Note that
228 .BR <lvl1> ,\ <lvl2> ,\ ...
229 are the known runlevels explained above.
230 The extension
231 .IR ,stop=<lvl1> [ ,<lvl2> ]]
232 is possible but ignored on SuSE Linux.
233 .TP
234 .RI \fB\-r\fR\ [[ / ] path/to/init.d/ ] script\ ...
235 List of scripts which should be removed from
236 the runlevels. If a path is used it
237 should point to the absolute or relative
238 location of the boot scripts.
239 .B insserv
240 checks for the existence of these scripts.
241 .\"
242 .SH EXIT CODES
243 The exit codes have the following conditions:
244 .RS 7
245 .IP 0 5
246 Service was successfully installed or removed
247 .IP 1 5
248 Service was not installed or removed
249 .RE
250 .RS 5
251 .SH NOTE
252 Please be aware that the following patterns of
253 boot script file names will be not accepted by
254 .BR insserv:
255 .sp 1
256 .in +1l
257 .nf
258 *.local
259 *.rpm*
260 *.ba*
261 *.old
262 *.new
263 *.org
264 *.orig
265 *.save
266 *.swp
267 *.core
268 *~
269 .fi
270 .in -1l
271 .sp 1
272 with the wildcard character
273 .BR * .
274 Beside this all boot script file names beginning with one
275 of the following characters
276 .sp 1
277 .in +1l
278 .nf
279 $.#%_+-\\*[]^:()~
280 .fi
281 .in -1l
282 .sp 1
283 will be ignored.
284 .SH BUGS
285 Boot script sometimes misses comments.
286 .SH FILES
287 .TP
288 .I /etc/insserv.conf
289 configuration file for
290 .B insserv
291 which defines the LSB System Facilities.
292 .TP
293 .I /etc/insserv.conf.d/
294 directory for further configuration files for declaring
295 LSB System Facilities.
296 .TP
297 .I /etc/init.d/
298 path to the SuSE boot script base directory as
299 required by the Linux Standard Base Specification (LSB).
300 .PP
301 .IR /etc/init.d/.depend.boot ,
302 .br
303 .IR /etc/init.d/.depend.start ,
304 .br
305 .I /etc/init.d/.depend.stop
306 .in +7
307 The
308 .BR make (1)
309 like dependency files produced by
310 .B insserv
311 for
312 .IR booting ", " starting ", and " stopping
313 with the help of
314 .BR startpar (8).
315 .in -7
316
317 .\"
318 .SH SEE ALSO
319 .BR init.d (7),
320 .BR init (7),
321 .BR startproc (8),
322 .BR checkproc (8),
323 .BR killproc (8),
324 .BR startpar (8).
325 .SH COPYRIGHT
326 2000\-2003 Werner Fink,
327 2000\-2003 SuSE GmbH Nuernberg, Germany.
328 .SH AUTHOR
329 Werner Fink <feedback@suse.de>
0 .\"
1 .\" Copyright 2000-2008 Werner Fink
2 .\" Copyright 2000-2003 SuSE GmbH Nuernberg, Germany
3 .\" Copyright 2007 SuSE Linux Products GmbH Nuernberg, Germany
4 .\" Copyright 2008 SuSE Linux Products GmbH Nuernberg, Germany
5 .\"
6 .\" This program is free software; you can redistribute it and/or modify
7 .\" it under the terms of the GNU General Public License as published by
8 .\" the Free Software Foundation; either version 2 of the License, or
9 .\" (at your option) any later version.
10 .\"
11 @@BEGIN_SUSE@@
12 .TH INSSERV 8 "Jan 30, 2008" "Version 1.11" "The SuSE boot concept"
13 .UC 8
14 .OS SuSE Linux
15 @@ELSE_SUSE@@
16 .TH INSSERV 8 "Jan 30, 2008" "Version 1.11"
17 .UC 8
18 .OS Debian
19 @@END_SUSE@@
20 .SH NAME
21 insserv \- Enable an installed system init script
22 .SH SYNOPSIS
23 .\"
24 .B insserv
25 .RB [ \-v ]
26 .RB [ \-c\ <config> ]
27 .RB [ \-p\ <path> ]
28 .RB [ \-d ]
29 .RB [ \-f ]
30 .RI [[ / ] path/to/init.d/ ] script \ ...
31 .PP
32 .B insserv
33 .RB [ \-v ]
34 .RB [ \-c\ <config> ]
35 .RB [ \-p\ <path> ]
36 @@BEGIN_SUSE@@
37 .RI [[ / ] path/to/init.d/ ] script [ ,start=<lvl1> [ ,<lvl2>\ ... ]
38 @@ELSE_SUSE@@
39 .RI [[ / ] path/to/init.d/ ] script [ ,start=<lvl1> [ ,<lvl2>\ ... ] ,stop=<lvl1> [ ,<lvl2>\ ... ]]
40 @@END_SUSE@@
41 .PP
42 .B insserv
43 .RB [ \-v ]
44 .RB [ \-c\ <config> ]
45 .RB [ \-p\ <path> ]
46 .B \-r
47 .RB [ \-d ]
48 .RB [ \-f ]
49 .RI [[ / ] path/to/init.d/ ] script \ ...
50 .PP
51 .B insserv
52 .B \-h
53 .PP
54 @@BEGIN_SUSE@@
55 .RB /usr/lib/lsb/install_initd
56 .RI [[ / ] path/to/init.d/script ]
57 .PP
58 .RB /usr/lib/lsb/remove_initd
59 .RI [[ / ] path/to/init.d/script ]
60 @@END_SUSE@@
61 .SH DESCRIPTION
62 .B insserv
63 enables an installed system init script (`boot script')
64 by reading the comment header of the script, e.g.:
65 .sp 1
66 .in +1l
67 .nf
68 ### BEGIN INIT INFO
69 # Provides: boot_facility_1 [ boot_facility_2 ...]
70 # Required-Start: boot_facility_1 [ boot_facility_2 ...]
71 # Required-Stop: boot_facility_1 [ boot_facility_2 ...]
72 # Should-Start: boot_facility_1 [ boot_facility_2 ...]
73 # Should-Stop: boot_facility_1 [ boot_facility_2 ...]
74 # X-Start-Before: boot_facility_1 [ boot_facility_2 ...]
75 # X-Stop-After: boot_facility_1 [ boot_facility_2 ...]
76 # Default-Start: run_level_1 [ run_level_2 ...]
77 # Default-Stop: run_level_1 [ run_level_2 ...]
78 # Short-Description: single_line_description
79 # Description: multiline_description
80 ### END INIT INFO
81 .fi
82 .in -1l
83 .sp 1
84 and calculating the dependencies between all scripts.
85 @@BEGIN_SUSE@@
86 Please note, that the
87 .BR Required-Stop,
88 .BR Should-Stop ,
89 .BR X-Stop-After,
90 and
91 .B Default\-Stop
92 are ignored in SuSE Linux, because the SuSE boot script concept
93 uses a differential link scheme (see
94 .IR init.d (7)).
95 @@ELSE_SUSE@@
96 Please be aware that the line
97 .sp 1
98 .in +1l
99 .nf
100 # Required-Stop: boot_facility_1 [ boot_facility_2 ...]
101 .fi
102 .in -1l
103 .sp 1
104 declares facilities which must be available during shutdown of the service
105 declared in the
106 .B Provides
107 tag. Same holds true for
108 .sp 1
109 .in +1l
110 .nf
111 # Should-Stop: boot_facility_1 [ boot_facility_2 ...]
112 .fi
113 .in -1l
114 .sp 1
115 which declares facilities which should be available during shutdown of
116 the service declared in the
117 .B Provides
118 tag. In both cases the script system should avoid stopping services
119 which are declared by these two Stop tags until the script including
120 these tags is stopped.
121 @@END_SUSE@@
122 .PP
123 The optional
124 .B X\-Start\-Before
125 keyword implies that the script using this keyword
126 should be started
127 .B before
128 the specified service names. This implies that those
129 services now depend on the specifying script.
130 With known dependencies and runlevel(s)
131 .B insserv
132 sets and reorders the corresponding symbolic links
133 of the concerned runlevels
134 @@BEGIN_SUSE@@
135 directories (see \fI init.d\fR (7)).
136 @@ELSE_SUSE@@
137 directories.
138 @@END_SUSE@@
139 Known runlevels are:
140 .sp 1
141 .in +1l
142 .nf
143 \fB0\fR\ used for System halt
144 \fB1\fR\ used for single user mode
145 \fB2\fR\ used for local multiuser without remote network
146 \fB3\fR\ used for full multiuser with network
147 \fB4\fR\ reserved for local use
148 \fB5\fR\ used for full multiuser with network and xdm
149 \fB6\fR\ used for System reboot
150 @@BEGIN_SUSE@@
151 \fBS\fR\ used during boot into single user mode
152 \fBB\fR\ used during boot before any other runlevel
153 @@ELSE_SUSE@@
154 \fBS\fR\ used during boot before any other runlevel
155 @@END_SUSE@@
156 .fi
157 .in -1l
158 .sp 1
159 .PP
160 .B insserv
161 scans for
162 .B System Facilities
163 in the configuration file
164 .I /etc/insserv.conf
165 and each file in the directory
166 .IR /etc/insserv.conf.d/ .
167 Each line which begins with
168 .B $
169 and a following name defines a system facility
170 accordingly to the Linux Standard Base Specification (LSB),
171 All names followed by such a system facility
172 will declare the required dependencies of the facility.
173 Here is an example for
174 .IR /etc/insserv.conf :
175 .sp 1
176 .in +1l
177 .nf
178 # All local filesystems are mounted
179 # (done during boot phase)
180 $local_fs boot
181
182 # Low level networking
183 $network network route
184
185 # Named is operational
186 $named named
187
188 # All remote filesystems are mounted
189 # (in some cases /usr may be remote).
190 $remote_fs $local_fs nfs
191
192 # System logger is operational
193 $syslog syslog
194
195 # All network daemons are running
196 $netdaemons portmap inetd
197
198 # Services which need to be interactive
199 <interactive> boot.crypto
200 .fi
201 .in -1l
202 .sp 1
203 Names starting with a `+' sign are marked as optional.
204 If the service with the name after the plus sign is
205 available it will be used, if not available it is
206 ignored silently. Words beginning with
207 .B <
208 and ending with
209 .B >
210 are keywords. Currently
211 .B <interactive>
212 is the only know keyword for marking a service
213 as an interactive one, e.g. a service which requires
214 a passphrase or password input during boot
215 or runlevel change.
216 .P
217 Beside the defined
218 .B System Facilities
219 in the configuration file
220 .IR /etc/insserv.conf ,
221 .B insserv
222 also knows the special facility
223 .BR $all .
224 This facility indicates that a service should be inserted
225 at the end of all services. Clearly all services using
226 this facility will be grouped into one starting order.
227 .\"
228 .SH OPTIONS
229 Currently there exists nine options for
230 .BR insserv .
231 .TP
232 .BR \-v ,\ \-\-verbose
233 Write out what is currently going on.
234 .TP
235 .BR \-c\ <config> ,\ \-\-config\ <config>
236 Specify path to the insserv.conf file and the insserv.conf.d
237 directory. Useful for testing.
238 .TP
239 .BR \-o\ <path> ,\ \-\-override\ <path>
240 Path to replace existing LSB comment headers with the comment
241 headers found in this path (default path is
242 .IR /etc/insserv/overrides/ ).
243 .TP
244 .BR \-p\ <path> ,\ \-\-path\ <path>
245 Specify path to init.d directory. Useful for testing.
246 .TP
247 .BR \-n ,\ \-\-dryrun
248 Do not update symlinks.
249 .TP
250 .BR \-r ,\ \-\-remove
251 Remove the listed scripts from all runlevels.
252 .TP
253 .BR \-d ,\ \-\-default
254 Use default runlevels a defined in the scripts.
255 This may restore an edited runlevel link scheme.
256 .TP
257 .BR \-f ,\ \-\-force
258 Ignore if a required service is missed.
259 .TP
260 .BR \-h ,\ \-\-help
261 Print out short usage message.
262 .PP
263 But you may use the argument syntax described in the
264 following section.
265 .SH ARGUMENTS
266 .TP
267 .RI [[ / ] path/to/init.d/ ]
268 Relative or absolute path to the init scripts base directory.
269 @@BEGIN_SUSE@@
270 For the SuSE Linux boot concept, this defaults to
271 @@ELSE_SUSE@@
272 This defaults to
273 @@END_SUSE@@
274 .I /etc/init.d/
275 in compliance with the LSB specification.
276 In this case
277 .B insserv
278 does not add or remove a script to the runlevels
279 declared in the script headers, but may re\-order the
280 runlevels if the order of the currently enabled scripts
281 has changed (see option
282 .BR \-d ).
283 Note that if a relative path is used
284 .B insserv
285 has to be called from the root directory.
286 .TP
287 .RI [[ / ] path/to/init.d/ ] script\ ...
288 List of scripts which have to be added to
289 the runlevels. If a path is used it
290 should point to the absolute or relative
291 location of the boot scripts.
292 .B insserv
293 checks for the existence of these scripts.
294 For the runlevels the information found in
295 the script is used.
296 .TP
297 .RI [[ / ] path/to/init.d/ ] script [ ,start=<lvl1> [ ,<lvl2> ]]\ ...
298 List of scripts which have to be added to
299 the specified runlevels to be started with.
300 You may use this extension to overwrite the default values
301 for start and stop runlevels of the script.
302 Note that
303 .BR <lvl1> ,\ <lvl2> ,\ ...
304 are the known runlevels explained above.
305 The extension
306 .IR ,stop=<lvl1> [ ,<lvl2> ]]
307 is possible
308 @@BEGIN_SUSE@@
309 is possible but ignored on SuSE Linux.
310 @@ELSE_SUSE@@
311 is also possible.
312 @@END_SUSE@@
313 .TP
314 .RI \fB\-r\fR\ [[ / ] path/to/init.d/ ] script\ ...
315 List of scripts which should be removed from
316 the runlevels. If a path is used it
317 should point to the absolute or relative
318 location of the boot scripts.
319 .B insserv
320 checks for the existence of these scripts.
321 .\"
322 .SH EXIT CODES
323 The exit codes have the following conditions:
324 .RS 7
325 .IP 0 5
326 Service was successfully installed or removed
327 .IP 1 5
328 Service was not installed or removed
329 .RE
330 .RS 5
331 .SH NOTE
332 Please be aware that the following patterns of
333 boot script file names will be not accepted by
334 .BR insserv:
335 .sp 1
336 .in +1l
337 .nf
338 @@BEGIN_SUSE@@
339 *.local
340 @@END_SUSE@@
341 *.dpkg*
342 *.rpm*
343 *.ba*
344 *.old
345 *.new
346 *.org
347 *.orig
348 *.save
349 *.swp
350 *.core
351 *~
352 .fi
353 .in -1l
354 .sp 1
355 with the wildcard character
356 .BR * .
357 Beside this all boot script file names beginning with one
358 of the following characters
359 .sp 1
360 .in +1l
361 .nf
362 $.#%_+-\\*[]^:()~
363 .fi
364 .in -1l
365 .sp 1
366 will be ignored.
367 .SH BUGS
368 Boot script sometimes misses comments.
369 .SH FILES
370 .TP
371 .I /etc/insserv.conf
372 configuration file for
373 .B insserv
374 which defines the LSB System Facilities.
375 .TP
376 .I /etc/insserv.conf.d/
377 directory for further configuration files for declaring
378 LSB System Facilities.
379 .TP
380 .I /etc/init.d/
381 path to the
382 @@BEGIN_SUSE@@
383 SuSE
384 @@END_SUSE@@
385 init script base directory as
386 required by the Linux Standard Base Specification (LSB).
387 .PP
388 .IR /etc/init.d/.depend.boot ,
389 .br
390 .IR /etc/init.d/.depend.start ,
391 .br
392 .I /etc/init.d/.depend.stop
393 .in +7
394 The
395 .BR make (1)
396 like dependency files produced by
397 .B insserv
398 for
399 .IR booting ", " starting ", and " stopping
400 with the help of
401 .BR startpar (8).
402 .in -7
403
404 .\"
405 .SH SEE ALSO
406 @@BEGIN_SUSE@@
407 .BR init.d (7),
408 @@END_SUSE@@
409 .BR init (7),
410 @@BEGIN_SUSE@@
411 .BR startproc (8),
412 .BR checkproc (8),
413 .BR killproc (8),
414 @@END_SUSE@@
415 .BR startpar (8).
416 .SH COPYRIGHT
417 2000\-2008 Werner Fink,
418 .br
419 2000\-2003 SuSE GmbH Nuernberg, Germany,
420 .br
421 2007 SuSE Linux Products GmbH Nuernberg, Germany.
422 .br
423 2008 SuSE Linux Products GmbH Nuernberg, Germany.
424 .SH AUTHOR
425 Werner Fink <feedback@suse.de>
00 /*
11 * insserv(.c)
22 *
3 * Copyright 2000-2005 Werner Fink, 2000 SuSE GmbH Nuernberg, Germany,
3 * Copyright 2000-2008 Werner Fink, 2000 SuSE GmbH Nuernberg, Germany,
44 * 2003 SuSE Linux AG, Germany.
55 * 2004 SuSE LINUX AG, Germany.
6 * 2005 SUSE LINUX Products GmbH
7 * Copyright 2005 Petter Reinholdtsen
6 * 2005-2008 SUSE LINUX Products GmbH, Germany.
7 * Copyright 2005,2008 Petter Reinholdtsen
88 *
99 * This program is free software; you can redistribute it and/or modify
1010 * it under the terms of the GNU General Public License as published by
1414
1515 #define MINIMAL_MAKE 1 /* Remove disabled scripts from .depend.boot,
1616 * .depend.start and .depend.stop */
17 #define FACI_EXPANSION 0 /* Expand all system facilities before use
18 them in dependcies */
19
1720 #include <pwd.h>
1821 #include <string.h>
1922 #include <unistd.h>
2427 #include <fcntl.h>
2528 #include <sys/stat.h>
2629 #include <sys/types.h>
30 #include <sys/param.h>
2731 #include <dirent.h>
2832 #include <regex.h>
2933 #include <errno.h>
3337
3438 static const char *map_runlevel_to_location(const int runlevel);
3539 #ifndef SUSE
36 static const int map_runlevel_to_lvl (const int runlevel);
37 static const int map_runlevel_to_seek(const int runlevel);
40 static int map_runlevel_to_seek(const int runlevel);
3841 #endif /* not SUSE */
42
43 #ifdef SUSE
44 #define DEFAULT_START_LVL "3 5"
45 #undef USE_STOP_TAGS
46 #undef USE_KILL_IN_SINGLE
47 #else /* not SUSE, but Debian */
48 #define DEFAULT_START_LVL "2 3 4 5"
49 #define DEFAULT_STOP_LVL "0 1 6"
50 #define DEFAULT_DEPENDENCY "$remote_fs $syslog"
51 #define USE_STOP_TAGS
52 #undef USE_KILL_IN_SINGLE
53 #endif /* not SUSE, but Debian */
3954
4055 #ifndef INITDIR
4156 # define INITDIR "/etc/init.d"
57 #endif
58 #ifndef OVERRIDEDIR
59 # define OVERRIDEDIR "/etc/insserv/overrides"
4260 #endif
4361 #ifndef INSCONF
4462 # define INSCONF "/etc/insserv.conf"
4866 * For a description of regular expressions see regex(7).
4967 */
5068 #define COMM "^#[[:blank:]]*"
51 #define VALUE ":[[:blank:]]*([[:print:][:blank:]]*)"
69 #define VALUE ":[[:blank:]]*([[:print:]]*)"
5270 /* The second substring contains our value (the first is all) */
5371 #define SUBNUM 2
5472 #define SUBNUM_SHD 3
7391 #define DESCRIPTION COMM "description" VALUE
7492
7593 /* System facility search within /etc/insserv.conf */
76 #define EQSIGN "([[:blank:]]?[=:]+[[:blank:]]?|[[:blank:]]+)"
77 #define CONFLINE "^(\\$[a-z0-9_-]+)" EQSIGN "([[:print:][:blank:]]*)"
78 #define CONFLINE2 "^(<[a-z0-9_-]+>)" EQSIGN "([[:print:][:blank:]]*)"
94 #define EQSIGN "([[:blank:]]*[=:][[:blank:]]*|[[:blank:]]+)"
95 #define CONFLINE "^(\\$[a-z0-9_-]+)" EQSIGN "([[:print:]]*)"
96 #define CONFLINE2 "^(<[a-z0-9_-]+>)" EQSIGN "([[:print:]]*)"
7997 #define SUBCONF 2
8098 #define SUBCONFNUM 4
8199
90108
91109 /* When to be verbose */
92110 static boolean dryrun = false;
111
112 /* When paths set do not add root if any */
113 static boolean set_override = false;
114 static boolean set_insconf = false;
93115
94116 /* Search results points here */
95117 typedef struct lsb_struct {
119141 regex_t desc;
120142 } reg_t;
121143
144 typedef struct creg_struct {
145 regex_t isysfaci;
146 regex_t isactive;
147 } creg_t;
148
122149 static lsb_t script_inf;
123150 static reg_t reg;
151 static creg_t creg;
124152 static char empty[1] = "";
125153
126154 /* Delimeters used for spliting results with strsep(3) */
137165
138166 static list_t pwd = { &(pwd), &(pwd) }, * topd = &(pwd);
139167
168 static void pushd(const char *const __restrict path);
140169 static void pushd(const char *const path)
141170 {
142171 pwd_t * dir;
189218 */
190219 typedef struct req_serv {
191220 list_t list;
192 unsigned int flags;
221 uint flags;
193222 char * serv;
194223 } req_t;
195224 #define REQ_MUST 0x00000001
218247 struct serv_struct {
219248 list_t id;
220249 sort_t sort;
221 unsigned int opts;
250 uint opts;
222251 char order;
223252 char * name;
224253 serv_t * main;
225 unsigned int lvls;
226 #ifndef SUSE
227 unsigned int lvlk;
228 #endif /* not SUSE */
254 uint lvls;
255 #ifdef USE_STOP_TAGS
256 uint lvlk;
257 #endif /* USE_STOP_TAGS */
229258 };
230259 #define getserv(arg) list_entry((arg), struct serv_struct, id)
231260
234263 /*
235264 * Find or add and initialize a service
236265 */
266 static serv_t * addserv(const char *const __restrict serv) __attribute__((nonnull(1)));
237267 static serv_t * addserv(const char *const serv)
238268 {
239269 serv_t * this;
262292 this->main = (serv_t *)0;
263293 this->order = 0;
264294 this->lvls = 0;
265 #ifndef SUSE
295 #ifdef USE_STOP_TAGS
266296 this->lvlk = 0;
267 #endif /* not SUSE */
297 #endif /* USE_STOP_TAGS */
268298 ptr = serv_start->prev;
269299 goto out;
270300 }
274304 return getserv(ptr);
275305 }
276306
307 static serv_t * findserv(const char *const __restrict serv) __attribute__((nonnull(1)));
277308 static serv_t * findserv(const char *const serv)
278309 {
279310 list_t * ptr;
295326 /*
296327 * Remember requests for required or should services and expand `$' token
297328 */
298 static void rememberreq(serv_t *serv, unsigned int bit, const char * required)
329 static void rememberreq(serv_t *__restrict serv, uint bit, const char *__restrict required) __attribute__((noinline,nonnull(1,3)));
330 static void rememberreq(serv_t *serv, uint bit, const char * required)
299331 {
300332 char * token, * tmp = strdupa(required);
301333 list_t * ptr;
302 unsigned int old = bit;
334 uint old = bit;
303335
304336 while ((token = strsep(&tmp, delimeter))) {
305337 boolean found = false;
359391 }
360392 }
361393
362 static void reversereq(const serv_t * serv, const char * token, const char * list)
394 static void reversereq(const serv_t *__restrict serv, uint bit, const char *__restrict list) __attribute__((noinline,nonnull(1,3)));
395 static void reversereq(const serv_t * serv, uint bit, const char * list)
363396 {
364397 const char * dep;
365398 char * rev = strdupa(list);
399 uint old = bit;
366400
367401 while ((dep = strsep(&rev, delimeter)) && *dep) {
368402 serv_t * tmp;
369403 list_t * ptr;
370404
405 if (!*dep)
406 continue;
407
408 bit = old;
409
371410 switch (*dep) {
372411 case '+':
373412 dep++;
413 bit = REQ_SHLD;
374414 default:
375 if ((tmp = findserv(dep))) {
415 if (!(tmp = findserv(dep)))
416 tmp = addserv(dep);
417 if (tmp) {
376418 const char * name;
377419 if ((name = getscript(serv->name)) == (char*)0)
378 name = serv->name;
379 rememberreq(tmp, REQ_SHLD, name);
380 }
381 requiresv(dep, token);
420 name = serv->name;
421 rememberreq(tmp, bit, name);
422 }
382423 break;
383424 case '$':
384425 list_for_each(ptr, sysfaci_start) {
385426 if (!strcmp(dep, getfaci(ptr)->name)) {
386 reversereq(serv, token, getfaci(ptr)->repl);
427 reversereq(serv, bit, getfaci(ptr)->repl);
387428 break;
388429 }
389430 }
395436 /*
396437 * Check required services for name
397438 */
439 static boolean chkrequired(const char *const __restrict name) __attribute__((nonnull(1)));
398440 static boolean chkrequired(const char *const name)
399441 {
400442 serv_t * serv = findserv(name);
424466 /*
425467 * Check dependencies for name as a service
426468 */
469 static boolean chkdependencies(const char *const __restrict name) __attribute__((nonnull(1)));
427470 static boolean chkdependencies(const char *const name)
428471 {
429472 list_t * srv;
454497 /*
455498 * This helps us to work out the current symbolic link structure
456499 */
457 static serv_t * current_structure(const char *const this, const char order, const int runlvl)
500 static serv_t * current_structure(const char *const __restrict this, const char order, const int runlvl, const char type) __attribute__((always_inline,nonnull(1)));
501 static serv_t * current_structure(const char *const this, const char order, const int runlvl, const char type)
458502 {
459503 serv_t * serv = addserv(this);
460504
461505 if (serv->order < order)
462506 serv->order = order;
463507
464 switch (runlvl) {
465 case 0: serv->lvls |= LVL_HALT; break;
466 case 1: serv->lvls |= LVL_ONE; break;
467 case 2: serv->lvls |= LVL_TWO; break;
468 case 3: serv->lvls |= LVL_THREE; break;
469 case 4: serv->lvls |= LVL_FOUR; break;
470 case 5: serv->lvls |= LVL_FIVE; break;
471 case 6: serv->lvls |= LVL_REBOOT; break;
472 #ifdef SUSE
473 case 7: serv->lvls |= LVL_SINGLE; break;
474 case 8: serv->lvls |= LVL_BOOT; break;
475 #else /* not SUSE */
476 case 7: serv->lvls |= LVL_BOOT; break;
477 #endif /* not SUSE */
478 default: break;
479 }
508 if ('S' == type)
509 serv->lvls |= map_runlevel_to_lvl(runlvl);
510 #ifdef USE_STOP_TAGS
511 else
512 serv->lvlk |= map_runlevel_to_lvl(runlvl);
513 #endif /* USE_STOP_TAGS */
480514
481515 return serv;
482516 }
483517
484 static void setlsb(const char* const name)
518 static void setlsb(const char *__restrict const name) __attribute__((unused));
519 static void setlsb(const char * const name)
485520 {
486521 serv_t * serv = findserv(name);
487522 if (serv)
493528 * max order, therefore we set a dependency to the first
494529 * lsb conform service found in current link scheme.
495530 */
531 static inline void nonlsb_script(void) __attribute__((always_inline));
496532 static inline void nonlsb_script(void)
497533 {
498534 list_t * pos;
528564 * within on start or stop service group. Remaining problem is that
529565 * if required scripts are missed the order can be wrong.
530566 */
567 static inline void active_script(void) __attribute__((always_inline));
531568 static inline void active_script(void)
532569 {
533570 list_t * pos;
603640 * current the start order.
604641 */
605642
643 static inline void all_script(void) __attribute__((always_inline));
606644 static inline void all_script(void)
607645 {
608646 list_t * pos;
647685 /*
648686 * Remember reverse requests for required services
649687 */
688 static void reverse(char *__restrict stop, char *__restrict request) __attribute__((nonnull(1,2)));
650689 static void reverse(char *stop, char *request)
651690 {
652691 serv_t * srv = addserv(stop);
671710 /*
672711 * Make the dependency files
673712 */
713 static inline void makedep(void) __attribute__((always_inline));
674714 static inline void makedep(void)
675715 {
676716 list_t * srv;
700740 const serv_t *serv = findserv(getprovides(name));
701741 if (!serv || !(serv->opts & SERV_ENABLED))
702742 continue;
703 #endif
743 #endif /* MINIMAL_MAKE */
704744 fprintf(boot, " %s", name);
705745 }
706746 putc('\n', boot);
712752 const serv_t *serv = findserv(getprovides(name));
713753 if (!serv || !(serv->opts & SERV_ENABLED))
714754 continue;
715 #endif
755 #endif /* MINIMAL_MAKE */
716756 fprintf(start, " %s", name);
717757 }
718758 putc('\n', start);
725765 #if defined(MINIMAL_MAKE) && (MINIMAL_MAKE != 0)
726766 if (!cur || !(cur->opts & SERV_ENABLED))
727767 continue;
728 #else
768 #else /* not MINIMAL_MAKE */
729769 if (!cur)
730770 continue;
731 #endif
771 #endif /* not MINIMAL_MAKE */
732772
733773 if (list_empty(&(cur->sort.req)))
734774 continue;
843883 const serv_t *serv = findserv(getprovides(name));
844884 if (!serv || !(serv->opts & SERV_ENABLED))
845885 continue;
846 #endif
886 #endif /* MINIMAL_MAKE */
847887 fprintf(stop, " %s", name);
848888 }
849889 putc('\n', stop);
899939 * Internal logger
900940 */
901941 char *myname = (char*)0;
942 static void _logger (const char *const __restrict fmt, va_list ap);
902943 static void _logger (const char *const fmt, va_list ap)
903944 {
904945 char buf[strlen(myname)+2+strlen(fmt)+1];
953994 * Check for script in list.
954995 */
955996 static int curr_argc = -1;
997 static inline boolean chkfor(const char *const __restrict script, char ** const __restrict list, const int cnt) __attribute__((nonnull(1,2)));
956998 static inline boolean chkfor(const char *const script, char ** const list, const int cnt)
957999 {
9581000 boolean isinc = false;
9731015 * Open a runlevel directory, if it not
9741016 * exists than create one.
9751017 */
976 static DIR * openrcdir(const char *const rcpath)
1018 static DIR * openrcdir(const char *const __restrict rcpath) __attribute__((nonnull(1)));
1019 static DIR * openrcdir(const char *const rcpath)
9771020 {
9781021 DIR * rcdir;
9791022 struct stat st;
10001043 /*
10011044 * Wrapper for regcomp(3)
10021045 */
1003 static inline void regcompiler (regex_t *preg, const char *regex, int cflags)
1046 static inline void regcompiler(regex_t *__restrict preg, const char *__restrict regex, int cflags) __attribute__((always_inline,nonnull(1,2)));
1047 static inline void regcompiler(regex_t *preg, const char *regex, int cflags)
10041048 {
10051049 register int ret = regcomp(preg, regex, cflags);
10061050 if (ret) {
10141058 /*
10151059 * Wrapper for regexec(3)
10161060 */
1017 static inline boolean regexecutor (regex_t *preg, const char *string,
1018 size_t nmatch, regmatch_t pmatch[], int eflags)
1061 static inline boolean regexecutor(regex_t *__restrict preg, const char *__restrict string, size_t nmatch, regmatch_t pmatch[], int eflags) __attribute__((nonnull(1,2)));
1062 static inline boolean regexecutor(regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags)
10191063 {
10201064 register int ret = regexec(preg, string, nmatch, pmatch, eflags);
10211065 if (ret > REG_NOMATCH) {
10221066 regerror(ret, preg, buf, sizeof (buf));
10231067 regfree (preg);
1024 error("%s\n", buf);
1068 warn("%s\n", buf);
10251069 }
10261070 return (ret ? false : true);
10271071 }
10321076 * calling scan_script_defaults(). After the last call
10331077 * of scan_script_defaults() we may free the expressions.
10341078 */
1035 static inline void scan_script_regalloc()
1079 static inline void scan_script_regalloc(void) __attribute__((always_inline));
1080 static inline void scan_script_regalloc(void)
10361081 {
10371082 regcompiler(&reg.prov, PROVIDES, REG_EXTENDED|REG_ICASE);
10381083 regcompiler(&reg.req_start, REQUIRED_START, REG_EXTENDED|REG_ICASE|REG_NEWLINE);
10461091 regcompiler(&reg.desc, DESCRIPTION, REG_EXTENDED|REG_ICASE|REG_NEWLINE);
10471092 }
10481093
1049 static boolean scan_script_defaults(const char *const path)
1094 static inline void scan_script_reset(void) __attribute__((always_inline));
1095 static inline void scan_script_reset(void)
1096 {
1097 xreset(script_inf.provides);
1098 xreset(script_inf.required_start);
1099 xreset(script_inf.required_stop);
1100 xreset(script_inf.should_start);
1101 xreset(script_inf.should_stop);
1102 xreset(script_inf.start_before);
1103 xreset(script_inf.stop_after);
1104 xreset(script_inf.default_start);
1105 xreset(script_inf.default_stop);
1106 xreset(script_inf.description);
1107 }
1108
1109 #define FOUND_LSB_HEADER 0x01
1110 #define FOUND_LSB_DEFAULT 0x02
1111 #define FOUND_LSB_OVERRIDE 0x04
1112
1113 static uchar scan_lsb_headers(const char *const __restrict path) __attribute__((nonnull(1)));
1114 static uchar scan_lsb_headers(const char *const path)
10501115 {
10511116 regmatch_t subloc[SUBNUM_SHD+1], *val = &subloc[SUBNUM-1], *shl = &subloc[SUBNUM_SHD-1];
10521117 FILE *script;
10531118 char *pbuf = buf;
10541119 char *begin = (char*)0, *end = (char*)0;
1055 boolean ret = false;
1120 uchar ret = 0;
10561121
10571122 #define provides script_inf.provides
10581123 #define required_start script_inf.required_start
10701135 if (!script)
10711136 error("fopen(%s): %s\n", path, strerror(errno));
10721137
1073 /* Reset old results */
1074 xreset(provides);
1075 xreset(required_start);
1076 xreset(required_stop);
1077 xreset(should_start);
1078 xreset(should_stop);
1079 xreset(start_before);
1080 xreset(stop_after);
1081 xreset(default_start);
1082 xreset(default_stop);
1083 xreset(description);
1084
10851138 #define COMMON_ARGS buf, SUBNUM, subloc, 0
10861139 #define COMMON_SHD_ARGS buf, SUBNUM_SHD, subloc, 0
10871140 while (fgets(buf, sizeof(buf), script)) {
10881141
10891142 /* Skip scanning above from LSB magic start */
1090 if (!begin && !(begin = strstr(buf, "### BEGIN INIT INFO")))
1091 continue;
1143 if (!begin) {
1144 if ( (begin = strstr(buf, "### BEGIN INIT INFO")) ) {
1145 /* Let the latest LSB header override the one found earlier */
1146 scan_script_reset();
1147 }
1148 continue;
1149 }
10921150
10931151 if (!provides && regexecutor(&reg.prov, COMMON_ARGS) == true) {
10941152 if (val->rm_so < val->rm_eo) {
11041162 } else
11051163 required_start = empty;
11061164 }
1107 #ifndef SUSE
1165 #ifdef USE_STOP_TAGS
11081166 if (!required_stop && regexecutor(&reg.req_stop, COMMON_ARGS) == true) {
11091167 if (val->rm_so < val->rm_eo) {
11101168 *(pbuf+val->rm_eo) = '\0';
11121170 } else
11131171 required_stop = empty;
11141172 }
1115 #endif /* not SUSE */
1173 #endif /* USE_STOP_TAGS */
11161174 if (!should_start && regexecutor(&reg.shl_start, COMMON_SHD_ARGS) == true) {
11171175 if (shl->rm_so < shl->rm_eo) {
11181176 *(pbuf+shl->rm_eo) = '\0';
11201178 } else
11211179 should_start = empty;
11221180 }
1123 #ifndef SUSE
1181 #ifdef USE_STOP_TAGS
11241182 if (!should_stop && regexecutor(&reg.shl_stop, COMMON_SHD_ARGS) == true) {
11251183 if (shl->rm_so < shl->rm_eo) {
11261184 *(pbuf+shl->rm_eo) = '\0';
11281186 } else
11291187 should_stop = empty;
11301188 }
1131 #endif /* not SUSE */
1189 #endif /* USE_STOP_TAGS */
11321190 if (!start_before && regexecutor(&reg.start_bf, COMMON_SHD_ARGS) == true) {
11331191 if (shl->rm_so < shl->rm_eo) {
11341192 *(pbuf+shl->rm_eo) = '\0';
11361194 } else
11371195 start_before = empty;
11381196 }
1139 #ifndef SUSE
1197 #ifdef USE_STOP_TAGS
11401198 if (!stop_after && regexecutor(&reg.stop_af, COMMON_SHD_ARGS) == true) {
11411199 if (shl->rm_so < shl->rm_eo) {
11421200 *(pbuf+shl->rm_eo) = '\0';
11441202 } else
11451203 stop_after = empty;
11461204 }
1147 #endif /* not SUSE */
1205 #endif /* USE_STOP_TAGS */
11481206 if (!default_start && regexecutor(&reg.def_start, COMMON_ARGS) == true) {
11491207 if (val->rm_so < val->rm_eo) {
11501208 *(pbuf+val->rm_eo) = '\0';
11521210 } else
11531211 default_start = empty;
11541212 }
1155 #ifndef SUSE
1213 #ifdef USE_STOP_TAGS
11561214 if (!default_stop && regexecutor(&reg.def_stop, COMMON_ARGS) == true) {
11571215 if (val->rm_so < val->rm_eo) {
11581216 *(pbuf+val->rm_eo) = '\0';
11601218 } else
11611219 default_stop = empty;
11621220 }
1163 #endif /* not SUSE */
1221 #endif /* USE_STOP_TAGS */
11641222 if (!description && regexecutor(&reg.desc, COMMON_ARGS) == true) {
11651223 if (val->rm_so < val->rm_eo) {
11661224 *(pbuf+val->rm_eo) = '\0';
11771235 #undef COMMON_SHD_ARGS
11781236
11791237 fclose(script);
1180 ret = begin && end;
1238 if (begin && end)
1239 ret |= FOUND_LSB_HEADER;
11811240
11821241 if (begin && !end) {
11831242 char *name = basename(path);
11871246 error("exiting now!\n");
11881247 }
11891248
1190 #ifdef SUSE
1249 #ifndef USE_STOP_TAGS
11911250 if (verbose && (begin && end && (!provides || !required_start)))
1192 #else
1251 #else /* USE_STOP_TAGS */
11931252 if (verbose && (begin && end && (!provides || !required_start || !required_stop)))
1194 #endif
1253 #endif /* USE_STOP_TAGS */
11951254 {
11961255 char *name = basename(path);
11971256 if (*name == 'S' || *name == 'K')
11981257 name += 3;
11991258 warn("script %s could be broken: incomplete LSB comment.\n", name);
12001259 if (!provides)
1201 warn("Missing entry for Provides: please add even if empty.\n", name);
1260 warn("Missing entry for Provides: please add even if empty.\n");
12021261 if (!required_start)
1203 warn("Missing entry for Required-Start: please add even if empty.\n", name);
1204 #ifndef SUSE
1262 warn("Missing entry for Required-Start: please add even if empty.\n");
1263 #ifdef USE_STOP_TAGS
12051264 if (!required_stop)
1206 warn("Missing entry for Required-Stop: please add even if empty.\n", name);
1207 #endif
1265 warn("Missing entry for Required-Stop: please add even if empty.\n");
1266 #endif /* USE_STOP_TAGS */
12081267 }
12091268
12101269 #undef provides
12171276 #undef default_start
12181277 #undef default_stop
12191278 #undef description
1220
12211279 return ret;
12221280 }
12231281
1282 /*
1283 * Follow symlinks, return the basename of the file pointed to by
1284 * symlinks or the basename of the current path if no symlink.
1285 */
1286 static char *scriptname(const char *__restrict path) __attribute__((nonnull(1)));
1287 static char *scriptname(const char * path)
1288 {
1289 uint deep = 0;
1290 char linkbuf[PATH_MAX+1];
1291 char *script = xstrdup(path);
1292
1293 strncpy(linkbuf, script, sizeof(linkbuf)-1);
1294 linkbuf[PATH_MAX] = '\0';
1295
1296 do {
1297 struct stat st;
1298 int linklen;
1299
1300 if (deep++ > MAXSYMLINKS) {
1301 errno = ELOOP;
1302 warn("Can not determine script name for %s: %s\n", path, strerror(errno));
1303 break;
1304 }
1305
1306 if (lstat(script, &st) < 0) {
1307 warn("Can not stat %s: %s\n", script, strerror(errno));
1308 break;
1309 }
1310
1311 if (!S_ISLNK(st.st_mode))
1312 break;
1313
1314 if ((linklen = readlink(script, linkbuf, sizeof(linkbuf)-1)) < 0)
1315 break;
1316 linkbuf[linklen] = '\0';
1317
1318 if (linkbuf[0] != '/') { /* restore relative links */
1319 const char *lastslash;
1320
1321 if ((lastslash = strrchr(script, '/'))) {
1322 size_t dirname_len = lastslash - script + 1;
1323
1324 if (dirname_len + linklen > PATH_MAX)
1325 linklen = PATH_MAX - dirname_len;
1326
1327 memmove(&linkbuf[dirname_len], &linkbuf[0], linklen + 1);
1328 memcpy(&linkbuf[0], script, dirname_len);
1329 }
1330 }
1331
1332 free(script);
1333 script = xstrdup(linkbuf);
1334
1335 } while (1);
1336
1337 free(script);
1338 script = xstrdup(basename(linkbuf));
1339
1340 return script;
1341 }
1342
1343 static uchar load_overrides(const char *const __restrict dir, const char *const __restrict name) __attribute__((nonnull(1,2)));
1344 static uchar load_overrides(const char *const dir, const char *const name)
1345 {
1346 uchar ret = 0;
1347 char fullpath[PATH_MAX+1];
1348 struct stat statbuf;
1349 int n;
1350
1351 n = snprintf(&fullpath[0], sizeof(fullpath), "%s%s/%s", (root && !set_override) ? root : "", dir, name);
1352 if (n >= sizeof(fullpath) || n < 0)
1353 error("snprintf(): %s\n", strerror(errno));
1354
1355 if (stat(fullpath, &statbuf) == 0 && S_ISREG(statbuf.st_mode))
1356 ret = scan_lsb_headers(fullpath);
1357 if (ret)
1358 ret |= FOUND_LSB_OVERRIDE;
1359 return ret;
1360 }
1361
1362 static uchar scan_script_defaults(const char *const __restrict path, const char *const __restrict override_path) __attribute__((nonnull(1,2)));
1363 static uchar scan_script_defaults(const char *const path, const char *const override_path)
1364 {
1365 uchar ret = 0;
1366 char *name = scriptname(path);
1367
1368 if (!name)
1369 return ret;
1370
1371 /* Reset old results */
1372 scan_script_reset();
1373
1374 #ifdef SUSE
1375 /* Common script ... */
1376 if (!strcmp(name, "halt")) {
1377 ret |= (FOUND_LSB_HEADER|FOUND_LSB_DEFAULT);
1378 goto out;
1379 }
1380
1381 /* ... and its link */
1382 if (!strcmp(name, "reboot")) {
1383 ret |= (FOUND_LSB_HEADER|FOUND_LSB_DEFAULT);
1384 goto out;
1385 }
1386
1387 /* Common script for single mode */
1388 if (!strcmp(name, "single")) {
1389 ret |= (FOUND_LSB_HEADER|FOUND_LSB_DEFAULT);
1390 goto out;
1391 }
1392 #endif /* SUSE */
1393
1394 /* Replace with headers from the script itself */
1395 ret |= scan_lsb_headers(path);
1396
1397 if (!ret) /* Load values if the override file exist */
1398 ret |= load_overrides("/usr/share/insserv/overrides", name);
1399 else
1400 ret |= FOUND_LSB_DEFAULT;
1401
1402 /*
1403 * Allow host-specific overrides to replace the content in the
1404 * init.d scripts
1405 */
1406 ret |= load_overrides(override_path, name);
1407 #ifdef SUSE
1408 out:
1409 #endif /* SUSE */
1410 free(name);
1411 return ret;
1412 }
1413
1414 static inline void scan_script_regfree() __attribute__((always_inline));
12241415 static inline void scan_script_regfree()
12251416 {
12261417 regfree(&reg.prov);
12391430 char *location;
12401431 const int lvl;
12411432 const int seek;
1433 const char key;
12421434 } runlevel_locations[] = {
12431435 #ifdef SUSE /* SuSE's SystemV link scheme */
1244 {"rc0.d/", LVL_HALT, LVL_NORM},
1245 {"rc1.d/", LVL_ONE, LVL_NORM}, /* runlevel 1 switch over to single user mode */
1246 {"rc2.d/", LVL_TWO, LVL_NORM},
1247 {"rc3.d/", LVL_THREE, LVL_NORM},
1248 {"rc4.d/", LVL_FOUR, LVL_NORM},
1249 {"rc5.d/", LVL_FIVE, LVL_NORM},
1250 {"rc6.d/", LVL_REBOOT, LVL_NORM},
1251 {"rcS.d/", LVL_SINGLE, LVL_NORM}, /* runlevel S is for single user mode */
1252 {"boot.d/", LVL_BOOT, LVL_BOOT}, /* runlevel B is for system initialization */
1436 {"rc0.d/", LVL_HALT, LVL_NORM, '0'},
1437 {"rc1.d/", LVL_ONE, LVL_NORM, '1'}, /* runlevel 1 switch over to single user mode */
1438 {"rc2.d/", LVL_TWO, LVL_NORM, '2'},
1439 {"rc3.d/", LVL_THREE, LVL_NORM, '3'},
1440 {"rc4.d/", LVL_FOUR, LVL_NORM, '4'},
1441 {"rc5.d/", LVL_FIVE, LVL_NORM, '5'},
1442 {"rc6.d/", LVL_REBOOT, LVL_NORM, '6'},
1443 {"rcS.d/", LVL_SINGLE, LVL_NORM, 'S'}, /* runlevel S is for single user mode */
1444 {"boot.d/", LVL_BOOT, LVL_BOOT, 'B'}, /* runlevel B is for system initialization */
12531445 #else /* not SUSE (actually, Debian) */
1254 {"../rc0.d/", LVL_HALT, LVL_NORM},
1255 {"../rc1.d/", LVL_ONE, LVL_NORM}, /* runlevel 1 switch over to single user mode */
1256 {"../rc2.d/", LVL_TWO, LVL_NORM},
1257 {"../rc3.d/", LVL_THREE, LVL_NORM},
1258 {"../rc4.d/", LVL_FOUR, LVL_NORM},
1259 {"../rc5.d/", LVL_FIVE, LVL_NORM},
1260 {"../rc6.d/", LVL_REBOOT, LVL_NORM},
1261 {"../rcS.d/", LVL_BOOT, LVL_BOOT}, /* runlevel S is for system initialization */
1446 {"../rc0.d/", LVL_HALT, LVL_NORM, '0'},
1447 {"../rc1.d/", LVL_ONE, LVL_NORM, '1'}, /* runlevel 1 switch over to single user mode */
1448 {"../rc2.d/", LVL_TWO, LVL_NORM, '2'},
1449 {"../rc3.d/", LVL_THREE, LVL_NORM, '3'},
1450 {"../rc4.d/", LVL_FOUR, LVL_NORM, '4'},
1451 {"../rc5.d/", LVL_FIVE, LVL_NORM, '5'},
1452 {"../rc6.d/", LVL_REBOOT, LVL_NORM, '6'},
1453 {"../rcS.d/", LVL_BOOT, LVL_BOOT, 'S'}, /* runlevel S is for system initialization */
12621454 /* On e.g. Debian there exist no boot.d */
12631455 #endif /* not SUSE */
12641456 };
12651457
12661458 #define RUNLEVLES (sizeof(runlevel_locations)/sizeof(runlevel_locations[0]))
12671459
1460 int map_has_runlevels(void)
1461 {
1462 return RUNLEVLES;
1463 }
1464
1465 char map_runlevel_to_key(const int runlevel)
1466 {
1467 if (runlevel >= RUNLEVLES) {
1468 warn("Wrong runlevel %d\n", runlevel);
1469 }
1470 return runlevel_locations[runlevel].key;
1471 }
1472
1473 int map_key_to_lvl(const char key)
1474 {
1475 int runlevel;
1476 const char uckey = toupper(key);
1477 for (runlevel = 0; runlevel < RUNLEVLES; runlevel++) {
1478 if (uckey == runlevel_locations[runlevel].key)
1479 return runlevel_locations[runlevel].lvl;
1480 }
1481 warn("Wrong runlevel key '%c'\n", uckey);
1482 return 0;
1483 }
1484
12681485 static const char *map_runlevel_to_location(const int runlevel)
12691486 {
1487 if (runlevel >= RUNLEVLES) {
1488 warn("Wrong runlevel %d\n", runlevel);
1489 }
12701490 return runlevel_locations[runlevel].location;
12711491 }
12721492
1493 int map_runlevel_to_lvl(const int runlevel)
1494 {
1495 if (runlevel >= RUNLEVLES) {
1496 warn("Wrong runlevel %d\n", runlevel);
1497 }
1498 return runlevel_locations[runlevel].lvl;
1499 }
1500
12731501 #ifndef SUSE
1274 static const int map_runlevel_to_lvl(const int runlevel)
1275 {
1276 return runlevel_locations[runlevel].lvl;
1277 }
1278
1279 static const int map_runlevel_to_seek(const int runlevel)
1502 static int map_runlevel_to_seek(const int runlevel)
12801503 {
12811504 return runlevel_locations[runlevel].seek;
12821505 }
12851508 /*
12861509 * Scan current service structure
12871510 */
1288 static void scan_script_locations(const char *const path, char ** const iargv, const int icnt)
1511 static void scan_script_locations(const char *const __restrict path,
1512 const char *const __restrict override_path, char ** const __restrict iargv, const int icnt) __attribute__((nonnull(1,2)));
1513 static void scan_script_locations(const char *const path, const char *const override_path, char ** const iargv, const int icnt)
12891514 {
12901515 int runlevel;
12911516
13051530 while ((d = readdir(rcdir)) != (struct dirent*)0) {
13061531 char * ptr = d->d_name;
13071532 char order = 0;
1533 char type;
13081534 char* begin = (char*)0; /* Remember address of ptr handled by strsep() */
1309 boolean lsb;
1310
1311 #ifdef SUSE
1535 uchar lsb = 0;
1536
1537 #ifndef USE_STOP_TAGS
13121538 if (*ptr != 'S')
1313 #else
1539 #else /* USE_STOP_TAGS */
13141540 if (*ptr != 'S' && *ptr != 'K')
1315 #endif
1541 #endif /* USE_STOP_TAGS */
13161542 continue;
1543 type = *ptr;
13171544 ptr++;
13181545
13191546 if (strspn(ptr, "0123456789") < 2)
13211548 order = atoi(ptr);
13221549 ptr += 2;
13231550
1324 if (iargv && chkfor(ptr, iargv, icnt))
1325 continue; /* ignore scripts if removed later */
1326
13271551 if (stat(d->d_name, &st_script) < 0) {
13281552 xremove(d->d_name); /* dangling sym link */
13291553 continue;
13301554 }
1331
1332 lsb = scan_script_defaults(d->d_name);
1555 #ifdef SUSE
1556 /*
1557 * Ignore scripts if removed later to avoid not used depencies
1558 * in the makefiles depend.boot, .depend.start and .depend.stop
1559 */
1560 if (iargv && chkfor(ptr, iargv, icnt))
1561 continue;
1562 #endif /* SUSE */
1563 lsb = scan_script_defaults(d->d_name, override_path);
1564
13331565 if (!script_inf.provides || script_inf.provides == empty)
13341566 script_inf.provides = xstrdup(ptr);
1567 #ifndef SUSE
1568 if (!lsb) {
1569 script_inf.required_start = xstrdup(DEFAULT_DEPENDENCY);
1570 script_inf.required_stop = xstrdup(DEFAULT_DEPENDENCY);
1571 script_inf.default_start = xstrdup(DEFAULT_START_LVL);
1572 script_inf.default_stop = xstrdup(DEFAULT_STOP_LVL);
1573 }
1574 #endif /* not SUSE */
13351575
13361576 begin = script_inf.provides;
1337 while ((token = strsep(&script_inf.provides, delimeter)) && *token) {
1577 while ((token = strsep(&begin, delimeter)) && *token) {
13381578 serv_t * service = (serv_t*)0;
13391579 if (*token == '$') {
13401580 warn("script %s provides system facility %s, skipped!\n", d->d_name, token);
13411581 continue;
13421582 }
1343 service = current_structure(token, order, runlevel);
1583 service = current_structure(token, order, runlevel, type);
13441584
13451585 if (service->opts & SERV_KNOWN)
13461586 continue;
13481588
13491589 if (!lsb)
13501590 service->opts |= SERV_NOTLSB;
1591
1592 if ((lsb & FOUND_LSB_HEADER) == 0) {
1593 if ((lsb & (FOUND_LSB_DEFAULT | FOUND_LSB_OVERRIDE)) == 0)
1594 warn("warning: script '%s' missing LSB tags and overrides\n", d->d_name);
1595 else
1596 warn("warning: script '%s' missing LSB tags\n", d->d_name);
1597 }
1598
13511599 if (script_inf.required_start && script_inf.required_start != empty) {
13521600 rememberreq(service, REQ_MUST, script_inf.required_start);
1353 requiresv(token, script_inf.required_start);
13541601 }
13551602 if (script_inf.should_start && script_inf.should_start != empty) {
13561603 rememberreq(service, REQ_SHLD, script_inf.should_start);
1357 requiresv(token, script_inf.should_start);
13581604 }
13591605 if (script_inf.start_before && script_inf.start_before != empty) {
1360 reversereq(service, token, script_inf.start_before);
1606 reversereq(service, REQ_SHLD, script_inf.start_before);
13611607 }
1362 #ifndef SUSE
1608 #ifdef USE_STOP_TAGS
13631609 /*
13641610 * required_stop and should_stop arn't used in SuSE Linux.
13651611 * Note: Sorting is done symetrical in stop and start!
13671613 */
13681614 if (script_inf.required_stop && script_inf.required_stop != empty) {
13691615 rememberreq(service, REQ_MUST, script_inf.required_stop);
1370 requiresv(token, script_inf.required_stop);
13711616 }
13721617 if (script_inf.should_stop && script_inf.should_stop != empty) {
13731618 rememberreq(service, REQ_SHLD, script_inf.should_stop);
1374 requiresv(token, script_inf.should_stop);
13751619 }
13761620 if (script_inf.stop_after && script_inf.stop_after != empty) {
1377 reversereq(service, token, script_inf.stop_after);
1621 reversereq(service, REQ_SHLD, script_inf.stop_after);
13781622 }
1379 #endif /* not SUSE */
1380 }
1381 script_inf.provides = begin;
1382
1383 xreset(script_inf.provides);
1384 xreset(script_inf.required_start);
1385 xreset(script_inf.required_stop);
1386 xreset(script_inf.should_start);
1387 xreset(script_inf.should_stop);
1388 xreset(script_inf.start_before);
1389 xreset(script_inf.stop_after);
1390 xreset(script_inf.default_start);
1391 xreset(script_inf.default_stop);
1392 xreset(script_inf.description);
1623 #endif /* USE_STOP_TAGS */
1624 }
1625
1626 scan_script_reset();
13931627 }
13941628 popd();
13951629 closedir(rcdir);
13981632 return;
13991633 }
14001634
1635 #if defined(FACI_EXPANSION) && (FACI_EXPANSION > 0)
1636 /*
1637 * Expand the system facilities after all insserv.conf files have been scanned.
1638 */
1639 static char * facisep(char **__restrict repl, int *__restrict deep) __attribute__((noinline,nonnull(1,2)));
1640 static char * facisep(char ** repl, int * deep)
1641 {
1642 char * token = (char*)0, * exp = *repl;
1643
1644 if (exp == (char*)0)
1645 goto out;
1646
1647 if (*deep > 10) {
1648 warn("The nested level of the system facilities in the insserv.conf file(s) is to large\n");
1649 goto next;
1650 }
1651
1652 if (*exp == '$') {
1653 static char * more, * start;
1654 if (more == (char*)0) {
1655 const char * end;
1656 list_t * ptr;
1657 size_t len;
1658
1659 if ((end = strpbrk(exp, delimeter)))
1660 len = end - exp;
1661 else
1662 len = strlen(exp);
1663
1664 list_for_each(ptr, sysfaci_start) {
1665 if (!strncmp(getfaci(ptr)->name, exp, len)) {
1666 more = xstrdup(getfaci(ptr)->repl);
1667 break;
1668 }
1669 }
1670
1671 if (more)
1672 start = more;
1673 else {
1674 (void)strsep(repl, delimeter);
1675 goto next;
1676 }
1677 }
1678 (*deep)++;
1679 token = facisep(&more, deep);
1680 (*deep)--;
1681 if (!more)
1682 (void)strsep(repl, delimeter);
1683 if (token)
1684 goto out;
1685 free(start);
1686 more = (char*)0;
1687 }
1688 next:
1689 token = strsep(repl, delimeter);
1690 out:
1691 return token;
1692 }
1693 #endif /* FACI_EXPANSION */
1694
14011695 /*
14021696 * The /etc/insserv.conf scanning engine.
14031697 */
1404 static void scan_conf_file(const char* file)
1405 {
1406 regex_t reg_conf, reg_conf2;
1698 static void scan_conf_file(const char *__restrict file) __attribute__((nonnull(1)));;
1699 static void scan_conf_file(const char * file)
1700 {
14071701 regmatch_t subloc[SUBCONFNUM], *val = (regmatch_t*)0;
14081702 FILE *conf;
1409 char *pbuf = buf;
1410
1411 regcompiler(&reg_conf, CONFLINE, REG_EXTENDED|REG_ICASE);
1412 regcompiler(&reg_conf2, CONFLINE2, REG_EXTENDED|REG_ICASE);
14131703
14141704 info("Loading %s\n", file);
14151705
14271717 } while (1);
14281718
14291719 while (fgets(buf, sizeof(buf), conf)) {
1720 char *pbuf = &buf[0];
14301721 if (*pbuf == '#')
14311722 continue;
1432 if (regexecutor(&reg_conf, buf, SUBCONFNUM, subloc, 0) == true) {
1723 if (*pbuf == '\n')
1724 continue;
1725 if (regexecutor(&creg.isysfaci, buf, SUBCONFNUM, subloc, 0) == true) {
14331726 char * virt = (char*)0, * real = (char*)0;
14341727 val = &subloc[SUBCONF - 1];
14351728 if (val->rm_so < val->rm_eo) {
14471740 list_for_each(ptr, sysfaci_start) {
14481741 if (!strcmp(getfaci(ptr)->name, virt)) {
14491742 found = true;
1450 if(real)
1451 {
1743 if(real) {
14521744 char* repl = getfaci(ptr)->repl;
14531745 repl = realloc(repl, strlen(repl)+strlen(real)+2);
14541746 strcat(repl, " ");
14681760 }
14691761 }
14701762 }
1471 if (regexecutor(&reg_conf2, buf, SUBCONFNUM, subloc, 0) == true) {
1763 if (regexecutor(&creg.isactive, buf, SUBCONFNUM, subloc, 0) == true) {
14721764 char * key = (char*)0, * servs = (char*)0;
14731765 val = &subloc[SUBCONF - 1];
14741766 if (val->rm_so < val->rm_eo) {
14911783 }
14921784 }
14931785 }
1494 regfree(&reg_conf);
1495 regfree(&reg_conf2);
1786
14961787 fclose(conf);
14971788 return;
14981789 err:
14991790 warn("fopen(%s): %s\n", file, strerror(errno));
15001791 }
15011792
1502 static int cfgfile_filter(const struct dirent* d)
1503 {
1793 static int cfgfile_filter(const struct dirent *__restrict d) __attribute__((nonnull(1)));
1794 static int cfgfile_filter(const struct dirent * d)
1795 {
1796 const char* name = d->d_name;
15041797 const char* end;
1505 if ((end = strrchr(d->d_name, '.'))) {
1798
1799 if (!name || (*name == '\0'))
1800 return 0;
1801 if ((*name == '.') && ((*(name+1) == '\0') || (*(name+1) == '.')))
1802 return 0;
1803 else {
1804 struct stat st;
1805 if ((stat(name,&st) < 0) || !S_ISREG(st.st_mode))
1806 return 0;
1807 }
1808 if ((end = strrchr(name, '.'))) {
15061809 end++;
1507 if (!strcmp(end, "local") ||
1508 !strncmp(end, "rpm", 3) || /* .rpmorig, .rpmnew, .rmpsave, ... */
1810 if (!strncmp(end, "rpm", 3) || /* .rpmorig, .rpmnew, .rmpsave, ... */
15091811 !strncmp(end, "ba", 2) || /* .bak, .backup, ... */
1812 #ifdef SUSE
1813 !strcmp(end, "local") || /* .local are sourced by the basename */
1814 #endif /* not SUSE */
15101815 !strcmp(end, "old") ||
15111816 !strcmp(end, "new") ||
15121817 !strcmp(end, "org") ||
15191824 return 0;
15201825 }
15211826 }
1522 if ((end = strrchr(d->d_name, ','))) {
1827 if ((end = strrchr(name, ','))) {
15231828 end++;
15241829 if (!strcmp(end, "v")) /* rcs-files */
1525 {
15261830 return 0;
1527 }
15281831 }
15291832 return 1;
15301833 }
15311834
1532 static void scan_conf()
1835 static void scan_conf(const char *__restrict file) __attribute__((nonnull(1)));;
1836 static void scan_conf(const char * file)
15331837 {
15341838 struct dirent** namelist = (struct dirent**)0;
15351839 char path[PATH_MAX+1];
1840 #if defined(FACI_EXPANSION) && (FACI_EXPANSION > 0)
1841 list_t * ptr;
1842 #endif /* FACI_EXPANSION */
15361843 int n;
15371844
1538 n = snprintf(&path[0], sizeof(path), "%s%s", root ? root : "", INSCONF);
1845 regcompiler(&creg.isysfaci, CONFLINE, REG_EXTENDED|REG_ICASE);
1846 regcompiler(&creg.isactive, CONFLINE2, REG_EXTENDED|REG_ICASE);
1847
1848 n = snprintf(&path[0], sizeof(path), "%s%s", (root && !set_insconf) ? root : "", file);
15391849 if (n >= sizeof(path) || n < 0)
15401850 error("snprintf(): %s\n", strerror(errno));
15411851
15421852 scan_conf_file(path);
15431853
1544 n = snprintf(&path[0], sizeof(path), "%s%s.d", root ? root : "", INSCONF);
1854 n = snprintf(&path[0], sizeof(path), "%s%s.d", (root && !set_insconf) ? root : "", file);
15451855 if (n >= sizeof(path) || n < 0)
15461856 error("snprintf(): %s\n", strerror(errno));
15471857
15481858 n = scandir(path, &namelist, cfgfile_filter, alphasort);
1549 if(n > 0)
1550 {
1551 while(n--)
1552 {
1553 char buf[PATH_MAX+1], * ptr = namelist[n]->d_name;
1859 if(n > 0) {
1860 while(n--) {
1861 char buf[PATH_MAX+1];
15541862 int r;
15551863
1556 if ((*ptr == '.') && ((*(ptr+1) == '\0') || (*(ptr+1) == '.'))) {
1557 free(namelist[n]);
1558 continue;
1559 }
1560
1561 r = snprintf(buf, sizeof(buf), "%s/%s", path, namelist[n]->d_name);
1864 r = snprintf(&buf[0], sizeof(buf), "%s/%s", path, namelist[n]->d_name);
15621865 if (r >= sizeof(buf) || r < 0)
15631866 error("snprintf(): %s\n", strerror(errno));
15641867
15671870 free(namelist[n]);
15681871 }
15691872 }
1873
15701874 if (namelist)
15711875 free(namelist);
1572 }
1573
1574 /*
1575 * Expand the system facilitis after all scripts have been scanned.
1576 */
1577 static void expand_conf()
1876
1877 regfree(&creg.isysfaci);
1878 regfree(&creg.isactive);
1879 #if defined(FACI_EXPANSION) && (FACI_EXPANSION > 0)
1880 list_for_each(ptr, sysfaci_start) {
1881 int deep = 0;
1882 char * repl = getfaci(ptr)->repl;
1883 char * real, *list = (char*)0;
1884
1885 while ((real = facisep(&repl, &deep))) {
1886 if (!list) {
1887 list = xstrdup(real);
1888 } else {
1889 list = realloc(list, strlen(list)+2+strlen(real));
1890 strcat(list, " ");
1891 strcat(list, real);
1892 }
1893 }
1894
1895 if (list) {
1896 free(getfaci(ptr)->repl);
1897 getfaci(ptr)->repl = list;
1898 }
1899 }
1900 #endif /* FACI_EXPANSION */
1901 }
1902
1903 #if !defined(FACI_EXPANSION) || (FACI_EXPANSION == 0)
1904 static inline void expand_conf(void)
15781905 {
15791906 list_t * ptr;
15801907 list_for_each(ptr, sysfaci_start)
15811908 virtprov(getfaci(ptr)->name, getfaci(ptr)->repl);
15821909 }
1910 #endif /* not FACI_EXPANSION */
15831911
15841912 /*
15851913 * Scan for a Start or Kill script within a runlevel directory.
15861914 * We start were we leave the directory, the upper level
15871915 * has to call rewinddir(3) if necessary.
15881916 */
1589 static inline char * scan_for(DIR *const rcdir, const char *const script, char type)
1917 static inline char * scan_for(DIR *const __restrict rcdir, const char *const __restrict script, char type) __attribute__((always_inline,nonnull(1,2)));;
1918 static inline char * scan_for(DIR *const rcdir, const char *const script, char type)
15901919 {
15911920 struct dirent *d;
15921921 char * ret = (char*)0;
16131942 static struct option long_options[] =
16141943 {
16151944 {"verbose", 0, (int*)0, 'v'},
1945 {"config", 1, (int*)0, 'c'},
16161946 {"dryrun", 0, (int*)0, 'n'},
16171947 {"default", 0, (int*)0, 'd'},
16181948 {"remove", 0, (int*)0, 'r'},
16191949 {"force", 0, (int*)0, 'f'},
1950 {"path", 1, (int*)0, 'p'},
1951 {"override",1, (int*)0, 'o'},
16201952 {"help", 0, (int*)0, 'h'},
16211953 { 0, 0, (int*)0, 0 },
16221954 };
16231955
1956 static void help(const char *const __restrict name) __attribute__((nonnull(1)));
16241957 static void help(const char *const name)
16251958 {
16261959 printf("Usage: %s [<options>] [init_script|init_directory]\n", name);
16291962 printf(" -r, --remove Remove the listed scripts from all runlevels.\n");
16301963 printf(" -f, --force Ignore if a required service is missed.\n");
16311964 printf(" -v, --verbose Provide information on what is being done.\n");
1965 printf(" -p <path>, --path <path> Path to replace " INITDIR ".\n");
1966 printf(" -o <path>, --override <path> Path to replace " OVERRIDEDIR ".\n");
1967 printf(" -c <config>, --config <config> Path to config file.\n");
16321968 printf(" -n, --dryrun Do not change the system, only talk about it.\n");
16331969 printf(" -d, --default Use default runlevels a defined in the scripts\n");
16341970 }
16441980 struct stat st_script;
16451981 char * argr[argc];
16461982 char * path = INITDIR;
1983 char * override_path = OVERRIDEDIR;
1984 char * insconf = INSCONF;
16471985 int runlevel, c;
16481986 boolean del = false;
16491987 boolean defaults = false;
16541992 for (c = 0; c < argc; c++)
16551993 argr[c] = (char*)0;
16561994
1657 while ((c = getopt_long(argc, argv, "dfrhvn", long_options, (int *)0)) != -1) {
1995 while ((c = getopt_long(argc, argv, "c:dfrhvno:p:", long_options, (int *)0)) != -1) {
16581996 switch (c) {
1997 case 'c':
1998 insconf = optarg;
1999 set_insconf = true;
2000 break;
16592001 case 'd':
16602002 defaults = true;
16612003 break;
16722014 verbose = true;
16732015 dryrun = true;
16742016 break;
2017 case 'p':
2018 path = optarg;
2019 break;
2020 case 'o':
2021 override_path = optarg;
2022 set_override = true;
2023 break;
16752024 case '?':
16762025 error("For help use: %s -h\n", myname);
16772026 case 'h':
17752124 for (c = 0; c < argc; c++)
17762125 if (argr[c])
17772126 printf("Overwrite argument for %s is %s\n", argv[c], argr[c]);
1778 #endif
2127 #endif /* DEBUG */
17792128
17802129 /*
17812130 * Scan and set our configuration for virtual services.
17822131 */
1783 scan_conf();
2132 scan_conf(insconf);
17842133
17852134 /*
17862135 * Initialize the regular scanner for the scripts.
17942143 #if 0
17952144 if (!defaults)
17962145 #endif
1797 scan_script_locations(path, (del ? argv : (char**)0), argc);
2146 scan_script_locations(path, override_path, (del ? argv : (char**)0), argc);
17982147
17992148 if ((initdir = opendir(path)) == (DIR*)0)
18002149 error("can not opendir(%s): %s\n", path, strerror(errno));
18062155 serv_t * service = (serv_t*)0;
18072156 char * token;
18082157 char* begin = (char*)0; /* Remember address of ptr handled by strsep() */
1809 boolean lsb = false;
2158 uchar lsb = 0;
18102159 errno = 0;
18112160
18122161 /* d_type seems not to work, therefore use stat(2) */
18812230 }
18822231
18832232 /* main scanner for LSB comment in current script */
1884 lsb = scan_script_defaults(d->d_name);
1885
2233 lsb = scan_script_defaults(d->d_name, override_path);
2234
2235 if ((lsb & FOUND_LSB_HEADER) == 0) {
2236 if ((lsb & (FOUND_LSB_DEFAULT | FOUND_LSB_OVERRIDE)) == 0)
2237 warn("warning: script '%s' missing LSB tags and overrides\n", d->d_name);
2238 else
2239 warn("warning: script '%s' missing LSB tags\n", d->d_name);
2240 }
2241
2242 #ifdef SUSE
18862243 /* Common script ... */
18872244 if (!strcmp(d->d_name, "halt")) {
18882245 makeprov("halt", d->d_name);
19042261 serv_t *serv = addserv("single");
19052262 makeprov("single", d->d_name);
19062263 runlevels("single", "1 S");
1907 requiresv("single", "kbd");
19082264 serv->opts |= SERV_ALL;
19092265 rememberreq(serv, REQ_SHLD, "kbd");
19102266 continue;
19112267 }
2268 #endif /* SUSE */
2269
2270 #ifndef SUSE
2271 if (!lsb) {
2272 script_inf.required_start = xstrdup(DEFAULT_DEPENDENCY);
2273 script_inf.required_stop = xstrdup(DEFAULT_DEPENDENCY);
2274 script_inf.default_start = xstrdup(DEFAULT_START_LVL);
2275 script_inf.default_stop = xstrdup(DEFAULT_STOP_LVL);
2276 }
2277 #endif /* not SUSE */
19122278
19132279 /*
19142280 * Oops, no comment found, guess one
19802346 char * provides = xstrdup(script_inf.provides);
19812347
19822348 begin = provides;
1983 while ((token = strsep(&provides, delimeter)) && *token) {
2349 while ((token = strsep(&begin, delimeter)) && *token) {
19842350
19852351 if (*token == '$') {
19862352 warn("script %s provides system facility %s, skipped!\n", d->d_name, token);
20152381 boolean known = (service->opts & SERV_KNOWN);
20162382 service->opts |= SERV_KNOWN;
20172383
2018 if ((!provides || !*provides) && (count > 1)) { /* Last token */
2384 if ((!begin || !*begin) && (count > 1)) { /* Last token */
20192385 const char * script = getscript(service->name);
20202386
20212387 if (script) {
20392405 if (!known) {
20402406 if (script_inf.required_start && script_inf.required_start != empty) {
20412407 rememberreq(service, REQ_MUST, script_inf.required_start);
2042 requiresv(token, script_inf.required_start);
20432408 }
20442409 if (script_inf.should_start && script_inf.should_start != empty) {
20452410 rememberreq(service, REQ_SHLD, script_inf.should_start);
2046 requiresv(token, script_inf.should_start);
20472411 }
2048 #ifndef SUSE
2412 #ifdef USE_STOP_TAGS
20492413 /*
20502414 * required_stop and should_stop arn't used in SuSE Linux.
20512415 * Note: Sorting is done symetrical in stop and start!
20532417 */
20542418 if (script_inf.required_stop && script_inf.required_stop != empty) {
20552419 rememberreq(service, REQ_MUST, script_inf.required_stop);
2056 requiresv(token, script_inf.required_stop);
20572420 }
20582421 if (script_inf.should_stop && script_inf.should_stop != empty) {
20592422 rememberreq(service, REQ_SHLD, script_inf.should_stop);
2060 requiresv(token, script_inf.should_stop);
20612423 }
2062 #endif /* not SUSE */
2424 #endif /* USE_STOP_TAGS */
20632425 }
2426
20642427 if (script_inf.start_before && script_inf.start_before != empty) {
2065 reversereq(service, token, script_inf.start_before);
2428 reversereq(service, REQ_SHLD, script_inf.start_before);
20662429 }
2067 #ifndef SUSE
2430 #ifdef USE_STOP_TAGS
20682431 if (script_inf.stop_after && script_inf.stop_after != empty) {
2069 reversereq(service, token, script_inf.stop_after);
2432 reversereq(service, REQ_SHLD, script_inf.stop_after);
20702433 }
2071 #endif /* not SUSE */
2434 #endif /* USE_STOP_TAGS */
20722435 /*
20732436 * Use information from symbolic link structure to
20742437 * check if all services are around for this script.
20842447 }
20852448
20862449 if (script_inf.default_start && script_inf.default_start != empty) {
2087 unsigned int deflvls = str2lvl(script_inf.default_start);
2450 uint deflvls = str2lvl(script_inf.default_start);
20882451
20892452 /*
20902453 * Compare all bits, which means `==' and not `&' and overwrite
21172480 /*
21182481 * Ahh ... set default multiuser with network
21192482 */
2120 script_inf.default_start = xstrdup("3 5");
2483 script_inf.default_start = xstrdup(DEFAULT_START_LVL);
21212484 }
2122 #ifndef SUSE
2485 #ifdef USE_STOP_TAGS
21232486 /*
21242487 * default_stop arn't used in SuSE Linux.
21252488 */
21262489 if (script_inf.default_stop && script_inf.default_stop != empty) {
2127 unsigned int deflvlk = str2lvl(script_inf.default_stop);
2490 uint deflvlk = str2lvl(script_inf.default_stop);
21282491
21292492 /*
21302493 * Compare all bits, which means `==' and not `&' and overwrite
21572520 * Do _not_ set default stop levels
21582521 */
21592522 }
2160 #endif /* not SUSE */
2523 #endif /* USE_STOP_TAGS */
21612524 }
21622525 }
2163 free(begin);
2164 }
2165
2166 #ifdef SUSE
2526 free(provides);
2527 }
2528
21672529 /* Ahh ... set default multiuser with network */
21682530 if (!script_inf.default_start || script_inf.default_start == empty)
2169 script_inf.default_start = xstrdup("3 5");
2170 #else /* not SUSE */
2171 if (!script_inf.default_start || script_inf.default_start == empty)
2172 script_inf.default_start = xstrdup("2 3 4 5"); /* for Debian*/
2531 script_inf.default_start = xstrdup(DEFAULT_START_LVL);
2532 #ifdef USE_STOP_TAGS
21732533 if (!script_inf.default_stop || script_inf.default_start == empty)
2174 script_inf.default_stop = xstrdup("S 0 1 6"); /* for Debian*/
2175 #endif /* not SUSE */
2534 script_inf.default_stop = xstrdup(DEFAULT_STOP_LVL);
2535 #endif /* USE_STOP_TAGS */
21762536
21772537 if (chkfor(d->d_name, argv, argc) && !defaults) {
21782538 if (argr[curr_argc]) {
22162576 runlevels(token, lvl2str(service->lvls));
22172577 else
22182578 runlevels(token, script_inf.default_start);
2219 #ifndef SUSE
2579 #ifdef USE_STOP_TAGS
22202580 /*
22212581 * default_stop arn't used in SuSE Linux.
22222582 */
22232583 if (script_inf.default_stop && script_inf.default_stop != empty) {
22242584 if (service && !del)
2585 {
22252586 service->lvlk = str2lvl(script_inf.default_stop);
2226 }
2227 #endif /* not SUSE */
2587 runlevels(token, script_inf.default_stop);
2588 }
2589 }
2590 #endif /* USE_STOP_TAGS */
22282591 }
22292592 script_inf.provides = begin;
22302593
22332596 service->opts |= SERV_NOTLSB;
22342597 }
22352598 /* Reset remaining pointers */
2236 xreset(script_inf.provides);
2237 xreset(script_inf.required_start);
2238 xreset(script_inf.required_stop);
2239 xreset(script_inf.should_start);
2240 xreset(script_inf.should_stop);
2241 xreset(script_inf.start_before);
2242 xreset(script_inf.stop_after);
2243 xreset(script_inf.default_start);
2244 xreset(script_inf.default_stop);
2245 xreset(script_inf.description);
2599 scan_script_reset();
22462600
22472601 /*
22482602 * Free the regular scanner for the scripts.
22532607 popd();
22542608 closedir(initdir);
22552609
2610 #if !defined(FACI_EXPANSION) || (FACI_EXPANSION == 0)
22562611 expand_conf();
2257
2612 #endif /* not FACI_EXPANSION */
2613
2614 #ifdef SUSE
22582615 /*
22592616 * Set initial order of some services
22602617 */
2261 setorder("network", 5, false); setlsb("network");
2262 setorder("inetd", 20, false); setlsb("inetd");
2263 setorder("halt", 20, false); setlsb("halt");
2264 setorder("reboot", 20, false); setlsb("reboot");
2265 setorder("single", 20, false); setlsb("single");
2266 setorder("serial", 10, false); setlsb("serial");
2267 setorder("gpm", 20, false); setlsb("gpm");
2268 setorder("boot.setup", 20, false);
2618 setorder("network", 5, false); setlsb("network");
2619 setorder("inetd", 20, false); setlsb("inetd");
2620 setorder("halt", 20, false); setlsb("halt");
2621 setorder("reboot", 20, false); setlsb("reboot");
2622 setorder("single", 20, false); setlsb("single");
2623 setorder("serial", 10, false); setlsb("serial");
2624 setorder("gpm", 20, false); setlsb("gpm");
2625 setorder("boot.setup", 20, false);
2626 #elif 0 /* not SUSE, but currently disabled */
2627 /*
2628 * Debian scripts with well known sequence numbers. Not sure if
2629 * we want to fix all of these.
2630 */
2631 setorder("checkroot.sh", 10, false); setlsb("checkroot.sh");
2632 setorder("checkfs.sh", 30, false); setlsb("checkfs.sh");
2633 setorder("networking", 40, false); setlsb("networking.sh");
2634 setorder("mountnfs.sh", 45, false); setlsb("mountnfs.sh");
2635 setorder("single", 90, false); setlsb("single");
2636 #endif /* not SUSE */
22692637
22702638 /*
22712639 * Set virtual dependencies for already enabled none LSB scripts.
22762644 * Now generate for all scripts the dependencies
22772645 */
22782646 follow_all();
2647
2648 if (is_loop_detected() && !ignore)
2649 error("exiting now!\n");
22792650
22802651 /*
22812652 * Re-order some well known scripts to get
24502821 popd();
24512822 closedir(rcdir);
24522823 }
2453 # else /* !SUSE, standard SystemV link scheme */
2824 # else /* not SUSE but Debian SystemV link scheme */
24542825 /*
24552826 * Remark: At SuSE we use boot scripts for system initialization which
24562827 * will be executed by /etc/init.d/boot (which is equal to rc.sysinit).
25102881 }
25112882
25122883 while (listscripts(&script, seek)) {
2513 const boolean stop = notincluded(script, runlevel);
2884 serv_t *serv = findserv(getprovides(script));
2885 const boolean stop = (notincluded(script, runlevel) || (serv->lvlk & lvl));
25142886 const boolean this = chkfor(script, argv, argc);
25152887 const char mode = (stop ? 'K' : 'S');
2516 serv_t *serv = findserv(getprovides(script));
25172888 int order = getorder(script);
25182889 boolean found;
25192890 char * clink;
25302901 # ifdef USE_KILL_IN_SINGLE
25312902 if (runlevel == 7) /* No kill links in rcS.d */
25322903 continue;
2533 # endif
2904 # endif /* USE_KILL_IN_SINGLE */
25342905 if ((serv->lvlk & lvl) == 0) /* No default_stop provided */
25352906 continue;
25362907 order = (maxorder + 1) - order;
25372908 }
2909
2910 if ((serv->lvls & lvl) == 0 && (serv->lvlk & lvl) == 0)
2911 continue; /* We aren't suppose to be on this runlevel */
25382912
25392913 sprintf(olink, "../init.d/%s", script);
25402914 sprintf(nlink, "%c%.2d%s", mode, order, script);
00 /*
11 * listing.c
22 *
3 * Copyright 2000-2003 Werner Fink, 2000 SuSE GmbH Nuernberg, Germany,
3 * Copyright 2000-2008 Werner Fink, 2000 SuSE GmbH Nuernberg, Germany,
44 * 2003 SuSE Linux AG, Germany.
5 * 2007-2008 SuSE Linux Products GmbH Nuernberg, Germany
56 *
67 * This source is free software; you can redistribute it and/or modify
78 * it under the terms of the GNU General Public License as published by
2122
2223 #define MAX_DEEP 99
2324
24 int maxorder = 0; /* Maximum order of runlevels 0 upto 6 and S */
25 int maxorder = 0; /* Maximum order of runlevels 0 upto 6 and S */
2526
2627 /* See listing.c for list_t and list_entry() macro */
2728 #define getdir(list) list_entry((list), struct dir_struct, d_list)
2829 #define getlink(list) list_entry((list), struct link_struct, l_list)
29 #define getlinkdir(list) (list_empty(list) ? NULL : getlink((list)->next)->target)
30 #define getnextlink(list) (list_empty(list) ? (dir_t*)0 : getlink((list)->next)->target)
3031
3132 /*
3233 * We handle services (aka scripts) as directories because
3334 * dependencies can be handels as symbolic links therein.
3435 * A provided service will be linked into a required service.
35 * For the general typ of linked list see listing.h.
36 * For the general type of linked lists see listing.h.
3637 */
3738
3839 typedef struct link_struct {
39 list_t l_list; /* The linked list to other symbolic links */
40 list_t l_list; /* The linked list of symbolic links */
4041 struct dir_struct * target;
41 } link_t; /* This is a "symbolic link" */
42 } __align link_t; /* This is a "symbolic link" */
4243
4344 typedef struct dir_struct {
44 list_t d_list; /* The linked list to other directories */
45 list_t link; /* symbolic links in this directory */
46 unsigned int flags;
47 char minord; /* Default order deep if any */
48 char order; /* Current order deep */
45 list_t d_list; /* The peg into linked list to other directories */
46 list_t s_link; /* The linked list of symbolic start links in this directory */
47 list_t k_link; /* The linked list of symbolic stop links in this directory */
48 ushort lvl;
49 ushort flags;
50 uchar minstart; /* Default start deep if any */
51 uchar start; /* Current start deep */
52 uchar minstop; /* Default stop deep if any */
53 uchar stop; /* Current stop deep */
4954 char * name;
5055 char * script;
51 unsigned int lvl;
52 } dir_t; /* This is a "directory" */
53
56 } __align dir_t; /* This is a "directory" */
57
58 /*
59 * The linked list off all directories, note that the d_list
60 * entry within the dir_struct is used as the peg pointer.
61 */
5462 static list_t dirs = { &(dirs), &(dirs) }, * d_start = &dirs;
5563
56 #define DIR_SCAN 0x00000001
57 #define DIR_LOOP 0x00000002
58 #define DIR_ISACTIVE 0x00000004
64 #define DIR_SCAN 0x0001
65 #define DIR_LOOP 0x0002
66 #define DIR_ISACTIVE 0x0004
67 #define DIR_LOOPREPORT 0x0008
68 #define DIR_MAXDEEP 0x0010
5969
6070 /*
6171 * Provide or find a service dir, set initial states and
6272 * link it into the maintaining if a new one.
6373 */
74 static dir_t * providedir(const char *__restrict name) __attribute__((nonnull(1)));
6475 static dir_t * providedir(const char * name)
6576 {
6677 dir_t * this;
6778 list_t * ptr;
6879
69 list_for_each(ptr, d_start)
80 list_for_each(ptr, d_start) {
7081 if (!strcmp(getdir(ptr)->name,name))
7182 goto out;
83 }
7284
7385 this = (dir_t *)malloc(sizeof(dir_t));
7486 if (this) {
75 list_t * l_start = &(this->link);
87 list_t * l_start = &(this->s_link);
88 list_t * l_stop = &(this->k_link);
89 insert(&(this->d_list), d_start->prev);
7690 l_start->next = l_start;
7791 l_start->prev = l_start;
78 insert(&(this->d_list), d_start->prev);
92 l_stop->next = l_stop;
93 l_stop->prev = l_stop;
7994 ptr = d_start->prev;
8095 this->name = xstrdup(name);
8196 this->script = NULL;
82 this->minord = 1;
83 this->order = 0;
97 this->minstart = 1;
98 this->minstop = MAX_DEEP;
99 this->start = 0;
100 this->stop = 0;
84101 this->flags = 0;
85102 this->lvl = 0;
86103 goto out;
94111 /*
95112 * Find a service dir by its script name.
96113 */
97 static dir_t * findscript(const char * script)
114 static inline dir_t * findscript(const char *__restrict script) __attribute__((always_inline,nonnull(1)));
115 static inline dir_t * findscript(const char * script)
98116 {
99117 dir_t * this = NULL;
100118 list_t * ptr;
122140 * Link the current service into the required service.
123141 * If the services do not exist, they will be created.
124142 */
143 static void ln_sf(const char *__restrict current, const char *__restrict required) __attribute__((nonnull(1,2)));
125144 static void ln_sf(const char * current, const char * required)
126145 {
127 dir_t * target = providedir(current);
128 dir_t * dir = providedir(required);
129 list_t * l_start = &(dir->link);
146 dir_t * cur = providedir(current);
147 dir_t * req = providedir(required);
148 list_t * l_list = &(req->s_link);
130149 list_t * dent;
131150 link_t * this;
132151
133 if (target == dir)
134 goto out;
135
136 list_for_each(dent, l_start) {
152 if (cur == req)
153 goto out;
154
155 list_for_each(dent, l_list) {
137156 dir_t * target = getlink(dent)->target;
138157 if (!strcmp(target->name, current))
139158 goto out;
141160
142161 this = (link_t *)malloc(sizeof(link_t));
143162 if (this) {
144 insert(&(this->l_list), l_start->prev);
145 this->target = target;
163 insert(&(this->l_list), l_list->prev);
164 this->target = cur;
146165 goto out;
147166 }
148167 error("%s", strerror(errno));
151170 }
152171
153172 /*
154 * Remember loops
155 */
173 * Remember loops to warn only once
174 */
175 static inline boolean remembernode (dir_t *__restrict dir) __attribute__((always_inline,nonnull(1)));
156176 static inline boolean remembernode (dir_t * dir)
157177 {
158 boolean ret = true;
178 register boolean ret = true;
159179
160180 if (dir->flags & DIR_LOOP)
161181 goto out;
193213 #define loop_check(a) \
194214 ((a) && (a)->flags & DIR_LOOP)
195215
196 static void __follow (dir_t * dir, dir_t * skip, const int level)
197 {
216 static void __follow (dir_t *__restrict dir, dir_t *__restrict skip, const int, const int) __attribute__((noinline,nonnull(1)));
217 static void __follow (dir_t * dir, dir_t * skip, const int level, const int reportloop)
218 {
219 list_t * l_list = &(dir->s_link);
220 uchar * minorder = &(dir->minstart);
198221 dir_t * tmp;
199 register int deep = level; /* Link depth, maybe we're called recursive */
200 register int loop;
201 static boolean warned = false;
222 register int deep = level; /* Link depth, maybe we're called recursively */
223 register int loop = 0; /* Count number of links in symbolic list */
202224
203225 if (dir->flags & DIR_SCAN) {
204226 if (skip) {
209231 if (!remembernode(dir))
210232 loop_warn_one(dir);
211233 }
212 return;
213 }
214
215 if (deep < dir->minord) /* Default order deep of this tree is higher */
216 deep = dir->minord;
234 goto out;
235 }
236
237 if (deep < *minorder) /* Default deep of this tree is higher */
238 deep = *minorder;
217239
218240 if (deep > MAX_DEEP) {
219 if (!warned)
220 warn("Max recursions depth %d reached\n", MAX_DEEP);
221 warned = true;
222 return;
223 }
224
225 for (loop = 0, tmp = dir; tmp; loop++, tmp = getlinkdir(&(tmp->link))) {
226 list_t *dent;
227 boolean recursion = true;
228
229 if (loop > MAX_DEEP) {
241 if ((dir->flags & DIR_MAXDEEP) == 0)
242 warn("Max recursions depth %d for %s reached\n", MAX_DEEP, dir->name);
243 dir->flags |= DIR_MAXDEEP;
244 goto out;
245 }
246
247 for (tmp = dir; tmp; tmp = getnextlink(l_list)) {
248 register boolean recursion = true;
249 uchar * order = &(tmp->start);
250 list_t * dent;
251
252 if (loop++ > MAX_DEEP) {
230253 if (skip) {
231254 if (!remembernode(skip) || !remembernode(tmp))
232255 loop_warn_two(tmp, skip);
234257 if (!remembernode(tmp))
235258 loop_warn_one(tmp);
236259 }
237 break; /* Loop detected, stop recursion */
238 }
260 break; /* Loop detected, stop recursion */
261 }
262 l_list = &(tmp->s_link); /* List of symbolic links for getnextlink() */
239263
240264 if (!(dir->lvl & tmp->lvl))
241 continue; /* Not same boot level */
265 continue; /* Not same boot level */
242266
243267 if (skip && skip == tmp) {
244268 if (!remembernode(skip) || !remembernode(tmp))
245269 loop_warn_one(skip);
246 break; /* Loop detected, stop recursion */
270 break; /* Loop detected, stop recursion */
247271 }
248272
249273 /*
250274 * As higher the link depth, as higher the start order.
251275 */
252 if (tmp->order > deep)
253 deep = tmp->order;
254 if (tmp->order < deep)
255 tmp->order = deep;
256
257 if (list_empty(&(tmp->link)))
258 break; /* No further service requires this one */
276 if (*order > deep)
277 deep = *order;
278 if (*order < deep)
279 *order = deep;
280
281 if (list_empty(l_list))
282 break; /* No further service requires this one */
259283
260284 /*
261285 * Do not count the dependcy deep of the system facilities
262286 * but follow them to count the replacing provides.
263287 */
264288 if ((*tmp->name != '$') && (++deep > MAX_DEEP)) {
265 if (!warned)
289 if ((tmp->flags & DIR_MAXDEEP) == 0)
266290 warn("Max recursions depth %d reached\n", MAX_DEEP);
267 warned = true;
291 tmp->flags |= DIR_MAXDEEP;
268292 break;
269293 }
270294
271 tmp->flags |= DIR_SCAN; /* Mark this service for loop detection */
295 tmp->flags |= DIR_SCAN; /* Mark this service for loop detection */
272296
273297 /*
274298 * If there are links in the links included, follow them
275299 */
276 list_for_each(dent, &(tmp->link)) {
300 list_for_each(dent, &(tmp->s_link)) {
277301 dir_t * target = getlink(dent)->target;
278302
279303 if (!(dir->lvl & target->lvl))
280 continue; /* Not same boot level */
304 continue; /* Not same boot level */
281305
282306 if (target == tmp)
283 break; /* Loop avoided */
307 break; /* Loop avoided */
284308
285309 if (target == dir)
286 break; /* Loop avoided */
310 break; /* Loop avoided */
287311
288312 if (skip && skip == target) {
289313 if (!remembernode(skip) || !remembernode(tmp))
290314 loop_warn_two(skip, tmp);
291315 recursion = false;
292 break; /* Loop detected, stop recursion */
316 break; /* Loop detected, stop recursion */
293317 }
294318
295 __follow(target, tmp, deep); /* The inner recursion */
319 if (target->start >= deep) /* Nothing new */
320 continue;
321 /* The inner recursion */
322 __follow(target, tmp, deep, reportloop);
296323
297324 /* Just for the case an inner recursion was stopped */
298325 if (loop_check(target) || loop_check(tmp) || loop_check(skip)) {
299326 recursion = false;
300 break; /* Loop detected, stop recursion */
327 break; /* Loop detected, stop recursion */
301328 }
302329 }
303330
304 tmp->flags &= ~DIR_SCAN; /* Remove loop detection mark */
305
306 if (!recursion)
307 break; /* Loop detected, stop recursion */
308 }
331 tmp->flags &= ~DIR_SCAN; /* Remove loop detection mark */
332
333 if (!recursion) {
334 if (reportloop && !(tmp->flags & DIR_LOOPREPORT)) {
335 warn(" loop involving service %s at depth %d\n", tmp->name, level);
336 tmp->flags |= DIR_LOOPREPORT;
337 }
338 break; /* Loop detected, stop recursion */
339 }
340 }
341 out:
342 return; /* Make compiler happy */
309343 }
310344
311345 #undef loop_warn_two
315349 /*
316350 * Helper for follow_all: start with depth one.
317351 */
318 inline static void follow(dir_t * dir)
352 static inline void follow(dir_t *__restrict dir, const int reportloop) __attribute__((always_inline,nonnull(1)));
353 static inline void follow(dir_t * dir, const int reportloop)
319354 {
320355 /* Link depth starts here with one */
321 __follow(dir, NULL, dir->minord);
356 __follow(dir, NULL, dir->minstart, reportloop);
322357 }
323358
324359 /*
326361 * The maximal order of not existing services can be
327362 * set if they are required by existing services.
328363 */
364 static void guess_order(dir_t *__restrict dir) __attribute__((nonnull(1)));
329365 static void guess_order(dir_t * dir)
330366 {
367 list_t * l_list = &(dir->s_link);
331368 register int min = 99, lvl = 0;
332 int deep = 0;
369 register int deep = 0;
333370
334371 if (dir->script) /* Skip it because we have read it */
335372 goto out;
338375 goto out;
339376
340377 /* No full loop required because we seek for the lowest order */
341 if (!list_empty(&(dir->link))) {
342 dir_t * target = getlinkdir(&(dir->link));
378 if (!list_empty(l_list)) {
379 dir_t * target = getnextlink(l_list);
380 uchar * order = &(target->start);
343381 list_t * dent;
344382
345 if (min > target->order)
346 min = target->order;
383 if (min > *order)
384 min = *order;
347385
348386 lvl |= target->lvl;
349387
350 list_for_each(dent, &(dir->link)) {
388 list_for_each(dent, &(dir->s_link)) {
351389 dir_t * target = getlink(dent)->target;
390 uchar * order = &(target->start);
352391
353392 if (++deep > MAX_DEEP)
354393 break;
356395 if (target == dir)
357396 break; /* Loop detected */
358397
359 if (min > target->order)
360 min = target->order;
398 if (min > *order)
399 min = *order;
361400
362401 lvl |= target->lvl;
363402 }
364403 if (min > 1) { /* Set guessed order of this unknown script */
365 dir->order = min - 1;
404 uchar * order = &(dir->start);
405 *order = min - 1;
366406 dir->lvl |= lvl; /* Set guessed runlevels of this unknown script */
367407 } else
368408 dir->lvl = LVL_BOOT;
382422 * Follow all scripts and calculate the main ordering.
383423 */
384424 list_for_each(tmp, d_start)
385 follow(getdir(tmp));
425 follow(getdir(tmp), 1);
386426
387427 /*
388428 * Guess order of not installed scripts in comparision
394434 list_for_each(tmp, d_start) {
395435 if (!(getdir(tmp)->lvl & LVL_ALL))
396436 continue;
397 if (maxorder < getdir(tmp)->order)
398 maxorder = getdir(tmp)->order;
399 }
437 if (maxorder < getdir(tmp)->start)
438 maxorder = getdir(tmp)->start;
439 }
440 }
441
442 boolean is_loop_detected(void)
443 {
444 list_t *tmp;
445 list_for_each(tmp, d_start) {
446 dir_t * dir = getdir(tmp);
447 if (dir->flags & DIR_LOOPREPORT)
448 return true;
449 }
450 return false;
400451 }
401452
402453 /*
409460 list_for_each(tmp, d_start) {
410461 dir_t * dir = getdir(tmp);
411462 if (dir->script)
412 fprintf(stderr, "%.2d %s 0x%.2x (%s)\n",
413 dir->order, dir->script, dir->lvl, dir->name);
463 fprintf(stderr, "%.2d %s 0x%.2x '%s' (%s)\n",
464 dir->start, dir->script, dir->lvl, lvl2str(dir->lvl), dir->name);
414465 else
415 fprintf(stderr, "%.2d %s 0x%.2x (%%%s)\n",
416 dir->order, dir->name, dir->lvl, *dir->name == '$' ? "system" : "guessed");
466 fprintf(stderr, "%.2d %s 0x%.2x '%s' (%%%s)\n",
467 dir->start, dir->name, dir->lvl, lvl2str(dir->lvl), *dir->name == '$' ? "system" : "guessed");
417468 }
418469 }
419470 #endif
425476 {
426477 list_t *tmp;
427478 boolean ret = false;
428 unsigned int lvl = 0;
429
430 switch (runlevel) {
431 case 0: lvl = LVL_HALT; break;
432 case 1: lvl = LVL_ONE; break;
433 case 2: lvl = LVL_TWO; break;
434 case 3: lvl = LVL_THREE; break;
435 case 4: lvl = LVL_FOUR; break;
436 case 5: lvl = LVL_FIVE; break;
437 case 6: lvl = LVL_REBOOT; break;
438 #ifdef SUSE
439 case 7: lvl = LVL_SINGLE; break;
440 case 8: lvl = LVL_BOOT; break;
441 #else
442 case 7: lvl = LVL_BOOT; break;
443 #endif /* not SUSE */
444
445 default:
446 warn("Wrong runlevel %d\n", runlevel);
447 }
479 uint lvl = 0;
480
481 lvl = map_runlevel_to_lvl (runlevel);
448482
449483 list_for_each(tmp, d_start) {
450484 dir_t * dir = getdir(tmp);
474508 static list_t * tmp;
475509 dir_t * dir;
476510 boolean ret;
477 unsigned int lvl = 0;
511 uint lvl = 0;
478512
479513 if (!*script)
480514 tmp = d_start->next;
481515
482 switch (runlevel) {
483 case 0: lvl = LVL_HALT; break;
484 case 1: lvl = LVL_ONE; break;
485 case 2: lvl = LVL_TWO; break;
486 case 3: lvl = LVL_THREE; break;
487 case 4: lvl = LVL_FOUR; break;
488 case 5: lvl = LVL_FIVE; break;
489 case 6: lvl = LVL_REBOOT; break;
490 #ifdef SUSE
491 case 7: lvl = LVL_SINGLE; break;
492 case 8: lvl = LVL_BOOT; break;
493 #else
494 case 7: lvl = LVL_BOOT; break;
495 #endif /* not SUSE */
496 default:
497 warn("Wrong runlevel %d\n", runlevel);
498 }
516 lvl = map_runlevel_to_lvl (runlevel);
499517
500518 do {
501519 ret = false;
504522 dir = getdir(tmp);
505523 ret = true;
506524 *script = dir->script;
507 *order = dir->order;
525 *order = dir->start;
508526
509527 #if defined (IGNORE_LOOPS) && (IGNORE_LOOPS > 0)
510528 if (dir->flags & DIR_LOOP)
565583 {
566584 dir_t * dir = providedir(this);
567585
568 dir->lvl = str2lvl(lvl);
586 dir->lvl |= str2lvl(lvl);
569587 }
570588
571589 /*
572590 * Two helpers for runlevel bits and strings.
573591 */
574 unsigned int str2lvl(const char * lvl)
592 uint str2lvl(const char * lvl)
575593 {
576594 char * token, *tmp = strdupa(lvl);
577 int num;
578 unsigned int ret = 0;
595 uint ret = 0;
579596
580597 if (!tmp)
581598 error("%s", strerror(errno));
586603 if (!strpbrk(token, "0123456sSbB"))
587604 continue;
588605
589 if (*token == 'S' || *token == 's')
590 num = 7;
591 else if (*token == 'B' || *token == 'b')
592 num = 8;
593 else
594 num = atoi(token);
595
596 switch (num) {
597 case 0: ret |= LVL_HALT; break;
598 case 1: ret |= LVL_ONE; break;
599 case 2: ret |= LVL_TWO; break;
600 case 3: ret |= LVL_THREE; break;
601 case 4: ret |= LVL_FOUR; break;
602 case 5: ret |= LVL_FIVE; break;
603 case 6: ret |= LVL_REBOOT; break;
604 #ifdef SUSE
605 case 7: ret |= LVL_SINGLE; break;
606 case 8: ret |= LVL_BOOT; break;
607 #else
608 case 7: ret |= LVL_BOOT; break;
609 #endif /* not SUSE */
610 default:
611 warn("Wrong runlevel %d\n", num);
612 }
606 ret |= map_key_to_lvl(*token);
613607 }
614608
615609 return ret;
616610 }
617611
618 char * lvl2str(const unsigned int lvl)
612 char * lvl2str(const uint lvl)
619613 {
620614 char str[20], * ptr = str;
621615 int num;
622 unsigned int bit = 0x001;
616 uint bit = 0x001;
623617
624618 memset(ptr , '\0', sizeof(str));
625619 for (num = 0; num < 9; num++) {
631625 *(ptr++) = 'S';
632626 else if (LVL_BOOT & bit)
633627 *(ptr++) = 'B';
634 #else
628 #else /* not SUSE */
635629 else if (LVL_BOOT & bit)
636630 *(ptr++) = 'S';
637631 #endif /* not SUSE */
656650 if (!dir)
657651 goto out;
658652
659 if (dir->minord < order)
660 dir->minord = order; /* Remember lowest default order deep */
661
662 if (dir->order >= dir->minord) /* Nothing to do */
653 if (dir->minstart < order)
654 dir->minstart = order; /* Remember lowest default order deep */
655
656 if (dir->start >= dir->minstart) /* Nothing to do */
663657 goto out;
664658
665659 if (!recursive) {
666 dir->order = dir->minord;
660 dir->start = dir->minstart;
667661 goto out;
668662 }
669663
670664 /*
671665 * Follow the script and re-calculate the ordering.
672666 */
673 __follow(dir, NULL, dir->minord);
667 __follow(dir, NULL, dir->minstart, 0);
674668
675669 /*
676670 * Guess order of not installed scripts in comparision
682676 list_for_each(tmp, d_start) {
683677 if (!(getdir(tmp)->lvl & LVL_ALL))
684678 continue;
685 if (maxorder < getdir(tmp)->order)
686 maxorder = getdir(tmp)->order;
679 if (maxorder < getdir(tmp)->start)
680 maxorder = getdir(tmp)->start;
687681 }
688682 out:
689683 return;
698692 int order = -1;
699693
700694 if (dir)
701 order = dir->order;
695 order = dir->start;
702696
703697 return order;
704698 }
00 /*
11 * listing.h
22 *
3 * Copyright 2000 Werner Fink, 2000 SuSE GmbH Nuernberg, Germany.
3 * Copyright 2000,2008 Werner Fink, 2000 SuSE GmbH Nuernberg, Germany.
4 * 2008 SuSE Linux Products GmbH Nuernberg, Germany
45 *
56 * This source is free software; you can redistribute it and/or modify
67 * it under the terms of the GNU General Public License as published by
1011
1112 #include <stddef.h>
1213
14 #if defined(DEBUG) && (DEBUG > 0)
15 # define __align __attribute__((packed))
16 #else
17 # define __align __attribute__((aligned(sizeof(struct list_struct*))))
18 #endif
19
1320 typedef struct list_struct {
1421 struct list_struct * next, * prev;
15 } list_t;
22 } __align list_t;
1623
1724 /*
1825 * Insert new entry as next member.
1926 */
27 static inline void insert (list_t *__restrict new, list_t *__restrict here) __attribute__((always_inline,nonnull(1,2)));
2028 static inline void insert (list_t * new, list_t * here)
2129 {
2230 list_t * prev = here;
3139 /*
3240 * Remove entries, note that the pointer its self remains.
3341 */
42 static inline void delete (list_t *__restrict entry) __attribute__((always_inline,nonnull(1)));
3443 static inline void delete (list_t * entry)
3544 {
3645 list_t * prev = entry->prev;
4049 prev->next = next;
4150 }
4251
43 static inline void join(list_t *list, list_t *head)
52 static inline void join(list_t *__restrict list, list_t *__restrict head) __attribute__((always_inline,nonnull(1,2)));
53 static inline void join(list_t * list, list_t * head)
4454 {
45 list_t *first = list->next;
55 list_t * first = list->next;
4656
4757 if (first != list) {
4858 list_t *last = list->prev;
5666 }
5767 }
5868
59 static inline int list_empty(list_t *head)
69 static inline int list_empty(list_t *__restrict head) __attribute__((always_inline,nonnull(1)));
70 static inline int list_empty(list_t * head)
6071 {
6172 return head->next == head;
6273 }
7081 for (pos = (head)->prev; pos != (head); pos = pos->prev)
7182
7283 typedef enum _boolean {false, true} boolean;
73 extern void follow_all();
74 extern void show_all();
75 extern void requiresl(const char * this, ...);
76 extern void requiresv(const char * this, const char * requires);
77 extern void runlevels(const char * this, const char * lvl);
78 extern unsigned int str2lvl(const char * lvl);
79 extern char * lvl2str(const unsigned int lvl);
80 extern int makeprov(const char * name, const char * script);
81 extern void setorder(const char * script, const int order, boolean recursive);
82 extern int getorder(const char * script);
83 extern boolean notincluded(const char * script, const int runlevel);
84 extern boolean foreach(const char ** script, int * order, const int runlevel);
85 extern void virtprov(const char * virt, const char * real);
86 extern const char * getscript(const char * prov);
87 extern const char * getprovides(const char * script);
88 extern boolean listscripts(const char ** script, const int lvl);
84 typedef unsigned char uchar;
85 typedef unsigned short ushort;
86 typedef unsigned int uint;
87
88 extern void follow_all(void);
89 extern void show_all(void);
90 extern void requiresl(const char *__restrict this, ...) __attribute__((nonnull(1)));
91 extern void requiresv(const char *__restrict this, const char *__restrict requires) __attribute__((nonnull(1,2)));
92 extern void runlevels(const char *__restrict this, const char *__restrict lvl) __attribute__((nonnull(1,2)));
93 extern uint str2lvl(const char *__restrict lvl) __attribute__((nonnull(1)));
94 extern char * lvl2str(const uint lvl);
95 extern int makeprov(const char *__restrict name, const char *__restrict script) __attribute__((nonnull(1,2)));
96 extern void setorder(const char *__restrict script, const int order, boolean recursive) __attribute__((nonnull(1)));
97 extern int getorder(const char *__restrict script) __attribute__((nonnull(1)));
98 extern boolean notincluded(const char *__restrict script, const int runlevel) __attribute__((nonnull(1)));
99 extern boolean foreach(const char **__restrict script, int *__restrict order, const int runlevel) __attribute__((nonnull(1,2)));
100 extern void virtprov(const char *__restrict virt, const char *__restrict real) __attribute__((nonnull(1,2)));
101 extern const char * getscript(const char *__restrict prov) __attribute__((nonnull(1)));
102 extern const char * getprovides(const char *__restrict script) __attribute__((nonnull(1)));
103 extern boolean listscripts(const char **__restrict script, const int lvl) __attribute__((nonnull(1)));
89104 extern int maxorder;
105 extern boolean is_loop_detected(void);
90106
91107 /*
92108 * Common short cuts
93109 */
94110 extern const char *const delimeter;
95 extern void error (const char *fmt, ...);
96 extern void warn (const char *fmt, ...);
97 extern void info (const char *fmt, ...);
111 extern void error (const char *__restrict fmt, ...) __attribute__((format(printf,1,2)));
112 extern void warn (const char *__restrict fmt, ...) __attribute__((format(printf,1,2)));
113 extern void info (const char *__restrict fmt, ...) __attribute__((format(printf,1,2)));
114 extern int map_has_runlevels(void);
115 extern int map_runlevel_to_lvl (const int runlevel);
116 extern int map_key_to_lvl(const char key);
98117
99 static inline char * xstrdup(const char *s)
118 static inline char * xstrdup(const char *__restrict s) __attribute__((always_inline,nonnull(1)));
119 static inline char * xstrdup(const char * s)
100120 {
101121 char * r;
102122 if (!s)
120140 /*
121141 * Bits of the runlevels
122142 */
123 #define LVL_HALT 0x001
124 #define LVL_ONE 0x002
125 #define LVL_TWO 0x004
126 #define LVL_THREE 0x008
127 #define LVL_FOUR 0x010
128 #define LVL_FIVE 0x020
129 #define LVL_REBOOT 0x040
130 #define LVL_SINGLE 0x080
131 #define LVL_BOOT 0x100
143 #define LVL_HALT 0x0001
144 #define LVL_ONE 0x0002
145 #define LVL_TWO 0x0004
146 #define LVL_THREE 0x0008
147 #define LVL_FOUR 0x0010
148 #define LVL_FIVE 0x0020
149 #define LVL_REBOOT 0x0040
150 #define LVL_SINGLE 0x0080
151 #define LVL_BOOT 0x0100
132152
133153 /*
134154 * LVL_BOOT is already done if one of the LVL_ALL will be entered.