sysinit is now a real runlevel that handles things like udev, dmesg and

mounting various bits in /dev and /sys.
init.sh JUST mounts /lib/rc/init.d (and /proc for Linux systems)
To make development of this easier we now return an empty RC_STRINGLIST
instead of a NULL for empty things.

If you don't have a udev init script installed, don't reboot your box OR
roll back to an older OpenRC version.
This commit is contained in:
Roy Marples
2008-10-10 08:37:21 +00:00
parent 247766695c
commit d6da8e8c48
23 changed files with 777 additions and 926 deletions

View File

@@ -48,7 +48,8 @@
extern const char *applet;
RC_DEPTREE *_rc_deptree_load(int *regen) {
RC_DEPTREE *
_rc_deptree_load(int *regen) {
int fd;
int retval;
int serrno = errno;
@@ -65,12 +66,10 @@ RC_DEPTREE *_rc_deptree_load(int *regen) {
if (regen)
*regen = 1;
ebegin("Caching service dependencies");
retval = rc_deptree_update();
eend (retval ? 0 : -1, "Failed to update the dependency tree");
}
return rc_deptree_load();
}
@@ -96,7 +95,8 @@ static const char * const longopts_help[] = {
};
#include "_usage.c"
int rc_depend(int argc, char **argv)
int
rc_depend(int argc, char **argv)
{
RC_STRINGLIST *list;
RC_STRINGLIST *types;
@@ -112,7 +112,6 @@ int rc_depend(int argc, char **argv)
char *token;
types = rc_stringlist_new();
while ((opt = getopt_long(argc, argv, getoptstring,
longopts, (int *) 0)) != -1)
{
@@ -145,14 +144,14 @@ int rc_depend(int argc, char **argv)
ebegin("Caching service dependencies");
update = rc_deptree_update();
eend(update ? 0 : -1, "%s: %s", applet, strerror(errno));
if (! update)
if (!update)
eerrorx("Failed to update the dependency tree");
}
if (! (deptree = _rc_deptree_load(NULL)))
if (!(deptree = _rc_deptree_load(NULL)))
eerrorx("failed to load deptree");
if (! runlevel)
if (!runlevel)
runlevel = rc_runlevel_get();
services = rc_stringlist_new();
@@ -161,8 +160,9 @@ int rc_depend(int argc, char **argv)
rc_stringlist_add(list, argv[optind]);
errno = 0;
depends = rc_deptree_depends(deptree, NULL, list, runlevel, 0);
if (! depends && errno == ENOENT)
eerror("no dependency info for service `%s'", argv[optind]);
if (!depends && errno == ENOENT)
eerror("no dependency info for service `%s'",
argv[optind]);
else
rc_stringlist_add(services, argv[optind]);
@@ -170,7 +170,7 @@ int rc_depend(int argc, char **argv)
rc_stringlist_free(list);
optind++;
}
if (! TAILQ_FIRST(services)) {
if (!TAILQ_FIRST(services)) {
rc_stringlist_free(services);
rc_stringlist_free(types);
rc_deptree_free(deptree);
@@ -181,12 +181,13 @@ int rc_depend(int argc, char **argv)
}
/* If we don't have any types, then supply some defaults */
if (! TAILQ_FIRST(types)) {
if (!TAILQ_FIRST(types)) {
rc_stringlist_add(types, "ineed");
rc_stringlist_add(types, "iuse");
}
depends = rc_deptree_depends(deptree, types, services, runlevel, options);
depends = rc_deptree_depends(deptree, types, services,
runlevel, options);
if (TAILQ_FIRST(depends)) {
TAILQ_FOREACH(s, depends, entries) {

View File

@@ -62,13 +62,15 @@ static RC_STRINGLIST *rc_conf = NULL;
extern char** environ;
#ifdef DEBUG_MEMORY
static void _free_rc_conf(void)
static void
_free_rc_conf(void)
{
rc_stringlist_free(rc_conf);
}
#endif
char *rc_conf_value(const char *setting)
char *
rc_conf_value(const char *setting)
{
RC_STRINGLIST *old;
RC_STRING *s;
@@ -83,31 +85,28 @@ char *rc_conf_value(const char *setting)
/* Support old configs */
if (exists(RC_CONF_OLD)) {
old = rc_config_load(RC_CONF_OLD);
if (old) {
if (rc_conf) {
TAILQ_CONCAT(rc_conf, old, entries);
free(old);
} else
rc_conf = old;
}
TAILQ_CONCAT(rc_conf, old, entries);
#ifdef DEBUG_MEMORY
free(old);
#endif
}
/* Convert old uppercase to lowercase */
if (rc_conf)
TAILQ_FOREACH(s, rc_conf, entries) {
p = s->value;
while (p && *p && *p != '=') {
if (isupper((unsigned char)*p))
*p = tolower((unsigned char)*p);
p++;
}
TAILQ_FOREACH(s, rc_conf, entries) {
p = s->value;
while (p && *p && *p != '=') {
if (isupper((unsigned char)*p))
*p = tolower((unsigned char)*p);
p++;
}
}
}
return rc_config_value(rc_conf, setting);
}
bool rc_conf_yesno(const char *setting)
bool
rc_conf_yesno(const char *setting)
{
return rc_yesno(rc_conf_value (setting));
}
@@ -122,10 +121,11 @@ static const char *const env_whitelist[] = {
NULL
};
void env_filter(void)
void
env_filter(void)
{
RC_STRINGLIST *env_allow;
RC_STRINGLIST *profile = NULL;
RC_STRINGLIST *profile;
RC_STRINGLIST *env_list;
RC_STRING *env;
char *e;
@@ -133,8 +133,7 @@ void env_filter(void)
/* Add the user defined list of vars */
env_allow = rc_stringlist_split(rc_conf_value("rc_env_allow"), " ");
if (exists(PROFILE_ENV))
profile = rc_config_load(PROFILE_ENV);
profile = rc_config_load(PROFILE_ENV);
/* Copy the env and work from this so we can manipulate it safely */
env_list = rc_stringlist_new();
@@ -163,21 +162,22 @@ void env_filter(void)
}
/* Now add anything missing from the profile */
if (profile) {
TAILQ_FOREACH(env, profile, entries) {
e = strchr(env->value, '=');
*e = '\0';
if (!getenv(env->value))
setenv(env->value, e + 1, 1);
}
TAILQ_FOREACH(env, profile, entries) {
e = strchr(env->value, '=');
*e = '\0';
if (!getenv(env->value))
setenv(env->value, e + 1, 1);
}
#ifdef DEBUG_MEMORY
rc_stringlist_free(env_list);
rc_stringlist_free(env_allow);
rc_stringlist_free(profile);
#endif
}
void env_config(void)
void
env_config(void)
{
size_t pplen = strlen(PATH_PREFIX);
char *path;
@@ -203,7 +203,8 @@ void env_config(void)
e = p = xmalloc(sizeof(char) * l);
p += snprintf(p, l, "%s", PATH_PREFIX);
/* Now go through the env var and only add bits not in our PREFIX */
/* Now go through the env var and only add bits not in our
* PREFIX */
while ((token = strsep(&path, ":"))) {
np = npp = xstrdup(PATH_PREFIX);
while ((tok = strsep(&npp, ":")))
@@ -259,48 +260,8 @@ void env_config(void)
setenv("EINFO_COLOR", "NO", 1);
}
bool service_plugable(const char *service)
{
char *list;
char *p;
char *star;
char *token;
bool allow = true;
char *match = rc_conf_value("rc_plug_services");
bool truefalse;
if (! match)
return true;
list = xstrdup(match);
p = list;
while ((token = strsep(&p, " "))) {
if (token[0] == '!') {
truefalse = false;
token++;
} else
truefalse = true;
star = strchr(token, '*');
if (star) {
if (strncmp(service, token, (size_t)(star - token)) == 0)
{
allow = truefalse;
break;
}
} else {
if (strcmp(service, token) == 0) {
allow = truefalse;
break;
}
}
}
free(list);
return allow;
}
int signal_setup(int sig, void (*handler)(int))
int
signal_setup(int sig, void (*handler)(int))
{
struct sigaction sa;
@@ -310,7 +271,8 @@ int signal_setup(int sig, void (*handler)(int))
return sigaction(sig, &sa, NULL);
}
pid_t exec_service(const char *service, const char *arg)
pid_t
exec_service(const char *service, const char *arg)
{
char *file;
char fifo[PATH_MAX];
@@ -320,7 +282,7 @@ pid_t exec_service(const char *service, const char *arg)
struct sigaction sa;
file = rc_service_resolve(service);
if (! exists(file)) {
if (!exists(file)) {
rc_service_mark(service, RC_SERVICE_STOPPED);
free(file);
return 0;
@@ -368,7 +330,6 @@ pid_t exec_service(const char *service, const char *arg)
sigprocmask(SIG_SETMASK, &old, NULL);
free(file);
return pid;
}

View File

@@ -58,7 +58,8 @@ static const char * const longopts_help[] = {
};
#include "_usage.c"
int rc_service(int argc, char **argv)
int
rc_service(int argc, char **argv)
{
int opt;
char *service;
@@ -75,17 +76,21 @@ int rc_service(int argc, char **argv)
case 'e':
service = rc_service_resolve(optarg);
opt = service ? EXIT_SUCCESS : EXIT_FAILURE;
#ifdef DEBUG_MEMORY
free(service);
#endif
return opt;
/* NOTREACHED */
case 'l':
list = rc_services_in_runlevel(NULL);
if (! list)
if (!TAILQ_FIRST(list))
return EXIT_FAILURE;
rc_stringlist_sort(&list);
TAILQ_FOREACH(s, list, entries)
printf("%s\n", s->value);
#ifdef DEBUG_MEMORY
rc_stringlist_free(list);
#endif
return EXIT_SUCCESS;
/* NOTREACHED */
case 'r':
@@ -93,7 +98,9 @@ int rc_service(int argc, char **argv)
if (!service)
return EXIT_FAILURE;
printf("%s\n", service);
#ifdef DEBUG_MEMORY
free(service);
#endif
return EXIT_SUCCESS;
/* NOTREACHED */
@@ -103,13 +110,10 @@ int rc_service(int argc, char **argv)
argc -= optind;
argv += optind;
if (!*argv)
eerrorx("%s: you need to specify a service", applet);
if (!(service = rc_service_resolve(*argv)))
eerrorx("%s: service `%s' does not exist", applet, *argv);
*argv = service;
execv(*argv, argv);
eerrorx("%s: %s", applet, strerror(errno));

View File

@@ -43,12 +43,6 @@ const char rc_copyright[] = "Copyright (c) 2007-2008 Roy Marples";
#include <sys/utsname.h>
#include <sys/wait.h>
/* So we can coldplug net devices */
#ifdef BSD
# include <sys/socket.h>
# include <ifaddrs.h>
#endif
#ifdef __linux__
# include <asm/setup.h> /* for COMMAND_LINE_SIZE */
#endif
@@ -519,115 +513,10 @@ static void handle_signal(int sig)
errno = serrno;
}
static void do_coldplug(void)
{
size_t l;
DIR *dp;
struct dirent *d;
char *service;
RC_STRING *s;
#ifdef BSD
struct ifaddrs *ifap;
struct ifaddrs *ifa;
char *p;
#endif
errno = 0;
if (!rc_conf_yesno("rc_coldplug") && errno != ENOENT)
return;
/* We need to ensure our state dirs exist.
* We should have a better call than this, but oh well. */
rc_deptree_update_needed();
#ifdef BSD
if (getifaddrs(&ifap) == 0) {
for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
if (ifa->ifa_addr->sa_family != AF_LINK)
continue;
l = strlen("net.") + strlen(ifa->ifa_name) + 1;
service = xmalloc(sizeof (char) * l);
snprintf(service, l, "net.%s", ifa->ifa_name);
if (rc_service_exists(service) &&
service_plugable(service))
rc_service_mark(service, RC_SERVICE_COLDPLUGGED);
free(service);
}
freeifaddrs (ifap);
}
/* The mice are a little more tricky.
* If we coldplug anything else, we'll probably do it here. */
if ((dp = opendir("/dev"))) {
while ((d = readdir(dp))) {
if (strncmp(d->d_name, "psm", 3) == 0 ||
strncmp(d->d_name, "ums", 3) == 0)
{
p = d->d_name + 3;
if (p && isdigit((unsigned char)*p)) {
l = strlen("moused.") + strlen(d->d_name) + 1;
service = xmalloc(sizeof(char) * l);
snprintf (service, l, "moused.%s", d->d_name);
if (rc_service_exists (service) &&
service_plugable (service))
rc_service_mark (service, RC_SERVICE_COLDPLUGGED);
free(service);
}
}
}
closedir (dp);
}
#else
/* udev likes to start services before we're ready when it does
* its coldplugging thing. runscript knows when we're not ready so it
* stores a list of coldplugged services in DEVBOOT for us to pick up
* here when we are ready for them */
if ((dp = opendir(DEVBOOT))) {
while ((d = readdir(dp))) {
if (d->d_name[0] == '.' &&
(d->d_name[1] == '\0' ||
(d->d_name[1] == '.' && d->d_name[2] == '\0')))
continue;
if (rc_service_exists(d->d_name) &&
service_plugable(d->d_name))
rc_service_mark(d->d_name, RC_SERVICE_COLDPLUGGED);
l = strlen(DEVBOOT "/") + strlen(d->d_name) + 1;
service = xmalloc(sizeof (char) * l);
snprintf(service, l, DEVBOOT "/%s", d->d_name);
if (unlink(service))
eerror("%s: unlink `%s': %s", applet, service,
strerror(errno));
free(service);
}
closedir(dp);
rmdir(DEVBOOT);
}
#endif
if (rc_yesno(getenv("EINFO_QUIET")))
return;
/* Load our list of coldplugged services and display them */
einfon("Device initiated services:%s", ecolor(ECOLOR_HILITE));
coldplugged_services = rc_services_in_state(RC_SERVICE_COLDPLUGGED);
if (coldplugged_services)
TAILQ_FOREACH(s, coldplugged_services, entries)
printf(" %s", s->value);
printf("%s\n", ecolor(ECOLOR_NORMAL));
}
static void do_newlevel(const char *newlevel)
{
struct utsname uts;
const char *sys;
#ifdef __linux__
char *cmd;
#endif
if (strcmp(newlevel, RC_LEVEL_SYSINIT) == 0
#ifndef PREFIX
@@ -669,39 +558,13 @@ static void do_newlevel(const char *newlevel)
ecolor(ECOLOR_GOOD), ecolor(ECOLOR_NORMAL));
setenv("RC_RUNLEVEL", newlevel, 1);
rc_plugin_run(RC_HOOK_RUNLEVEL_START_IN, newlevel);
hook_out = RC_HOOK_RUNLEVEL_START_OUT;
run_program(INITSH);
#ifdef __linux__
/* If we requested a runlevel, save it now */
if ((cmd = proc_getent("rc_runlevel"))) {
set_krunlevel(cmd);
free(cmd);
} else if ((cmd = proc_getent("softlevel"))) {
set_krunlevel(cmd);
free(cmd);
} else
set_krunlevel(NULL);
#endif
/* Setup our coldplugged services now */
do_coldplug();
rc_plugin_run(RC_HOOK_RUNLEVEL_START_OUT, newlevel);
hook_out = 0;
if (want_interactive())
mark_interactive();
exit(EXIT_SUCCESS);
} else if (strcmp(newlevel, RC_LEVEL_SINGLE) == 0) {
#ifndef PREFIX
if (! RUNLEVEL ||
(strcmp(RUNLEVEL, "S") != 0 &&
strcmp(RUNLEVEL, "1") != 0))
{
/* Remember the current runlevel for when we come back */
set_krunlevel(runlevel);
single_user();
}
@@ -883,7 +746,12 @@ interactive_option:
if (! parallel) {
rc_waitpid(pid);
remove_pid(pid);
/* Attempt to open the logger as a service may
* mount the needed /dev/pts for this to work */
if (rc_logger_tty == -1)
rc_logger_open(runlevel);
}
}
}
@@ -1076,7 +944,8 @@ int main(int argc, char **argv)
{
/* Try not to join boot and krunlevels together */
if (! newlevel ||
strcmp(newlevel, getenv("RC_BOOTLEVEL")) != 0)
(strcmp(newlevel, getenv("RC_BOOTLEVEL")) != 0 &&
strcmp(newlevel, RC_LEVEL_SYSINIT) != 0))
if (get_krunlevel(krunlevel, sizeof(krunlevel)))
newlevel = krunlevel;
} else if (! RUNLEVEL ||
@@ -1135,21 +1004,11 @@ int main(int argc, char **argv)
* correct order for stopping them */
stop_services = rc_services_in_state(RC_SERVICE_STARTED);
tmplist = rc_services_in_state(RC_SERVICE_INACTIVE);
if (tmplist) {
if (stop_services) {
TAILQ_CONCAT(stop_services, tmplist, entries);
free(tmplist);
} else
stop_services = tmplist;
}
TAILQ_CONCAT(stop_services, tmplist, entries);
free(tmplist);
tmplist = rc_services_in_state(RC_SERVICE_STARTING);
if (tmplist) {
if (stop_services) {
TAILQ_CONCAT(stop_services, tmplist, entries);
free(tmplist);
} else
stop_services = tmplist;
}
TAILQ_CONCAT(stop_services, tmplist, entries);
free(tmplist);
if (stop_services)
rc_stringlist_sort(&stop_services);
@@ -1171,24 +1030,30 @@ int main(int argc, char **argv)
strcmp(newlevel ? newlevel : runlevel, RC_LEVEL_SHUTDOWN) != 0 &&
strcmp(newlevel ? newlevel : runlevel, RC_LEVEL_REBOOT) != 0)
{
/* We need to include the boot runlevel services if we're not in it */
start_services = rc_services_in_runlevel(bootlevel);
if (strcmp (newlevel ? newlevel : runlevel, bootlevel) != 0) {
tmplist = rc_services_in_runlevel(newlevel ? newlevel : runlevel);
if (tmplist) {
if (start_services) {
TAILQ_CONCAT(start_services, tmplist, entries);
free(tmplist);
} else
start_services = tmplist;
start_services = rc_services_in_runlevel(RC_LEVEL_SYSINIT);
if (strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_SYSINIT)
!= 0)
{
/* We need to include the boot runlevel services */
tmplist = rc_services_in_runlevel(bootlevel);
TAILQ_CONCAT(start_services, tmplist, entries);
free(tmplist);
if (strcmp (newlevel ? newlevel : runlevel, bootlevel)
!= 0)
{
tmplist = rc_services_in_runlevel(newlevel ?
newlevel :
runlevel);
TAILQ_CONCAT(start_services, tmplist, entries);
free(tmplist);
}
}
if (coldplugged_services) {
if (!start_services)
start_services = rc_stringlist_new();
TAILQ_FOREACH(service, coldplugged_services, entries)
rc_stringlist_addu(start_services, service->value);
if (coldplugged_services) {
if (!start_services)
start_services = rc_stringlist_new();
TAILQ_FOREACH(service, coldplugged_services, entries)
rc_stringlist_addu(start_services, service->value);
}
}
}
@@ -1265,14 +1130,15 @@ int main(int argc, char **argv)
if (start_services) {
do_start_services(parallel);
/* FIXME: If we skip the boot runlevel and go straight
* to default from sysinit, we should now re-evaluate our
* start services + coldplugged services and call
* do_start_services a second time. */
/* Wait for our services to finish */
wait_for_services();
}
rc_plugin_run(RC_HOOK_RUNLEVEL_START_OUT, runlevel);
hook_out = 0;
#ifdef __linux__
/* mark any services skipped as stopped */
if (PREVLEVEL && strcmp(PREVLEVEL, "N") == 0) {
@@ -1285,12 +1151,15 @@ int main(int argc, char **argv)
}
#endif
rc_plugin_run(RC_HOOK_RUNLEVEL_START_OUT, runlevel);
hook_out = 0;
/* If we're in the boot runlevel and we regenerated our dependencies
* we need to delete them so that they are regenerated again in the
* default runlevel as they may depend on things that are now available */
* default runlevel as they may depend on things that are now
* available */
if (regen && strcmp(runlevel, bootlevel) == 0)
unlink(RC_DEPTREE_CACHE);
return EXIT_SUCCESS;
}

File diff suppressed because it is too large Load Diff