diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile | 4 | ||||
-rw-r--r-- | src/builtins.h | 4 | ||||
-rw-r--r-- | src/librc-daemon.c | 64 | ||||
-rw-r--r-- | src/librc-depend.c | 158 | ||||
-rw-r--r-- | src/librc-misc.c | 90 | ||||
-rw-r--r-- | src/librc.c | 97 | ||||
-rw-r--r-- | src/librc.h | 16 | ||||
-rw-r--r-- | src/rc-depend.c | 27 | ||||
-rw-r--r-- | src/rc.c | 10 | ||||
-rw-r--r-- | src/rc.h | 30 | ||||
-rw-r--r-- | src/runscript.c | 26 |
11 files changed, 230 insertions, 296 deletions
diff --git a/src/Makefile b/src/Makefile index f57cf901..a607e70a 100644 --- a/src/Makefile +++ b/src/Makefile @@ -54,12 +54,12 @@ LDLIBS_LIBEINFO = $(LDLIBS) LIBRCSOVER = 0 LIBRCSO = librc.so.$(LIBRCSOVER) LIBRCOBJS = librc.o librc-depend.o librc-daemon.o librc-misc.o librc-strlist.o -LDLIBS_LIBRC = -leinfo +LDLIBS_LIBRC = RCOBJS = checkown.o env-update.o fstabinfo.o mountinfo.o \ rc-depend.o rc-plugin.o rc-status.o rc-update.o runscript.o \ start-stop-daemon.o rc.o -LDLIBS_RC = $(LDLIBS_LIBRC) -lrc -lutil +LDLIBS_RC = $(LDLIBS_LIBRC) -leinfo -lrc -lutil LIB_TARGETS = $(LIBEINFOSO) $(LIBRCSO) SBIN_TARGETS = rc diff --git a/src/builtins.h b/src/builtins.h index c234ad83..9c420e29 100644 --- a/src/builtins.h +++ b/src/builtins.h @@ -7,6 +7,8 @@ * Released under the GPLv2 */ +#include "rc.h" + int checkown (int argc, char **argv); int env_update (int argc, char **argv); int fstabinfo (int argc, char **argv); @@ -17,3 +19,5 @@ int rc_update (int argc, char **argv); int runscript (int argc, char **argv); int start_stop_daemon (int argc, char **argv); +/* Handy function so we can wrap einfo around our deptree */ +rc_depinfo_t *_rc_deptree_load (void); diff --git a/src/librc-daemon.c b/src/librc-daemon.c index 5b1e0239..d9b68b08 100644 --- a/src/librc-daemon.c +++ b/src/librc-daemon.c @@ -79,16 +79,16 @@ pid_t *rc_find_pids (const char *exec, const char *cmd, DIR *procdir; struct dirent *entry; int npids = 0; - int foundany = false; pid_t p; pid_t *pids = NULL; + pid_t *tmp = NULL; char buffer[PATH_MAX]; struct stat sb; pid_t runscript_pid = 0; char *pp; if ((procdir = opendir ("/proc")) == NULL) - eerrorx ("opendir `/proc': %s", strerror (errno)); + return (NULL); /* We never match RC_RUNSCRIPT_PID if present so we avoid the below @@ -109,7 +109,6 @@ pid_t *rc_find_pids (const char *exec, const char *cmd, while ((entry = readdir (procdir)) != NULL) { if (sscanf (entry->d_name, "%d", &p) != 1) continue; - foundany = true; if (runscript_pid != 0 && runscript_pid == p) continue; @@ -129,9 +128,14 @@ pid_t *rc_find_pids (const char *exec, const char *cmd, if (exec && ! cmd && ! pid_is_exec (p, exec)) continue; - pids = realloc (pids, sizeof (pid_t) * (npids + 2)); - if (! pids) - eerrorx ("memory exhausted"); + tmp = realloc (pids, sizeof (pid_t) * (npids + 2)); + if (! tmp) { + free (pids); + closedir (procdir); + errno = ENOMEM; + return (NULL); + } + pids = tmp; pids[npids] = p; pids[npids + 1] = 0; @@ -139,9 +143,6 @@ pid_t *rc_find_pids (const char *exec, const char *cmd, } closedir (procdir); - if (! foundany) - eerrorx ("nothing in /proc"); - return (pids); } librc_hidden_def(rc_find_pids) @@ -177,6 +178,7 @@ pid_t *rc_find_pids (const char *exec, const char *cmd, int argc = 0; char **argv; pid_t *pids = NULL; + pid_t *tmp; int npids = 0; if ((kd = kvm_openfiles (NULL, NULL, NULL, O_RDONLY, errbuf)) == NULL) @@ -210,15 +212,20 @@ pid_t *rc_find_pids (const char *exec, const char *cmd, continue; } - pids = realloc (pids, sizeof (pid_t) * (npids + 2)); - if (! pids) - eerrorx ("memory exhausted"); + tmp = realloc (pids, sizeof (pid_t) * (npids + 2)); + if (! tmp) { + free (pids); + kvm_close (kd); + errno = ENOMEM; + return (NULL); + } + pids = tmp; pids[npids] = p; pids[npids + 1] = 0; npids++; } - kvm_close(kd); + kvm_close (kd); return (pids); } @@ -238,13 +245,7 @@ static bool _match_daemon (const char *path, const char *file, int lc = 0; int m = 0; - if (! rc_exists (ffile)) { - free (ffile); - return (false); - } - if ((fp = fopen (ffile, "r")) == NULL) { - eerror ("fopen `%s': %s", ffile, strerror (errno)); free (ffile); return (false); } @@ -350,19 +351,14 @@ void rc_set_service_daemon (const char *service, const char *exec, char buffer[10]; FILE *fp; - if (! rc_is_dir (dirpath)) - if (mkdir (dirpath, 0755) != 0) - eerror ("mkdir `%s': %s", dirpath, strerror (errno)); - - snprintf (buffer, sizeof (buffer), "%03d", nfiles + 1); - file = rc_strcatpaths (dirpath, buffer, (char *) NULL); - if ((fp = fopen (file, "w")) == NULL) - eerror ("fopen `%s': %s", file, strerror (errno)); - else { - fprintf (fp, "%s\n%s\n%s\n", mexec, mname, mpidfile); + if (mkdir (dirpath, 0755) == 0 || errno == EEXIST) { + snprintf (buffer, sizeof (buffer), "%03d", nfiles + 1); + file = rc_strcatpaths (dirpath, buffer, (char *) NULL); + if ((fp = fopen (file, "w"))) + fprintf (fp, "%s\n%s\n%s\n", mexec, mname, mpidfile); fclose (fp); + free (file); } - free (file); } free (mexec); @@ -458,10 +454,8 @@ bool rc_service_daemons_crashed (const char *service) path = rc_strcatpaths (dirpath, file, (char *) NULL); fp = fopen (path, "r"); free (path); - if (! fp) { - eerror ("fopen `%s': %s", file, strerror (errno)); - continue; - } + if (! fp) + break; while ((fgets (buffer, RC_LINEBUFFER, fp))) { int lb = strlen (buffer) - 1; @@ -499,13 +493,11 @@ bool rc_service_daemons_crashed (const char *service) } if ((fp = fopen (pidfile, "r")) == NULL) { - eerror ("fopen `%s': %s", pidfile, strerror (errno)); retval = true; break; } if (fscanf (fp, "%d", &pid) != 1) { - eerror ("no pid found in `%s'", pidfile); fclose (fp); retval = true; break; diff --git a/src/librc-depend.c b/src/librc-depend.c index 4a3c10e2..d8bad32c 100644 --- a/src/librc-depend.c +++ b/src/librc-depend.c @@ -41,7 +41,7 @@ static char *get_shell_value (char *string) return (NULL); } -void rc_free_deptree (rc_depinfo_t *deptree) +void rc_deptree_free (rc_depinfo_t *deptree) { rc_depinfo_t *di = deptree; while (di) @@ -61,9 +61,9 @@ void rc_free_deptree (rc_depinfo_t *deptree) di = dip; } } -librc_hidden_def(rc_free_deptree) +librc_hidden_def(rc_deptree_free) -rc_depinfo_t *rc_load_deptree (void) +rc_depinfo_t *rc_deptree_load (void) { FILE *fp; rc_depinfo_t *deptree = NULL; @@ -75,9 +75,6 @@ rc_depinfo_t *rc_load_deptree (void) char *e; int i; - /* Update our deptree, but only if we need too */ - rc_update_deptree (false); - if (! (fp = fopen (RC_DEPTREE, "r"))) return (NULL); @@ -150,9 +147,9 @@ rc_depinfo_t *rc_load_deptree (void) return (deptree); } -librc_hidden_def(rc_load_deptree) +librc_hidden_def(rc_deptree_load) -rc_depinfo_t *rc_get_depinfo (rc_depinfo_t *deptree, const char *service) +rc_depinfo_t *rc_deptree_depinfo (rc_depinfo_t *deptree, const char *service) { rc_depinfo_t *di; @@ -165,9 +162,9 @@ rc_depinfo_t *rc_get_depinfo (rc_depinfo_t *deptree, const char *service) return (NULL); } -librc_hidden_def(rc_get_depinfo) +librc_hidden_def(rc_deptree_depinfo) -rc_deptype_t *rc_get_deptype (rc_depinfo_t *depinfo, const char *type) +rc_deptype_t *rc_deptree_deptype (rc_depinfo_t *depinfo, const char *type) { rc_deptype_t *dt; @@ -180,7 +177,7 @@ rc_deptype_t *rc_get_deptype (rc_depinfo_t *depinfo, const char *type) return (NULL); } -librc_hidden_def(rc_get_deptype) +librc_hidden_def(rc_deptree_deptype) static bool valid_service (const char *runlevel, const char *service) { @@ -263,7 +260,7 @@ static char **get_provided (rc_depinfo_t *deptree, rc_depinfo_t *depinfo, if (rc_service_exists (depinfo->service)) return (NULL); - dt = rc_get_deptype (depinfo, "providedby"); + dt = rc_deptree_deptype (depinfo, "providedby"); if (! dt) return (NULL); @@ -382,7 +379,7 @@ static void visit_service (rc_depinfo_t *deptree, char **types, STRLIST_FOREACH (types, item, i) { - if ((dt = rc_get_deptype (depinfo, item))) + if ((dt = rc_deptree_deptype (depinfo, item))) { STRLIST_FOREACH (dt->services, service, j) { @@ -392,12 +389,12 @@ static void visit_service (rc_depinfo_t *deptree, char **types, continue; } - di = rc_get_depinfo (deptree, service); + di = rc_deptree_depinfo (deptree, service); if ((provides = get_provided (deptree, di, runlevel, options))) { STRLIST_FOREACH (provides, lp, k) { - di = rc_get_depinfo (deptree, lp); + di = rc_deptree_depinfo (deptree, lp); if (di && (strcmp (item, "ineed") == 0 || strcmp (item, "needsme") == 0 || valid_service (runlevel, di->service))) @@ -417,11 +414,12 @@ static void visit_service (rc_depinfo_t *deptree, char **types, } /* Now visit the stuff we provide for */ - if (options & RC_DEP_TRACE && (dt = rc_get_deptype (depinfo, "iprovide"))) + if (options & RC_DEP_TRACE && + (dt = rc_deptree_deptype (depinfo, "iprovide"))) { STRLIST_FOREACH (dt->services, service, i) { - if ((di = rc_get_depinfo (deptree, service))) + if ((di = rc_deptree_depinfo (deptree, service))) if ((provides = get_provided (deptree, di, runlevel, options))) { STRLIST_FOREACH (provides, lp, j) @@ -440,13 +438,13 @@ static void visit_service (rc_depinfo_t *deptree, char **types, are also the service calling us or we are provided by something */ svcname = getenv("SVCNAME"); if (! svcname || strcmp (svcname, depinfo->service) != 0) - if (! rc_get_deptype (depinfo, "providedby")) + if (! rc_deptree_deptype (depinfo, "providedby")) rc_strlist_add (&sorted->list, depinfo->service); } -char **rc_get_depends (rc_depinfo_t *deptree, - char **types, char **services, - const char *runlevel, int options) +char **rc_deptree_depends (rc_depinfo_t *deptree, + char **types, char **services, + const char *runlevel, int options) { struct lhead sorted; struct lhead visited; @@ -466,17 +464,17 @@ char **rc_get_depends (rc_depinfo_t *deptree, STRLIST_FOREACH (services, service, i) { - di = rc_get_depinfo (deptree, service); + di = rc_deptree_depinfo (deptree, service); visit_service (deptree, types, &sorted, &visited, di, runlevel, options); } rc_strlist_free (visited.list); return (sorted.list); } -librc_hidden_def(rc_get_depends) +librc_hidden_def(rc_deptree_depends) -char **rc_order_services (rc_depinfo_t *deptree, const char *runlevel, - int options) +char **rc_deptree_order_services (rc_depinfo_t *deptree, const char *runlevel, + int options) { char **list = NULL; char **types = NULL; @@ -530,8 +528,8 @@ char **rc_order_services (rc_depinfo_t *deptree, const char *runlevel, rc_strlist_add (&types, "ineed"); rc_strlist_add (&types, "iuse"); rc_strlist_add (&types, "iafter"); - services = rc_get_depends (deptree, types, list, runlevel, - RC_DEP_STRICT | RC_DEP_TRACE | options); + services = rc_deptree_depends (deptree, types, list, runlevel, + RC_DEP_STRICT | RC_DEP_TRACE | options); rc_strlist_free (list); rc_strlist_free (types); @@ -540,7 +538,7 @@ char **rc_order_services (rc_depinfo_t *deptree, const char *runlevel, return (services); } -librc_hidden_def(rc_order_services) +librc_hidden_def(rc_deptree_order_services) static bool is_newer_than (const char *file, const char *target) { @@ -611,6 +609,39 @@ static const char *depdirs[] = NULL }; +bool rc_deptree_update_needed (void) +{ + bool newer = false; + char **config; + char *service; + int i; + + /* Create base directories if needed */ + for (i = 0; depdirs[i]; i++) + if (mkdir (depdirs[i], 0755) != 0 && errno != EEXIST) + fprintf (stderr, "mkdir `%s': %s", depdirs[i], strerror (errno)); + + /* Quick test to see if anything we use has changed */ + if (! is_newer_than (RC_DEPTREE, RC_INITDIR) || + ! is_newer_than (RC_DEPTREE, RC_CONFDIR) || + ! is_newer_than (RC_DEPTREE, "/etc/rc.conf")) + return (true); + + /* Some init scripts dependencies change depending on config files + * outside of baselayout, like syslog-ng, so we check those too. */ + config = rc_get_list (RC_DEPCONFIG); + STRLIST_FOREACH (config, service, i) { + if (! is_newer_than (RC_DEPTREE, service)) { + newer = true; + break; + } + } + rc_strlist_free (config); + + return (newer); +} +librc_hidden_def(rc_deptree_update_needed) + /* This is a 5 phase operation Phase 1 is a shell script which loads each init script and config in turn and echos their dependency info to stdout @@ -619,7 +650,7 @@ static const char *depdirs[] = Phase 4 scans that depinfo object and puts in backlinks Phase 5 saves the depinfo object to disk */ -int rc_update_deptree (bool force) +int rc_deptree_update (void) { char *depends; char *service; @@ -642,41 +673,6 @@ int rc_update_deptree (bool force) int k; bool already_added; - /* Create base directories if needed */ - for (i = 0; depdirs[i]; i++) - if (! rc_is_dir (depdirs[i])) - if (mkdir (depdirs[i], 0755) != 0) - eerrorx ("mkdir `%s': %s", depdirs[i], strerror (errno)); - - /* Quick test to see if anything we use has changed */ - if (! force && - is_newer_than (RC_DEPTREE, RC_INITDIR) && - is_newer_than (RC_DEPTREE, RC_CONFDIR) && - is_newer_than (RC_DEPTREE, "/etc/rc.conf")) - { - bool newer = false; - - /* Some init scripts dependencies change depending on config files - * outside of baselayout, like syslog-ng, so we check those too. */ - if (! rc_exists (RC_DEPCONFIG)) - return 0; - - config = rc_get_list (RC_DEPCONFIG); - STRLIST_FOREACH (config, service, i) { - if (! is_newer_than (RC_DEPTREE, service)) { - newer = true; - break; - } - } - rc_strlist_free (config); - config = NULL; - - if (! newer) - return (0); - } - - ebegin ("Caching service dependencies"); - /* Some init scripts need RC_LIBDIR to source stuff Ideally we should be setting our full env instead */ if (! getenv ("RC_LIBDIR")) @@ -684,7 +680,7 @@ int rc_update_deptree (bool force) /* Phase 1 */ if (! (fp = popen (GENDEP, "r"))) - eerrorx ("popen: %s", strerror (errno)); + return (-1); deptree = rc_xmalloc (sizeof (rc_depinfo_t)); memset (deptree, 0, sizeof (rc_depinfo_t)); @@ -783,7 +779,7 @@ int rc_update_deptree (bool force) /* Phase 3 - add our providors to the tree */ for (depinfo = deptree; depinfo; depinfo = depinfo->next) { - if ((deptype = rc_get_deptype (depinfo, "iprovide"))) + if ((deptype = rc_deptree_deptype (depinfo, "iprovide"))) STRLIST_FOREACH (deptype->services, service, i) { for (di = deptree; di; di = di->next) @@ -807,19 +803,20 @@ int rc_update_deptree (bool force) { for (i = 0; deppairs[i].depend; i++) { - deptype = rc_get_deptype (depinfo, deppairs[i].depend); + deptype = rc_deptree_deptype (depinfo, deppairs[i].depend); if (! deptype) continue; STRLIST_FOREACH (deptype->services, service, j) { - di = rc_get_depinfo (deptree, service); + di = rc_deptree_depinfo (deptree, service); if (! di) { if (strcmp (deptype->type, "ineed") == 0) { - eerror ("Service `%s' needs non existant service `%s'", - depinfo->service, service); + fprintf (stderr, + "Service `%s' needs non existant service `%s'", + depinfo->service, service); retval = -1; } continue; @@ -869,10 +866,7 @@ int rc_update_deptree (bool force) This works and should be entirely shell parseable provided that depend names don't have any non shell variable characters in */ - if (! (fp = fopen (RC_DEPTREE, "w"))) - eerror ("fopen `%s': %s", RC_DEPTREE, strerror (errno)); - else - { + if ((fp = fopen (RC_DEPTREE, "w"))) { i = 0; for (depinfo = deptree; depinfo; depinfo = depinfo->next) { @@ -890,24 +884,22 @@ int rc_update_deptree (bool force) i++; } fclose (fp); - } + } else + fprintf (stderr, "fopen `%s': %s", RC_DEPTREE, strerror (errno)); /* Save our external config files to disk */ if (config) { - if (! (fp = fopen (RC_DEPCONFIG, "w"))) - eerror ("fopen `%s': %s", RC_DEPCONFIG, strerror (errno)); - else - { + if ((fp = fopen (RC_DEPCONFIG, "w"))) { STRLIST_FOREACH (config, service, i) fprintf (fp, "%s\n", service); fclose (fp); - } + } else + fprintf (stderr, "fopen `%s': %s\n", RC_DEPCONFIG, strerror (errno)); rc_strlist_free (config); } - rc_free_deptree (deptree); + rc_deptree_free (deptree); - eend (retval, "Failed to update the service dependency tree"); return (retval); } -librc_hidden_def(rc_update_deptree) +librc_hidden_def(rc_deptree_update) diff --git a/src/librc-misc.c b/src/librc-misc.c index ad144395..c3a67541 100644 --- a/src/librc-misc.c +++ b/src/librc-misc.c @@ -6,7 +6,7 @@ #include "librc.h" -#define ERRX eerrorx("out of memory"); +#define ERRX fprintf (stderr, "out of memory\n"); exit (1) #define PROFILE_ENV "/etc/profile.env" #define SYS_WHITELIST RC_LIBDIR "/conf.d/env_whitelist" @@ -26,7 +26,7 @@ void *rc_xmalloc (size_t size) if (value) return (value); - ERRX + ERRX; } librc_hidden_def(rc_xmalloc) @@ -37,7 +37,7 @@ void *rc_xrealloc (void *ptr, size_t size) if (value) return (value); - ERRX + ERRX; } librc_hidden_def(rc_xrealloc) @@ -53,7 +53,7 @@ char *rc_xstrdup (const char *str) if (value) return (value); - ERRX + ERRX; } librc_hidden_def(rc_xstrdup) @@ -217,14 +217,9 @@ char **rc_ls_dir (const char *dir, int options) struct dirent *d; char **list = NULL; - if (! dir) + if ((dp = opendir (dir)) == NULL) return (NULL); - if ((dp = opendir (dir)) == NULL) { - eerror ("failed to opendir `%s': %s", dir, strerror (errno)); - return (NULL); - } - errno = 0; while (((d = readdir (dp)) != NULL) && errno == 0) { if (d->d_name[0] != '.') { @@ -248,12 +243,6 @@ char **rc_ls_dir (const char *dir, int options) } closedir (dp); - if (errno != 0) { - eerror ("failed to readdir `%s': %s", dir, strerror (errno)); - rc_strlist_free (list); - return (NULL); - } - return (list); } librc_hidden_def(rc_ls_dir) @@ -263,13 +252,8 @@ bool rc_rm_dir (const char *pathname, bool top) DIR *dp; struct dirent *d; - if (! pathname) - return (false); - - if ((dp = opendir (pathname)) == NULL) { - eerror ("failed to opendir `%s': %s", pathname, strerror (errno)); + if ((dp = opendir (pathname)) == NULL) return (false); - } errno = 0; while (((d = readdir (dp)) != NULL) && errno == 0) { @@ -284,7 +268,6 @@ bool rc_rm_dir (const char *pathname, bool top) } } else { if (unlink (tmp)) { - eerror ("failed to unlink `%s': %s", tmp, strerror (errno)); free (tmp); closedir (dp); return (false); @@ -293,14 +276,10 @@ bool rc_rm_dir (const char *pathname, bool top) free (tmp); } } - if (errno != 0) - eerror ("failed to readdir `%s': %s", pathname, strerror (errno)); closedir (dp); - if (top && rmdir (pathname) != 0) { - eerror ("failed to rmdir `%s': %s", pathname, strerror (errno)); - return false; - } + if (top && rmdir (pathname) != 0) + return (false); return (true); } @@ -321,14 +300,9 @@ char **rc_get_config (const char *file) char *entry; char *newline; - if (! file) + if (! (fp = fopen (file, "r"))) return (NULL); - if (! (fp = fopen (file, "r"))) { - ewarn ("rc_get_config `%s': %s", file, strerror (errno)); - return (NULL); - } - while (fgets (buffer, RC_LINEBUFFER, fp)) { p = buffer; @@ -419,10 +393,8 @@ char **rc_get_list (const char *file) char *token; char **list = NULL; - if (! (fp = fopen (file, "r"))) { - ewarn ("rc_get_list `%s': %s", file, strerror (errno)); + if (! (fp = fopen (file, "r"))) return (NULL); - } while (fgets (buffer, RC_LINEBUFFER, fp)) { p = buffer; @@ -465,7 +437,7 @@ char **rc_filter_env (void) whitelist = rc_get_list (SYS_WHITELIST); if (! whitelist) - ewarn ("system environment whitelist (" SYS_WHITELIST ") missing"); + fprintf (stderr, "system environment whitelist (" SYS_WHITELIST ") missing\n"); env = rc_get_list (USR_WHITELIST); rc_strlist_join (&whitelist, env); @@ -557,18 +529,13 @@ static bool file_regex (const char *file, const char *regex) bool retval = false; int result; - if (! rc_exists (file)) + if (! (fp = fopen (file, "r"))) return (false); - if (! (fp = fopen (file, "r"))) { - ewarn ("file_regex `%s': %s", file, strerror (errno)); - return (false); - } - if ((result = regcomp (&re, regex, REG_EXTENDED | REG_NOSUB)) != 0) { fclose (fp); regerror (result, &re, buffer, sizeof (buffer)); - eerror ("file_regex: %s", buffer); + fprintf (stderr, "file_regex: %s", buffer); return (false); } @@ -652,23 +619,19 @@ char **rc_make_env (void) rc_strlist_add (&env, line); free (line); - if (rc_exists (RC_KSOFTLEVEL)) { - if (! (fp = fopen (RC_KSOFTLEVEL, "r"))) - eerror ("fopen `%s': %s", RC_KSOFTLEVEL, strerror (errno)); - else { - memset (buffer, 0, sizeof (buffer)); - if (fgets (buffer, sizeof (buffer), fp)) { - i = strlen (buffer) - 1; - if (buffer[i] == '\n') - buffer[i] = 0; - i += strlen ("RC_DEFAULTLEVEL=") + 2; - line = rc_xmalloc (sizeof (char *) * i); - snprintf (line, i, "RC_DEFAULTLEVEL=%s", buffer); - rc_strlist_add (&env, line); - free (line); - } - fclose (fp); + if ((fp = fopen (RC_KSOFTLEVEL, "r"))) { + memset (buffer, 0, sizeof (buffer)); + if (fgets (buffer, sizeof (buffer), fp)) { + i = strlen (buffer) - 1; + if (buffer[i] == '\n') + buffer[i] = 0; + i += strlen ("RC_DEFAULTLEVEL=") + 2; + line = rc_xmalloc (sizeof (char *) * i); + snprintf (line, i, "RC_DEFAULTLEVEL=%s", buffer); + rc_strlist_add (&env, line); + free (line); } + fclose (fp); } else rc_strlist_add (&env, "RC_DEFAULTLEVEL=" RC_LEVEL_DEFAULT); @@ -679,8 +642,7 @@ char **rc_make_env (void) memset (sys, 0, sizeof (sys)); if (rc_is_dir ("/proc/xen")) { - fp = fopen ("/proc/xen/capabilities", "r"); - if (fp) { + if ((fp = fopen ("/proc/xen/capabilities", "r"))) { fclose (fp); if (file_regex ("/proc/xen/capabilities", "control_d")) snprintf (sys, sizeof (sys), "XENU"); diff --git a/src/librc.c b/src/librc.c index 96588e3f..83eca265 100644 --- a/src/librc.c +++ b/src/librc.c @@ -104,13 +104,15 @@ char *rc_get_runlevel (void) } librc_hidden_def(rc_get_runlevel) -void rc_set_runlevel (const char *runlevel) +bool rc_set_runlevel (const char *runlevel) { FILE *fp = fopen (SOFTLEVEL, "w"); + if (! fp) - eerrorx ("failed to open `" SOFTLEVEL "': %s", strerror (errno)); + return (false); fprintf (fp, "%s", runlevel); fclose (fp); + return (true); } librc_hidden_def(rc_set_runlevel) @@ -200,17 +202,13 @@ char **rc_service_options (const char *service) char *p = buffer; FILE *fp; - if (! rc_service_exists (service)) + if (! (svc = rc_resolve_service (service))) return (NULL); - svc = rc_resolve_service (service); - snprintf (cmd, sizeof (cmd), ". '%s'; echo \"${opts}\"", svc); - if (! (fp = popen (cmd, "r"))) { - eerror ("popen `%s': %s", svc, strerror (errno)); - free (svc); + free (svc); + if (! (fp = popen (cmd, "r"))) return (NULL); - } if (fgets (buffer, RC_LINEBUFFER, fp)) { if (buffer[strlen (buffer) - 1] == '\n') @@ -232,22 +230,17 @@ char *rc_service_description (const char *service, const char *option) FILE *fp; int i; - if (! rc_service_exists (service)) + if (! (svc = rc_resolve_service (service))) return (NULL); - svc = rc_resolve_service (service); - if (! option) option = ""; snprintf (cmd, sizeof (cmd), ". '%s'; echo \"${description%s%s}\"", svc, option ? "_" : "", option); - if (! (fp = popen (cmd, "r"))) { - eerror ("popen `%s': %s", svc, strerror (errno)); - free (svc); - return (NULL); - } free (svc); + if (! (fp = popen (cmd, "r"))) + return (NULL); while (fgets (buffer, RC_LINEBUFFER, fp)) { if (! desc) { @@ -315,7 +308,6 @@ bool rc_mark_service (const char *service, const rc_service_state_t state) unlink (file); i = symlink (init, file); if (i != 0) { - eerror ("symlink `%s' to `%s': %s", init, file, strerror (errno)); free (file); free (init); free (svc); @@ -353,18 +345,11 @@ bool rc_mark_service (const char *service, const rc_service_state_t state) rc_parse_service_state (RC_SERVICE_WASINACTIVE), base, (char *) NULL); - if (symlink (init, wasfile) != 0) - eerror ("symlink `%s' to `%s': %s", init, wasfile, - strerror (errno)); - + symlink (init, wasfile); skip_wasinactive = true; free (wasfile); } - - errno = 0; - if (unlink (file) != 0 && errno != ENOENT) - eerror ("failed to delete `%s': %s", file, - strerror (errno)); + unlink (file); } free (file); } @@ -376,9 +361,7 @@ bool rc_mark_service (const char *service, const rc_service_state_t state) state == RC_SERVICE_INACTIVE) { file = rc_strcatpaths (RC_SVCDIR, "exclusive", base, (char *) NULL); - if (rc_exists (file)) - if (unlink (file) != 0) - eerror ("unlink `%s': %s", file, strerror (errno)); + unlink (file); free (file); } @@ -408,9 +391,7 @@ bool rc_mark_service (const char *service, const rc_service_state_t state) STRLIST_FOREACH (dirs, dir, i) { char *bdir = rc_strcatpaths (sdir, dir, (char *) NULL); file = rc_strcatpaths (bdir, base, (char *) NULL); - if (rc_exists (file)) - if (unlink (file) != 0) - eerror ("unlink `%s': %s", file, strerror (errno)); + unlink (file); free (file); /* Try and remove the dir - we don't care about errors */ @@ -468,18 +449,14 @@ char *rc_get_service_option (const char *service, const char *option) (char *) NULL); char *value = NULL; - if (rc_exists (file)) { - if ((fp = fopen (file, "r")) == NULL) - eerror ("fopen `%s': %s", file, strerror (errno)); - else { - memset (buffer, 0, sizeof (buffer)); - if (fgets (buffer, RC_LINEBUFFER, fp)) - value = rc_xstrdup (buffer); - fclose (fp); - } + if ((fp = fopen (file, "r"))) { + memset (buffer, 0, sizeof (buffer)); + if (fgets (buffer, RC_LINEBUFFER, fp)) + value = rc_xstrdup (buffer); + fclose (fp); } - free (file); + return (value); } librc_hidden_def(rc_get_service_option) @@ -494,16 +471,13 @@ bool rc_set_service_option (const char *service, const char *option, if (! rc_is_dir (path)) { if (mkdir (path, 0755) != 0) { - eerror ("mkdir `%s': %s", path, strerror (errno)); free (path); free (file); return (false); } } - if ((fp = fopen (file, "w")) == NULL) - eerror ("fopen `%s': %s", file, strerror (errno)); - else { + if ((fp = fopen (file, "w"))) { if (value) fprintf (fp, "%s", value); fclose (fp); @@ -537,7 +511,6 @@ static pid_t _exec_service (const char *service, const char *arg) free (svc); if (mkfifo (fifo, 0600) != 0 && errno != EEXIST) { - eerror ("unable to create fifo `%s': %s", fifo, strerror (errno)); free (fifo); free (file); return (-1); @@ -545,7 +518,7 @@ static pid_t _exec_service (const char *service, const char *arg) if ((pid = vfork ()) == 0) { execl (file, file, arg, (char *) NULL); - eerror ("unable to exec `%s': %s", file, strerror (errno)); + fprintf (stderr, "unable to exec `%s': %s\n", file, strerror (errno)); unlink (fifo); _exit (EXIT_FAILURE); } @@ -554,7 +527,7 @@ static pid_t _exec_service (const char *service, const char *arg) free (file); if (pid == -1) - eerror ("vfork: %s", strerror (errno)); + fprintf (stderr, "vfork: %s\n", strerror (errno)); return (pid); } @@ -593,17 +566,18 @@ pid_t rc_start_service (const char *service) } librc_hidden_def(rc_start_service) -void rc_schedule_start_service (const char *service, +bool rc_schedule_start_service (const char *service, const char *service_to_start) { char *dir; char *init; char *file; char *svc; + bool retval; /* service may be a provided service, like net */ if (! service || ! rc_service_exists (service_to_start)) - return; + return (false); svc = rc_xstrdup (service); dir = rc_strcatpaths (RC_SVCDIR, "scheduled", basename (svc), @@ -611,21 +585,20 @@ void rc_schedule_start_service (const char *service, free (svc); if (! rc_is_dir (dir)) if (mkdir (dir, 0755) != 0) { - eerror ("mkdir `%s': %s", dir, strerror (errno)); free (dir); - return; + return (false); } init = rc_resolve_service (service_to_start); svc = rc_xstrdup (service_to_start); file = rc_strcatpaths (dir, basename (svc), (char *) NULL); free (svc); - if (! rc_exists (file) && symlink (init, file) != 0) - eerror ("symlink `%s' to `%s': %s", init, file, strerror (errno)); - + retval = (rc_exists (file) || symlink (init, file) == 0); free (init); free (file); free (dir); + + return (retval); } librc_hidden_def(rc_schedule_start_service) @@ -674,10 +647,8 @@ bool rc_wait_service (const char *service) } if (nanosleep (&ts, NULL) == -1) { - if (errno != EINTR) { - eerror ("nanosleep: %s", strerror (errno)); + if (errno != EINTR) break; - } } if (! forever) @@ -703,11 +674,7 @@ char **rc_services_in_runlevel (const char *runlevel) return (NULL); dir = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, (char *) NULL); - if (! rc_is_dir (dir)) - eerror ("runlevel `%s' does not exist", runlevel); - else - list = rc_ls_dir (dir, RC_LS_INITD); - + list = rc_ls_dir (dir, RC_LS_INITD); free (dir); return (list); } diff --git a/src/librc.h b/src/librc.h index 86f75835..4fd444d3 100644 --- a/src/librc.h +++ b/src/librc.h @@ -42,7 +42,6 @@ #include <kvm.h> #endif -#include "einfo.h" #include "librc-depend.h" #include "rc.h" #include "rc-misc.h" @@ -53,16 +52,20 @@ #define librc_hidden_def(x) hidden_def(x) librc_hidden_proto(rc_allow_plug) +librc_hidden_proto(rc_deptree_depends) +librc_hidden_proto(rc_deptree_depinfo) +librc_hidden_proto(rc_deptree_deptype) +librc_hidden_proto(rc_deptree_free) +librc_hidden_proto(rc_deptree_load) +librc_hidden_proto(rc_deptree_order_services) +librc_hidden_proto(rc_deptree_update) +librc_hidden_proto(rc_deptree_update_needed) librc_hidden_proto(rc_env_bool) librc_hidden_proto(rc_exists) librc_hidden_proto(rc_filter_env) librc_hidden_proto(rc_find_pids) -librc_hidden_proto(rc_free_deptree) librc_hidden_proto(rc_get_config) librc_hidden_proto(rc_get_config_entry) -librc_hidden_proto(rc_get_depends) -librc_hidden_proto(rc_get_depinfo) -librc_hidden_proto(rc_get_deptype) librc_hidden_proto(rc_get_list) librc_hidden_proto(rc_get_runlevel) librc_hidden_proto(rc_get_runlevels) @@ -71,11 +74,9 @@ librc_hidden_proto(rc_is_dir) librc_hidden_proto(rc_is_exec) librc_hidden_proto(rc_is_file) librc_hidden_proto(rc_is_link) -librc_hidden_proto(rc_load_deptree) librc_hidden_proto(rc_ls_dir) librc_hidden_proto(rc_make_env) librc_hidden_proto(rc_mark_service) -librc_hidden_proto(rc_order_services) librc_hidden_proto(rc_resolve_service) librc_hidden_proto(rc_rm_dir) librc_hidden_proto(rc_runlevel_exists) @@ -111,7 +112,6 @@ librc_hidden_proto(rc_strlist_delete) librc_hidden_proto(rc_strlist_free) librc_hidden_proto(rc_strlist_join) librc_hidden_proto(rc_strlist_reverse) -librc_hidden_proto(rc_update_deptree) librc_hidden_proto(rc_wait_service) librc_hidden_proto(rc_waitpid) librc_hidden_proto(rc_xmalloc) diff --git a/src/rc-depend.c b/src/rc-depend.c index 3201fc77..ece00a21 100644 --- a/src/rc-depend.c +++ b/src/rc-depend.c @@ -19,6 +19,18 @@ #include "rc-misc.h" #include "strlist.h" +rc_depinfo_t *_rc_deptree_load (void) { + if (rc_deptree_update_needed ()) { + int retval; + + ebegin ("Caching service dependencies"); + retval = rc_deptree_update (); + eend (retval, "Failed to update the dependency tree"); + } + + return (rc_deptree_load ()); +} + int rc_depend (int argc, char **argv) { char **types = NULL; @@ -39,8 +51,9 @@ int rc_depend (int argc, char **argv) for (i = 1; i < argc; i++) { if (strcmp (argv[i], "--update") == 0) { if (! update) { - rc_update_deptree (true); - update = true; + ebegin ("Caching service dependencies"); + update = (rc_deptree_update () == 0); + eend (update ? 0 : -1, "Failed to update the dependency tree"); } continue; } @@ -59,10 +72,10 @@ int rc_depend (int argc, char **argv) argv[i]++; rc_strlist_add (&types, argv[i]); } else { - if ((deptree = rc_load_deptree ()) == NULL) + if ((deptree = _rc_deptree_load ()) == NULL) eerrorx ("failed to load deptree"); - di = rc_get_depinfo (deptree, argv[i]); + di = rc_deptree_depinfo (deptree, argv[i]); if (! di) eerror ("no dependency info for service `%s'", argv[i]); else @@ -72,7 +85,7 @@ int rc_depend (int argc, char **argv) if (! services) { rc_strlist_free (types); - rc_free_deptree (deptree); + rc_deptree_free (deptree); if (update) return (EXIT_SUCCESS); eerrorx ("no services specified"); @@ -84,7 +97,7 @@ int rc_depend (int argc, char **argv) rc_strlist_add (&types, "iuse"); } - depends = rc_get_depends (deptree, types, services, runlevel, options); + depends = rc_deptree_depends (deptree, types, services, runlevel, options); if (depends) { STRLIST_FOREACH (depends, service, i) { @@ -103,7 +116,7 @@ int rc_depend (int argc, char **argv) rc_strlist_free (types); rc_strlist_free (services); rc_strlist_free (depends); - rc_free_deptree (deptree); + rc_deptree_free (deptree); return (EXIT_SUCCESS); } @@ -104,7 +104,7 @@ static void cleanup (void) rc_strlist_free (coldplugged_services); rc_strlist_free (stop_services); rc_strlist_free (start_services); - rc_free_deptree (deptree); + rc_deptree_free (deptree); rc_strlist_free (types); /* Clean runlevel start, stop markers */ @@ -1021,7 +1021,7 @@ int main (int argc, char **argv) } /* Load our deptree now */ - if ((deptree = rc_load_deptree ()) == NULL) + if ((deptree = _rc_deptree_load ()) == NULL) eerrorx ("failed to load deptree"); /* Clean the failed services state dir now */ @@ -1112,7 +1112,7 @@ int main (int argc, char **argv) rc_strlist_add (&types, "iuse"); rc_strlist_add (&types, "iafter"); - deporder = rc_get_depends (deptree, types, stop_services, + deporder = rc_deptree_depends (deptree, types, stop_services, runlevel, depoptions | RC_DEP_STOP); rc_strlist_free (stop_services); @@ -1231,7 +1231,7 @@ int main (int argc, char **argv) /* We got this far! Or last check is to see if any any service that going to be started depends on us */ rc_strlist_add (&stopdeps, service); - deporder = rc_get_depends (deptree, types, stopdeps, + deporder = rc_deptree_depends (deptree, types, stopdeps, runlevel, RC_DEP_STRICT); rc_strlist_free (stopdeps); stopdeps = NULL; @@ -1300,7 +1300,7 @@ int main (int argc, char **argv) rc_strlist_add (&types, "ineed"); rc_strlist_add (&types, "iuse"); rc_strlist_add (&types, "iafter"); - deporder = rc_get_depends (deptree, types, start_services, + deporder = rc_deptree_depends (deptree, types, start_services, runlevel, depoptions | RC_DEP_START); rc_strlist_free (types); types = NULL; @@ -114,7 +114,7 @@ int rc_waitpid (pid_t pid); /*! Schedule a service to be started when another service starts * @param service that starts the scheduled service when started * @param service_to_start service that will be started */ -void rc_schedule_start_service (const char *service, +bool rc_schedule_start_service (const char *service, const char *service_to_start); /*! Return a NULL terminated list of services that are scheduled to start * when the given service has started @@ -171,7 +171,7 @@ char *rc_get_runlevel (void); /*! Set the runlevel. * This just changes the stored runlevel and does not start or stop any services. * @param runlevel to store */ -void rc_set_runlevel (const char *runlevel); +bool rc_set_runlevel (const char *runlevel); /*! Checks if the runlevel exists or not * @param runlevel to check @@ -254,25 +254,29 @@ typedef void *rc_depinfo_t; /*! Update the cached dependency tree if it's older than any init script, * its configuration file or an external configuration file the init script * has specified. - * @param force an update * @return 0 if successful, otherwise -1 */ -int rc_update_deptree (bool force); +int rc_deptree_update (void); +/*! Check if the cached dependency tree is older than any init script, + * its configuration file or an external configuration file the init script + * has specified. + * @return true if it needs updating, otherwise false */ +bool rc_deptree_update_needed (void); /*! Load the cached dependency tree and return a pointer to it. - * This pointer should be freed with rc_free_deptree when done. + * This pointer should be freed with rc_deptree_free when done. * @return pointer to the dependency tree */ -rc_depinfo_t *rc_load_deptree (void); +rc_depinfo_t *rc_deptree_load (void); /*! Get a services depedency information from a loaded tree * @param deptree to search * @param service to find * @return service dependency information */ -rc_depinfo_t *rc_get_depinfo (rc_depinfo_t *deptree, const char *service); +rc_depinfo_t *rc_deptree_depinfo (rc_depinfo_t *deptree, const char *service); /*! Get a depenency type from the service dependency information * @param depinfo service dependency to search * @param type to find * @return service dependency type information */ -rc_deptype_t *rc_get_deptype (rc_depinfo_t *depinfo, const char *type); -char **rc_get_depends (rc_depinfo_t *deptree, char **types, - char **services, const char *runlevel, int options); +rc_deptype_t *rc_deptree_deptype (rc_depinfo_t *depinfo, const char *type); +char **rc_deptree_depends (rc_depinfo_t *deptree, char **types, + char **services, const char *runlevel, int options); /*! List all the services that should be stoppned and then started, in order, * for the given runlevel, including sysinit and boot services where * approriate. @@ -280,11 +284,11 @@ char **rc_get_depends (rc_depinfo_t *deptree, char **types, * @param runlevel to change into * @param options to pass * @return NULL terminated list of services in order */ -char **rc_order_services (rc_depinfo_t *deptree, const char *runlevel, - int options); +char **rc_deptree_order_services (rc_depinfo_t *deptree, const char *runlevel, + int options); /*! Free a deptree and its information * @param deptree to free */ -void rc_free_deptree (rc_depinfo_t *deptree); +void rc_deptree_free (rc_depinfo_t *deptree); /*! @name Plugins * For each plugin loaded we will call rc_plugin_hook with the below diff --git a/src/runscript.c b/src/runscript.c index 49048044..f35b7137 100644 --- a/src/runscript.c +++ b/src/runscript.c @@ -259,7 +259,7 @@ static void cleanup (void) } rc_plugin_unload (); - rc_free_deptree (deptree); + rc_deptree_free (deptree); rc_strlist_free (services); rc_strlist_free (types); rc_strlist_free (svclist); @@ -578,7 +578,7 @@ static void svc_start (bool deps) depoptions |= RC_DEP_START; if (deps) { - if (! deptree && ((deptree = rc_load_deptree ()) == NULL)) + if (! deptree && ((deptree = _rc_deptree_load ()) == NULL)) eerrorx ("failed to load deptree"); rc_strlist_free (types); @@ -588,7 +588,7 @@ static void svc_start (bool deps) svclist = NULL; rc_strlist_add (&svclist, applet); rc_strlist_free (services); - services = rc_get_depends (deptree, types, svclist, softlevel, 0); + services = rc_deptree_depends (deptree, types, svclist, softlevel, 0); if (services) { eerrorn ("ERROR: `%s' needs ", applet); STRLIST_FOREACH (services, svc, i) { @@ -605,12 +605,12 @@ static void svc_start (bool deps) types = NULL; rc_strlist_add (&types, "ineed"); rc_strlist_free (need_services); - need_services = rc_get_depends (deptree, types, svclist, + need_services = rc_deptree_depends (deptree, types, svclist, softlevel, depoptions); rc_strlist_add (&types, "iuse"); rc_strlist_free (use_services); - use_services = rc_get_depends (deptree, types, svclist, + use_services = rc_deptree_depends (deptree, types, svclist, softlevel, depoptions); if (! rc_runlevel_starting ()) { @@ -624,7 +624,7 @@ static void svc_start (bool deps) /* Now wait for them to start */ rc_strlist_add (&types, "iafter"); - services = rc_get_depends (deptree, types, svclist, + services = rc_deptree_depends (deptree, types, svclist, softlevel, depoptions); /* We use tmplist to hold our scheduled by list */ @@ -686,7 +686,7 @@ static void svc_start (bool deps) svclist = NULL; rc_strlist_add (&svclist, svc); rc_strlist_free (providelist); - providelist = rc_get_depends (deptree, types, svclist, + providelist = rc_deptree_depends (deptree, types, svclist, softlevel, depoptions); STRLIST_FOREACH (providelist, svc2, j) rc_schedule_start_service (svc2, service); @@ -766,7 +766,7 @@ static void svc_start (bool deps) svclist = NULL; rc_strlist_add (&svclist, applet); rc_strlist_free (tmplist); - tmplist = rc_get_depends (deptree, types, svclist, softlevel, depoptions); + tmplist = rc_deptree_depends (deptree, types, svclist, softlevel, depoptions); STRLIST_FOREACH (tmplist, svc2, j) { rc_strlist_free (services); @@ -822,7 +822,7 @@ static void svc_stop (bool deps) if (rc_runlevel_stopping ()) depoptions |= RC_DEP_STOP; - if (! deptree && ((deptree = rc_load_deptree ()) == NULL)) + if (! deptree && ((deptree = _rc_deptree_load ()) == NULL)) eerrorx ("failed to load deptree"); rc_strlist_free (types); @@ -834,7 +834,7 @@ static void svc_stop (bool deps) rc_strlist_free (tmplist); tmplist = NULL; rc_strlist_free (services); - services = rc_get_depends (deptree, types, svclist, + services = rc_deptree_depends (deptree, types, svclist, softlevel, depoptions); rc_strlist_reverse (services); STRLIST_FOREACH (services, svc, i) { @@ -885,7 +885,7 @@ static void svc_stop (bool deps) This is important when a runlevel stops */ rc_strlist_add (&types, "usesme"); rc_strlist_add (&types, "ibefore"); - services = rc_get_depends (deptree, types, svclist, + services = rc_deptree_depends (deptree, types, svclist, softlevel, depoptions); STRLIST_FOREACH (services, svc, i) { if (rc_service_state (svc) & RC_SERVICE_STOPPED) @@ -1189,7 +1189,7 @@ int runscript (int argc, char **argv) if (rc_env_bool ("RC_DEPEND_STRICT")) depoptions |= RC_DEP_STRICT; - if (! deptree && ((deptree = rc_load_deptree ()) == NULL)) + if (! deptree && ((deptree = _rc_deptree_load ()) == NULL)) eerrorx ("failed to load deptree"); rc_strlist_free (types); @@ -1199,7 +1199,7 @@ int runscript (int argc, char **argv) svclist = NULL; rc_strlist_add (&svclist, applet); rc_strlist_free (services); - services = rc_get_depends (deptree, types, svclist, + services = rc_deptree_depends (deptree, types, svclist, softlevel, depoptions); STRLIST_FOREACH (services, svc, i) printf ("%s%s", i == 1 ? "" : " ", svc); |