add ability for openrc-shutdown to communicate with sysvinit
This fixes #315.
This commit is contained in:
parent
7ddc281ab6
commit
cac41092e4
@ -14,7 +14,8 @@ SRCS+= rc-selinux.c
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq (${OS},Linux)
|
ifeq (${OS},Linux)
|
||||||
SRCS+= kill_all.c openrc-init.c openrc-shutdown.c broadcast.c rc-wtmp.c
|
SRCS+= kill_all.c openrc-init.c openrc-shutdown.c rc-sysvinit.c broadcast.c \
|
||||||
|
rc-wtmp.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
CLEANFILES= version.h rc-selinux.o
|
CLEANFILES= version.h rc-selinux.o
|
||||||
@ -134,7 +135,7 @@ mountinfo: mountinfo.o _usage.o rc-misc.o
|
|||||||
openrc rc: rc.o rc-logger.o rc-misc.o rc-plugin.o _usage.o
|
openrc rc: rc.o rc-logger.o rc-misc.o rc-plugin.o _usage.o
|
||||||
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
|
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
|
||||||
|
|
||||||
openrc-shutdown: openrc-shutdown.o rc-misc.o _usage.o broadcast.o rc-wtmp.o
|
openrc-shutdown: openrc-shutdown.o rc-misc.o _usage.o broadcast.o rc-wtmp.o rc-sysvinit.o
|
||||||
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
|
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
|
||||||
|
|
||||||
openrc-run runscript: openrc-run.o _usage.o rc-misc.o rc-plugin.o
|
openrc-run runscript: openrc-run.o _usage.o rc-misc.o rc-plugin.o
|
||||||
|
@ -35,8 +35,9 @@
|
|||||||
#include "rc.h"
|
#include "rc.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "rc-misc.h"
|
#include "rc-misc.h"
|
||||||
#include "_usage.h"
|
#include "rc-sysvinit.h"
|
||||||
#include "rc-wtmp.h"
|
#include "rc-wtmp.h"
|
||||||
|
#include "_usage.h"
|
||||||
|
|
||||||
const char *applet = NULL;
|
const char *applet = NULL;
|
||||||
const char *extraopts = NULL;
|
const char *extraopts = NULL;
|
||||||
@ -328,15 +329,17 @@ int main(int argc, char **argv)
|
|||||||
syslog(LOG_NOTICE, "The system will %s now", state);
|
syslog(LOG_NOTICE, "The system will %s now", state);
|
||||||
unlink(nologin_file);
|
unlink(nologin_file);
|
||||||
unlink(shutdown_pid);
|
unlink(shutdown_pid);
|
||||||
if (do_halt)
|
if (do_halt) {
|
||||||
|
sysvinit_runlevel('0');
|
||||||
send_cmd("halt");
|
send_cmd("halt");
|
||||||
else if (do_kexec)
|
} else if (do_kexec)
|
||||||
send_cmd("kexec");
|
send_cmd("kexec");
|
||||||
else if (do_poweroff)
|
else if (do_poweroff)
|
||||||
send_cmd("poweroff");
|
send_cmd("poweroff");
|
||||||
else if (do_reboot)
|
else if (do_reboot) {
|
||||||
send_cmd("reboot");
|
sysvinit_runlevel('6');
|
||||||
else if (do_single)
|
send_cmd("reboot");
|
||||||
|
} else if (do_single)
|
||||||
send_cmd("single");
|
send_cmd("single");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
66
src/rc/rc-sysvinit.c
Normal file
66
src/rc/rc-sysvinit.c
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* rc-sysvinit.c
|
||||||
|
* Helper to send a runlevel change to sysvinit
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019 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 <fcntl.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include "einfo.h"
|
||||||
|
#include "rc-sysvinit.h"
|
||||||
|
|
||||||
|
void sysvinit_runlevel(char rl)
|
||||||
|
{
|
||||||
|
struct init_request request;
|
||||||
|
int fd;
|
||||||
|
char *p;
|
||||||
|
size_t bytes;
|
||||||
|
ssize_t r;
|
||||||
|
|
||||||
|
if (!rl)
|
||||||
|
return;
|
||||||
|
|
||||||
|
fd = open("/run/initctl", O_WRONLY|O_NONBLOCK|O_CLOEXEC|O_NOCTTY);
|
||||||
|
if (fd < 0) {
|
||||||
|
if (errno != ENOENT)
|
||||||
|
eerror("Failed to open initctl fifo: %s", strerror(errno));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
request = (struct init_request) {
|
||||||
|
.magic = INIT_MAGIC,
|
||||||
|
.sleeptime = 0,
|
||||||
|
.cmd = INIT_CMD_RUNLVL,
|
||||||
|
.runlevel = rl,
|
||||||
|
};
|
||||||
|
p = (char *) &request;
|
||||||
|
bytes = sizeof(request);
|
||||||
|
do {
|
||||||
|
r = write(fd, p, bytes);
|
||||||
|
if (r < 0) {
|
||||||
|
if ((errno == EAGAIN) || (errno == EINTR))
|
||||||
|
continue;
|
||||||
|
eerror("Failed to write to /run/initctl: %s", strerror(errno));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
p += r;
|
||||||
|
bytes -= r;
|
||||||
|
} while (bytes > 0);
|
||||||
|
exit(0);
|
||||||
|
}
|
71
src/rc/rc-sysvinit.h
Normal file
71
src/rc/rc-sysvinit.h
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* rc-sysvinit.h - Interface to communicate with sysvinit via /run/initctl.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _RC_SYSVINIT_H
|
||||||
|
#define _RC_SYSVINIT_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The #defines and structures below are taken from initreq.h in
|
||||||
|
* sysvinit and must be used by any program wishing to communicate with
|
||||||
|
* it.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define INIT_MAGIC 0x03091969
|
||||||
|
#define INIT_CMD_START 0
|
||||||
|
#define INIT_CMD_RUNLVL 1
|
||||||
|
#define INIT_CMD_POWERFAIL 2
|
||||||
|
#define INIT_CMD_POWERFAILNOW 3
|
||||||
|
#define INIT_CMD_POWEROK 4
|
||||||
|
#define INIT_CMD_BSD 5
|
||||||
|
#define INIT_CMD_SETENV 6
|
||||||
|
#define INIT_CMD_UNSETENV 7
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is what BSD 4.4 uses when talking to init.
|
||||||
|
* Linux doesn't use this right now.
|
||||||
|
*/
|
||||||
|
struct init_request_bsd {
|
||||||
|
char gen_id[8]; /* Beats me.. telnetd uses "fe" */
|
||||||
|
char tty_id[16]; /* Tty name minus /dev/tty */
|
||||||
|
char host[64]; /* Hostname */
|
||||||
|
char term_type[16]; /* Terminal type */
|
||||||
|
int signal; /* Signal to send */
|
||||||
|
int pid; /* Process to send to */
|
||||||
|
char exec_name[128]; /* Program to execute */
|
||||||
|
char reserved[128]; /* For future expansion. */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Because of legacy interfaces, "runlevel" and "sleeptime"
|
||||||
|
* aren't in a seperate struct in the union.
|
||||||
|
*
|
||||||
|
* The weird sizes are because init expects the whole
|
||||||
|
* struct to be 384 bytes.
|
||||||
|
*/
|
||||||
|
struct init_request {
|
||||||
|
int magic; /* Magic number */
|
||||||
|
int cmd; /* What kind of request */
|
||||||
|
int runlevel; /* Runlevel to change to */
|
||||||
|
int sleeptime; /* Time between TERM and KILL */
|
||||||
|
union {
|
||||||
|
struct init_request_bsd bsd;
|
||||||
|
char data[368];
|
||||||
|
} i;
|
||||||
|
};
|
||||||
|
|
||||||
|
void sysvinit_runlevel(char rl);
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user