PROGRAM GEManage;

USES Crt,Ramon,Fido;

{$L pascal.obj}

const
   REMOVED  = $0010;  (* Area should be removed by GSETUP Pack *)
   MAXSYSTEMS = 350;    (* Systems per area *)

type
   ADDRESS = record
      zone  : word;
      net   : word;
      node  : word;
      point : word;
   end;

type
   EXPORTENTRY = record
      address : ADDRESS;
      status  : byte;
   end;

type
   AREAFILE_HDR = record
      hdrsize : word;  (* sizeof(AREAFILE_HDR) *)
      recsize : word;  (* Size of an area file record, excluding exportlist *)
      systems : word;  (* Number of entries in the export list (1-MAXSYSTEMS) *)
   end;

type
   Arr51 = array[1..51] of char;
   Arr61 = array[1..61] of char;

   AREAFILE_GE = record
      name         : Arr51;  (* AREA tag, must be uppercase, no spaces *)
      comment      : Arr61;  (* Description of the topics discussed in area *)
      path         : Arr51;  (* Location where *.MSG files are stored *)
      originline   : Arr61;  (* Custom origin line, used if origlinenr = 0 *)
      areanumber   : word;   (* Area number 1-MAXAREAS, 1-200 = Hudson *)
      group        : char;   (* Group (A-Z) *)
      options      : word;   (* See --- Area options bits *)
      originlinenr : byte;   (* Origin line (1-20, 0 = custom) *)
      pkt_origin   : byte;   (* Address for the packet/Origin line (0-10) *)
      seenbys      : word;   (* Addresses (bits 0-10) to add to the SEEN-BY *)
      reserved     : word;
      msgs         : word;   (* Maximum number of messages       (MBUTIL Purge) *)
      days         : word;   (* Maximum age of non-Rcvd messages (MBUTIL Purge) *)
      rcvddays     : word;   (* Maximum age of Rcvd messages     (MBUTIL Purge) *)
      areatype     : byte;   (* See --- Area type *)
   end;

   stringptr = ^string;

var fidonode : fidoaddrtype;
    nodestr : fidoaddrstring;
    newlist : array[1..3000] of stringptr;

procedure c2p(dest : string ; src : pointer; max : byte); external;
procedure p2c(dest : pointer; src : string ; max : byte); external;

Var AreaFileGE : FILE;
    AreaHdr     : AREAFILE_HDR;
   result      : word;
   arearecsize : word;
   records     : word;
   counter     : word;
   AreaFile    : AREAFILE_GE;
   buffer      : string[255];

procedure openareafile;
begin
{$I-}
   assign(AreaFileGE, 'AREAFILE.GE');
   reset(AreaFileGE, 1);
{$I+}
   if IOresult <> 0 then
   begin
      writeln (Output,'Unable to open AREAFILE.GE');
      Close (Output);
      halt(255);
   end;
   blockread(AreaFileGE, AreaHdr, sizeof(AREAFILE_HDR), result);
   if result < sizeof(AREAFILE_HDR) then
   begin
      writeln(Output,'Error reading AREAFILE header');
      close (areafileGE);
      Close (output);
      halt(255)
   end;

   if AreaHdr.recsize < sizeof(AREAFILE_GE) then
   begin
      writeln(Output,'Incompatible AREAFILE record size');
      Close (areafileGE);
      Close (output);
      halt(255)
   end;
end;


PROCEDURE UsedAreas;

VAR

   Outputfile : text;
   Lp         : WORD;
   exportrec  : array[1..50] of exportentry;
   connected  : char;

