Remove multicall binary structure from OpenRC
This eliminates the need for the selinux-specific wrapper scrript we were installing in /lib*/rc/{bin,sbin}.
This commit is contained in:
parent
fe485f4433
commit
bf2f40828e
@ -53,6 +53,9 @@
|
|||||||
} while (/* CONSTCOND */ 0)
|
} while (/* CONSTCOND */ 0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
_unused static void *xmalloc (size_t size)
|
_unused static void *xmalloc (size_t size)
|
||||||
{
|
{
|
||||||
void *value = malloc(size);
|
void *value = malloc(size);
|
||||||
@ -104,4 +107,18 @@ _unused static const char *basename_c(const char *path)
|
|||||||
return (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
|
#endif
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
|
#include "rc.h"
|
||||||
|
|
||||||
#define RC_LEVEL_BOOT "boot"
|
#define RC_LEVEL_BOOT "boot"
|
||||||
#define RC_LEVEL_DEFAULT "default"
|
#define RC_LEVEL_DEFAULT "default"
|
||||||
@ -41,20 +42,6 @@
|
|||||||
#define RC_SVCDIR_STARTED RC_SVCDIR "/started"
|
#define RC_SVCDIR_STARTED RC_SVCDIR "/started"
|
||||||
#define RC_SVCDIR_COLDPLUGGED RC_SVCDIR "/coldplugged"
|
#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);
|
char *rc_conf_value(const char *var);
|
||||||
bool rc_conf_yesno(const char *var);
|
bool rc_conf_yesno(const char *var);
|
||||||
void env_filter(void);
|
void env_filter(void);
|
||||||
@ -78,4 +65,13 @@ const char *detect_prefix(void);
|
|||||||
const char *get_systype(void);
|
const char *get_systype(void);
|
||||||
const char *detect_container(void);
|
const char *detect_container(void);
|
||||||
const char *detect_vm(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
|
#endif
|
||||||
|
121
src/rc/Makefile
121
src/rc/Makefile
@ -1,8 +1,4 @@
|
|||||||
PROG= openrc
|
SRCS= rc.c rc-logger.c rc-misc.c rc-plugin.c
|
||||||
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
|
|
||||||
|
|
||||||
ifeq (${MKSELINUX},yes)
|
ifeq (${MKSELINUX},yes)
|
||||||
SRCS+= rc-selinux.c
|
SRCS+= rc-selinux.c
|
||||||
@ -14,26 +10,26 @@ BINDIR= ${PREFIX}/bin
|
|||||||
SBINDIR= ${PREFIX}/sbin
|
SBINDIR= ${PREFIX}/sbin
|
||||||
LINKDIR= ${LIBEXECDIR}
|
LINKDIR= ${LIBEXECDIR}
|
||||||
|
|
||||||
BINLINKS= rc-status
|
BINPROGS= rc-status
|
||||||
SBINLINKS= rc rc-service rc-update openrc-run runscript service \
|
SBINPROGS = openrc openrc-run rc rc-service rc-update runscript service start-stop-daemon
|
||||||
start-stop-daemon
|
RC_BINPROGS= einfon einfo ewarnn ewarn eerrorn eerror ebegin eend ewend \
|
||||||
RC_BINLINKS= einfon einfo ewarnn ewarn eerrorn eerror ebegin eend ewend \
|
|
||||||
eindent eoutdent esyslog eval_ecolors ewaitfile \
|
eindent eoutdent esyslog eval_ecolors ewaitfile \
|
||||||
veinfo vewarn vebegin veend vewend veindent veoutdent \
|
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_starting service_started \
|
||||||
service_stopping service_stopped \
|
service_stopping service_stopped \
|
||||||
service_inactive service_wasinactive \
|
service_inactive service_wasinactive \
|
||||||
service_hotplugged service_started_daemon service_crashed \
|
service_hotplugged service_started_daemon service_crashed \
|
||||||
checkpath fstabinfo mountinfo rc-depend \
|
shell_var
|
||||||
service_get_value service_set_value get_options save_options \
|
RC_SBINPROGS= mark_service_starting mark_service_started \
|
||||||
shell_var is_newer_than is_older_than
|
|
||||||
RC_SBINLINKS= mark_service_starting mark_service_started \
|
|
||||||
mark_service_stopping mark_service_stopped \
|
mark_service_stopping mark_service_stopped \
|
||||||
mark_service_inactive mark_service_wasinactive \
|
mark_service_inactive mark_service_wasinactive \
|
||||||
mark_service_hotplugged mark_service_failed \
|
mark_service_hotplugged mark_service_failed \
|
||||||
rc-abort swclock
|
rc-abort swclock
|
||||||
ALL_LINKS= ${BINLINKS} ${SBINLINKS} ${RC_BINLINKS} ${RC_SBINLINKS}
|
ALL_PROGS= ${BINPROGS} ${SBINPROGS} ${RC_BINPROGS} ${RC_SBINPROGS}
|
||||||
CLEANFILES+= ${ALL_LINKS}
|
CLEANFILES+= ${ALL_PROGS}
|
||||||
|
|
||||||
LOCAL_CPPFLAGS=-I../includes -I../librc -I../libeinfo
|
LOCAL_CPPFLAGS=-I../includes -I../librc -I../libeinfo
|
||||||
LOCAL_LDFLAGS=-L../librc -L../libeinfo
|
LOCAL_LDFLAGS=-L../librc -L../libeinfo
|
||||||
@ -49,22 +45,6 @@ include ${MK}/termcap.mk
|
|||||||
LDADD+= ${LIBDL} ${LIBKVM}
|
LDADD+= ${LIBDL} ${LIBKVM}
|
||||||
include ${MK}/pam.mk
|
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
|
${SRCS}: version.h
|
||||||
|
|
||||||
.PHONY: version.h.tmp
|
.PHONY: version.h.tmp
|
||||||
@ -79,15 +59,13 @@ version.h: version.h.tmp
|
|||||||
|
|
||||||
install: all
|
install: all
|
||||||
${INSTALL} -d ${DESTDIR}${SBINDIR}
|
${INSTALL} -d ${DESTDIR}${SBINDIR}
|
||||||
${INSTALL} -m ${BINMODE} ${PROG} ${DESTDIR}${SBINDIR}
|
${INSTALL} -m ${BINMODE} ${SBINPROGS} ${DESTDIR}${SBINDIR}
|
||||||
${INSTALL} -d ${DESTDIR}${BINDIR}
|
${INSTALL} -d ${DESTDIR}${BINDIR}
|
||||||
$(call make-links,${BINLINKS},${SBINDIR}/${PROG},${DESTDIR}${BINDIR})
|
${INSTALL} -m ${BINMODE} ${BINPROGS} ${DESTDIR}${BINDIR}
|
||||||
${INSTALL} -d ${DESTDIR}${SBINDIR}
|
|
||||||
$(call make-links,${SBINLINKS},${SBINDIR}/${PROG},${DESTDIR}${SBINDIR})
|
|
||||||
${INSTALL} -d ${DESTDIR}${LINKDIR}/bin
|
${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
|
${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 \
|
if test "${MKPAM}" = pam; then \
|
||||||
${INSTALL} -d ${DESTDIR}${PAMDIR}; \
|
${INSTALL} -d ${DESTDIR}${PAMDIR}; \
|
||||||
${INSTALL} -m ${PAMMODE} start-stop-daemon.pam ${DESTDIR}${PAMDIR}/start-stop-daemon; \
|
${INSTALL} -m ${PAMMODE} start-stop-daemon.pam ${DESTDIR}${PAMDIR}/start-stop-daemon; \
|
||||||
@ -95,5 +73,70 @@ install: all
|
|||||||
|
|
||||||
check test::
|
check test::
|
||||||
|
|
||||||
links: ${PROG}
|
all: ${ALL_PROGS}
|
||||||
$(call make-links,${ALL_LINKS},${PROG},.)
|
|
||||||
|
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}
|
||||||
|
@ -10,8 +10,12 @@
|
|||||||
* except according to the terms contained in the LICENSE file.
|
* except according to the terms contained in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "version.h"
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "rc-misc.h"
|
||||||
|
#include "_usage.h"
|
||||||
|
#include "version.h"
|
||||||
|
|
||||||
#if lint
|
#if lint
|
||||||
# define _noreturn
|
# define _noreturn
|
||||||
@ -22,7 +26,7 @@
|
|||||||
# define _noreturn
|
# define _noreturn
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void set_quiet_options(void)
|
void set_quiet_options(void)
|
||||||
{
|
{
|
||||||
static int qcount = 0;
|
static int qcount = 0;
|
||||||
|
|
||||||
@ -37,8 +41,7 @@ static void set_quiet_options(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_noreturn static void
|
_noreturn void show_version(void)
|
||||||
show_version(void)
|
|
||||||
{
|
{
|
||||||
const char *systype = NULL;
|
const char *systype = NULL;
|
||||||
|
|
||||||
@ -56,8 +59,7 @@ show_version(void)
|
|||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
_noreturn static void
|
_noreturn void usage(int exit_status)
|
||||||
usage(int exit_status)
|
|
||||||
{
|
{
|
||||||
const char * const has_arg[] = { "", "<arg>", "[arg]" };
|
const char * const has_arg[] = { "", "<arg>", "[arg]" };
|
||||||
int i;
|
int i;
|
||||||
@ -67,15 +69,15 @@ usage(int exit_status)
|
|||||||
char *token;
|
char *token;
|
||||||
char val[4] = "-?,";
|
char val[4] = "-?,";
|
||||||
|
|
||||||
#ifdef usagestring
|
if (usagestring)
|
||||||
printf(usagestring);
|
printf("%s", usagestring);
|
||||||
#else
|
else
|
||||||
printf("Usage: %s [options] ", applet);
|
printf("Usage: %s [options] ", applet);
|
||||||
#endif
|
|
||||||
#ifdef extraopts
|
if (extraopts)
|
||||||
printf(extraopts);
|
printf("%s", extraopts);
|
||||||
#endif
|
|
||||||
printf("\n\nOptions: [" getoptstring "]\n");
|
printf("\n\nOptions: [ %s ]\n", getoptstring);
|
||||||
for (i = 0; longopts[i].name; ++i) {
|
for (i = 0; longopts[i].name; ++i) {
|
||||||
val[1] = longopts[i].val;
|
val[1] = longopts[i].val;
|
||||||
len = printf(" %3s --%s %s", isprint(longopts[i].val) ? val : "",
|
len = printf(" %3s --%s %s", isprint(longopts[i].val) ? val : "",
|
||||||
|
@ -10,6 +10,8 @@
|
|||||||
* except according to the terms contained in the LICENSE file.
|
* except according to the terms contained in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <getopt.h>
|
||||||
|
|
||||||
#define getoptstring_COMMON "ChqVv"
|
#define getoptstring_COMMON "ChqVv"
|
||||||
|
|
||||||
#define longopts_COMMON \
|
#define longopts_COMMON \
|
||||||
@ -41,3 +43,14 @@
|
|||||||
case 'v': case_RC_COMMON_getopt_case_v; break; \
|
case 'v': case_RC_COMMON_getopt_case_v; break; \
|
||||||
case 'q': case_RC_COMMON_getopt_case_q; break; \
|
case 'q': case_RC_COMMON_getopt_case_q; break; \
|
||||||
default: case_RC_COMMON_getopt_default; 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);
|
||||||
|
@ -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);
|
|
@ -29,10 +29,10 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "builtins.h"
|
|
||||||
#include "einfo.h"
|
#include "einfo.h"
|
||||||
#include "rc-misc.h"
|
#include "rc-misc.h"
|
||||||
#include "rc-selinux.h"
|
#include "rc-selinux.h"
|
||||||
|
#include "_usage.h"
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
inode_unknown = 0,
|
inode_unknown = 0,
|
||||||
@ -41,7 +41,32 @@ typedef enum {
|
|||||||
inode_fifo = 3,
|
inode_fifo = 3,
|
||||||
} inode_t;
|
} 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,
|
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)
|
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;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "_usage.h"
|
int main(int argc, char **argv)
|
||||||
#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 opt;
|
int opt;
|
||||||
uid_t uid = geteuid();
|
uid_t uid = geteuid();
|
||||||
@ -229,6 +227,7 @@ int checkpath(int argc, char **argv)
|
|||||||
bool writable = false;
|
bool writable = false;
|
||||||
bool selinux_on = false;
|
bool selinux_on = false;
|
||||||
|
|
||||||
|
applet = basename_c(argv[0]);
|
||||||
while ((opt = getopt_long(argc, argv, getoptstring,
|
while ((opt = getopt_long(argc, argv, getoptstring,
|
||||||
longopts, (int *) 0)) != -1)
|
longopts, (int *) 0)) != -1)
|
||||||
{
|
{
|
||||||
|
228
src/rc/do_e.c
Normal file
228
src/rc/do_e.c
Normal file
@ -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;
|
||||||
|
}
|
91
src/rc/do_mark_service.c
Normal file
91
src/rc/do_mark_service.c
Normal file
@ -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;
|
||||||
|
}
|
78
src/rc/do_service.c
Normal file
78
src/rc/do_service.c
Normal file
@ -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;
|
||||||
|
}
|
64
src/rc/do_value.c
Normal file
64
src/rc/do_value.c
Normal file
@ -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;
|
||||||
|
}
|
@ -55,11 +55,36 @@
|
|||||||
# define ENT_PASS(_ent) ent->fs_passno
|
# define ENT_PASS(_ent) ent->fs_passno
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "builtins.h"
|
|
||||||
#include "einfo.h"
|
#include "einfo.h"
|
||||||
#include "queue.h"
|
#include "queue.h"
|
||||||
#include "rc.h"
|
#include "rc.h"
|
||||||
#include "rc-misc.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
|
#ifdef HAVE_GETMNTENT
|
||||||
static struct mntent *
|
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_FILE (1 << 1)
|
||||||
#define OUTPUT_MOUNTARGS (1 << 2)
|
#define OUTPUT_MOUNTARGS (1 << 2)
|
||||||
#define OUTPUT_OPTIONS (1 << 3)
|
#define OUTPUT_OPTIONS (1 << 3)
|
||||||
@ -161,8 +162,7 @@ static const char * const longopts_help[] = {
|
|||||||
#define OUTPUT_MOUNT (1 << 6)
|
#define OUTPUT_MOUNT (1 << 6)
|
||||||
#define OUTPUT_REMOUNT (1 << 7)
|
#define OUTPUT_REMOUNT (1 << 7)
|
||||||
|
|
||||||
int
|
int main(int argc, char **argv)
|
||||||
fstabinfo(int argc, char **argv)
|
|
||||||
{
|
{
|
||||||
struct ENT *ent;
|
struct ENT *ent;
|
||||||
int result = EXIT_SUCCESS;
|
int result = EXIT_SUCCESS;
|
||||||
@ -181,6 +181,7 @@ fstabinfo(int argc, char **argv)
|
|||||||
/* Ensure that we are only quiet when explicitly told to be */
|
/* Ensure that we are only quiet when explicitly told to be */
|
||||||
unsetenv("EINFO_QUIET");
|
unsetenv("EINFO_QUIET");
|
||||||
|
|
||||||
|
applet = basename_c(argv[0]);
|
||||||
while ((opt = getopt_long(argc, argv, getoptstring,
|
while ((opt = getopt_long(argc, argv, getoptstring,
|
||||||
longopts, (int *) 0)) != -1)
|
longopts, (int *) 0)) != -1)
|
||||||
{
|
{
|
||||||
|
33
src/rc/is_newer_than.c
Normal file
33
src/rc/is_newer_than.c
Normal file
@ -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;
|
||||||
|
}
|
34
src/rc/is_older_than.c
Normal file
34
src/rc/is_older_than.c
Normal file
@ -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;
|
||||||
|
}
|
@ -39,13 +39,48 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "builtins.h"
|
|
||||||
#include "einfo.h"
|
#include "einfo.h"
|
||||||
#include "queue.h"
|
#include "queue.h"
|
||||||
#include "rc.h"
|
#include "rc.h"
|
||||||
#include "rc-misc.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 {
|
typedef enum {
|
||||||
mount_from,
|
mount_from,
|
||||||
@ -334,45 +369,7 @@ get_regex(const char *string)
|
|||||||
return reg;
|
return reg;
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "_usage.h"
|
int main(int argc, char **argv)
|
||||||
#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)
|
|
||||||
{
|
{
|
||||||
struct args args;
|
struct args args;
|
||||||
regex_t *point_regex = NULL;
|
regex_t *point_regex = NULL;
|
||||||
@ -390,6 +387,7 @@ mountinfo(int argc, char **argv)
|
|||||||
#define REG_FREE(_var) \
|
#define REG_FREE(_var) \
|
||||||
if (_var) { regfree(_var); free(_var); }
|
if (_var) { regfree(_var); free(_var); }
|
||||||
|
|
||||||
|
applet = basename_c(argv[0]);
|
||||||
memset (&args, 0, sizeof(args));
|
memset (&args, 0, sizeof(args));
|
||||||
args.mount_type = mount_to;
|
args.mount_type = mount_to;
|
||||||
args.netdev = net_ignore;
|
args.netdev = net_ignore;
|
||||||
|
@ -47,13 +47,13 @@
|
|||||||
# include <libutil.h>
|
# include <libutil.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "builtins.h"
|
|
||||||
#include "einfo.h"
|
#include "einfo.h"
|
||||||
#include "queue.h"
|
#include "queue.h"
|
||||||
#include "rc.h"
|
#include "rc.h"
|
||||||
#include "rc-misc.h"
|
#include "rc-misc.h"
|
||||||
#include "rc-plugin.h"
|
#include "rc-plugin.h"
|
||||||
#include "rc-selinux.h"
|
#include "rc-selinux.h"
|
||||||
|
#include "_usage.h"
|
||||||
|
|
||||||
#define PREFIX_LOCK RC_SVCDIR "/prefix.lock"
|
#define PREFIX_LOCK RC_SVCDIR "/prefix.lock"
|
||||||
|
|
||||||
@ -61,7 +61,29 @@
|
|||||||
#define WAIT_TIMEOUT 60 /* seconds until we timeout */
|
#define WAIT_TIMEOUT 60 /* seconds until we timeout */
|
||||||
#define WARN_TIMEOUT 10 /* warn about this every N seconds */
|
#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 char *service, *runlevel, *ibsave, *prefix;
|
||||||
static RC_DEPTREE *deptree;
|
static RC_DEPTREE *deptree;
|
||||||
static RC_STRINGLIST *applet_list, *services, *tmplist;
|
static RC_STRINGLIST *applet_list, *services, *tmplist;
|
||||||
@ -1063,31 +1085,7 @@ service_plugable(void)
|
|||||||
return allow;
|
return allow;
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "_usage.h"
|
int main(int argc, char **argv)
|
||||||
#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)
|
|
||||||
{
|
{
|
||||||
bool doneone = false;
|
bool doneone = false;
|
||||||
int retval, opt, depoptions = RC_DEP_TRACE;
|
int retval, opt, depoptions = RC_DEP_TRACE;
|
||||||
@ -1396,10 +1394,3 @@ openrc_run(int argc, char **argv)
|
|||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
runscript(int argc, char **argv)
|
|
||||||
{
|
|
||||||
ewarnv("runscript is deprecated; please use openrc-run instead.");
|
|
||||||
return (openrc_run(argc, argv));
|
|
||||||
}
|
|
||||||
|
43
src/rc/rc-abort.c
Normal file
43
src/rc/rc-abort.c
Normal file
@ -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;
|
||||||
|
}
|
@ -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);
|
|
||||||
}
|
|
@ -31,70 +31,16 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <utime.h>
|
#include <utime.h>
|
||||||
|
|
||||||
#include "builtins.h"
|
|
||||||
#include "einfo.h"
|
#include "einfo.h"
|
||||||
#include "queue.h"
|
#include "queue.h"
|
||||||
#include "rc.h"
|
#include "rc.h"
|
||||||
#include "rc-misc.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"
|
#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'},
|
{ "starting", 0, NULL, 'a'},
|
||||||
{ "stopping", 0, NULL, 'o'},
|
{ "stopping", 0, NULL, 'o'},
|
||||||
{ "type", 1, NULL, 't'},
|
{ "type", 1, NULL, 't'},
|
||||||
@ -104,7 +50,7 @@ static const struct option longopts[] = {
|
|||||||
{ "deptree-file", 1, NULL, 'F'},
|
{ "deptree-file", 1, NULL, 'F'},
|
||||||
longopts_COMMON
|
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 starting",
|
||||||
"Order services as if runlevel is stopping",
|
"Order services as if runlevel is stopping",
|
||||||
"Type(s) of dependency to list",
|
"Type(s) of dependency to list",
|
||||||
@ -114,10 +60,9 @@ static const char * const longopts_help[] = {
|
|||||||
"File to load cached deptree from",
|
"File to load cached deptree from",
|
||||||
longopts_help_COMMON
|
longopts_help_COMMON
|
||||||
};
|
};
|
||||||
#include "_usage.c"
|
const char *usagestring = NULL;
|
||||||
|
|
||||||
int
|
int main(int argc, char **argv)
|
||||||
rc_depend(int argc, char **argv)
|
|
||||||
{
|
{
|
||||||
RC_STRINGLIST *list;
|
RC_STRINGLIST *list;
|
||||||
RC_STRINGLIST *types;
|
RC_STRINGLIST *types;
|
||||||
@ -132,6 +77,7 @@ rc_depend(int argc, char **argv)
|
|||||||
char *token;
|
char *token;
|
||||||
char *deptree_file = NULL;
|
char *deptree_file = NULL;
|
||||||
|
|
||||||
|
applet = basename_c(argv[0]);
|
||||||
types = rc_stringlist_new();
|
types = rc_stringlist_new();
|
||||||
while ((opt = getopt_long(argc, argv, getoptstring,
|
while ((opt = getopt_long(argc, argv, getoptstring,
|
||||||
longopts, (int *) 0)) != -1)
|
longopts, (int *) 0)) != -1)
|
||||||
|
107
src/rc/rc-misc.c
107
src/rc/rc-misc.c
@ -23,6 +23,7 @@
|
|||||||
# include <sys/sysinfo.h>
|
# include <sys/sysinfo.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <sys/time.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
@ -31,7 +32,9 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <utime.h>
|
||||||
|
|
||||||
#include "einfo.h"
|
#include "einfo.h"
|
||||||
#include "queue.h"
|
#include "queue.h"
|
||||||
@ -488,3 +491,107 @@ const char *detect_vm(void)
|
|||||||
|
|
||||||
return NULL;
|
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;
|
||||||
|
}
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
* except according to the terms contained in the LICENSE file.
|
* except according to the terms contained in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_SELINUX
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
@ -384,3 +386,5 @@ out:
|
|||||||
free(run_init_t);
|
free(run_init_t);
|
||||||
free(curr_t);
|
free(curr_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
@ -21,39 +21,36 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "builtins.h"
|
|
||||||
#include "einfo.h"
|
#include "einfo.h"
|
||||||
#include "queue.h"
|
#include "queue.h"
|
||||||
#include "rc.h"
|
#include "rc.h"
|
||||||
#include "rc-misc.h"
|
#include "rc-misc.h"
|
||||||
|
|
||||||
extern char *applet;
|
|
||||||
|
|
||||||
#include "_usage.h"
|
#include "_usage.h"
|
||||||
#define usagestring "" \
|
|
||||||
"Usage: rc-service [options] [-i] <service> <cmd>...\n" \
|
const char *applet = NULL;
|
||||||
" or: rc-service [options] -e <service>\n" \
|
const char *extraopts = NULL;
|
||||||
" or: rc-service [options] -l\n" \
|
const char *getoptstring = "e:ilr:" getoptstring_COMMON;
|
||||||
" or: rc-service [options] -r <service>"
|
const struct option longopts[] = {
|
||||||
#define getoptstring "e:ilr:" getoptstring_COMMON
|
|
||||||
static const struct option longopts[] = {
|
|
||||||
{ "exists", 1, NULL, 'e' },
|
{ "exists", 1, NULL, 'e' },
|
||||||
{ "ifexists", 0, NULL, 'i' },
|
{ "ifexists", 0, NULL, 'i' },
|
||||||
{ "list", 0, NULL, 'l' },
|
{ "list", 0, NULL, 'l' },
|
||||||
{ "resolve", 1, NULL, 'r' },
|
{ "resolve", 1, NULL, 'r' },
|
||||||
longopts_COMMON
|
longopts_COMMON
|
||||||
};
|
};
|
||||||
static const char * const longopts_help[] = {
|
const char * const longopts_help[] = {
|
||||||
"tests if the service exists or not",
|
"tests if the service exists or not",
|
||||||
"if the service exists then run the command",
|
"if the service exists then run the command",
|
||||||
"list all available services",
|
"list all available services",
|
||||||
"resolve the service name to an init script",
|
"resolve the service name to an init script",
|
||||||
longopts_help_COMMON
|
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
|
int main(int argc, char **argv)
|
||||||
rc_service(int argc, char **argv)
|
|
||||||
{
|
{
|
||||||
int opt;
|
int opt;
|
||||||
char *service;
|
char *service;
|
||||||
@ -61,6 +58,7 @@ rc_service(int argc, char **argv)
|
|||||||
RC_STRING *s;
|
RC_STRING *s;
|
||||||
bool if_exists = false;
|
bool if_exists = false;
|
||||||
|
|
||||||
|
applet = basename_c(argv[0]);
|
||||||
/* Ensure that we are only quiet when explicitly told to be */
|
/* Ensure that we are only quiet when explicitly told to be */
|
||||||
unsetenv("EINFO_QUIET");
|
unsetenv("EINFO_QUIET");
|
||||||
|
|
||||||
|
@ -21,13 +21,37 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "builtins.h"
|
|
||||||
#include "einfo.h"
|
#include "einfo.h"
|
||||||
#include "queue.h"
|
#include "queue.h"
|
||||||
#include "rc.h"
|
#include "rc.h"
|
||||||
#include "rc-misc.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 bool test_crashed = false;
|
||||||
static RC_DEPTREE *deptree;
|
static RC_DEPTREE *deptree;
|
||||||
static RC_STRINGLIST *types;
|
static RC_STRINGLIST *types;
|
||||||
@ -35,35 +59,6 @@ static RC_STRINGLIST *types;
|
|||||||
static RC_STRINGLIST *levels, *services, *tmp, *alist;
|
static RC_STRINGLIST *levels, *services, *tmp, *alist;
|
||||||
static RC_STRINGLIST *sservices, *nservices, *needsme;
|
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
|
static void
|
||||||
print_level(const char *prefix, const char *level)
|
print_level(const char *prefix, const char *level)
|
||||||
{
|
{
|
||||||
@ -178,33 +173,7 @@ print_stacked_services(const char *runlevel)
|
|||||||
stackedlevels = NULL;
|
stackedlevels = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "_usage.h"
|
int main(int argc, char **argv)
|
||||||
#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)
|
|
||||||
{
|
{
|
||||||
RC_STRING *s, *l, *t, *level;
|
RC_STRING *s, *l, *t, *level;
|
||||||
|
|
||||||
@ -213,6 +182,7 @@ rc_status(int argc, char **argv)
|
|||||||
|
|
||||||
test_crashed = _rc_can_find_pids();
|
test_crashed = _rc_can_find_pids();
|
||||||
|
|
||||||
|
applet = basename_c(argv[0]);
|
||||||
while ((opt = getopt_long(argc, argv, getoptstring, longopts,
|
while ((opt = getopt_long(argc, argv, getoptstring, longopts,
|
||||||
(int *) 0)) != -1)
|
(int *) 0)) != -1)
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
|
@ -24,13 +24,31 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "builtins.h"
|
|
||||||
#include "einfo.h"
|
#include "einfo.h"
|
||||||
#include "queue.h"
|
#include "queue.h"
|
||||||
#include "rc.h"
|
#include "rc.h"
|
||||||
#include "rc-misc.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:
|
/* Return the number of changes made:
|
||||||
* -1 = no changes (error)
|
* -1 = no changes (error)
|
||||||
@ -182,32 +200,11 @@ show(RC_STRINGLIST *runlevels, bool verbose)
|
|||||||
rc_stringlist_free (services);
|
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 DOADD (1 << 1)
|
||||||
#define DODELETE (1 << 2)
|
#define DODELETE (1 << 2)
|
||||||
#define DOSHOW (1 << 3)
|
#define DOSHOW (1 << 3)
|
||||||
|
|
||||||
int
|
int main(int argc, char **argv)
|
||||||
rc_update(int argc, char **argv)
|
|
||||||
{
|
{
|
||||||
RC_DEPTREE *deptree;
|
RC_DEPTREE *deptree;
|
||||||
RC_STRINGLIST *runlevels;
|
RC_STRINGLIST *runlevels;
|
||||||
@ -222,6 +219,7 @@ rc_update(int argc, char **argv)
|
|||||||
int (*actfunc)(const char *, const char *);
|
int (*actfunc)(const char *, const char *);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
applet = basename_c(argv[0]);
|
||||||
while ((opt = getopt_long(argc, argv, getoptstring,
|
while ((opt = getopt_long(argc, argv, getoptstring,
|
||||||
longopts, (int *)0)) != -1)
|
longopts, (int *)0)) != -1)
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
|
55
src/rc/rc.c
55
src/rc/rc.c
@ -45,7 +45,6 @@ const char rc_copyright[] = "Copyright (c) 2007-2008 Roy Marples";
|
|||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "builtins.h"
|
|
||||||
#include "einfo.h"
|
#include "einfo.h"
|
||||||
#include "queue.h"
|
#include "queue.h"
|
||||||
#include "rc.h"
|
#include "rc.h"
|
||||||
@ -54,6 +53,27 @@ const char rc_copyright[] = "Copyright (c) 2007-2008 Roy Marples";
|
|||||||
#include "rc-plugin.h"
|
#include "rc-plugin.h"
|
||||||
|
|
||||||
#include "version.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 INITSH RC_LIBEXECDIR "/sh/init.sh"
|
||||||
#define INITEARLYSH RC_LIBEXECDIR "/sh/init-early.sh"
|
#define INITEARLYSH RC_LIBEXECDIR "/sh/init-early.sh"
|
||||||
@ -721,31 +741,7 @@ handle_bad_signal(int sig)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "_usage.h"
|
int main(int argc, char **argv)
|
||||||
#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)
|
|
||||||
{
|
{
|
||||||
const char *bootlevel = NULL;
|
const char *bootlevel = NULL;
|
||||||
char *newlevel = NULL;
|
char *newlevel = NULL;
|
||||||
@ -785,9 +781,6 @@ main(int argc, char **argv)
|
|||||||
if (!applet)
|
if (!applet)
|
||||||
eerrorx("arguments required");
|
eerrorx("arguments required");
|
||||||
|
|
||||||
/* Run our built in applets. If we ran one, we don't return. */
|
|
||||||
run_applets(argc, argv);
|
|
||||||
|
|
||||||
argc--;
|
argc--;
|
||||||
argv++;
|
argv++;
|
||||||
|
|
||||||
@ -813,10 +806,6 @@ main(int argc, char **argv)
|
|||||||
longopts, (int *) 0)) != -1)
|
longopts, (int *) 0)) != -1)
|
||||||
{
|
{
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'a':
|
|
||||||
/* Do nothing, actual logic in run_applets, this
|
|
||||||
* is a placeholder */
|
|
||||||
break;
|
|
||||||
case 'n':
|
case 'n':
|
||||||
nostop = true;
|
nostop = true;
|
||||||
break;
|
break;
|
||||||
|
41
src/rc/shell_var.c
Normal file
41
src/rc/shell_var.c
Normal file
@ -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;
|
||||||
|
}
|
@ -59,11 +59,75 @@
|
|||||||
static struct pam_conv conv = { NULL, NULL};
|
static struct pam_conv conv = { NULL, NULL};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "builtins.h"
|
|
||||||
#include "einfo.h"
|
#include "einfo.h"
|
||||||
#include "queue.h"
|
#include "queue.h"
|
||||||
#include "rc.h"
|
#include "rc.h"
|
||||||
#include "rc-misc.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
|
typedef struct scheduleitem
|
||||||
{
|
{
|
||||||
@ -81,7 +145,6 @@ typedef struct scheduleitem
|
|||||||
TAILQ_HEAD(, scheduleitem) schedule;
|
TAILQ_HEAD(, scheduleitem) schedule;
|
||||||
static char **nav;
|
static char **nav;
|
||||||
|
|
||||||
extern const char *applet;
|
|
||||||
static char *changeuser, *ch_root, *ch_dir;
|
static char *changeuser, *ch_root, *ch_dir;
|
||||||
|
|
||||||
extern char **environ;
|
extern char **environ;
|
||||||
@ -567,70 +630,7 @@ expand_home(const char *home, const char *path)
|
|||||||
return nh;
|
return nh;
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "_usage.h"
|
int main(int argc, char **argv)
|
||||||
#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 devnull_fd = -1;
|
int devnull_fd = -1;
|
||||||
#ifdef TIOCNOTTY
|
#ifdef TIOCNOTTY
|
||||||
@ -686,6 +686,7 @@ start_stop_daemon(int argc, char **argv)
|
|||||||
char **margv;
|
char **margv;
|
||||||
unsigned int start_wait = 0;
|
unsigned int start_wait = 0;
|
||||||
|
|
||||||
|
applet = basename_c(argv[0]);
|
||||||
TAILQ_INIT(&schedule);
|
TAILQ_INIT(&schedule);
|
||||||
#ifdef DEBUG_MEMORY
|
#ifdef DEBUG_MEMORY
|
||||||
atexit(cleanup);
|
atexit(cleanup);
|
||||||
|
@ -25,40 +25,39 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <utime.h>
|
#include <utime.h>
|
||||||
|
|
||||||
#include "builtins.h"
|
|
||||||
#include "einfo.h"
|
#include "einfo.h"
|
||||||
#include "rc-misc.h"
|
#include "rc-misc.h"
|
||||||
|
#include "_usage.h"
|
||||||
|
|
||||||
#define RC_SHUTDOWNTIME RC_SVCDIR "/shutdowntime"
|
#define RC_SHUTDOWNTIME RC_SVCDIR "/shutdowntime"
|
||||||
|
|
||||||
extern const char *applet;
|
const char *applet = NULL;
|
||||||
|
const char *extraopts = "file";
|
||||||
#include "_usage.h"
|
const char *getoptstring = "sw" getoptstring_COMMON;
|
||||||
#define extraopts "file"
|
const struct option longopts[] = {
|
||||||
#define getoptstring "sw" getoptstring_COMMON
|
|
||||||
static const struct option longopts[] = {
|
|
||||||
{ "save", 0, NULL, 's' },
|
{ "save", 0, NULL, 's' },
|
||||||
{ "warn", 0, NULL, 'w' },
|
{ "warn", 0, NULL, 'w' },
|
||||||
longopts_COMMON
|
longopts_COMMON
|
||||||
};
|
};
|
||||||
static const char * const longopts_help[] = {
|
const char * const longopts_help[] = {
|
||||||
"saves the time",
|
"saves the time",
|
||||||
"no error if no reference file",
|
"no error if no reference file",
|
||||||
longopts_help_COMMON
|
longopts_help_COMMON
|
||||||
};
|
};
|
||||||
#include "_usage.c"
|
const char *usagestring = NULL;
|
||||||
|
|
||||||
int
|
int main(int argc, char **argv)
|
||||||
swclock(int argc, char **argv)
|
|
||||||
{
|
{
|
||||||
int opt, sflag = 0, wflag = 0;
|
int opt, sflag = 0, wflag = 0;
|
||||||
const char *file = RC_SHUTDOWNTIME;
|
const char *file = RC_SHUTDOWNTIME;
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
|
|
||||||
|
applet = basename_c(argv[0]);
|
||||||
while ((opt = getopt_long(argc, argv, getoptstring,
|
while ((opt = getopt_long(argc, argv, getoptstring,
|
||||||
longopts, (int *) 0)) != -1)
|
longopts, (int *) 0)) != -1)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user