# encoding: utf-8
=begin

* Name: SiSU

** Description: documents, structuring, processing, publishing, search
*** system environment, resource control and configuration details

** Author: Ralph Amissah
  [ralph@amissah.com]
  [ralph.amissah@gmail.com]

** Copyright: (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
  2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Ralph Amissah,
  All Rights Reserved.

** License: GPL 3 or later:

  SiSU, a framework for document structuring, publishing and search

  Copyright (C) Ralph Amissah

  This program is free software: you can redistribute it and/or modify it
  under the terms of the GNU General Public License as published by the Free
  Software Foundation, either version 3 of the License, or (at your option)
  any later version.

  This program is distributed in the hope that it will be useful, but WITHOUT
  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  more details.

  You should have received a copy of the GNU General Public License along with
  this program. If not, see [http://www.gnu.org/licenses/].

  If you have Internet connection, the latest version of the GPL should be
  available at these locations:
  [http://www.fsf.org/licensing/licenses/gpl.html]
  [http://www.gnu.org/licenses/gpl.html]

** SiSU uses:
  * Standard SiSU markup syntax,
  * Standard SiSU meta-markup syntax, and the
  * Standard SiSU object citation numbering and system

** Hompages:
  [http://www.jus.uio.no/sisu]
  [http://www.sisudoc.org]

** Git
  [http://git.sisudoc.org/gitweb/?p=code/sisu.git;a=summary]
  [http://git.sisudoc.org/gitweb/?p=code/sisu.git;a=blob;f=lib/sisu/se_programs.rb;hb=HEAD]

=end
module SiSU_Sys_Call
  begin
    require 'singleton'
  rescue LoadError
    SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
      error('singleton NOT FOUND (LoadError)')
  end
  class SystemCall
    @@locale_flag=false
    def initialize(input='',output='',opt_or_cmd='')
      @input,@output=input,output
      (opt_or_cmd.is_a?(SiSU_Commandline::Options)) \
      ? (@cmd,@opt=opt_or_cmd.cmd,opt_or_cmd)
      : (@cmd,@opt=opt_or_cmd,nil) #cmd.is_a?(String)
      @prog=SiSU_Env::InfoProgram.new
      @sys=SiSU_Info_Sys::InfoSystem.instance
    end
    def program_found?(program)
      found=`which #{program} 2>&1` #`whereis #{program}`
      (found =~/bin\/#{program}\b/) ? true : false
    end
    def locale                         #locales utf8 or other
      unless @@locale_flag
        @@locale_flag=true
      end
      @sys.locale
    end
    def file_encoding(filename,act='') #file encoding
      program='file'
      fnsp=SiSU_Env::InfoEnv.new(filename).source_file_with_path
      if program_found?(program)
        encoding=%x{file -L #{fnsp}}.strip
        encoding=encoding.gsub(/#{fnsp}:(\s+|$)/,'')
        encoding=if encoding \
        and not encoding.empty?
          encoding
        else 'UTF-8 assumed, encoding undetermined'
        end
        if act[:verbose_plus][:set] ==:on \
        or  act[:maintenance][:set] ==:on
          puts encoding
        end
        encoding
      else
        'UTF-8 assumed, file encoding check program unavailable'
      end
    end
    def wc                             #word count
      program='wc'
      if program_found?(program) \
      and locale !~/utf-?8/i
        true
      else
        program_ref="(not available)" \
          unless program_found?(program)
        program_ref="(UTF-8)" \
          if locale =~/utf-?8/i
        false
      end
    end
    def rcs                            #rcs for document markup data
      program='rcs'
      program_ref="\n\t\tdocument version information requested"
      if program_found?(program); true
      else
        SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
          warn("#{program} is not installed #{program_ref}")
        false
      end
    end
    def cvs                            #cvs for document markup data
      program='cvs'
      program_ref="\n\t\tdocument version information requested"
      if program_found?(program); true
      else
        SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
          warn("#{program} is not installed #{program_ref}")
        false
      end
    end
    def po4a                           #po4a
      program='po4a'
      program_ref="\n\t\tpo4a"
      if program_found?(program); true
      else
        SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
          warn("#{program} is not installed #{program_ref}")
        false
      end
    end
    def zip                            #zip
      program='zip'
      program_ref="\n\t\tused to in the making of number of file formats, odf, epub"
      if program_found?(program); true
      else
        SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
          mark("*WARN* #{program} is not installed #{program_ref}")
        false
      end
    end
    def openssl                        #openssl for digests
      program='openssl'
      program_ref="\n\t\tused to generate requested source document identification digest"
      if program_found?(program); true
      else
        SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
          warn("#{program} is not installed #{program_ref}")
        false
      end
    end
    def md5(filename)                  #md5 dgst
      program='openssl'
      program_ref="\n\t\tmd5 digest requested"
      if program_found?(program)
        pwd=Dir.pwd
        Dir.chdir(File.dirname(filename))
        dgst=%x{openssl dgst -md5 #{File.basename(filename)}}.strip #use file name without file path
        Dir.chdir(pwd)
        dgst.scan(/\S+/)
      else
        SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
          warn("#{program} is not installed #{program_ref}")
        false
      end
    end
    def sha256(filename)               #sha dgst
      program='openssl'
      program_ref="\n\t\tsha digest requested"
      if program_found?(program)
        pwd=Dir.pwd
        Dir.chdir(File.dirname(filename))
        dgst=%x{openssl dgst -sha256 #{File.basename(filename)}}.strip #use file name without file path
        Dir.chdir(pwd)
        dgst.scan(/\S+/)
      else
        SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
          warn("#{program} is not installed #{program_ref}")
        false
      end
    end
    def sha512(filename)               #sha dgst
      program='openssl'
      program_ref="\n\t\tsha digest requested"
      if program_found?(program)
        pwd=Dir.pwd
        Dir.chdir(File.dirname(filename))
        dgst=%x{openssl dgst -sha512 #{File.basename(filename)}}.strip #use file name without file path
        Dir.chdir(pwd)
        dgst.scan(/\S+/)
      else
        SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
          warn("#{program} is not installed #{program_ref}")
        false
      end
    end
    def psql                           #psql
      program='psql'
      program_ref="\n\t\tpsql requested"
      if program_found?(program); true
      else
        SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
          warn("#{program} is not installed #{program_ref}")
        false
      end
    end
    def create_pg_db(dbname_stub=nil)  #createdb
      unless dbname_stub
        @pwd ||=Dir.pwd
        m=/.+\/(?:src\/)?(\S+)/im # m=/.+?\/(?:src\/)?([^\/]+)$/im # m=/.+\/(\S+)/m
        dbname_stub=@pwd[m,1]
      end
      program='createdb'
      db_name="#{Db[:name_prefix]}#{dbname_stub}"
      program_ref="\n\t\tcreatedb dbname #{db_name} #for postgresql database creation"
      (program_found?(program)) \
      ? system("#{program} #{dbname_name}")
      : (STDERR.puts "\t*WARN* #{program} is not available #{program_ref}")
    end
    def relaxng(cmd='')                #trang - convert between different schema languages for XML
      program='trang'
      program_ref="\n\t\tsee <http://www.thaiopensource.com/relaxng/trang.html>"
      (program_found?(program)) \
      ? system("#{program} #{@input} #{@output}")
      : (STDERR.puts "\t*WARN* #{program} is not installed #{program_ref}" if cmd =~/V/)
    end
    def qrencode                       #qrcode - for generating QR code
      program='qrencode'
      program_ref="\n\t\tsee <http://megaui.net/fukuchi/works/qrencode/index.en.html>"
      found=(program_found?(program)) ? true : false
      found \
      ? (system(%{
          echo "#{@input}" | #{program} -s 3 -o #{@output}
        }))
      : (STDERR.puts "\t*WARN* #{program} is not installed #{program_ref}" if @cmd =~/V/)
      #found
    end
    def imagemagick                    #imagemagick is a image manipulation program
      program='identify'
      #program_ref="\n\t\tsee <http://www.imagemagick.org/>"
      found=(program_found?(program)) ? true : false
      #STDERR.puts "\t*WARN* #{program} is not installed #{program_ref}" unless found
      found
    end
    def graphicsmagick                #graphicsmagick is a image manipulation program
      program='gm'
      #program_ref="\n\t\tsee <http://www.graphicsmagick.org/>"
      found=(program_found?(program)) ? true : false
      #STDERR.puts "\t*WARN* #{program} is not installed #{program_ref}" unless found
      found
    end
    def well_formed?                   #tidy - check for well formed xml xhtml etc.
      program=@prog.tidy
      program_ref="\n\t\tsee <http://tidy.sourceforge.net/>"
      (program_found?(program)) \
      ? system("#{@prog.tidy} -xml #{@input} > #{@output}")
      : (STDERR.puts "\t*WARN* #{program} is not installed #{program_ref}")
    end
    def tex2pdf_engine
      progs=['xetex','xelatex','pdflatex','pdfetex','pdftex']
      @pdfetex_flag=false
      @cmd ||=''
      @texpdf=nil
      progs.each do |program|
        if program_found?(program)
          @texpdf=program if program =~/xetex|xelatex|pdftex|pdflatex/
          @pdfetex_flag=true
          break
        end
      end
      if @pdfetex_flag==false
        @texpdf=progs.join(', ')
      end
      @texpdf
    end
    def latex2pdf(md,papersize='a4')   #convert from latex to pdf
      tell=if @cmd =~/[MV]/
        ''
      elsif @cmd =~/[v]/
        %q{2>&1 | grep -v ' WARNING '}
      else %q{2>&1 | grep -v '$'}
      end
      mode='batchmode' #mode='nonstopmode'
      texpdf=tex2pdf_engine
      if @pdfetex_flag
        texpdf_cmd=case texpdf
        when /xetex/
          %{#{texpdf} -interaction=#{mode} -fmt=xelatex -papersize="#{papersize}" #{@input} #{tell}\n}
        when /xelatex/
          %{#{texpdf} -interaction=#{mode} -papersize="#{papersize}" #{@input} #{tell}\n}
        when /pdftex/
          "#{texpdf} -interaction=#{mode} -fmt=pdflatex #{@input} #{tell}\n"
        when /pdflatex/
          "#{texpdf} -interaction=#{mode} #{@input} #{tell}\n"
        end
        system(texpdf_cmd)
      else STDERR.puts "\t*WARN* none of the following programs are installed: #{@texpdf}"
      end
    end
    def makeinfo                       #texinfo
      program='makeinfo'
      options='' #'--force' #''
      program_ref="\n\t\tsee http://www.gnu.org/software/texinfo/"
      (program_found?(program)) \
      ? system("#{program} #{options} #{@input}\n")
      : (STDERR.puts "\t*WARN* #{program} is not installed #{program_ref}")
    end
    def scp
      puts "scp -Cr #{@input} #{@output}" if @cmd =~/[vVM]/
      puts "scp disabled"
    end
    def rsync(action='',chdir=nil)
      program='rsync'
      if program_found?(program)
        vb=if @cmd =~/q/; 'q'
        elsif @cmd =~/v/; 'v'
        else              ''
        end
        cX=SiSU_Screen::Ansi.new(@cmd).cX
        msg=(@cmd =~/q/) ? '' : %{ && echo " #{cX.grey}OK: #{@input} -> #{@output}#{cX.off}"}
        amp=(@opt \
        && @opt.files.length > 1) \
        ? ''
        : ((@cmd =~/[vVM]/) ? '' : '&')
        rsync_cmd="rsync -az#{vb} #{action} #{@input} #{@output}"
        puts rsync_cmd if @cmd =~/[vVM]/
        dir_change=dir_return=nil
        if not chdir.nil? \
        && chdir != Dir.pwd
          dir_change=Dir.chdir(chdir)
          dir_return=Dir.pwd
        end
        dir_change if dir_change
        system("
          #{rsync_cmd} #{msg} #{amp}
        ")
        dir_return if dir_return
      else STDERR.puts "\t*WARN* #{program} not found"
      end
    end
    def rm
      if @cmd =~/^-Z[mMvVq]*$/;      FileUtils::rm_rf(@input)
      elsif @cmd =~/V/;              FileUtils::rm(@input)
      elsif @cmd !~/q/;              FileUtils::rm(@input)
      elsif @cmd =~/q/;              FileUtils::rm(@input)
      else                           STDERR.puts "\t*WARN* operation ignored"
      end
    end
  end
end
module SiSU_Info_Program
  require_relative 'constants'                             # constants.rb
  require_relative 'utils'                                 # utils.rb
  require_relative 'se_info_env'                           # se_info_env.rb
  class InfoProgram < SiSU_Info_Env::InfoEnv               # se_info_env.rb
    attr_accessor :editor,:wc,:tidy,:rexml,:pdflatex,:postgresql,:sqlite
    def initialize
      prog=SiSU_Env::InfoEnv.new.program
      @editor,           @wc,    @tidy,    @rexml,    @pdflatex,    @postgresql,    @sqlite=
        prog.text_editor,prog.wc,prog.tidy,prog.rexml,prog.pdflatex,prog.postgresql,prog.sqlite
    end
  end
end
module SiSU_Info_Set
  require_relative 'se_info_env'                           # se_info_env.rb
  class InfoSettings < SiSU_Info_Env::InfoEnv              # se_info_env.rb
    def permission?(prog)                                  # program defaults
      (defined? @rc['permission_set'][prog]) \
      ? @rc['permission_set'][prog]
      : false
    end
    def program?(prog)                                     # program defaults
      (defined? @rc['program_set'][prog]) \
      ? @rc['program_set'][prog]
      : false
    end
  end
end
__END__
