#! /bin/csh -f
#
#  setup a uread fortran program to be resident in memory; manage transfer
#  of command line input to this "server" program
#
#  see the "ichannel" procedure, used to pipe input from files...
#
#  forms of the command:
#
#     uread_server init <dir> <progname> [wait:filename] [prog-input]
#       ...launch a UREAD program <progname>
#
#     uread_server send <dir> [wait:filename] <prog-input>
#       ...send input to previously launched UREAD program
#
#     uread_server kill <dir>
#       ...cause UREAD program to exit
#
#  where:
#    <dir> is the "communications" directory.  If a subdirectory of $cwd
#          then it will be created if necessary; otherwise need prior; 
#          1st argument to "ichannel" launch/pipe procedure.
#    <progname> is the name of the executable program.
#    [wait:filename] wait on appearance of specified file (rel. to $cwd).
#    <prog-input> input line to UREAD program
#
#------------------------------------------------
#
  if ( $#argv < 2 ) then
    echo " ?uread_server: syntax error: too few arguments."
    exit 1
  endif
#
  set action = $1
  shift
#
  if ( "$action" != "init" && "$action" != "send" && "$action" != "kill" ) then
    echo " ?uread_server: invalid 1st argument (action): $action "
    echo "  expected one of: <init|send|kill> "
    exit 1
  endif
#
  set dir = $1
  shift
#
  if ( "$action" == "init" ) then
    if ( ! -d $dir ) then
      mkdir $dir
    endif
  endif
#
  if ( ! -d $dir ) then
    echo " ?uread_server: communications directory not found: $dir "
    exit 1
  endif
#
  if ( "$action" == "kill" ) then
    echo " %uread_server: executing action: $action "
    if ( ! -f $dir/pid.dat ) then
      echo "  NOTE: $dir/pid.dat -- not found. "
    endif
    if ( ! -f $dir/progname.dat ) then
      echo "  NOTE: $dir/progname.dat -- not found. "
    endif
    date > $dir/kill.dat
    rm -f $dir/progname.dat
    exit 0
  endif
#
  if ( "$action" == "init" ) then

    # look for program name

    if ( $#argv < 1 ) then
      echo " ?uread_server(init): program name argument missing "
      exit 1
    else
      set progname = $1
      shift
    endif

    if ( -f $dir/progname.dat ) then
      set old_progname = `cat $dir/progname.dat`
      if ( $old_progname != $progname ) then
        echo " ?uread_server(init): directory $dir in use by $old_progname "
        exit 2
      endif
    else
      echo " %uread_server: $progname communications directory: $dir "
      echo $progname > $dir/progname.dat
    endif

    set test = `which $progname`
    if ( $#test != 1 ) then
      echo " ?uread_server(init): not an executable program: $progname "
      exit 1
    endif

    # see if program is already running as recorded server; if so, kill it...

    if ( -f $dir/pid.dat ) then
      set saved_pid = `cat $dir/pid.dat`
      echo " %uread_server: check prior instance of server, saved_pid: $saved_pid "

      set plist = `ps uxww | grep $progname | awk '{print $2}'`
      echo "  pid list for $progname -- $plist "

      @ i = 0
      while ( $i < $#plist ) 
        @ i++
        if ( "$plist[$i]" == "$saved_pid" ) then
          echo " %uread_server: old running copy of $progname killed. "
	  rm -f $dir/old_kill.dat
          date > $dir/kill.dat
	  @ j = 0
	  while ( $j < 30 )
            @ j++
            if ( ! -f $dir/old_kill.dat ) then
	      echo " trying... "
              sleep 1
	    else
              @ j = 100
            endif
          end
          if ( $j < 100 ) then
            echo " %uread_server: ichannel not responding; direct kill tried."
            kill $saved_pid
            echo " (...delay...) "
            sleep 3
          endif
        endif
      end

    endif
    rm -f $dir/pid.dat

    # (re)launch the program

    if ( -f $dir/input.dat ) then
      mv $dir/input.dat $dir/unused_input.dat
    endif

    if ( -f $dir/$progname.log ) then
      mv $dir/$progname.log $dir/old_$progname.log
    endif

    #------------
    # subprocess LAUNCH

    echo " %uread_server: $progname launched... "

    ichannel $dir | $progname >&! $dir/$progname.log &

    uread_send_wait $dir $dir/pid.dat \*J:\$PID:$dir/pid.dat
    if ( $status ) then
      echo "uread_server: uread_send_wait ERROR"
      exit 1
    endif

    uread_send_wait $dir $dir/input_record.tmi ">$dir/input_record.tmi"
    if ( $status ) then
      echo "uread_server: uread_send_wait ERROR"
      exit 1
    endif

    #------------

  endif

  if ( "$action" == "send" ) then

    if ( $#argv == 0 ) then
      echo " ?uread_server: program input argument(s) missing "
      exit 1
    endif

  endif

  if ( ! -f $dir/progname.dat ) then
    echo " ?uread_server: not found: $dir/progname.dat "
    exit 1
  endif

  #-------------------------------
  # process input...

  if ( $#argv == 0 ) then
    exit 0
  endif

  set wait_file = $dir/prev_input.dat

  set arg1 = $1
  set argtest = `echo $arg1 | sed 's/^wait://'`

  if ( "$arg1" != "$argtest" ) then
    set wait_file = $argtest
    shift

    if ( $#argv == 0 ) then
      echo " ?uread_server: program input argument(s) missing "
      exit 1
    endif

  endif

  echo " %uread_server(debug) : wait_file = $wait_file "
  @ try = 0
  while ( $try < 2 )
    @ try++
    if ( $try > 1 ) then
      echo "TRY = $try"
      echo uread_send_wait $dir $wait_file "$argv"
    endif
    uread_send_wait $dir $wait_file "$argv"
    if ( $status ) then
      echo "uread_server: uread_send_wait ERROR"
#if timeout check if ichannel still running
      set opath=`echo $dir | sed 's#/.*##'`
      set plist=`ps uxw | grep ichannel | grep $dir | awk '{print $2}'`
      if ( $#plist > 0 ) then
#        ichannel-pid is parent of pid.dat 
         @ ipid=`cat $dir/pid.dat` - 1
         set restart=1
         @ i = 0
         while ( $i < $#plist &&  $restart ) 
            @ i++
            if ( "$plist[$i]" == "$ipid" ) then
               restart=0
            endif
         end
      else
         set restart=1
      endif
# If not running try to re-initialize
# use init command stored by trxpl_server in init.cmd   
      if ( $restart ) then
         if ( -f $opath/init.cmd ) then
            mv $dir/lost_pid.dat $dir/lost_pid.dat~ >& /dev/null
            mv $dir/pid.dat $dir/lost_pid.dat >& /dev/null
            set cmd=`cat $opath/init.cmd`
            echo "%uread_server -I- try to re-initialize "
            echo $cmd
	    $cmd
            if ($status ) then
               echo "FAILED"
               exit 1
            else
               echo "%uread_server -I- re-initialized"
	       sleep 1
            endif
         else
            echo "%uread_server -I- $opath/init.cmd is missing"
            echo "                  can not re-initialize"
            exit 1
         endif
      else
         exit 1
      endif
    else
      exit 0
    endif
  end
  exit 0
