aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/includes/helpers.h17
-rw-r--r--src/includes/rc-misc.h24
-rw-r--r--src/rc/Makefile133
-rw-r--r--src/rc/_usage.c32
-rw-r--r--src/rc/_usage.h13
-rw-r--r--src/rc/builtins.h34
-rw-r--r--src/rc/checkpath.c59
-rw-r--r--src/rc/do_e.c228
-rw-r--r--src/rc/do_mark_service.c91
-rw-r--r--src/rc/do_service.c78
-rw-r--r--src/rc/do_value.c64
-rw-r--r--src/rc/fstabinfo.c55
-rw-r--r--src/rc/is_newer_than.c33
-rw-r--r--src/rc/is_older_than.c34
-rw-r--r--src/rc/mountinfo.c80
-rw-r--r--src/rc/openrc-run.c59
-rw-r--r--src/rc/rc-abort.c43
-rw-r--r--src/rc/rc-applets.c557
-rw-r--r--src/rc/rc-depend.c72
-rw-r--r--src/rc/rc-misc.c107
-rw-r--r--src/rc/rc-selinux.c4
-rw-r--r--src/rc/rc-service.c28
-rw-r--r--src/rc/rc-status.c86
-rw-r--r--src/rc/rc-update.c46
-rw-r--r--src/rc/rc.c55
-rw-r--r--src/rc/shell_var.c41
-rw-r--r--src/rc/start-stop-daemon.c133
-rw-r--r--src/rc/swclock.c21
28 files changed, 1160 insertions, 1067 deletions
diff --git a/src/includes/helpers.h b/src/includes/helpers.h
index c541f99a..1a00d3d0 100644
--- a/src/includes/helpers.h
+++ b/src/includes/helpers.h
@@ -53,6 +53,9 @@
} while (/* CONSTCOND */ 0)
#endif
+#include <stdbool.h>
+#include <sys/stat.h>
+
_unused static void *xmalloc (size_t size)
{
void *value = malloc(size);
@@ -104,4 +107,18 @@ _unused static const char *basename_c(const char *path)
return (path);
}
+_unused static bool exists(const char *pathname)
+{
+ struct stat buf;
+
+ return (stat(pathname, &buf) == 0);
+}
+
+_unused static bool existss(const char *pathname)
+{
+ struct stat buf;
+
+ return (stat(pathname, &buf) == 0 && buf.st_size != 0);
+}
+
#endif
diff --git a/src/includes/rc-misc.h b/src/includes/rc-misc.h
index 89d6336b..96166341 100644
--- a/src/includes/rc-misc.h
+++ b/src/includes/rc-misc.h
@@ -26,6 +26,7 @@
#include <unistd.h>
#include "helpers.h"
+#include "rc.h"
#define RC_LEVEL_BOOT "boot"
#define RC_LEVEL_DEFAULT "default"
@@ -41,20 +42,6 @@
#define RC_SVCDIR_STARTED RC_SVCDIR "/started"
#define RC_SVCDIR_COLDPLUGGED RC_SVCDIR "/coldplugged"
-_unused static bool exists(const char *pathname)
-{
- struct stat buf;
-
- return (stat(pathname, &buf) == 0);
-}
-
-_unused static bool existss(const char *pathname)
-{
- struct stat buf;
-
- return (stat(pathname, &buf) == 0 && buf.st_size != 0);
-}
-
char *rc_conf_value(const char *var);
bool rc_conf_yesno(const char *var);
void env_filter(void);
@@ -78,4 +65,13 @@ const char *detect_prefix(void);
const char *get_systype(void);
const char *detect_container(void);
const char *detect_vm(void);
+
+/* Handy function so we can wrap einfo around our deptree */
+RC_DEPTREE *_rc_deptree_load (int, int *);
+
+/* Test to see if we can see pid 1 or not */
+bool _rc_can_find_pids(void);
+
+RC_SERVICE lookup_service_state(const char *service);
+
#endif
diff --git a/src/rc/Makefile b/src/rc/Makefile
index 65b58113..1df26d86 100644
--- a/src/rc/Makefile
+++ b/src/rc/Makefile
@@ -1,8 +1,4 @@
-PROG= openrc
-SRCS= checkpath.c fstabinfo.c mountinfo.c openrc-run.c \
- rc-applets.c rc-depend.c rc-logger.c \
- rc-misc.c rc-plugin.c rc-service.c rc-status.c rc-update.c \
- rc.c start-stop-daemon.c swclock.c
+SRCS= rc.c rc-logger.c rc-misc.c rc-plugin.c
ifeq (${MKSELINUX},yes)
SRCS+= rc-selinux.c
@@ -14,26 +10,26 @@ BINDIR= ${PREFIX}/bin
SBINDIR= ${PREFIX}/sbin
LINKDIR= ${LIBEXECDIR}
-BINLINKS= rc-status
-SBINLINKS= rc rc-service rc-update openrc-run runscript service \
- start-stop-daemon
-RC_BINLINKS= einfon einfo ewarnn ewarn eerrorn eerror ebegin eend ewend \
- eindent eoutdent esyslog eval_ecolors ewaitfile \
- veinfo vewarn vebegin veend vewend veindent veoutdent \
- service_starting service_started \
- service_stopping service_stopped \
- service_inactive service_wasinactive \
- service_hotplugged service_started_daemon service_crashed \
- checkpath fstabinfo mountinfo rc-depend \
- service_get_value service_set_value get_options save_options \
- shell_var is_newer_than is_older_than
-RC_SBINLINKS= mark_service_starting mark_service_started \
+BINPROGS= rc-status
+SBINPROGS = openrc openrc-run rc rc-service rc-update runscript service start-stop-daemon
+RC_BINPROGS= einfon einfo ewarnn ewarn eerrorn eerror ebegin eend ewend \
+ eindent eoutdent esyslog eval_ecolors ewaitfile \
+ veinfo vewarn vebegin veend vewend veindent veoutdent \
+ checkpath fstabinfo mountinfo rc-depend \
+ is_newer_than is_older_than \
+ service_get_value service_set_value get_options save_options \
+ service_starting service_started \
+ service_stopping service_stopped \
+ service_inactive service_wasinactive \
+ service_hotplugged service_started_daemon service_crashed \
+ shell_var
+RC_SBINPROGS= mark_service_starting mark_service_started \
mark_service_stopping mark_service_stopped \
mark_service_inactive mark_service_wasinactive \
mark_service_hotplugged mark_service_failed \
rc-abort swclock
-ALL_LINKS= ${BINLINKS} ${SBINLINKS} ${RC_BINLINKS} ${RC_SBINLINKS}
-CLEANFILES+= ${ALL_LINKS}
+ALL_PROGS= ${BINPROGS} ${SBINPROGS} ${RC_BINPROGS} ${RC_SBINPROGS}
+CLEANFILES+= ${ALL_PROGS}
LOCAL_CPPFLAGS=-I../includes -I../librc -I../libeinfo
LOCAL_LDFLAGS=-L../librc -L../libeinfo
@@ -49,22 +45,6 @@ include ${MK}/termcap.mk
LDADD+= ${LIBDL} ${LIBKVM}
include ${MK}/pam.mk
-# create symlinks to rc if not an SELINUX system, otherwise create a wrapper
-# script to call rc with the proper name of the applet to execute.
-# $1 is a list of the links
-# $2 is the path+name of the target to link to (usually 'rc' or '/sbin/rc')
-# $3 is the path where the links are created
-define make-links
- for x in $(1); do \
- if [ "${MKSELINUX}" = yes ]; then \
- printf '#!/bin/sh\nexec ${2} --applet %s "$$@"\n' $$x >${3}/$$x; \
- chmod ${BINMODE} ${3}/$$x; \
- else \
- ln -sf ${2} ${3}/$$x; \
- fi; \
- done;
-endef
-
${SRCS}: version.h
.PHONY: version.h.tmp
@@ -79,15 +59,13 @@ version.h: version.h.tmp
install: all
${INSTALL} -d ${DESTDIR}${SBINDIR}
- ${INSTALL} -m ${BINMODE} ${PROG} ${DESTDIR}${SBINDIR}
+ ${INSTALL} -m ${BINMODE} ${SBINPROGS} ${DESTDIR}${SBINDIR}
${INSTALL} -d ${DESTDIR}${BINDIR}
- $(call make-links,${BINLINKS},${SBINDIR}/${PROG},${DESTDIR}${BINDIR})
- ${INSTALL} -d ${DESTDIR}${SBINDIR}
- $(call make-links,${SBINLINKS},${SBINDIR}/${PROG},${DESTDIR}${SBINDIR})
+ ${INSTALL} -m ${BINMODE} ${BINPROGS} ${DESTDIR}${BINDIR}
${INSTALL} -d ${DESTDIR}${LINKDIR}/bin
- $(call make-links,${RC_BINLINKS},${SBINDIR}/${PROG},${DESTDIR}${LINKDIR}/bin)
+ ${INSTALL} -m ${BINMODE} ${RC_BINPROGS} ${DESTDIR}${LINKDIR}/bin
${INSTALL} -d ${DESTDIR}${LINKDIR}/sbin
- $(call make-links, ${RC_SBINLINKS},${SBINDIR}/${PROG},${DESTDIR}${LINKDIR}/sbin)
+ ${INSTALL} -m ${BINMODE} ${RC_SBINPROGS} ${DESTDIR}${LINKDIR}/sbin
if test "${MKPAM}" = pam; then \
${INSTALL} -d ${DESTDIR}${PAMDIR}; \
${INSTALL} -m ${PAMMODE} start-stop-daemon.pam ${DESTDIR}${PAMDIR}/start-stop-daemon; \
@@ -95,5 +73,70 @@ install: all
check test::
-links: ${PROG}
- $(call make-links,${ALL_LINKS},${PROG},.)
+all: ${ALL_PROGS}
+
+checkpath: checkpath.o _usage.o rc-misc.o rc-selinux.o
+ ${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
+
+einfon einfo ewarnn ewarn eerrorn eerror ebegin eend ewend \
+eindent eoutdent esyslog eval_ecolors ewaitfile \
+veinfo vewarn vebegin veend vewend veindent veoutdent: do_e.o rc-misc.o
+ ${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
+
+fstabinfo: fstabinfo.o _usage.o rc-misc.o
+ ${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
+
+is_newer_than: is_newer_than.o rc-misc.o
+ ${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
+
+is_older_than: is_older_than.o rc-misc.o
+ ${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
+
+mark_service_starting mark_service_started \
+mark_service_stopping mark_service_stopped \
+mark_service_inactive mark_service_wasinactive \
+mark_service_hotplugged mark_service_failed: do_mark_service.o rc-misc.o
+ ${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
+
+mountinfo: mountinfo.o _usage.o rc-misc.o
+ ${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
+
+openrc rc: rc.o rc-logger.o rc-misc.o rc-plugin.o rc-selinux.o _usage.o
+ ${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
+
+openrc-run runscript: openrc-run.o _usage.o rc-misc.o rc-plugin.o
+ ${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
+
+rc-abort: rc-abort.o
+ ${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ -leinfo
+
+rc-depend: rc-depend.o _usage.o rc-misc.o
+ ${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
+
+rc-status: rc-status.o _usage.o rc-misc.o
+ ${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
+
+rc-service service: rc-service.o _usage.o rc-misc.o
+ ${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
+
+rc-update: rc-update.o _usage.o rc-misc.o
+ ${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
+
+start-stop-daemon: start-stop-daemon.o _usage.o rc-misc.o
+ ${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
+
+service_get_value service_set_value get_options save_options: do_value.o rc-misc.o
+ ${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
+
+service_starting service_started \
+service_stopping service_stopped \
+service_inactive service_wasinactive \
+service_hotplugged service_started_daemon \
+service_crashed: do_service.o rc-misc.o
+ ${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
+
+shell_var: shell_var.o
+ ${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^
+
+swclock: swclock.o _usage.o rc-misc.o
+ ${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
diff --git a/src/rc/_usage.c b/src/rc/_usage.c
index e190eb40..f0c7f0fc 100644
--- a/src/rc/_usage.c
+++ b/src/rc/_usage.c
@@ -10,8 +10,12 @@
* except according to the terms contained in the LICENSE file.
*/
-#include "version.h"
#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "rc-misc.h"
+#include "_usage.h"
+#include "version.h"
#if lint
# define _noreturn
@@ -22,7 +26,7 @@
# define _noreturn
#endif
-static void set_quiet_options(void)
+void set_quiet_options(void)
{
static int qcount = 0;
@@ -37,8 +41,7 @@ static void set_quiet_options(void)
}
}
-_noreturn static void
-show_version(void)
+_noreturn void show_version(void)
{
const char *systype = NULL;
@@ -56,8 +59,7 @@ show_version(void)
exit(EXIT_SUCCESS);
}
-_noreturn static void
-usage(int exit_status)
+_noreturn void usage(int exit_status)
{
const char * const has_arg[] = { "", "<arg>", "[arg]" };
int i;
@@ -67,15 +69,15 @@ usage(int exit_status)
char *token;
char val[4] = "-?,";
-#ifdef usagestring
- printf(usagestring);
-#else
- printf("Usage: %s [options] ", applet);
-#endif
-#ifdef extraopts
- printf(extraopts);
-#endif
- printf("\n\nOptions: [" getoptstring "]\n");
+ if (usagestring)
+ printf("%s", usagestring);
+ else
+ printf("Usage: %s [options] ", applet);
+
+ if (extraopts)
+ printf("%s", extraopts);
+
+ printf("\n\nOptions: [ %s ]\n", getoptstring);
for (i = 0; longopts[i].name; ++i) {
val[1] = longopts[i].val;
len = printf(" %3s --%s %s", isprint(longopts[i].val) ? val : "",
diff --git a/src/rc/_usage.h b/src/rc/_usage.h
index dc859098..fd20971b 100644
--- a/src/rc/_usage.h
+++ b/src/rc/_usage.h
@@ -10,6 +10,8 @@
* except according to the terms contained in the LICENSE file.
*/
+#include <getopt.h>
+
#define getoptstring_COMMON "ChqVv"
#define longopts_COMMON \
@@ -41,3 +43,14 @@
case 'v': case_RC_COMMON_getopt_case_v; break; \
case 'q': case_RC_COMMON_getopt_case_q; break; \
default: case_RC_COMMON_getopt_default; break;
+
+extern const char *applet;
+extern const char *extraopts;
+extern const char *getoptstring;
+extern const struct option longopts[];
+extern const char * const longopts_help[];
+extern const char *usagestring;
+
+void set_quiet_options(void);
+void show_version(void);
+void usage(int exit_status);
diff --git a/src/rc/builtins.h b/src/rc/builtins.h
deleted file mode 100644
index ce2828f2..00000000
--- a/src/rc/builtins.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2007-2015 The OpenRC Authors.
- * See the Authors file at the top-level directory of this distribution and
- * https://github.com/OpenRC/openrc/blob/master/AUTHORS
- *
- * This file is part of OpenRC. It is subject to the license terms in
- * the LICENSE file found in the top-level directory of this
- * distribution and at https://github.com/OpenRC/openrc/blob/master/LICENSE
- * This file may not be copied, modified, propagated, or distributed
- * except according to the terms contained in the LICENSE file.
- */
-
-#include "queue.h"
-#include "rc.h"
-
-int checkpath(int, char **);
-int fstabinfo(int, char **);
-int mountinfo(int, char **);
-int openrc_run(int, char **);
-int rc_depend(int, char **);
-int rc_service(int, char **);
-int rc_status(int, char **);
-int rc_update(int, char **);
-int runscript(int, char **);
-int start_stop_daemon(int, char **);
-int swclock(int, char **);
-
-void run_applets(int, char **);
-
-/* Handy function so we can wrap einfo around our deptree */
-RC_DEPTREE *_rc_deptree_load (int, int *);
-
-/* Test to see if we can see pid 1 or not */
-bool _rc_can_find_pids(void);
diff --git a/src/rc/checkpath.c b/src/rc/checkpath.c
index b5a85891..c44ffe8d 100644
--- a/src/rc/checkpath.c
+++ b/src/rc/checkpath.c
@@ -29,10 +29,10 @@
#include <string.h>
#include <unistd.h>
-#include "builtins.h"
#include "einfo.h"
#include "rc-misc.h"
#include "rc-selinux.h"
+#include "_usage.h"
typedef enum {
inode_unknown = 0,
@@ -41,7 +41,32 @@ typedef enum {
inode_fifo = 3,
} inode_t;
-extern const char *applet;
+const char *applet = NULL;
+const char *extraopts ="path1 [path2] [...]";
+const char *getoptstring = "dDfFpm:o:W" getoptstring_COMMON;
+const struct option longopts[] = {
+ { "directory", 0, NULL, 'd'},
+ { "directory-truncate", 0, NULL, 'D'},
+ { "file", 0, NULL, 'f'},
+ { "file-truncate", 0, NULL, 'F'},
+ { "pipe", 0, NULL, 'p'},
+ { "mode", 1, NULL, 'm'},
+ { "owner", 1, NULL, 'o'},
+ { "writable", 0, NULL, 'W'},
+ longopts_COMMON
+};
+const char * const longopts_help[] = {
+ "Create a directory if not exists",
+ "Create/empty directory",
+ "Create a file if not exists",
+ "Truncate file",
+ "Create a named pipe (FIFO) if not exists",
+ "Mode to check",
+ "Owner to check (user:group)",
+ "Check whether the path is writable or not",
+ longopts_help_COMMON
+};
+const char *usagestring = NULL;
static int do_check(char *path, uid_t uid, gid_t gid, mode_t mode,
inode_t type, bool trunc, bool chowner, bool selinux_on)
@@ -187,34 +212,7 @@ static int parse_owner(struct passwd **user, struct group **group,
return retval;
}
-#include "_usage.h"
-#define extraopts "path1 [path2] [...]"
-#define getoptstring "dDfFpm:o:W" getoptstring_COMMON
-static const struct option longopts[] = {
- { "directory", 0, NULL, 'd'},
- { "directory-truncate", 0, NULL, 'D'},
- { "file", 0, NULL, 'f'},
- { "file-truncate", 0, NULL, 'F'},
- { "pipe", 0, NULL, 'p'},
- { "mode", 1, NULL, 'm'},
- { "owner", 1, NULL, 'o'},
- { "writable", 0, NULL, 'W'},
- longopts_COMMON
-};
-static const char * const longopts_help[] = {
- "Create a directory if not exists",
- "Create/empty directory",
- "Create a file if not exists",
- "Truncate file",
- "Create a named pipe (FIFO) if not exists",
- "Mode to check",
- "Owner to check (user:group)",
- "Check whether the path is writable or not",
- longopts_help_COMMON
-};
-#include "_usage.c"
-
-int checkpath(int argc, char **argv)
+int main(int argc, char **argv)
{
int opt;
uid_t uid = geteuid();
@@ -229,6 +227,7 @@ int checkpath(int argc, char **argv)
bool writable = false;
bool selinux_on = false;
+ applet = basename_c(argv[0]);
while ((opt = getopt_long(argc, argv, getoptstring,
longopts, (int *) 0)) != -1)
{
diff --git a/src/rc/do_e.c b/src/rc/do_e.c
new file mode 100644
index 00000000..426087e9
--- /dev/null
+++ b/src/rc/do_e.c
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) 2007-2015 The OpenRC Authors.
+ * See the Authors file at the top-level directory of this distribution and
+ * https://github.com/OpenRC/openrc/blob/master/AUTHORS
+ *
+ * This file is part of OpenRC. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution and at https://github.com/OpenRC/openrc/blob/master/LICENSE
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file.
+ */
+
+#define SYSLOG_NAMES
+
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include <errno.h>
+#include <ctype.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <string.h>
+#include <syslog.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "einfo.h"
+#include "helpers.h"
+
+/* usecs to wait while we poll the file existance */
+#define WAIT_INTERVAL 20000000
+
+const char *applet = NULL;
+
+static int syslog_decode(char *name, CODE *codetab)
+{
+ CODE *c;
+
+ if (isdigit((unsigned char)*name))
+ return atoi(name);
+
+ for (c = codetab; c->c_name; c++)
+ if (! strcasecmp(name, c->c_name))
+ return c->c_val;
+
+ return -1;
+}
+
+int main(int argc, char **argv)
+{
+ int retval = EXIT_SUCCESS;
+ int i;
+ size_t l = 0;
+ char *message = NULL;
+ char *p;
+ int level = 0;
+ struct timespec ts;
+ struct timeval stop, now;
+ int (*e) (const char *, ...) EINFO_PRINTF(1, 2) = NULL;
+ int (*ee) (int, const char *, ...) EINFO_PRINTF(2, 3) = NULL;
+
+ applet = basename_c(argv[0]);
+ argc--;
+ argv++;
+
+ if (strcmp(applet, "eval_ecolors") == 0) {
+ printf("GOOD='%s'\nWARN='%s'\nBAD='%s'\nHILITE='%s'\nBRACKET='%s'\nNORMAL='%s'\n",
+ ecolor(ECOLOR_GOOD),
+ ecolor(ECOLOR_WARN),
+ ecolor(ECOLOR_BAD),
+ ecolor(ECOLOR_HILITE),
+ ecolor(ECOLOR_BRACKET),
+ ecolor(ECOLOR_NORMAL));
+ exit(EXIT_SUCCESS);
+ }
+
+ if (argc > 0) {
+ if (strcmp(applet, "eend") == 0 ||
+ strcmp(applet, "ewend") == 0 ||
+ strcmp(applet, "veend") == 0 ||
+ strcmp(applet, "vweend") == 0 ||
+ strcmp(applet, "ewaitfile") == 0)
+ {
+ errno = 0;
+ retval = (int)strtoimax(argv[0], &p, 0);
+ if (!p || *p != '\0')
+ errno = EINVAL;
+ if (errno)
+ retval = EXIT_FAILURE;
+ else {
+ argc--;
+ argv++;
+ }
+ } else if (strcmp(applet, "esyslog") == 0 ||
+ strcmp(applet, "elog") == 0) {
+ p = strchr(argv[0], '.');
+ if (!p ||
+ (level = syslog_decode(p + 1, prioritynames)) == -1)
+ eerrorx("%s: invalid log level `%s'", applet, argv[0]);
+
+ if (argc < 3)
+ eerrorx("%s: not enough arguments", applet);
+
+ unsetenv("EINFO_LOG");
+ setenv("EINFO_LOG", argv[1], 1);
+
+ argc -= 2;
+ argv += 2;
+ }
+ }
+
+ if (strcmp(applet, "ewaitfile") == 0) {
+ if (errno)
+ eerrorx("%s: invalid timeout", applet);
+ if (argc == 0)
+ eerrorx("%s: not enough arguments", applet);
+
+ gettimeofday(&stop, NULL);
+ /* retval stores the timeout */
+ stop.tv_sec += retval;
+ ts.tv_sec = 0;
+ ts.tv_nsec = WAIT_INTERVAL;
+ for (i = 0; i < argc; i++) {
+ ebeginv("Waiting for %s", argv[i]);
+ for (;;) {
+ if (exists(argv[i]))
+ break;
+ if (nanosleep(&ts, NULL) == -1)
+ return EXIT_FAILURE;
+ gettimeofday(&now, NULL);
+ if (retval <= 0)
+ continue;
+ if (timercmp(&now, &stop, <))
+ continue;
+ eendv(EXIT_FAILURE,
+ "timed out waiting for %s", argv[i]);
+ return EXIT_FAILURE;
+ }
+ eendv(EXIT_SUCCESS, NULL);
+ }
+ return EXIT_SUCCESS;
+ }
+
+ if (argc > 0) {
+ for (i = 0; i < argc; i++)
+ l += strlen(argv[i]) + 1;
+
+ message = xmalloc(l);
+ p = message;
+
+ for (i = 0; i < argc; i++) {
+ if (i > 0)
+ *p++ = ' ';
+ l = strlen(argv[i]);
+ memcpy(p, argv[i], l);
+ p += l;
+ }
+ *p = 0;
+ }
+
+ if (strcmp(applet, "einfo") == 0)
+ e = einfo;
+ else if (strcmp(applet, "einfon") == 0)
+ e = einfon;
+ else if (strcmp(applet, "ewarn") == 0)
+ e = ewarn;
+ else if (strcmp(applet, "ewarnn") == 0)
+ e = ewarnn;
+ else if (strcmp(applet, "eerror") == 0) {
+ e = eerror;
+ retval = 1;
+ } else if (strcmp(applet, "eerrorn") == 0) {
+ e = eerrorn;
+ retval = 1;
+ } else if (strcmp(applet, "ebegin") == 0)
+ e = ebegin;
+ else if (strcmp(applet, "eend") == 0)
+ ee = eend;
+ else if (strcmp(applet, "ewend") == 0)
+ ee = ewend;
+ else if (strcmp(applet, "esyslog") == 0) {
+ elog(retval, "%s", message);
+ retval = 0;
+ } else if (strcmp(applet, "veinfo") == 0)
+ e = einfov;
+ else if (strcmp(applet, "veinfon") == 0)
+ e = einfovn;
+ else if (strcmp(applet, "vewarn") == 0)
+ e = ewarnv;
+ else if (strcmp(applet, "vewarnn") == 0)
+ e = ewarnvn;
+ else if (strcmp(applet, "vebegin") == 0)
+ e = ebeginv;
+ else if (strcmp(applet, "veend") == 0)
+ ee = eendv;
+ else if (strcmp(applet, "vewend") == 0)
+ ee = ewendv;
+ else if (strcmp(applet, "eindent") == 0)
+ eindent();
+ else if (strcmp(applet, "eoutdent") == 0)
+ eoutdent();
+ else if (strcmp(applet, "veindent") == 0)
+ eindentv();
+ else if (strcmp(applet, "veoutdent") == 0)
+ eoutdentv();
+ else {
+ eerror("%s: unknown applet", applet);
+ retval = EXIT_FAILURE;
+ }
+
+ if (message) {
+ if (e)
+ e("%s", message);
+ else if (ee)
+ ee(retval, "%s", message);
+ } else {
+ if (e)
+ e(NULL);
+ else if (ee)
+ ee(retval, NULL);
+ }
+
+ free(message);
+ return retval;
+}
diff --git a/src/rc/do_mark_service.c b/src/rc/do_mark_service.c
new file mode 100644
index 00000000..fea31eec
--- /dev/null
+++ b/src/rc/do_mark_service.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2007-2015 The OpenRC Authors.
+ * See the Authors file at the top-level directory of this distribution and
+ * https://github.com/OpenRC/openrc/blob/master/AUTHORS
+ *
+ * This file is part of OpenRC. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution and at https://github.com/OpenRC/openrc/blob/master/LICENSE
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file.
+ */
+
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include <errno.h>
+#include <ctype.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <string.h>
+#include <syslog.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "einfo.h"
+#include "rc.h"
+#include "rc-misc.h"
+
+const char *applet = NULL;
+
+int main(int argc, char **argv)
+{
+ bool ok = false;
+ char *svcname = getenv("RC_SVCNAME");
+ char *service = NULL;
+ char *openrc_pid;
+ /* char *mtime; */
+ pid_t pid;
+ RC_SERVICE bit;
+ /* size_t l; */
+
+ applet = basename_c(argv[0]);
+ if (argc > 1)
+ service = argv[1];
+ else
+ service = svcname;
+
+ if (service == NULL || *service == '\0')
+ eerrorx("%s: no service specified", applet);
+
+ if (!strncmp(applet, "mark_", 5) &&
+ (bit = lookup_service_state(applet + 5)))
+ ok = rc_service_mark(service, bit);
+ else
+ eerrorx("%s: unknown applet", applet);
+
+ /* If we're marking ourselves then we need to inform our parent
+ openrc-run process so they do not mark us based on our exit code */
+ /*
+ * FIXME: svcname and service are almost always equal except called from a
+ * shell with just argv[1] - So that doesn't seem to do what Roy initially
+ * expected.
+ * See 20120424041423.GA23657@odin.qasl.de (Tue, 24 Apr 2012 06:14:23 +0200,
+ * openrc@gentoo.org).
+ */
+ if (ok && svcname && strcmp(svcname, service) == 0) {
+ openrc_pid = getenv("RC_OPENRC_PID");
+ if (openrc_pid && sscanf(openrc_pid, "%d", &pid) == 1)
+ if (kill(pid, SIGHUP) != 0)
+ eerror("%s: failed to signal parent %d: %s",
+ applet, pid, strerror(errno));
+
+ /* Remove the exclusive time test. This ensures that it's not
+ in control as well */
+ /*
+ l = strlen(RC_SVCDIR "/exclusive") + strlen(svcname) +
+ strlen(openrc_pid) + 4;
+ mtime = xmalloc(l);
+ snprintf(mtime, l, RC_SVCDIR "/exclusive/%s.%s",
+ svcname, openrc_pid);
+ if (exists(mtime) && unlink(mtime) != 0)
+ eerror("%s: unlink: %s", applet, strerror(errno));
+ free(mtime);
+ */
+ }
+
+ return ok ? EXIT_SUCCESS : EXIT_FAILURE;
+}
diff --git a/src/rc/do_service.c b/src/rc/do_service.c
new file mode 100644
index 00000000..3c39d35f
--- /dev/null
+++ b/src/rc/do_service.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2007-2015 The OpenRC Authors.
+ * See the Authors file at the top-level directory of this distribution and
+ * https://github.com/OpenRC/openrc/blob/master/AUTHORS
+ *
+ * This file is part of OpenRC. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution and at https://github.com/OpenRC/openrc/blob/master/LICENSE
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file.
+ */
+
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include <errno.h>
+#include <ctype.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <string.h>
+#include <syslog.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "einfo.h"
+#include "rc.h"
+#include "rc-misc.h"
+
+const char *applet = NULL;
+
+int main(int argc, char **argv)
+{
+ bool ok = false;
+ char *service;
+ char *exec;
+ int idx;
+ RC_SERVICE state, bit;
+
+ applet = basename_c(argv[0]);
+ if (argc > 1)
+ service = argv[1];
+ else
+ service = getenv("RC_SVCNAME");
+
+ if (service == NULL || *service == '\0')
+ eerrorx("%s: no service specified", applet);
+
+ state = rc_service_state(service);
+ bit = lookup_service_state(applet);
+ if (bit) {
+ ok = (state & bit);
+ } else if (strcmp(applet, "service_started_daemon") == 0) {
+ service = getenv("RC_SVCNAME");
+ exec = argv[1];
+ if (argc > 3) {
+ service = argv[1];
+ exec = argv[2];
+ sscanf(argv[3], "%d", &idx);
+ } else if (argc == 3) {
+ if (sscanf(argv[2], "%d", &idx) != 1) {
+ service = argv[1];
+ exec = argv[2];
+ }
+ }
+ ok = rc_service_started_daemon(service, exec, NULL, idx);
+
+ } else if (strcmp(applet, "service_crashed") == 0) {
+ ok = (_rc_can_find_pids() &&
+ rc_service_daemons_crashed(service) &&
+ errno != EACCES);
+ } else
+ eerrorx("%s: unknown applet", applet);
+
+ return ok ? EXIT_SUCCESS : EXIT_FAILURE;
+}
diff --git a/src/rc/do_value.c b/src/rc/do_value.c
new file mode 100644
index 00000000..a511afd9
--- /dev/null
+++ b/src/rc/do_value.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2016 The OpenRC Authors.
+ * See the Authors file at the top-level directory of this distribution and
+ * https://github.com/OpenRC/openrc/blob/master/AUTHORS
+ *
+ * This file is part of OpenRC. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution and at https://github.com/OpenRC/openrc/blob/master/LICENSE
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file.
+ */
+
+#define SYSLOG_NAMES
+
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include <errno.h>
+#include <ctype.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <string.h>
+#include <syslog.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "einfo.h"
+#include "rc-misc.h"
+
+const char *applet = NULL;
+
+int main(int argc, char **argv)
+{
+ bool ok = false;
+ char *service = getenv("RC_SVCNAME");
+ char *option;
+
+ applet = basename_c(argv[0]);
+ if (service == NULL)
+ eerrorx("%s: no service specified", applet);
+
+ if (argc < 2 || ! argv[1] || *argv[1] == '\0')
+ eerrorx("%s: no option specified", applet);
+
+ if (strcmp(applet, "service_get_value") == 0 ||
+ strcmp(applet, "get_options") == 0)
+ {
+ option = rc_service_value_get(service, argv[1]);
+ if (option) {
+ printf("%s", option);
+ free(option);
+ ok = true;
+ }
+ } else if (strcmp(applet, "service_set_value") == 0 ||
+ strcmp(applet, "save_options") == 0)
+ ok = rc_service_value_set(service, argv[1], argv[2]);
+ else
+ eerrorx("%s: unknown applet", applet);
+
+ return ok ? EXIT_SUCCESS : EXIT_FAILURE;
+}
diff --git a/src/rc/fstabinfo.c b/src/rc/fstabinfo.c
index b132c5c3..bd2372d6 100644
--- a/src/rc/fstabinfo.c
+++ b/src/rc/fstabinfo.c
@@ -55,11 +55,36 @@
# define ENT_PASS(_ent) ent->fs_passno
#endif
-#include "builtins.h"
#include "einfo.h"
#include "queue.h"
#include "rc.h"
#include "rc-misc.h"
+#include "_usage.h"
+
+const char *applet = NULL;
+const char *extraopts = NULL;
+const char *getoptstring = "MRbmop:t:" getoptstring_COMMON;
+const struct option longopts[] = {
+ { "mount", 0, NULL, 'M' },
+ { "remount", 0, NULL, 'R' },
+ { "blockdevice", 0, NULL, 'b' },
+ { "mountargs", 0, NULL, 'm' },
+ { "options", 0, NULL, 'o' },
+ { "passno", 1, NULL, 'p' },
+ { "fstype", 1, NULL, 't' },
+ longopts_COMMON
+};
+const char * const longopts_help[] = {
+ "Mounts the filesytem from the mountpoint",
+ "Remounts the filesystem based on the information in fstab",
+ "Extract the block device",
+ "Show arguments needed to mount the entry",
+ "Extract the options field",
+ "Extract or query the pass number field",
+ "List entries with matching file system type",
+ longopts_help_COMMON
+};
+const char *usagestring = NULL;
#ifdef HAVE_GETMNTENT
static struct mntent *
@@ -129,30 +154,6 @@ do_mount(struct ENT *ent, bool remount)
}
}
-#include "_usage.h"
-#define getoptstring "MRbmop:t:" getoptstring_COMMON
-static const struct option longopts[] = {
- { "mount", 0, NULL, 'M' },
- { "remount", 0, NULL, 'R' },
- { "blockdevice", 0, NULL, 'b' },
- { "mountargs", 0, NULL, 'm' },
- { "options", 0, NULL, 'o' },
- { "passno", 1, NULL, 'p' },
- { "fstype", 1, NULL, 't' },
- longopts_COMMON
-};
-static const char * const longopts_help[] = {
- "Mounts the filesytem from the mountpoint",
- "Remounts the filesystem based on the information in fstab",
- "Extract the block device",
- "Show arguments needed to mount the entry",
- "Extract the options field",
- "Extract or query the pass number field",
- "List entries with matching file system type",
- longopts_help_COMMON
-};
-#include "_usage.c"
-
#define OUTPUT_FILE (1 << 1)
#define OUTPUT_MOUNTARGS (1 << 2)
#define OUTPUT_OPTIONS (1 << 3)
@@ -161,8 +162,7 @@ static const char * const longopts_help[] = {
#define OUTPUT_MOUNT (1 << 6)
#define OUTPUT_REMOUNT (1 << 7)
-int
-fstabinfo(int argc, char **argv)
+int main(int argc, char **argv)
{
struct ENT *ent;
int result = EXIT_SUCCESS;
@@ -181,6 +181,7 @@ fstabinfo(int argc, char **argv)
/* Ensure that we are only quiet when explicitly told to be */
unsetenv("EINFO_QUIET");
+ applet = basename_c(argv[0]);
while ((opt = getopt_long(argc, argv, getoptstring,
longopts, (int *) 0)) != -1)
{
diff --git a/src/rc/is_newer_than.c b/src/rc/is_newer_than.c
new file mode 100644
index 00000000..f1aa9d61
--- /dev/null
+++ b/src/rc/is_newer_than.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2016 The OpenRC Authors.
+ * See the Authors file at the top-level directory of this distribution and
+ * https://github.com/OpenRC/openrc/blob/master/AUTHORS
+ *
+ * This file is part of OpenRC. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution and at https://github.com/OpenRC/openrc/blob/master/LICENSE
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file.
+ */
+
+#include <errno.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "rc-misc.h"
+
+int main(int argc, char **argv)
+{
+ int i;
+
+ if (argc < 3)
+ return EXIT_FAILURE;
+
+ /* This test is correct as it's not present in baselayout */
+ for (i = 2; i < argc; ++i)
+ if (!rc_newer_than(argv[1], argv[i], NULL, NULL))
+ return EXIT_FAILURE;
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/rc/is_older_than.c b/src/rc/is_older_than.c
new file mode 100644
index 00000000..87d56414
--- /dev/null
+++ b/src/rc/is_older_than.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2016 The OpenRC Authors.
+ * See the Authors file at the top-level directory of this distribution and
+ * https://github.com/OpenRC/openrc/blob/master/AUTHORS
+ *
+ * This file is part of OpenRC. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution and at https://github.com/OpenRC/openrc/blob/master/LICENSE
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file.
+ */
+
+#include <errno.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "rc-misc.h"
+
+int main(int argc, char **argv)
+{
+ int i;
+
+ if (argc < 3)
+ return EXIT_FAILURE;
+
+ /* This test is perverted - historically the baselayout function
+ * returns 0 on *failure*, which is plain wrong */
+ for (i = 2; i < argc; ++i)
+ if (!rc_newer_than(argv[1], argv[i], NULL, NULL))
+ return EXIT_SUCCESS;
+
+ return EXIT_FAILURE;
+}
diff --git a/src/rc/mountinfo.c b/src/rc/mountinfo.c
index 2b8171df..10e3238d 100644
--- a/src/rc/mountinfo.c
+++ b/src/rc/mountinfo.c
@@ -39,13 +39,48 @@
#include <stdlib.h>
#include <string.h>
-#include "builtins.h"
#include "einfo.h"
#include "queue.h"
#include "rc.h"
#include "rc-misc.h"
+#include "_usage.h"
-extern const char *applet;
+const char *applet = NULL;
+const char *extraopts = "[mount1] [mount2] ...";
+const char *getoptstring = "f:F:n:N:o:O:p:P:iste:E:" getoptstring_COMMON;
+const struct option longopts[] = {
+ { "fstype-regex", 1, NULL, 'f'},
+ { "skip-fstype-regex", 1, NULL, 'F'},
+ { "node-regex", 1, NULL, 'n'},
+ { "skip-node-regex", 1, NULL, 'N'},
+ { "options-regex", 1, NULL, 'o'},
+ { "skip-options-regex", 1, NULL, 'O'},
+ { "point-regex", 1, NULL, 'p'},
+ { "skip-point-regex", 1, NULL, 'P'},
+ { "options", 0, NULL, 'i'},
+ { "fstype", 0, NULL, 's'},
+ { "node", 0, NULL, 't'},
+ { "netdev", 0, NULL, 'e'},
+ { "nonetdev", 0, NULL, 'E'},
+ longopts_COMMON
+};
+const char * const longopts_help[] = {
+ "fstype regex to find",
+ "fstype regex to skip",
+ "node regex to find",
+ "node regex to skip",
+ "options regex to find",
+ "options regex to skip",
+ "point regex to find",
+ "point regex to skip",
+ "print options",
+ "print fstype",
+ "print node",
+ "is it a network device",
+ "is it not a network device",
+ longopts_help_COMMON
+};
+const char *usagestring = NULL;
typedef enum {
mount_from,
@@ -334,45 +369,7 @@ get_regex(const char *string)
return reg;
}
-#include "_usage.h"
-#define extraopts "[mount1] [mount2] ..."
-#define getoptstring "f:F:n:N:o:O:p:P:iste:E:" getoptstring_COMMON
-static const struct option longopts[] = {
- { "fstype-regex", 1, NULL, 'f'},
- { "skip-fstype-regex", 1, NULL, 'F'},
- { "node-regex", 1, NULL, 'n'},
- { "skip-node-regex", 1, NULL, 'N'},
- { "options-regex", 1, NULL, 'o'},
- { "skip-options-regex", 1, NULL, 'O'},
- { "point-regex", 1, NULL, 'p'},
- { "skip-point-regex", 1, NULL, 'P'},
- { "options", 0, NULL, 'i'},
- { "fstype", 0, NULL, 's'},
- { "node", 0, NULL, 't'},
- { "netdev", 0, NULL, 'e'},
- { "nonetdev", 0, NULL, 'E'},
- longopts_COMMON
-};
-static const char * const longopts_help[] = {
- "fstype regex to find",
- "fstype regex to skip",
- "node regex to find",
- "node regex to skip",
- "options regex to find",
- "options regex to skip",
- "point regex to find",
- "point regex to skip",
- "print options",
- "print fstype",
- "print node",
- "is it a network device",
- "is it not a network device",
- longopts_help_COMMON
-};
-#include "_usage.c"
-
-int
-mountinfo(int argc, char **argv)
+int main(int argc, char **argv)
{
struct args args;
regex_t *point_regex = NULL;
@@ -390,6 +387,7 @@ mountinfo(int argc, char **argv)
#define REG_FREE(_var) \
if (_var) { regfree(_var); free(_var); }
+ applet = basename_c(argv[0]);
memset (&args, 0, sizeof(args));
args.mount_type = mount_to;
args.netdev = net_ignore;
diff --git a/src/rc/openrc-run.c b/src/rc/openrc-run.c
index e414450d..757412a5 100644
--- a/src/rc/openrc-run.c
+++ b/src/rc/openrc-run.c
@@ -47,13 +47,13 @@
# include <libutil.h>
#endif
-#include "builtins.h"
#include "einfo.h"
#include "queue.h"
#include "rc.h"
#include "rc-misc.h"
#include "rc-plugin.h"
#include "rc-selinux.h"
+#include "_usage.h"
#define PREFIX_LOCK RC_SVCDIR "/prefix.lock"
@@ -61,7 +61,29 @@
#define WAIT_TIMEOUT 60 /* seconds until we timeout */
#define WARN_TIMEOUT 10 /* warn about this every N seconds */
-static const char *applet;
+const char *applet = NULL;
+const char *extraopts = "stop | start | restart | describe | zap";
+const char *getoptstring = "dDsSvl:Z" getoptstring_COMMON;
+const struct option longopts[] = {
+ { "debug", 0, NULL, 'd'},
+ { "dry-run", 0, NULL, 'Z'},
+ { "ifstarted", 0, NULL, 's'},
+ { "ifstopped", 0, NULL, 'S'},
+ { "nodeps", 0, NULL, 'D'},
+ { "lockfd", 1, NULL, 'l'},
+ longopts_COMMON
+};
+const char *const longopts_help[] = {
+ "set xtrace when running the script",
+ "show what would be done",
+ "only run commands when started",
+ "only run commands when stopped",
+ "ignore dependencies",
+ "fd of the exclusive lock from rc",
+ longopts_help_COMMON
+};
+const char *usagestring = NULL;
+
static char *service, *runlevel, *ibsave, *prefix;
static RC_DEPTREE *deptree;
static RC_STRINGLIST *applet_list, *services, *tmplist;
@@ -1063,31 +1085,7 @@ service_plugable(void)
return allow;
}
-#include "_usage.h"
-#define getoptstring "dDsSvl:Z" getoptstring_COMMON
-#define extraopts "stop | start | restart | describe | zap"
-static const struct option longopts[] = {
- { "debug", 0, NULL, 'd'},
- { "dry-run", 0, NULL, 'Z'},
- { "ifstarted", 0, NULL, 's'},
- { "ifstopped", 0, NULL, 'S'},
- { "nodeps", 0, NULL, 'D'},
- { "lockfd", 1, NULL, 'l'},
- longopts_COMMON
-};
-static const char *const longopts_help[] = {
- "set xtrace when running the script",
- "show what would be done",
- "only run commands when started",
- "only run commands when stopped",
- "ignore dependencies",
- "fd of the exclusive lock from rc",
- longopts_help_COMMON
-};
-#include "_usage.c"
-
-int
-openrc_run(int argc, char **argv)
+int main(int argc, char **argv)
{
bool doneone = false;
int retval, opt, depoptions = RC_DEP_TRACE;
@@ -1396,10 +1394,3 @@ openrc_run(int argc, char **argv)
return retval;
}
-
-int
-runscript(int argc, char **argv)
-{
- ewarnv("runscript is deprecated; please use openrc-run instead.");
- return (openrc_run(argc, argv));
-}
diff --git a/src/rc/rc-abort.c b/src/rc/rc-abort.c
new file mode 100644
index 00000000..c81abe71
--- /dev/null
+++ b/src/rc/rc-abort.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2007-2015 The OpenRC Authors.
+ * See the Authors file at the top-level directory of this distribution and
+ * https://github.com/OpenRC/openrc/blob/master/AUTHORS
+ *
+ * This file is part of OpenRC. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution and at https://github.com/OpenRC/openrc/blob/master/LICENSE
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file.
+ */
+
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include <errno.h>
+#include <ctype.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <string.h>
+#include <syslog.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "einfo.h"
+
+int main(void)
+{
+ const char *p = getenv("RC_PID");
+ int pid;
+
+ if (p && sscanf(p, "%d", &pid) == 1) {
+ if (kill(pid, SIGUSR1) != 0)
+ eerrorx("rc-abort: failed to signal parent %d: %s",
+ pid, strerror(errno));
+ return EXIT_SUCCESS;
+ }
+
+ return EXIT_FAILURE;
+}
diff --git a/src/rc/rc-applets.c b/src/rc/rc-applets.c
deleted file mode 100644
index ed86a4d8..00000000
--- a/src/rc/rc-applets.c
+++ /dev/null
@@ -1,557 +0,0 @@
-/*
- * rc-applets.c
- *
- * Handle multicall applets for use in our init scripts.
- * Basically this makes us a lot faster for the most part, and removes
- * any shell incompatabilities we might otherwise encounter.
-*/
-
-/*
- * Copyright (c) 2007-2015 The OpenRC Authors.
- * See the Authors file at the top-level directory of this distribution and
- * https://github.com/OpenRC/openrc/blob/master/AUTHORS
- *
- * This file is part of OpenRC. It is subject to the license terms in
- * the LICENSE file found in the top-level directory of this
- * distribution and at https://github.com/OpenRC/openrc/blob/master/LICENSE
- * This file may not be copied, modified, propagated, or distributed
- * except according to the terms contained in the LICENSE file.
- */
-
-#define SYSLOG_NAMES
-
-#include <sys/types.h>
-#include <sys/time.h>
-
-#include <errno.h>
-#include <ctype.h>
-#include <inttypes.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <string.h>
-#include <syslog.h>
-#include <time.h>
-#include <unistd.h>
-
-#include "builtins.h"
-#include "einfo.h"
-#include "rc-misc.h"
-
-/* usecs to wait while we poll the file existance */
-#define WAIT_INTERVAL 20000000
-#define ONE_SECOND 690000000
-
-/* Applet is first parsed in rc.c - no point in doing it again */
-extern const char *applet;
-
-static int
-syslog_decode(char *name, CODE *codetab)
-{
- CODE *c;
-
- if (isdigit((unsigned char)*name))
- return atoi(name);
-
- for (c = codetab; c->c_name; c++)
- if (! strcasecmp(name, c->c_name))
- return c->c_val;
-
- return -1;
-}
-
-static int
-do_e(int argc, char **argv)
-{
- int retval = EXIT_SUCCESS;
- int i;
- size_t l = 0;
- char *message = NULL;
- char *p;
- int level = 0;
- struct timespec ts;
- struct timeval stop, now;
- int (*e) (const char *, ...) EINFO_PRINTF(1, 2) = NULL;
- int (*ee) (int, const char *, ...) EINFO_PRINTF(2, 3) = NULL;
-
- /* Punt applet */
- argc--;
- argv++;
-
- if (strcmp(applet, "eval_ecolors") == 0) {
- printf("GOOD='%s'\nWARN='%s'\nBAD='%s'\nHILITE='%s'\nBRACKET='%s'\nNORMAL='%s'\n",
- ecolor(ECOLOR_GOOD),
- ecolor(ECOLOR_WARN),
- ecolor(ECOLOR_BAD),
- ecolor(ECOLOR_HILITE),
- ecolor(ECOLOR_BRACKET),
- ecolor(ECOLOR_NORMAL));
- exit(EXIT_SUCCESS);
- }
-
- if (argc > 0) {
- if (strcmp(applet, "eend") == 0 ||
- strcmp(applet, "ewend") == 0 ||
- strcmp(applet, "veend") == 0 ||
- strcmp(applet, "vweend") == 0 ||
- strcmp(applet, "ewaitfile") == 0)
- {
- errno = 0;
- retval = (int)strtoimax(argv[0], &p, 0);
- if (!p || *p != '\0')
- errno = EINVAL;
- if (errno)
- retval = EXIT_FAILURE;
- else {
- argc--;
- argv++;
- }
- } else if (strcmp(applet, "esyslog") == 0 ||
- strcmp(applet, "elog") == 0) {
- p = strchr(argv[0], '.');
- if (!p ||
- (level = syslog_decode(p + 1, prioritynames)) == -1)
- eerrorx("%s: invalid log level `%s'", applet, argv[0]);
-
- if (argc < 3)
- eerrorx("%s: not enough arguments", applet);
-
- unsetenv("EINFO_LOG");
- setenv("EINFO_LOG", argv[1], 1);
-
- argc -= 2;
- argv += 2;
- }
- }
-
- if (strcmp(applet, "ewaitfile") == 0) {
- if (errno)
- eerrorx("%s: invalid timeout", applet);
- if (argc == 0)
- eerrorx("%s: not enough arguments", applet);
-
- gettimeofday(&stop, NULL);
- /* retval stores the timeout */
- stop.tv_sec += retval;
- ts.tv_sec = 0;
- ts.tv_nsec = WAIT_INTERVAL;
- for (i = 0; i < argc; i++) {
- ebeginv("Waiting for %s", argv[i]);
- for (;;) {
- if (exists(argv[i]))
- break;
- if (nanosleep(&ts, NULL) == -1)
- return EXIT_FAILURE;
- gettimeofday(&now, NULL);
- if (retval <= 0)
- continue;
- if (timercmp(&now, &stop, <))
- continue;
- eendv(EXIT_FAILURE,
- "timed out waiting for %s", argv[i]);
- return EXIT_FAILURE;
- }
- eendv(EXIT_SUCCESS, NULL);
- }
- return EXIT_SUCCESS;
- }
-
- if (argc > 0) {
- for (i = 0; i < argc; i++)
- l += strlen(argv[i]) + 1;
-
- message = xmalloc(l);
- p = message;
-
- for (i = 0; i < argc; i++) {
- if (i > 0)
- *p++ = ' ';
- l = strlen(argv[i]);
- memcpy(p, argv[i], l);
- p += l;
- }
- *p = 0;
- }
-
- if (strcmp(applet, "einfo") == 0)
- e = einfo;
- else if (strcmp(applet, "einfon") == 0)
- e = einfon;
- else if (strcmp(applet, "ewarn") == 0)
- e = ewarn;
- else if (strcmp(applet, "ewarnn") == 0)
- e = ewarnn;
- else if (strcmp(applet, "eerror") == 0) {
- e = eerror;
- retval = 1;
- } else if (strcmp(applet, "eerrorn") == 0) {
- e = eerrorn;
- retval = 1;
- } else if (strcmp(applet, "ebegin") == 0)
- e = ebegin;
- else if (strcmp(applet, "eend") == 0)
- ee = eend;
- else if (strcmp(applet, "ewend") == 0)
- ee = ewend;
- else if (strcmp(applet, "esyslog") == 0) {
- elog(retval, "%s", message);
- retval = 0;
- } else if (strcmp(applet, "veinfo") == 0)
- e = einfov;
- else if (strcmp(applet, "veinfon") == 0)
- e = einfovn;
- else if (strcmp(applet, "vewarn") == 0)
- e = ewarnv;
- else if (strcmp(applet, "vewarnn") == 0)
- e = ewarnvn;
- else if (strcmp(applet, "vebegin") == 0)
- e = ebeginv;
- else if (strcmp(applet, "veend") == 0)
- ee = eendv;
- else if (strcmp(applet, "vewend") == 0)
- ee = ewendv;
- else if (strcmp(applet, "eindent") == 0)
- eindent();
- else if (strcmp(applet, "eoutdent") == 0)
- eoutdent();
- else if (strcmp(applet, "veindent") == 0)
- eindentv();
- else if (strcmp(applet, "veoutdent") == 0)
- eoutdentv();
- else {
- eerror("%s: unknown applet", applet);
- retval = EXIT_FAILURE;
- }
-
- if (message) {
- if (e)
- e("%s", message);
- else if (ee)
- ee(retval, "%s", message);
- } else {
- if (e)
- e(NULL);
- else if (ee)
- ee(retval, NULL);
- }
-
- free(message);
- return retval;
-}
-
-static const struct {
- const char * const name;
- RC_SERVICE bit;
-} service_bits[] = {
- { "service_started", RC_SERVICE_STARTED, },
- { "service_stopped", RC_SERVICE_STOPPED, },
- { "service_inactive", RC_SERVICE_INACTIVE, },
- { "service_starting", RC_SERVICE_STARTING, },
- { "service_stopping", RC_SERVICE_STOPPING, },
- { "service_hotplugged", RC_SERVICE_HOTPLUGGED, },
- { "service_wasinactive", RC_SERVICE_WASINACTIVE, },
- { "service_failed", RC_SERVICE_FAILED, },
-};
-
-static RC_SERVICE
-lookup_service_state(const char *service)
-{
- size_t i;
- for (i = 0; i < ARRAY_SIZE(service_bits); ++i)
- if (!strcmp(service, service_bits[i].name))
- return service_bits[i].bit;
- return 0;
-}
-
-static int
-do_service(int argc, char **argv)
-{
- bool ok = false;
- char *service;
- char *exec;
- int idx;
- RC_SERVICE state, bit;
-
- if (argc > 1)
- service = argv[1];
- else
- service = getenv("RC_SVCNAME");
-
- if (service == NULL || *service == '\0')
- eerrorx("%s: no service specified", applet);
-
- state = rc_service_state(service);
- bit = lookup_service_state(applet);
- if (bit) {
- ok = (state & bit);
- } else if (strcmp(applet, "service_started_daemon") == 0) {
- service = getenv("RC_SVCNAME");
- exec = argv[1];
- if (argc > 3) {
- service = argv[1];
- exec = argv[2];
- sscanf(argv[3], "%d", &idx);
- } else if (argc == 3) {
- if (sscanf(argv[2], "%d", &idx) != 1) {
- service = argv[1];
- exec = argv[2];
- }
- }
- ok = rc_service_started_daemon(service, exec, NULL, idx);
-
- } else if (strcmp(applet, "service_crashed") == 0) {
- ok = (_rc_can_find_pids() &&
- rc_service_daemons_crashed(service) &&
- errno != EACCES);
- } else
- eerrorx("%s: unknown applet", applet);
-
- return ok ? EXIT_SUCCESS : EXIT_FAILURE;
-}
-
-static int
-do_mark_service(int argc, char **argv)
-{
- bool ok = false;
- char *svcname = getenv("RC_SVCNAME");
- char *service = NULL;
- char *openrc_pid;
- /* char *mtime; */
- pid_t pid;
- RC_SERVICE bit;
- /* size_t l; */
-
- if (argc > 1)
- service = argv[1];
- else
- service = svcname;
-
- if (service == NULL || *service == '\0')
- eerrorx("%s: no service specified", applet);
-
- if (!strncmp(applet, "mark_", 5) &&
- (bit = lookup_service_state(applet + 5)))
- ok = rc_service_mark(service, bit);
- else
- eerrorx("%s: unknown applet", applet);
-
- /* If we're marking ourselves then we need to inform our parent
- openrc-run process so they do not mark us based on our exit code */
- /*
- * FIXME: svcname and service are almost always equal except called from a
- * shell with just argv[1] - So that doesn't seem to do what Roy initially
- * expected.
- * See 20120424041423.GA23657@odin.qasl.de (Tue, 24 Apr 2012 06:14:23 +0200,
- * openrc@gentoo.org).
- */
- if (ok && svcname && strcmp(svcname, service) == 0) {
- openrc_pid = getenv("RC_OPENRC_PID");
- if (openrc_pid && sscanf(openrc_pid, "%d", &pid) == 1)
- if (kill(pid, SIGHUP) != 0)
- eerror("%s: failed to signal parent %d: %s",
- applet, pid, strerror(errno));
-
- /* Remove the exclusive time test. This ensures that it's not
- in control as well */
- /*
- l = strlen(RC_SVCDIR "/exclusive") + strlen(svcname) +
- strlen(openrc_pid) + 4;
- mtime = xmalloc(l);
- snprintf(mtime, l, RC_SVCDIR "/exclusive/%s.%s",
- svcname, openrc_pid);
- if (exists(mtime) && unlink(mtime) != 0)
- eerror("%s: unlink: %s", applet, strerror(errno));
- free(mtime);
- */
- }
-
- return ok ? EXIT_SUCCESS : EXIT_FAILURE;
-}
-
-static int
-do_value(int argc, char **argv)
-{
- bool ok = false;
- char *service = getenv("RC_SVCNAME");
- char *option;
-
- if (service == NULL)
- eerrorx("%s: no service specified", applet);
-
- if (argc < 2 || ! argv[1] || *argv[1] == '\0')
- eerrorx("%s: no option specified", applet);
-
- if (strcmp(applet, "service_get_value") == 0 ||
- strcmp(applet, "get_options") == 0)
- {
- option = rc_service_value_get(service, argv[1]);
- if (option) {
- printf("%s", option);
- free(option);
- ok = true;
- }
- } else if (strcmp(applet, "service_set_value") == 0 ||
- strcmp(applet, "save_options") == 0)
- ok = rc_service_value_set(service, argv[1], argv[2]);
- else
- eerrorx("%s: unknown applet", applet);
-
- return ok ? EXIT_SUCCESS : EXIT_FAILURE;
-}
-
-static int
-shell_var(int argc, char **argv)
-{
- int i;
- char *p;
- int c;
-
- for (i = 1; i < argc; i++) {
- p = argv[i];
- if (i != 1)
- putchar(' ');
- while (*p) {
- c = (unsigned char)*p++;
- if (! isalnum(c))
- c = '_';
- putchar(c);
- }
- }
- putchar('\n');
- return EXIT_SUCCESS;
-}
-
-static int
-is_older_than(int argc, char **argv)
-{
- int i;
-
- if (argc < 3)
- return EXIT_FAILURE;
-
- /* This test is perverted - historically the baselayout function
- * returns 0 on *failure*, which is plain wrong */
- for (i = 2; i < argc; ++i)
- if (!rc_newer_than(argv[1], argv[i], NULL, NULL))
- return EXIT_SUCCESS;
-
- return EXIT_FAILURE;
-}
-
-static int
-is_newer_than(int argc, char **argv)
-{
- int i;
-
- if (argc < 3)
- return EXIT_FAILURE;
-
- /* This test is correct as it's not present in baselayout */
- for (i = 2; i < argc; ++i)
- if (!rc_newer_than(argv[1], argv[i], NULL, NULL))
- return EXIT_FAILURE;
-
- return EXIT_SUCCESS;
-}
-
-static int
-is_runlevel_start(_unused int argc, _unused char **argv)
-{
- return rc_runlevel_starting() ? 0 : 1;
-}
-
-static int
-is_runlevel_stop(_unused int argc, _unused char **argv)
-{
- return rc_runlevel_stopping() ? 0 : 1;
-}
-
-static int
-rc_abort(_unused int argc, _unused char **argv)
-{
- const char *p = getenv("RC_PID");
- int pid;
-
- if (p && sscanf(p, "%d", &pid) == 1) {
- if (kill(pid, SIGUSR1) != 0)
- eerrorx("rc-abort: failed to signal parent %d: %s",
- pid, strerror(errno));
- return EXIT_SUCCESS;
- }
-
- return EXIT_FAILURE;
-}
-
-static const struct {
- const char * const name;
- int (* const applet)(int argc, char **argv);
-} applets[] = {
-#define A(a) { #a, a }
- A(fstabinfo),
- A(mountinfo),
- { "openrc-run", openrc_run, },
- { "rc-depend", rc_depend, },
- { "rc-service", rc_service, },
- { "rc-status", rc_status, },
- { "rc-update", rc_update, },
- { "service", rc_service, },
- { "update-rc", rc_update, },
- A(runscript),
- { "start-stop-daemon", start_stop_daemon, },
- A(checkpath),
- A(swclock),
- A(shell_var),
- A(is_older_than),
- A(is_newer_than),
- A(is_runlevel_start),
- A(is_runlevel_stop),
- { "rc-abort", rc_abort, },
- /* These are purely for init scripts and do not make sense as
- * anything else */
- { "service_get_value", do_value, },
- { "service_set_value", do_value, },
- { "get_options", do_value, },
- { "save_options", do_value, },
-#undef A
-};
-
-void
-run_applets(int argc, char **argv)
-{
- size_t i;
-
- /*
- * The "rc" applet is deprecated and should be referred to as
- * "openrc", so output a warning.
- */
- if (strcmp(applet, "rc") == 0)
- ewarnv("The 'rc' applet is deprecated; please use 'openrc' instead.");
- /* Bug 351712: We need an extra way to explicitly select an applet OTHER
- * than trusting argv[0], as argv[0] is not going to be the applet value if
- * we are doing SELinux context switching. For this, we allow calls such as
- * 'rc --applet APPLET', and shift ALL of argv down by two array items. */
- if ((strcmp(applet, "rc") == 0 || strcmp(applet, "openrc") == 0) &&
- argc >= 3 &&
- (strcmp(argv[1],"--applet") == 0 || strcmp(argv[1], "-a") == 0)) {
- applet = argv[2];
- argv += 2;
- argc -= 2;
- }
-
- for (i = 0; i < ARRAY_SIZE(applets); ++i)
- if (!strcmp(applet, applets[i].name))
- exit(applets[i].applet(argc, argv));
-
- if (applet[0] == 'e' || (applet[0] == 'v' && applet[1] == 'e'))
- exit(do_e(argc, argv));
-
- if (strncmp(applet, "service_", strlen("service_")) == 0)
- exit(do_service(argc, argv));
-
- if (strncmp(applet, "mark_service_", strlen("mark_service_")) == 0)
- exit(do_mark_service(argc, argv));
-
- if (strcmp(applet, "rc") != 0 && strcmp(applet, "openrc") != 0)
- eerrorx("%s: unknown applet", applet);
-}
diff --git a/src/rc/rc-depend.c b/src/rc/rc-depend.c
index fdc6c332..51c6a5e1 100644
--- a/src/rc/rc-depend.c
+++ b/src/rc/rc-depend.c
@@ -31,70 +31,16 @@
#include <unistd.h>
#include <utime.h>
-#include "builtins.h"
#include "einfo.h"
#include "queue.h"
#include "rc.h"
#include "rc-misc.h"
-
-extern const char *applet;
-
-RC_DEPTREE *
-_rc_deptree_load(int force, int *regen) {
- int fd;
- int retval;
- int serrno = errno;
- int merrno;
- time_t t;
- char file[PATH_MAX];
- struct stat st;
- struct utimbuf ut;
- FILE *fp;
-
- t = 0;
- if (rc_deptree_update_needed(&t, file) || force != 0) {
- /* Test if we have permission to update the deptree */
- fd = open(RC_DEPTREE_CACHE, O_WRONLY);
- merrno = errno;
- errno = serrno;
- if (fd == -1 && merrno == EACCES)
- return rc_deptree_load();
- close(fd);
-
- if (regen)
- *regen = 1;
- ebegin("Caching service dependencies");
- retval = rc_deptree_update() ? 0 : -1;
- eend (retval, "Failed to update the dependency tree");
-
- if (retval == 0) {
- stat(RC_DEPTREE_CACHE, &st);
- if (st.st_mtime < t) {
- eerror("Clock skew detected with `%s'", file);
- eerrorn("Adjusting mtime of `" RC_DEPTREE_CACHE
- "' to %s", ctime(&t));
- fp = fopen(RC_DEPTREE_SKEWED, "w");
- if (fp != NULL) {
- fprintf(fp, "%s\n", file);
- fclose(fp);
- }
- ut.actime = t;
- ut.modtime = t;
- utime(RC_DEPTREE_CACHE, &ut);
- } else {
- if (exists(RC_DEPTREE_SKEWED))
- unlink(RC_DEPTREE_SKEWED);
- }
- }
- if (force == -1 && regen != NULL)
- *regen = retval;
- }
- return rc_deptree_load();
-}
-
#include "_usage.h"
-#define getoptstring "aot:suTF:" getoptstring_COMMON
-static const struct option longopts[] = {
+
+const char *applet = NULL;
+const char *extraopts = NULL;
+const char *getoptstring = "aot:suTF:" getoptstring_COMMON;
+const struct option longopts[] = {
{ "starting", 0, NULL, 'a'},
{ "stopping", 0, NULL, 'o'},
{ "type", 1, NULL, 't'},
@@ -104,7 +50,7 @@ static const struct option longopts[] = {
{ "deptree-file", 1, NULL, 'F'},
longopts_COMMON
};
-static const char * const longopts_help[] = {
+const char * const longopts_help[] = {
"Order services as if runlevel is starting",
"Order services as if runlevel is stopping",
"Type(s) of dependency to list",
@@ -114,10 +60,9 @@ static const char * const longopts_help[] = {
"File to load cached deptree from",
longopts_help_COMMON
};
-#include "_usage.c"
+const char *usagestring = NULL;
-int
-rc_depend(int argc, char **argv)
+int main(int argc, char **argv)
{
RC_STRINGLIST *list;
RC_STRINGLIST *types;
@@ -132,6 +77,7 @@ rc_depend(int argc, char **argv)
char *token;
char *deptree_file = NULL;
+ applet = basename_c(argv[0]);
types = rc_stringlist_new();
while ((opt = getopt_long(argc, argv, getoptstring,
longopts, (int *) 0)) != -1)
diff --git a/src/rc/rc-misc.c b/src/rc/rc-misc.c
index f2f4d9f0..6dfa4235 100644
--- a/src/rc/rc-misc.c
+++ b/src/rc/rc-misc.c
@@ -23,6 +23,7 @@
# include <sys/sysinfo.h>
#endif
+#include <sys/time.h>
#include <ctype.h>
#include <fcntl.h>
#include <limits.h>
@@ -31,7 +32,9 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <time.h>
#include <unistd.h>
+#include <utime.h>
#include "einfo.h"
#include "queue.h"
@@ -488,3 +491,107 @@ const char *detect_vm(void)
return NULL;
}
+
+RC_DEPTREE * _rc_deptree_load(int force, int *regen)
+{
+ int fd;
+ int retval;
+ int serrno = errno;
+ int merrno;
+ time_t t;
+ char file[PATH_MAX];
+ struct stat st;
+ struct utimbuf ut;
+ FILE *fp;
+
+ t = 0;
+ if (rc_deptree_update_needed(&t, file) || force != 0) {
+ /* Test if we have permission to update the deptree */
+ fd = open(RC_DEPTREE_CACHE, O_WRONLY);
+ merrno = errno;
+ errno = serrno;
+ if (fd == -1 && merrno == EACCES)
+ return rc_deptree_load();
+ close(fd);
+
+ if (regen)
+ *regen = 1;
+ ebegin("Caching service dependencies");
+ retval = rc_deptree_update() ? 0 : -1;
+ eend (retval, "Failed to update the dependency tree");
+
+ if (retval == 0) {
+ stat(RC_DEPTREE_CACHE, &st);
+ if (st.st_mtime < t) {
+ eerror("Clock skew detected with `%s'", file);
+ eerrorn("Adjusting mtime of `" RC_DEPTREE_CACHE
+ "' to %s", ctime(&t));
+ fp = fopen(RC_DEPTREE_SKEWED, "w");
+ if (fp != NULL) {
+ fprintf(fp, "%s\n", file);
+ fclose(fp);
+ }
+ ut.actime = t;
+ ut.modtime = t;
+ utime(RC_DEPTREE_CACHE, &ut);
+ } else {
+ if (exists(RC_DEPTREE_SKEWED))
+ unlink(RC_DEPTREE_SKEWED);
+ }
+ }
+ if (force == -1 && regen != NULL)
+ *regen = retval;
+ }
+ return rc_deptree_load();
+}
+
+bool _rc_can_find_pids(void)
+{
+ RC_PIDLIST *pids;
+ RC_PID *pid;
+ RC_PID *pid2;
+ bool retval = false;
+
+ if (geteuid() == 0)
+ return true;
+
+ /* If we cannot see process 1, then we don't test to see if
+ * services crashed or not */
+ pids = rc_find_pids(NULL, NULL, 0, 1);
+ if (pids) {
+ pid = LIST_FIRST(pids);
+ if (pid) {
+ retval = true;
+ while (pid) {
+ pid2 = LIST_NEXT(pid, entries);
+ free(pid);
+ pid = pid2;
+ }
+ }
+ free(pids);
+ }
+ return retval;
+}
+
+static const struct {
+ const char * const name;
+ RC_SERVICE bit;
+} service_bits[] = {
+ { "service_started", RC_SERVICE_STARTED, },
+ { "service_stopped", RC_SERVICE_STOPPED, },
+ { "service_inactive", RC_SERVICE_INACTIVE, },
+ { "service_starting", RC_SERVICE_STARTING, },
+ { "service_stopping", RC_SERVICE_STOPPING, },
+ { "service_hotplugged", RC_SERVICE_HOTPLUGGED, },
+ { "service_wasinactive", RC_SERVICE_WASINACTIVE, },
+ { "service_failed", RC_SERVICE_FAILED, },
+};
+
+RC_SERVICE lookup_service_state(const char *service)
+{
+ size_t i;
+ for (i = 0; i < ARRAY_SIZE(service_bits); ++i)
+ if (!strcmp(service, service_bits[i].name))
+ return service_bits[i].bit;
+ return 0;
+}
diff --git a/src/rc/rc-selinux.c b/src/rc/rc-selinux.c
index ed89be1e..3e484a67 100644
--- a/src/rc/rc-selinux.c
+++ b/src/rc/rc-selinux.c
@@ -15,6 +15,8 @@
* except according to the terms contained in the LICENSE file.
*/
+#ifdef HAVE_SELINUX
+
#include <stddef.h>
#include <errno.h>
#include <dlfcn.h>
@@ -384,3 +386,5 @@ out:
free(run_init_t);
free(curr_t);
}
+
+#endif
diff --git a/src/rc/rc-service.c b/src/rc/rc-service.c
index 6b03767b..8e9da446 100644
--- a/src/rc/rc-service.c
+++ b/src/rc/rc-service.c
@@ -21,39 +21,36 @@
#include <string.h>
#include <unistd.h>
-#include "builtins.h"
#include "einfo.h"
#include "queue.h"
#include "rc.h"
#include "rc-misc.h"
-
-extern char *applet;
-
#include "_usage.h"
-#define usagestring "" \
- "Usage: rc-service [options] [-i] <service> <cmd>...\n" \
- " or: rc-service [options] -e <service>\n" \
- " or: rc-service [options] -l\n" \
- " or: rc-service [options] -r <service>"
-#define getoptstring "e:ilr:" getoptstring_COMMON
-static const struct option longopts[] = {
+
+const char *applet = NULL;
+const char *extraopts = NULL;
+const char *getoptstring = "e:ilr:" getoptstring_COMMON;
+const struct option longopts[] = {
{ "exists", 1, NULL, 'e' },
{ "ifexists", 0, NULL, 'i' },
{ "list", 0, NULL, 'l' },
{ "resolve", 1, NULL, 'r' },
longopts_COMMON
};
-static const char * const longopts_help[] = {
+const char * const longopts_help[] = {
"tests if the service exists or not",
"if the service exists then run the command",
"list all available services",
"resolve the service name to an init script",
longopts_help_COMMON
};
-#include "_usage.c"
+const char *usagestring = "" \
+ "Usage: rc-service [options] [-i] <service> <cmd>...\n" \
+ " or: rc-service [options] -e <service>\n" \
+ " or: rc-service [options] -l\n" \
+ " or: rc-service [options] -r <service>";
-int
-rc_service(int argc, char **argv)
+int main(int argc, char **argv)
{
int opt;
char *service;
@@ -61,6 +58,7 @@ rc_service(int argc, char **argv)
RC_STRING *s;
bool if_exists = false;
+ applet = basename_c(argv[0]);
/* Ensure that we are only quiet when explicitly told to be */
unsetenv("EINFO_QUIET");
diff --git a/src/rc/rc-status.c b/src/rc/rc-status.c
index b3f5d360..5018662e 100644
--- a/src/rc/rc-status.c
+++ b/src/rc/rc-status.c
@@ -21,13 +21,37 @@
#include <string.h>
#include <unistd.h>
-#include "builtins.h"
#include "einfo.h"
#include "queue.h"
#include "rc.h"
#include "rc-misc.h"
+#include "_usage.h"
+
+const char *applet = NULL;
+const char *extraopts = NULL;
+const char *getoptstring = "aclrsu" getoptstring_COMMON;
+const struct option longopts[] = {
+ {"all", 0, NULL, 'a'},
+ {"crashed", 0, NULL, 'c'},
+ {"list", 0, NULL, 'l'},
+ {"runlevel", 0, NULL, 'r'},
+ {"servicelist", 0, NULL, 's'},
+ {"unused", 0, NULL, 'u'},
+ longopts_COMMON
+};
+const char * const longopts_help[] = {
+ "Show services from all run levels",
+ "Show crashed services",
+ "Show list of run levels",
+ "Show the name of the current runlevel",
+ "Show service list",
+ "Show services not assigned to any runlevel",
+ longopts_help_COMMON
+};
+const char *usagestring = "" \
+ "Usage: rc-status [options] <runlevel>...\n" \
+ " or: rc-status [options] [-a | -c | -l | -r | -s | -u]";
-extern const char *applet;
static bool test_crashed = false;
static RC_DEPTREE *deptree;
static RC_STRINGLIST *types;
@@ -35,35 +59,6 @@ static RC_STRINGLIST *types;
static RC_STRINGLIST *levels, *services, *tmp, *alist;
static RC_STRINGLIST *sservices, *nservices, *needsme;
-bool
-_rc_can_find_pids(void)
-{
- RC_PIDLIST *pids;
- RC_PID *pid;
- RC_PID *pid2;
- bool retval = false;
-
- if (geteuid() == 0)
- return true;
-
- /* If we cannot see process 1, then we don't test to see if
- * services crashed or not */
- pids = rc_find_pids(NULL, NULL, 0, 1);
- if (pids) {
- pid = LIST_FIRST(pids);
- if (pid) {
- retval = true;
- while (pid) {
- pid2 = LIST_NEXT(pid, entries);
- free(pid);
- pid = pid2;
- }
- }
- free(pids);
- }
- return retval;
-}
-
static void
print_level(const char *prefix, const char *level)
{
@@ -178,33 +173,7 @@ print_stacked_services(const char *runlevel)
stackedlevels = NULL;
}
-#include "_usage.h"
-#define usagestring "" \
- "Usage: rc-status [options] <runlevel>...\n" \
- " or: rc-status [options] [-a | -c | -l | -r | -s | -u]"
-#define getoptstring "aclrsu" getoptstring_COMMON
-static const struct option longopts[] = {
- {"all", 0, NULL, 'a'},
- {"crashed", 0, NULL, 'c'},
- {"list", 0, NULL, 'l'},
- {"runlevel", 0, NULL, 'r'},
- {"servicelist", 0, NULL, 's'},
- {"unused", 0, NULL, 'u'},
- longopts_COMMON
-};
-static const char * const longopts_help[] = {
- "Show services from all run levels",
- "Show crashed services",
- "Show list of run levels",
- "Show the name of the current runlevel",
- "Show service list",
- "Show services not assigned to any runlevel",
- longopts_help_COMMON
-};
-#include "_usage.c"
-
-int
-rc_status(int argc, char **argv)
+int main(int argc, char **argv)
{
RC_STRING *s, *l, *t, *level;
@@ -213,6 +182,7 @@ rc_status(int argc, char **argv)
test_crashed = _rc_can_find_pids();
+ applet = basename_c(argv[0]);
while ((opt = getopt_long(argc, argv, getoptstring, longopts,
(int *) 0)) != -1)
switch (opt) {
diff --git a/src/rc/rc-update.c b/src/rc/rc-update.c
index 77b7ae75..9bc1fe5b 100644
--- a/src/rc/rc-update.c
+++ b/src/rc/rc-update.c
@@ -24,13 +24,31 @@
#include <string.h>
#include <unistd.h>
-#include "builtins.h"
#include "einfo.h"
#include "queue.h"
#include "rc.h"
#include "rc-misc.h"
+#include "_usage.h"
-extern const char *applet;
+const char *applet = NULL;
+const char *extraopts = NULL;
+const char *usagestring = "" \
+ "Usage: rc-update [options] add <service> [<runlevel>...]\n" \
+ " or: rc-update [options] del <service> [<runlevel>...]\n" \
+ " or: rc-update [options] [show [<runlevel>...]]";
+const char *getoptstring = "asu" getoptstring_COMMON;
+const struct option longopts[] = {
+ { "all", 0, NULL, 'a' },
+ { "stack", 0, NULL, 's' },
+ { "update", 0, NULL, 'u' },
+ longopts_COMMON
+};
+const char * const longopts_help[] = {
+ "Process all runlevels",
+ "Stack a runlevel instead of a service",
+ "Force an update of the dependency tree",
+ longopts_help_COMMON
+};
/* Return the number of changes made:
* -1 = no changes (error)
@@ -182,32 +200,11 @@ show(RC_STRINGLIST *runlevels, bool verbose)
rc_stringlist_free (services);
}
-#include "_usage.h"
-#define usagestring "" \
- "Usage: rc-update [options] add <service> [<runlevel>...]\n" \
- " or: rc-update [options] del <service> [<runlevel>...]\n" \
- " or: rc-update [options] [show [<runlevel>...]]"
-#define getoptstring "asu" getoptstring_COMMON
-static const struct option longopts[] = {
- { "all", 0, NULL, 'a' },
- { "stack", 0, NULL, 's' },
- { "update", 0, NULL, 'u' },
- longopts_COMMON
-};
-static const char * const longopts_help[] = {
- "Process all runlevels",
- "Stack a runlevel instead of a service",
- "Force an update of the dependency tree",
- longopts_help_COMMON
-};
-#include "_usage.c"
-
#define DOADD (1 << 1)
#define DODELETE (1 << 2)
#define DOSHOW (1 << 3)
-int
-rc_update(int argc, char **argv)
+int main(int argc, char **argv)
{
RC_DEPTREE *deptree;
RC_STRINGLIST *runlevels;
@@ -222,6 +219,7 @@ rc_update(int argc, char **argv)
int (*actfunc)(const char *, const char *);
int ret;
+ applet = basename_c(argv[0]);
while ((opt = getopt_long(argc, argv, getoptstring,
longopts, (int *)0)) != -1)
switch (opt) {
diff --git a/src/rc/rc.c b/src/rc/rc.c
index a0b18865..87c4913f 100644
--- a/src/rc/rc.c
+++ b/src/rc/rc.c
@@ -45,7 +45,6 @@ const char rc_copyright[] = "Copyright (c) 2007-2008 Roy Marples";
#include <termios.h>
#include <unistd.h>
-#include "builtins.h"
#include "einfo.h"
#include "queue.h"
#include "rc.h"
@@ -54,6 +53,27 @@ const char rc_copyright[] = "Copyright (c) 2007-2008 Roy Marples";
#include "rc-plugin.h"
#include "version.h"
+#include "_usage.h"
+
+const char *extraopts = NULL;
+const char *getoptstring = "a:no:s:S" getoptstring_COMMON;
+const struct option longopts[] = {
+ { "no-stop", 0, NULL, 'n' },
+ { "override", 1, NULL, 'o' },
+ { "service", 1, NULL, 's' },
+ { "sys", 0, NULL, 'S' },
+ longopts_COMMON
+};
+const char * const longopts_help[] = {
+ "do not stop any services",
+ "override the next runlevel to change into\n"
+ "when leaving single user or boot runlevels",
+ "runs the service specified with the rest\nof the arguments",
+ "output the RC system type, if any",
+ longopts_help_COMMON
+};
+const char *usagestring = "" \
+ "Usage: openrc [options] [<runlevel>]";
#define INITSH RC_LIBEXECDIR "/sh/init.sh"
#define INITEARLYSH RC_LIBEXECDIR "/sh/init-early.sh"
@@ -721,31 +741,7 @@ handle_bad_signal(int sig)
}
#endif
-#include "_usage.h"
-#define usagestring "" \
- "Usage: openrc [options] [<runlevel>]"
-#define getoptstring "a:no:s:S" getoptstring_COMMON
-static const struct option longopts[] = {
- { "applet", 1, NULL, 'a' },
- { "no-stop", 0, NULL, 'n' },
- { "override", 1, NULL, 'o' },
- { "service", 1, NULL, 's' },
- { "sys", 0, NULL, 'S' },
- longopts_COMMON
-};
-static const char * const longopts_help[] = {
- "runs the applet specified by the next argument",
- "do not stop any services",
- "override the next runlevel to change into\n"
- "when leaving single user or boot runlevels",
- "runs the service specified with the rest\nof the arguments",
- "output the RC system type, if any",
- longopts_help_COMMON
-};
-#include "_usage.c"
-
-int
-main(int argc, char **argv)
+int main(int argc, char **argv)
{
const char *bootlevel = NULL;
char *newlevel = NULL;
@@ -785,9 +781,6 @@ main(int argc, char **argv)
if (!applet)
eerrorx("arguments required");
- /* Run our built in applets. If we ran one, we don't return. */
- run_applets(argc, argv);
-
argc--;
argv++;
@@ -813,10 +806,6 @@ main(int argc, char **argv)
longopts, (int *) 0)) != -1)
{
switch (opt) {
- case 'a':
- /* Do nothing, actual logic in run_applets, this
- * is a placeholder */
- break;
case 'n':
nostop = true;
break;
diff --git a/src/rc/shell_var.c b/src/rc/shell_var.c
new file mode 100644
index 00000000..a13f58e2
--- /dev/null
+++ b/src/rc/shell_var.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2007-2015 The OpenRC Authors.
+ * See the Authors file at the top-level directory of this distribution and
+ * https://github.com/OpenRC/openrc/blob/master/AUTHORS
+ *
+ * This file is part of OpenRC. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution and at https://github.com/OpenRC/openrc/blob/master/LICENSE
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file.
+ */
+
+#include <errno.h>
+#include <ctype.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+int main(int argc, char **argv)
+{
+ int i;
+ char *p;
+ int c;
+
+ for (i = 1; i < argc; i++) {
+ p = argv[i];
+ if (i != 1)
+ putchar(' ');
+ while (*p) {
+ c = (unsigned char)*p++;
+ if (! isalnum(c))
+ c = '_';
+ putchar(c);
+ }
+ }
+ putchar('\n');
+ return EXIT_SUCCESS;
+}
diff --git a/src/rc/start-stop-daemon.c b/src/rc/start-stop-daemon.c
index 8f973199..775bd7de 100644
--- a/src/rc/start-stop-daemon.c
+++ b/src/rc/start-stop-daemon.c
@@ -59,11 +59,75 @@
static struct pam_conv conv = { NULL, NULL};
#endif
-#include "builtins.h"
#include "einfo.h"
#include "queue.h"
#include "rc.h"
#include "rc-misc.h"
+#include "_usage.h"
+
+const char *applet = NULL;
+const char *extraopts = NULL;
+const char *getoptstring = "I:KN:PR:Sa:bc:d:e:g:ik:mn:op:s:tu:r:w:x:1:2:" \
+ getoptstring_COMMON;
+const struct option longopts[] = {
+ { "ionice", 1, NULL, 'I'},
+ { "stop", 0, NULL, 'K'},
+ { "nicelevel", 1, NULL, 'N'},
+ { "retry", 1, NULL, 'R'},
+ { "start", 0, NULL, 'S'},
+ { "startas", 1, NULL, 'a'},
+ { "background", 0, NULL, 'b'},
+ { "chuid", 1, NULL, 'c'},
+ { "chdir", 1, NULL, 'd'},
+ { "env", 1, NULL, 'e'},
+ { "umask", 1, NULL, 'k'},
+ { "group", 1, NULL, 'g'},
+ { "interpreted", 0, NULL, 'i'},
+ { "make-pidfile", 0, NULL, 'm'},
+ { "name", 1, NULL, 'n'},
+ { "oknodo", 0, NULL, 'o'},
+ { "pidfile", 1, NULL, 'p'},
+ { "signal", 1, NULL, 's'},
+ { "test", 0, NULL, 't'},
+ { "user", 1, NULL, 'u'},
+ { "chroot", 1, NULL, 'r'},
+ { "wait", 1, NULL, 'w'},
+ { "exec", 1, NULL, 'x'},
+ { "stdout", 1, NULL, '1'},
+ { "stderr", 1, NULL, '2'},
+ { "progress", 0, NULL, 'P'},
+ longopts_COMMON
+};
+const char * const longopts_help[] = {
+ "Set an ionice class:data when starting",
+ "Stop daemon",
+ "Set a nicelevel when starting",
+ "Retry schedule to use when stopping",
+ "Start daemon",
+ "deprecated, use --exec or --name",
+ "Force daemon to background",
+ "deprecated, use --user",
+ "Change the PWD",
+ "Set an environment string",
+ "Set the umask for the daemon",
+ "Change the process group",
+ "Match process name by interpreter",
+ "Create a pidfile",
+ "Match process name",
+ "deprecated",
+ "Match pid found in this file",
+ "Send a different signal",
+ "Test actions, don't do them",
+ "Change the process user",
+ "Chroot to this directory",
+ "Milliseconds to wait for daemon start",
+ "Binary to start/stop",
+ "Redirect stdout to file",
+ "Redirect stderr to file",
+ "Print dots each second while waiting",
+ longopts_help_COMMON
+};
+const char *usagestring = NULL;
typedef struct scheduleitem
{
@@ -81,7 +145,6 @@ typedef struct scheduleitem
TAILQ_HEAD(, scheduleitem) schedule;
static char **nav;
-extern const char *applet;
static char *changeuser, *ch_root, *ch_dir;
extern char **environ;
@@ -567,70 +630,7 @@ expand_home(const char *home, const char *path)
return nh;
}
-#include "_usage.h"
-#define getoptstring "I:KN:PR:Sa:bc:d:e:g:ik:mn:op:s:tu:r:w:x:1:2:" getoptstring_COMMON
-static const struct option longopts[] = {
- { "ionice", 1, NULL, 'I'},
- { "stop", 0, NULL, 'K'},
- { "nicelevel", 1, NULL, 'N'},
- { "retry", 1, NULL, 'R'},
- { "start", 0, NULL, 'S'},
- { "startas", 1, NULL, 'a'},
- { "background", 0, NULL, 'b'},
- { "chuid", 1, NULL, 'c'},
- { "chdir", 1, NULL, 'd'},
- { "env", 1, NULL, 'e'},
- { "umask", 1, NULL, 'k'},
- { "group", 1, NULL, 'g'},
- { "interpreted", 0, NULL, 'i'},
- { "make-pidfile", 0, NULL, 'm'},
- { "name", 1, NULL, 'n'},
- { "oknodo", 0, NULL, 'o'},
- { "pidfile", 1, NULL, 'p'},
- { "signal", 1, NULL, 's'},
- { "test", 0, NULL, 't'},
- { "user", 1, NULL, 'u'},
- { "chroot", 1, NULL, 'r'},
- { "wait", 1, NULL, 'w'},
- { "exec", 1, NULL, 'x'},
- { "stdout", 1, NULL, '1'},
- { "stderr", 1, NULL, '2'},
- { "progress", 0, NULL, 'P'},
- longopts_COMMON
-};
-static const char * const longopts_help[] = {
- "Set an ionice class:data when starting",
- "Stop daemon",
- "Set a nicelevel when starting",
- "Retry schedule to use when stopping",
- "Start daemon",
- "deprecated, use --exec or --name",
- "Force daemon to background",
- "deprecated, use --user",
- "Change the PWD",
- "Set an environment string",
- "Set the umask for the daemon",
- "Change the process group",
- "Match process name by interpreter",
- "Create a pidfile",
- "Match process name",
- "deprecated",
- "Match pid found in this file",
- "Send a different signal",
- "Test actions, don't do them",
- "Change the process user",
- "Chroot to this directory",
- "Milliseconds to wait for daemon start",
- "Binary to start/stop",
- "Redirect stdout to file",
- "Redirect stderr to file",
- "Print dots each second while waiting",
- longopts_help_COMMON
-};
-#include "_usage.c"
-
-int
-start_stop_daemon(int argc, char **argv)
+int main(int argc, char **argv)
{
int devnull_fd = -1;
#ifdef TIOCNOTTY
@@ -686,6 +686,7 @@ start_stop_daemon(int argc, char **argv)
char **margv;
unsigned int start_wait = 0;
+ applet = basename_c(argv[0]);
TAILQ_INIT(&schedule);
#ifdef DEBUG_MEMORY
atexit(cleanup);
diff --git a/src/rc/swclock.c b/src/rc/swclock.c
index 2c7e8b8e..4b62a460 100644
--- a/src/rc/swclock.c
+++ b/src/rc/swclock.c
@@ -25,40 +25,39 @@
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
+#include <stdio.h>
#include <unistd.h>
#include <utime.h>
-#include "builtins.h"
#include "einfo.h"
#include "rc-misc.h"
+#include "_usage.h"
#define RC_SHUTDOWNTIME RC_SVCDIR "/shutdowntime"
-extern const char *applet;
-
-#include "_usage.h"
-#define extraopts "file"
-#define getoptstring "sw" getoptstring_COMMON
-static const struct option longopts[] = {
+const char *applet = NULL;
+const char *extraopts = "file";
+const char *getoptstring = "sw" getoptstring_COMMON;
+const struct option longopts[] = {
{ "save", 0, NULL, 's' },
{ "warn", 0, NULL, 'w' },
longopts_COMMON
};
-static const char * const longopts_help[] = {
+const char * const longopts_help[] = {
"saves the time",
"no error if no reference file",
longopts_help_COMMON
};
-#include "_usage.c"
+const char *usagestring = NULL;
-int
-swclock(int argc, char **argv)
+int main(int argc, char **argv)
{
int opt, sflag = 0, wflag = 0;
const char *file = RC_SHUTDOWNTIME;
struct stat sb;
struct timeval tv;
+ applet = basename_c(argv[0]);
while ((opt = getopt_long(argc, argv, getoptstring,
longopts, (int *) 0)) != -1)
{