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:
William Hubbs 2015-12-23 14:06:31 -06:00
parent fe485f4433
commit bf2f40828e
28 changed files with 1160 additions and 1067 deletions

View File

@ -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

View File

@ -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

View File

@ -1,8 +1,4 @@
PROG= openrc
SRCS= checkpath.c fstabinfo.c mountinfo.c openrc-run.c \
rc-applets.c rc-depend.c rc-logger.c \
rc-misc.c rc-plugin.c rc-service.c rc-status.c rc-update.c \
rc.c start-stop-daemon.c swclock.c
SRCS= rc.c rc-logger.c rc-misc.c rc-plugin.c
ifeq (${MKSELINUX},yes)
SRCS+= rc-selinux.c
@ -14,26 +10,26 @@ BINDIR= ${PREFIX}/bin
SBINDIR= ${PREFIX}/sbin
LINKDIR= ${LIBEXECDIR}
BINLINKS= rc-status
SBINLINKS= rc rc-service rc-update openrc-run runscript service \
start-stop-daemon
RC_BINLINKS= einfon einfo ewarnn ewarn eerrorn eerror ebegin eend ewend \
eindent eoutdent esyslog eval_ecolors ewaitfile \
veinfo vewarn vebegin veend vewend veindent veoutdent \
service_starting service_started \
service_stopping service_stopped \
service_inactive service_wasinactive \
service_hotplugged service_started_daemon service_crashed \
checkpath fstabinfo mountinfo rc-depend \
service_get_value service_set_value get_options save_options \
shell_var is_newer_than is_older_than
RC_SBINLINKS= mark_service_starting mark_service_started \
BINPROGS= rc-status
SBINPROGS = openrc openrc-run rc rc-service rc-update runscript service start-stop-daemon
RC_BINPROGS= einfon einfo ewarnn ewarn eerrorn eerror ebegin eend ewend \
eindent eoutdent esyslog eval_ecolors ewaitfile \
veinfo vewarn vebegin veend vewend veindent veoutdent \
checkpath fstabinfo mountinfo rc-depend \
is_newer_than is_older_than \
service_get_value service_set_value get_options save_options \
service_starting service_started \
service_stopping service_stopped \
service_inactive service_wasinactive \
service_hotplugged service_started_daemon service_crashed \
shell_var
RC_SBINPROGS= mark_service_starting mark_service_started \
mark_service_stopping mark_service_stopped \
mark_service_inactive mark_service_wasinactive \
mark_service_hotplugged mark_service_failed \
rc-abort swclock
ALL_LINKS= ${BINLINKS} ${SBINLINKS} ${RC_BINLINKS} ${RC_SBINLINKS}
CLEANFILES+= ${ALL_LINKS}
ALL_PROGS= ${BINPROGS} ${SBINPROGS} ${RC_BINPROGS} ${RC_SBINPROGS}
CLEANFILES+= ${ALL_PROGS}
LOCAL_CPPFLAGS=-I../includes -I../librc -I../libeinfo
LOCAL_LDFLAGS=-L../librc -L../libeinfo
@ -49,22 +45,6 @@ include ${MK}/termcap.mk
LDADD+= ${LIBDL} ${LIBKVM}
include ${MK}/pam.mk
# create symlinks to rc if not an SELINUX system, otherwise create a wrapper
# script to call rc with the proper name of the applet to execute.
# $1 is a list of the links
# $2 is the path+name of the target to link to (usually 'rc' or '/sbin/rc')
# $3 is the path where the links are created
define make-links
for x in $(1); do \
if [ "${MKSELINUX}" = yes ]; then \
printf '#!/bin/sh\nexec ${2} --applet %s "$$@"\n' $$x >${3}/$$x; \
chmod ${BINMODE} ${3}/$$x; \
else \
ln -sf ${2} ${3}/$$x; \
fi; \
done;
endef
${SRCS}: version.h
.PHONY: version.h.tmp
@ -79,15 +59,13 @@ version.h: version.h.tmp
install: all
${INSTALL} -d ${DESTDIR}${SBINDIR}
${INSTALL} -m ${BINMODE} ${PROG} ${DESTDIR}${SBINDIR}
${INSTALL} -m ${BINMODE} ${SBINPROGS} ${DESTDIR}${SBINDIR}
${INSTALL} -d ${DESTDIR}${BINDIR}
$(call make-links,${BINLINKS},${SBINDIR}/${PROG},${DESTDIR}${BINDIR})
${INSTALL} -d ${DESTDIR}${SBINDIR}
$(call make-links,${SBINLINKS},${SBINDIR}/${PROG},${DESTDIR}${SBINDIR})
${INSTALL} -m ${BINMODE} ${BINPROGS} ${DESTDIR}${BINDIR}
${INSTALL} -d ${DESTDIR}${LINKDIR}/bin
$(call make-links,${RC_BINLINKS},${SBINDIR}/${PROG},${DESTDIR}${LINKDIR}/bin)
${INSTALL} -m ${BINMODE} ${RC_BINPROGS} ${DESTDIR}${LINKDIR}/bin
${INSTALL} -d ${DESTDIR}${LINKDIR}/sbin
$(call make-links, ${RC_SBINLINKS},${SBINDIR}/${PROG},${DESTDIR}${LINKDIR}/sbin)
${INSTALL} -m ${BINMODE} ${RC_SBINPROGS} ${DESTDIR}${LINKDIR}/sbin
if test "${MKPAM}" = pam; then \
${INSTALL} -d ${DESTDIR}${PAMDIR}; \
${INSTALL} -m ${PAMMODE} start-stop-daemon.pam ${DESTDIR}${PAMDIR}/start-stop-daemon; \
@ -95,5 +73,70 @@ install: all
check test::
links: ${PROG}
$(call make-links,${ALL_LINKS},${PROG},.)
all: ${ALL_PROGS}
checkpath: checkpath.o _usage.o rc-misc.o rc-selinux.o
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
einfon einfo ewarnn ewarn eerrorn eerror ebegin eend ewend \
eindent eoutdent esyslog eval_ecolors ewaitfile \
veinfo vewarn vebegin veend vewend veindent veoutdent: do_e.o rc-misc.o
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
fstabinfo: fstabinfo.o _usage.o rc-misc.o
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
is_newer_than: is_newer_than.o rc-misc.o
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
is_older_than: is_older_than.o rc-misc.o
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
mark_service_starting mark_service_started \
mark_service_stopping mark_service_stopped \
mark_service_inactive mark_service_wasinactive \
mark_service_hotplugged mark_service_failed: do_mark_service.o rc-misc.o
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
mountinfo: mountinfo.o _usage.o rc-misc.o
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
openrc rc: rc.o rc-logger.o rc-misc.o rc-plugin.o rc-selinux.o _usage.o
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
openrc-run runscript: openrc-run.o _usage.o rc-misc.o rc-plugin.o
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
rc-abort: rc-abort.o
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ -leinfo
rc-depend: rc-depend.o _usage.o rc-misc.o
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
rc-status: rc-status.o _usage.o rc-misc.o
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
rc-service service: rc-service.o _usage.o rc-misc.o
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
rc-update: rc-update.o _usage.o rc-misc.o
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
start-stop-daemon: start-stop-daemon.o _usage.o rc-misc.o
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
service_get_value service_set_value get_options save_options: do_value.o rc-misc.o
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
service_starting service_started \
service_stopping service_stopped \
service_inactive service_wasinactive \
service_hotplugged service_started_daemon \
service_crashed: do_service.o rc-misc.o
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
shell_var: shell_var.o
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^
swclock: swclock.o _usage.o rc-misc.o
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}

