#!/bin/bash # # Demo of a shell frontend that communicates with a xorriso slave via # two named pipes. # # This script creates two named pipes and starts xorriso with command # -named_pipes_loop cleanup /tmp/xorriso_stdin_pipe_$$ xorriso_stdin_pipe_$$ - # Its main loop prompts the user for commands, sends them to xorriso, # receives the replies, and parses them by xorriso command # -msg_op parse_silently. The resulting words are printed to stdout. # # xorriso removes the two pipes when it finishes execution of -named_pipes_loop # regularly. (E.g. because of commands -end or -rollback_end or because of # name loop control message "end_named_pipe_loop".) # The vanishing of the pipe files tells this script that xorriso is gone. # # # Copyright (C) 2013 # Thomas Schmitt , libburnia-project.org # Provided under BSD license: Use, modify, and distribute as you like. # # What xorriso program to use xorriso=xorriso if test o"$1" = o"-xorriso" then xorriso="$2" fi # Version of xorriso and minimum requirement by this script export xorriso_version= export xorriso_version_req=1.3.1 # Info about the xorriso slave process export xorriso_is_running=0 export xorriso_pid=0 export xorriso_will_end=0 # Will be set to 1 before this script ends normally export normal_end=0 # ---------------- An interpreter for quoted xorriso replies ---------------- # xorriso commands like -lsl wrap filenames into quotation marks in order # to unambiguously represent any character byte except the 0-byte. # This piece of code parses input strings into words by letting xorriso # command -msg_op "parse_silently" do the hard work. # The input strings should be composed by concatenating input lines with # newline characters between them. Begin by submitting a single line (without # newline at its end) and retry with an appended further line, if # xorriso_parse # returns 1. See below xorriso_cmd_and_handle_result() for an example. # The parsed reply words. # Valid are reply_array[0] to reply_array[reply_count-1)] export reply_array export reply_count # Interpret reply of -msg_op parse xorriso_recv_parse_reply() { reply_count=0 unset reply_array export reply_array ret=-1 read ret if test "$ret" -lt 0 -o -z "$ret" then echo "Unexpected text as first reply line of -msg_op parse" >&2 xorriso_is_running=0 return 2 fi test "$ret" = 0 && return "1" read num_strings string_count=0 while true do test "$string_count" -ge "$num_strings" && break read num_lines line_count=0 acc= while true do test "$line_count" -ge "$num_lines" && break read line test "$line_count" -gt 0 && acc="$acc"$'\n' acc="$acc""$line" line_count=$(($line_count + 1)) done reply_array["$string_count"]="$acc" string_count=$(($string_count + 1)) done reply_count="$num_strings" return 0 } # Parse a quoted multi-line string into words xorriso_parse() { # $1 : The string which shall be parsed # $2 : The number of concatenated input lines (= number of newlines + 1) # return: 0= array is valid , 1= line incomplete , 2= other error test "$xorriso_is_running" = 0 && return 1 xorriso_send_cmd "msg_op parse_silently "'"'"'' '' 0 0 $2"'"'$'\n'"$1" || \ return 2 xorriso_recv_parse_reply <"$result_pipe" || xorriso_is_running=0 ret=$? test "$xorriso_is_running" = 0 && ret=2 return "$ret" } # ------------- End of interpreter for quoted xorriso replies -------------- # Send one or more command lines to xorriso xorriso_send_cmd() { # $1 : the lines to send # >>> is it possible to have a timeout on echo ? if test -p "$cmd_pipe" then echo -E "$1" >"$cmd_pipe" else xorriso_is_running=0 return 1 fi } # Make filenames safe for transport by wrapping them in quotes and # escaping quotes in their text xorriso_esc() { echo -n "'" echo -n "$1" | sed -e "s/'/'"'"'"'"'"'"'/g" echo -n "'" } # A handler function for xorriso_cmd_and_handle_result xorriso_reply_to_stdout() { echo "${reply_array[*]}" } # Let a handler inspect the result lines of a xorriso command line xorriso_cmd_and_handle_result() { # $1: handler command word and possibly argument words # $2: command line for xorriso if test "$xorriso_is_running" = 0 then return 1 fi handler="$1" xorriso_send_cmd "$2" || return 1 res=$(cat "$result_pipe") ret=$? if test "$xorriso_will_end" = 1 -o "$xorriso_is_running" = 0 -o "$ret" -ne 0 then test -n "$res" && echo -n "$res" xorriso_is_running=0 test "$ret" = 0 || return 1 return 0 fi test -z "$res" && return 0 echo "$res" | \ while read line do line_count=1 while true do xorriso_parse "$line" "$line_count" ret=$? test "$ret" = 0 && break if test "$ret" = 2 then return 1 fi read addon line="$line"$'\n'"$addon" line_count=$(expr "$line_count" + 1) done # One can now make use of reply_array[0...(reply_count-1)] $handler done return 0 } # Execute -version and let xorriso_version_handler interpret reply xorriso_check_version() { lookfor='^xorriso version : ' xorriso_version=$("$xorriso" -version 2>/dev/null | grep "$lookfor" | \ sed -e "s/${lookfor}//") ret=$? if test "$ret" -ne 0 -o "$xorriso_version" = "" then echo "SORRY: Program run '${xorriso}' -version did not yield a result." >&2 echo >&2 exit 2 fi smallest=$((echo "$xorriso_version_req" ; echo "$xorriso_version" ) | \ sort | head -1) test "$smallest" = "$xorriso_version_req" && return 0 echo "SORRY: xorriso version too old: ${xorriso_version} . Need at least xorriso-${xorriso_version_req} ." >&2 echo >&2 exit 2 } # To be executed on exit xorriso_cleanup() { send_end_cmd=0 if test -p "$cmd_pipe" -a "$xorriso_is_running" = 1 then if test "$normal_end" = 0 then echo "Checking whether xorriso is still running ..." >&2 set -x # Give xorriso time to abort sleep 1 if ps | grep '^'"$xorriso_pid" >/dev/null then # >>> try to further confirm xorriso identity send_end_cmd=1 fi else send_end_cmd=1 fi fi test "$normal_end" = 0 && set -x if test "$send_end_cmd" = 1 then echo "Sending xorriso an -end command ..." >&2 xorriso_send_cmd "end" && \ test -p "$result_pipe" && cat "$result_pipe" >/dev/null fi test -p "$cmd_pipe" && rm "$cmd_pipe" test -p "$result_pipe" && rm "$result_pipe" } # ---------------------------------- main --------------------------------- # Choose pipe names export cmd_pipe=/tmp/xorriso_stdin_pipe_$$ export result_pipe=/tmp/xorriso_stdout_pipe_$$ # Check the program whether it is modern enough xorriso_check_version "$xorriso" # Prepare for then end of this script trap xorriso_cleanup EXIT # Create the pipes and start xorriso mknod "$cmd_pipe" p mknod "$result_pipe" p "$xorriso" -abort_on NEVER -for_backup \ -named_pipe_loop cleanup:buffered "$cmd_pipe" "$result_pipe" "-" & xorriso_pid=$! xorriso_is_running=1 # Get a sign of life from xorriso before issuing the loop prompt xorriso_cmd_and_handle_result xorriso_reply_to_stdout \ "print_info 'xorriso process ${xorriso_pid} started by $0'" echo >&2 # Now get commands from the user, send them to xorriso and display them # via the simple handler xorriso_reply_to_stdout() while test "$xorriso_is_running" = 1 do if test -p "$cmd_pipe" then echo -n "xorriso> " >&2 else echo "$0 : Lost contact to xorriso process $xorriso_pid" >&2 xorriso_is_running=0 break fi read line if echo "$line" | grep '^-*end$' >/dev/null then break fi if echo "$line" | grep '^-*rollback_end$' >/dev/null then xorriso_will_end=1 fi xorriso_cmd_and_handle_result xorriso_reply_to_stdout "$line" done # Prevent set -x in the exit handler normal_end=1