BEGIN
     OpenAreaFile;

   assign (outputfile,paramstr (3));
   {$I-} rewrite (outputfile); {$I+}
   IF (IOResult <> 0) THEN
   BEGIN
        WriteLn (Output,'Cannot create file: '+ParamStr (3));
        Close (output);
        Halt;
   END;

   writeLn (Output,'Exporting used areas listing for ',Copy (NodeStr,1,Pos ('/',NodeStr)-1),
            ' to ',UpCaseString (ParamStr (3)));
   if (Pos ('/',paramstr (2)) > 0) then
      writeLn (Output,'Except for ',NodeStr);

   arearecsize := AreaHdr.systems * sizeof(EXPORTENTRY) + AreaHdr.recsize;
   records := (filesize(AreaFileGE) - AreaHdr.hdrsize) div arearecsize;
   for counter := 0 to records-1 do
   begin
      seek(AreaFileGE, AreaHdr.hdrsize + longint(arearecsize) * longint(counter));
      blockread(AreaFileGE, AreaFile, sizeof(AREAFILE_GE), result);
      if result = sizeof(AREAFILE_GE) then
      begin
         if (AreaFile.options and REMOVED) = 0 then
         begin
              blockread (areafilege,exportrec,50*sizeof (exportentry));
              connected:='-';
              for lp:=1 to 50 do
                  if (pos ('/',paramstr (2)) > 0) THEN
                  begin
                       if (exportrec[lp].address.zone = fidonode.zone) and
                          (exportrec[lp].address.net = fidonode.net) and
                          (exportrec[lp].address.node <> fidonode.node) then
                       begin
                            connected:='+';
                            break;
                       end;
                  end else
                  begin
                       if (exportrec[lp].address.zone = fidonode.zone) and
                          (exportrec[lp].address.net = fidonode.net) then
                       begin
                            connected:='+';
                            break;
                       end;
                  end;

              if (connected = '+') then
              begin
                   c2p(buffer, @AreaFile.name, 50);
                   writeln(outputfile,connected+buffer);
                   for lp:=1 to 50 do
                       with exportrec[lp].address do
                       begin
                            if (pos ('/',paramstr (2)) > 0) and
                               (zone = fidonode.zone) and
                               (net = fidonode.net) and
                               (node = fidonode.node) then
                               connected:=' ';

                            if (connected = '+') then
                               if (zone = fidonode.zone) and
                                  (net = fidonode.net) then
                                  writeln (outputfile,'  ',zone,':',net,'/',node,'.',point);

                            connected:='+';
                       end;
              end;
         end
      end
   end;
   close(AreaFileGE);

   Close (outputfile);
END;


PROCEDURE ListAreas;

VAR
   Outputfile : text;
   Lp         : WORD;
   exportrec  : array[1..50] of exportentry;
   connected  : char;

BEGIN
     openareafile;

   assign (outputfile,paramstr (3));
   {$i-} rewrite (outputfile); {$I+}
   IF (IOResult <> 0) THEN
   BEGIN
        WriteLn (Output,'Cannot create output file: '+ParamStr (3));
        Close (Output);
        Halt;
   END;

   writeln (Output,'Exporting areas listing for ',NodeStr,' to ',UpcaseString (ParamStr (3)));

   arearecsize := AreaHdr.systems * sizeof(EXPORTENTRY) + AreaHdr.recsize;
   records := (filesize(AreaFileGE) - AreaHdr.hdrsize) div arearecsize;
   for counter := 0 to records-1 do
   begin
      seek(AreaFileGE, AreaHdr.hdrsize + longint(arearecsize) * longint(counter));
      blockread(AreaFileGE, AreaFile, sizeof(AREAFILE_GE), result);
      if result = sizeof(AREAFILE_GE) then
      begin
         if (AreaFile.options and REMOVED) = 0 then
         begin
              blockread (areafilege,exportrec,50*sizeof (exportentry));
              connected:='-';
              for lp:=1 to 50 do
                  if (exportrec[lp].address.zone = fidonode.zone) and
                     (exportrec[lp].address.net = fidonode.net) and
                     (exportrec[lp].address.node = fidonode.node) and
                     (exportrec[lp].address.point = fidonode.point) then
                  begin
                       connected:='+';
                       break;
                  end;

            c2p(buffer, @AreaFile.name, 50);
            writeln(outputfile,connected+buffer);
         end
      end
   end;
   close(AreaFileGE);

   Close (outputfile);
END;


PROCEDURE SetAreas;

type moverec = array[1..sizeof (exportentry)*50] of byte;

VAR
   Inputfile : text;
   connectednr,
   count,
   Lp         : WORD;
   exportrec  : array[1..50] of exportentry;
   connected  : char;

