diff options
| author | William Hubbs <w.d.hubbs@gmail.com> | 2015-12-23 14:06:31 -0600 | 
|---|---|---|
| committer | William Hubbs <w.d.hubbs@gmail.com> | 2016-01-12 10:42:14 -0600 | 
| commit | bf2f40828ee26d3ba9185f29db596ee5d7b9cf61 (patch) | |
| tree | de1ccdb2fd86e476323908c37ae6588a9ac9ae97 | |
| parent | fe485f44339963fdbee143687dcbef2069924bc6 (diff) | |
| download | openrc-bf2f40828ee26d3ba9185f29db596ee5d7b9cf61.tar.xz | |
Remove multicall binary structure from OpenRC
This eliminates the need for the selinux-specific wrapper scrript we
were installing in /lib*/rc/{bin,sbin}.
| -rw-r--r-- | src/includes/helpers.h | 17 | ||||
| -rw-r--r-- | src/includes/rc-misc.h | 24 | ||||
| -rw-r--r-- | src/rc/Makefile | 133 | ||||
| -rw-r--r-- | src/rc/_usage.c | 32 | ||||
| -rw-r--r-- | src/rc/_usage.h | 13 | ||||
| -rw-r--r-- | src/rc/builtins.h | 34 | ||||
| -rw-r--r-- | src/rc/checkpath.c | 59 | ||||
| -rw-r--r-- | src/rc/do_e.c | 228 | ||||
| -rw-r--r-- | src/rc/do_mark_service.c | 91 | ||||
| -rw-r--r-- | src/rc/do_service.c | 78 | ||||
| -rw-r--r-- | src/rc/do_value.c | 64 | ||||
| -rw-r--r-- | src/rc/fstabinfo.c | 55 | ||||
| -rw-r--r-- | src/rc/is_newer_than.c | 33 | ||||
| -rw-r--r-- | src/rc/is_older_than.c | 34 | ||||
| -rw-r--r-- | src/rc/mountinfo.c | 80 | ||||
| -rw-r--r-- | src/rc/openrc-run.c | 59 | ||||
| -rw-r--r-- | src/rc/rc-abort.c | 43 | ||||
| -rw-r--r-- | src/rc/rc-applets.c | 557 | ||||
| -rw-r--r-- | src/rc/rc-depend.c | 72 | ||||
| -rw-r--r-- | src/rc/rc-misc.c | 107 | ||||
| -rw-r--r-- | src/rc/rc-selinux.c | 4 | ||||
| -rw-r--r-- | src/rc/rc-service.c | 28 | ||||
| -rw-r--r-- | src/rc/rc-status.c | 86 | ||||
| -rw-r--r-- | src/rc/rc-update.c | 46 | ||||
| -rw-r--r-- | src/rc/rc.c | 55 | ||||
| -rw-r--r-- | src/rc/shell_var.c | 41 | ||||
| -rw-r--r-- | src/rc/start-stop-daemon.c | 133 | ||||
| -rw-r--r-- | src/rc/swclock.c | 21 | 
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)  	{ | 
