Hello,

while fbsplash works well in root fs, it doesn't work when started from
an initrd. It exhibits this behavior:

1. the nash shell, used in initrd, can't start the applet in background;
it blocks forever the loading process.

==> I added back the code to fork the process (if this can be
acceptable).


2. once started with the above fork code, if I want to redirect the
messages from the console to the uart, passing to the kernel the option
'console=uart', it doesn't receive the commands from the fifo.

==> I substitute the file manipulation library functions (fopen,
fgetline, fclose..) with the system one (open, read, close..) and thus
it works.

Il giorno ven, 28/03/2008 alle 09.06 -0400, Paul Fox ha scritto:
> is the proper solution simply to open it twice, once for reading,
> and once for writing?  this guarantees a writer (which will never
> write anything).

Following the suggestion of Paul, now I open the fifo twice to use the
opportunity to make the read blocking. After reading, the buffer is
scanned in order to take the last command line.
If the commands comes from the stdin, when the function returns 0 it
assumes that has reached the EOF and it exits.

Please, can you consider the attached patch?

Thanks.
Michele


diff -urP busybox/miscutils/Config.in busybox_0204/miscutils/Config.in
--- busybox/miscutils/Config.in	2008-04-02 09:20:14.000000000 +0200
+++ busybox_0204/miscutils/Config.in	2008-04-04 09:17:36.000000000 +0200
@@ -210,14 +210,14 @@
 	  Usage:
 	  - use kernel option 'vga=xxx' or otherwise enable fb device.
 	  - put somewhere fbsplash.cfg file and an image in .ppm format.
-	  - $ setsid fbsplash [params] &
+	  - $ fbsplash [params]
 	    -c: hide cursor
 	    -d /dev/fbN: framebuffer device (if not /dev/fb0)
 	    -s path_to_image_file (can be "-" for stdin)
 	    -i path_to_cfg_file (can be "-" for stdin)
 	    -f path_to_fifo (can be "-" for stdin)
 	  - if you want to run it only in presence of kernel parameter:
-	    grep -q "fbsplash=on" </proc/cmdline && setsid fbsplash [params] &
+	    grep -q "fbsplash=on" </proc/cmdline && fbsplash [params]
 	  - commands for fifo:
 	    "NN" (ASCII decimal number) - percentage to show on progress bar
 	    "exit" - well you guessed it
diff -urP busybox/miscutils/fbsplash.c busybox_0204/miscutils/fbsplash.c
--- busybox/miscutils/fbsplash.c	2008-04-02 09:20:14.000000000 +0200
+++ busybox_0204/miscutils/fbsplash.c	2008-04-04 11:24:17.000000000 +0200
@@ -8,7 +8,7 @@
  * Usage:
  * - use kernel option 'vga=xxx' or otherwise enable framebuffer device.
  * - put somewhere fbsplash.cfg file and an image in .ppm format.
- * - run applet: $ setsid fbsplash [params] &
+ * - run applet: $ fbsplash [params]
  *	-c: hide cursor
  *	-d /dev/fbN: framebuffer device (if not /dev/fb0)
  *	-s path_to_image_file (can be "-" for stdin)
@@ -16,7 +16,7 @@
  * 	-f path_to_fifo (can be "-" for stdin)
  * - if you want to run it only in presence of a kernel parameter
  *   (for example fbsplash=on), use:
- *   grep -q "fbsplash=on" </proc/cmdline && setsid fbsplash [params]
+ *   grep -q "fbsplash=on" </proc/cmdline && fbsplash [params]
  * - commands for fifo:
  *   "NN" (ASCII decimal number) - percentage to show on progress bar.
  *   "exit" (or just close fifo) - well you guessed it.
