summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Heim <phreak@gentoo.org>2005-12-02 10:56:06 +0000
committerChristian Heim <phreak@gentoo.org>2005-12-02 10:56:06 +0000
commita14ee4ab9b6b622475c9520fb3d08e6f78b08881 (patch)
treeff48cc3f5de2918ab569e3cb391db1ec883a35eb /src/core/src
parentImport the latest baselayout changes. Merging revision 1648. (diff)
downloadbaselayout-vserver-a14ee4ab9b6b622475c9520fb3d08e6f78b08881.tar.gz
baselayout-vserver-a14ee4ab9b6b622475c9520fb3d08e6f78b08881.tar.bz2
baselayout-vserver-a14ee4ab9b6b622475c9520fb3d08e6f78b08881.zip
Import the latest baselayout changes. Merging revision 1658.
svn path=/baselayout-vserver/trunk/; revision=127
Diffstat (limited to 'src/core/src')
-rw-r--r--src/core/src/Makefile.am17
-rw-r--r--src/core/src/depscan.c298
-rw-r--r--src/core/src/runscript.c237
3 files changed, 552 insertions, 0 deletions
diff --git a/src/core/src/Makefile.am b/src/core/src/Makefile.am
new file mode 100644
index 0000000..27d52d9
--- /dev/null
+++ b/src/core/src/Makefile.am
@@ -0,0 +1,17 @@
+sbin_PROGRAMS = \
+ depscan \
+ runscript
+
+INCLUDES = \
+ -I$(top_srcdir) \
+ $(RCSCRIPTS_DEFINES)
+
+LIBRCSCRIPTS = $(top_builddir)/librcscripts/librcscripts.la
+
+depscan_CFLAGS = -DLEGACY_DEPSCAN
+depscan_LDADD = $(LIBRCSCRIPTS)
+depscan_SOURCES = depscan.c
+
+runscript_LDADD = $(LIBRCSCRIPTS) -ldl
+runscript_SOURCES = runscript.c
+
diff --git a/src/core/src/depscan.c b/src/core/src/depscan.c
new file mode 100644
index 0000000..8cc9da8
--- /dev/null
+++ b/src/core/src/depscan.c
@@ -0,0 +1,298 @@
+/*
+ * depscan.c
+ *
+ * Basic frontend for updating the dependency cache.
+ *
+ * Copyright (C) 2004,2005 Martin Schlemmer <azarah@nosferatu.za.org>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Header$
+ */
+
+#include <errno.h>
+#ifndef __KLIBC__
+# include <locale.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "librcscripts/rcscripts.h"
+#include "librcscripts/debug.h"
+#include "librcscripts/depend.h"
+#include "librcscripts/misc.h"
+#include "librcscripts/parse.h"
+
+char* svcdir_subdirs[] = {
+ "softscripts",
+ "snapshot",
+ "options",
+ "started",
+ "starting",
+ "inactive",
+ "stopping",
+ NULL
+};
+
+char *svcdir_volatile_subdirs[] = {
+ "snapshot",
+ "broken",
+ NULL
+};
+
+int create_directory(const char *name);
+int create_var_dirs(const char *svcdir);
+int delete_var_dirs(const char *svcdir);
+
+int create_directory(const char *name) {
+ if ((NULL == name) || (0 == strlen(name))) {
+ DBG_MSG("Invalid argument passed!\n");
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* Check if directory exist, and is not a symlink */
+ if (!is_dir(name, 0)) {
+ if (exists(name)) {
+ /* Remove it if not a directory */
+ if (-1 == unlink(name)) {
+ DBG_MSG("Failed to remove '%s'!\n", name);
+ return -1;
+ }
+ }
+ /* Now try to create the directory */
+ if (-1 == mktree(name, 0755)) {
+ DBG_MSG("Failed to create '%s'!\n", name);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int create_var_dirs(const char *svcdir) {
+ char *tmp_path = NULL;
+ int i = 0;
+
+ if ((NULL == svcdir) || (0 == strlen(svcdir))) {
+ DBG_MSG("Invalid argument passed!\n");
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* Check and create svcdir if needed */
+ if (-1 == create_directory(svcdir)) {
+ DBG_MSG("Failed to create '%s'!\n", svcdir);
+ return -1;
+ }
+
+ while (NULL != svcdir_subdirs[i]) {
+ tmp_path = strcatpaths(svcdir, svcdir_subdirs[i]);
+ if (NULL == tmp_path) {
+ DBG_MSG("Failed to allocate buffer!\n");
+ return -1;
+ }
+
+ /* Check and create all the subdirs if needed */
+ if (-1 == create_directory(tmp_path)) {
+ DBG_MSG("Failed to create '%s'!\n", tmp_path);
+ free(tmp_path);
+ return -1;
+ }
+
+ free(tmp_path);
+ i++;
+ }
+
+ return 0;
+}
+
+int delete_var_dirs(const char *svcdir) {
+ char *tmp_path = NULL;
+ int i = 0;
+
+ if ((NULL == svcdir) || (0 == strlen(svcdir))) {
+ DBG_MSG("Invalid argument passed!\n");
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* Just quit if svcdir do not exist */
+ if (!exists(svcdir)) {
+ DBG_MSG("'%s' does not exist!\n", svcdir);
+ return 0;
+ }
+
+ while (NULL != svcdir_volatile_subdirs[i]) {
+ tmp_path = strcatpaths(svcdir, svcdir_volatile_subdirs[i]);
+ if (NULL == tmp_path) {
+ DBG_MSG("Failed to allocate buffer!\n");
+ return -1;
+ }
+
+ /* Skip the directory if it does not exist */
+ if (!exists(tmp_path))
+ goto _continue;
+
+ /* Check and delete all files and sub directories if needed */
+ if (-1 == rmtree(tmp_path)) {
+ DBG_MSG("Failed to delete '%s'!\n", tmp_path);
+ free(tmp_path);
+ return -1;
+ }
+
+_continue:
+ free(tmp_path);
+ i++;
+ }
+
+ return 0;
+}
+
+#if defined(LEGACY_DEPSCAN)
+
+int main() {
+ FILE *cachefile_fd = NULL;
+ char *data = NULL;
+ char *svcdir = NULL;
+ char *cachefile = NULL;
+ char *tmp_cachefile = NULL;
+ int tmp_cachefile_fd = 0;
+ int datasize = 0;
+
+ /* Make sure we do not run into locale issues */
+#ifndef __KLIBC__
+ setlocale (LC_ALL, "C");
+#endif
+
+ if (0 != getuid()) {
+ EERROR("Must be root!\n");
+ exit(EXIT_FAILURE);
+ }
+
+ svcdir = get_cnf_entry(RC_CONFD_FILE_NAME, SVCDIR_CONFIG_ENTRY);
+ if (NULL == svcdir) {
+ EERROR("Failed to get config entry '%s'!\n",
+ SVCDIR_CONFIG_ENTRY);
+ exit(EXIT_FAILURE);
+ }
+
+ /* Delete (if needed) volatile directories in svcdir */
+ if (-1 == delete_var_dirs(svcdir)) {
+ /* XXX: Not 100% accurate below message ... */
+ EERROR("Failed to delete '%s', %s", svcdir,
+ "or one of its sub directories!\n");
+ exit(EXIT_FAILURE);
+ }
+
+ /* Create all needed directories in svcdir */
+ if (-1 == create_var_dirs(svcdir)) {
+ EERROR("Failed to create '%s', %s", svcdir,
+ "or one of its sub directories!\n");
+ exit(EXIT_FAILURE);
+ }
+
+ cachefile = strcatpaths(svcdir, LEGACY_CACHE_FILE_NAME);
+ if (NULL == cachefile) {
+ DBG_MSG("Failed to allocate buffer!\n");
+ exit(EXIT_FAILURE);
+ }
+
+ tmp_cachefile = strcatpaths(cachefile, "XXXXXX");
+ if (NULL == tmp_cachefile) {
+ DBG_MSG("Failed to allocate buffer!\n");
+ exit(EXIT_FAILURE);
+ }
+ /* Replace the "/XXXXXX" with ".XXXXXX"
+ * Yes, I am lazy. */
+ tmp_cachefile[strlen(tmp_cachefile) - strlen(".XXXXXX")] = '.';
+
+ if (-1 == get_rcscripts()) {
+ EERROR("Failed to get rc-scripts list!\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if (-1 == check_rcscripts_mtime(cachefile)) {
+ EINFO("Caching service dependencies ...\n");
+ DBG_MSG("Regenerating cache file '%s'.\n", cachefile);
+
+ datasize = generate_stage2(&data);
+ if (-1 == datasize) {
+ EERROR("Failed to generate stage2!\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if (-1 == parse_cache(data, datasize)) {
+ EERROR("Failed to parse stage2 output!\n");
+ free(data);
+ exit(EXIT_FAILURE);
+ }
+
+#if 0
+ tmp_cachefile_fd = open("foo", O_CREAT | O_TRUNC | O_RDWR, 0600);
+ write(tmp_cachefile_fd, data, datasize);
+ close(tmp_cachefile_fd);
+#endif
+
+ free(data);
+
+ if (-1 == service_resolve_dependencies()) {
+ EERROR("Failed to resolve dependencies!\n");
+ exit(EXIT_FAILURE);
+ }
+
+#ifndef __KLIBC__
+ tmp_cachefile_fd = mkstemp(tmp_cachefile);
+#else
+ /* FIXME: Need to add a mkstemp implementation for klibc */
+ tmp_cachefile_fd = open(tmp_cachefile, O_CREAT | O_TRUNC | O_RDWR, 0600);
+#endif
+ if (-1 == tmp_cachefile_fd) {
+ EERROR("Could not open temporary file for writing!\n");
+ exit(EXIT_FAILURE);
+ }
+ cachefile_fd = fdopen(tmp_cachefile_fd, "w");
+ if (NULL == cachefile_fd) {
+ EERROR("Could not open temporary file for writing!\n");
+ exit(EXIT_FAILURE);
+ }
+
+ write_legacy_stage3(cachefile_fd);
+ fclose(cachefile_fd);
+
+ if ((-1 == unlink(cachefile)) && (exists(cachefile))) {
+ EERROR("Could not remove '%s'!\n", cachefile);
+ unlink(tmp_cachefile);
+ exit(EXIT_FAILURE);
+ }
+
+ if (-1 == rename(tmp_cachefile, cachefile)) {
+ EERROR("Could not move temporary file to '%s'!\n",
+ cachefile);
+ unlink(tmp_cachefile);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ exit(EXIT_SUCCESS);
+}
+
+#endif
+
diff --git a/src/core/src/runscript.c b/src/core/src/runscript.c
new file mode 100644
index 0000000..dc3ba51
--- /dev/null
+++ b/src/core/src/runscript.c
@@ -0,0 +1,237 @@
+/*
+ * runscript.c
+ * Handle launching of Gentoo init scripts.
+ *
+ * Copyright 1999-2004 Gentoo Foundation
+ * Distributed under the terms of the GNU General Public License v2
+ * $Header$
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <dlfcn.h>
+
+#include "librcscripts/rcscripts.h"
+#include "librcscripts/debug.h"
+#include "librcscripts/misc.h"
+
+#define IS_SBIN_RC() ((caller) && (0 == strcmp(caller, SBIN_RC)))
+
+static void (*selinux_run_init_old) (void);
+static void (*selinux_run_init_new) (int argc, char **argv);
+
+extern char **environ;
+
+void setup_selinux(int argc, char **argv) {
+ void *lib_handle = NULL;
+
+ lib_handle = dlopen(SELINUX_LIB, RTLD_NOW | RTLD_GLOBAL);
+ if (NULL != lib_handle) {
+ selinux_run_init_old = dlsym(lib_handle, "selinux_runscript");
+ selinux_run_init_new = dlsym(lib_handle, "selinux_runscript2");
+
+ /* Use new run_init if it exists, else fall back to old */
+ if (NULL != selinux_run_init_new)
+ selinux_run_init_new(argc, argv);
+ else if (NULL != selinux_run_init_old)
+ selinux_run_init_old();
+ else {
+ /* This shouldnt happen... probably corrupt lib */
+ fprintf(stderr, "Run_init is missing from runscript_selinux.so!\n");
+ exit(127);
+ }
+ }
+}
+
+char **get_whitelist(char **whitelist, char *filename) {
+ char *buf = NULL;
+ char *tmp_buf = NULL;
+ char *tmp_p = NULL;
+ char *token = NULL;
+ size_t lenght = 0;
+ int count = 0;
+ int current = 0;
+
+ if (-1 == file_map(filename, &buf, &lenght))
+ return NULL;
+
+ while (current < lenght) {
+ count = buf_get_line(buf, lenght, current);
+
+ tmp_buf = strndup(&buf[current], count);
+ if (NULL == tmp_buf) {
+ DBG_MSG("Failed to allocate temporary buffer!\n");
+ goto error;
+ }
+ tmp_p = tmp_buf;
+
+ /* Strip leading spaces/tabs */
+ while ((tmp_p[0] == ' ') || (tmp_p[0] == '\t'))
+ tmp_p++;
+
+ /* Get entry - we do not want comments, and only the first word
+ * on a line is valid */
+ token = strsep(&tmp_p, "# \t");
+ if (NULL != token && '\0' != token[0]) {
+ tmp_p = strndup(token, strlen(token));
+ STRING_LIST_ADD(whitelist, tmp_p, error);
+ }
+
+ current += count + 1;
+ free(tmp_buf);
+ /* Set to NULL in case we error out above and have
+ * to free below */
+ tmp_buf = NULL;
+ }
+
+
+ file_unmap(buf, lenght);
+
+ return whitelist;
+
+error:
+ if (NULL != tmp_buf)
+ free(tmp_buf);
+ file_unmap(buf, lenght);
+ STRING_LIST_FREE(whitelist);
+
+ return NULL;
+}
+
+char **filter_environ(char *caller) {
+ char **myenv = NULL;
+ char **whitelist = NULL;
+ char *env_name = NULL;
+ int check_profile = 1;
+ int count = 0;
+
+ if (NULL != getenv(SOFTLEVEL) && !IS_SBIN_RC())
+ /* Called from /sbin/rc, but not /sbin/rc itself, so current
+ * environment should be fine */
+ return environ;
+
+ if (1 == is_file(SYS_WHITELIST, 1))
+ whitelist = get_whitelist(whitelist, SYS_WHITELIST);
+ else
+ EWARN("System environment whitelist missing!\n");
+
+ if (1 == is_file(USR_WHITELIST, 1))
+ whitelist = get_whitelist(whitelist, USR_WHITELIST);
+
+ if (NULL == whitelist)
+ /* If no whitelist is present, revert to old behaviour */
+ return environ;
+
+ if (1 != is_file(PROFILE_ENV, 1))
+ /* XXX: Maybe warn here? */
+ check_profile = 0;
+
+ STRING_LIST_FOR_EACH(whitelist, env_name, count) {
+ char *env_var = NULL;
+ char *tmp_p = NULL;
+ int env_len = 0;
+
+ env_var = getenv(env_name);
+ if (NULL != env_var)
+ goto add_entry;
+
+ if (1 == check_profile) {
+ char *tmp_env_name = NULL;
+ int tmp_len = 0;
+
+ /* The entries in PROFILE_ENV is of the form:
+ * export VAR_NAME=value */
+ tmp_len = strlen(env_name) + strlen("export ") + 1;
+ tmp_env_name = calloc(tmp_len, sizeof(char *));
+ if (NULL == tmp_env_name) {
+ DBG_MSG("Failed to allocate temporary buffer!\n");
+ goto error;
+ }
+ snprintf(tmp_env_name, tmp_len, "export %s", env_name);
+
+ /* Clear errno so that subsequent calls do not trigger
+ * DBG_MSG */
+ errno = 0;
+ env_var = get_cnf_entry(PROFILE_ENV, tmp_env_name);
+ free(tmp_env_name);
+ if (NULL == env_var && ENOMSG != errno)
+ goto error;
+ else if (NULL != env_var)
+ goto add_entry;
+ }
+
+ continue;
+
+add_entry:
+ env_len = strlen(env_name) + strlen(env_var) + 2;
+ tmp_p = calloc(env_len, sizeof(char *));
+ if (NULL == tmp_p) {
+ DBG_MSG("Failed to allocate temporary buffer!\n");
+ goto error;
+ }
+ snprintf(tmp_p, env_len, "%s=%s", env_name, env_var);
+ STRING_LIST_ADD(myenv, tmp_p, error);
+ }
+
+ STRING_LIST_FREE(whitelist);
+
+ if (NULL == myenv)
+ /* If all else fails, just add a default PATH */
+ STRING_LIST_ADD(myenv, strdup(DEFAULT_PATH), error);
+
+ return myenv;
+
+error:
+ STRING_LIST_FREE(myenv);
+ STRING_LIST_FREE(whitelist);
+
+ return NULL;
+}
+
+int main(int argc, char *argv[]) {
+ char *myargs[32];
+ char **myenv = NULL;
+ char *caller = argv[1];
+ int new = 1;
+
+ /* Need to be /bin/bash, else BASH is invalid */
+ myargs[0] = "/bin/bash";
+ while (argv[new] != 0) {
+ myargs[new] = argv[new];
+ new++;
+ }
+ myargs[new] = NULL;
+
+ /* Do not do help for /sbin/rc */
+ if (argc < 3 && !IS_SBIN_RC()) {
+ execv(RCSCRIPT_HELP, myargs);
+ exit(1);
+ }
+
+ /* Setup a filtered environment according to the whitelist */
+ myenv = filter_environ(caller);
+ if (NULL == myenv) {
+ EWARN("%s: Failed to filter the environment!\n", caller);
+ /* XXX: Might think to bail here, but it could mean the system
+ * is rendered unbootable, so rather not */
+ myenv = environ;
+ }
+
+ /* Ok, we are ready to go, so setup selinux if applicable */
+ setup_selinux(argc, argv);
+
+ if (!IS_SBIN_RC()) {
+ if (execve("/sbin/runscript.sh", myargs, myenv) < 0)
+ exit(1);
+ } else {
+ if (execve("/bin/bash", myargs, myenv) < 0)
+ exit(1);
+ }
+
+ return 0;
+}