diff --git a/libisoburn/trunk/Makefile.am b/libisoburn/trunk/Makefile.am index 510150a6..937fe7b3 100644 --- a/libisoburn/trunk/Makefile.am +++ b/libisoburn/trunk/Makefile.am @@ -244,6 +244,7 @@ EXTRA_DIST = \ doc/partition_offset.wiki \ doc/qemu_xorriso.wiki \ doc/startup_file.txt \ + test/frontend_pipes_xorriso.c \ README \ AUTHORS \ CONTRIBUTORS \ diff --git a/libisoburn/trunk/test/frontend_pipes_xorriso.c b/libisoburn/trunk/test/frontend_pipes_xorriso.c new file mode 100644 index 00000000..a4d47ea2 --- /dev/null +++ b/libisoburn/trunk/test/frontend_pipes_xorriso.c @@ -0,0 +1,230 @@ + +/* Beefed-up example from man 2 pipe + to illustrate how xorriso is to be used by frontend programs via two pipes. + + Build: + cc -g -o frontend_pipes_xorriso frontend_pipes_xorriso.c + + Usage: + ./frontend_pipes_xorriso [path_to_xorriso_binary] + +*/ + +#include +#include +#include +#include +#include +#include + + +/* Local helpers of parent process */ +int await_all_replies(int fd, char *pending_mark); +int prompt_for_command(char *line, int line_size); + + +/* Parent and child */ +int main(int argc, char *argv[]) +{ + int command_pipe[2], reply_pipe[2]; + pid_t cpid; + char *xorriso_path = "/usr/bin/xorriso"; + + if (argc > 1) + xorriso_path = argv[1]; + + if (pipe(command_pipe) == -1) + { perror("pipe"); exit(1); } + if (pipe(reply_pipe) == -1) + { perror("pipe"); exit(1); } + + cpid = fork(); + if (cpid == -1) + { perror("fork"); exit(2); } + + if (cpid == 0) { + /* Child redirects stdin and stdout. Then it becomes xorriso. */ + + char *xargv[8]; + + close(command_pipe[1]); /* Close unused write end */ + close(reply_pipe[0]); /* Close unused read end */ + + /* Attach pipe ends to stdin and stdout */ + close(0); + if (dup2(command_pipe[0], 0) == -1) + { perror("dup2(,0)"); exit(1); } + close(1); + if (dup2(reply_pipe[1], 1) == -1) + { perror("dup2(,1)"); exit(1); } + + xargv[0] = xorriso_path; + xargv[1] = "-dialog"; + xargv[2] = "on"; + xargv[3] = "-pkt_output"; + xargv[4] = "on"; + xargv[5] = "-mark"; + xargv[6] = "0"; /* corresponds to mark_count = 0 in parent */ + xargv[7] = NULL; + execv(xorriso_path, xargv); + perror("execv"); exit(1); + + } else { + /* Parent prompts user for command lines and prints xorriso replies. + It knows when all reply text of the pending command line has arrived + by watching for -mark reply pending_mark. + */ + + int mark_count = 0, ret; + char pending_mark[16], line[4096]; + + close(command_pipe[0]); /* Close unused read end */ + close(reply_pipe[1]); /* Close unused write end */ + + /* Dialog loop */ + sprintf(pending_mark, "%d", mark_count); + while (1) { + + /* Wait for pending mark and print all replies */ + ret = await_all_replies(reply_pipe[0], pending_mark); + if (ret < 0) + break; + + /* Prompt for command line */ + ret = prompt_for_command(line, sizeof(line)); + if (ret <= 0) + break; + + /* Send line and -mark command */ + ret = write(command_pipe[1], line, strlen(line)); + if (ret == -1) { + perror("write"); + break; + } + /* Produce new unique -mark text to watch for */ + mark_count++; + sprintf(pending_mark, "%d", mark_count); + sprintf(line, "-mark %s\n", pending_mark); + ret = write(command_pipe[1], line, strlen(line)); + if (ret == -1) { + perror("write"); + break; + } + } + + + /* >>> if child is still operational: send -rollback_end */; + + /* >>> wait a short while */; + + /* >>> if not yet ended: kill child */; + + wait(NULL); /* Wait for child */ + exit(0); + } +} + + +/* Local helpers of parent process */ + + +int await_all_replies(int fd, char *pending_mark) +{ + int count, remainder = 0; + char buf[32769], *line, *npt; + + while (1) { + count = read(fd, buf + remainder, sizeof(buf) - 1 - remainder); + if (count == -1) { + perror("read"); + return(-1); + } + if (count == 0) { + fprintf(stderr, "+++ EOF encounterd by Master process\n"); + return(-2); + } + for (npt = buf + remainder; npt < buf + count; npt++) { + if (*npt == 0) { + fprintf(stderr, + "+++ Protocol error : Reply contains 0-chars\n"); + return(-1); + } + } + + /* Split buf into lines */ + buf[remainder + count] = 0; /* for convenience */ + line = buf; + while (1) { + npt = strchr(line, '\n'); + if (npt == NULL) { + /* Move line to start of buffer and set remainder */ + if (line != buf) { + remainder = 0; + for (npt = line; *npt; npt++) + buf[remainder++] = *npt; + } + /* Now read more data in the hope to get a newline char */ + break; + } + /* Interpret line */ + *npt = 0; + if (line[0] == 'M') { + /* M-replies will be outdated until the pending command line + is completely done and the appended -mark command gets + into effect. + */ + if (strlen(line) < 6) { + fprintf(stderr, + "+++ Protocol error : M-channel line shorter than 6 chars\n"); + return(-1); + } + if (strcmp(line + 5, pending_mark) == 0) { + if ((line - buf) + strlen(line) + 1 < count) { + fprintf(stderr, + "+++ Protocol error : Surplus reply data after M-match\n"); + fprintf(stderr, "%s\n", line + strlen(line) + 1); + return(-1); + } + return (1); /* Expected mark has arrived */ + } + } else if (line[0] == 'R') { + /* R-replies are result lines of inquiry commands, like -ls. + They should be handled by specialized code which knows + how to parse and interpret them. + */ + printf("%s\n", line); + } else { + /* I-replies are pacifiers, notifications, warnings, or + error messages. They should be handled by a general + message interpreter which determines their severity + and decides whether to bother the user. + */ + fprintf(stderr, "%s\n", line); + } + line = npt + 1; + } + } + return(1); +} + + +int prompt_for_command(char *line, int line_size) +{ + int l; + char *line_res; + + fprintf(stderr, "+++ Enter a command and its parameters :\n"); + line_res = fgets(line, line_size - 1, stdin); + if (line_res == NULL) + return(0); + l = strlen(line); + if (l == 0) { + line[0] = '\n'; + line[1] = 0; + } else if (line[l - 1] != '\n') { + line[l] = '\n'; + line[l + 1] = 0; + } + return(1); +} + diff --git a/libisoburn/trunk/xorriso/make_xorriso_standalone.sh b/libisoburn/trunk/xorriso/make_xorriso_standalone.sh index c1edf10e..7f24f2c9 100755 --- a/libisoburn/trunk/xorriso/make_xorriso_standalone.sh +++ b/libisoburn/trunk/xorriso/make_xorriso_standalone.sh @@ -231,7 +231,8 @@ copy_files doc/partition_offset.wiki \ create_dir "$lone_dir"/test copy_files \ test/compare_file.c \ - "$lone_dir"/test/compare_file.c + test/frontend_pipes_xorriso.c \ + "$lone_dir"/test # releng diff --git a/libisoburn/trunk/xorriso/xorriso_makefile_am.txt b/libisoburn/trunk/xorriso/xorriso_makefile_am.txt index 5957a3e6..e02ba305 100644 --- a/libisoburn/trunk/xorriso/xorriso_makefile_am.txt +++ b/libisoburn/trunk/xorriso/xorriso_makefile_am.txt @@ -1,5 +1,5 @@ -# Copyright (c) 2007 - 2010 Thomas Schmitt +# Copyright (c) 2007 - 2012 Thomas Schmitt # Provided under GPL version 2 or later. # ts A90315 : LIBBURNIA_PKGCONFDIR is defined OS specific in acinclude.m4 @@ -328,6 +328,7 @@ EXTRA_DIST = \ doc/susp_aaip_isofs_names.txt \ doc/zisofs_format.txt \ doc/startup_file.txt \ + test/frontend_pipes_xorriso.c \ libisofs/aaip-os-dummy.c \ libisofs/aaip-os-linux.c \ libisofs/aaip-os-freebsd.c \ diff --git a/libisoburn/trunk/xorriso/xorriso_timestamp.h b/libisoburn/trunk/xorriso/xorriso_timestamp.h index 6bb697c4..f7aff236 100644 --- a/libisoburn/trunk/xorriso/xorriso_timestamp.h +++ b/libisoburn/trunk/xorriso/xorriso_timestamp.h @@ -1 +1 @@ -#define Xorriso_timestamP "2012.09.08.181144" +#define Xorriso_timestamP "2012.09.09.181723"