diff --git a/libisoburn/libisoburn.ver b/libisoburn/libisoburn.ver index 9b3573d6..efd5b321 100644 --- a/libisoburn/libisoburn.ver +++ b/libisoburn/libisoburn.ver @@ -234,6 +234,7 @@ Xorriso_option_move; Xorriso_option_msg_op; Xorriso_option_mvi; Xorriso_option_no_rc; +Xorriso_option_named_pipe_loop; Xorriso_option_not_leaf; Xorriso_option_not_list; Xorriso_option_not_mgt; diff --git a/xorriso/base_obj.c b/xorriso/base_obj.c index f395b15a..f4ead501 100644 --- a/xorriso/base_obj.c +++ b/xorriso/base_obj.c @@ -307,6 +307,7 @@ int Xorriso_new(struct XorrisO ** xorriso,char *progname, int flag) m->hfsplus_hidings= NULL; m->disk_excl_mode= 1; m->use_stdin= 0; + m->tolerate_stdin_eof= 0; m->result_page_length= 0; m->result_page_width= 80; m->mark_text[0]= 0; diff --git a/xorriso/opts_d_h.c b/xorriso/opts_d_h.c index 80734445..87cb2598 100644 --- a/xorriso/opts_d_h.c +++ b/xorriso/opts_d_h.c @@ -2093,6 +2093,9 @@ int Xorriso_option_help(struct XorrisO *xorriso, int flag) " \"parse\"|\"parse_bulk\"|\"compare_sev\"|\"list_sev\" param_text", " Enable, use, or disable message sieve. Or parse lines into", " words. Or compare or list severity names.", +" -named_pipes_loop disk_path_stdin disk_path_stdout disk_path_stderr", +" Enter an EOF resistant dialog loop at a named pipe as input", +" and zero, one or two named pipes as output. \"-\" = no pipe.", " -launch_frontend program [args ...] --", " Start a program, connect its stdin to xorriso stdout and", " stderr, connect its stdout to xorriso stdin.", diff --git a/xorriso/opts_i_o.c b/xorriso/opts_i_o.c index f72b2e64..7a26c2ca 100644 --- a/xorriso/opts_i_o.c +++ b/xorriso/opts_i_o.c @@ -1086,6 +1086,22 @@ ex:; } +/* Option -named_pipe_loop */ +int Xorriso_option_named_pipe_loop(struct XorrisO *xorriso, char *stdin_pipe, + char *stdout_pipe, char *stderr_pipe, + int flag) +{ + char *pipe_paths[3]; + int ret; + + pipe_paths[0]= stdin_pipe; + pipe_paths[1]= stdout_pipe; + pipe_paths[2]= stderr_pipe; + ret= Xorriso_named_pipe_loop(xorriso, pipe_paths, 0); + return(ret); +} + + /* Option -no_rc */ int Xorriso_option_no_rc(struct XorrisO *xorriso, int flag) { diff --git a/xorriso/parse_exec.c b/xorriso/parse_exec.c index a794b2bd..7f806203 100644 --- a/xorriso/parse_exec.c +++ b/xorriso/parse_exec.c @@ -534,7 +534,7 @@ int Xorriso_count_args(struct XorrisO *xorriso, int argc, char **argv, "" }; static char arg3_commands[][40]= { - "append_partition", + "append_partition","named_pipe_loop", "" }; static char arg4_commands[][40]= { @@ -741,7 +741,7 @@ int Xorriso_cmd_sorting_rank(struct XorrisO *xorriso, "dialog", "page", "use_readline", "reassure", "* Support for frontend programs via stdin and stdout (3):", - "launch_frontend", + "launch_frontend", "named_pipe_loop", "* Scripting, dialog and program control features (3):", "rollback_end", "end", @@ -1460,6 +1460,12 @@ next_command:; } else if(strcmp(cmd,"mkdir")==0 || strcmp(cmd,"mkdiri")==0) { ret= Xorriso_option_mkdiri(xorriso, argc, argv, idx, 0); + } else if(strcmp(cmd,"named_pipe_loop")==0) { + (*idx)+= 3; + ret= Xorriso_option_named_pipe_loop(xorriso, arg1, arg2, arg3, 0); + if(ret == 3) + goto ex; + } else if(strcmp(cmd,"no_rc")==0) { ret= Xorriso_option_no_rc(xorriso, 0); diff --git a/xorriso/text_io.c b/xorriso/text_io.c index f350d049..fb8dece4 100644 --- a/xorriso/text_io.c +++ b/xorriso/text_io.c @@ -87,11 +87,14 @@ int Xorriso_dialog_input(struct XorrisO *xorriso, char line[], int linesize, get_single:; #ifdef Xorriso_with_readlinE - if(xorriso->use_stdin || xorriso->dev_fd_1>=0) { + if(xorriso->use_stdin || xorriso->dev_fd_1>=0 || + xorriso->tolerate_stdin_eof) { if(flag&2) {ret= 1; goto ex;} if(Sfile_fgets_n(linept,linesize - base_length - 1, stdin, (xorriso->dialog == 2)) == NULL) { + if(xorriso->tolerate_stdin_eof) + {ret= -2; goto ex;} /* need a very dramatic end */ kill(getpid(),SIGHUP); {ret= -1; goto ex;} @@ -126,6 +129,8 @@ process_single:; {ret= 1; goto ex;} if(Sfile_fgets_n(linept, linesize - base_length - 1, stdin, (xorriso->dialog == 2)) == NULL) { + if(xorriso->tolerate_stdin_eof) + {ret= -2; goto ex;} /* need a very dramatic end */ kill(getpid(),SIGHUP); {ret= -1; goto ex;} @@ -3949,3 +3954,168 @@ ex:; return(ret); } + + +int Xorriso_open_named_pipe(struct XorrisO *xorriso, char fd_names[3][20], + int mem_fds[], char *pipe_paths[], int pipe_fds[], + int i, int flag) +{ + if(mem_fds[i] == -1) + return(2); + pipe_fds[i]= open(pipe_paths[i], i == 0 ? O_RDONLY : O_WRONLY); + if(pipe_fds[i] == -1) { + sprintf(xorriso->info_text, + "-named_pipe_loop: Failed to open %s pipe ", fd_names[i]); + Text_shellsafe(pipe_paths[i], xorriso->info_text, 1); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE",0); + return(0); + } + close(i); + dup2(pipe_fds[i], i); + return(1); +} + + +/* Usage example via bash: + + xorriso_cmd() { + echo "$@" >/u/test/xorriso_stdin + cat tolerate_stdin_eof) { + sprintf(xorriso->info_text, + "Already in -named_pipe_loop. Ignoring further -named_pipe_loop command."); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "SORRY", 0); + return(0); /* intentionally not goto ex */ + } + + Xorriso_alloc_meM(line, char, SfileadrL); + for(i= 0; i < 3; i++ ) + mem_fds[i]= pipe_fds[i]= -1; + + /* Memorize stdin, stdout, and stderr. Close originals. */ + for(i= 0; i < 3; i++ ) { + if(pipe_paths[i][0] == 0 || strcmp(pipe_paths[i], "-") == 0) + continue; + if(stat(pipe_paths[i], &stbuf) == -1) { + sprintf(xorriso->info_text, + "-named_pipe_loop: Cannot determine properties of file "); + Text_shellsafe(pipe_paths[i], xorriso->info_text, 1); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0); + ret= 0; goto ex; + } + if(!S_ISFIFO(stbuf.st_mode)) { + sprintf(xorriso->info_text, + "-named_pipe_loop: File is not a named pipe: "); + Text_shellsafe(pipe_paths[i], xorriso->info_text, 1); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto ex; + } + mem_fds[i]= dup(i); + if(mem_fds[i] == -1) { + sprintf(xorriso->info_text, + "-named_pipe_loop: Cannot duplicate original %s", fd_names[i]); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0); + ret= 0; goto ex; + } + } + + while(1) { + /* Open input pipe */ + ret= Xorriso_open_named_pipe(xorriso, fd_names, mem_fds, pipe_paths, + pipe_fds, 0, 0); + if(ret <= 0) + goto ex; + + /* As long as the input connection exists */ + xorriso->tolerate_stdin_eof= 1; + first_line= 1; + while(1) { + + /* Fetch input line */ + ret= Xorriso_dialog_input(xorriso, line, SfileadrL, 1); + + /* Open output pipes late to allow the sender to open them after + the first (and usually only) input line was transmitted: + echo ... >stdin_pipe + res=$(cat 0) + {ret= hret; goto ex;} + } + } + + /* Now evaluate outcome of Xorriso_dialog_input() */ + if(ret == -2) /* EOF at stdin */ + break; + if(ret <= 0) /* Other error */ + goto ex; + + /* Regular end of command */ + if(strcmp(line, "end_named_pipe_loop") == 0) + {ret= 1; goto ex;} + + /* Perform xorriso command */ + ret= Xorriso_execute_option(xorriso, line, (1 << 16)); + if(ret <= 0) + goto ex; + if(ret == 3) /* e.g. -end command */ + goto ex; + Xorriso_mark(xorriso,0); + } + + /* Restore stdin, stdout and stderr */ + for(i= 0; i < 3; i++) { + if(mem_fds[i] != -1) { + if(pipe_fds[i] != -1) + close(pipe_fds[i]); + pipe_fds[i]= -1; + close(i); + dup2(mem_fds[i], i); + } + } + } + + ret= 1; +ex:; + xorriso->tolerate_stdin_eof= 0; + /* Close any open pipes. Restore stdin, stdout and stderr. */ + for(i= 0; i < 3; i++) { + if(pipe_fds[i] != -1) + close(pipe_fds[i]); + if(mem_fds[i] != -1) { + close(i); + dup2(mem_fds[i], i); + close(mem_fds[i]); + } + } + Xorriso_free_meM(line); + return(ret); +} + + diff --git a/xorriso/text_io.h b/xorriso/text_io.h index b521e93f..ddf957a4 100644 --- a/xorriso/text_io.h +++ b/xorriso/text_io.h @@ -99,5 +99,8 @@ int Xorriso_msg_op_parse_bulk(struct XorrisO *xorriso, int Xorriso_launch_frontend(struct XorrisO *xorriso, int argc, char **argv, char *cmd_pipe_adr, char *reply_pipe_adr, int flag); +int Xorriso_named_pipe_loop(struct XorrisO *xorriso, + char *pipe_paths[3], int flag); + #endif /* ! Xorriso_pvt_textio_includeD */ diff --git a/xorriso/xorriso.1 b/xorriso/xorriso.1 index b94e721f..47d01cc0 100644 --- a/xorriso/xorriso.1 +++ b/xorriso/xorriso.1 @@ -9,7 +9,7 @@ .\" First parameter, NAME, should be all caps .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection .\" other parameters are allowed: see man(7), man(1) -.TH XORRISO 1 "Version 1.3.1, Jun 27, 2013" +.TH XORRISO 1 "Version 1.3.1, Jun 29, 2013" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: @@ -4679,7 +4679,24 @@ Above example "SORRY,UPDATE" will yield 1. .br Print to the result channel a blank separated list of all severity names. Sorted from low to high severity. +.TP +\fB\-named_pipe_loop\fR disk_path_stdin disk_path_stdout disk_path_stderr +Temporarily replace standard input, standard output and standard error by +named pipes. Enter dialog mode without readline. +The three parameters must either be disk paths to existing named pipes, +or be "\-" to leave the according standard i/o channel unreplaced. .br +xorriso will open the stdin pipe, read and execute dialog lines from it +until the sender closes the pipe. Then xorriso will close its side of +the pipes and enter a new cycle of opening, reading and executing. +.br +The output pipes will get opened after the first input line was +read from a freshly opened pipe. This allows the sender to first send +a very long line and to only then open an output pipe for reading the reply. +.br +If an input line consists only of the word "end_named_pipe_loop" +then \-named_pipe_loop will end and further xorriso commands may be +executed from other sources. .TP \fB\-launch_frontend\fR program [arguments ...] -- Start the program that is given as first parameter. Submit the other diff --git a/xorriso/xorriso.h b/xorriso/xorriso.h index f9c4f8ea..4c102698 100644 --- a/xorriso/xorriso.h +++ b/xorriso/xorriso.h @@ -1663,6 +1663,11 @@ int Xorriso_option_msg_op(struct XorrisO *xorriso, char *what, char *arg, int Xorriso_option_mvi(struct XorrisO *xorriso, int argc, char **argv, int *idx, int flag); +/* Option -named_pipe_loop */ +int Xorriso_option_named_pipe_loop(struct XorrisO *xorriso, char *stdin_pipe, + char *stdout_pipe, char *stderr_pipe, + int flag); + /* Command -no_rc */ int Xorriso_option_no_rc(struct XorrisO *xorriso, int flag); diff --git a/xorriso/xorriso.info b/xorriso/xorriso.info index 9c0a845a..2f26cf38 100644 --- a/xorriso/xorriso.info +++ b/xorriso/xorriso.info @@ -4092,6 +4092,24 @@ File: xorriso.info, Node: Frontend, Next: ExDevices, Prev: Scripting, Up: Co *list_sev* Print to the result channel a blank separated list of all severity names. Sorted from low to high severity. + +-named_pipe_loop disk_path_stdin disk_path_stdout disk_path_stderr + Temporarily replace standard input, standard output and standard + error by named pipes. Enter dialog mode without readline. The + three parameters must either be disk paths to existing named pipes, + or be "-" to leave the according standard i/o channel unreplaced. + xorriso will open the stdin pipe, read and execute dialog lines + from it until the sender closes the pipe. Then xorriso will close + its side of the pipes and enter a new cycle of opening, reading + and executing. + The output pipes will get opened after the first input line was + read from a freshly opened pipe. This allows the sender to first + send a very long line and to only then open an output pipe for + reading the reply. + If an input line consists only of the word "end_named_pipe_loop" + then -named_pipe_loop will end and further xorriso commands may be + executed from other sources. + -launch_frontend program [arguments ...] -- Start the program that is given as first parameter. Submit the other parameters as program arguments. Enable xorriso dialog mode. @@ -4837,7 +4855,7 @@ File: xorriso.info, Node: CommandIdx, Next: ConceptIdx, Prev: Legal, Up: Top * -jigdo clears JTE or or adds parameter to JTE: Jigdo. (line 33) * -joliet enables production of Joliet tree: SetWrite. (line 10) * -launch_frontend starts frontend program at pipes: Frontend. - (line 116) + (line 134) * -list_arg_sorting prints sorting order of -x: ArgSort. (line 27) * -list_delimiter replaces '--': Scripting. (line 60) * -list_extras lists compile time extra features: Scripting. @@ -4869,6 +4887,7 @@ File: xorriso.info, Node: CommandIdx, Next: ConceptIdx, Prev: Legal, Up: Top * -msg_op perform operations on program messages: Frontend. (line 30) * -mv renames files in ISO image: Manip. (line 42) * -mv renames single file in ISO image: Manip. (line 35) +* -named_pipe_loop enters EOF resistant dialog: Frontend. (line 117) * -no_rc disables startup files: Scripting. (line 7) * -not_leaf sets exclusion pattern: SetInsert. (line 62) * -not_list sets exclusions from disk file: SetInsert. (line 67) @@ -4891,8 +4910,8 @@ File: xorriso.info, Node: CommandIdx, Next: ConceptIdx, Prev: Legal, Up: Top * -print_info prints message text line: Scripting. (line 102) * -print_mark prints synchronizing text line: Scripting. (line 105) * -print_size predicts image size: Inquiry. (line 91) -* -prog sets program name: Frontend. (line 151) -* -prog_help prints help text: Frontend. (line 154) +* -prog sets program name: Frontend. (line 169) +* -prog_help prints help text: Frontend. (line 172) * -prompt prompts for enter key: Scripting. (line 110) * -publisher sets publisher id: SetWrite. (line 186) * -pvd_info shows image id strings: Inquiry. (line 115) @@ -5008,6 +5027,7 @@ File: xorriso.info, Node: ConceptIdx, Prev: CommandIdx, Up: Top * Dialog, bring text into history, -history: Scripting. (line 44) * Dialog, confirmation question, -reassure: DialogCtl. (line 32) * Dialog, enable dialog mode, -dialog: DialogCtl. (line 7) +* Dialog, EOF resistant, -named_pipe_loop: Frontend. (line 117) * Dialog, line editing, -use_readline: DialogCtl. (line 28) * Dialog, terminal geometry, -page: DialogCtl. (line 19) * Directories, copy, -cp_clone: Insert. (line 192) @@ -5050,7 +5070,7 @@ File: xorriso.info, Node: ConceptIdx, Prev: CommandIdx, Up: Top * Filter, unregister, -unregister_filter: Filter. (line 48) * Filter, zisofs parameters, -zisofs: SetWrite. (line 272) * Frontend program, start at pipes, -launch_frontend: Frontend. - (line 116) + (line 134) * GPT, _definition: Extras. (line 38) * Group, global in ISO image, -gid: SetWrite. (line 268) * Group, in ISO image, -chgrp: Manip. (line 57) @@ -5164,7 +5184,7 @@ File: xorriso.info, Node: ConceptIdx, Prev: CommandIdx, Up: Top * Program, end without writing, -rollback_end: Scripting. (line 159) * Program, list extra features, -list_extras: Scripting. (line 26) * Program, print help text, -help: Scripting. (line 20) -* Program, print help text, -prog_help: Frontend. (line 154) +* Program, print help text, -prog_help: Frontend. (line 172) * Program, print message text line, -print_info: Scripting. (line 102) * Program, print result text line, -print: Scripting. (line 99) * Program, print synchronizing text line, -print_mark: Scripting. @@ -5172,7 +5192,7 @@ File: xorriso.info, Node: ConceptIdx, Prev: CommandIdx, Up: Top * Program, print version, -version: Scripting. (line 23) * Program, prompt for enter key, -prompt: Scripting. (line 110) * Program, replace --, -list_delimiter: Scripting. (line 60) -* Program, set name, -prog: Frontend. (line 151) +* Program, set name, -prog: Frontend. (line 169) * Program, show current settings, -status: Scripting. (line 47) * Program, status history, -status_history_max: Scripting. (line 56) * Program, wait a time span, -sleep: Scripting. (line 114) @@ -5279,28 +5299,28 @@ Node: Restore178554 Node: Emulation185641 Node: Scripting195943 Node: Frontend203100 -Node: Examples211175 -Node: ExDevices212353 -Node: ExCreate213012 -Node: ExDialog214297 -Node: ExGrowing215562 -Node: ExModifying216367 -Node: ExBootable216871 -Node: ExCharset217423 -Node: ExPseudo218244 -Node: ExCdrecord219142 -Node: ExMkisofs219459 -Node: ExGrowisofs220799 -Node: ExException221934 -Node: ExTime222388 -Node: ExIncBackup222847 -Node: ExRestore226827 -Node: ExRecovery227760 -Node: Files228330 -Node: Seealso229629 -Node: Bugreport230352 -Node: Legal230933 -Node: CommandIdx231944 -Node: ConceptIdx248246 +Node: Examples212162 +Node: ExDevices213340 +Node: ExCreate213999 +Node: ExDialog215284 +Node: ExGrowing216549 +Node: ExModifying217354 +Node: ExBootable217858 +Node: ExCharset218410 +Node: ExPseudo219231 +Node: ExCdrecord220129 +Node: ExMkisofs220446 +Node: ExGrowisofs221786 +Node: ExException222921 +Node: ExTime223375 +Node: ExIncBackup223834 +Node: ExRestore227814 +Node: ExRecovery228747 +Node: Files229317 +Node: Seealso230616 +Node: Bugreport231339 +Node: Legal231920 +Node: CommandIdx232931 +Node: ConceptIdx249306  End Tag Table diff --git a/xorriso/xorriso.texi b/xorriso/xorriso.texi index 798a5d1d..a73f0815 100644 --- a/xorriso/xorriso.texi +++ b/xorriso/xorriso.texi @@ -50,7 +50,7 @@ @c man .\" First parameter, NAME, should be all caps @c man .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection @c man .\" other parameters are allowed: see man(7), man(1) -@c man .TH XORRISO 1 "Version 1.3.1, Jun 27, 2013" +@c man .TH XORRISO 1 "Version 1.3.1, Jun 29, 2013" @c man .\" Please adjust this date whenever revising the manpage. @c man .\" @c man .\" Some roff macros, for reference: @@ -5468,7 +5468,26 @@ Above example "SORRY,UPDATE" will yield 1. @* Print to the result channel a blank separated list of all severity names. Sorted from low to high severity. +@c man .TP +@item -named_pipe_loop disk_path_stdin disk_path_stdout disk_path_stderr +@kindex -named_pipe_loop enters EOF resistant dialog +@cindex Dialog, EOF resistant, -named_pipe_loop +Temporarily replace standard input, standard output and standard error by +named pipes. Enter dialog mode without readline. +The three parameters must either be disk paths to existing named pipes, +or be "-" to leave the according standard i/o channel unreplaced. @* +xorriso will open the stdin pipe, read and execute dialog lines from it +until the sender closes the pipe. Then xorriso will close its side of +the pipes and enter a new cycle of opening, reading and executing. +@* +The output pipes will get opened after the first input line was +read from a freshly opened pipe. This allows the sender to first send +a very long line and to only then open an output pipe for reading the reply. +@* +If an input line consists only of the word "end_named_pipe_loop" +then -named_pipe_loop will end and further xorriso commands may be +executed from other sources. @c man .TP @item -launch_frontend program [arguments ...] @minus{}@minus{} @kindex -launch_frontend starts frontend program at pipes diff --git a/xorriso/xorriso_private.h b/xorriso/xorriso_private.h index f56f5e22..c0417f66 100644 --- a/xorriso/xorriso_private.h +++ b/xorriso/xorriso_private.h @@ -572,6 +572,8 @@ struct XorrisO { /* the global context of xorriso */ struct ExclusionS *hfsplus_hidings; int use_stdin; /* use raw stdin even if readline support is compiled */ + int tolerate_stdin_eof; /* Do not abort on EOF in Xorriso_dialog_input + but rather return -2. */ int result_page_length; int result_page_width; char mark_text[SfileadrL]; /* ( stdout+stderr, M: ) */ diff --git a/xorriso/xorriso_timestamp.h b/xorriso/xorriso_timestamp.h index 9f28ab7c..a0ddd61b 100644 --- a/xorriso/xorriso_timestamp.h +++ b/xorriso/xorriso_timestamp.h @@ -1 +1 @@ -#define Xorriso_timestamP "2013.06.27.125407" +#define Xorriso_timestamP "2013.06.30.160008"