%begin
%option "-NOCHECK-NOSTACK-NODIAG-NOLINE"
! Hacked from USEFUL:USERS 26/5/88 JHB

%include "inc:util.imp"
%include "inc:fs.imp"
%include "inc:fsutil.imp"

%constinteger maxfstores=3
%recordformat pcbf(%integer fs, uno, stn, %string (255) user, dir)
%record (pcbf) temp
%record (pcbf) %array pcb(0:64*maxfstores-1)
%string (255) %array new, trace(0:255)

!* next arrays are to contain some filestore specific details
%constant %string(7) %array Fstores (1:maxfstores+1) = %c
                  "Bravo", "Charlie", "Met", "Alpha"
%constant %integer %array nodenum (1:maxfstores+1) = %c
                 16_15, 16_1B, 16_44, 16_14
%integerarray unosa, Unosl, xnosa, Xnosl,Readin(1:maxfstores)
!* array above for location of each filestores $:UNOS/XNOS in system memory
%integer xno=-1

!******************************************************************************
!* Following stolen from EFTP source
!* With some minor mods.... routine connect :== integer function fs connect
!*

%predicate gotack(%integer port)
! Wait for ACK and return TRUE.
! Return FALSE if fed up waiting.
%integer bit,deadline
  bit = 1<<port
  deadline = cputime+2000
  %cycle
    %if ack&bit#0 %start
      %trueif nak&bit=0
      nak = nak!!bit
      %false
    %finish
  %repeatuntil cputime>deadline
  %false
%end

%predicate gotdtx(%integer port)
! Wait for DTX and TRUE.  FALSE when fed up
%integer bit,deadline
  bit = 1<<port
  deadline = cputime+2000
  %cycle
    %trueif dtx&bit#0
  %repeatuntil cputime>deadline
  %false
%end

