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 via email to