Codebase list insserv / 1ede924
Import Upstream version 1.04.0 Dmitry Bogatov 5 years ago
6 changed file(s) with 166 addition(s) and 102 deletion(s). Raw diff Collapse all Expand all
0 -------------------------------------------------------------------
1 Thu Nov 10 18:05:53 CET 2005 - werner@suse.de
2
3 - Add patches from Petter Reinholdtsen
4 * Avoid zero pointer
5 * Allow not existing rc ditrectories at dryrun
6 * Some more debugging code
7 * Map the runlevel scheme into a common struct
8
9 -------------------------------------------------------------------
10 Fri Oct 28 17:48:38 CEST 2005 - werner@suse.de
11
12 - Fix duplet handling in make like service handling (bug #130451)
13
014 -------------------------------------------------------------------
115 Thu Sep 15 16:54:40 CEST 2005 - werner@suse.de
216
1212 DEBUG =
1313 ISSUSE = -DSUSE
1414 DESTDIR =
15 VERSION = 1.02.0
15 VERSION = 1.04.0
1616 DATE = $(shell date +'%d%b%y' | tr '[:lower:]' '[:upper:]')
1717
1818 #
+0
-15
insserv-1.02.0.lsm less more
0 Begin3
1 Title: insserv tool for boot scripts
2 Version: 1.02.0
3 Entered-date: 15SEP05
4 Description: Used for enabling of installed boot scripts
5 by scanning comment headers which are LSB conform.
6 Keywords: boot service control, LSB
7 Author: Werner Fink <werner@suse.de>
8 Maintained-by: Werner Fink <werner@suse.de>
9 Primary-site: sunsite.unc.edu /pub/Linux/system/daemons/init
10 @UNKNOWN insserv-1.02.0.tar.gz
11 Alternate-site: ftp.suse.com /pub/projects/init
12 Platforms: Linux with System VR2 or higher boot scheme
13 Copying-policy: GPL
14 End
0 Begin3
1 Title: insserv tool for boot scripts
2 Version: 1.04.0
3 Entered-date: 10NOV05
4 Description: Used for enabling of installed boot scripts
5 by scanning comment headers which are LSB conform.
6 Keywords: boot service control, LSB
7 Author: Werner Fink <werner@suse.de>
8 Maintained-by: Werner Fink <werner@suse.de>
9 Primary-site: sunsite.unc.edu /pub/Linux/system/daemons/init
10 @UNKNOWN insserv-1.04.0.tar.gz
11 Alternate-site: ftp.suse.com /pub/projects/init
12 Platforms: Linux with System VR2 or higher boot scheme
13 Copying-policy: GPL
14 End
00 /*
11 * insserv(.c)
22 *
3 * Copyright 2000-2004 Werner Fink, 2000 SuSE GmbH Nuernberg, Germany,
3 * Copyright 2000-2005 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
68 *
79 * This program is free software; you can redistribute it and/or modify
810 * it under the terms of the GNU General Public License as published by
2729 #include <getopt.h>
2830 #include "listing.h"
2931
32 static char *map_runlevel_to_location(const int runlevel);
33 static const int map_runlevel_to_lvl (const int runlevel) __attribute__ ((unused));
34 static const int map_runlevel_to_seek(const int runlevel) __attribute__ ((unused));
35
3036 #ifndef INITDIR
3137 # define INITDIR "/etc/init.d"
3238 #endif
191197 list_t req, rev;
192198 } sort_t;
193199
194 typedef struct serv_struct {
200 struct serv_struct;
201 typedef struct serv_struct serv_t;
202
203 struct serv_struct {
195204 list_t id;
196205 sort_t sort;
197206 unsigned int opts;
198207 char order;
199208 char * name;
209 serv_t * main;
200210 unsigned int lvls;
201211 #ifndef SUSE
202212 unsigned int lvlk;
203213 #endif
204 } serv_t;
214 };
205215 #define getserv(arg) list_entry((arg), struct serv_struct, id)
206216
207217 static list_t serv = { &(serv), &(serv) }, *serv_start = &(serv);
234244
235245 this->opts = 0;
236246 this->name = xstrdup(serv);
247 this->main = (serv_t *)0;
237248 this->order = 0;
238249 this->lvls = 0;
239250 #ifndef SUSE
620631 fprintf(start, "INTERACTIVE =");
621632 list_for_each(srv, serv_start) {
622633 serv_t * cur = getserv(srv);
623 serv_t * chk;
624634
625635 if (!cur || list_empty(&(cur->sort.req)))
626636 continue;
633643 if ((name = getscript(cur->name)) == 0)
634644 name = cur->name;
635645
636 if ((chk = findserv(name)) && (cur != chk)) {
637 cur->opts |= SERV_DUPLET; /* Duplet */
638 continue;
639 }
646 if (cur->opts & SERV_DUPLET)
647 continue; /* Duplet */
640648
641649 if (cur->opts & SERV_ACTIVE)
642650 fprintf(out, " %s", name);
675683 continue;
676684
677685 /*
678 * Skip not existing services even if they do not exist
686 * Skip not existing services even if they are used
679687 * otherwise the make call will skip all dependencies
680688 */
681 if (!dep || (dep->opts & SERV_DUPLET))
682 continue; /* Duplet */
689 if (!dep) continue;
690
691 if ((dep->opts & SERV_DUPLET) && dep->main)
692 dep = dep->main; /* Duplet */
683693
684694 if ((name = getscript(dep->name)) == NULL)
685695 name = dep->name;
701711 reverse(req->serv, cur->name);
702712
703713 /*
704 * Skip not existing services even if they do not exist
714 * Skip not existing services even if they are used
705715 * otherwise the make call will skip all dependencies
706716 */
707 if (!dep || (dep->opts & SERV_DUPLET))
708 continue; /* Duplet */
717 if (!dep) continue;
718
719 if ((dep->opts & SERV_DUPLET) && dep->main)
720 dep = dep->main; /* Duplet */
709721
710722 if ((name = getscript(req->serv)) == NULL)
711723 name = req->serv;
762774 pr++;
763775 }
764776
765 if (!dep || (dep->opts & SERV_DUPLET))
766 continue; /* Duplet */
777 if (!dep) continue;
778
779 if ((dep->opts & SERV_DUPLET) && dep->main)
780 dep = dep->main; /* Duplet */
767781
768782 if ((name = getscript(rev->serv)) == NULL)
769783 name = rev->serv;
849863 error("can not stat(%s): %s\n", rcpath, strerror(errno));
850864 }
851865
852 if ((rcdir = opendir(rcpath)) == NULL)
853 error("can not opendir(%s): %s\n", rcpath, strerror(errno));
866 if ((rcdir = opendir(rcpath)) == NULL) {
867 if (dryrun)
868 warn ("can not opendir(%s): %s\n", rcpath, strerror(errno));
869 else
870 error("can not opendir(%s): %s\n", rcpath, strerror(errno));
871 }
854872
855873 return rcdir;
856874 }
919937 #define default_stop script_inf.default_stop
920938 #define description script_inf.description
921939
940 info("Loading %s\n", path);
922941 script = fopen(path, "r");
923942 if (!script)
924943 error("fopen(%s): %s\n", path, strerror(errno));
10381057 regfree(&reg.desc);
10391058 }
10401059
1060 static struct {
1061 char *location;
1062 const int lvl;
1063 const int seek;
1064 } runlevel_locations[] = {
1065 #ifdef SUSE /* SuSE's SystemV link scheme */
1066 {"rc0.d/", LVL_HALT, LVL_NORM},
1067 {"rc1.d/", LVL_ONE, LVL_NORM},
1068 {"rc2.d/", LVL_TWO, LVL_NORM},
1069 {"rc3.d/", LVL_THREE, LVL_NORM},
1070 {"rc4.d/", LVL_FOUR, LVL_NORM},
1071 {"rc5.d/", LVL_FIVE, LVL_NORM},
1072 {"rc6.d/", LVL_REBOOT, LVL_NORM},
1073 {"rcS.d/", LVL_SINGLE, LVL_NORM}, /* runlevel S */
1074 {"boot.d/", LVL_BOOT, LVL_BOOT}, /* runlevel B */
1075 #else /* not SUSE (actually, Debian) */
1076 {"../rc0.d/", LVL_HALT, LVL_NORM},
1077 {"../rc1.d/", LVL_SINGLE, LVL_NORM},
1078 {"../rc2.d/", LVL_TWO, LVL_NORM},
1079 {"../rc3.d/", LVL_THREE, LVL_NORM},
1080 {"../rc4.d/", LVL_FOUR, LVL_NORM},
1081 {"../rc5.d/", LVL_FIVE, LVL_NORM},
1082 {"../rc6.d/", LVL_REBOOT, LVL_NORM},
1083 {"../rcS.d/", LVL_BOOT, LVL_BOOT}, /* runlevel S */
1084 /* On e.g. Debian there exist no boot.d */
1085 #endif
1086 };
1087
1088 #define RUNLEVLES (sizeof(runlevel_locations)/sizeof(runlevel_locations[0]))
1089
1090 static char *map_runlevel_to_location(const int runlevel)
1091 {
1092 return runlevel_locations[runlevel].location;
1093 }
1094
1095 static const int map_runlevel_to_lvl(const int runlevel)
1096 {
1097 return runlevel_locations[runlevel].lvl;
1098 }
1099
1100 static const int map_runlevel_to_seek(const int runlevel)
1101 {
1102 return runlevel_locations[runlevel].seek;
1103 }
1104
10411105 /*
10421106 * Scan current service structure
10431107 */
10461110 int runlevel;
10471111
10481112 pushd(path);
1049 for (runlevel = 0; runlevel < 9; runlevel++) {
1113 for (runlevel = 0; runlevel < RUNLEVLES; runlevel++) {
10501114 char * rcd = NULL;
10511115 DIR * rcdir;
10521116 struct dirent *d;
10531117 char * token;
10541118 struct stat st_script;
10551119
1056 switch (runlevel) {
1057 case 0: rcd = "rc0.d/"; break;
1058 case 1: rcd = "rc1.d/"; break;
1059 case 2: rcd = "rc2.d/"; break;
1060 case 3: rcd = "rc3.d/"; break;
1061 case 4: rcd = "rc4.d/"; break;
1062 case 5: rcd = "rc5.d/"; break;
1063 case 6: rcd = "rc6.d/"; break;
1064 case 7: rcd = "rcS.d/"; break; /* runlevel S */
1065 case 8: rcd = "boot.d/"; break; /* runlevel B */
1066 default:
1067 error("Wrong runlevel %d\n", runlevel);
1068 }
1069
1120 rcd = map_runlevel_to_location(runlevel);
10701121 rcdir = openrcdir(rcd); /* Creates runlevel directory if necessary */
1122 if (rcdir == NULL)
1123 break;
10711124 pushd(rcd);
10721125 while ((d = readdir(rcdir)) != NULL) {
10731126 char * ptr = d->d_name;
11631216 regcompiler(&reg_conf, CONFLINE, REG_EXTENDED|REG_ICASE);
11641217 regcompiler(&reg_conf2, CONFLINE2, REG_EXTENDED|REG_ICASE);
11651218
1219 info("Loading %s\n", file);
1220
11661221 do {
11671222 const char * fptr = file;
11681223 if (*fptr == '/')
12551310 if ((end = strrchr(d->d_name, '.'))) {
12561311 end++;
12571312 if (!strcmp(end, "local") ||
1258 !strncmp(end, "rpm", 3) || /* .rmporig, .rpmnew, .rmpsave, ... */
1313 !strncmp(end, "rpm", 3) || /* .rpmorig, .rpmnew, .rmpsave, ... */
12591314 !strncmp(end, "ba", 2) || /* .bak, .backup, ... */
12601315 !strcmp(end, "old") ||
12611316 !strcmp(end, "new") ||
15251580 pushd(path);
15261581 while ((d = readdir(initdir)) != NULL) {
15271582 serv_t * service = NULL;
1528 char * end;
15291583 char * token;
15301584 char* begin = (char*)NULL; /* Remember address of ptr handled by strsep() */
15311585 boolean lsb = false;
15721626 continue;
15731627 }
15741628
1575 if (!strcmp(d->d_name, "boot") || !strcmp(d->d_name, "rc")) {
1629 #ifdef SUSE
1630 if (!strcmp(d->d_name, "boot") || !strcmp(d->d_name, "rc"))
1631 #else
1632 if (!strcmp(d->d_name, "rcS") || !strcmp(d->d_name, "rc"))
1633 #endif
1634 {
15761635 if (chkfor(d->d_name, argv, argc))
15771636 warn("script name %s is not valid, skipped!\n", d->d_name);
15781637 continue;
15791638 }
15801639
1581 if ((end = strrchr(d->d_name, '.'))) {
1582 end++;
1583 if (!strcmp(end, "local") ||
1584 !strncmp(end, "rpm", 3) || /* .rmporig, .rpmnew, .rmpsave, ... */
1585 !strncmp(end, "ba", 2) || /* .bak, .backup, ... */
1586 !strcmp(end, "old") ||
1587 !strcmp(end, "new") ||
1588 !strcmp(end, "save") ||
1589 !strcmp(end, "swp") || /* Used by vi like editors */
1590 !strcmp(end, "core")) /* modern core dump */
1591 {
1592 if (chkfor(d->d_name, argv, argc))
1593 warn("script name %s is not valid, skipped!\n", d->d_name);
1594 continue;
1595 }
1640 if (cfgfile_filter(d) == 0) {
1641 if (chkfor(d->d_name, argv, argc))
1642 warn("script name %s is not valid, skipped!\n", d->d_name);
1643 continue;
15961644 }
15971645
15981646 /* Leaved by emacs like editors */
17041752 * (by using the list from the first scan for script locations).
17051753 */
17061754 if (!service) {
1755 int count = 0;
17071756 char * provides = xstrdup(script_inf.provides);
17081757
17091758 begin = provides;
17361785
17371786 if (!(service = findserv(token)))
17381787 service = addserv(token);
1788 count++; /* Count token */
17391789
17401790 if (service) {
17411791 boolean known = (service->opts & SERV_KNOWN);
17421792 service->opts |= SERV_KNOWN;
1793
1794 if (!provides && (count > 1)) { /* Last token */
1795 const char * script = getscript(service->name);
1796
1797 if (script) {
1798 list_t * srv;
1799
1800 list_for_each(srv, serv_start) {
1801 serv_t * cur = getserv(srv);
1802 const char * chk;
1803
1804 if (!cur || !(chk = getscript(cur->name)))
1805 continue;
1806
1807 if (!strcmp(chk, script) && (service != cur)) {
1808 cur->opts |= SERV_DUPLET;
1809 cur->main = service; /* Remember main service */
1810 }
1811 }
1812 }
1813 }
17431814
17441815 if (!known && script_inf.required_start && script_inf.required_start != empty) {
17451816 rememberreq(service, REQ_MUST, script_inf.required_start);
19111982 /*
19121983 * default_stop arn't used in SuSE Linux.
19131984 */
1914 if (!service || !del)
1915 service->lvlk = str2lvl(script_inf.default_stop);
1985 if (script_inf.default_stop && script_inf.default_stop != empty) {
1986 if (!service || !del)
1987 service->lvlk = str2lvl(script_inf.default_stop);
1988 }
19161989 #endif
19171990 }
19181991 script_inf.provides = begin;
20032076 char * rcd = NULL;
20042077 DIR * rcdir;
20052078
2006 switch (runlevel) {
2007 case 0: rcd = "rc0.d/"; break;
2008 case 1: rcd = "rc1.d/"; break;
2009 case 2: rcd = "rc2.d/"; break;
2010 case 3: rcd = "rc3.d/"; break;
2011 case 4: rcd = "rc4.d/"; break;
2012 case 5: rcd = "rc5.d/"; break;
2013 case 6: rcd = "rc6.d/"; break;
2014 case 7: rcd = "rcS.d/"; break; /* runlevel S */
2015 case 8: rcd = "boot.d/"; break; /* runlevel B */
2016 default:
2017 error("Wrong runlevel %d\n", runlevel);
2018 }
2079 rcd = map_runlevel_to_location(runlevel);
20192080
20202081 script = NULL;
20212082 rcdir = openrcdir(rcd); /* Creates runlevel directory if necessary */
2083 if (rcdir == NULL)
2084 break;
20222085 pushd(rcd);
20232086
20242087 /*
21512214 * a traditional standard SystemV link scheme. Maybe for such an
21522215 * approach a new directory halt.d/ whould be an idea.
21532216 */
2154 # ifndef RUNLEVLES
2155 # define RUNLEVLES 8 /* On e.g. Debian there exist no boot.d */
2156 # endif
21572217 pushd(path);
21582218 for (runlevel = 0; runlevel < RUNLEVLES; runlevel++) {
21592219 int lvl = 0, seek = 0;
21622222 char * rcd = NULL;
21632223 DIR * rcdir;
21642224
2165 switch (runlevel) { /* LVL_NORM: nearly all but not BOOT and not SINGLE */
2166 case 0: rcd = "rc0.d/"; lvl = LVL_HALT; seek = LVL_NORM; break;
2167 case 1: rcd = "rc1.d/"; lvl = LVL_ONE; seek = LVL_NORM; break;
2168 case 2: rcd = "rc2.d/"; lvl = LVL_TWO; seek = LVL_NORM; break;
2169 case 3: rcd = "rc3.d/"; lvl = LVL_THREE; seek = LVL_NORM; break;
2170 case 4: rcd = "rc4.d/"; lvl = LVL_FOUR; seek = LVL_NORM; break;
2171 case 5: rcd = "rc5.d/"; lvl = LVL_FIVE; seek = LVL_NORM; break;
2172 case 6: rcd = "rc6.d/"; lvl = LVL_REBOOT; seek = LVL_NORM; break;
2173 case 7: rcd = "rcS.d/"; lvl = LVL_SINGLE; seek = LVL_NORM; break; /* runlevel S */
2174 # if defined(RUNLEVLES) && (RUNLEVLES > 8)
2175 case 8: rcd = "boot.d/"; lvl = LVL_BOOT; seek = LVL_BOOT; break; /* runlevel B */
2176 # endif
2177 default:
2178 error("Wrong runlevel %d\n", runlevel);
2179 }
2225 rcd = map_runlevel_to_location(runlevel);
2226 lvl = map_runlevel_to_lvl(runlevel);
2227 seek = map_runlevel_to_seek(runlevel);
21802228
21812229 script = NULL;
21822230 rcdir = openrcdir(rcd); /* Creates runlevel directory if necessary */
2231 if (rcdir == NULL)
2232 break;
21832233 pushd(rcd);
21842234
21852235 /*
108108 #define xremove(x) ({ if ((dryrun ? 0 : (remove(x) < 0))) \
109109 warn ("can not remove(%s%s): %s\n", rcd, x, strerror(errno)); \
110110 else \
111 info("remove service %s%s%s\n", path, rcd, x); })
111 info("remove service %s/%s%s\n", path, rcd, x); })
112112 #define xsymlink(x,y) ({ if ((dryrun ? 0 : (symlink(x, y) < 0))) \
113113 warn ("can not symlink(%s, %s%s): %s\n", x, rcd, y, strerror(errno)); \
114114 else \
115 info("enable service %s -> %s%s%s\n", x, path, rcd, y); })
115 info("enable service %s -> %s/%s%s\n", x, path, rcd, y); })
116116
117117 /*
118118 * Bits of the runlevels