libarchive: *_compression_programにオプションを渡すパッチ

archive_read_support_compression_program("lzop -dc")とかやるためのパッチ。
そのうち投げるかも。

--- filter_fork.c.orig	2008-12-28 15:08:31.000000000 -0500
+++ filter_fork.c	2009-01-30 00:36:13.000000000 -0500
@@ -50,14 +50,22 @@ __FBSDID("$FreeBSD: src/lib/libarchive/f
 #ifdef HAVE_UNISTD_H
 #  include <unistd.h>
 #endif
+#ifdef HAVE_STRING_H
+#  include <string.h>
+#endif
 
 #include "filter_fork.h"
 
+#define MAX_ARGS 256
+
 pid_t
 __archive_create_child(const char *path, int *child_stdin, int *child_stdout)
 {
 	pid_t child;
 	int stdin_pipe[2], stdout_pipe[2], tmp;
+	char *child_argv[MAX_ARGS + 1];
+	char *cmdlin;
+	int cmdlin_i = 0, argv_i = 1, break_argv = 0;
 
 	if (pipe(stdin_pipe) == -1)
 		goto state_allocated;
@@ -94,7 +102,24 @@ __archive_create_child(const char *path,
 			_exit(254);
 		if (stdout_pipe[1] != 1 /* stdout */)
 			close(stdout_pipe[1]);
-		execlp(path, path, (char *)NULL);
+		if ((cmdlin = strdup(path)) == NULL)
+			_exit(254);
+		child_argv[0] = cmdlin;
+		while (cmdlin[cmdlin_i]) {
+			if (0x20 == cmdlin[cmdlin_i]) {
+				cmdlin[cmdlin_i] = '\0';
+				break_argv = 1;
+			} else if (break_argv) {
+				break_argv = 0;
+				child_argv[argv_i] = cmdlin + cmdlin_i;
+				argv_i++;
+			}
+			if (argv_i >= MAX_ARGS)
+				break;
+			cmdlin_i++;
+		}
+		child_argv[argv_i] = NULL;
+		execvp(child_argv[0], child_argv);
 		_exit(254);
 	default:
 		close(stdin_pipe[0]);

追記
返事きた。はえーなー。


Thank you very much.

I think this is too simple. Parsing command lines
has complex rules about \, ", and other special
characters. I would prefer that you:
* Check for special characters
(space, tab, \, ", ', &, >, <, maybe others)
* If there are none, use execlp(path, path, NULL);
* If there are special characters, use execvp("/bin/sh", child_argv)
where child_argv has "/bin/sh", "-c", and path.

Does this make sense? This will handle simple commands
like "lzop -dc" and also more complex commands like:
"uudecode -p | lzop -dc | decrypt --key 'password'".

Cheers,

Tim

まあ、シンプルすぎますね。
でも、unlzopみたいなコマンドがないんだよー。