#!/bin/bash
#    pc-kc87-fileserver
#Kopplung von PC und KC87 mit Z80-PIO-Interface
#(c)Wolfgang Littke,<WolfgangLittke@web.de>, 4.02.2008
#Das Programm laueft am besten staendig im Hintergrund
#Das Basisverzeichnis ist '/root/pc-kc87'
#Alle anderen Pfadangaben erfolgen dazu relativ.
#Ein existierendes File 'fende.txt' mit beliebigen Inhalt beendet das Programm.
#Weitere Erklaerungen am Fileende.

WD="${HOME}/pc-kc87"
NULF=$(mktemp)
SR="${WD}/server-run.txt"
FE="${WD}/fende.txt"
#Default File-Verzeichnis
FD="${WD}"
#Default Arbeits-Verzeichnis
AD="${WD}"
#Default File-Name
FINA=""
#moegl. Statuswerte :
#  0  Grundzustand
#  1  Daten gueltig bzw. Daten angefordert
#  3  RESET (spaeter)
#  5  Filename fehlt
#  6  File-Eingabe-Fehler
ST=0
#moegl. Kommandostrings :
#  "C(pfad)"  Ausgabe Strings, "..."
#  "D(pfad)"
#  "P(file)"  Eingabe LP,HP,Bytes
#  "G(file)"  Ausgabe LP,HP,Bytes
#  "S(file)"  Eingabe Strings, "..."
#  "A(file)"  Ausgabe Strings, "..."
CS="";
#Kommandozeichen= 1.Buchstabe von CS :
CMD=""
#Parameter= Rest von CS :
PAR=""
ZEI=""
#spezielle Hilfsfunktionen und Variablenfestlegungen einbinden, entspricht 'include':
. pc-kc87.src

#***************************************************
# Hauptprogramm:
pushd ${WD} >${NULF}
#Pruefen, ob das Programm schon laueft:
if [[ -f ${SR} ]];
then
  popd >${NULF}
  exit 0
  :;:;:;
