openrc/src/librc.c

867 lines
18 KiB
C
Raw Normal View History

/*
librc
core RC functions
Copyright 2007 Gentoo Foundation
Released under the GPLv2
*/
#include "librc.h"
/* usecs to wait while we poll the fifo */
#define WAIT_INTERVAL 20000000
/* max nsecs to wait until a service comes up */
#define WAIT_MAX 60000000000
#define SOFTLEVEL RC_SVCDIR "/softlevel"
/* File stream used for plugins to write environ vars to */
FILE *rc_environ_fd = NULL;
static const char *rc_service_state_names[] = {
2007-04-11 18:14:47 +05:30
"started",
"stopped",
"starting",
"stopping",
"inactive",
"wasinactive",
"coldplugged",
"failed",
"scheduled",
NULL
};
2007-09-25 23:00:07 +05:30
bool rc_runlevel_starting (void)
{
2007-08-28 14:43:46 +05:30
return (rc_is_dir (RC_STARTING));
}
librc_hidden_def(rc_runlevel_starting)
2007-09-25 23:00:07 +05:30
bool rc_runlevel_stopping (void)
{
2007-08-28 14:43:46 +05:30
return (rc_is_dir (RC_STOPPING));
}
librc_hidden_def(rc_runlevel_stopping)
char **rc_get_runlevels (void)
{
char **dirs = rc_ls_dir (RC_RUNLEVELDIR, 0);
2007-04-11 18:14:47 +05:30
char **runlevels = NULL;
int i;
char *dir;
STRLIST_FOREACH (dirs, dir, i) {
char *path = rc_strcatpaths (RC_RUNLEVELDIR, dir, (char *) NULL);
2007-09-25 23:00:07 +05:30
if (rc_is_dir (path))
rc_strlist_addsort (&runlevels, dir);
2007-04-11 18:14:47 +05:30
free (path);
}
rc_strlist_free (dirs);
return (runlevels);
}
librc_hidden_def(rc_get_runlevels)
char *rc_get_runlevel (void)
{
2007-04-11 18:14:47 +05:30
FILE *fp;
char buffer[RC_LINEBUFFER];
char *runlevel = NULL;
if ((fp = fopen (SOFTLEVEL, "r"))) {
if (fgets (buffer, PATH_MAX, fp)) {
int i = strlen (buffer) - 1;
if (buffer[i] == '\n')
buffer[i] = 0;
runlevel = rc_xstrdup (buffer);
}
2007-04-11 18:14:47 +05:30
fclose (fp);
}
if (! runlevel)
runlevel = rc_xstrdup (RC_LEVEL_SYSINIT);
return (runlevel);
}
librc_hidden_def(rc_get_runlevel)
void rc_set_runlevel (const char *runlevel)
{
2007-04-11 18:14:47 +05:30
FILE *fp = fopen (SOFTLEVEL, "w");
if (! fp)
eerrorx ("failed to open `" SOFTLEVEL "': %s", strerror (errno));
fprintf (fp, "%s", runlevel);
fclose (fp);
}
librc_hidden_def(rc_set_runlevel)
2007-09-25 23:00:07 +05:30
bool rc_runlevel_exists (const char *runlevel)
{
2007-04-11 18:14:47 +05:30
char *path;
2007-09-25 23:00:07 +05:30
bool retval;
2007-04-11 18:14:47 +05:30
if (! runlevel)
2007-09-25 23:00:07 +05:30
return (false);
2007-04-11 18:14:47 +05:30
path = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, (char *) NULL);
retval = rc_is_dir (path);
free (path);
return (retval);
}
librc_hidden_def(rc_runlevel_exists)
/* Resolve a service name to it's full path */
char *rc_resolve_service (const char *service)
{
2007-04-11 18:14:47 +05:30
char buffer[PATH_MAX];
char *file;
int r = 0;
if (! service)
return (NULL);
if (service[0] == '/')
2007-09-06 14:29:35 +05:30
return (rc_xstrdup (service));
2007-04-11 18:14:47 +05:30
file = rc_strcatpaths (RC_SVCDIR, "started", service, (char *) NULL);
2007-09-25 23:00:07 +05:30
if (! rc_is_link (file)) {
2007-04-11 18:14:47 +05:30
free (file);
file = rc_strcatpaths (RC_SVCDIR, "inactive", service, (char *) NULL);
2007-09-25 23:00:07 +05:30
if (! rc_is_link (file)) {
2007-04-11 18:14:47 +05:30
free (file);
file = NULL;
}
}
memset (buffer, 0, sizeof (buffer));
if (file) {
r = readlink (file, buffer, sizeof (buffer));
free (file);
if (r > 0)
2007-04-19 20:24:35 +05:30
return (rc_xstrdup (buffer));
2007-04-11 18:14:47 +05:30
}
snprintf (buffer, sizeof (buffer), RC_INITDIR "/%s", service);
2007-09-06 14:29:35 +05:30
return (rc_xstrdup (buffer));
}
librc_hidden_def(rc_resolve_service)
2007-09-25 23:00:07 +05:30
bool rc_service_exists (const char *service)
{
2007-04-11 18:14:47 +05:30
char *file;
2007-09-25 23:00:07 +05:30
bool retval = false;
2007-04-11 18:14:47 +05:30
int len;
if (! service)
2007-09-25 23:00:07 +05:30
return (false);
2007-04-11 18:14:47 +05:30
len = strlen (service);
/* .sh files are not init scripts */
if (len > 2 && service[len - 3] == '.' &&
service[len - 2] == 's' &&
service[len - 1] == 'h')
2007-09-25 23:00:07 +05:30
return (false);
2007-04-11 18:14:47 +05:30
file = rc_resolve_service (service);
2007-09-25 23:00:07 +05:30
if (rc_exists (file))
retval = rc_is_exec (file);
2007-04-11 18:14:47 +05:30
free (file);
return (retval);
}
librc_hidden_def(rc_service_exists)
char **rc_service_options (const char *service)
{
char *svc;
char cmd[PATH_MAX];
char buffer[RC_LINEBUFFER];
char **opts = NULL;
char *token;
char *p = buffer;
FILE *fp;
if (! rc_service_exists (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);
return (NULL);
}
if (fgets (buffer, RC_LINEBUFFER, fp)) {
if (buffer[strlen (buffer) - 1] == '\n')
buffer[strlen (buffer) - 1] = '\0';
while ((token = strsep (&p, " ")))
rc_strlist_addsort (&opts, token);
}
pclose (fp);
return (opts);
}
librc_hidden_def(rc_service_options)
2007-07-11 00:44:37 +05:30
char *rc_service_description (const char *service, const char *option)
{
char *svc;
char cmd[PATH_MAX];
char buffer[RC_LINEBUFFER];
char *desc = NULL;
FILE *fp;
int i;
if (! rc_service_exists (service))
return (NULL);
svc = rc_resolve_service (service);
2007-07-11 00:44:37 +05:30
if (! option)
option = "";
snprintf (cmd, sizeof (cmd), ". '%s'; echo \"${description%s%s}\"",
2007-07-11 00:44:37 +05:30
svc, option ? "_" : "", option);
if (! (fp = popen (cmd, "r"))) {
eerror ("popen `%s': %s", svc, strerror (errno));
free (svc);
return (NULL);
}
free (svc);
while (fgets (buffer, RC_LINEBUFFER, fp)) {
if (! desc) {
desc = rc_xmalloc (strlen (buffer) + 1);
*desc = '\0';
} else {
desc = rc_xrealloc (desc, strlen (desc) + strlen (buffer) + 1);
}
i = strlen (desc);
memcpy (desc + i, buffer, strlen (buffer));
memset (desc + i + strlen (buffer), 0, 1);
}
pclose (fp);
return (desc);
}
librc_hidden_def(rc_service_description)
2007-09-25 23:00:07 +05:30
bool rc_service_in_runlevel (const char *service, const char *runlevel)
{
2007-04-11 18:14:47 +05:30
char *file;
2007-09-25 23:00:07 +05:30
bool retval;
2007-04-13 19:24:53 +05:30
char *svc;
2007-04-11 18:14:47 +05:30
if (! runlevel || ! service)
2007-09-25 23:00:07 +05:30
return (false);
2007-04-13 19:24:53 +05:30
svc = rc_xstrdup (service);
file = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, basename (svc),
2007-04-11 18:14:47 +05:30
(char *) NULL);
2007-04-13 19:24:53 +05:30
free (svc);
2007-04-11 18:14:47 +05:30
retval = rc_exists (file);
free (file);
2007-04-11 18:14:47 +05:30
return (retval);
}
librc_hidden_def(rc_service_in_runlevel)
2007-09-25 23:00:07 +05:30
bool rc_mark_service (const char *service, const rc_service_state_t state)
{
2007-04-11 18:14:47 +05:30
char *file;
int i = 0;
int skip_state = -1;
char *base;
2007-04-13 19:24:53 +05:30
char *svc;
2007-04-11 18:14:47 +05:30
char *init = rc_resolve_service (service);
bool skip_wasinactive = false;
if (! service)
2007-09-25 23:00:07 +05:30
return (false);
2007-04-11 18:14:47 +05:30
2007-04-13 19:24:53 +05:30
svc = rc_xstrdup (service);
base = basename (svc);
2007-04-11 18:14:47 +05:30
if (state != rc_service_stopped) {
2007-09-25 23:00:07 +05:30
if (! rc_is_file(init)) {
2007-04-11 18:14:47 +05:30
free (init);
2007-04-13 19:24:53 +05:30
free (svc);
2007-09-25 23:00:07 +05:30
return (false);
2007-04-11 18:14:47 +05:30
}
file = rc_strcatpaths (RC_SVCDIR, rc_service_state_names[state], base,
(char *) NULL);
2007-09-25 23:00:07 +05:30
if (rc_exists (file))
2007-04-11 18:14:47 +05:30
unlink (file);
i = symlink (init, file);
if (i != 0) {
eerror ("symlink `%s' to `%s': %s", init, file, strerror (errno));
2007-04-11 18:14:47 +05:30
free (file);
free (init);
2007-04-13 19:24:53 +05:30
free (svc);
2007-09-25 23:00:07 +05:30
return (false);
2007-04-11 18:14:47 +05:30
}
free (file);
skip_state = state;
}
if (state == rc_service_coldplugged) {
free (init);
2007-04-13 19:24:53 +05:30
free (svc);
2007-09-25 23:00:07 +05:30
return (true);
2007-04-11 18:14:47 +05:30
}
/* Remove any old states now */
i = 0;
while (rc_service_state_names[i]) {
if ((i != skip_state &&
i != rc_service_stopped &&
i != rc_service_coldplugged &&
i != rc_service_scheduled &&
i != rc_service_crashed) &&
(! skip_wasinactive || i != rc_service_wasinactive))
{
file = rc_strcatpaths (RC_SVCDIR, rc_service_state_names[i], base,
(char *) NULL);
2007-09-25 23:00:07 +05:30
if (rc_exists (file)) {
2007-04-11 18:14:47 +05:30
if ((state == rc_service_starting ||
state == rc_service_stopping) &&
i == rc_service_inactive)
{
char *wasfile = rc_strcatpaths (RC_SVCDIR,
rc_service_state_names[rc_service_wasinactive],
base, (char *) NULL);
if (symlink (init, wasfile) != 0)
eerror ("symlink `%s' to `%s': %s", init, wasfile,
strerror (errno));
skip_wasinactive = true;
free (wasfile);
}
errno = 0;
if (unlink (file) != 0 && errno != ENOENT)
eerror ("failed to delete `%s': %s", file,
strerror (errno));
}
free (file);
}
i++;
}
/* Remove the exclusive state if we're inactive */
if (state == rc_service_started ||
state == rc_service_stopped ||
state == rc_service_inactive)
{
file = rc_strcatpaths (RC_SVCDIR, "exclusive", base, (char *) NULL);
2007-09-25 23:00:07 +05:30
if (rc_exists (file))
2007-04-11 18:14:47 +05:30
if (unlink (file) != 0)
eerror ("unlink `%s': %s", file, strerror (errno));
free (file);
}
/* Remove any options and daemons the service may have stored */
if (state == rc_service_stopped) {
char *dir = rc_strcatpaths (RC_SVCDIR, "options", base, (char *) NULL);
2007-09-25 23:00:07 +05:30
if (rc_is_dir (dir))
2007-04-11 18:14:47 +05:30
rc_rm_dir (dir, true);
free (dir);
dir = rc_strcatpaths (RC_SVCDIR, "daemons", base, (char *) NULL);
2007-09-25 23:00:07 +05:30
if (rc_is_dir (dir))
2007-04-11 18:14:47 +05:30
rc_rm_dir (dir, true);
free (dir);
rc_schedule_clear (service);
}
/* These are final states, so remove us from scheduled */
if (state == rc_service_started || state == rc_service_stopped) {
char *sdir = rc_strcatpaths (RC_SVCDIR, "scheduled", (char *) NULL);
char **dirs = rc_ls_dir (sdir, 0);
2007-04-11 18:14:47 +05:30
char *dir;
int serrno;
STRLIST_FOREACH (dirs, dir, i) {
char *bdir = rc_strcatpaths (sdir, dir, (char *) NULL);
file = rc_strcatpaths (bdir, base, (char *) NULL);
2007-09-25 23:00:07 +05:30
if (rc_exists (file))
2007-04-11 18:14:47 +05:30
if (unlink (file) != 0)
eerror ("unlink `%s': %s", file, strerror (errno));
free (file);
/* Try and remove the dir - we don't care about errors */
serrno = errno;
rmdir (bdir);
errno = serrno;
free (bdir);
}
rc_strlist_free (dirs);
free (sdir);
}
2007-04-13 19:24:53 +05:30
free (svc);
2007-04-11 18:14:47 +05:30
free (init);
2007-09-25 23:00:07 +05:30
return (true);
}
librc_hidden_def(rc_mark_service)
2007-09-25 23:00:07 +05:30
bool rc_service_state (const char *service, const rc_service_state_t state)
{
2007-04-11 18:14:47 +05:30
char *file;
bool retval;
2007-04-13 19:24:53 +05:30
char *svc;
2007-04-11 18:14:47 +05:30
/* If the init script does not exist then we are stopped */
if (! rc_service_exists (service))
2007-09-25 23:00:07 +05:30
return (state == rc_service_stopped ? true : false);
2007-04-11 18:14:47 +05:30
/* We check stopped state by not being in any of the others */
if (state == rc_service_stopped)
2007-09-25 23:00:07 +05:30
return ( ! (rc_service_state (service, rc_service_started) ||
rc_service_state (service, rc_service_starting) ||
rc_service_state (service, rc_service_stopping) ||
rc_service_state (service, rc_service_inactive)));
2007-04-11 18:14:47 +05:30
/* The crashed state and scheduled states are virtual */
if (state == rc_service_crashed)
return (rc_service_daemons_crashed (service));
else if (state == rc_service_scheduled) {
char **services = rc_services_scheduled_by (service);
2007-09-25 23:00:07 +05:30
retval = (services);
if (services)
free (services);
return (retval);
2007-04-11 18:14:47 +05:30
}
/* Now we just check if a file by the service name rc_exists
in the state dir */
2007-04-13 19:24:53 +05:30
svc = rc_xstrdup (service);
2007-04-11 18:14:47 +05:30
file = rc_strcatpaths (RC_SVCDIR, rc_service_state_names[state],
2007-04-13 19:24:53 +05:30
basename (svc), (char*) NULL);
free (svc);
2007-04-11 18:14:47 +05:30
retval = rc_exists (file);
free (file);
return (retval);
}
librc_hidden_def(rc_service_state)
char *rc_get_service_option (const char *service, const char *option)
{
2007-04-11 18:14:47 +05:30
FILE *fp;
char buffer[RC_LINEBUFFER];
char *file = rc_strcatpaths (RC_SVCDIR, "options", service, option,
(char *) NULL);
char *value = NULL;
2007-04-11 18:14:47 +05:30
2007-09-25 23:00:07 +05:30
if (rc_exists (file)) {
2007-04-11 18:14:47 +05:30
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);
2007-04-11 18:14:47 +05:30
fclose (fp);
}
}
free (file);
return (value);
}
librc_hidden_def(rc_get_service_option)
2007-09-25 23:00:07 +05:30
bool rc_set_service_option (const char *service, const char *option,
2007-04-11 18:14:47 +05:30
const char *value)
{
2007-04-11 18:14:47 +05:30
FILE *fp;
char *path = rc_strcatpaths (RC_SVCDIR, "options", service, (char *) NULL);
char *file = rc_strcatpaths (path, option, (char *) NULL);
2007-09-25 23:00:07 +05:30
bool retval = false;
2007-04-11 18:14:47 +05:30
2007-09-25 23:00:07 +05:30
if (! rc_is_dir (path)) {
2007-04-11 18:14:47 +05:30
if (mkdir (path, 0755) != 0) {
eerror ("mkdir `%s': %s", path, strerror (errno));
free (path);
free (file);
2007-09-25 23:00:07 +05:30
return (false);
2007-04-11 18:14:47 +05:30
}
}
if ((fp = fopen (file, "w")) == NULL)
eerror ("fopen `%s': %s", file, strerror (errno));
else {
if (value)
fprintf (fp, "%s", value);
fclose (fp);
2007-09-25 23:00:07 +05:30
retval = true;
2007-04-11 18:14:47 +05:30
}
free (path);
free (file);
return (retval);
}
librc_hidden_def(rc_set_service_option)
static pid_t _exec_service (const char *service, const char *arg)
{
2007-04-11 18:14:47 +05:30
char *file;
char *fifo;
pid_t pid = -1;
2007-04-13 19:24:53 +05:30
char *svc;
2007-04-11 18:14:47 +05:30
file = rc_resolve_service (service);
2007-09-25 23:00:07 +05:30
if (! rc_is_file (file)) {
2007-04-11 18:14:47 +05:30
rc_mark_service (service, rc_service_stopped);
free (file);
return (0);
}
/* We create a fifo so that other services can wait until we complete */
2007-04-13 19:24:53 +05:30
svc = rc_xstrdup (service);
fifo = rc_strcatpaths (RC_SVCDIR, "exclusive", basename (svc),
2007-04-11 18:14:47 +05:30
(char *) NULL);
2007-04-13 19:24:53 +05:30
free (svc);
2007-04-11 18:14:47 +05:30
if (mkfifo (fifo, 0600) != 0 && errno != EEXIST) {
eerror ("unable to create fifo `%s': %s", fifo, strerror (errno));
free (fifo);
free (file);
return (-1);
}
if ((pid = vfork ()) == 0) {
execl (file, file, arg, (char *) NULL);
eerror ("unable to exec `%s': %s", file, strerror (errno));
2007-04-21 14:53:37 +05:30
unlink (fifo);
_exit (EXIT_FAILURE);
2007-04-11 18:14:47 +05:30
}
free (fifo);
free (file);
if (pid == -1)
eerror ("vfork: %s", strerror (errno));
return (pid);
}
2007-04-11 18:14:47 +05:30
2007-09-26 14:09:16 +05:30
int rc_waitpid (pid_t pid)
{
int status = 0;
pid_t savedpid = pid;
int retval = -1;
2007-04-11 18:14:47 +05:30
errno = 0;
while ((pid = waitpid (savedpid, &status, 0)) > 0) {
if (pid == savedpid)
retval = WIFEXITED (status) ? WEXITSTATUS (status) : EXIT_FAILURE;
}
return (retval);
}
2007-09-26 14:09:16 +05:30
librc_hidden_def(rc_waitpid)
pid_t rc_stop_service (const char *service)
{
2007-09-25 23:00:07 +05:30
if (rc_service_state (service, rc_service_stopped))
2007-04-11 18:14:47 +05:30
return (0);
2007-04-11 18:14:47 +05:30
return (_exec_service (service, "stop"));
}
librc_hidden_def(rc_stop_service)
pid_t rc_start_service (const char *service)
{
2007-09-25 23:00:07 +05:30
if (! rc_service_state (service, rc_service_stopped))
2007-04-11 18:14:47 +05:30
return (0);
2007-04-11 18:14:47 +05:30
return (_exec_service (service, "start"));
}
librc_hidden_def(rc_start_service)
void rc_schedule_start_service (const char *service,
2007-04-11 18:14:47 +05:30
const char *service_to_start)
{
2007-04-11 18:14:47 +05:30
char *dir;
char *init;
char *file;
2007-04-13 19:24:53 +05:30
char *svc;
2007-04-11 18:14:47 +05:30
/* service may be a provided service, like net */
if (! service || ! rc_service_exists (service_to_start))
return;
2007-04-13 19:24:53 +05:30
svc = rc_xstrdup (service);
dir = rc_strcatpaths (RC_SVCDIR, "scheduled", basename (svc),
2007-04-11 18:14:47 +05:30
(char *) NULL);
2007-04-13 19:24:53 +05:30
free (svc);
2007-09-25 23:00:07 +05:30
if (! rc_is_dir (dir))
2007-04-11 18:14:47 +05:30
if (mkdir (dir, 0755) != 0) {
eerror ("mkdir `%s': %s", dir, strerror (errno));
free (dir);
return;
}
init = rc_resolve_service (service_to_start);
2007-04-13 19:24:53 +05:30
svc = rc_xstrdup (service_to_start);
file = rc_strcatpaths (dir, basename (svc), (char *) NULL);
free (svc);
2007-09-25 23:00:07 +05:30
if (! rc_exists (file) && symlink (init, file) != 0)
2007-04-11 18:14:47 +05:30
eerror ("symlink `%s' to `%s': %s", init, file, strerror (errno));
free (init);
free (file);
free (dir);
}
librc_hidden_def(rc_schedule_start_service)
void rc_schedule_clear (const char *service)
{
2007-04-13 19:24:53 +05:30
char *svc = rc_xstrdup (service);
char *dir = rc_strcatpaths (RC_SVCDIR, "scheduled", basename (svc),
2007-04-11 18:14:47 +05:30
(char *) NULL);
2007-04-13 19:24:53 +05:30
free (svc);
2007-09-25 23:00:07 +05:30
if (rc_is_dir (dir))
2007-04-11 18:14:47 +05:30
rc_rm_dir (dir, true);
free (dir);
}
librc_hidden_def(rc_schedule_clear)
2007-09-25 23:00:07 +05:30
bool rc_wait_service (const char *service)
{
char *svc;
char *base;
char *fifo;
struct timespec ts;
int nloops = WAIT_MAX / WAIT_INTERVAL;
2007-09-25 23:00:07 +05:30
bool retval = false;
bool forever = false;
if (! service)
2007-09-25 23:00:07 +05:30
return (false);
2007-04-11 18:14:47 +05:30
svc = rc_xstrdup (service);
base = basename (svc);
fifo = rc_strcatpaths (RC_SVCDIR, "exclusive", base, (char *) NULL);
/* FIXME: find a better way of doing this
* Maybe a setting in the init script? */
if (strcmp (base, "checkfs") == 0 || strcmp (base, "checkroot") == 0)
forever = true;
free (svc);
ts.tv_sec = 0;
ts.tv_nsec = WAIT_INTERVAL;
while (nloops) {
2007-09-25 23:00:07 +05:30
if (! rc_exists (fifo)) {
retval = true;
2007-04-11 18:14:47 +05:30
break;
}
if (nanosleep (&ts, NULL) == -1) {
2007-04-25 23:42:49 +05:30
if (errno != EINTR) {
eerror ("nanosleep: %s", strerror (errno));
2007-04-25 23:42:49 +05:30
break;
}
2007-04-11 18:14:47 +05:30
}
if (! forever)
nloops --;
2007-04-11 18:14:47 +05:30
}
free (fifo);
return (retval);
}
librc_hidden_def(rc_wait_service)
char **rc_services_in_runlevel (const char *runlevel)
{
2007-04-11 18:14:47 +05:30
char *dir;
char **list = NULL;
2007-04-11 18:14:47 +05:30
if (! runlevel)
return (rc_ls_dir (RC_INITDIR, RC_LS_INITD));
2007-04-11 18:14:47 +05:30
/* These special levels never contain any services */
if (strcmp (runlevel, RC_LEVEL_SYSINIT) == 0 ||
strcmp (runlevel, RC_LEVEL_SINGLE) == 0)
return (NULL);
2007-04-11 18:14:47 +05:30
dir = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, (char *) NULL);
2007-09-25 23:00:07 +05:30
if (! rc_is_dir (dir))
2007-04-11 18:14:47 +05:30
eerror ("runlevel `%s' does not exist", runlevel);
else
list = rc_ls_dir (dir, RC_LS_INITD);
2007-04-11 18:14:47 +05:30
free (dir);
return (list);
}
librc_hidden_def(rc_services_in_runlevel)
char **rc_services_in_state (rc_service_state_t state)
{
2007-04-11 18:14:47 +05:30
char *dir = rc_strcatpaths (RC_SVCDIR, rc_service_state_names[state],
(char *) NULL);
char **list = NULL;
if (state == rc_service_scheduled) {
char **dirs = rc_ls_dir (dir, 0);
2007-04-11 18:14:47 +05:30
char *d;
int i;
STRLIST_FOREACH (dirs, d, i) {
char *p = rc_strcatpaths (dir, d, (char *) NULL);
char **entries = rc_ls_dir (p, RC_LS_INITD);
2007-04-11 18:14:47 +05:30
char *e;
int j;
STRLIST_FOREACH (entries, e, j)
rc_strlist_addsortu (&list, e);
2007-04-11 18:14:47 +05:30
if (entries)
free (entries);
}
if (dirs)
free (dirs);
} else {
2007-09-25 23:00:07 +05:30
if (rc_is_dir (dir))
list = rc_ls_dir (dir, RC_LS_INITD);
2007-04-11 18:14:47 +05:30
}
free (dir);
return (list);
}
librc_hidden_def(rc_services_in_state)
2007-09-25 23:00:07 +05:30
bool rc_service_add (const char *runlevel, const char *service)
{
2007-09-25 23:00:07 +05:30
bool retval;
2007-04-11 18:14:47 +05:30
char *init;
char *file;
2007-04-13 19:24:53 +05:30
char *svc;
2007-04-11 18:14:47 +05:30
if (! rc_runlevel_exists (runlevel)) {
errno = ENOENT;
2007-09-25 23:00:07 +05:30
return (false);
2007-04-11 18:14:47 +05:30
}
2007-09-25 23:00:07 +05:30
if (rc_service_in_runlevel (service, runlevel)) {
2007-04-11 18:14:47 +05:30
errno = EEXIST;
2007-09-25 23:00:07 +05:30
return (false);
2007-04-11 18:14:47 +05:30
}
init = rc_resolve_service (service);
2007-04-13 19:24:53 +05:30
svc = rc_xstrdup (service);
file = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, basename (svc),
2007-04-11 18:14:47 +05:30
(char *) NULL);
2007-04-13 19:24:53 +05:30
free (svc);
2007-09-25 23:00:07 +05:30
retval = (symlink (init, file) == 0);
2007-04-11 18:14:47 +05:30
free (init);
free (file);
return (retval);
}
librc_hidden_def(rc_service_add)
2007-09-25 23:00:07 +05:30
bool rc_service_delete (const char *runlevel, const char *service)
{
2007-04-11 18:14:47 +05:30
char *file;
2007-04-13 19:24:53 +05:30
char *svc;
2007-09-25 23:00:07 +05:30
bool retval = false;
2007-04-11 18:14:47 +05:30
if (! runlevel || ! service)
2007-09-25 23:00:07 +05:30
return (false);
2007-04-10 16:54:58 +05:30
2007-04-13 19:24:53 +05:30
svc = rc_xstrdup (service);
file = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, basename (svc),
2007-04-11 18:14:47 +05:30
(char *) NULL);
2007-04-13 19:24:53 +05:30
free (svc);
2007-09-25 23:00:07 +05:30
if (unlink (file) == 0)
retval = true;
2007-04-11 18:14:47 +05:30
free (file);
return (retval);
}
librc_hidden_def(rc_service_delete)
char **rc_services_scheduled_by (const char *service)
{
char **dirs = rc_ls_dir (RC_SVCDIR "/scheduled", 0);
2007-04-11 18:14:47 +05:30
char **list = NULL;
char *dir;
int i;
STRLIST_FOREACH (dirs, dir, i) {
char *file = rc_strcatpaths (RC_SVCDIR, "scheduled", dir, service,
2007-04-11 18:14:47 +05:30
(char *) NULL);
2007-09-25 23:00:07 +05:30
if (rc_exists (file))
rc_strlist_add (&list, file);
2007-04-11 18:14:47 +05:30
free (file);
}
rc_strlist_free (dirs);
return (list);
}
librc_hidden_def(rc_services_scheduled_by)
char **rc_services_scheduled (const char *service)
{
2007-04-13 19:24:53 +05:30
char *svc = rc_xstrdup (service);
char *dir = rc_strcatpaths (RC_SVCDIR, "scheduled", basename (svc),
2007-04-11 18:14:47 +05:30
(char *) NULL);
char **list = NULL;
2007-09-25 23:00:07 +05:30
if (rc_is_dir (dir))
list = rc_ls_dir (dir, RC_LS_INITD);
2007-04-13 19:24:53 +05:30
free (svc);
2007-04-11 18:14:47 +05:30
free (dir);
return (list);
}
librc_hidden_def(rc_services_scheduled)
2007-09-25 23:00:07 +05:30
bool rc_allow_plug (char *service)
{
2007-04-11 18:14:47 +05:30
char *list;
char *p;
char *star;
char *token;
2007-09-25 23:00:07 +05:30
bool allow = true;
2007-04-11 18:14:47 +05:30
char *match = getenv ("RC_PLUG_SERVICES");
if (! match)
2007-09-25 23:00:07 +05:30
return true;
2007-04-11 18:14:47 +05:30
2007-04-13 19:24:53 +05:30
list = rc_xstrdup (match);
2007-04-11 18:14:47 +05:30
p = list;
while ((token = strsep (&p, " "))) {
2007-09-25 23:00:07 +05:30
bool truefalse = true;
2007-04-11 18:14:47 +05:30
if (token[0] == '!') {
2007-09-25 23:00:07 +05:30
truefalse = false;
2007-04-11 18:14:47 +05:30
token++;
}
star = strchr (token, '*');
if (star) {
if (strncmp (service, token, star - token) == 0) {
allow = truefalse;
break;
}
} else {
if (strcmp (service, token) == 0) {
allow = truefalse;
break;
}
}
}
free (list);
return (allow);
}
librc_hidden_def(rc_allow_plug)