BEGIN
     openareafile;

   assign (inputfile,paramstr (3));
   {$I-} reset (inputfile); {$I+}
   IF (IOResult <> 0) THEN
   BEGIN
        writeln (Output,'Cannot open '+UpCaseString (ParamStr (3)));
        close (areafilege);
        Close (output);
        halt (255);
   END;

   writeln (Output,'Updating connected areas for ',NodeStr,' from ',UpcaseString (ParamStr (3)));
   count:=0;
   while (not eof (inputfile)) do
   begin
        readln (inputfile,buffer);
        inc (count);
        getmem (newlist[count],sizeof (buffer)+1);
        newlist[count]^:=buffer;
   end;

   arearecsize := AreaHdr.systems * sizeof(EXPORTENTRY) + AreaHdr.recsize;
   records := (filesize(AreaFileGE) - AreaHdr.hdrsize) div arearecsize;
   for counter := 0 to records-1 do
   begin
      seek(AreaFileGE, AreaHdr.hdrsize + longint(arearecsize) * longint(counter));
      blockread(AreaFileGE, AreaFile, sizeof(AREAFILE_GE), result);
      if result = sizeof(AREAFILE_GE) then
      begin
         if (AreaFile.options and REMOVED) = 0 then
         begin
              blockread (areafilege,exportrec,50*sizeof (exportentry));
              connected:='-';
              for lp:=1 to 50 do
              begin
                   if (exportrec[lp].address.zone = fidonode.zone) and
                      (exportrec[lp].address.net = fidonode.net) and
                      (exportrec[lp].address.node = fidonode.node) and
                      (exportrec[lp].address.point = fidonode.point) then
                      begin
                           connected:='+';
                           connectedNr:=lp;
                           break;
                      end;
              end;

            c2p(buffer, @AreaFile.name, 50);
            for lp:=1 to count do
                if (newlist[lp]^ = newlist[lp]^[1]+buffer) then
                   if (newlist[lp]^[1] <> connected) then
                   begin
                        if (connected = '+') THEN
                        BEGIN
                             Writeln (Output,'Disconnecting '+buffer);
                             if (connectedNr <> 50) then
                             begin
                                  move (moverec (exportrec)[connectedNr*sizeof (exportentry)],
                                        moverec (exportrec)[(connectedNr-1)*sizeof (exportentry)],
                                        sizeof (exportentry)*(50-connectedNr));
                             end;

                             with exportrec[50].address do
                             begin
                                  zone:=0;
                                  net:=0;
                                  node:=0;
                                  point:=0;
                             end;

                             seek (areafilege,AreaHdr.hdrsize + longint(arearecsize) * longint(counter)+sizeof (areafile_ge));
                             blockwrite (areafilege,exportrec,50*sizeof (exportentry));
                        END else
                        BEGIN
                             writelN (Output,'Connecting '+buffer);

                             connectednr:=0;
                             for lp:=1 to 50 do
                                 with exportrec[lp].address do
                                      if (zone+net+node+point = 0) then
                                      begin
                                           connectedNr:=lp;
                                           break;
                                      end;
                             if (connectednr = 0) then
                                writeln (Output,'Cannot connect, call programmer!')
                             else begin
                                  with exportrec[connectednr].address do
                                  begin
                                       zone:=fidonode.zone;
                                       net:=fidonode.net;
                                       node:=fidonode.node;
                                       point:=fidonode.point;
                                  end;
                                  exportrec[connectednr].status:=0; { normal }

                                  seek (areafilege,AreaHdr.hdrsize+longint(arearecsize)*longint(counter)+sizeof(areafile_ge));
                                  blockwrite (areafilege,exportrec,50*sizeof (exportentry));
                             end;
                        end;

                        connected:=' ';
                       break; { uit de for }
                   end else
                       connected:=' ';

            if (connected <> ' ') THEN
               writelN (Output,'!Unknown! ',Newlist[Lp]^);
         end
      end
   end;
   close(AreaFileGE);

   Close (inputfile);
   for lp:=1 to count do
       freemem (newlist[lp],ord (newlist[lp]^[1])+1);
END;


{ main }

VAR Command : STRING;

BEGIN
     Assign (Output,'');
     ReWrite (Output);

     WriteLn (Output,'GE Manager v1.1');
     WriteLn (Output,'(c) Ramon van der Winkel ''93');
     WriteLn (Output);

     IF (ParamCount <> 3) THEN
     BEGIN
          WriteLn (Output,'Usage: GEMANAGE <command> <node> <filename>');
          WriteLn (Output);
          WriteLn (Output,'<command> = LIST - List all areas <node> is [not/]connected to.');
          WriteLn (Output,'            SET  - Adjust connected areas for <node>.');
          WriteLn (Output,'            USED - List all connect by nodes in a certain zone and net.');
          WriteLn (Output,'                   If a node is given, this node is skipped. This way');
          WriteLn (Output,'                   your feed stays out of the list.');
          WriteLn (Output);
          WriteLn (Output,'In both cases <filename> is the name of the input/output file to use.');
          WriteLn (Output);
          WriteLn (Output,'Examples: GEMANAGE LIST 2:512/301 AREAS.LST');
          WriteLn (Output,'          GEMANAGE SET 2:512/301 AREAS.LST');
          WriteLn (Output,'          GEMANAGE USED 60:100 USED.LST');
          WriteLn (Output,'          GEMANAGE USED 60:100/0 USED.LST');
          WriteLn (Output);
          WriteLn (Output,'The first 50 nodes per area are looked into only!');
          Close (output);
          Halt;
     END;

     Command:=UpCaseString (ParamStr (1));
     fidosplit (paramstr(2),fidonode);
     nodestr:=fido2str (fidonode);

     IF (Command = 'LIST') THEN
     BEGIN
          ListAreas;
          Close (Output);
          Halt;
     END;

     IF (Command = 'SET') THEN
     BEGIN
          SetAreas;
          Close (output);
          Halt;
     END;

     IF (Command = 'USED') THEN
     BEGIN
          UsedAreas;
          Close (output);
          Halt;
     END;

     WriteLn (Output,'Unknown command');
     Close (Output);
END.

