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:
		@@ -53,6 +53,9 @@
 | 
			
		||||
	} while (/* CONSTCOND */ 0)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
 | 
			
		||||
_unused static void *xmalloc (size_t size)
 | 
			
		||||
{
 | 
			
		||||
	void *value = malloc(size);
 | 
			
		||||
@@ -104,4 +107,18 @@ _unused static const char *basename_c(const char *path)
 | 
			
		||||
	return (path);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
_unused static bool exists(const char *pathname)
 | 
			
		||||
{
 | 
			
		||||
	struct stat buf;
 | 
			
		||||
 | 
			
		||||
	return (stat(pathname, &buf) == 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
_unused static bool existss(const char *pathname)
 | 
			
		||||
{
 | 
			
		||||
	struct stat buf;
 | 
			
		||||
 | 
			
		||||
	return (stat(pathname, &buf) == 0 && buf.st_size != 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -26,6 +26,7 @@
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
 | 
			
		||||
#include "helpers.h"
 | 
			
		||||
#include "rc.h"
 | 
			
		||||
 | 
			
		||||
#define RC_LEVEL_BOOT           "boot"
 | 
			
		||||
#define RC_LEVEL_DEFAULT        "default"
 | 
			
		||||
@@ -41,20 +42,6 @@
 | 
			
		||||
#define RC_SVCDIR_STARTED       RC_SVCDIR "/started"
 | 
			
		||||
#define RC_SVCDIR_COLDPLUGGED	RC_SVCDIR "/coldplugged"
 | 
			
		||||
 | 
			
		||||
_unused static bool exists(const char *pathname)
 | 
			
		||||
{
 | 
			
		||||
	struct stat buf;
 | 
			
		||||
 | 
			
		||||
	return (stat(pathname, &buf) == 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
_unused static bool existss(const char *pathname)
 | 
			
		||||
{
 | 
			
		||||
	struct stat buf;
 | 
			
		||||
 | 
			
		||||
	return (stat(pathname, &buf) == 0 && buf.st_size != 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char *rc_conf_value(const char *var);
 | 
			
		||||
bool rc_conf_yesno(const char *var);
 | 
			
		||||
void env_filter(void);
 | 
			
		||||
@@ -78,4 +65,13 @@ const char *detect_prefix(void);
 | 
			
		||||
const char *get_systype(void);
 | 
			
		||||
const char *detect_container(void);
 | 
			
		||||
const char *detect_vm(void);
 | 
			
		||||
 | 
			
		||||
/* Handy function so we can wrap einfo around our deptree */
 | 
			
		||||
RC_DEPTREE *_rc_deptree_load (int, int *);
 | 
			
		||||
 | 
			
		||||
/* Test to see if we can see pid 1 or not */
 | 
			
		||||
bool _rc_can_find_pids(void);
 | 
			
		||||
 | 
			
		||||
RC_SERVICE lookup_service_state(const char *service);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										121
									
								
								src/rc/Makefile
									
									
									
									
									
								
							
							
						
						
									
										121
									
								
								src/rc/Makefile
									
									
									
									
									
								
							@@ -1,8 +1,4 @@
 | 
			
		||||
PROG=		openrc
 | 
			
		||||
SRCS=		checkpath.c fstabinfo.c mountinfo.c openrc-run.c \
 | 
			
		||||
		rc-applets.c rc-depend.c rc-logger.c \
 | 
			
		||||
		rc-misc.c rc-plugin.c rc-service.c rc-status.c rc-update.c \
 | 
			
		||||
		rc.c start-stop-daemon.c swclock.c
 | 
			
		||||
SRCS=	rc.c 	rc-logger.c rc-misc.c rc-plugin.c
 | 
			
		||||
 | 
			
		||||
ifeq (${MKSELINUX},yes)
 | 
			
		||||
SRCS+=		rc-selinux.c
 | 
			
		||||
@@ -14,26 +10,26 @@ BINDIR=		${PREFIX}/bin
 | 
			
		||||
SBINDIR=	${PREFIX}/sbin
 | 
			
		||||
LINKDIR=	${LIBEXECDIR}
 | 
			
		||||
 | 
			
		||||
BINLINKS=	rc-status
 | 
			
		||||
SBINLINKS=	rc rc-service rc-update openrc-run runscript service \
 | 
			
		||||
			start-stop-daemon
 | 
			
		||||
RC_BINLINKS=	einfon einfo ewarnn ewarn eerrorn eerror ebegin eend ewend \
 | 
			
		||||
BINPROGS=	rc-status
 | 
			
		||||
SBINPROGS = openrc openrc-run rc rc-service rc-update runscript service start-stop-daemon
 | 
			
		||||
RC_BINPROGS=	einfon einfo ewarnn ewarn eerrorn eerror ebegin eend ewend \
 | 
			
		||||
				eindent eoutdent esyslog eval_ecolors ewaitfile \
 | 
			
		||||
				veinfo vewarn vebegin veend vewend veindent veoutdent \
 | 
			
		||||
				checkpath fstabinfo mountinfo rc-depend \
 | 
			
		||||
				is_newer_than is_older_than \
 | 
			
		||||
				service_get_value service_set_value get_options save_options \
 | 
			
		||||
				service_starting service_started \
 | 
			
		||||
				service_stopping service_stopped \
 | 
			
		||||
				service_inactive service_wasinactive \
 | 
			
		||||
				service_hotplugged service_started_daemon service_crashed \
 | 
			
		||||
		checkpath fstabinfo mountinfo rc-depend \
 | 
			
		||||
		service_get_value service_set_value get_options save_options \
 | 
			
		||||
		shell_var is_newer_than is_older_than
 | 
			
		||||
RC_SBINLINKS=	mark_service_starting mark_service_started \
 | 
			
		||||
				shell_var
 | 
			
		||||
RC_SBINPROGS=	mark_service_starting mark_service_started \
 | 
			
		||||
		mark_service_stopping mark_service_stopped \
 | 
			
		||||
		mark_service_inactive mark_service_wasinactive \
 | 
			
		||||
		mark_service_hotplugged mark_service_failed \
 | 
			
		||||
		rc-abort swclock
 | 
			
		||||
ALL_LINKS=	${BINLINKS} ${SBINLINKS} ${RC_BINLINKS} ${RC_SBINLINKS}
 | 
			
		||||
CLEANFILES+=	${ALL_LINKS}
 | 
			
		||||
ALL_PROGS=	${BINPROGS} ${SBINPROGS} ${RC_BINPROGS} ${RC_SBINPROGS}
 | 
			
		||||
CLEANFILES+=	${ALL_PROGS}
 | 
			
		||||
 | 
			
		||||
LOCAL_CPPFLAGS=-I../includes -I../librc -I../libeinfo
 | 
			
		||||
LOCAL_LDFLAGS=-L../librc -L../libeinfo
 | 
			
		||||
@@ -49,22 +45,6 @@ include ${MK}/termcap.mk
 | 
			
		||||
LDADD+=		${LIBDL} ${LIBKVM}
 | 
			
		||||
include ${MK}/pam.mk
 | 
			
		||||
 | 
			
		||||
# create symlinks to rc if not an SELINUX system, otherwise create a wrapper
 | 
			
		||||
# script to call rc with the proper name of the applet to execute.
 | 
			
		||||
# $1 is a list of the links
 | 
			
		||||
# $2 is the path+name of the target to link to (usually 'rc' or '/sbin/rc')
 | 
			
		||||
# $3 is the path where the links are created
 | 
			
		||||
define make-links
 | 
			
		||||
	for x in $(1); do \
 | 
			
		||||
		if [ "${MKSELINUX}" = yes ]; then \
 | 
			
		||||
			printf '#!/bin/sh\nexec ${2} --applet %s "$$@"\n' $$x >${3}/$$x; \
 | 
			
		||||
			chmod ${BINMODE} ${3}/$$x; \
 | 
			
		||||
		else \
 | 
			
		||||
			ln -sf ${2} ${3}/$$x; \
 | 
			
		||||
		fi; \
 | 
			
		||||
	done;
 | 
			
		||||
endef
 | 
			
		||||
 | 
			
		||||
${SRCS}: version.h
 | 
			
		||||
 | 
			
		||||
.PHONY:	version.h.tmp
 | 
			
		||||
@@ -79,15 +59,13 @@ version.h: version.h.tmp
 | 
			
		||||
 | 
			
		||||
install: all
 | 
			
		||||
	${INSTALL} -d ${DESTDIR}${SBINDIR}
 | 
			
		||||
	${INSTALL} -m ${BINMODE} ${PROG} ${DESTDIR}${SBINDIR}
 | 
			
		||||
	${INSTALL} -m ${BINMODE} ${SBINPROGS} ${DESTDIR}${SBINDIR}
 | 
			
		||||
	${INSTALL} -d ${DESTDIR}${BINDIR}
 | 
			
		||||
	$(call make-links,${BINLINKS},${SBINDIR}/${PROG},${DESTDIR}${BINDIR})
 | 
			
		||||
	${INSTALL} -d ${DESTDIR}${SBINDIR}
 | 
			
		||||
	$(call make-links,${SBINLINKS},${SBINDIR}/${PROG},${DESTDIR}${SBINDIR})
 | 
			
		||||
	${INSTALL} -m ${BINMODE} ${BINPROGS} ${DESTDIR}${BINDIR}
 | 
			
		||||
	${INSTALL} -d ${DESTDIR}${LINKDIR}/bin
 | 
			
		||||
	$(call make-links,${RC_BINLINKS},${SBINDIR}/${PROG},${DESTDIR}${LINKDIR}/bin)
 | 
			
		||||
	${INSTALL} -m ${BINMODE} ${RC_BINPROGS} ${DESTDIR}${LINKDIR}/bin
 | 
			
		||||
	${INSTALL} -d ${DESTDIR}${LINKDIR}/sbin
 | 
			
		||||
	$(call make-links, ${RC_SBINLINKS},${SBINDIR}/${PROG},${DESTDIR}${LINKDIR}/sbin)
 | 
			
		||||
	${INSTALL} -m ${BINMODE} ${RC_SBINPROGS} ${DESTDIR}${LINKDIR}/sbin
 | 
			
		||||
	if test "${MKPAM}" = pam; then \
 | 
			
		||||
		${INSTALL} -d ${DESTDIR}${PAMDIR}; \
 | 
			
		||||
		${INSTALL} -m ${PAMMODE} start-stop-daemon.pam ${DESTDIR}${PAMDIR}/start-stop-daemon; \
 | 
			
		||||
@@ -95,5 +73,70 @@ install: all
 | 
			
		||||
 | 
			
		||||
check test::
 | 
			
		||||
 | 
			
		||||
links: ${PROG}
 | 
			
		||||
	$(call make-links,${ALL_LINKS},${PROG},.)
 | 
			
		||||
all: ${ALL_PROGS}
 | 
			
		||||
 | 
			
		||||
checkpath: checkpath.o _usage.o rc-misc.o rc-selinux.o
 | 
			
		||||
	${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
 | 
			
		||||
 | 
			
		||||
einfon einfo ewarnn ewarn eerrorn eerror ebegin eend ewend \
 | 
			
		||||
eindent eoutdent esyslog eval_ecolors ewaitfile \
 | 
			
		||||
veinfo vewarn vebegin veend vewend veindent veoutdent: do_e.o rc-misc.o
 | 
			
		||||
	${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
 | 
			
		||||
 | 
			
		||||
fstabinfo: fstabinfo.o _usage.o rc-misc.o
 | 
			
		||||
	${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
 | 
			
		||||
 | 
			
		||||
is_newer_than: is_newer_than.o rc-misc.o
 | 
			
		||||
	${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
 | 
			
		||||
 | 
			
		||||
is_older_than: is_older_than.o rc-misc.o
 | 
			
		||||
	${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
 | 
			
		||||
 | 
			
		||||
mark_service_starting mark_service_started \
 | 
			
		||||
mark_service_stopping mark_service_stopped \
 | 
			
		||||
mark_service_inactive mark_service_wasinactive \
 | 
			
		||||
mark_service_hotplugged mark_service_failed: do_mark_service.o rc-misc.o
 | 
			
		||||
	${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
 | 
			
		||||
 | 
			
		||||
mountinfo: mountinfo.o _usage.o rc-misc.o
 | 
			
		||||
	${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
 | 
			
		||||
 | 
			
		||||
openrc rc: rc.o rc-logger.o rc-misc.o rc-plugin.o rc-selinux.o _usage.o
 | 
			
		||||
	${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
 | 
			
		||||
 | 
			
		||||
openrc-run runscript: openrc-run.o _usage.o rc-misc.o rc-plugin.o
 | 
			
		||||
	${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
 | 
			
		||||
 | 
			
		||||
rc-abort: rc-abort.o
 | 
			
		||||
	${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ -leinfo
 | 
			
		||||
 | 
			
		||||
rc-depend: rc-depend.o _usage.o rc-misc.o
 | 
			
		||||
	${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
 | 
			
		||||
 | 
			
		||||
rc-status: rc-status.o _usage.o rc-misc.o
 | 
			
		||||
	${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
 | 
			
		||||
 | 
			
		||||
rc-service service: rc-service.o _usage.o rc-misc.o
 | 
			
		||||
	${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
 | 
			
		||||
 | 
			
		||||
rc-update: rc-update.o _usage.o rc-misc.o
 | 
			
		||||
	${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
 | 
			
		||||
 | 
			
		||||
start-stop-daemon: start-stop-daemon.o _usage.o rc-misc.o
 | 
			
		||||
	${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
 | 
			
		||||
 | 
			
		||||
service_get_value service_set_value get_options save_options: do_value.o rc-misc.o
 | 
			
		||||
	${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
 | 
			
		||||
 | 
			
		||||
service_starting service_started \
 | 
			
		||||
service_stopping service_stopped \
 | 
			
		||||
service_inactive service_wasinactive \
 | 
			
		||||
service_hotplugged service_started_daemon \
 | 
			
		||||
service_crashed: do_service.o rc-misc.o
 | 
			
		||||
	${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
 | 
			
		||||
 | 
			
		||||
shell_var: shell_var.o
 | 
			
		||||
	${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^
 | 
			
		||||
 | 
			
		||||
swclock: swclock.o _usage.o rc-misc.o
 | 
			
		||||
	${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
 | 
			
		||||
 
 | 
			
		||||
@@ -10,8 +10,12 @@
 | 
			
		||||
 *    except according to the terms contained in the LICENSE file.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "version.h"
 | 
			
		||||
#include <ctype.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include "rc-misc.h"
 | 
			
		||||
#include "_usage.h"
 | 
			
		||||
#include "version.h"
 | 
			
		||||
 | 
			
		||||
#if lint
 | 
			
		||||
#  define _noreturn
 | 
			
		||||
@@ -22,7 +26,7 @@
 | 
			
		||||
#  define _noreturn
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static void set_quiet_options(void)
 | 
			
		||||
void set_quiet_options(void)
 | 
			
		||||
{
 | 
			
		||||
	static int qcount = 0;
 | 
			
		||||
 | 
			
		||||
@@ -37,8 +41,7 @@ static void set_quiet_options(void)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
_noreturn static void
 | 
			
		||||
show_version(void)
 | 
			
		||||
_noreturn void show_version(void)
 | 
			
		||||
{
 | 
			
		||||
	const char *systype = NULL;
 | 
			
		||||
 | 
			
		||||
@@ -56,8 +59,7 @@ show_version(void)
 | 
			
		||||
	exit(EXIT_SUCCESS);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
_noreturn static void
 | 
			
		||||
usage(int exit_status)
 | 
			
		||||
_noreturn void usage(int exit_status)
 | 
			
		||||
{
 | 
			
		||||
	const char * const has_arg[] = { "", "<arg>", "[arg]" };
 | 
			
		||||
	int i;
 | 
			
		||||
@@ -67,15 +69,15 @@ usage(int exit_status)
 | 
			
		||||
	char *token;
 | 
			
		||||
	char val[4] = "-?,";
 | 
			
		||||
 | 
			
		||||
#ifdef usagestring
 | 
			
		||||
	printf(usagestring);
 | 
			
		||||
#else
 | 
			
		||||
	if (usagestring)
 | 
			
		||||
		printf("%s", usagestring);
 | 
			
		||||
	else
 | 
			
		||||
		printf("Usage: %s [options] ", applet);
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef extraopts
 | 
			
		||||
	printf(extraopts);
 | 
			
		||||
#endif
 | 
			
		||||
	printf("\n\nOptions: [" getoptstring "]\n");
 | 
			
		||||
 | 
			
		||||
	if (extraopts)
 | 
			
		||||
		printf("%s", extraopts);
 | 
			
		||||
 | 
			
		||||
	printf("\n\nOptions: [ %s ]\n", getoptstring);
 | 
			
		||||
	for (i = 0; longopts[i].name; ++i) {
 | 
			
		||||
		val[1] = longopts[i].val;
 | 
			
		||||
		len = printf("  %3s --%s %s", isprint(longopts[i].val) ? val : "",
 | 
			
		||||
 
 | 
			
		||||
@@ -10,6 +10,8 @@
 | 
			
		||||
 *    except according to the terms contained in the LICENSE file.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <getopt.h>
 | 
			
		||||
 | 
			
		||||
#define getoptstring_COMMON "ChqVv"
 | 
			
		||||
 | 
			
		||||
#define longopts_COMMON							      \
 | 
			
		||||
@@ -41,3 +43,14 @@
 | 
			
		||||
	case 'v': case_RC_COMMON_getopt_case_v; break;			      \
 | 
			
		||||
	case 'q': case_RC_COMMON_getopt_case_q; break;			      \
 | 
			
		||||
	default:  case_RC_COMMON_getopt_default; break;
 | 
			
		||||
 | 
			
		||||
extern const char *applet;
 | 
			
		||||
extern const char *extraopts;
 | 
			
		||||
extern const char *getoptstring;
 | 
			
		||||
extern const struct option longopts[];
 | 
			
		||||
extern const char * const longopts_help[];
 | 
			
		||||
extern const char *usagestring;
 | 
			
		||||
 | 
			
		||||
void set_quiet_options(void);
 | 
			
		||||
void show_version(void);
 | 
			
		||||
void usage(int exit_status);
 | 
			
		||||
 
 | 
			
		||||
@@ -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 <unistd.h>
 | 
			
		||||
 | 
			
		||||
#include "builtins.h"
 | 
			
		||||
#include "einfo.h"
 | 
			
		||||
#include "rc-misc.h"
 | 
			
		||||
#include "rc-selinux.h"
 | 
			
		||||
#include "_usage.h"
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
	inode_unknown = 0,
 | 
			
		||||
@@ -41,7 +41,32 @@ typedef enum {
 | 
			
		||||
	inode_fifo = 3,
 | 
			
		||||
} inode_t;
 | 
			
		||||
 | 
			
		||||
extern const char *applet;
 | 
			
		||||
const char *applet = NULL;
 | 
			
		||||
const char *extraopts ="path1 [path2] [...]";
 | 
			
		||||
const char *getoptstring = "dDfFpm:o:W" getoptstring_COMMON;
 | 
			
		||||
const struct option longopts[] = {
 | 
			
		||||
	{ "directory",          0, NULL, 'd'},
 | 
			
		||||
	{ "directory-truncate", 0, NULL, 'D'},
 | 
			
		||||
	{ "file",               0, NULL, 'f'},
 | 
			
		||||
	{ "file-truncate",      0, NULL, 'F'},
 | 
			
		||||
	{ "pipe",               0, NULL, 'p'},
 | 
			
		||||
	{ "mode",               1, NULL, 'm'},
 | 
			
		||||
	{ "owner",              1, NULL, 'o'},
 | 
			
		||||
	{ "writable",           0, NULL, 'W'},
 | 
			
		||||
	longopts_COMMON
 | 
			
		||||
};
 | 
			
		||||
const char * const longopts_help[] = {
 | 
			
		||||
	"Create a directory if not exists",
 | 
			
		||||
	"Create/empty directory",
 | 
			
		||||
	"Create a file if not exists",
 | 
			
		||||
	"Truncate file",
 | 
			
		||||
	"Create a named pipe (FIFO) if not exists",
 | 
			
		||||
	"Mode to check",
 | 
			
		||||
	"Owner to check (user:group)",
 | 
			
		||||
	"Check whether the path is writable or not",
 | 
			
		||||
	longopts_help_COMMON
 | 
			
		||||
};
 | 
			
		||||
const char *usagestring = NULL;
 | 
			
		||||
 | 
			
		||||
static int do_check(char *path, uid_t uid, gid_t gid, mode_t mode,
 | 
			
		||||
	inode_t type, bool trunc, bool chowner, bool selinux_on)
 | 
			
		||||
@@ -187,34 +212,7 @@ static int parse_owner(struct passwd **user, struct group **group,
 | 
			
		||||
	return retval;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#include "_usage.h"
 | 
			
		||||
#define extraopts "path1 [path2] [...]"
 | 
			
		||||
#define getoptstring "dDfFpm:o:W" getoptstring_COMMON
 | 
			
		||||
static const struct option longopts[] = {
 | 
			
		||||
	{ "directory",          0, NULL, 'd'},
 | 
			
		||||
	{ "directory-truncate", 0, NULL, 'D'},
 | 
			
		||||
	{ "file",               0, NULL, 'f'},
 | 
			
		||||
	{ "file-truncate",      0, NULL, 'F'},
 | 
			
		||||
	{ "pipe",               0, NULL, 'p'},
 | 
			
		||||
	{ "mode",               1, NULL, 'm'},
 | 
			
		||||
	{ "owner",              1, NULL, 'o'},
 | 
			
		||||
	{ "writable",           0, NULL, 'W'},
 | 
			
		||||
	longopts_COMMON
 | 
			
		||||
};
 | 
			
		||||
static const char * const longopts_help[] = {
 | 
			
		||||
	"Create a directory if not exists",
 | 
			
		||||
	"Create/empty directory",
 | 
			
		||||
	"Create a file if not exists",
 | 
			
		||||
	"Truncate file",
 | 
			
		||||
	"Create a named pipe (FIFO) if not exists",
 | 
			
		||||
	"Mode to check",
 | 
			
		||||
	"Owner to check (user:group)",
 | 
			
		||||
	"Check whether the path is writable or not",
 | 
			
		||||
	longopts_help_COMMON
 | 
			
		||||
};
 | 
			
		||||
#include "_usage.c"
 | 
			
		||||
 | 
			
		||||
int checkpath(int argc, char **argv)
 | 
			
		||||
int main(int argc, char **argv)
 | 
			
		||||
{
 | 
			
		||||
	int opt;
 | 
			
		||||
	uid_t uid = geteuid();
 | 
			
		||||
@@ -229,6 +227,7 @@ int checkpath(int argc, char **argv)
 | 
			
		||||
	bool writable = false;
 | 
			
		||||
	bool selinux_on = false;
 | 
			
		||||
 | 
			
		||||
	applet = basename_c(argv[0]);
 | 
			
		||||
	while ((opt = getopt_long(argc, argv, getoptstring,
 | 
			
		||||
		    longopts, (int *) 0)) != -1)
 | 
			
		||||
	{
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										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
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "builtins.h"
 | 
			
		||||
#include "einfo.h"
 | 
			
		||||
#include "queue.h"
 | 
			
		||||
#include "rc.h"
 | 
			
		||||
#include "rc-misc.h"
 | 
			
		||||
#include "_usage.h"
 | 
			
		||||
 | 
			
		||||
const char *applet = NULL;
 | 
			
		||||
const char *extraopts = NULL;
 | 
			
		||||
const char *getoptstring = "MRbmop:t:" getoptstring_COMMON;
 | 
			
		||||
const struct option longopts[] = {
 | 
			
		||||
	{ "mount",          0, NULL, 'M' },
 | 
			
		||||
	{ "remount",        0, NULL, 'R' },
 | 
			
		||||
	{ "blockdevice",    0, NULL, 'b' },
 | 
			
		||||
	{ "mountargs",      0, NULL, 'm' },
 | 
			
		||||
	{ "options",        0, NULL, 'o' },
 | 
			
		||||
	{ "passno",         1, NULL, 'p' },
 | 
			
		||||
	{ "fstype",         1, NULL, 't' },
 | 
			
		||||
	longopts_COMMON
 | 
			
		||||
};
 | 
			
		||||
const char * const longopts_help[] = {
 | 
			
		||||
	"Mounts the filesytem from the mountpoint",
 | 
			
		||||
	"Remounts the filesystem based on the information in fstab",
 | 
			
		||||
	"Extract the block device",
 | 
			
		||||
	"Show arguments needed to mount the entry",
 | 
			
		||||
	"Extract the options field",
 | 
			
		||||
	"Extract or query the pass number field",
 | 
			
		||||
	"List entries with matching file system type",
 | 
			
		||||
	longopts_help_COMMON
 | 
			
		||||
};
 | 
			
		||||
const char *usagestring = NULL;
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_GETMNTENT
 | 
			
		||||
static struct mntent *
 | 
			
		||||
@@ -129,30 +154,6 @@ do_mount(struct ENT *ent, bool remount)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#include "_usage.h"
 | 
			
		||||
#define getoptstring "MRbmop:t:" getoptstring_COMMON
 | 
			
		||||
static const struct option longopts[] = {
 | 
			
		||||
	{ "mount",          0, NULL, 'M' },
 | 
			
		||||
	{ "remount",        0, NULL, 'R' },
 | 
			
		||||
	{ "blockdevice",    0, NULL, 'b' },
 | 
			
		||||
	{ "mountargs",      0, NULL, 'm' },
 | 
			
		||||
	{ "options",        0, NULL, 'o' },
 | 
			
		||||
	{ "passno",         1, NULL, 'p' },
 | 
			
		||||
	{ "fstype",         1, NULL, 't' },
 | 
			
		||||
	longopts_COMMON
 | 
			
		||||
};
 | 
			
		||||
static const char * const longopts_help[] = {
 | 
			
		||||
	"Mounts the filesytem from the mountpoint",
 | 
			
		||||
	"Remounts the filesystem based on the information in fstab",
 | 
			
		||||
	"Extract the block device",
 | 
			
		||||
	"Show arguments needed to mount the entry",
 | 
			
		||||
	"Extract the options field",
 | 
			
		||||
	"Extract or query the pass number field",
 | 
			
		||||
	"List entries with matching file system type",
 | 
			
		||||
	longopts_help_COMMON
 | 
			
		||||
};
 | 
			
		||||
#include "_usage.c"
 | 
			
		||||
 | 
			
		||||
#define OUTPUT_FILE      (1 << 1)
 | 
			
		||||
#define OUTPUT_MOUNTARGS (1 << 2)
 | 
			
		||||
#define OUTPUT_OPTIONS   (1 << 3)
 | 
			
		||||
@@ -161,8 +162,7 @@ static const char * const longopts_help[] = {
 | 
			
		||||
#define OUTPUT_MOUNT     (1 << 6)
 | 
			
		||||
#define OUTPUT_REMOUNT   (1 << 7)
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
fstabinfo(int argc, char **argv)
 | 
			
		||||
int main(int argc, char **argv)
 | 
			
		||||
{
 | 
			
		||||
	struct ENT *ent;
 | 
			
		||||
	int result = EXIT_SUCCESS;
 | 
			
		||||
@@ -181,6 +181,7 @@ fstabinfo(int argc, char **argv)
 | 
			
		||||
	/* Ensure that we are only quiet when explicitly told to be */
 | 
			
		||||
	unsetenv("EINFO_QUIET");
 | 
			
		||||
 | 
			
		||||
	applet = basename_c(argv[0]);
 | 
			
		||||
	while ((opt = getopt_long(argc, argv, getoptstring,
 | 
			
		||||
		    longopts, (int *) 0)) != -1)
 | 
			
		||||
	{
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										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 <string.h>
 | 
			
		||||
 | 
			
		||||
#include "builtins.h"
 | 
			
		||||
#include "einfo.h"
 | 
			
		||||
#include "queue.h"
 | 
			
		||||
#include "rc.h"
 | 
			
		||||
#include "rc-misc.h"
 | 
			
		||||
#include "_usage.h"
 | 
			
		||||
 | 
			
		||||
extern const char *applet;
 | 
			
		||||
const char *applet = NULL;
 | 
			
		||||
const char *extraopts = "[mount1] [mount2] ...";
 | 
			
		||||
const char *getoptstring = "f:F:n:N:o:O:p:P:iste:E:" getoptstring_COMMON;
 | 
			
		||||
const struct option longopts[] = {
 | 
			
		||||
	{ "fstype-regex",        1, NULL, 'f'},
 | 
			
		||||
	{ "skip-fstype-regex",   1, NULL, 'F'},
 | 
			
		||||
	{ "node-regex",          1, NULL, 'n'},
 | 
			
		||||
	{ "skip-node-regex",     1, NULL, 'N'},
 | 
			
		||||
	{ "options-regex",       1, NULL, 'o'},
 | 
			
		||||
	{ "skip-options-regex",  1, NULL, 'O'},
 | 
			
		||||
	{ "point-regex",         1, NULL, 'p'},
 | 
			
		||||
	{ "skip-point-regex",    1, NULL, 'P'},
 | 
			
		||||
	{ "options",             0, NULL, 'i'},
 | 
			
		||||
	{ "fstype",              0, NULL, 's'},
 | 
			
		||||
	{ "node",                0, NULL, 't'},
 | 
			
		||||
	{ "netdev",              0, NULL, 'e'},
 | 
			
		||||
	{ "nonetdev",            0, NULL, 'E'},
 | 
			
		||||
	longopts_COMMON
 | 
			
		||||
};
 | 
			
		||||
const char * const longopts_help[] = {
 | 
			
		||||
	"fstype regex to find",
 | 
			
		||||
	"fstype regex to skip",
 | 
			
		||||
	"node regex to find",
 | 
			
		||||
	"node regex to skip",
 | 
			
		||||
	"options regex to find",
 | 
			
		||||
	"options regex to skip",
 | 
			
		||||
	"point regex to find",
 | 
			
		||||
	"point regex to skip",
 | 
			
		||||
	"print options",
 | 
			
		||||
	"print fstype",
 | 
			
		||||
	"print node",
 | 
			
		||||
	"is it a network device",
 | 
			
		||||
	"is it not a network device",
 | 
			
		||||
	longopts_help_COMMON
 | 
			
		||||
};
 | 
			
		||||
const char *usagestring = NULL;
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
	mount_from,
 | 
			
		||||
@@ -334,45 +369,7 @@ get_regex(const char *string)
 | 
			
		||||
	return reg;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#include "_usage.h"
 | 
			
		||||
#define extraopts "[mount1] [mount2] ..."
 | 
			
		||||
#define getoptstring "f:F:n:N:o:O:p:P:iste:E:" getoptstring_COMMON
 | 
			
		||||
static const struct option longopts[] = {
 | 
			
		||||
	{ "fstype-regex",        1, NULL, 'f'},
 | 
			
		||||
	{ "skip-fstype-regex",   1, NULL, 'F'},
 | 
			
		||||
	{ "node-regex",          1, NULL, 'n'},
 | 
			
		||||
	{ "skip-node-regex",     1, NULL, 'N'},
 | 
			
		||||
	{ "options-regex",       1, NULL, 'o'},
 | 
			
		||||
	{ "skip-options-regex",  1, NULL, 'O'},
 | 
			
		||||
	{ "point-regex",         1, NULL, 'p'},
 | 
			
		||||
	{ "skip-point-regex",    1, NULL, 'P'},
 | 
			
		||||
	{ "options",             0, NULL, 'i'},
 | 
			
		||||
	{ "fstype",              0, NULL, 's'},
 | 
			
		||||
	{ "node",                0, NULL, 't'},
 | 
			
		||||
	{ "netdev",              0, NULL, 'e'},
 | 
			
		||||
	{ "nonetdev",            0, NULL, 'E'},
 | 
			
		||||
	longopts_COMMON
 | 
			
		||||
};
 | 
			
		||||
static const char * const longopts_help[] = {
 | 
			
		||||
	"fstype regex to find",
 | 
			
		||||
	"fstype regex to skip",
 | 
			
		||||
	"node regex to find",
 | 
			
		||||
	"node regex to skip",
 | 
			
		||||
	"options regex to find",
 | 
			
		||||
	"options regex to skip",
 | 
			
		||||
	"point regex to find",
 | 
			
		||||
	"point regex to skip",
 | 
			
		||||
	"print options",
 | 
			
		||||
	"print fstype",
 | 
			
		||||
	"print node",
 | 
			
		||||
	"is it a network device",
 | 
			
		||||
	"is it not a network device",
 | 
			
		||||
	longopts_help_COMMON
 | 
			
		||||
};
 | 
			
		||||
#include "_usage.c"
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
mountinfo(int argc, char **argv)
 | 
			
		||||
int main(int argc, char **argv)
 | 
			
		||||
{
 | 
			
		||||
	struct args args;
 | 
			
		||||
	regex_t *point_regex = NULL;
 | 
			
		||||
@@ -390,6 +387,7 @@ mountinfo(int argc, char **argv)
 | 
			
		||||
#define REG_FREE(_var)							      \
 | 
			
		||||
	if (_var) { regfree(_var); free(_var); }
 | 
			
		||||
 | 
			
		||||
	applet = basename_c(argv[0]);
 | 
			
		||||
	memset (&args, 0, sizeof(args));
 | 
			
		||||
	args.mount_type = mount_to;
 | 
			
		||||
	args.netdev = net_ignore;
 | 
			
		||||
 
 | 
			
		||||
@@ -47,13 +47,13 @@
 | 
			
		||||
#  include <libutil.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "builtins.h"
 | 
			
		||||
#include "einfo.h"
 | 
			
		||||
#include "queue.h"
 | 
			
		||||
#include "rc.h"
 | 
			
		||||
#include "rc-misc.h"
 | 
			
		||||
#include "rc-plugin.h"
 | 
			
		||||
#include "rc-selinux.h"
 | 
			
		||||
#include "_usage.h"
 | 
			
		||||
 | 
			
		||||
#define PREFIX_LOCK	RC_SVCDIR "/prefix.lock"
 | 
			
		||||
 | 
			
		||||
@@ -61,7 +61,29 @@
 | 
			
		||||
#define WAIT_TIMEOUT	60		/* seconds until we timeout */
 | 
			
		||||
#define WARN_TIMEOUT	10		/* warn about this every N seconds */
 | 
			
		||||
 | 
			
		||||
static const char *applet;
 | 
			
		||||
const char *applet = NULL;
 | 
			
		||||
const char *extraopts = "stop | start | restart | describe | zap";
 | 
			
		||||
const char *getoptstring = "dDsSvl:Z" getoptstring_COMMON;
 | 
			
		||||
const struct option longopts[] = {
 | 
			
		||||
	{ "debug",      0, NULL, 'd'},
 | 
			
		||||
	{ "dry-run",    0, NULL, 'Z'},
 | 
			
		||||
	{ "ifstarted",  0, NULL, 's'},
 | 
			
		||||
	{ "ifstopped",  0, NULL, 'S'},
 | 
			
		||||
	{ "nodeps",     0, NULL, 'D'},
 | 
			
		||||
	{ "lockfd",     1, NULL, 'l'},
 | 
			
		||||
	longopts_COMMON
 | 
			
		||||
};
 | 
			
		||||
const char *const longopts_help[] = {
 | 
			
		||||
	"set xtrace when running the script",
 | 
			
		||||
	"show what would be done",
 | 
			
		||||
	"only run commands when started",
 | 
			
		||||
	"only run commands when stopped",
 | 
			
		||||
	"ignore dependencies",
 | 
			
		||||
	"fd of the exclusive lock from rc",
 | 
			
		||||
	longopts_help_COMMON
 | 
			
		||||
};
 | 
			
		||||
const char *usagestring = NULL;
 | 
			
		||||
 | 
			
		||||
static char *service, *runlevel, *ibsave, *prefix;
 | 
			
		||||
static RC_DEPTREE *deptree;
 | 
			
		||||
static RC_STRINGLIST *applet_list, *services, *tmplist;
 | 
			
		||||
@@ -1063,31 +1085,7 @@ service_plugable(void)
 | 
			
		||||
	return allow;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#include "_usage.h"
 | 
			
		||||
#define getoptstring "dDsSvl:Z" getoptstring_COMMON
 | 
			
		||||
#define extraopts "stop | start | restart | describe | zap"
 | 
			
		||||
static const struct option longopts[] = {
 | 
			
		||||
	{ "debug",      0, NULL, 'd'},
 | 
			
		||||
	{ "dry-run",    0, NULL, 'Z'},
 | 
			
		||||
	{ "ifstarted",  0, NULL, 's'},
 | 
			
		||||
	{ "ifstopped",  0, NULL, 'S'},
 | 
			
		||||
	{ "nodeps",     0, NULL, 'D'},
 | 
			
		||||
	{ "lockfd",     1, NULL, 'l'},
 | 
			
		||||
	longopts_COMMON
 | 
			
		||||
};
 | 
			
		||||
static const char *const longopts_help[] = {
 | 
			
		||||
	"set xtrace when running the script",
 | 
			
		||||
	"show what would be done",
 | 
			
		||||
	"only run commands when started",
 | 
			
		||||
	"only run commands when stopped",
 | 
			
		||||
	"ignore dependencies",
 | 
			
		||||
	"fd of the exclusive lock from rc",
 | 
			
		||||
	longopts_help_COMMON
 | 
			
		||||
};
 | 
			
		||||
#include "_usage.c"
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
openrc_run(int argc, char **argv)
 | 
			
		||||
int main(int argc, char **argv)
 | 
			
		||||
{
 | 
			
		||||
	bool doneone = false;
 | 
			
		||||
	int retval, opt, depoptions = RC_DEP_TRACE;
 | 
			
		||||
@@ -1396,10 +1394,3 @@ openrc_run(int argc, char **argv)
 | 
			
		||||
 | 
			
		||||
	return retval;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
runscript(int argc, char **argv)
 | 
			
		||||
{
 | 
			
		||||
	ewarnv("runscript is deprecated; please use openrc-run instead.");
 | 
			
		||||
	return (openrc_run(argc, argv));
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										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 <utime.h>
 | 
			
		||||
 | 
			
		||||
#include "builtins.h"
 | 
			
		||||
#include "einfo.h"
 | 
			
		||||
#include "queue.h"
 | 
			
		||||
#include "rc.h"
 | 
			
		||||
#include "rc-misc.h"
 | 
			
		||||
 | 
			
		||||
extern const char *applet;
 | 
			
		||||
 | 
			
		||||
RC_DEPTREE *
 | 
			
		||||
_rc_deptree_load(int force, int *regen) {
 | 
			
		||||
	int fd;
 | 
			
		||||
	int retval;
 | 
			
		||||
	int serrno = errno;
 | 
			
		||||
	int merrno;
 | 
			
		||||
	time_t t;
 | 
			
		||||
	char file[PATH_MAX];
 | 
			
		||||
	struct stat st;
 | 
			
		||||
	struct utimbuf ut;
 | 
			
		||||
	FILE *fp;
 | 
			
		||||
 | 
			
		||||
	t = 0;
 | 
			
		||||
	if (rc_deptree_update_needed(&t, file) || force != 0) {
 | 
			
		||||
		/* Test if we have permission to update the deptree */
 | 
			
		||||
		fd = open(RC_DEPTREE_CACHE, O_WRONLY);
 | 
			
		||||
		merrno = errno;
 | 
			
		||||
		errno = serrno;
 | 
			
		||||
		if (fd == -1 && merrno == EACCES)
 | 
			
		||||
			return rc_deptree_load();
 | 
			
		||||
		close(fd);
 | 
			
		||||
 | 
			
		||||
		if (regen)
 | 
			
		||||
			*regen = 1;
 | 
			
		||||
		ebegin("Caching service dependencies");
 | 
			
		||||
		retval = rc_deptree_update() ? 0 : -1;
 | 
			
		||||
		eend (retval, "Failed to update the dependency tree");
 | 
			
		||||
 | 
			
		||||
		if (retval == 0) {
 | 
			
		||||
			stat(RC_DEPTREE_CACHE, &st);
 | 
			
		||||
			if (st.st_mtime < t) {
 | 
			
		||||
				eerror("Clock skew detected with `%s'", file);
 | 
			
		||||
				eerrorn("Adjusting mtime of `" RC_DEPTREE_CACHE
 | 
			
		||||
				    "' to %s", ctime(&t));
 | 
			
		||||
				fp = fopen(RC_DEPTREE_SKEWED, "w");
 | 
			
		||||
				if (fp != NULL) {
 | 
			
		||||
					fprintf(fp, "%s\n", file);
 | 
			
		||||
					fclose(fp);
 | 
			
		||||
				}
 | 
			
		||||
				ut.actime = t;
 | 
			
		||||
				ut.modtime = t;
 | 
			
		||||
				utime(RC_DEPTREE_CACHE, &ut);
 | 
			
		||||
			} else {
 | 
			
		||||
				if (exists(RC_DEPTREE_SKEWED))
 | 
			
		||||
					unlink(RC_DEPTREE_SKEWED);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if (force == -1 && regen != NULL)
 | 
			
		||||
			*regen = retval;
 | 
			
		||||
	}
 | 
			
		||||
	return rc_deptree_load();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#include "_usage.h"
 | 
			
		||||
#define getoptstring "aot:suTF:" getoptstring_COMMON
 | 
			
		||||
static const struct option longopts[] = {
 | 
			
		||||
 | 
			
		||||
const char *applet = NULL;
 | 
			
		||||
const char *extraopts = NULL;
 | 
			
		||||
const char *getoptstring = "aot:suTF:" getoptstring_COMMON;
 | 
			
		||||
const struct option longopts[] = {
 | 
			
		||||
	{ "starting", 0, NULL, 'a'},
 | 
			
		||||
	{ "stopping", 0, NULL, 'o'},
 | 
			
		||||
	{ "type",     1, NULL, 't'},
 | 
			
		||||
@@ -104,7 +50,7 @@ static const struct option longopts[] = {
 | 
			
		||||
	{ "deptree-file", 1, NULL, 'F'},
 | 
			
		||||
	longopts_COMMON
 | 
			
		||||
};
 | 
			
		||||
static const char * const longopts_help[] = {
 | 
			
		||||
const char * const longopts_help[] = {
 | 
			
		||||
	"Order services as if runlevel is starting",
 | 
			
		||||
	"Order services as if runlevel is stopping",
 | 
			
		||||
	"Type(s) of dependency to list",
 | 
			
		||||
@@ -114,10 +60,9 @@ static const char * const longopts_help[] = {
 | 
			
		||||
	"File to load cached deptree from",
 | 
			
		||||
	longopts_help_COMMON
 | 
			
		||||
};
 | 
			
		||||
#include "_usage.c"
 | 
			
		||||
const char *usagestring = NULL;
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
rc_depend(int argc, char **argv)
 | 
			
		||||
int main(int argc, char **argv)
 | 
			
		||||
{
 | 
			
		||||
	RC_STRINGLIST *list;
 | 
			
		||||
	RC_STRINGLIST *types;
 | 
			
		||||
@@ -132,6 +77,7 @@ rc_depend(int argc, char **argv)
 | 
			
		||||
	char *token;
 | 
			
		||||
	char *deptree_file = NULL;
 | 
			
		||||
 | 
			
		||||
	applet = basename_c(argv[0]);
 | 
			
		||||
	types = rc_stringlist_new();
 | 
			
		||||
	while ((opt = getopt_long(argc, argv, getoptstring,
 | 
			
		||||
		    longopts, (int *) 0)) != -1)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										107
									
								
								src/rc/rc-misc.c
									
									
									
									
									
								
							
							
						
						
									
										107
									
								
								src/rc/rc-misc.c
									
									
									
									
									
								
							@@ -23,6 +23,7 @@
 | 
			
		||||
#  include <sys/sysinfo.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <sys/time.h>
 | 
			
		||||
#include <ctype.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <limits.h>
 | 
			
		||||
@@ -31,7 +32,9 @@
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <time.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <utime.h>
 | 
			
		||||
 | 
			
		||||
#include "einfo.h"
 | 
			
		||||
#include "queue.h"
 | 
			
		||||
@@ -488,3 +491,107 @@ const char *detect_vm(void)
 | 
			
		||||
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RC_DEPTREE * _rc_deptree_load(int force, int *regen)
 | 
			
		||||
{
 | 
			
		||||
	int fd;
 | 
			
		||||
	int retval;
 | 
			
		||||
	int serrno = errno;
 | 
			
		||||
	int merrno;
 | 
			
		||||
	time_t t;
 | 
			
		||||
	char file[PATH_MAX];
 | 
			
		||||
	struct stat st;
 | 
			
		||||
	struct utimbuf ut;
 | 
			
		||||
	FILE *fp;
 | 
			
		||||
 | 
			
		||||
	t = 0;
 | 
			
		||||
	if (rc_deptree_update_needed(&t, file) || force != 0) {
 | 
			
		||||
		/* Test if we have permission to update the deptree */
 | 
			
		||||
		fd = open(RC_DEPTREE_CACHE, O_WRONLY);
 | 
			
		||||
		merrno = errno;
 | 
			
		||||
		errno = serrno;
 | 
			
		||||
		if (fd == -1 && merrno == EACCES)
 | 
			
		||||
			return rc_deptree_load();
 | 
			
		||||
		close(fd);
 | 
			
		||||
 | 
			
		||||
		if (regen)
 | 
			
		||||
			*regen = 1;
 | 
			
		||||
		ebegin("Caching service dependencies");
 | 
			
		||||
		retval = rc_deptree_update() ? 0 : -1;
 | 
			
		||||
		eend (retval, "Failed to update the dependency tree");
 | 
			
		||||
 | 
			
		||||
		if (retval == 0) {
 | 
			
		||||
			stat(RC_DEPTREE_CACHE, &st);
 | 
			
		||||
			if (st.st_mtime < t) {
 | 
			
		||||
				eerror("Clock skew detected with `%s'", file);
 | 
			
		||||
				eerrorn("Adjusting mtime of `" RC_DEPTREE_CACHE
 | 
			
		||||
				    "' to %s", ctime(&t));
 | 
			
		||||
				fp = fopen(RC_DEPTREE_SKEWED, "w");
 | 
			
		||||
				if (fp != NULL) {
 | 
			
		||||
					fprintf(fp, "%s\n", file);
 | 
			
		||||
					fclose(fp);
 | 
			
		||||
				}
 | 
			
		||||
				ut.actime = t;
 | 
			
		||||
				ut.modtime = t;
 | 
			
		||||
				utime(RC_DEPTREE_CACHE, &ut);
 | 
			
		||||
			} else {
 | 
			
		||||
				if (exists(RC_DEPTREE_SKEWED))
 | 
			
		||||
					unlink(RC_DEPTREE_SKEWED);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if (force == -1 && regen != NULL)
 | 
			
		||||
			*regen = retval;
 | 
			
		||||
	}
 | 
			
		||||
	return rc_deptree_load();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool _rc_can_find_pids(void)
 | 
			
		||||
{
 | 
			
		||||
	RC_PIDLIST *pids;
 | 
			
		||||
	RC_PID *pid;
 | 
			
		||||
	RC_PID *pid2;
 | 
			
		||||
	bool retval = false;
 | 
			
		||||
 | 
			
		||||
	if (geteuid() == 0)
 | 
			
		||||
		return true;
 | 
			
		||||
 | 
			
		||||
	/* If we cannot see process 1, then we don't test to see if
 | 
			
		||||
	 * services crashed or not */
 | 
			
		||||
	pids = rc_find_pids(NULL, NULL, 0, 1);
 | 
			
		||||
	if (pids) {
 | 
			
		||||
		pid = LIST_FIRST(pids);
 | 
			
		||||
		if (pid) {
 | 
			
		||||
			retval = true;
 | 
			
		||||
			while (pid) {
 | 
			
		||||
				pid2 = LIST_NEXT(pid, entries);
 | 
			
		||||
				free(pid);
 | 
			
		||||
				pid = pid2;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		free(pids);
 | 
			
		||||
	}
 | 
			
		||||
	return retval;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct {
 | 
			
		||||
	const char * const name;
 | 
			
		||||
	RC_SERVICE bit;
 | 
			
		||||
} service_bits[] = {
 | 
			
		||||
	{ "service_started",     RC_SERVICE_STARTED,     },
 | 
			
		||||
	{ "service_stopped",     RC_SERVICE_STOPPED,     },
 | 
			
		||||
	{ "service_inactive",    RC_SERVICE_INACTIVE,    },
 | 
			
		||||
	{ "service_starting",    RC_SERVICE_STARTING,    },
 | 
			
		||||
	{ "service_stopping",    RC_SERVICE_STOPPING,    },
 | 
			
		||||
	{ "service_hotplugged",  RC_SERVICE_HOTPLUGGED,  },
 | 
			
		||||
	{ "service_wasinactive", RC_SERVICE_WASINACTIVE, },
 | 
			
		||||
	{ "service_failed",      RC_SERVICE_FAILED,      },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
RC_SERVICE lookup_service_state(const char *service)
 | 
			
		||||
{
 | 
			
		||||
	size_t i;
 | 
			
		||||
	for (i = 0; i < ARRAY_SIZE(service_bits); ++i)
 | 
			
		||||
		if (!strcmp(service, service_bits[i].name))
 | 
			
		||||
			return service_bits[i].bit;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -15,6 +15,8 @@
 | 
			
		||||
 *    except according to the terms contained in the LICENSE file.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_SELINUX
 | 
			
		||||
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <dlfcn.h>
 | 
			
		||||
@@ -384,3 +386,5 @@ out:
 | 
			
		||||
	free(run_init_t);
 | 
			
		||||
	free(curr_t);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -21,39 +21,36 @@
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
 | 
			
		||||
#include "builtins.h"
 | 
			
		||||
#include "einfo.h"
 | 
			
		||||
#include "queue.h"
 | 
			
		||||
#include "rc.h"
 | 
			
		||||
#include "rc-misc.h"
 | 
			
		||||
 | 
			
		||||
extern char *applet;
 | 
			
		||||
 | 
			
		||||
#include "_usage.h"
 | 
			
		||||
#define usagestring ""							\
 | 
			
		||||
	"Usage: rc-service [options] [-i] <service> <cmd>...\n"		\
 | 
			
		||||
	"   or: rc-service [options] -e <service>\n"			\
 | 
			
		||||
	"   or: rc-service [options] -l\n"				\
 | 
			
		||||
	"   or: rc-service [options] -r <service>"
 | 
			
		||||
#define getoptstring "e:ilr:" getoptstring_COMMON
 | 
			
		||||
static const struct option longopts[] = {
 | 
			
		||||
 | 
			
		||||
const char *applet = NULL;
 | 
			
		||||
const char *extraopts = NULL;
 | 
			
		||||
const char *getoptstring = "e:ilr:" getoptstring_COMMON;
 | 
			
		||||
const struct option longopts[] = {
 | 
			
		||||
	{ "exists",   1, NULL, 'e' },
 | 
			
		||||
	{ "ifexists", 0, NULL, 'i' },
 | 
			
		||||
	{ "list",     0, NULL, 'l' },
 | 
			
		||||
	{ "resolve",  1, NULL, 'r' },
 | 
			
		||||
	longopts_COMMON
 | 
			
		||||
};
 | 
			
		||||
static const char * const longopts_help[] = {
 | 
			
		||||
const char * const longopts_help[] = {
 | 
			
		||||
	"tests if the service exists or not",
 | 
			
		||||
	"if the service exists then run the command",
 | 
			
		||||
	"list all available services",
 | 
			
		||||
	"resolve the service name to an init script",
 | 
			
		||||
	longopts_help_COMMON
 | 
			
		||||
};
 | 
			
		||||
#include "_usage.c"
 | 
			
		||||
const char *usagestring = ""							\
 | 
			
		||||
	"Usage: rc-service [options] [-i] <service> <cmd>...\n"		\
 | 
			
		||||
	"   or: rc-service [options] -e <service>\n"			\
 | 
			
		||||
	"   or: rc-service [options] -l\n"				\
 | 
			
		||||
	"   or: rc-service [options] -r <service>";
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
rc_service(int argc, char **argv)
 | 
			
		||||
int main(int argc, char **argv)
 | 
			
		||||
{
 | 
			
		||||
	int opt;
 | 
			
		||||
	char *service;
 | 
			
		||||
@@ -61,6 +58,7 @@ rc_service(int argc, char **argv)
 | 
			
		||||
	RC_STRING *s;
 | 
			
		||||
	bool if_exists = false;
 | 
			
		||||
 | 
			
		||||
	applet = basename_c(argv[0]);
 | 
			
		||||
	/* Ensure that we are only quiet when explicitly told to be */
 | 
			
		||||
	unsetenv("EINFO_QUIET");
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -21,13 +21,37 @@
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
 | 
			
		||||
#include "builtins.h"
 | 
			
		||||
#include "einfo.h"
 | 
			
		||||
#include "queue.h"
 | 
			
		||||
#include "rc.h"
 | 
			
		||||
#include "rc-misc.h"
 | 
			
		||||
#include "_usage.h"
 | 
			
		||||
 | 
			
		||||
const char *applet = NULL;
 | 
			
		||||
const char *extraopts = NULL;
 | 
			
		||||
const char *getoptstring = "aclrsu" getoptstring_COMMON;
 | 
			
		||||
const struct option longopts[] = {
 | 
			
		||||
	{"all",         0, NULL, 'a'},
 | 
			
		||||
	{"crashed",     0, NULL, 'c'},
 | 
			
		||||
	{"list",        0, NULL, 'l'},
 | 
			
		||||
	{"runlevel",    0, NULL, 'r'},
 | 
			
		||||
	{"servicelist", 0, NULL, 's'},
 | 
			
		||||
	{"unused",      0, NULL, 'u'},
 | 
			
		||||
	longopts_COMMON
 | 
			
		||||
};
 | 
			
		||||
const char * const longopts_help[] = {
 | 
			
		||||
	"Show services from all run levels",
 | 
			
		||||
	"Show crashed services",
 | 
			
		||||
	"Show list of run levels",
 | 
			
		||||
	"Show the name of the current runlevel",
 | 
			
		||||
	"Show service list",
 | 
			
		||||
	"Show services not assigned to any runlevel",
 | 
			
		||||
	longopts_help_COMMON
 | 
			
		||||
};
 | 
			
		||||
const char *usagestring = ""						\
 | 
			
		||||
	"Usage: rc-status [options] <runlevel>...\n"		\
 | 
			
		||||
	"   or: rc-status [options] [-a | -c | -l | -r | -s | -u]";
 | 
			
		||||
 | 
			
		||||
extern const char *applet;
 | 
			
		||||
static bool test_crashed = false;
 | 
			
		||||
static RC_DEPTREE *deptree;
 | 
			
		||||
static RC_STRINGLIST *types;
 | 
			
		||||
@@ -35,35 +59,6 @@ static RC_STRINGLIST *types;
 | 
			
		||||
static RC_STRINGLIST *levels, *services, *tmp, *alist;
 | 
			
		||||
static RC_STRINGLIST *sservices, *nservices, *needsme;
 | 
			
		||||
 | 
			
		||||
bool
 | 
			
		||||
_rc_can_find_pids(void)
 | 
			
		||||
{
 | 
			
		||||
	RC_PIDLIST *pids;
 | 
			
		||||
	RC_PID *pid;
 | 
			
		||||
	RC_PID *pid2;
 | 
			
		||||
	bool retval = false;
 | 
			
		||||
 | 
			
		||||
	if (geteuid() == 0)
 | 
			
		||||
		return true;
 | 
			
		||||
 | 
			
		||||
	/* If we cannot see process 1, then we don't test to see if
 | 
			
		||||
	 * services crashed or not */
 | 
			
		||||
	pids = rc_find_pids(NULL, NULL, 0, 1);
 | 
			
		||||
	if (pids) {
 | 
			
		||||
		pid = LIST_FIRST(pids);
 | 
			
		||||
		if (pid) {
 | 
			
		||||
			retval = true;
 | 
			
		||||
			while (pid) {
 | 
			
		||||
				pid2 = LIST_NEXT(pid, entries);
 | 
			
		||||
				free(pid);
 | 
			
		||||
				pid = pid2;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		free(pids);
 | 
			
		||||
	}
 | 
			
		||||
	return retval;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
print_level(const char *prefix, const char *level)
 | 
			
		||||
{
 | 
			
		||||
@@ -178,33 +173,7 @@ print_stacked_services(const char *runlevel)
 | 
			
		||||
	stackedlevels = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#include "_usage.h"
 | 
			
		||||
#define usagestring ""						\
 | 
			
		||||
	"Usage: rc-status [options] <runlevel>...\n"		\
 | 
			
		||||
	"   or: rc-status [options] [-a | -c | -l | -r | -s | -u]"
 | 
			
		||||
#define getoptstring "aclrsu" getoptstring_COMMON
 | 
			
		||||
static const struct option longopts[] = {
 | 
			
		||||
	{"all",         0, NULL, 'a'},
 | 
			
		||||
	{"crashed",     0, NULL, 'c'},
 | 
			
		||||
	{"list",        0, NULL, 'l'},
 | 
			
		||||
	{"runlevel",    0, NULL, 'r'},
 | 
			
		||||
	{"servicelist", 0, NULL, 's'},
 | 
			
		||||
	{"unused",      0, NULL, 'u'},
 | 
			
		||||
	longopts_COMMON
 | 
			
		||||
};
 | 
			
		||||
static const char * const longopts_help[] = {
 | 
			
		||||
	"Show services from all run levels",
 | 
			
		||||
	"Show crashed services",
 | 
			
		||||
	"Show list of run levels",
 | 
			
		||||
	"Show the name of the current runlevel",
 | 
			
		||||
	"Show service list",
 | 
			
		||||
	"Show services not assigned to any runlevel",
 | 
			
		||||
	longopts_help_COMMON
 | 
			
		||||
};
 | 
			
		||||
#include "_usage.c"
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
rc_status(int argc, char **argv)
 | 
			
		||||
int main(int argc, char **argv)
 | 
			
		||||
{
 | 
			
		||||
    RC_STRING *s, *l, *t, *level;
 | 
			
		||||
 | 
			
		||||
@@ -213,6 +182,7 @@ rc_status(int argc, char **argv)
 | 
			
		||||
 | 
			
		||||
	test_crashed = _rc_can_find_pids();
 | 
			
		||||
 | 
			
		||||
	applet = basename_c(argv[0]);
 | 
			
		||||
	while ((opt = getopt_long(argc, argv, getoptstring, longopts,
 | 
			
		||||
				  (int *) 0)) != -1)
 | 
			
		||||
		switch (opt) {
 | 
			
		||||
 
 | 
			
		||||
@@ -24,13 +24,31 @@
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
 | 
			
		||||
#include "builtins.h"
 | 
			
		||||
#include "einfo.h"
 | 
			
		||||
#include "queue.h"
 | 
			
		||||
#include "rc.h"
 | 
			
		||||
#include "rc-misc.h"
 | 
			
		||||
#include "_usage.h"
 | 
			
		||||
 | 
			
		||||
extern const char *applet;
 | 
			
		||||
const char *applet = NULL;
 | 
			
		||||
const char *extraopts = NULL;
 | 
			
		||||
const char *usagestring = ""							\
 | 
			
		||||
	"Usage: rc-update [options] add <service> [<runlevel>...]\n"	\
 | 
			
		||||
	"   or: rc-update [options] del <service> [<runlevel>...]\n"	\
 | 
			
		||||
	"   or: rc-update [options] [show [<runlevel>...]]";
 | 
			
		||||
const char *getoptstring = "asu" getoptstring_COMMON;
 | 
			
		||||
const struct option longopts[] = {
 | 
			
		||||
	{ "all",             0, NULL, 'a' },
 | 
			
		||||
	{ "stack",           0, NULL, 's' },
 | 
			
		||||
	{ "update",          0, NULL, 'u' },
 | 
			
		||||
	longopts_COMMON
 | 
			
		||||
};
 | 
			
		||||
const char * const longopts_help[] = {
 | 
			
		||||
	"Process all runlevels",
 | 
			
		||||
	"Stack a runlevel instead of a service",
 | 
			
		||||
	"Force an update of the dependency tree",
 | 
			
		||||
	longopts_help_COMMON
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Return the number of changes made:
 | 
			
		||||
 *  -1 = no changes (error)
 | 
			
		||||
@@ -182,32 +200,11 @@ show(RC_STRINGLIST *runlevels, bool verbose)
 | 
			
		||||
	rc_stringlist_free (services);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#include "_usage.h"
 | 
			
		||||
#define usagestring ""							\
 | 
			
		||||
	"Usage: rc-update [options] add <service> [<runlevel>...]\n"	\
 | 
			
		||||
	"   or: rc-update [options] del <service> [<runlevel>...]\n"	\
 | 
			
		||||
	"   or: rc-update [options] [show [<runlevel>...]]"
 | 
			
		||||
#define getoptstring "asu" getoptstring_COMMON
 | 
			
		||||
static const struct option longopts[] = {
 | 
			
		||||
	{ "all",             0, NULL, 'a' },
 | 
			
		||||
	{ "stack",           0, NULL, 's' },
 | 
			
		||||
	{ "update",          0, NULL, 'u' },
 | 
			
		||||
	longopts_COMMON
 | 
			
		||||
};
 | 
			
		||||
static const char * const longopts_help[] = {
 | 
			
		||||
	"Process all runlevels",
 | 
			
		||||
	"Stack a runlevel instead of a service",
 | 
			
		||||
	"Force an update of the dependency tree",
 | 
			
		||||
	longopts_help_COMMON
 | 
			
		||||
};
 | 
			
		||||
#include "_usage.c"
 | 
			
		||||
 | 
			
		||||
#define DOADD    (1 << 1)
 | 
			
		||||
#define DODELETE (1 << 2)
 | 
			
		||||
#define DOSHOW   (1 << 3)
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
rc_update(int argc, char **argv)
 | 
			
		||||
int main(int argc, char **argv)
 | 
			
		||||
{
 | 
			
		||||
	RC_DEPTREE *deptree;
 | 
			
		||||
	RC_STRINGLIST *runlevels;
 | 
			
		||||
@@ -222,6 +219,7 @@ rc_update(int argc, char **argv)
 | 
			
		||||
	int (*actfunc)(const char *, const char *);
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	applet = basename_c(argv[0]);
 | 
			
		||||
	while ((opt = getopt_long(argc, argv, getoptstring,
 | 
			
		||||
		    longopts, (int *)0)) != -1)
 | 
			
		||||
		switch (opt) {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										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 <unistd.h>
 | 
			
		||||
 | 
			
		||||
#include "builtins.h"
 | 
			
		||||
#include "einfo.h"
 | 
			
		||||
#include "queue.h"
 | 
			
		||||
#include "rc.h"
 | 
			
		||||
@@ -54,6 +53,27 @@ const char rc_copyright[] = "Copyright (c) 2007-2008 Roy Marples";
 | 
			
		||||
#include "rc-plugin.h"
 | 
			
		||||
 | 
			
		||||
#include "version.h"
 | 
			
		||||
#include "_usage.h"
 | 
			
		||||
 | 
			
		||||
const char *extraopts = NULL;
 | 
			
		||||
const char *getoptstring = "a:no:s:S" getoptstring_COMMON;
 | 
			
		||||
const struct option longopts[] = {
 | 
			
		||||
	{ "no-stop", 0, NULL, 'n' },
 | 
			
		||||
	{ "override",    1, NULL, 'o' },
 | 
			
		||||
	{ "service",     1, NULL, 's' },
 | 
			
		||||
	{ "sys",         0, NULL, 'S' },
 | 
			
		||||
	longopts_COMMON
 | 
			
		||||
};
 | 
			
		||||
const char * const longopts_help[] = {
 | 
			
		||||
	"do not stop any services",
 | 
			
		||||
	"override the next runlevel to change into\n"
 | 
			
		||||
	"when leaving single user or boot runlevels",
 | 
			
		||||
	"runs the service specified with the rest\nof the arguments",
 | 
			
		||||
	"output the RC system type, if any",
 | 
			
		||||
	longopts_help_COMMON
 | 
			
		||||
};
 | 
			
		||||
const char *usagestring = ""					\
 | 
			
		||||
    "Usage: openrc [options] [<runlevel>]";
 | 
			
		||||
 | 
			
		||||
#define INITSH                  RC_LIBEXECDIR "/sh/init.sh"
 | 
			
		||||
#define INITEARLYSH             RC_LIBEXECDIR "/sh/init-early.sh"
 | 
			
		||||
@@ -721,31 +741,7 @@ handle_bad_signal(int sig)
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "_usage.h"
 | 
			
		||||
#define usagestring ""					\
 | 
			
		||||
    "Usage: openrc [options] [<runlevel>]"
 | 
			
		||||
#define getoptstring "a:no:s:S" getoptstring_COMMON
 | 
			
		||||
static const struct option longopts[] = {
 | 
			
		||||
	{ "applet",   1, NULL, 'a' },
 | 
			
		||||
	{ "no-stop", 0, NULL, 'n' },
 | 
			
		||||
	{ "override",    1, NULL, 'o' },
 | 
			
		||||
	{ "service",     1, NULL, 's' },
 | 
			
		||||
	{ "sys",         0, NULL, 'S' },
 | 
			
		||||
	longopts_COMMON
 | 
			
		||||
};
 | 
			
		||||
static const char * const longopts_help[] = {
 | 
			
		||||
	"runs the applet specified by the next argument",
 | 
			
		||||
	"do not stop any services",
 | 
			
		||||
	"override the next runlevel to change into\n"
 | 
			
		||||
	"when leaving single user or boot runlevels",
 | 
			
		||||
	"runs the service specified with the rest\nof the arguments",
 | 
			
		||||
	"output the RC system type, if any",
 | 
			
		||||
	longopts_help_COMMON
 | 
			
		||||
};
 | 
			
		||||
#include "_usage.c"
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
main(int argc, char **argv)
 | 
			
		||||
int main(int argc, char **argv)
 | 
			
		||||
{
 | 
			
		||||
	const char *bootlevel = NULL;
 | 
			
		||||
	char *newlevel = NULL;
 | 
			
		||||
@@ -785,9 +781,6 @@ main(int argc, char **argv)
 | 
			
		||||
	if (!applet)
 | 
			
		||||
		eerrorx("arguments required");
 | 
			
		||||
 | 
			
		||||
	/* Run our built in applets. If we ran one, we don't return. */
 | 
			
		||||
	run_applets(argc, argv);
 | 
			
		||||
 | 
			
		||||
	argc--;
 | 
			
		||||
	argv++;
 | 
			
		||||
 | 
			
		||||
@@ -813,10 +806,6 @@ main(int argc, char **argv)
 | 
			
		||||
		    longopts, (int *) 0)) != -1)
 | 
			
		||||
	{
 | 
			
		||||
		switch (opt) {
 | 
			
		||||
		case 'a':
 | 
			
		||||
			/* Do nothing, actual logic in run_applets, this
 | 
			
		||||
			 * is a placeholder */
 | 
			
		||||
			break;
 | 
			
		||||
		case 'n':
 | 
			
		||||
			nostop = true;
 | 
			
		||||
			break;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										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};
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "builtins.h"
 | 
			
		||||
#include "einfo.h"
 | 
			
		||||
#include "queue.h"
 | 
			
		||||
#include "rc.h"
 | 
			
		||||
#include "rc-misc.h"
 | 
			
		||||
#include "_usage.h"
 | 
			
		||||
 | 
			
		||||
const char *applet = NULL;
 | 
			
		||||
const char *extraopts = NULL;
 | 
			
		||||
const char *getoptstring = "I:KN:PR:Sa:bc:d:e:g:ik:mn:op:s:tu:r:w:x:1:2:" \
 | 
			
		||||
	getoptstring_COMMON;
 | 
			
		||||
const struct option longopts[] = {
 | 
			
		||||
	{ "ionice",       1, NULL, 'I'},
 | 
			
		||||
	{ "stop",         0, NULL, 'K'},
 | 
			
		||||
	{ "nicelevel",    1, NULL, 'N'},
 | 
			
		||||
	{ "retry",        1, NULL, 'R'},
 | 
			
		||||
	{ "start",        0, NULL, 'S'},
 | 
			
		||||
	{ "startas",      1, NULL, 'a'},
 | 
			
		||||
	{ "background",   0, NULL, 'b'},
 | 
			
		||||
	{ "chuid",        1, NULL, 'c'},
 | 
			
		||||
	{ "chdir",        1, NULL, 'd'},
 | 
			
		||||
	{ "env",          1, NULL, 'e'},
 | 
			
		||||
	{ "umask",        1, NULL, 'k'},
 | 
			
		||||
	{ "group",        1, NULL, 'g'},
 | 
			
		||||
	{ "interpreted",  0, NULL, 'i'},
 | 
			
		||||
	{ "make-pidfile", 0, NULL, 'm'},
 | 
			
		||||
	{ "name",         1, NULL, 'n'},
 | 
			
		||||
	{ "oknodo",       0, NULL, 'o'},
 | 
			
		||||
	{ "pidfile",      1, NULL, 'p'},
 | 
			
		||||
	{ "signal",       1, NULL, 's'},
 | 
			
		||||
	{ "test",         0, NULL, 't'},
 | 
			
		||||
	{ "user",         1, NULL, 'u'},
 | 
			
		||||
	{ "chroot",       1, NULL, 'r'},
 | 
			
		||||
	{ "wait",         1, NULL, 'w'},
 | 
			
		||||
	{ "exec",         1, NULL, 'x'},
 | 
			
		||||
	{ "stdout",       1, NULL, '1'},
 | 
			
		||||
	{ "stderr",       1, NULL, '2'},
 | 
			
		||||
	{ "progress",     0, NULL, 'P'},
 | 
			
		||||
	longopts_COMMON
 | 
			
		||||
};
 | 
			
		||||
const char * const longopts_help[] = {
 | 
			
		||||
	"Set an ionice class:data when starting",
 | 
			
		||||
	"Stop daemon",
 | 
			
		||||
	"Set a nicelevel when starting",
 | 
			
		||||
	"Retry schedule to use when stopping",
 | 
			
		||||
	"Start daemon",
 | 
			
		||||
	"deprecated, use --exec or --name",
 | 
			
		||||
	"Force daemon to background",
 | 
			
		||||
	"deprecated, use --user",
 | 
			
		||||
	"Change the PWD",
 | 
			
		||||
	"Set an environment string",
 | 
			
		||||
	"Set the umask for the daemon",
 | 
			
		||||
	"Change the process group",
 | 
			
		||||
	"Match process name by interpreter",
 | 
			
		||||
	"Create a pidfile",
 | 
			
		||||
	"Match process name",
 | 
			
		||||
	"deprecated",
 | 
			
		||||
	"Match pid found in this file",
 | 
			
		||||
	"Send a different signal",
 | 
			
		||||
	"Test actions, don't do them",
 | 
			
		||||
	"Change the process user",
 | 
			
		||||
	"Chroot to this directory",
 | 
			
		||||
	"Milliseconds to wait for daemon start",
 | 
			
		||||
	"Binary to start/stop",
 | 
			
		||||
	"Redirect stdout to file",
 | 
			
		||||
	"Redirect stderr to file",
 | 
			
		||||
	"Print dots each second while waiting",
 | 
			
		||||
	longopts_help_COMMON
 | 
			
		||||
};
 | 
			
		||||
const char *usagestring = NULL;
 | 
			
		||||
 | 
			
		||||
typedef struct scheduleitem
 | 
			
		||||
{
 | 
			
		||||
@@ -81,7 +145,6 @@ typedef struct scheduleitem
 | 
			
		||||
TAILQ_HEAD(, scheduleitem) schedule;
 | 
			
		||||
static char **nav;
 | 
			
		||||
 | 
			
		||||
extern const char *applet;
 | 
			
		||||
static char *changeuser, *ch_root, *ch_dir;
 | 
			
		||||
 | 
			
		||||
extern char **environ;
 | 
			
		||||
@@ -567,70 +630,7 @@ expand_home(const char *home, const char *path)
 | 
			
		||||
	return nh;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#include "_usage.h"
 | 
			
		||||
#define getoptstring "I:KN:PR:Sa:bc:d:e:g:ik:mn:op:s:tu:r:w:x:1:2:" getoptstring_COMMON
 | 
			
		||||
static const struct option longopts[] = {
 | 
			
		||||
	{ "ionice",       1, NULL, 'I'},
 | 
			
		||||
	{ "stop",         0, NULL, 'K'},
 | 
			
		||||
	{ "nicelevel",    1, NULL, 'N'},
 | 
			
		||||
	{ "retry",        1, NULL, 'R'},
 | 
			
		||||
	{ "start",        0, NULL, 'S'},
 | 
			
		||||
	{ "startas",      1, NULL, 'a'},
 | 
			
		||||
	{ "background",   0, NULL, 'b'},
 | 
			
		||||
	{ "chuid",        1, NULL, 'c'},
 | 
			
		||||
	{ "chdir",        1, NULL, 'd'},
 | 
			
		||||
	{ "env",          1, NULL, 'e'},
 | 
			
		||||
	{ "umask",        1, NULL, 'k'},
 | 
			
		||||
	{ "group",        1, NULL, 'g'},
 | 
			
		||||
	{ "interpreted",  0, NULL, 'i'},
 | 
			
		||||
	{ "make-pidfile", 0, NULL, 'm'},
 | 
			
		||||
	{ "name",         1, NULL, 'n'},
 | 
			
		||||
	{ "oknodo",       0, NULL, 'o'},
 | 
			
		||||
	{ "pidfile",      1, NULL, 'p'},
 | 
			
		||||
	{ "signal",       1, NULL, 's'},
 | 
			
		||||
	{ "test",         0, NULL, 't'},
 | 
			
		||||
	{ "user",         1, NULL, 'u'},
 | 
			
		||||
	{ "chroot",       1, NULL, 'r'},
 | 
			
		||||
	{ "wait",         1, NULL, 'w'},
 | 
			
		||||
	{ "exec",         1, NULL, 'x'},
 | 
			
		||||
	{ "stdout",       1, NULL, '1'},
 | 
			
		||||
	{ "stderr",       1, NULL, '2'},
 | 
			
		||||
	{ "progress",     0, NULL, 'P'},
 | 
			
		||||
	longopts_COMMON
 | 
			
		||||
};
 | 
			
		||||
static const char * const longopts_help[] = {
 | 
			
		||||
	"Set an ionice class:data when starting",
 | 
			
		||||
	"Stop daemon",
 | 
			
		||||
	"Set a nicelevel when starting",
 | 
			
		||||
	"Retry schedule to use when stopping",
 | 
			
		||||
	"Start daemon",
 | 
			
		||||
	"deprecated, use --exec or --name",
 | 
			
		||||
	"Force daemon to background",
 | 
			
		||||
	"deprecated, use --user",
 | 
			
		||||
	"Change the PWD",
 | 
			
		||||
	"Set an environment string",
 | 
			
		||||
	"Set the umask for the daemon",
 | 
			
		||||
	"Change the process group",
 | 
			
		||||
	"Match process name by interpreter",
 | 
			
		||||
	"Create a pidfile",
 | 
			
		||||
	"Match process name",
 | 
			
		||||
	"deprecated",
 | 
			
		||||
	"Match pid found in this file",
 | 
			
		||||
	"Send a different signal",
 | 
			
		||||
	"Test actions, don't do them",
 | 
			
		||||
	"Change the process user",
 | 
			
		||||
	"Chroot to this directory",
 | 
			
		||||
	"Milliseconds to wait for daemon start",
 | 
			
		||||
	"Binary to start/stop",
 | 
			
		||||
	"Redirect stdout to file",
 | 
			
		||||
	"Redirect stderr to file",
 | 
			
		||||
	"Print dots each second while waiting",
 | 
			
		||||
	longopts_help_COMMON
 | 
			
		||||
};
 | 
			
		||||
#include "_usage.c"
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
start_stop_daemon(int argc, char **argv)
 | 
			
		||||
int main(int argc, char **argv)
 | 
			
		||||
{
 | 
			
		||||
	int devnull_fd = -1;
 | 
			
		||||
#ifdef TIOCNOTTY
 | 
			
		||||
@@ -686,6 +686,7 @@ start_stop_daemon(int argc, char **argv)
 | 
			
		||||
	char **margv;
 | 
			
		||||
	unsigned int start_wait = 0;
 | 
			
		||||
 | 
			
		||||
	applet = basename_c(argv[0]);
 | 
			
		||||
	TAILQ_INIT(&schedule);
 | 
			
		||||
#ifdef DEBUG_MEMORY
 | 
			
		||||
	atexit(cleanup);
 | 
			
		||||
 
 | 
			
		||||
@@ -25,40 +25,39 @@
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <getopt.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <utime.h>
 | 
			
		||||
 | 
			
		||||
#include "builtins.h"
 | 
			
		||||
#include "einfo.h"
 | 
			
		||||
#include "rc-misc.h"
 | 
			
		||||
#include "_usage.h"
 | 
			
		||||
 | 
			
		||||
#define RC_SHUTDOWNTIME    RC_SVCDIR "/shutdowntime"
 | 
			
		||||
 | 
			
		||||
extern const char *applet;
 | 
			
		||||
 | 
			
		||||
#include "_usage.h"
 | 
			
		||||
#define extraopts "file"
 | 
			
		||||
#define getoptstring "sw" getoptstring_COMMON
 | 
			
		||||
static const struct option longopts[] = {
 | 
			
		||||
const char *applet = NULL;
 | 
			
		||||
const char *extraopts = "file";
 | 
			
		||||
const char *getoptstring = "sw" getoptstring_COMMON;
 | 
			
		||||
const struct option longopts[] = {
 | 
			
		||||
	{ "save", 0, NULL, 's' },
 | 
			
		||||
	{ "warn", 0, NULL, 'w' },
 | 
			
		||||
	longopts_COMMON
 | 
			
		||||
};
 | 
			
		||||
static const char * const longopts_help[] = {
 | 
			
		||||
const char * const longopts_help[] = {
 | 
			
		||||
	"saves the time",
 | 
			
		||||
	"no error if no reference file",
 | 
			
		||||
	longopts_help_COMMON
 | 
			
		||||
};
 | 
			
		||||
#include "_usage.c"
 | 
			
		||||
const char *usagestring = NULL;
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
swclock(int argc, char **argv)
 | 
			
		||||
int main(int argc, char **argv)
 | 
			
		||||
{
 | 
			
		||||
	int opt, sflag = 0, wflag = 0;
 | 
			
		||||
	const char *file = RC_SHUTDOWNTIME;
 | 
			
		||||
	struct stat sb;
 | 
			
		||||
	struct timeval tv;
 | 
			
		||||
 | 
			
		||||
	applet = basename_c(argv[0]);
 | 
			
		||||
	while ((opt = getopt_long(argc, argv, getoptstring,
 | 
			
		||||
		    longopts, (int *) 0)) != -1)
 | 
			
		||||
	{
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user