272f112c98
it closes (and leaves closed) the named pipe /run/initctl. This can be used to make sure init does not have any files open. However, it also means we cannot switch run levels or bring down the system. The pipe can be re-opened by sending init the SIGUSR1 signal. Updated the man pages for initctl and init to include this information.
151 lines
6.1 KiB
Groff
151 lines
6.1 KiB
Groff
'\" -*- coding: UTF-8 -*-
|
|
.\" Copyright (C) 2018 Jesse Smith
|
|
.\"
|
|
.\" This program is free software; you can redistribute it and/or modify
|
|
.\" it under the terms of the GNU General Public License as published by
|
|
.\" the Free Software Foundation; either version 2 of the License.
|
|
.\"
|
|
.\" This program is distributed in the hope that it will be useful,
|
|
.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
.\" GNU General Public License for more details.
|
|
.\"
|
|
.\" You should have received a copy of the GNU General Public License
|
|
.\" along with this program; if not, write to the Free Software
|
|
.\" Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
.\"
|
|
.TH INITCTL 5 "April 13, 2018" "" "Linux System Administrator's Manual"
|
|
.SH NAME
|
|
initctl \- /run/initctl is a named pipe which passes commands to SysV init.
|
|
.SH SYNOPSIS
|
|
/run/initctl
|
|
.SH DESCRIPTION
|
|
|
|
This document describes the communiction pipe set up by SysV init
|
|
at /run/initctl. This named pipe allows programs with the proper
|
|
permissions (typically programs run by root have read+write access to
|
|
the pipe) to send signals to the init program (PID 1).
|
|
|
|
The init manual page has, up until recently, simply stated
|
|
that people wishing to understand how to send messages to init
|
|
should read the init program's source code, but that is not usually practical.
|
|
|
|
Messages sent to the pipe to talk to init must have a special format.
|
|
This format is defined as a C structure and the technical break-down
|
|
is presented here:
|
|
|
|
/*
|
|
* 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;
|
|
};
|
|
|
|
|
|
Let's go through the init_request structure one line at a time. The
|
|
first variable, the "magic" number must be of the value 0x03091969.
|
|
The init program then knows that only programs with root access which send
|
|
this magic number are authorized to communicate with init.
|
|
|
|
The cmd variable is a value in the range of 0-8 (currently). This cmd
|
|
variable tells init what we want it to do. Here are the possible options:
|
|
|
|
1 - Set the current runlevel, specified by the runlevel variable.
|
|
|
|
2 - The power will fail soon (probably low battery) prepare to shutdown.
|
|
|
|
3 - The power is failing, do shutdown immediately.
|
|
|
|
4 - The power is okay, cancel shutdown.
|
|
|
|
6 - Set an environment variable to a value to be specified in
|
|
the data variable of this structure.
|
|
|
|
Other cmd options may be added to init later. For example, command values
|
|
0, 5 and 7 are defined but currently not implemented.
|
|
|
|
The runlevel variable will specify the runlevel to switch to (0-6).
|
|
|
|
The sleeptime variable is to be used when we want to tell init to change
|
|
the time spent waiting between sending SIGTERM and SIGKILL during the
|
|
shutdown process. Changing this at run time is not yet implemented.
|
|
|
|
The data variable (in the union) can be used to pass misc data which init
|
|
might need to process our request. For example, when setting environment
|
|
variables.
|
|
|
|
When setting an environment variable through init's /run/initctl pipe,
|
|
the data variable should have the format VARIABLE=VALUE. The string
|
|
should be terminated with a NULL character.
|
|
|
|
.SH EXAMPLES
|
|
|
|
The following C code example shows how to send a set environment variable
|
|
request to the init process using the /run/initctl pipe. This example
|
|
is simplified and skips the error checking. A more comlpete example can be
|
|
found in the shutdown.c program's init_setnv() function.
|
|
|
|
.nf
|
|
struct init_request request; /* structure defined above */
|
|
int fd; /* file descriptor for pipe */
|
|
|
|
memset(&request, 0, sizeof(request)); /* initialize structure */
|
|
request.magic = 0x03091969; /* magic number required */
|
|
request.cmd = 6; /* 6 is to set a variable */
|
|
sprintf(request.data, "VARIABLE=VALUE"); /* set VAR to VALUE in init */
|
|
|
|
if ((fd = open(INIT_FIFO, O_WRONLY)) >= 0) /* open pipe for writing */
|
|
{
|
|
size_t s = sizeof(request); /* size of structure to write */
|
|
void *ptr = &request; /* temporary pointer */
|
|
write(fd, ptr, s); /* send structure to the pipe */
|
|
close(fd); /* close the pipe when done */
|
|
}
|
|
.fi
|
|
|
|
.sp
|
|
.RE
|
|
.SH NOTES
|
|
Usually the /run/initctl pipe would only be used by low-level programs to
|
|
request a power-related shutdown or change the runlevel, like telinit
|
|
would do. Most of the time there is no need to talk to init directly, but
|
|
this gives us an extenable approach so init can be taught how to learn
|
|
more commands.
|
|
.PP
|
|
The commands passed through the /run/initctl pipe must be sent in a specific
|
|
binary format and be of a specific length. Larger data structures or ones
|
|
not using the proper format will be ignored. Typically, only root has the
|
|
ability to write to the initctl pipe for security reasons.
|
|
.PP
|
|
The /run/initctl pipe can be closed by sending init (PID 1) the SIGUSR2
|
|
signal. This closes the pipe and leaves it closed. This may be useful
|
|
for making sure init is not keeping any files open. However, when the
|
|
pipe is closed, init no longer receives signals, such as those sent by
|
|
shutdown or telinit. In other words if we close the pipe, init cannot
|
|
change its runlevel directly. The pipe may be re-opened by sending init (PID 1)
|
|
the SIGUSR1 signal.
|
|
.PP
|
|
If the /run/initctl pipe is closed then it may still be possible to bring
|
|
down the system using the shutdown command's -n flag, but this is not
|
|
always clean and not recommended.
|
|
.RE
|
|
.SH FILES
|
|
/run/initctl
|
|
/sbin/init
|
|
.SH AUTHOR
|
|
Jesse Smith <jsmith@resonatingmedia.com>
|
|
.SH "SEE ALSO"
|
|
init(8)
|