@@ -359,8 +359,9 @@
 int fbsplash_main(int argc ATTRIBUTE_UNUSED, char **argv)
 {
 	const char *fb_device, *cfg_filename, *fifo_filename;
-	FILE *fp = fp; // for compiler
+	int fd_r, fd_w;
 	bool bCursorOff;
+	pid_t pid;
 
 	INIT_G();
 
@@ -375,7 +376,7 @@
 	if (cfg_filename)
 		init(cfg_filename);
 
-	// We must have -s IMG
+	// we must have -s IMG
 	if (!G.image_filename)
 		bb_show_usage();
 
@@ -391,61 +392,102 @@
 	if (!fifo_filename)
 		return EXIT_SUCCESS;
 
-	fp = xfopen_stdin(fifo_filename);
+	// when run from initrd, the nash shell can't put it in background 
+	// forks the parent process
+	pid = fork();
+	if (pid < 0) {
+		bb_error_msg_and_die("can't fork");
+	}
+	else if (pid > 0) {
+		// if we got a good PID, then we can exit from the parent process.
+		exit(EXIT_SUCCESS);
+	}
+	// this is the child process
+	// change the file mode mask
+	umask(0);
+				
+	// create a new SID for the child process
+	if (setsid() < 0) {
+#if DEBUG
+		DEBUG_MESSAGE("failed to create new sid");
+#endif
+		bb_error_msg_and_die("can't sid");
+	}
+
+	if (*fifo_filename != '-') {
+		// opens the fifo twice
+		fd_r = xopen(fifo_filename, O_RDONLY);
+		fd_w = xopen(fifo_filename, O_WRONLY);	// only for make the 'read' blocking
+	}
+	else {
+		fd_r = xopen("/dev/stdin", O_RDONLY);
+		fd_w = -1;
+	}
+
+	fb_drawprogressbar(0);
 
 	while (1) {
 		struct stat statbuf;
 		unsigned num;
-		char *num_buf;
+		char cmd_buf[32];
+		int nlen;
+		char *p, *last_cmd; 
 
-		fb_drawprogressbar(0);
-		// Block on read, waiting for some input.
-		// Use of <stdio.h> style I/O allows to correctly
-		// handle a case when we have many buffered lines
-		// already in the pipe
-		while ((num_buf = xmalloc_fgetline(fp)) != NULL) {
-			if (strncmp(num_buf, "exit", 4) == 0) {
-				DEBUG_MESSAGE("exit");
- exit_cmd:
-				if (bCursorOff) {
-					// restore cursor
-					full_write(STDOUT_FILENO, "\x1b" "[?25h", 6);
-				}
-				return EXIT_SUCCESS;
-			}
-			num = atoi(num_buf);
-			if (isdigit(num_buf[0]) && (num <= 100)) {
+		nlen = read(fd_r, cmd_buf, 32);
+
+		if (nlen == -1) {
 #if DEBUG
-				char strVal[10];
-				sprintf(strVal, "%d", num);
-				DEBUG_MESSAGE(strVal);
+			DEBUG_MESSAGE("error reading the fifo");
 #endif
-				fb_drawprogressbar(num);
+			continue;
+		}
+		else if (nlen == 0) {	// EOF
+			if (LONE_DASH(fifo_filename)
+			|| stat(fifo_filename, &statbuf) != 0
+			|| !S_ISFIFO(statbuf.st_mode)) {
+				// EOF from stdin so exits
+				break;
 			}
-			free(num_buf);
+			
+			continue;
 		}
-		// We got EOF/error on fp
-		if (ferror(fp))
-			goto exit_cmd;
-		fclose(fp);
-		if (LONE_DASH(fifo_filename)
-		 || stat(fifo_filename, &statbuf) != 0
-		 || !S_ISFIFO(statbuf.st_mode)
-		) {
-			goto exit_cmd;
+
+		cmd_buf[nlen] = '\0';
+
+		// when we have many buffered lines already in the pipe, takes the last one.
+		p = cmd_buf;
+		last_cmd = cmd_buf;
+		while (((p = strchr(last_cmd, '\n')) != (cmd_buf + nlen - 1)) && (p != NULL)) {
+			last_cmd = (p + 1);
+		}
+
+		if (strncmp(last_cmd, "exit", 4) == 0) {
+#if DEBUG
+			DEBUG_MESSAGE("exit");
+#endif
+			break;
+		}
+
+		num = atoi(last_cmd);
+		if (isdigit(cmd_buf[0]) && (num <= 100)) {
+#if DEBUG
+			char strVal[10];
+			sprintf(strVal, "%d", num);
+			DEBUG_MESSAGE(strVal);
+#endif
+			fb_drawprogressbar(num);
 		}
-		// It's really a named pipe!
-		// For named pipes, we want to support this:
-		//  mkfifo cmd_pipe
-		//  fbsplash -f cmd_pipe .... &
-		//  ...
-		//  echo 33 >cmd_pipe
-		//  ...
-		//  echo 66 >cmd_pipe
-		// This means that on EOF, we need to close/open cmd_pipe
-		// (just reading again works too, but it hogs CPU)
-		fp = xfopen_stdin(fifo_filename); // blocks on open
 	} // end of while (1)
 
+	if (bCursorOff) {
+		// restore cursor
+		full_write(STDOUT_FILENO, "\x1b" "[?25h", 6);
+	}
+
+	close(fd_r);
+
+	if (fd_w != -1)
+		close(fd_w);
+
 	return EXIT_SUCCESS;
 }
_______________________________________________
busybox mailing list
[email protected]
http://busybox.net/cgi-bin/mailman/listinfo/busybox

Reply via email to