add ability for openrc-shutdown to communicate with sysvinit
This fixes #315.
This commit is contained in:
		@@ -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
 | 
			
		||||
		Reference in New Issue
	
	Block a user