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
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
${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}
|
||||
|
||||
openrc-run runscript: openrc-run.o _usage.o rc-misc.o rc-plugin.o
|
||||
|
@ -35,8 +35,9 @@
|
||||
#include "rc.h"
|
||||
#include "helpers.h"
|
||||
#include "rc-misc.h"
|
||||
#include "_usage.h"
|
||||
#include "rc-sysvinit.h"
|
||||
#include "rc-wtmp.h"
|
||||
#include "_usage.h"
|
||||
|
||||
const char *applet = NULL;
|
||||
const char *extraopts = NULL;
|
||||
@ -328,15 +329,17 @@ int main(int argc, char **argv)
|
||||
syslog(LOG_NOTICE, "The system will %s now", state);
|
||||
unlink(nologin_file);
|
||||
unlink(shutdown_pid);
|
||||
if (do_halt)
|
||||
if (do_halt) {
|
||||
sysvinit_runlevel('0');
|
||||
send_cmd("halt");
|
||||
else if (do_kexec)
|
||||
} else if (do_kexec)
|
||||
send_cmd("kexec");
|
||||
else if (do_poweroff)
|
||||
send_cmd("poweroff");
|
||||
else if (do_reboot)
|
||||
send_cmd("reboot");
|
||||
else if (do_single)
|
||||
else if (do_reboot) {
|
||||
sysvinit_runlevel('6');
|
||||
send_cmd("reboot");
|
||||
} else if (do_single)
|
||||
send_cmd("single");
|
||||
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