[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

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: