#!/usr/bin/env ruby # fep.rb -- # simple general purpose front end for line-oriented command. # # Copyright (C) 1998-2006 by Takaaki Tateishi # # USAGE: # do 'fep -h' # # opts.rb -- # parse the options # # Copyright (C) 1999 by Takaaki Tateishi # Time-stamp: <1999-03-21 23:08:38 ttate> # # Example: # 1) $ARGV = ["-b","a","-a","arg1","-h","arg2","arg3"] # opts = OPTS.new($ARGV,{'-a' => 1, '-h' => 0, '-b' => 1}) # opts['-a'] ==> ["arg1"] # opts['-h'] ==> true # opts['-b'] ==> ["a"] # opts[0] ==> "arg2" # opts[1] ==> "arg3" # # 2) $ARGV = ["-a","-b","-c","cmd","-p","1","10","arg"] # opts = OPTS.new($ARGV,{'-a'=>0, '-c'=>1, '-p'=>2}) # opts['-a'] ==> true # opts['-c'] ==> ["cmd"] # opts['-p'] ==> ["1","2"] # opts[0] ==> "-b" # opts[1] ==> "arg" class OPTS attr_reader :opts, :args def initialize(argv=ARGV,opts={}) @opts = {} @args = [] parse(argv,opts) end def OPTS.parse(argv=ARGV,opts={}) OPT.new(argv,opts) end def [](key) case key when Integer @args[key] when String @opts[key] else raise(TypeError,"key must be a integer or string") end end def []=(key,val) case key when Integer @args[key] = val when String @opts[key] = val else raise(TypeError,"key must be a integer or string") end end def parse(argv,opts={}) args = argv.clone while( args[0] ) case (val = opts[args[0]]) when Integer if( val > 0 ) key = args[0] args.shift @opts[key] = [] for i in 1 .. val @opts[key].push(args[0]) args.shift end else @opts[args[0]] = true args.shift end else @args.push(args[0]) args.shift end end end private :parse end ################################################################ print < MSG begin require "readline" rescue LoadError $stderr.print("can't load readline module.\n", "please get and install it.\n") eixt(1) end $opts = OPTS.new(ARGV,{'-L'=>0, '-l'=>1, '-i'=>1, '-o'=>1, '-h'=>0}) if( $opts['-h'] ) $stdout.print <] [-o ] [-l ] -h: this help -i : records inputs into -o : records outputs of into -l : same as '-i' and '-o' MSG exit(0) end if( $opts[0] ) CMD = $opts.args.join(" ") else $stderr.print("you must specify a program and its arguments.\n") exit(1) end $USE_GETS = $opts['-L'] $ILOG_FILE_NAME = $opts['-i'][0] if $opts['-i'] $OLOG_FILE_NAME = $opts['-o'][0] if $opts['-o'] $LOG_FILE_NAME = $opts['-l'][0] if $opts['-l'] $USE_OLOG = ($LOG_FILE_NAME || $OLOG_FILE_NAME) def child_proc(cmd, ioin, ioout) STDOUT.reopen(ioout) if ioout STDIN.reopen(ioin) if ioin begin exec(cmd) rescue $stderr.print("can't execute '#{cmd}'.\n") ensure $pout2.close if $pout2 $pin1.close if $pin1 end end if( $LOG_FILE_NAME ) begin $LOG_FILE = File.open($LOG_FILE_NAME,"w") rescue $stderr.print("can't open the file '#{$LOG_FILE_NAME}'.\n") exit(1) end else $LOG_FILE = nil end if( $ILOG_FILE_NAME ) begin $ILOG_FILE = File.open($ILOG_FILE_NAME,"w") rescue $stderr.print("can't open the file '#{$ILOG_FILE_NAME}'.\n") exit(1) end else $ILOG_FILE = nil end if( $OLOG_FILE_NAME ) begin $OLOG_FILE = File.open($OLOG_FILE_NAME,"w") rescue $stderr.print("can't open the file '#{$OLOG_FILE_NAME}'.\n") exit(1) end else $OLOG_FILE = nil end $pin1,$pout1 = IO::pipe $pin2,$pout2 = IO::pipe if $USE_OLOG $pid = Process.fork{ $pout1.close $pin2.close if $pin2 $ILOG_FILE.close if $ILOG_FILE $OLOG_FILE.close if $OLOG_FILE $LOG_FILE.close if $LOG_FILE child_proc(CMD,$pin1,$pout2) exit(1) } $pin1.close $pout1.sync = true if( $USE_OLOG ) Thread.new{ if( $USE_GETS ) while(str = $pin2.gets) $stdout.print(str) $LOG_FILE.print(str) if $LOG_FILE $OLOG_FILE.print(str) if $OLOG_FILE end else while(str = $pin2.read(1)) $stdout.print(str) $LOG_FILE.print(str) if $LOG_FILE $OLOG_FILE.print(str) if $OLOG_FILE end end $pin2.close if $pin2 $OLOG_FILE.close if $OLOG_FILE } end begin while( line = Readline.readline(" \b", true) ) $pout1.print(line,"\n") $LOG_FILE.print(line,"\n") if $LOG_FILE $ILOG_FILE.print(line,"\n") if $ILOG_FILE end ensure $pout1.close $LOG_FILE.close if $LOG_FILE $ILOG_FILE.close if $ILOG_FILE end