|
|
DataMuseum.dkPresents historical artifacts from the history of: Rational R1000/400 Tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Rational R1000/400 Tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: B T
Length: 16299 (0x3fab)
Types: TextFile
Names: »B«
└─⟦afbc8121e⟧ Bits:30000532 8mm tape, Rational 1000, MC68020_OS2000 7_2_2
└─⟦77aa8350c⟧ »DATA«
└─⟦f794ecd1d⟧
└─⟦this⟧
with Log;
with Machine;
with Byte_Defs;
with Transport;
with Transport_Defs;
with Transport_Name;
with String_Utilities;
with Device_Independent_Io;
procedure Os2000_Transfer
(Local_File : String;
Remote_File : String;
Transliterate : Boolean;
Transfer_Type : Os2000_Transfer_Utilities.Transfer_Type;
Remote_Machine : String;
Response : Profile.Response_Profile) is
subtype Byte is Byte_Defs.Byte;
subtype Byte_String is Byte_Defs.Byte_String;
function "=" (L, R : Byte) return Boolean renames Byte_Defs."=";
package Tp renames Transport;
package Tn renames Transport_Name;
package Td renames Transport_Defs;
package Util renames Os2000_Transfer_Utilities;
package Dio renames Device_Independent_Io;
Handshake_Socket : constant Transport_Defs.Socket_Id := (1, 13);
-- This is the socket on which the OS2000 server will
-- wait for commands. Sockets less than (4,0) are
-- treated as privileged by OS2000 TCP/IP implementation.
--
Long_Time : constant Duration := 300.0; -- 5 minutes
Primary : Tp.Connection_Id;
Secondary : Tp.Connection_Id;
Status : Td.Status_Code;
Count : Natural;
Debug : constant Boolean := Util.Debug;
task Transceiver is
entry Start (Network : Td.Network_Name);
entry Wait_For_Connection;
entry Finish;
end Transceiver;
procedure Put_Debug (Msg : String) is
begin
Log.Put_Line (Msg, Kind => Profile.Debug_Msg, Response => Response);
end Put_Debug;
function Setup_Ax25_Port
(Host : Td.Host_Id; Network : Td.Network_Name) return String is
-- The_Job : constant String := Long_Integer'Image
-- (Long_Integer (Machine.Get_Task_Id));
-- Disable : constant String :=
-- Transport.Set_Options
-- (Network,
-- -- for Ax25 the port number is first byte of host id
-- Context => Integer'Image (Integer (Host (Host'First))),
-- Options => "ENABLED => FALSE");
begin
return Transport.Set_Options
(Network,
-- for Ax25 the port number is first byte of host id
Context => Integer'Image (Integer (Host (Host'First))),
Options => "ENABLED => TRUE," & "PROTOCOL_HALF => DCE");
-- "LEVEL_0 => (TASK =>" & The_Job & ")," &
-- "LEVEL_2 => (MONITOR => TRUE)," &
-- "LEVEL_3 => (MONITOR => TRUE)");
end Setup_Ax25_Port;
-- function Disable_Ax25_Port
-- (Host : Td.Host_Id; Network : Td.Network_Name) return String is
-- begin
-- return Transport.Set_Options
-- (Network,
-- -- for Ax25 the port number is first byte of host id
-- Context => Integer'Image (Integer (Host (Host'First))),
-- Options => "ENABLED => FALSE");
-- end Disable_Ax25_Port;
procedure Transmit (Connection : Tp.Connection_Id; Data : Byte_String) is
Status : Td.Status_Code;
Total : Natural;
Count : Natural;
begin
Tp.Transmit (Connection, Status, Data, Total);
Util.Check_Transmit (Status, Response);
while Total < Data'Length loop
Tp.Transmit (Connection, Status,
Data (Data'First + Total .. Data'Last), Count);
Util.Check_Transmit (Status, Response);
Total := Total + Count;
end loop;
end Transmit;
task body Transceiver is
Status : Td.Status_Code;
Count : Natural;
Total : Natural := 0;
File : Dio.File_Type;
Rws : Natural;
procedure Process_Output_Buffer
(S : in out Byte_String; Count : Natural) is
-- change Lf to Cr on output
begin
for I in S'First .. S'First + Count - 1 loop
if S (I) = Character'Pos (Ascii.Lf) then
S (I) := Character'Pos (Ascii.Cr);
end if;
end loop;
end Process_Output_Buffer;
procedure Process_Input_Buffer
(S : in out Byte_String; Count : Natural) is
-- change Cr to Lf on input
begin
for I in S'First .. S'First + Count - 1 loop
if S (I) = Character'Pos (Ascii.Cr) then
S (I) := Character'Pos (Ascii.Lf);
end if;
end loop;
end Process_Input_Buffer;
begin
begin
accept Start (Network : Td.Network_Name) do
Tp.Open (Secondary, Status, Network);
Util.Check_Open (Status, Response);
if Debug then
Put_Debug ("Transceiver opened.");
end if;
end Start;
if Debug then
Put_Debug ("Transceiver connecting ...");
end if;
Tp.Connect (Secondary, Status);
if Debug then
Put_Debug ("Transceiver connected.");
end if;
accept Wait_For_Connection do
Util.Check_Connect (Status, Response);
end Wait_For_Connection;
exception
when Util.Check_Failed =>
Log.Put_Line
("Transceiver terminating due to Open or Connect failure",
Kind => Profile.Negative_Msg,
Response => Response);
raise;
end;
declare
S : Byte_String (1 .. 1024);
Rf_Status : Util.Remote_File_Status;
begin
Tp.Receive (Secondary, Status, S, Count, Long_Time);
Util.Check_Receive (Status, Response);
Rf_Status := Util.Extract_Status (S (1 .. Count));
case Rf_Status is
when Util.Success =>
null;
when others =>
Log.Put_Line ("OS2000 unable to open file due to " &
Util.Remote_File_Status'Image (Rf_Status),
Kind => Profile.Error_Msg,
Response => Response);
raise Util.No_Remote_File;
end case;
begin
case Transfer_Type is
when Util.Put_Exe | Util.Put_File =>
Dio.Open (File, Dio.In_File, Local_File);
Log.Put_Line ("Opened R1000 file " & Local_File,
Kind => Profile.Positive_Msg,
Response => Response);
when Util.Get_File =>
Dio.Create (File, Dio.Out_File, Local_File);
Log.Put_Line ("Created R1000 file " & Local_File,
Kind => Profile.Positive_Msg,
Response => Response);
end case;
exception
when others =>
Log.Put_Line ("Couldn't open R1000 file " & Local_File,
Kind => Profile.Error_Msg,
Response => Response);
raise Util.No_Local_File;
end;
Rws := 0;
case Transfer_Type is
when Util.Put_Exe | Util.Put_File =>
Count := 0;
while not Dio.End_Of_File (File) loop
Dio.Read (File, S, Count);
if Debug then
Put_Debug ("Number of bytes read: " &
Integer'Image (Count));
end if;
if Transliterate then
Process_Output_Buffer (S, Count);
end if;
if Count = S'Length then
Transmit (Secondary, S);
Rws := Rws + 1;
elsif Count > 0 then
Transmit (Secondary, S (1 .. Count));
Rws := Rws + 1;
else
exit;
end if;
Total := Total + Count;
end loop;
if Transliterate and then (Count > 0) and then
(S (Count) /= Character'Pos (Ascii.Cr)) then
S (S'First) := Character'Pos (Ascii.Cr);
Transmit (Secondary, S (1 .. 1));
Rws := Rws + 1;
end if;
when Util.Get_File =>
loop
Tp.Receive (Secondary, Status, S, Count, Long_Time);
if Count > 0 then
Util.Check_Receive (Status, Response);
if Transliterate then
Process_Input_Buffer (S, Count);
end if;
if Count = S'Length then
Dio.Write (File, S);
else
Dio.Write (File, S (1 .. Count));
end if;
Total := Total + Count;
else
exit;
end if;
end loop;
declare
Excess : Byte_String (1 .. 1);
begin
loop
Tp.Receive (Secondary, Status, Excess, Count);
if Count > 0 then
Log.Put_Line ("Excess data received: " &
Character'Val (Excess (1)),
Kind => Profile.Warning_Msg,
Response => Response);
end if;
exit when not Tp.Is_Connected (Secondary);
end loop;
end;
end case;
if Debug then
Put_Debug ("Number of read/writes: " & Integer'Image (Rws));
end if;
Log.Put_Line ("Number of bytes transferred = " &
Integer'Image (Total),
Kind => Profile.Positive_Msg,
Response => Response);
Dio.Close (File);
Log.Put_Line ("Closed file " & Local_File,
Kind => Profile.Positive_Msg,
Response => Response);
exception
when Util.No_Remote_File | Util.No_Local_File =>
Log.Put_Line ("Transceiver not attempting transfer",
Kind => Profile.Negative_Msg,
Response => Response);
when others =>
Log.Put_Line
("Transceiver got an unexpected exception in transfer.",
Kind => Profile.Exception_Msg,
Response => Response);
end;
Tp.Disconnect (Secondary);
Tp.Close (Secondary);
accept Finish;
exception
when Util.Check_Failed =>
null;
when others =>
Log.Put_Line ("Transceiver got an unexpected exception.",
Kind => Profile.Exception_Msg,
Response => Response);
end Transceiver;
procedure Connect (Connection : Tp.Connection_Id;
Host : Td.Host_Id;
Socket : Td.Socket_Id) is
Retries : constant := 20;
Backoff : constant Duration := 3.0;
Status : Td.Status_Code;
begin
for I in 1 .. Retries loop
Tp.Connect (Connection, Status, Host, Socket);
case Status is
when Td.Not_Initialized | Td.Connection_Refused =>
delay Backoff;
when others =>
exit;
end case;
end loop;
Util.Check_Connect (Status, Response);
end Connect;
begin
declare
Machine : constant String :=
Util.Remote_Machine (Remote_Machine, Response);
Network : constant Td.Network_Name := Util.Network (Machine, Response);
Host : constant Td.Host_Id := Util.Host (Machine, Response);
Is_Ax25 : constant Boolean :=
String_Utilities.Equal
(String (Network), "AX25", Ignore_Case => True);
begin
Log.Put_Line ("Initiating OS2000 transfer to remote machine " &
String_Utilities.Upper_Case (Machine),
Kind => Profile.Positive_Msg,
Response => Response);
if Is_Ax25 then
declare
Result : constant String := Setup_Ax25_Port (Host, Network);
begin
if Result'Length > 0 then
Log.Put_Line ("Ax25 Options rejected: " & Result,
Kind => Profile.Negative_Msg,
Response => Response);
end if;
end;
end if;
begin
Tp.Open (Primary, Status, Network);
Util.Check_Open (Status, Response);
Connect (Primary, Host, Handshake_Socket);
Transceiver.Start (Network);
while not Tp.Is_Connecting_Passive (Secondary) loop
delay 0.5;
end loop;
exception
when Util.Check_Failed =>
Log.Put_Line
("Aborting transfer because Open or Connect failed.",
Kind => Profile.Negative_Msg,
Response => Response);
raise;
when others =>
Log.Put_Line
("Unexpected exception in OS2000 transfer initialization",
Kind => Profile.Exception_Msg,
Response => Response);
raise;
end;
declare
My_Socket : constant Td.Socket_Id := Tp.Local_Socket (Secondary);
begin
if Debug then
Put_Debug ("Secondary local socket = ");
for I in My_Socket'Range loop
Put_Debug (Integer'Image (Integer (My_Socket (I))));
end loop;
end if;
end;
Transmit (Primary, Util.Make_Command
(Tp.Local_Socket (Secondary), Transfer_Type));
if Debug then
Put_Debug ("***TRANSMIT status => " & Td.Image (Status));
end if;
Transceiver.Wait_For_Connection;
declare
Send_Name : Byte_String (Remote_File'First .. Remote_File'Last);
begin
Log.Put_Line ("Requesting OS2000 to open file " &
String_Utilities.Upper_Case (Remote_File),
Kind => Profile.Positive_Msg,
Response => Response);
for I in Remote_File'Range loop
Send_Name (I) := Character'Pos (Remote_File (I));
end loop;
Transmit (Primary, Send_Name);
end;
Transceiver.Finish;
Tp.Disconnect (Primary);
Tp.Close (Primary);
Log.Put_Line ("[OS2000 transfer complete]",
Kind => Profile.Auxiliary_Msg,
Response => Response);
end;
exception
when Util.Remote_Machine_Unknown =>
Log.Put_Line ("Aborting transfer because remote machine unknown",
Kind => Profile.Negative_Msg,
Response => Response);
abort Transceiver;
when Util.Check_Failed =>
abort Transceiver;
when others =>
Log.Put_Line ("Unexpected exception in OS2000 transfer.",
Kind => Profile.Exception_Msg,
Response => Response);
abort Transceiver;
raise;
end Os2000_Transfer;