%integerfunction fs connect(%integer port,node)
! Establish a connection between local port PORT
! and network server NODE providing facility 2 (Filestore)
%string(127)reply
%integer i
%byte facility
{printstring("Attempting to connect port "); phex2(port)
{printstring(" to node "); phex2(node); newline
  facility = 2
  etheropen(port,node<<8)
  etherwrite(port,facility,1)
  %unless gotack(port) %start
    printstring("Node "); phex2(node)
    printstring(" not acknowledging connect request")
    etherclose(port)
    newline
    %result = 0
  %finish
  %unless gotdtx(port) %start
    printstring("Node "); phex2(node)
    printstring(" not responding to connect request")
    etherclose(port)
    newline
    %result = 0
  %finish
  length(reply) = etherread(port,charno(reply,1),127)
  i = charno(reply,length(reply))
  %unless i=nl %and length(reply)=2 %and charno(reply,1)>'0' %start
    printstring("Cannot connect to node "); phex2(node)
    printstring(": ".reply)
    etherclose(port)
    newline %unless i=nl
    %result = 0
  %finish
  i = charno(reply,1)-'0'
  etheropen(port,node<<8+i)
{printstring("Local port "); phex2(port); printstring(" connected to node ")
{phex2(node); printstring(" port "); phex2(i); newline
  %result = 1
%end

%routine disconnect(%integer port)
%byte eot = 12
  %onevent 15 %start
    %return
  %finish
{printstring("Attempting to disconnect port "); phex2(port)
{printstring(" from node "); phex2(s_nodeno); newline
  etherwrite(port,eot,1)
  %unless gotack(port) %start
    printstring("Cannot disconnect port "); phex2(port)
    printstring(" - Nak")
    newline
    %return
  %finish
  etherclose(port)
{printstring("Disconnected port "); phex2(port)
{newline
%end
!*
!* Thats all that was stolen from EFTP
!* That is the last of all the stolen stuff
!******************************************************************************

%routine wait(%integer msec)
   msec = cputime + msec
   %cycle; %repeatuntil cputime>=msec
%end

%integerfn hex2(%string (255) s, %integer i)
   %integer a,b
   a=charno(s,i); a=a-7 %if a>'9'; %if a=' ' %then a=0 %else a=a-'0'
   b=charno(s,i+1); b=b-7 %if b>'9';%if b=' ' %then b=0 %else b=b-'0'
   %result = a<<4+b
%end

%routine Readin Unos and Xnos
!* Reads in the $:UNOS file from the filestores requested.
!* $:UNOS are connected (read in) to the APM and the start address and
!* lengths are saved in an array (see declarations at to of program)
!* for later processing as wanted by user
  %integer i, currentflag, old uno, old port
  %for i = 1,1,maxfstores %cycle
        %if etherstation # nodenum(i) %start
          old uno = user no
          old port = fs port
          user no = 0
          !* only connect to filestore if we are not already connected
          %if fs connect (2,nodenum(i)) # 0 %start
            fs port = 2
            connect file("$:UNOS",0,unosa(i),Unosl(i))
            connect file("$:XNOS",0,xnosa(i),Xnosl(i))
            disconnect(2)
            readin(i) = nodenum(i)
          %finish %else Readin(i) = 0
          fs port = old port
          user no = old uno
        %finish %else %start
          connect file("$:UNOS",0,unosa(i),Unosl(i))
          connect file("$:XNOS",0,xnosa(i),Xnosl(i))
          Readin(i) = nodenum(i)
        %finish
  %repeat
%end

%routine unpack uno file(%integer f)

   %string (255) s
   %integer i, p

   %routine unpack(%string (255) s, %record (pcbf) %name pcb)

     %string(255) %fn str7(%integer i)
        %string (255) t
        %integer j,k
        j=0
        %for k=0, 1, 7 %cycle
           j=j+1 %and charno(t, j) = charno(s, k+i) {%if charno(s, k+i) # ' '}
        %repeat
        length(t) = j
        %result=t
     %end

     pcb_fs=readin(f)
     pcb_uno=f<<6+hex2(s, 6)
     pcb_stn=hex2(s, 10)
     pcb_user=str7(16)
     pcb_dir=str7(24)
   %end

   %routine readlin(%string (255) %name s)
      %integer c
      s=""
      %cycle
         c=byteinteger(p); p=p+1
         %exit %if c<=13
         s=s.tostring(c)
      %repeat
   %end

   %for i=0,1,63 %cycle; pcb(i)_user="-       "; %repeat
   p=unosa(f)
   %cycle
      readlin(s)
      unpack(s, temp)
      pcb(temp_uno) = temp
      %exit %if p>=unosa(f)+unosl(f)
   %repeat
%end

%predicate find(%string (255) text, %string(255) %arrayname list(0:*))
   %integer i
   i=0
   %cycle
      %false %if list(i)=""
      %true %if list(i)=text
      i=i+1
   %repeat
%end

%routine dump xno file (%integer f)
   %string (255) s, text
   %string (255) %array new(0:63)
   %integer uno, l, i, p
   %routine readlin(%string (255) %name s)
      %integer c
      s=""
      %cycle
         c=byteinteger(p); p=p+1
         %exit %if c<=13
         s=s.tostring(c)
      %repeat
   %end

   p = xnosa(f)
   l=0
   %cycle
      readlin(s)
      length(s)=34
      uno = (f<<6+hex2(s,8))&16_FFF
      %if charno(s, 7) = '-' %or uno<0 %or uno>=64*maxfstores %start
         uno=16_FFF; text=" ".s
      %else
         text=" ".pcb(uno)_user." ".s
      %finish
      %unless find(text, trace) %start
         phex2(nodenum((uno>>6)&16_F)); printsymbol(':')
         phex2(uno&16_3F); printline(text)
      %finish
      new(l)=text; l=l+1
      %exit %if p>=xnosa(f)+xnosl(f)
   %repeat

   %for i=0, 1, l-1 %cycle; trace(i)=new(i); %repeat; trace(l)=""
%end

%routine Unos Unos (%integer i)
!* the most primitive (and therefore fast) method of outputing who
!* is logged on... simply dumps the $:UNOS files as read in with no
!* tidying up at all
  %integer j
  printsymbol(byteinteger(j)) %for j=unosa(i),1,unosa(i)+unosl(i)-1
  printsymbol(byteinteger(j)) %for j=xnosa(i),1,xnosa(i)+xnosl(i)-1
%end

  %integer i

!******************************************************************************
!* Main program block
!*
set terminal mode(8)
%cycle
  %for i = 1,1,maxfstores %cycle
    Readin Unos and Xnos
    unpack uno file(i) %if readin(i)#0
  %repeat
  %for i=1,1,maxfstores %cycle
    %if readin(i) # 0 %start
      dump xno file(i)
    %finish
  %repeat
  wait(500)
%repeat

%end %of %program
