Bug#383249: usplash: add support for user input
I've attached a patch which adds user input support to usplash.
This works by creating a second fifo /dev/.initramfs/usplash_outfifo and
two new commands: INPUT and INPUTQUIET.
Both INPUT and INPUTQUIET take a prompt as argument. The prompt is
written to the usplash screen and then one line of user input is read to
a buffer. If INPUTQUIET has been used, the user input is not echoed to
screen (but '*').
usplash then waits for a reader to be ready on the outfifo or until the
timeout time elapses. If a reader is available, the user input is
written to the fifo from the buffer.
In a initramfs script, something like this would be used:
if [ -p /dev/.initramfs/usplash_outfifo ]; then
usplash_write "INPUTQUIET Enter password: "
PASS="$(cat /dev/.initramfs/usplash_outfifo)"
else
echo -n "Enter password: "
read PASS
echo
fi
I have tried the patch locally with a slightly modified cryptsetup
initramfs script and it seems to work.
Regards,
David
Index: usplash-0.3e-quilt/usplash.c
===================================================================
--- usplash-0.3e-quilt.orig/usplash.c 2006-08-17 21:50:39.000000000 +0200
+++ usplash-0.3e-quilt/usplash.c 2006-08-19 01:54:47.000000000 +0200
@@ -20,6 +20,7 @@
*/
#include <linux/vt.h>
+#include <linux/limits.h>
#include <sys/select.h>
#include <sys/time.h>
@@ -59,6 +60,7 @@
static void draw_line (const char *string, size_t len);
static void draw_status (const char *string, size_t len, int mode);
+static int handle_input (const char *string, size_t len, int quiet);
/* Default theme, used when no suitable alternative can be found */
extern struct usplash_theme testcard_theme;
@@ -115,6 +117,14 @@
}
}
+ if (mkfifo (USPLASH_OUTFIFO, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) < 0) {
+ if (errno != EEXIST) {
+ perror ("mkfifo");
+ ret = 1;
+ goto exit;
+ }
+ }
+
fifo_fd = open (USPLASH_FIFO, O_RDONLY|O_NONBLOCK);
if (fifo_fd < 0) {
perror ("open");
@@ -180,6 +190,9 @@
ioctl (fd, VT_ACTIVATE, vt);
ioctl (fd, VT_WAITACTIVE, vt);
close (fd);
+
+ close (STDIN_FILENO);
+ open (vtname, O_RDONLY);
}
static void
@@ -333,6 +346,12 @@
} else if (! strncmp (command, "PROGRESS", commandlen)) {
draw_progressbar (atoi (string));
+
+ } else if (! strncmp (command, "INPUT", commandlen)) {
+ return handle_input (string, len, 0);
+
+ } else if (! strncmp (command, "INPUTQUIET", commandlen)) {
+ return handle_input (string, len, 1);
}
return 0;
@@ -473,3 +492,75 @@
bogl_text (x1, y1, string, len, fg, theme->text_background,
0, theme->font);
}
+
+static int
+handle_input (const char *string, const size_t len, const int quiet)
+{
+ int i;
+ char input;
+ int x1, y1, x2, y2, xpos;
+ ssize_t wlen;
+ int fifo_outfd;
+ char inputbuf[PIPE_BUF] = "";
+
+ /* some variables which we'll need */
+ x1 = left_edge + theme->text_x;
+ x2 = x1 + theme->text_width;
+
+ y2 = top_edge + theme->text_y + theme->text_height;
+ y1 = y2 - theme->line_height;
+
+ /* draw the prompt */
+ draw_line (string, len);
+ xpos = x1 + bogl_metrics (string, len, theme->font);
+
+ /* Get user input */
+ for (i = 0; i < PIPE_BUF - 1; i++) {
+ input = getchar ();
+ if (input == '\n' || input == '\r' || input == '\0')
+ break;
+
+ inputbuf[i] = input;
+
+ if (quiet)
+ input = '*';
+
+ /* Make sure the text doesn't overflow */
+ if (xpos + bogl_metrics (&input, 1, theme->font) > x2) {
+ bogl_move (x1,
+ top_edge + theme->text_y + theme->line_height,
+ x1,
+ top_edge + theme->text_y,
+ theme->text_width,
+ theme->text_height - theme->line_height);
+ bogl_clear (x1, y1, x2, y2, theme->text_background);
+ xpos = x1;
+ }
+
+ bogl_text (xpos, y1, &input, 1,
+ theme->text_foreground, theme->text_background,
+ 0, theme->font);
+ xpos += bogl_metrics (&input, 1, theme->font);
+ }
+ inputbuf[i] = '\0';
+
+ /* We wait for timeout seconds for someone to read the user input */
+ for (i = 1; i != timeout + 1; i++) {
+ fifo_outfd = open (USPLASH_OUTFIFO, O_WRONLY|O_NONBLOCK);
+ if (fifo_outfd < 0)
+ sleep(1);
+ else
+ break;
+ }
+
+ if (fifo_outfd < 0)
+ return 1;
+
+ wlen = write (fifo_outfd, inputbuf, strlen(inputbuf) + 1);
+ if (wlen < 0)
+ return 1;
+
+ close(fifo_outfd);
+ memset(inputbuf, 0, PIPE_BUF);
+ return 0;
+}
Index: usplash-0.3e-quilt/usplash.h
===================================================================
--- usplash-0.3e-quilt.orig/usplash.h 2006-08-17 21:50:39.000000000 +0200
+++ usplash-0.3e-quilt/usplash.h 2006-08-17 21:51:09.000000000 +0200
@@ -27,6 +27,9 @@
/* Filename of usplash control fifo within the USPLASH_DIR directory */
#define USPLASH_FIFO "usplash_fifo"
+/* Filename of usplash feedback fifo */
+#define USPLASH_OUTFIFO "usplash_outfifo"
+
/* Location of usplash theme */
#define USPLASH_THEME "/usr/lib/usplash/usplash-artwork.so"
Index: usplash-0.3e-quilt/initramfs/scripts/init-top/usplash
===================================================================
--- usplash-0.3e-quilt.orig/initramfs/scripts/init-top/usplash 2006-08-19 00:55:32.000000000 +0200
+++ usplash-0.3e-quilt/initramfs/scripts/init-top/usplash 2006-08-19 01:00:48.000000000 +0200
@@ -27,6 +27,8 @@
done
if [ $SPLASH = "true" ]; then
+ modprobe -q i8042
+ modprobe -q atkbd
/sbin/usplash -c &
sleep 1
fi
Index: usplash-0.3e-quilt/usplash_write.8
===================================================================
--- usplash-0.3e-quilt.orig/usplash_write.8 2006-08-18 23:09:56.000000000 +0200
+++ usplash-0.3e-quilt/usplash_write.8 2006-08-18 23:16:30.000000000 +0200
@@ -50,6 +50,17 @@
Update the progress bar to show that the given percentage (0-100) of the
process has been completed.
.\"
+.TP
+.BI INPUT " prompt"
+Displays the given prompt and waits for one line of user input. The line
+can then be read from /dev/.initramfs/usplash_outfifo within the timeout
+period.
+.\"
+.TP
+.BI INPUTQUIET " prompt"
+Works in the same way as INPUT above with the exception that the user input
+is not echoed to the console. Useful for password prompts.
+.\"
.SH EXIT STATUS
.B usplash_write
always returns an exit status of zero.
Reply to: