9 #define INIT_MAGIC 0x03091969
10 #define INIT_CMD_START 0
11 #define INIT_CMD_RUNLVL 1
12 #define INIT_CMD_POWERFAIL 2
13 #define INIT_CMD_POWERFAILNOW 3
14 #define INIT_CMD_POWEROK 4
15 #define INIT_CMD_BSD 5
16 #define INIT_CMD_SETENV 6
17 #define INIT_CMD_UNSETENV 7
18 #define INIT_CMD_CHANGECONS 12345
19 #define INITRQ_HLEN 64
30 * abc ignored (inittab)
36 * -r, reboot runlevel 6 5, setenv INIT_HALT
37 * -h, default halt runlevel 0 5, setenv INIT_HALT
38 * -P, poweroff runlevel S 5, setenv INIT_HALT=POWERDOWN
39 * -H, just halt runlevel S 5, setenv INIT_HALT=HALT
40 * -f, skip fsck runlevel S 5, setenv INIT_HALT
41 * -F, force fskc runlevel S 5, setenv INIT_HALT
45 * This is what BSD 4.4 uses when talking to init.
46 * Linux doesn't use this right now.
48 struct init_request_bsd {
49 char gen_id[8]; /* Beats me.. telnetd uses "fe" */
50 char tty_id[16]; /* Tty name minus /dev/tty */
51 char host[INITRQ_HLEN]; /* Hostname */
52 char term_type[16]; /* Terminal type */
53 int signal; /* Signal to send */
54 int pid; /* Process to send to */
55 char exec_name[128]; /* Program to execute */
56 char reserved[128]; /* For future expansion. */
60 * Because of legacy interfaces, "runlevel" and "sleeptime" aren't in a
61 * seperate struct in the union.
63 * The weird sizes are because init expects the whole struct to be 384 bytes.
66 int magic; /* Magic number */
67 int cmd; /* What kind of request */
68 int runlevel; /* Runlevel to change to */
69 int sleeptime; /* Time between TERM and KILL */
71 struct init_request_bsd bsd;
76 const char *telinit_map[0x100] = {
77 /* not sure if these are mapped correctly */
78 ['0'] "runlevel poweroff",
79 ['1'] "runlevel single",
80 ['2'] "runlevel bare",
81 ['3'] "runlevel system",
82 ['5'] "runlevel user",
83 ['6'] "runlevel reboot",
84 ['s'] "runlevel single",
85 ['S'] "runlevel single",
92 int open_initctl(char *init_fifo)
94 /* First, try to create /dev/initctl if not present. */
96 if (stat(init_fifo, &st2) < 0 && errno == ENOENT)
97 mkfifo(init_fifo, 0600);
99 /* Now finally try to open /dev/initctl */
100 int pipe_fd = open(init_fifo, O_RDWR);
102 err(errno, "error opening %s", init_fifo);
104 /* Make sure it's a fifo */
106 if (!S_ISFIFO(st.st_mode)) {
108 err(errno, "%s is not a fifo", init_fifo);
114 void process_request(struct init_request *request)
116 if (request->sleeptime)
117 printf("eval SLEEP_TIME=%d\n", request->sleeptime);
119 switch (request->cmd) {
120 case INIT_CMD_RUNLVL:
121 if (telinit_map[request->runlevel])
122 printf("%s\n", telinit_map[request->runlevel]);
124 case INIT_CMD_POWERFAIL:
125 printf("powerfail\n");
127 case INIT_CMD_POWERFAILNOW:
128 printf("powerfailnow\n");
130 case INIT_CMD_POWEROK:
133 case INIT_CMD_SETENV:
134 printf("eval export %.*s\n",
135 sizeof(request->i.data),
138 case INIT_CMD_CHANGECONS:
139 printf("changeconsole %.*s\n",
140 sizeof(request->i.bsd.reserved),
141 request->i.bsd.reserved);
144 fprintf(stderr, "got unimplemented initrequest");
150 int main(int argc, char **argv)
153 printf("usage: %s <initctl>\n", argv[0]);
156 char *init_fifo = argv[1];
157 int pipe_fd = open_initctl(init_fifo);
159 /* Main loop, process data and reopen pipe when necessasairy */
161 /* Read the data, return on EINTR. */
162 struct init_request request;
163 int n = read(pipe_fd, &request, sizeof(request));
165 pipe_fd = open_initctl(init_fifo);
167 warn("error reading request");
168 else if (n != sizeof(request))
170 else if (request.magic != INIT_MAGIC)
171 warn("got bogus request");
173 process_request(&request);