mirror of
https://github.com/troglobit/finit.git
synced 2026-10-08 16:34:45 +07:00
Merge branch 'external-getty-support'
This commit is contained in:
@@ -86,9 +86,14 @@ inetd ssh/tcp@*,!eth0 nowait [2345] /sbin/dropbear -i -R -F -- SSH service
|
||||
# Run start scripts from this directory
|
||||
# runparts /etc/start.d
|
||||
|
||||
# Virtual consoles to start built-in getty on
|
||||
tty [12345] /dev/tty1 115200 linux
|
||||
# Virtual consoles run BusyBox getty
|
||||
tty [12345] /sbin/getty -L 115200 /dev/tty1 linux
|
||||
tty [12345] /sbin/getty -L 115200 /dev/tty2 linux
|
||||
tty [12345] /sbin/getty -L 115200 /dev/tty3 linux
|
||||
|
||||
# Use built-in getty for serial port and USB serial
|
||||
tty [12345] /dev/ttyAMA0 115200 vt100
|
||||
tty [12345] /dev/ttyUSB0 115200 vt100
|
||||
```
|
||||
|
||||
The `service` stanza, as well as `task`, `run`, `inetd` and others are
|
||||
|
||||
+13
-2
@@ -137,13 +137,24 @@ Syntax:
|
||||
Include another configuration file. Absolute path required.
|
||||
|
||||
* `tty [LVLS] <DEV> [BAUD] [TERM] [noclear]`
|
||||
Start the built-in getty on the given TTY device DEV, in the given
|
||||
runlevels. Default baud rate is `38400`.
|
||||
`tty [LVLS] <CMD> <ARGS>`
|
||||
The first variant of this option uses the built-in getty on the given
|
||||
TTY device DEV, in the given runlevels. Default baud rate is `38400`.
|
||||
|
||||
**Example:**
|
||||
```conf
|
||||
tty [12345] /dev/ttyAMA0 115200 noclear
|
||||
```
|
||||
|
||||
The second variant is for using an external getty, like agetty or the
|
||||
BusyBox getty. There are no default settings for this variant, but a
|
||||
word of caution: *you have give the absolute path to the TTY*.
|
||||
|
||||
**Example:**
|
||||
```conf
|
||||
tty [12345] /sbin/getty -L 115200 /dev/ttyAMA0 vt100
|
||||
```
|
||||
|
||||
On really bare bones systems Finit offers a fallback shell, but one
|
||||
can also use the `service` stanza to start a stand-alone shell:
|
||||
|
||||
|
||||
+76
-12
@@ -27,6 +27,7 @@
|
||||
#include <ctype.h> /* isdigit() */
|
||||
#include <dirent.h>
|
||||
#include <stdarg.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <sys/wait.h>
|
||||
#include <lite/lite.h>
|
||||
@@ -212,30 +213,93 @@ int run_interactive(char *cmd, char *fmt, ...)
|
||||
return status;
|
||||
}
|
||||
|
||||
static void prepare_tty(char *tty, char *procname, int console)
|
||||
{
|
||||
/* Reset signal handlers that were set by the parent process */
|
||||
sig_unblock();
|
||||
setsid();
|
||||
|
||||
/* Set INIT_PROCESS UTMP entry */
|
||||
utmp_set_init(tty, 0);
|
||||
|
||||
if (console)
|
||||
procname = "console";
|
||||
prctl(PR_SET_NAME, procname, 0, 0, 0);
|
||||
}
|
||||
|
||||
pid_t run_getty(char *tty, char *speed, char *term, int noclear, int console)
|
||||
{
|
||||
pid_t pid;
|
||||
|
||||
pid = fork();
|
||||
if (!pid) {
|
||||
/* Reset signal handlers that were set by the parent process */
|
||||
sig_unblock();
|
||||
setsid();
|
||||
|
||||
/* Set INIT_PROCESS UTMP entry */
|
||||
utmp_set_init(tty, 0);
|
||||
|
||||
if (console)
|
||||
prctl(PR_SET_NAME, "console", 0, 0, 0);
|
||||
else
|
||||
prctl(PR_SET_NAME, "finit-getty", 0, 0, 0);
|
||||
|
||||
prepare_tty(tty, "finit-getty", console);
|
||||
_exit(getty(tty, speed, term, noclear, NULL));
|
||||
}
|
||||
|
||||
return pid;
|
||||
}
|
||||
|
||||
pid_t run_getty2(char *tty, char *cmd, char *args[], int console)
|
||||
{
|
||||
pid_t pid;
|
||||
|
||||
pid = fork();
|
||||
if (!pid) {
|
||||
int i, fd;
|
||||
struct sigaction sa;
|
||||
|
||||
/* Reset signal handlers that were set by the parent process */
|
||||
for (i = 1; i < NSIG; i++)
|
||||
DFLSIG(sa, i, 0);
|
||||
|
||||
/* Detach from initial controlling TTY */
|
||||
vhangup();
|
||||
|
||||
close(STDERR_FILENO);
|
||||
close(STDOUT_FILENO);
|
||||
close(STDIN_FILENO);
|
||||
|
||||
/* Attach TTY to console */
|
||||
fd = open(tty, O_RDWR);
|
||||
if (fd != STDIN_FILENO)
|
||||
exit(1);
|
||||
|
||||
dup2(fd, STDIN_FILENO);
|
||||
dup2(fd, STDOUT_FILENO);
|
||||
dup2(fd, STDERR_FILENO);
|
||||
|
||||
prepare_tty(tty, "getty", console);
|
||||
|
||||
if (ioctl(STDIN_FILENO, TIOCSCTTY, 1) < 0)
|
||||
_pe("Failed TIOCSCTTY");
|
||||
|
||||
while (!fexist(SYNC_SHUTDOWN)) {
|
||||
char c;
|
||||
static const char msg[] = "\nPlease press Enter to activate this console.";
|
||||
|
||||
if (fexist(SYNC_STOPPED)) {
|
||||
sleep(1);
|
||||
continue;
|
||||
}
|
||||
|
||||
(void)write(STDERR_FILENO, msg, sizeof(msg));
|
||||
while (read(STDIN_FILENO, &c, 1) == 1 && c != '\n')
|
||||
continue;
|
||||
|
||||
if (fexist(SYNC_STOPPED))
|
||||
continue;
|
||||
|
||||
_exit(execv(cmd, args));
|
||||
}
|
||||
|
||||
close(fd);
|
||||
vhangup();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
return pid;
|
||||
}
|
||||
|
||||
int run_parts(char *dir, char *cmd)
|
||||
{
|
||||
|
||||
@@ -64,6 +64,7 @@ int complete (char *cmd, int pid);
|
||||
int run (char *cmd);
|
||||
int run_interactive (char *cmd, char *fmt, ...);
|
||||
pid_t run_getty (char *tty, char *speed, char *term, int noclear, int console);
|
||||
pid_t run_getty2 (char *tty, char *cmd, char *args[], int console);
|
||||
int run_parts (char *dir, char *cmd);
|
||||
|
||||
static inline void create(char *path, mode_t mode, uid_t uid, gid_t gid)
|
||||
|
||||
@@ -83,12 +83,33 @@ void tty_sweep(void)
|
||||
}
|
||||
}
|
||||
|
||||
/* tty [!1-9,S] <DEV> [BAUD[,BAUD,...]] [TERM] [noclear] */
|
||||
/**
|
||||
* tty_register - Register a getty on a device
|
||||
* @line: Configuration, text after initial "tty"
|
||||
* @mtime: Modification time, to propagate to lower layers
|
||||
*
|
||||
* A Finit tty line can use the internal getty implementation or an
|
||||
* external one, like the BusyBox getty for instance. This function
|
||||
* determines which one to use based on a leading '/dev' prefix. If
|
||||
* a leading '/dev' is encountered the remaining options must be in
|
||||
* the following sequence:
|
||||
*
|
||||
* tty [!1-9,S] <DEV> [BAUD[,BAUD,...]] [TERM] [noclear]
|
||||
*
|
||||
* Otherwise the leading prefix must be the full path to an existing
|
||||
* getty implementation, with it's arguments following:
|
||||
*
|
||||
* tty [!1-9,S] </path/to/getty> [ARGS]
|
||||
*
|
||||
* Different getty implementations prefer the TTY device argument in
|
||||
* different order, so take care to investigate this first.
|
||||
*/
|
||||
int tty_register(char *line, struct timeval *mtime)
|
||||
{
|
||||
tty_node_t *entry;
|
||||
int insert = 0, noclear = 0;
|
||||
char *tok, *dev = NULL, *baud = NULL;
|
||||
int i, num = 1, insert = 0, noclear = 0;
|
||||
char *tok, *cmd = NULL, *args[TTY_MAX_ARGS];
|
||||
char *dev = NULL, *baud = NULL;
|
||||
char *runlevels = NULL, *term = NULL;
|
||||
|
||||
if (!line) {
|
||||
@@ -96,24 +117,58 @@ int tty_register(char *line, struct timeval *mtime)
|
||||
return errno = EINVAL;
|
||||
}
|
||||
|
||||
tok = strtok(line, " ");
|
||||
while (tok) {
|
||||
if (tok[0] == '[')
|
||||
runlevels = &tok[0];
|
||||
else if (tok[0] == '/')
|
||||
dev = tok;
|
||||
else if (isdigit(tok[0]))
|
||||
baud = tok;
|
||||
else if (!strcmp(tok, "noclear"))
|
||||
noclear = 1;
|
||||
else
|
||||
term = tok;
|
||||
tok = strchr(line, '/');
|
||||
if (tok && strncmp(tok, "/dev", 4)) {
|
||||
/* External getty */
|
||||
cmd = tok;
|
||||
|
||||
tok = strtok(NULL, " ");
|
||||
for (tok = strtok(line, " "); tok; tok = strtok(NULL, " ")) {
|
||||
if (cmd == tok) {
|
||||
cmd = strdup(tok);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tok[0] == '[') {
|
||||
runlevels = &tok[0];
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tok[0] == '/' && tok != cmd)
|
||||
dev = strdup(tok);
|
||||
|
||||
args[num++] = strdup(tok);
|
||||
if (num >= TTY_MAX_ARGS)
|
||||
break;
|
||||
}
|
||||
|
||||
cmd = strdup(cmd);
|
||||
tok = strrchr(cmd, '/');
|
||||
if (!tok)
|
||||
tok = cmd;
|
||||
else
|
||||
tok++;
|
||||
args[0] = strdup(tok);
|
||||
} else {
|
||||
/* Built-in getty */
|
||||
tok = strtok(line, " ");
|
||||
while (tok) {
|
||||
if (tok[0] == '[')
|
||||
runlevels = &tok[0];
|
||||
else if (tok[0] == '/')
|
||||
dev = strdup(tok);
|
||||
else if (isdigit(tok[0]))
|
||||
baud = tok;
|
||||
else if (!strcmp(tok, "noclear"))
|
||||
noclear = 1;
|
||||
else
|
||||
term = tok;
|
||||
|
||||
tok = strtok(NULL, " ");
|
||||
}
|
||||
}
|
||||
|
||||
if (!dev) {
|
||||
_e("Incomplete tty, cannot register");
|
||||
_e("Incomplete tty, no device given, cannot register.");
|
||||
return errno = EINVAL;
|
||||
}
|
||||
|
||||
@@ -121,15 +176,24 @@ int tty_register(char *line, struct timeval *mtime)
|
||||
if (!entry) {
|
||||
insert = 1;
|
||||
entry = calloc(1, sizeof(*entry));
|
||||
if (!entry)
|
||||
if (!entry) {
|
||||
free(dev);
|
||||
return errno = ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
entry->data.name = strdup(dev);
|
||||
entry->data.name = dev;
|
||||
entry->data.baud = baud ? strdup(baud) : NULL;
|
||||
entry->data.term = term ? strdup(term) : NULL;
|
||||
entry->data.noclear = noclear;
|
||||
entry->data.runlevels = conf_parse_runlevels(runlevels);
|
||||
|
||||
/* External getty */
|
||||
entry->data.cmd = cmd;
|
||||
for (i = 0; i < num && i < TTY_MAX_ARGS; i++)
|
||||
entry->data.args[i] = args[i];
|
||||
entry->data.args[++i] = NULL;
|
||||
|
||||
_d("Registering tty %s at %s baud with term=%s on runlevels %s",
|
||||
dev, baud ?: "NULL", term ?: "N/A", runlevels ?: "[2-5]");
|
||||
|
||||
@@ -155,6 +219,15 @@ int tty_unregister(tty_node_t *tty)
|
||||
free(tty->data.baud);
|
||||
if (tty->data.term)
|
||||
free(tty->data.term);
|
||||
if (tty->data.cmd) {
|
||||
int i;
|
||||
|
||||
free(tty->data.cmd);
|
||||
for (i = 0; tty->data.args[i] && i < TTY_MAX_ARGS; i++) {
|
||||
free(tty->data.args[i]);
|
||||
tty->data.args[i] = NULL;
|
||||
}
|
||||
}
|
||||
free(tty);
|
||||
|
||||
return 0;
|
||||
@@ -275,7 +348,10 @@ void tty_start(finit_tty_t *tty)
|
||||
return;
|
||||
}
|
||||
|
||||
tty->pid = run_getty(dev, tty->baud, tty->term, tty->noclear, is_console);
|
||||
if (!tty->cmd)
|
||||
tty->pid = run_getty(dev, tty->baud, tty->term, tty->noclear, is_console);
|
||||
else
|
||||
tty->pid = run_getty2(dev, tty->cmd, tty->args, is_console);
|
||||
}
|
||||
|
||||
void tty_stop(finit_tty_t *tty)
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <limits.h>
|
||||
#include <lite/queue.h> /* BSD sys/queue.h API */
|
||||
|
||||
#define TTY_MAX_ARGS 16
|
||||
#define EVENT_SIZE ((sizeof(struct inotify_event) + NAME_MAX + 1))
|
||||
|
||||
typedef struct {
|
||||
@@ -37,6 +38,9 @@ typedef struct {
|
||||
int noclear;
|
||||
int runlevels;
|
||||
|
||||
char *cmd; /* NULL when running built-in getty */
|
||||
char *args[TTY_MAX_ARGS];
|
||||
|
||||
int pid;
|
||||
} finit_tty_t;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user