fix sysvinit compatibility

This allows openrc to direct sysvinit to shut down the system by setting
the INIT_HALT environment variable appropriately. Also, we do not try to
communicate with sysvinit if its fifo does not exist.
This commit is contained in:
William Hubbs 2019-08-15 12:02:30 -05:00
parent 92de9a693b
commit 0dabda6f6f
3 changed files with 72 additions and 22 deletions

View File

@ -330,16 +330,29 @@ int main(int argc, char **argv)
unlink(nologin_file);
unlink(shutdown_pid);
if (do_halt) {
sysvinit_runlevel('0');
send_cmd("halt");
if (exists("/run/initctl")) {
sysvinit_setenv("INIT_HALT", "HALT");
sysvinit_runlevel('0');
} else
send_cmd("halt");
} else if (do_kexec)
send_cmd("kexec");
else if (do_poweroff)
send_cmd("poweroff");
else if (do_reboot) {
sysvinit_runlevel('6');
else if (do_poweroff) {
if (exists("/run/initctl")) {
sysvinit_setenv("INIT_HALT", "POWEROFF");
sysvinit_runlevel('0');
} else
send_cmd("poweroff");
} else if (do_reboot) {
if (exists("/run/initctl"))
sysvinit_runlevel('6');
else
send_cmd("reboot");
} else if (do_single)
send_cmd("single");
} else if (do_single) {
if (exists("/run/initctl"))
sysvinit_runlevel('S');
else
send_cmd("single");
}
return 0;
}

View File

@ -26,31 +26,21 @@
#include "einfo.h"
#include "rc-sysvinit.h"
void sysvinit_runlevel(char rl)
static void sysvinit_send_cmd(struct init_request *request)
{
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);
p = (char *) request;
bytes = sizeof(*request);
do {
r = write(fd, p, bytes);
if (r < 0) {
@ -62,5 +52,51 @@ void sysvinit_runlevel(char rl)
p += r;
bytes -= r;
} while (bytes > 0);
exit(0);
}
void sysvinit_runlevel(char rl)
{
struct init_request request;
if (!rl)
return;
request = (struct init_request) {
.magic = INIT_MAGIC,
.sleeptime = 0,
.cmd = INIT_CMD_RUNLVL,
.runlevel = rl,
};
sysvinit_send_cmd(&request);
return;
}
/*
* Set environment variables in the init process.
*/
void sysvinit_setenv(char *name, char *value)
{
struct init_request request;
size_t nl;
size_t vl;
memset(&request, 0, sizeof(request));
request.magic = INIT_MAGIC;
request.cmd = INIT_CMD_SETENV;
nl = strlen(name);
if (value)
vl = strlen(value);
else
vl = 0;
if (nl + vl + 3 >= (int)sizeof(request.i.data))
return -1;
memcpy(request.i.data, name, nl);
if (value) {
request.i.data[nl] = '=';
memcpy(request.i.data + nl + 1, value, vl);
}
sysvinit_send_cmd(&request);
return 0;
}

View File

@ -67,5 +67,6 @@ struct init_request {
};
void sysvinit_runlevel(char rl);
void sysvinit_setenv(char *name, char *value);
#endif