fi
echo "pc-kc87-fileserver: Start" >${SR}
#Kommunikation initialisieren:
kcpreset
while [[ 1 ]] ;
do
  #Der KC87 muss einen Kommandostring senden:
  #Status pruefen:
  ST=$(pstatus)
  if [[ ${ST} -eq 3 ]];
  then
    #RESET , wird spaeter realisiert.
    break;
  fi
  if [[ ${ST} -eq 5 ]];
  then
    #kein Filename , darf hier eigentlich nicht auftreten!.
    break;
  fi
  if [[ ${ST} -eq 6 ]];
  then
    #File-Eingabe-Fehler , darf hier eigentlich nicht auftreten!.
    break;
  fi
  if [[ ${ST} -eq 0 ]];
  then
    #Grundzustand
    continue;
  fi
  if [[ ${ST} -eq 1 ]];
  then
    #Kommandostring holen:
    CS=$(strin)
    ST=$?
    if [[ ${ST} -eq 3 ]];
    then
      break;
    fi
    CMD=${CS:0:1}
    PAR=${CS:1}
    case "${CMD}" in 
    'C')
       #  "C(pfad)"  Ausgabe Strings, "..."
       if [[ "x${PAR}" == "x" ]];
       then
         AD="${WD}"
       else
         AD="${WD}/${PAR}"
       fi
       if [[ ! -d ${AD} ]];
       then
         mkdir --mode=a+rwx ${AD} ;
       fi
       FINA="cat.txt"
       ls -B -C -m -x -w 32 -I .. -I . ${AD} >${FINA} ;
       #Das File FINA ist zeilenweise auszugeben
       #und ein Ende-String anzuhaengen.
       A=""
       if [[ -s ${FINA} ]];
       then
         #Fileinhalt senden:
         A=$(cat ${FINA});
         A=${A// /§}
         A=${A//$'\t'/§}
         #nicht noetig: A=${A//$'\n'/ }
         for X in ${A};
         do
           X=${X//§/ }
           strausgabe "${X}"
           ST=$?
           if [[ ${ST} -eq 3 ]];
           then
             break 2;
           fi
         done ;
       fi
       #Endestring senden:
       strausgabe "..."
       ST=$?
       if [[ ${ST} -eq 3 ]];
       then
         break;
       fi
       preset;
       ST=$?
       if [[ ${ST} -eq 3 ]];
       then
         break;
       fi;
       ;;
    'D')
       #  "D(pfad)"
       if [[ "x${PAR}" == "x" ]];
       then
         FD="${WD}"
       else
         FD="${WD}/${PAR}"
       fi
       if [[ ! -d ${FD} ]];
       then
         mkdir --mode=a+rwx ${FD} ;
       fi
       preset;
       ST=$?
       if [[ ${ST} -eq 3 ]];
       then
         break;
       fi;
       ;;
    'P')
       #  "P(file)"  Eingabe LP,HP,Bytes
       if [[ "x${PAR}" == "x" ]];
       then
         FINA="default.mem"
       else
         FINA="${FD}/${PAR}"
       fi
       if [[ -f ${FINA} ]];
       then
         #das File existiert schon, Backup herstellen
         cp -f ${FINA} "${FINA}~" >>${NULF} ;
       fi
       #codiertes BASIC-File holen:
       kcfin ${FINA}
       ST=$?
       #Status auswerten:
 
       # wandeln in .bas -File

       preset;
       ST=$?
       if [[ ${ST} -eq 3 ]];
       then
         break;
       fi;
       ;;
    'G')
       #  "G(file)"  Ausgabe LP,HP,Bytes
       if [[ "x${PAR}" == "x" ]];
       then
         FINA="default.mem"
       else
         FINA="${FD}/${PAR}"
       fi
       if [[ ! -f ${FINA} ]];
       then
         #codiertes File existiert nicht
         # .bas -File suchen, wandeln
         # sonst ein Minimalfile bereitstellen
         :;:;:;
       fi
       #codiertes BASIC-File ausgeben:
       kcfout ${FINA}
       ST=$?
       #Status auswerten:

       preset;
       ST=$?
       if [[ ${ST} -eq 3 ]];
       then
         break;
       fi;
       ;;
    'S')
       #  "S(file)"  Eingabe Strings, "..."
       if [[ "x${PAR}" == "x" ]];
       then
         FINA="default.txt"
       else
         FINA="${FD}/${PAR}"
       fi
       if [[ -f ${FINA} ]];
       then
         #das File existiert schon, Backup herstellen
         cp -f ${FINA} "${FINA}~" >>${NULF} ;
       fi
       #File holen:
       while [[ 1 ]];
       do
         ZEI=$(strin)
         ST=$?
         if [[ ${ST} -eq 3 ]];then break 2; fi
         if [[ "x${ZEI}" == "x..." ]];
         then
           #Endestring erhalten.
           break;
         fi
         echo -e "${ZEI}" >>${FINA} ;
       done ;
       #Status auswerten:
 
       preset;
       ST=$?
       if [[ ${ST} -eq 3 ]];
       then
         break;
       fi;
       ;;
    'A')
       #  "A(file)"  Ausgabe Strings, "..."
       if [[ "x${PAR}" == "x" ]];
       then
         FINA="default.txt"
       else
         FINA="${FD}/${PAR}"
       fi
       if [[ ! -f ${FINA} ]];
       then
         #Das File existiert nicht
         #default.txt -File suchen, wandeln
         #sonst ein Minimalfile bereitstellen
         :;:;:;
       fi
       #Fileinhalt senden:
       A=$(cat ${FINA});
       A=${A// /§}
       A=${A//$'\t'/§}
       #nicht noetig: A=${A//$'\n'/ }
       for X in ${A};
       do
         X=${X//§/ }
         strausgabe "${X}"
         ST=$?
         if [[ ${ST} -eq 3 ]];
         then
          break 2;
         fi
       done ;
       #Endestring senden:
       strausgabe "..."
       ST=$?
       if [[ ${ST} -eq 3 ]];
       then
         break;
       fi
       preset;
       ST=$?
       if [[ ${ST} -eq 3 ]];
       then
         break;
       fi;
       ;;
#*****Template fuer Erweiterungen:
#     Beispiel-Kommando: X
#    'X')
#      Variable PAR auswerten.
#      Weitere Aktionen SONST-typisch durchfuehren
#      usw.
#      Am Schluss PC auf Eingabe stellen:
#      preset;
#      ST=$?
#      if [[ ${ST} -eq 3 ]];
#      then
#        break;
#      fi;
#      ;;
#*****Ende des Template.
    esac
    #Kommando fertig abgearbeitet
    # *** noch zu behandeln: falsches Kommando ?
    :;:;:;
  fi
  #Pruefen, ob der Fileserver regulaer beendet werden soll
  if [[ -f ${FE} ]];
  then
    rm -f ${FE}
    break;
  fi
  :;:;:;
done
rm -f ${SR}
popd >>${NULF}
rm -f ${NULF}

#+++++++++++++++++++++++++++++
#Pruefen, ob RESET vom HP-Rechner gegeben wurde:
# erst spaeter realisieren:
if [[ ${ST} -eq 3 ]];
then
  sleep 2
  cd ${WD}
#  pc-kc87-fileserver &
  :;:;:;
else
 :;:;:;
fi
#++++++++++++++++++++++++++++++

# ### Notizen ###
#---------------------
#Anfordern des Inhaltsverzeichnissen fuer ein Directory, rekursiv :
#KC87 sendet:
#"C(rel.Pfad)"
#
#PC sendet:
#"(mit 'ls' erzeugte Zeilen)"
#"..." als Ende
#Es werden nur Strings gesendet bzw. empfangen.
#Als Endestring fungiert "..."
#---------------------
#Einstellen des File-Verzeichnisses im PC relativ zum Basisverzeichnis fuer
#nachfolgende File-Operationen 'G'et und 'P'ut :
#KC87 sendet:
#"D(rel.Pfad)"
#Hier ist kein Endestring vorhanden
#
#Der PC sendet nichts.
#Sollte das angegebene Verzeichnis relativ zum Basis-Verzeichnis nicht vorhanden sein, so wird es neu erstellt.
#---------------------
#Eingabe eines codierten BASIC-Files vom KC87 in den PC
#KC87 sendet:
#"P(filename)"
#danach sendet der KC87:
#(Inhalt des codierten BASIC-Files)
#
#Bem.: filename ist mit Erweiterung und ggf. Pfad verstanden.
#
#Das codierte BASIC-File ist ein Binaerfile und enthaelt neben der Byteanzahl den Speicherabzug des BASIC-Programmbereiches im KC87 ab
#Speicheradresse 400H . Dieser Bereich endet, wenn 3-mal das Null-Byte auftritt.
#Das File hat folgenden Aufbau (LP=Low Part und HP=High Part):
#1. Byte:         LP(Anzahl der Bytes des Speicherabzuges)
#2. Byte:         HP(Anzahl der Bytes des Speicherabzuges)
#... alle Bytes des Speicherabzuges ...
#
#[Spaeter erweitert:
#Es wird nach Abschluss der File-Uebertragung ein File mit der zusaetzlichen Namensendung '.bas'
#mit dem normalen BASIC-Quellcode im PC erzeugt .
#]
#--------------------
#Ausgabe eines codierten BASIC-Files vom PC auf den KC87
#KC87 sendet:
#"G(filename)"
#
#PC sendet:
#(Inhalt des codierten BASIC-Files)
#
#[Spaeter erweitert:
#Es wird, wenn kein File existiert, nach einem gleichnamigen File mit der zusaetlichen Endung '.bas'
#gesucht, welches die normale BASIC-Quellcode-Darstellung enthaelt. Existiert dieses, so wird es in
#ein codiertes-File gewandelt und gesendet.
#]
#--------------------
#Zeilen eines Text-Datenfiles als Strings vom PC auf den KC87 uebertragen:
#KC87 sendet:
#"A(filename)"
#PC sendet:
#"(Zeilen des Files)"
#"..." als Ende
#
#Strings mit Text/Daten vom KC87 auf den PC uebertragen und in einem File ablegen:
#KC87 sendet:
#"S(filename)"
#"(Strings)"
#"..." als ende
#
########################