View File

@ -10,8 +10,12 @@
* except according to the terms contained in the LICENSE file.
*/
#include "version.h"
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include "rc-misc.h"
#include "_usage.h"
#include "version.h"
#if lint
# define _noreturn
@ -22,7 +26,7 @@
# define _noreturn
#endif
static void set_quiet_options(void)
void set_quiet_options(void)
{
static int qcount = 0;
@ -37,8 +41,7 @@ static void set_quiet_options(void)
}
}
_noreturn static void
show_version(void)
_noreturn void show_version(void)
{
const char *systype = NULL;
@ -56,8 +59,7 @@ show_version(void)
exit(EXIT_SUCCESS);
}
_noreturn static void
usage(int exit_status)
_noreturn void usage(int exit_status)
{
const char * const has_arg[] = { "", "<arg>", "[arg]" };
int i;
@ -67,15 +69,15 @@ usage(int exit_status)
char *token;
char val[4] = "-?,";
#ifdef usagestring
printf(usagestring);
#else
printf("Usage: %s [options] ", applet);
#endif
#ifdef extraopts
printf(extraopts);
#endif
printf("\n\nOptions: [" getoptstring "]\n");
if (usagestring)
printf("%s", usagestring);
else
printf("Usage: %s [options] ", applet);
if (extraopts)
printf("%s", extraopts);
printf("\n\nOptions: [ %s ]\n", getoptstring);
for (i = 0; longopts[i].name; ++i) {
val[1] = longopts[i].val;
len = printf(" %3s --%s %s", isprint(longopts[i].val) ? val : "",

View File

@ -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);

View File

@ -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);

View File

@ -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
View 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
View 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
View 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
View 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;
}

View File

@ -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
View 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
View 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;
}

View File

@ -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;

View File

@ -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
View 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;
}

View File

@ -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);
}

View File

@ -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)

View File

@ -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;
}

View File

@ -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

View File

@ -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");

View File

@ -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) {

View File

@ -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) {

View File

@ -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
View 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;
}

View File

@ -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);

View File

@ -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)
{