|
|
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: 30642 (0x77b2)
Types: TextFile
Names: »B«
└─⟦180fe333a⟧ Bits:30000405 8mm tape, Rational 1000, SW CATALOG, 10_20_0
└─⟦180fe333a⟧ Bits:30000537 8mm tape, Rational 1000, SW Catalog 10_20_0
└─⟦5cb1d1d7f⟧ »DATA«
└─⟦3b1ee7bd8⟧
└─⟦this⟧
with Io;
with Io_Exceptions;
with Device_Independent_Io;
with Terminal_Specific;
with String_Utilities;
with System_Utilities;
with System;
with Operator;
with Editor;
with Terminal;
with Job;
with Debug_Tools;
with Time_Utilities;
with Directory_Tools;
procedure Xmodem is
package Dio renames Device_Independent_Io;
package Tio renames Terminal_Specific;
package Su renames String_Utilities;
package Object renames Directory_Tools.Object;
package Naming renames Directory_Tools.Naming;
package Statistics renames Directory_Tools.Statistics;
package Traversal renames Directory_Tools.Traversal;
package Any_Object renames Directory_Tools.Any_Object;
function "+" (L, R : Dio.Byte) return Dio.Byte renames System."+";
function "*" (L, R : Dio.Byte) return Dio.Byte renames System."*";
function "-" (L, R : Dio.Byte) return Dio.Byte renames System."-";
function "mod" (L, R : Dio.Byte) return Dio.Byte renames System."mod";
function "=" (L, R : Dio.Byte) return Boolean renames System."=";
function Image (N : Integer;
B : Integer := 10;
W : Integer := 1;
Lead : Character := ' ') return String
renames Su.Number_To_String;
type Xmit_Error is (None, Duplicate_Sector, Ignored_Character,
Bad_Sector_Check_Byte, Bad_Sector_Number,
Bad_Checksum, Timeout, No_Nak, No_Ack);
type Write_State is (Start, Text_1, Text_2, Text_3, Text_4, Nulls, Stop);
Error : Xmit_Error := None;
Error_Ring : array (0 .. 19) of Xmit_Error;
Error_Byte : array (0 .. 19) of Integer;
Ring_Ptr : Integer := 0;
Secsiz : constant := 128;
Ttime : constant := 60.0;
Bufsize : constant := Secsiz;
Errormax : constant := 20;
Retrymax : constant := 20;
Nul : constant := Character'Pos (Ascii.Nul);
Soh : constant := Character'Pos (Ascii.Soh);
Eot : constant := Character'Pos (Ascii.Eot);
Ack : constant := Character'Pos (Ascii.Ack);
Nak : constant := Character'Pos (Ascii.Nak);
Space : constant := Character'Pos (' ');
Tilde : constant := Character'Pos ('~');
Lf : constant := Character'Pos (Ascii.Lf);
Cr : constant := Character'Pos (Ascii.Cr);
Bufr : Dio.Byte_String (1 .. Bufsize);
Bytes_Xferred : Integer;
subtype String_Of_One_Byte is Tio.Byte_String (1 .. 1);
Error_Stream : Io.File_Type := Io.Standard_Error;
Output : Dio.File_Type;
Input : Dio.File_Type;
Time_Out : exception;
Term : Terminal.Port := Terminal.Current;
N : Integer;
S : String (1 .. 100);
Status : Object.Error_Code;
procedure Open_Terminal (Terminal : Integer) is
Name : constant String := System_Utilities.Terminal_Name (Terminal);
begin
for I in 1 .. 30 loop
begin
Operator.Disable_Terminal (Terminal);
Dio.Open (Input, Dio.In_File, Name);
exit;
exception
when Io_Exceptions.Use_Error =>
delay (1.0);
end;
end loop;
Dio.Open (Output, Dio.Out_File, Name);
Tio.Input.Flush (Input);
end Open_Terminal;
procedure Close_Terminal (Terminal : Integer) is
begin
Dio.Close (Input);
Dio.Close (Output);
Operator.Enable_Terminal (Terminal);
end Close_Terminal;
procedure Emitt (S : String) is
N : Integer;
begin
Tio.Write (Output, S & Ascii.Cr & Ascii.Lf, N, Duration'Last);
end Emitt;
procedure Emits (S : String) is
begin
Io.Put_Line (Error_Stream, S);
end Emits;
--***********************************************************
-- send char and read char functions for the xmodem function
--***********************************************************
procedure Prompt (P : String; S : out String; Count : out Integer) is
N, M, Actual : Integer;
Inp : String (1 .. S'Length);
Raw : System.Byte_String (1 .. S'Length);
C : Integer := S'First - 1;
begin
Tio.Write (Output, P, Actual, 1.0);
Pole:
loop
Tio.Read (Input, Raw, M, Duration'Last);
for I in 1 .. M loop
if System.">" (Raw (I), 127) then
Inp (I) := '%';
else
Inp (I) := Character'Val (Raw (I));
end if;
Ring_Ptr := (Ring_Ptr + 1) mod 20;
Error_Ring (Ring_Ptr) := None;
Error_Byte (Ring_Ptr) := Integer (Raw (I));
case Inp (I) is
when Ascii.Lf | Ascii.Cr | Ascii.Eot =>
Tio.Write (Output, Ascii.Cr & Ascii.Lf,
N, Duration'Last);
exit Pole;
when Ascii.Bs | Ascii.Del =>
if C >= S'First then
C := C - 1;
end if;
Tio.Write (Output, Ascii.Bs & ' ' & Ascii.Bs,
N, Duration'Last);
when Ascii.Can | Ascii.Nak =>
while C >= S'First loop
Tio.Write (Output, Ascii.Bs & ' ' & Ascii.Bs,
N, Duration'Last);
C := C - 1;
end loop;
when others =>
Tio.Write (Output, Inp (I .. I), N, Duration'Last);
C := C + 1;
S (C) := Inp (I);
end case;
end loop;
end loop Pole;
Count := C;
end Prompt;
procedure Sendchar (Ch : Dio.Byte) is
Actual : Integer;
begin
Tio.Write (Output, String_Of_One_Byte'(1 => Ch), Actual, 30.0);
if Actual = 0 then
raise Time_Out;
end if;
end Sendchar;
function Readchar (Wait : Duration := Duration (Ttime)) return Dio.Byte is
Ch : Dio.Byte_String (1 .. 1);
N : Integer;
begin
Tio.Read (Input, Ch, N, Wait);
if N = 0 then
raise Time_Out;
end if;
return (Ch (1));
end Readchar;
--***********************************
-- xmodem send and recieve functions
--***********************************
procedure Write (Fd : Dio.File_Type;
B : Dio.Byte;
State : in out Write_State;
Null_Count : in out Natural) is
-- The procedure implements a simple state machine necessary to
-- absorb the preamble sent by Xmodem from a Macintosh for text only
-- files. This preamble consists of the tokens:
-- <garbage>TEXT<garbage><29 null characters>
-- All graphic characters following this preamble may be written to an
-- R1000 file, although carriage returns must be translated into
-- linefeeds, in order to follow the R1000 Text_Io conventions for
-- New_Line.
begin
case State is
when Start =>
if B = Character'Pos ('T') then
State := Text_1;
end if;
when Text_1 =>
if B = Character'Pos ('E') then
State := Text_2;
else
State := Start;
end if;
when Text_2 =>
if B = Character'Pos ('X') then
State := Text_3;
else
State := Start;
end if;
when Text_3 =>
if B = Character'Pos ('T') then
State := Text_4;
else
State := Start;
end if;
when Text_4 =>
if B = Character'Pos (Ascii.Nul) then
State := Nulls;
end if;
when Nulls =>
if B = Character'Pos (Ascii.Nul) then
Null_Count := Null_Count + 1;
if Null_Count = 29 then
State := Stop;
end if;
else
State := Text_4;
end if;
when Stop =>
case B is
when Cr =>
Dio.Write (Fd, Ascii.Lf);
when Space .. Tilde =>
Dio.Write (Fd, B);
when others =>
null;
end case;
end case;
end Write;
function Receive (Fd : Dio.File_Type;
Truncate : Boolean := True;
As_Text : Boolean := False) return Xmit_Error is
Sectcurr : Dio.Byte;
Errors : Integer := 0;
Bufptr : Integer := 0;
Sectnum : Integer := 1;
Checksum : Integer;
Error : Xmit_Error := None;
State : Write_State := Start;
Null_Count : Natural := 0;
begin
while Errors < Errormax loop
begin
case Readchar (10.0) is
when Eot =>
if Errors = 0 then
Sendchar (Ack);
if Truncate then
while Bufptr > 0 and then
Bufr (Bufptr) = Nul loop
Bufptr := Bufptr - 1;
Bytes_Xferred := Bytes_Xferred - 1;
end loop;
end if;
if not As_Text then
Dio.Write (Fd, Bufr (1 .. Bufptr));
else
for Index in 1 .. Bufptr loop
Write (Fd, Bufr (Index), State, Null_Count);
end loop;
end if;
return None;
end if;
when Soh =>
Sectcurr := Readchar;
if Sectcurr + Readchar = 255 then
if Integer (Sectcurr) = Sectnum mod 256 then
if Bufptr >= Bufsize then
if not As_Text then
Dio.Write (Fd, Bufr);
else
for Index in Bufr'Range loop
Write (Fd, Bufr (Index),
State, Null_Count);
end loop;
end if;
Bufptr := 0;
end if;
Checksum := 0;
for J in Bufptr + 1 .. Bufptr + Secsiz loop
Bufr (J) := Readchar;
Checksum := Checksum + Integer (Bufr (J));
end loop;
if Dio.Byte (Checksum mod 256) = Readchar then
Errors := 0;
Sectnum := Sectnum + 1;
Bufptr := Bufptr + Secsiz;
Bytes_Xferred := Bytes_Xferred + Secsiz;
Error := None;
else
Error := Bad_Checksum;
end if;
else
Error := Bad_Sector_Number;
end if;
else
Error := Bad_Sector_Check_Byte;
end if;
if Error /= None then
Ring_Ptr := (Ring_Ptr + 1) mod 20;
Error_Ring (Ring_Ptr) := Error;
Error_Byte (Ring_Ptr) := Bytes_Xferred;
if Error > Bad_Sector_Number then
Errors := Errors + 1;
Sendchar (Nak);
end if;
else
Sendchar (Ack);
end if;
when others =>
Ring_Ptr := (Ring_Ptr + 1) mod 20;
Error_Ring (Ring_Ptr) := Ignored_Character;
Error_Byte (Ring_Ptr) := Bytes_Xferred;
end case;
exception
when Time_Out =>
Sendchar (Nak);
end;
end loop;
return Error;
end Receive;
procedure Receive (File : String; From_Mac : Boolean := False) is
Fd : Dio.File_Type;
Forks : Integer := 0;
begin
Bytes_Xferred := 0;
Error := None;
Error_Ring := (others => None);
Error_Byte := (others => 0);
Ring_Ptr := 19;
begin
Dio.Create (Fd, Dio.Out_File, File);
exception
when others =>
Emitt ("Can't create " & File & " (" &
Debug_Tools.Get_Exception_Name & ')');
return;
end;
Emitt ("Ready to receive " & Dio.Name (Fd));
Emitt ("Send three ^D's at end of transmission.");
if not From_Mac then
Error := Receive (Fd, True, False);
else
while Readchar /= Character'Pos (Ascii.Esc) loop
null;
end loop;
while Readchar /= Character'Pos ('a') loop
null;
end loop;
Sendchar (Ack);
Error := Receive (Fd, False, False);
if Error = None then
if Bufr (1 + 86) /= 0 or else Bufr (1 + 85) /= 0 or else
Bufr (1 + 84) /= 0 or else Bufr (1 + 83) /= 0 then
Forks := Forks + 1;
end if;
if Bufr (1 + 90) /= 0 or else Bufr (1 + 89) /= 0 or else
Bufr (1 + 88) /= 0 or else Bufr (1 + 87) /= 0 then
Forks := Forks + 1;
end if;
end if;
for J in 1 .. Forks loop
Error := Receive (Fd, J = Forks, False);
exit when Error /= None;
end loop;
end if;
Tio.Input.Flush (Input);
Dio.Close (Fd);
loop
exit when Readchar = Eot and then
Readchar = Eot and then Readchar = Eot;
end loop;
if Error = None then
Emitt (Su.Number_To_String (Bytes_Xferred) & " bytes received.");
else
Emitt ("*** Too many errors! (" & Xmit_Error'Image (Error) & ')');
end if;
exception
when others =>
if Dio.Is_Open (Fd) then
Dio.Close (Fd);
end if;
Terminal_Specific.Input.Flush (Input);
Emitt ("Transmission failed with " &
Debug_Tools.Get_Exception_Name);
end Receive;
procedure Receive_Text (File : String; From_Mac : Boolean := False) is
Fd : Dio.File_Type;
Forks : Integer := 0;
begin
Bytes_Xferred := 0;
Error := None;
Error_Ring := (others => None);
Error_Byte := (others => 0);
Ring_Ptr := 19;
begin
Dio.Create (Fd, Dio.Out_File, File);
exception
when others =>
Emitt ("Can't create " & File & " (" &
Debug_Tools.Get_Exception_Name & ')');
return;
end;
Emitt ("Ready to receive " & Dio.Name (Fd) & " as text file");
Emitt ("Send three ^D's at end of transmission.");
if not From_Mac then
Error := Receive (Fd, True, True);
else
while Readchar /= Character'Pos (Ascii.Esc) loop
null;
end loop;
while Readchar /= Character'Pos ('a') loop
null;
end loop;
Sendchar (Ack);
Error := Receive (Fd, False, True);
if Error = None then
if Bufr (1 + 86) /= 0 or else Bufr (1 + 85) /= 0 or else
Bufr (1 + 84) /= 0 or else Bufr (1 + 83) /= 0 then
Forks := Forks + 1;
end if;
if Bufr (1 + 90) /= 0 or else Bufr (1 + 89) /= 0 or else
Bufr (1 + 88) /= 0 or else Bufr (1 + 87) /= 0 then
Forks := Forks + 1;
end if;
end if;
for J in 1 .. Forks loop
Error := Receive (Fd, J = Forks, True);
exit when Error /= None;
end loop;
end if;
Tio.Input.Flush (Input);
Dio.Close (Fd);
loop
exit when Readchar = Eot and then
Readchar = Eot and then Readchar = Eot;
end loop;
if Error = None then
Emitt (Su.Number_To_String (Bytes_Xferred) & " bytes received.");
else
Emitt ("*** Too many errors! (" & Xmit_Error'Image (Error) & ')');
end if;
exception
when others =>
if Dio.Is_Open (Fd) then
Dio.Close (Fd);
end if;
Terminal_Specific.Input.Flush (Input);
Emitt ("Transmission failed with " &
Debug_Tools.Get_Exception_Name);
end Receive_Text;
function Send (Fd : Dio.File_Type;
N : Integer := Integer'Last;
As_Text : Boolean := False) return Xmit_Error is
Sectnum : Integer := 1;
Bytes : Integer;
Checksum : Integer;
Bufptr : Integer;
begin
for J in 1 .. Errormax loop
exit when Readchar = Nak;
if J = Errormax then
return No_Nak;
end if;
end loop;
for I in 1 .. N loop
exit when Dio.End_Of_File (Fd);
Dio.Read (Fd, Bufr, Bytes);
for J in Bytes + 1 .. Secsiz * ((Bytes + Secsiz - 1) / Secsiz) loop
Bufr (J) := Nul;
end loop;
Bufptr := 0;
while Bufptr < Bytes loop
for Attempt in 1 .. Retrymax loop
Sendchar (Soh);
Sendchar (Dio.Byte (Sectnum mod 256));
Sendchar (Dio.Byte (255 - Sectnum mod 256));
Checksum := 0;
for J in Bufptr + 1 .. Bufptr + Secsiz loop
if As_Text and then Bufr (J) = Lf then
Bufr (J) := Cr;
end if;
Sendchar (Bufr (J));
Checksum := Checksum + Integer (Bufr (J));
end loop;
Sendchar (Dio.Byte (Checksum mod 256));
exit when Readchar = Ack;
if Attempt = Retrymax then
return No_Ack;
end if;
end loop;
Bufptr := Bufptr + Secsiz;
Sectnum := Sectnum + 1;
end loop;
Bytes_Xferred := Bytes_Xferred + Bytes;
end loop;
for Attempt in 1 .. Retrymax loop
Sendchar (Eot);
if Readchar = Ack then
return None;
end if;
end loop;
end Send;
procedure Send (File : String; To_Mac : Boolean := False) is
Fd : Dio.File_Type;
Error : Xmit_Error := None;
Df, Rf : Integer;
begin
begin
Dio.Open (Fd, Dio.In_File, File);
exception
when others =>
Emitt ("Can't open " & File & " (" &
Debug_Tools.Get_Exception_Name & ')');
return;
end;
Emitt ("Sending File " & Dio.Name (Fd));
Bytes_Xferred := 0;
if not To_Mac then
Error := Send (Fd, Integer'Last, False);
else
delay 10.0;
Sendchar (Character'Pos (Ascii.Esc));
Sendchar (Character'Pos ('a'));
while Readchar /= Ack loop
null;
end loop;
Error := Send (Fd, 1, False);
if Error = None then
Df := Integer (Bufr (1 + 86) +
256 * (Bufr (1 + 85) +
256 * (Bufr (1 + 84) +
256 * (Bufr (1 + 83)))));
Rf := Integer (Bufr (1 + 90) +
256 * (Bufr (1 + 89) +
256 * (Bufr (1 + 88) +
256 * (Bufr (1 + 87)))));
if Df > 0 then
Error := Send (Fd, (Df + 127) / 128, False);
end if;
if Error = None and then Rf > 0 then
Error := Send (Fd, (Rf + 127) / 128, False);
end if;
end if;
end if;
Dio.Close (Fd);
if Error = None then
delay 5.0;
Emitt (Su.Number_To_String (Bytes_Xferred) & " bytes transmitted.");
else
Emitt ("*** Too many errors! (" & Xmit_Error'Image (Error) & ')');
end if;
exception
when others =>
Emitt ("Transmission failed with " &
Debug_Tools.Get_Exception_Name);
if Dio.Is_Open (Fd) then
Dio.Close (Fd);
end if;
end Send;
procedure Send_Text (File : String; To_Mac : Boolean := False) is
Fd : Dio.File_Type;
Error : Xmit_Error := None;
Df, Rf : Integer;
begin
begin
Dio.Open (Fd, Dio.In_File, File);
exception
when others =>
Emitt ("Can't open " & File & " (" &
Debug_Tools.Get_Exception_Name & ')');
return;
end;
Emitt ("Sending File " & Dio.Name (Fd) & " as text");
Bytes_Xferred := 0;
if not To_Mac then
Error := Send (Fd, Integer'Last, True);
else
delay 10.0;
Sendchar (Character'Pos (Ascii.Esc));
Sendchar (Character'Pos ('a'));
while Readchar /= Ack loop
null;
end loop;
Error := Send (Fd, 1, True);
if Error = None then
Df := Integer (Bufr (1 + 86) +
256 * (Bufr (1 + 85) +
256 * (Bufr (1 + 84) +
256 * (Bufr (1 + 83)))));
Rf := Integer (Bufr (1 + 90) +
256 * (Bufr (1 + 89) +
256 * (Bufr (1 + 88) +
256 * (Bufr (1 + 87)))));
if Df > 0 then
Error := Send (Fd, (Df + 127) / 128, True);
end if;
if Error = None and then Rf > 0 then
Error := Send (Fd, (Rf + 127) / 128, True);
end if;
end if;
end if;
Dio.Close (Fd);
if Error = None then
delay 5.0;
Emitt (Su.Number_To_String (Bytes_Xferred) & " bytes transmitted.");
else
Emitt ("*** Too many errors! (" & Xmit_Error'Image (Error) & ')');
end if;
exception
when others =>
Emitt ("Transmission failed with " &
Debug_Tools.Get_Exception_Name);
if Dio.Is_Open (Fd) then
Dio.Close (Fd);
end if;
end Send_Text;
procedure Show_Usage is
begin
Emitt ("Usage:");
Emitt ("..> sx <file> -- send a file via Xmodem");
Emitt ("..> st <file> -- send a text file via Xmodem");
Emitt ("..> rx <file> -- receive a file via Xmodem");
Emitt ("..> rt <file> -- receive a text file via Xmodem");
Emitt ("..> cd <dir> -- connect to another directory");
Emitt ("..> vd <pat> -- display selected objects");
Emitt ("..> ty <file> -- type a file to the screen");
Emitt ("..> ex -- exit Xmodem and release terminal");
end Show_Usage;
function Ok (Status : Object.Error_Code; Msg : String) return Boolean is
begin
if Object.Is_Bad (Status) then
Emitt (Msg);
Emitt (Object.Message (Status));
return False;
else
return True;
end if;
end Ok;
function Maxlength (S : String; W : Integer) return Integer is
begin
if S'Length > W then
return S'Length;
else
return W;
end if;
end Maxlength;
function Padded (S : String; W : Integer) return String is
begin
return S & String'(S'Length .. W => ' ');
end Padded;
procedure Vd (Dir : String) is
Children : Object.Iterator := Naming.Resolution (Dir);
Width : Integer := 0;
Child : Object.Handle;
Parent : Object.Handle := Object.Nil;
Last_Parent : Object.Handle := Object.Nil;
begin
if Object.Is_Bad (Children) then
Emitt (Object.Message (Children));
else
while not Object.Done (Children) loop
Child := Object.Value (Children);
Width := Maxlength (Naming.Unique_Simple_Name (Child), Width);
Object.Next (Children);
end loop;
Object.Reset (Children);
while not Object.Done (Children) loop
Child := Object.Value (Children);
Parent := Traversal.Parent (Child);
if Object.Is_Ok (Parent) and then
not Object.Same_Object (Parent, Last_Parent) then
Last_Parent := Parent;
Emitt ("");
Emitt ("Selected objects in """ &
Naming.Unique_Full_Name (Parent) & '"');
Emitt ("");
end if;
Emitt (Padded (Naming.Unique_Simple_Name (Child), Width) &
Time_Utilities.Image
(Time_Utilities.Convert_Time
(Statistics.Time_Of_Last_Update (Child)),
Time_Utilities.Year_Month_Day,
Time_Utilities.Short) &
Su.Number_To_String
(Statistics.Object_Size (Child) / 8, 10, 7));
Object.Next (Children);
end loop;
end if;
end Vd;
procedure Ty (F : String) is
package Sio renames Io;
File : Sio.File_Type;
S : String (1 .. 1);
begin
Sio.Open (File, Sio.In_File, F);
while not Sio.End_Of_File (File) loop
Emitt (Sio.Get_Line (File));
Tio.Read (Input, S, N, 0.0);
exit when N > 0;
end loop;
Sio.Close (File);
exception
when others =>
if Sio.Is_Open (File) then
Sio.Close (File);
end if;
Emitt ("Abandoning file dump: " & Debug_Tools.Get_Exception_Name);
end Ty;
begin
Emits ("You will be using terminal >>> " &
Su.Number_To_String (Term) & " <<<");
Terminal.Set_Disconnect_On_Logoff (Term, False);
Job.Disconnect;
Operator.Force_Logoff (Term);
Open_Terminal (Term);
Emitt (Ascii.Esc & "[H" & Ascii.Esc & "[J");
Emitt ("Xmodem Transfer Subsystem, V1.0");
Main:
loop
begin
loop
Prompt ("Xmodem> ", S, N);
case N is
when 0 =>
null;
when 1 =>
if S (1) = '?' then
Show_Usage;
else
Emitt ((1 => Ascii.Bel));
end if;
when others =>
exit Main when S (1 .. 2) = "ex";
if S (1 .. 3) = "sx " then
Send (S (4 .. N), False);
elsif S (1 .. 3) = "st " then
Send_Text (S (4 .. N), False);
elsif S (1 .. 3) = "rx " then
Receive (S (4 .. N), False);
elsif S (1 .. 3) = "rt " then
Receive_Text (S (4 .. N), False);
elsif S (1 .. 3) = "cd " then
Naming.Set_Default_Context (S (4 .. N), Status);
if Ok (Status,
"Can't set current directory to " &
S (4 .. N)) then
Emitt ("Current directory is " &
Naming.Default_Context);
end if;
elsif S (1 .. N) = "vd" then
Vd ("@");
elsif S (1 .. 3) = "vd " then
Vd (S (3 .. N));
elsif S (1 .. 3) = "ty " then
Ty (S (3 .. N));
else
Emitt ((1 => Ascii.Bel));
end if;
end case;
end loop;
exception
when others =>
Tio.Input.Flush (Input);
Emitt ("unexpected exception: " &
Debug_Tools.Get_Exception_Name);
end;
end loop Main;
raise Io_Exceptions.End_Error;
exception
when others =>
Close_Terminal (Term);
if Term >= 240 then
Terminal.Set_Disconnect_On_Logoff (Term, True);
end if;
end Xmodem;