From 09f990a7c835d75f67cfe696a35e8c46e67c612f Mon Sep 17 00:00:00 2001 From: "Robin H. Johnson" Date: Wed, 5 Jan 2011 22:03:43 -0800 Subject: Implement explicit selection of subsystem types. - Fixes bugs #347583, #349389, both of which were triggered by cgroups being detected as the LXC subsystem type. - Makes it much easier to select "prefix" type. - "rc -S" will now print a warning if you have not configured rc_sys in /etc/rc.conf - All other semantics of rc_sys are unchanged in this patch. Signed-off-by: Robin H. Johnson --- etc/Makefile | 3 +++ etc/Makefile.Linux | 6 +---- etc/rc.conf.FreeBSD | 8 ++++++ etc/rc.conf.Linux | 12 +++++++++ etc/rc.conf.NetBSD | 9 +++++++ etc/rc.conf.in | 1 + src/librc/librc.c | 55 +++++++++++++++++++++++++++++++++++++++- src/librc/librc.h | 2 ++ src/librc/rc.h.in | 11 ++++++++ src/librc/rc.map | 2 ++ src/rc/rc.c | 13 +++++++--- src/test/librc.funcs.hidden.list | 2 ++ src/test/rc.funcs.list | 4 +++ 13 files changed, 119 insertions(+), 9 deletions(-) create mode 100644 etc/rc.conf.FreeBSD create mode 100644 etc/rc.conf.NetBSD diff --git a/etc/Makefile b/etc/Makefile index ee1642e8..24e54550 100644 --- a/etc/Makefile +++ b/etc/Makefile @@ -7,3 +7,6 @@ MK= ../mk include ${MK}/os.mk include Makefile.${OS} include ${MK}/scripts.mk + +rc.conf: rc.conf.in rc.conf.${OS} + ${SED} ${SED_REPLACE} ${SED_EXTRA} $^ > $@ diff --git a/etc/Makefile.Linux b/etc/Makefile.Linux index 9ac0bc25..5b562947 100644 --- a/etc/Makefile.Linux +++ b/etc/Makefile.Linux @@ -1,6 +1,2 @@ SED_EXTRA= -e 's:@TERM@:wsvt25:g' -SRCS+= rc.in rc.shutdown.in - -rc.conf: - cp rc.conf.in rc.conf - cat rc.conf.Linux >> rc.conf +SRCS+= rc.conf.in rc.in rc.shutdown.in diff --git a/etc/rc.conf.FreeBSD b/etc/rc.conf.FreeBSD new file mode 100644 index 00000000..5682e1db --- /dev/null +++ b/etc/rc.conf.FreeBSD @@ -0,0 +1,8 @@ +# This is the subsystem type. Valid options on FreeBSD: +# "" - nothing special +# "jail" - FreeBSD jails +# "prefix" - Prefix +# If unset, the old automagic detection code will be triggered. Said old code +# is deprecated and be removed not later than 2010/03/01. +rc_sys="" + diff --git a/etc/rc.conf.Linux b/etc/rc.conf.Linux index e1f5ef5b..001e9c08 100644 --- a/etc/rc.conf.Linux +++ b/etc/rc.conf.Linux @@ -1,3 +1,15 @@ +# This is the subsystem type. Valid options on Linux: +# "" - nothing special +# "lxc" - Linux Containers +# "openvz" - Linux OpenVZ +# "prefix" - Prefix +# "uml" - Usermode Linux +# "vserver" - Linux vserver +# "xen0" - Xen0 Domain +# "xenU" - XenU Domain +# If unset, the old automagic detection code will be triggered. Said old code +# is deprecated and be removed not later than 2010/03/01. +rc_sys="" ############################################################################## # LINUX SPECIFIC OPTIONS diff --git a/etc/rc.conf.NetBSD b/etc/rc.conf.NetBSD new file mode 100644 index 00000000..25d86a4c --- /dev/null +++ b/etc/rc.conf.NetBSD @@ -0,0 +1,9 @@ +# This is the subsystem type. Valid options on NetBSD: +# "" - nothing special +# "prefix" - Prefix +# "xen0" - Xen0 Domain +# "xenU" - XenU Domain +# If unset, the old automagic detection code will be triggered. Said old code +# is deprecated and be removed not later than 2010/03/01. +rc_sys="" + diff --git a/etc/rc.conf.in b/etc/rc.conf.in index 200c4ce0..6aa36135 100644 --- a/etc/rc.conf.in +++ b/etc/rc.conf.in @@ -115,3 +115,4 @@ # You can also remove dependencies. # This is mainly used for saying which servies do NOT provide net. #rc_net_tap0_provide="!net" + diff --git a/src/librc/librc.c b/src/librc/librc.c index fe9e1b6b..6d823434 100644 --- a/src/librc/librc.c +++ b/src/librc/librc.c @@ -199,7 +199,51 @@ file_regex(const char *file, const char *regex) #endif const char * -rc_sys(void) +rc_sys_v2(void) +{ +#define __STRING_SWITCH(x) { char* __string_switch = x; if(false) {} +#define __STRING_CASE(y) else if(strcmp(__string_switch,y) == 0) +#define __STRING_SWITCH_END() } + char* systype = rc_conf_value("rc_sys"); + /* New sys identification code */ + if(systype) { + char* s = systype; + // Convert to uppercase + while(s && *s) { + if(islower((unsigned char)*s)) + *s = toupper((unsigned char)*s); + s++; + } + // Now do detection + __STRING_SWITCH(systype) + __STRING_CASE(RC_SYS_PREFIX) { return RC_SYS_PREFIX; } +#ifdef __FreeBSD__ + __STRING_CASE(RC_SYS_JAIL) { return RC_SYS_JAIL; } +#endif /* __FreeBSD__ */ +#ifdef __NetBSD__ + __STRING_CASE(RC_SYS_XEN0) { return RC_SYS_XEN0; } + __STRING_CASE(RC_SYS_XENU) { return RC_SYS_XENU; } +#endif /* __NetBSD__ */ +#ifdef __linux__ + __STRING_CASE(RC_SYS_XEN0) { return RC_SYS_XEN0; } + __STRING_CASE(RC_SYS_XENU) { return RC_SYS_XENU; } + __STRING_CASE(RC_SYS_UML) { return RC_SYS_UML; } + __STRING_CASE(RC_SYS_VSERVER) { return RC_SYS_VSERVER; } + __STRING_CASE(RC_SYS_OPENVZ) { return RC_SYS_OPENVZ; } + __STRING_CASE(RC_SYS_LXC) { return RC_SYS_LXC; } +#endif /* __linux__ */ + __STRING_SWITCH_END() + } +#undef __STRING_SWITCH +#undef __STRING_CASE +#undef __STRING_SWITCH_END + return NULL; +} +librc_hidden_def(rc_sys_v2) + +/* Old sys identification code */ +const char * +rc_sys_v1(void) { #ifdef PREFIX return RC_SYS_PREFIX; @@ -243,6 +287,15 @@ rc_sys(void) return NULL; #endif /* PREFIX */ } +librc_hidden_def(rc_sys_v1) + +const char * +rc_sys(void) +{ + const char *s = rc_sys_v2(); + if(s) return s; + return rc_sys_v1(); +} librc_hidden_def(rc_sys) static const char * diff --git a/src/librc/librc.h b/src/librc/librc.h index fc87bb10..dc97f1d3 100644 --- a/src/librc/librc.h +++ b/src/librc/librc.h @@ -125,6 +125,8 @@ librc_hidden_proto(rc_stringlist_new) librc_hidden_proto(rc_stringlist_split) librc_hidden_proto(rc_stringlist_sort) librc_hidden_proto(rc_sys) +librc_hidden_proto(rc_sys_v1) +librc_hidden_proto(rc_sys_v2) librc_hidden_proto(rc_yesno) #endif diff --git a/src/librc/rc.h.in b/src/librc/rc.h.in index d9d04539..3d0ffb42 100644 --- a/src/librc/rc.h.in +++ b/src/librc/rc.h.in @@ -274,8 +274,19 @@ bool rc_service_daemons_crashed(const char *); #define RC_SYS_VSERVER "VSERVER" #define RC_SYS_XEN0 "XEN0" #define RC_SYS_XENU "XENU" + +/*! Returns the type of subsystem + * @return string from RC_SYS_* types or NULL if none detected */ const char *rc_sys(void); +/*! Returns the type of subsystem using old automatic code + * @return string from RC_SYS_* types or NULL if none detected */ +const char *rc_sys_v1(void); + +/*! Returns the type of subsystem using new rc.conf rc_sys value + * @return string from RC_SYS_* types or NULL if none detected */ +const char *rc_sys_v2(void); + /*! @name Dependency options * These options can change the services found by the rc_get_depinfo and * rc_get_depends functions. */ diff --git a/src/librc/rc.map b/src/librc/rc.map index 3f1e7e70..113f2d7d 100644 --- a/src/librc/rc.map +++ b/src/librc/rc.map @@ -55,6 +55,8 @@ global: rc_stringlist_sort; rc_stringlist_free; rc_sys; + rc_sys_v1; + rc_sys_v2; rc_yesno; local: diff --git a/src/rc/rc.c b/src/rc/rc.c index ccafbe38..b062349a 100644 --- a/src/rc/rc.c +++ b/src/rc/rc.c @@ -878,9 +878,16 @@ main(int argc, char **argv) eerrorx("%s: %s", applet, strerror(errno)); /* NOTREACHED */ case 'S': - bootlevel = rc_sys(); - if (bootlevel) - printf("%s\n", bootlevel); + if (rc_conf_value("rc_sys")) { + bootlevel = rc_sys_v2(); + if(bootlevel) + printf("%s\n", bootlevel); + } else { + ewarn("WARNING: rc_sys not defined in rc.conf. Falling back to automatic detection"); + bootlevel = rc_sys_v1(); + if(bootlevel) + printf("%s\n", bootlevel); + } exit(EXIT_SUCCESS); /* NOTREACHED */ case_RC_COMMON_GETOPT diff --git a/src/test/librc.funcs.hidden.list b/src/test/librc.funcs.hidden.list index 121bfcf0..b661850f 100644 --- a/src/test/librc.funcs.hidden.list +++ b/src/test/librc.funcs.hidden.list @@ -51,4 +51,6 @@ rc_stringlist_new rc_stringlist_sort rc_stringlist_split rc_sys +rc_sys_v1 +rc_sys_v2 rc_yesno diff --git a/src/test/rc.funcs.list b/src/test/rc.funcs.list index b67c0d8f..0aac8f9a 100644 --- a/src/test/rc.funcs.list +++ b/src/test/rc.funcs.list @@ -104,5 +104,9 @@ rc_stringlist_split rc_stringlist_split@@RC_1.0 rc_sys rc_sys@@RC_1.0 +rc_sys_v1 +rc_sys_v1@@RC_1.0 +rc_sys_v2 +rc_sys_v2@@RC_1.0 rc_yesno rc_yesno@@RC_1.0 -- cgit v1.2.3