diff --git a/src/includes/rc-misc.h b/src/includes/rc-misc.h index f2449cd7..de73c5c1 100644 --- a/src/includes/rc-misc.h +++ b/src/includes/rc-misc.h @@ -43,6 +43,7 @@ char *rc_conf_value(const char *var); bool rc_conf_yesno(const char *var); +char *get_systype(void); void env_filter(void); void env_config(void); int signal_setup(int sig, void (*handler)(int)); @@ -60,10 +61,6 @@ int is_writable(const char *); #define service_stop(service) exec_service(service, "stop"); int parse_mode(mode_t *, char *); -const char *detect_prefix(void); -const char *get_systype(void); -const char *detect_container(void); -const char *detect_vm(void); /* Handy function so we can wrap einfo around our deptree */ RC_DEPTREE *_rc_deptree_load (int, int *); diff --git a/src/rc/_usage.c b/src/rc/_usage.c index 9fc3e5d8..40d81422 100644 --- a/src/rc/_usage.c +++ b/src/rc/_usage.c @@ -44,12 +44,9 @@ void set_quiet_options(void) _noreturn void show_version(void) { - const char *systype = NULL; + char *systype = get_systype(); printf("%s (OpenRC", applet); - systype = detect_container(); - if (!systype) - systype = detect_vm(); if (systype) printf(" [%s]", systype); printf(") %s", VERSION); diff --git a/src/rc/rc-misc.c b/src/rc/rc-misc.c index 2c6c3883..e0e6e2c7 100644 --- a/src/rc/rc-misc.c +++ b/src/rc/rc-misc.c @@ -50,6 +50,172 @@ rc_conf_yesno(const char *setting) return rc_yesno(rc_conf_value (setting)); } +/* + * static bool is_container(const char *systype) + * { + * FreeBSD: RC_SYS_JAIL + * Linux: RC_SYS_UML RC_SYS_VSERVER RC_SYS_OPENVZ RC_SYS_LXC + * RC_SYS_RKT RC_SYS_SYSTEMD_NSPAWN RC_SYS_DOCKER + * } + * + * static bool is_vm(const char *systype) + * { + * NetBSD: RC_SYS_XEN0 RC_SYS_XENU + * Linux: RC_SYS_XEN0 RC_SYS_XENU + * } + */ + +static bool file_regex(const char *file, const char *regex) +{ + FILE *fp; + char *line = NULL; + size_t len = 0; + regex_t re; + bool retval = true; + int result; + + if (!(fp = fopen(file, "r"))) + return false; + + if ((result = regcomp(&re, regex, REG_EXTENDED | REG_NOSUB)) != 0) { + fclose(fp); + line = xmalloc(sizeof(char) * BUFSIZ); + regerror(result, &re, line, BUFSIZ); + fprintf(stderr, "file_regex: %s", line); + free(line); + return false; + } + + while ((rc_getline(&line, &len, fp))) { + char *str = line; + /* some /proc files have \0 separated content so we have to + loop through the 'line' */ + do { + if (regexec(&re, str, 0, NULL, 0) == 0) + goto found; + str += strlen(str) + 1; + /* len is the size of allocated buffer and we don't + want call regexec BUFSIZE times. find next str */ + while (str < line + len && *str == '\0') + str++; + } while (str < line + len); + } + retval = false; +found: + fclose(fp); + free(line); + regfree(&re); + + return retval; +} + +char *get_systype(void) +{ + char *systype = rc_conf_value("rc_sys"); + char *s; + + if (systype) { + if (*systype == '\0') { + free(systype); + return NULL; + } + s = systype; + /* Convert to uppercase */ + while (s && *s) { + if (islower((unsigned char) *s)) + *s = toupper((unsigned char) *s); + s++; + } + if (strcmp(systype,RC_SYS_PREFIX) == 0) + return systype; + +#ifdef __FreeBSD__ + if (strcmp(systype, RC_SYS_JAIL) == 0) + return systype; +#endif + +#ifdef __linux__ + if (strcmp(systype, RC_SYS_UML) == 0) + return systype; + else if (strcmp(systype, RC_SYS_VSERVER) == 0) + return systype; + else if (strcmp(systype, RC_SYS_OPENVZ) == 0) + return systype; + else if (strcmp(systype, RC_SYS_LXC) == 0) + return systype; + else if (strcmp(systype, RC_SYS_RKT) == 0) + return systype; + else if (strcmp(systype, RC_SYS_SYSTEMD_NSPAWN) == 0) + return systype; + else if (strcmp(systype, RC_SYS_DOCKER) == 0) + return systype; + else if (strcmp(systype, RC_SYS_XEN0) == 0) + return systype; + else if (strcmp(systype, RC_SYS_XENU) == 0) + return systype; +#endif + +#ifdef __NetBSD__ + if(strcmp(systype, RC_SYS_XEN0) == 0) + return systype; + else if (strcmp(systype, RC_SYS_XENU) == 0) + return systype; +#endif + } + + free(systype); + systype = NULL; + +#ifdef PREFIX + systype = xstrdup(RC_SYS_PREFIX); + return systype; +#endif + +#ifdef __FreeBSD__ + int jailed = 0; + size_t len = sizeof(jailed); + + if (sysctlbyname("security.jail.jailed", &jailed, &len, NULL, 0) == 0) + if (jailed == 1) + systype = xstrdup(RC_SYS_JAIL); +#endif + +#ifdef __linux__ + if (file_regex("/proc/cpuinfo", "UML")) + systype = xstrdup(RC_SYS_UML); + else if (file_regex("/proc/self/status", + "(s_context|VxID):[[:space:]]*[1-9]")) + systype = xstrdup(RC_SYS_VSERVER); + else if (exists("/proc/vz/veinfo") && !exists("/proc/vz/version")) + systype = xstrdup(RC_SYS_OPENVZ); + else if (file_regex("/proc/self/status", + "envID:[[:space:]]*[1-9]")) + systype = xstrdup(RC_SYS_OPENVZ); /* old test */ + else if (file_regex("/proc/1/environ", "container=lxc")) + systype = xstrdup(RC_SYS_LXC); + else if (file_regex("/proc/1/environ", "container=rkt")) + systype = xstrdup(RC_SYS_RKT); + else if (file_regex("/proc/1/environ", "container=systemd-nspawn")) + systype = xstrdup(RC_SYS_SYSTEMD_NSPAWN); + else if (file_regex("/proc/1/environ", "container=docker")) + systype = xstrdup(RC_SYS_DOCKER); + else if (exists("/proc/xen")) { + if (file_regex("/proc/xen/capabilities", "control_d")) + systype = xstrdup(RC_SYS_XEN0); + systype = xstrdup(RC_SYS_XENU); + } +#endif + +#ifdef __NetBSD__ + if (exists("/kern/xen/privcmd")) + systype = xstrdup(RC_SYS_XEN0); + else if (exists("/kern/xen")) + systype = xstrdup(RC_SYS_XENU); +#endif + + return systype; +} + static const char *const env_whitelist[] = { "EERROR_QUIET", "EINFO_QUIET", "IN_BACKGROUND", "IN_HOTPLUG", @@ -126,7 +292,7 @@ env_config(void) char *np; char *npp; char *tok; - const char *sys = NULL; + char *sys = get_systype(); char buffer[PATH_MAX]; /* Ensure our PATH is prefixed with the system locations first @@ -177,12 +343,10 @@ env_config(void) } else setenv("RC_DEFAULTLEVEL", RC_LEVEL_DEFAULT, 1); - sys = detect_container(); - if (!sys) - sys = detect_vm(); - - if (sys) + if (sys) { setenv("RC_SYS", sys, 1); + free(sys); + } #ifdef PREFIX setenv("RC_PREFIX", RC_PREFIX, 1); @@ -338,163 +502,6 @@ is_writable(const char *path) return 0; } -static bool file_regex(const char *file, const char *regex) -{ - FILE *fp; - char *line = NULL; - size_t len = 0; - regex_t re; - bool retval = true; - int result; - - if (!(fp = fopen(file, "r"))) - return false; - - if ((result = regcomp(&re, regex, REG_EXTENDED | REG_NOSUB)) != 0) { - fclose(fp); - line = xmalloc(sizeof(char) * BUFSIZ); - regerror(result, &re, line, BUFSIZ); - fprintf(stderr, "file_regex: %s", line); - free(line); - return false; - } - - while ((rc_getline(&line, &len, fp))) { - char *str = line; - /* some /proc files have \0 separated content so we have to - loop through the 'line' */ - do { - if (regexec(&re, str, 0, NULL, 0) == 0) - goto found; - str += strlen(str) + 1; - /* len is the size of allocated buffer and we don't - want call regexec BUFSIZE times. find next str */ - while (str < line + len && *str == '\0') - str++; - } while (str < line + len); - } - retval = false; -found: - fclose(fp); - free(line); - regfree(&re); - - return retval; -} - -const char *detect_prefix(void) -{ -#ifdef PREFIX - return RC_SYS_PREFIX; -#else - return NULL; -#endif -} - -const char *get_systype(void) -{ - char *systype = rc_conf_value("rc_sys"); - if (systype) { - char *s = systype; - /* Convert to uppercase */ - while (s && *s) { - if (islower((unsigned char) *s)) - *s = toupper((unsigned char) *s); - s++; - } - } - return systype; -} - -const char *detect_container(void) -{ - const char *systype = get_systype(); - -#ifdef __FreeBSD__ - if (systype && strcmp(systype, RC_SYS_JAIL) == 0) - return RC_SYS_JAIL; - int jailed = 0; - size_t len = sizeof(jailed); - - if (sysctlbyname("security.jail.jailed", &jailed, &len, NULL, 0) == 0) - if (jailed == 1) - return RC_SYS_JAIL; -#endif - -#ifdef __linux__ - if (systype) { - if (strcmp(systype, RC_SYS_UML) == 0) - return RC_SYS_UML; - if (strcmp(systype, RC_SYS_VSERVER) == 0) - return RC_SYS_VSERVER; - if (strcmp(systype, RC_SYS_OPENVZ) == 0) - return RC_SYS_OPENVZ; - if (strcmp(systype, RC_SYS_LXC) == 0) - return RC_SYS_LXC; - if (strcmp(systype, RC_SYS_RKT) == 0) - return RC_SYS_RKT; - if (strcmp(systype, RC_SYS_SYSTEMD_NSPAWN) == 0) - return RC_SYS_SYSTEMD_NSPAWN; - if (strcmp(systype, RC_SYS_DOCKER) == 0) - return RC_SYS_DOCKER; - } - if (file_regex("/proc/cpuinfo", "UML")) - return RC_SYS_UML; - else if (file_regex("/proc/self/status", - "(s_context|VxID):[[:space:]]*[1-9]")) - return RC_SYS_VSERVER; - else if (exists("/proc/vz/veinfo") && !exists("/proc/vz/version")) - return RC_SYS_OPENVZ; - else if (file_regex("/proc/self/status", - "envID:[[:space:]]*[1-9]")) - return RC_SYS_OPENVZ; /* old test */ - else if (file_regex("/proc/1/environ", "container=lxc")) - return RC_SYS_LXC; - else if (file_regex("/proc/1/environ", "container=rkt")) - return RC_SYS_RKT; - else if (file_regex("/proc/1/environ", "container=systemd-nspawn")) - return RC_SYS_SYSTEMD_NSPAWN; - else if (file_regex("/proc/1/environ", "container=docker")) - return RC_SYS_DOCKER; -#endif - - return NULL; -} - -const char *detect_vm(void) -{ - const char *systype = get_systype(); - -#ifdef __NetBSD__ - if (systype) { - if(strcmp(systype, RC_SYS_XEN0) == 0) - return RC_SYS_XEN0; - if (strcmp(systype, RC_SYS_XENU) == 0) - return RC_SYS_XENU; - } - if (exists("/kern/xen/privcmd")) - return RC_SYS_XEN0; - if (exists("/kern/xen")) - return RC_SYS_XENU; -#endif - -#ifdef __linux__ - if (systype) { - if (strcmp(systype, RC_SYS_XEN0) == 0) - return RC_SYS_XEN0; - if (strcmp(systype, RC_SYS_XENU) == 0) - return RC_SYS_XENU; - } - if (exists("/proc/xen")) { - if (file_regex("/proc/xen/capabilities", "control_d")) - return RC_SYS_XEN0; - return RC_SYS_XENU; - } -#endif - - return NULL; -} - RC_DEPTREE * _rc_deptree_load(int force, int *regen) { int fd; diff --git a/src/rc/rc.c b/src/rc/rc.c index 87c4913f..0a970b4e 100644 --- a/src/rc/rc.c +++ b/src/rc/rc.c @@ -281,12 +281,8 @@ open_shell(void) struct passwd *pw; #ifdef __linux__ - const char *sys = NULL; + char *sys = get_systype(); - sys = detect_container(); - if (!sys) - sys = detect_vm(); - /* VSERVER and OPENVZ systems cannot really drop to shells */ if (sys && (strcmp(sys, "VSERVER") == 0 || strcmp(sys, "OPENVZ") == 0)) @@ -470,7 +466,7 @@ static void do_sysinit() { struct utsname uts; - const char *sys; + char *sys = get_systype(); /* exec init-early.sh if it exists * This should just setup the console to use the correct @@ -491,9 +487,6 @@ do_sysinit() uts.machine); #endif - sys = detect_container(); - if (!sys) - sys = detect_vm(); if (sys) printf(" [%s]", sys); @@ -509,9 +502,7 @@ do_sysinit() /* init may have mounted /proc so we can now detect or real * sys */ - sys = detect_container(); - if (!sys) - sys = detect_vm(); + sys = get_systype(); if (sys) setenv("RC_SYS", sys, 1); } @@ -832,9 +823,7 @@ int main(int argc, char **argv) eerrorx("%s: %s", applet, strerror(errno)); /* NOTREACHED */ case 'S': - systype = detect_container(); - if (!systype) - systype = detect_vm(); + systype = get_systype(); if (systype) printf("%s\n", systype); exit(EXIT_SUCCESS);