home *** CD-ROM | disk | FTP | other *** search
/ kermit.columbia.edu / kermit.columbia.edu.tar / kermit.columbia.edu / ucsdpecan / kermutil.text < prev    next >
Text File  |  1990-08-04  |  17KB  |  597 lines

  1. $D OS_ERHDL+}    { indicates to compile to use Pecan's errorhandler unit 
  2. $D OS_TIMER+}    { indicates to compile to use TIME() for timeouts 
  3.  
  4. unit kermutil;
  5.  
  6. { Change log:
  7. 13 May 89, V1.1: Eliminated "int_bool_rec" & misc cleanups   RTC
  8. 30 Apr 89, V1.1: Moved set/show & connect from kermit to here   RTC
  9. 26 Apr 89, V1.1: Added support for TIMEr controlled timeouts   RTC
  10. 16 Apr 89, V1.1: Added procedure flush_comm to Flush REMOTE:    RTC
  11. 13 Apr 89, V1.1: Added Version message          RTC
  12. 17 Aug 88: Fixed missing EOLN's problem in debf    RTC
  13. 14 Aug 88: Fixed the debug messages to all go to debf      RTC
  14. 31 Jul 88: Modified setup_comm to funct., updated io_error.    RTC
  15. 10 Jul 88: Converted to using screenops unit     RTC
  16. 02 Jul 88: Misc cleanup, eliminated char_int_rec, etc.   RTC
  17. 26 Jun 88 Patched Unitwrite problem in Echo   RTC
  18. 26 Jun 88 Modified read_ch to use cr_getkb    RTC
  19.  
  20.         13 May 84: Use KERNEL's syscom record for screen control -sp-
  21. }
  22.  
  23. $I intfutil.text
  24.  
  25. uses {$U *system.library} screenops, {RTC, 10 Jul 88}
  26.      {$U kermenus.code} kermenus,
  27.      {$U kermpack.code} kermpack (pak_version),
  28.      {$U helper.code} helper (hlp_version),
  29.      {$U parser.code} parser (par_version),
  30.      {$U sender.code} sender (sen_version),
  31.      {$U receiver.code} receiver (rec_version),
  32.      {$U client.code} client (cli_version),
  33.      {$U remunit.code} remunit,  {SP, 1/14/84}
  34.      {$U syslibr:kernel.code} kernel (syscom,version) {$B OS_ERHDL+},
  35.      {$U syslibr:errorhandl.code} error_handling {$E OS_ERHDL+};
  36.  
  37. const
  38.   my_version = '   Kermutil Unit V1.1, 13 May 89';
  39.  
  40. type
  41.   time_value = integer[10];
  42.  
  43. var
  44.   old_flush, old_stop: char;
  45.   time_limit : time_value;
  46.  
  47. $I setshow.text
  48.  
  49. procedure connect;
  50.  
  51. (* connect to remote host and transceive *)
  52.  
  53. var ch: char;
  54.     close: boolean;
  55.  
  56.   procedure read_esc;
  57.  
  58.   (* read character after esc char and interpret it *)
  59.  
  60.     begin
  61.       repeat
  62.       until read_ch(keyport,ch);       (* wait until they've typed something in *)
  63.       if (ch in ['a'..'z']) then  (* uppercase it *)
  64.           ch := chr(ord(ch) - ord('a') + ord('A'));
  65.       if ch in ['B','C','S','?'] then
  66.           case ch of
  67.               'B': sendbrk;       (* B: send a break to the IBM *)
  68.               'C': close := true; (* C: end connection *)
  69.               'S': begin          (* S: show status *)
  70.                       noun := allsym;
  71.                       showparms
  72.                    end; (* S *)
  73.               '?': begin          (* ?: show options *)
  74.                   writeln
  75. ('B    Send a BREAK signal.');
  76.                   writeln
  77. ('C    Close Connection, return to KERMIT-UCSD command level.');
  78.                   writeln
  79. ('S    Show Status of connection');
  80.                   writeln
  81. ('?    Print this list');
  82.                   writeln
  83. ('^',ctl(esc_char),'   send the escape character itself to the remote host.')
  84.                 end; (* ? *)
  85.             end (* case *)
  86.       else if ch = esc_char then  (* ESC-char: send it out *)
  87.         begin
  88.           if half_duplex then
  89.               write(ch); { changed from echo() by SP }
  90.           write_ch(oport,ch)
  91.         end (* else if *)
  92.       else                        (* anything else: ignore *)
  93.           write(chr(bell))
  94.     end; (* read_esc *)
  95.  
  96.   begin (* connect *)
  97.     clear_buf(keyport);                    (* empty keyboard buffer *)
  98.     clear_buf(inport);                    (* empty remote input buffer *)
  99.     writeln('Connecting to host...type CTRL-',ctl(esc_char),' C to exit');
  100.     close := false;
  101.     repeat
  102.         if read_ch(inport,ch) then        (* if char from host then *)
  103.             echo(ch);                   (* echo it *)
  104.  
  105.         if read_ch(keyport,ch) then        (* if char from keyboard then *)
  106.             if ch <> esc_char then      (* if not ESC-char then *)
  107.               begin
  108.                 if half_duplex then       (* echo it if half-duplex *)
  109.                     write(ch); { changed from echo() by sp }
  110.                 write_ch(oport,ch)     (* send it out the port *)
  111.               end (* if *)
  112.             else (* ch = esc_char *)    (* else is ESC-char so *)
  113.               read_esc;                   (* interpret next char *)
  114.     until close;                      (* if still connected, get more *)
  115.     writeln('Disconnected')
  116.   end; (* connect *)
  117.  
  118. procedure uppercase(*var s: string255*);
  119.  
  120. var i: integer;
  121.  
  122.   begin
  123.     for i := 1 to length(s) do
  124.         if s[i] in ['a'..'z'] then
  125.             s[i] := chr(ord(s[i]) - ord('a') + ord('A'))
  126.   end; (* uppercase *)
  127.  
  128.  
  129. function read_ch(*unitno:integer; var ch: char): boolean*);
  130.  
  131. (* read a character from an input queue *)
  132. var
  133.    ready: boolean;
  134.  
  135.   begin
  136.     if unitno=keyport then
  137.        ready := cr_kbstat
  138.     else if unitno=inport then
  139.        ready := cr_remstat
  140.     else
  141.        ready := false;
  142.     if ready then            (* if a char there *)
  143.        if unitno=keyport then
  144.           ch := cr_getkb
  145.        else
  146.           ch := cr_getrem;
  147.     read_ch := ready
  148.   end; (* read_ch *)
  149.  
  150. procedure write_ch(*unitno: integer; ch: char*);
  151. begin
  152.    if unitno=oport then
  153.       cr_putrem( ch )
  154. end;
  155.  
  156.  
  157. procedure read_str(*unitno:integer; var s: string255*);
  158.  
  159. (* acts like readln(s) but takes input from input queue *)
  160.  
  161. var i: integer;
  162.  
  163.   begin
  164.     i := 0;
  165.     s := copy('',0,0);
  166.     repeat
  167.       repeat                              (* get a character *)
  168.       until read_ch(unitno,ch);
  169.       if (ord(ch) = backspace) then       (* if it's a backspace then *)
  170.         begin
  171.           if (i > 0) then                   (* if not at beginning of line *)
  172.             begin
  173.               write(ch);                      (* go back a space on screen *)
  174.               write(' ');                     (* erase char on screen *)
  175.               write(ch);                      (* go back a space again *)
  176.               i := i - 1;                     (* adjust string counter *)
  177.               s := copy(s,1,i)                (* adjust string *)
  178.             end (* if *)
  179.         end (* if *)
  180.       else if (ord(ch) <> eoln_sym) then  (* otherwise if not at eoln  then *)
  181.         begin
  182.           write(ch);                        (* echo char on screen *)
  183.           i := i + 1;                       (* inc string counter *)
  184.           s := concat(s,' ');
  185.           s[i] := ch;                       (* put char in string *)
  186.         end; (* if *)
  187.     until (ord(ch) = eoln_sym);           (* if not eoln, get another char *)
  188.     s := copy(s,1,i);                     (* correct string length *)
  189.     writeln                               (* write a line on the screen *)
  190.   end; (* read_str *)
  191.  
  192.  
  193. procedure clear_buf(*unitno:integer*);
  194.  modified by SP 
  195. begin
  196.    if unitno=keyport then
  197.       unitclear( unitno )
  198. end;
  199.  
  200.  
  201. procedure send_brk;
  202. begin
  203.    cr_break
  204. end;
  205.  
  206.  
  207. function setup_comm{ : boolean};
  208.  SP, 14 Jan 84 
  209. var
  210.    result: cr_baud_result;
  211. begin
  212.    setup_comm := false;
  213.    cr_setcommunications(false,
  214.                         false,
  215.                         baud,
  216.                         8,
  217.                         1,
  218.                         cr_orig,
  219.                         system_id,
  220.                         result );
  221.    case result of
  222.      CR_bad_parameter :
  223.          writeln('Bad Parameter, # Bits or Parity wrong');
  224.      CR_bad_rate :
  225.          writeln('Bad Baud Rate selection');
  226.      CR_set_OK :
  227.          setup_comm := true;
  228.      CR_select_not_supported :
  229.          writeln('Hardware does not support Baud selection')
  230.    end {case}
  231. end;
  232.  
  233. procedure flush_comm;                {added 16 Apr 89, RTC}
  234.  
  235.   var
  236.     ch : char;
  237.  
  238.   begin {flush_comm}
  239.     while CR_remstat do
  240.       ch := CR_getrem   {flush all characters in REMOTE port}
  241.   end {flush_comm};
  242.  
  243. function aand(*x,y: integer): integer*);
  244.  
  245. (* arithmetic and--takes 2 integers and ands them, yeilding an integer *)
  246.  
  247.   begin
  248.     aand := ord(odd(x) and odd(y));  (* use as booleans to 'and' them *)
  249.   end; (* aand *)
  250.  
  251.  
  252. function aor(*x,y: integer): integer*);
  253.  
  254. (* arithmetic or *)
  255.  
  256.   begin
  257.     aor := ord(odd(x) or odd(y));   (* use as booleans to 'or' them *)
  258.   end; (* aor *)
  259.  
  260. function xor(*x,y: integer): integer*);
  261.  
  262. (* exclusive or *)
  263.  
  264.   begin
  265.     xor := ord( (odd(x) or odd(y)) and not(odd(x) and odd(y)) );
  266.   end; (* xor *)
  267.  
  268. procedure error(*p: packettype; len: integer*);
  269.  
  270. (* writes error message sent by remote host *)
  271.  
  272. var i: integer;
  273.  
  274.   begin
  275.     gotoxy(0,errorline);
  276.     for i := 0 to len-1 do
  277.         write(p[i]);
  278.     gotoxy(0,promptline);
  279.   end; (* error *)
  280.  
  281. procedure io_error(*i: integer*);
  282.  
  283.   var
  284.     message : string;
  285.  
  286.   begin
  287.     SC_erase_to_EOL( 0, errorline );
  288.     {$B OS_ERHDL+}
  289.     IOR_to_message(i,message);
  290.     {$E OS_ERHDL+} {$B OS_ERHDL-}
  291.     case i of
  292.         0: message := 'No error';
  293.         1: message := 'Bad Block, Parity error (CRC)';
  294.         2: message := 'Bad Unit Number';
  295.         3: message := 'Bad I/O request, Illegal operation';
  296.         4: message := 'Undefined hardware error';
  297.         5: message := 'Lost unit, Volume is no longer on-line';
  298.         6: message := 'Lost file, File is no longer in directory';
  299.         7: message := 'Bad Title, Illegal file name';
  300.         8: message := 'No room, insufficient space';
  301.         9: message := 'No unit, No such volume on line';
  302.         10: message := 'No file, No such file on volume';
  303.         11: message := 'Duplicate file';
  304.         12: message := 'Not closed, attempt to open an open file';
  305.         13: message := 'Not open, attempt to access a closed file';
  306.         14: message := 'Bad format, error in reading real or integer';
  307.         15: message := 'Queue overflow';
  308.         16: message := 'Write Protected volume';
  309.         17: message := 'Illegal Block';
  310.         18: message := 'Illegal Buffer for low-level I/O';
  311.         19: message := 'Illegal Size or Range of File Attribute';
  312.         20: message := 'Attempted read past End of File';
  313.       end; (* case *)
  314.       if i >= 128 then
  315.         begin
  316.           i := i - 128; message := '0';
  317.           while i > 0 do
  318.             begin
  319.               message[1] := chr(ord('0') + i mod 10);
  320.               message := concat(' ',message);
  321.               i := i div 10
  322.             end;
  323.           message := concat('Host Operating System Error #',message)
  324.         end;
  325.     {$E OS_ERHDL-}
  326.     writeln(message);
  327.     gotoxy(0,promptline)
  328.   end; (* io_error *)
  329.  
  330. procedure debugwrite(*s: string255*);
  331.  
  332. (* writes a debugging message *)
  333. var i: integer;
  334.  
  335.   begin
  336.     if debug then
  337.       begin
  338.         SC_erase_to_EOL(0,debugline);
  339.         gotoxy(0,pred(debugline)); writeln(debf);
  340.         write(debf,s);
  341.         for i := 1 to 2000 do ;                (* write debugging message *)
  342.       end (* if debug *)
  343.   end; (* debugwrite *)
  344.  
  345. procedure debugint(*s: string255; i: integer*);
  346.  
  347. (* write a debugging message and an integer *)
  348.  
  349.   begin
  350.     if debug then
  351.       begin
  352.         debugwrite(s);
  353.         write(debf,i)
  354.       end (* if debug *)
  355.   end; (* debugint *)
  356.  
  357. function min(*x,y: integer): integer*);
  358.  
  359. (* returns smaller of two integers *)
  360.  
  361.   begin
  362.     if x < y then
  363.         min := x
  364.     else
  365.         min := y
  366.   end; (* min *)
  367.  
  368. function tochar(*ch: char): char*);
  369.  
  370. (* tochar converts a control character to a printable one by adding space *)
  371.  
  372.   begin
  373.     tochar := chr(ord(ch) + ord(' '))
  374.   end; (* tochar *)
  375.  
  376. function unchar(*ch: char): char*);
  377.  
  378. (* unchar undoes tochar *)
  379.  
  380.   begin
  381.     unchar := chr(ord(ch) - ord(' '))
  382.   end; (* unchar *)
  383.  
  384. function ctl(*ch: char): char*);
  385.  
  386. (* ctl toggles control bit: ^A becomes A, A becomes ^A *)
  387.  
  388.   begin
  389.     ctl := chr(xor(ord(ch),64))
  390.   end; (* ctl *)
  391.  
  392. procedure echo(*ch: char*);
  393.  
  394. (* echos a character on the screen *)
  395.  
  396. var cursorx, cursory:integer;
  397.     ch_buf : packed array [0..1] of char;
  398.  
  399.  The DataMedia emulation is by John Socha. 
  400. begin
  401.    ch := chr(aand(ord(ch),127)); (* mask off parity bit *)
  402.    ch_buf[0] := ch;     {for unitwrite portability      RTC}
  403.  
  404.    if emulating and (ord(ch) in [30,25,28,31,29,11]) then
  405.       case ord(ch) of
  406.          { Datamedia 1520 emulation }
  407.          { rs }30: begin
  408.                       { allow timeout while waiting for coordinates
  409.                         so computer doesn't freeze }
  410.                       set_timer(2);
  411.                       repeat
  412.                       until read_ch( inport, ch ) or timeout;
  413.                       if not timeout then begin
  414.                          cursorx:=ord(ch)-32;
  415.                          repeat
  416.                          until read_ch( inport, ch ) or timeout;
  417.                          if not timeout then begin
  418.                             cursory:=ord(ch)-32;
  419.                             gotoxy(cursorx,cursory)
  420.                          end
  421.                       end
  422.                    end;
  423.          { em }25: SC_home;
  424.          { fs }28: SC_right;
  425.          { us }31: SC_up;
  426.          { gs }29: SC_erase_to_EOL(SC_find_X,SC_find_Y);
  427.          { vt }11: SC_eras_eos(SC_find_X,SC_find_Y)
  428.       end
  429.     else
  430.        unitwrite(1,ch_buf[0],1,,12)  { the 12 eliminates DLE & CR expansion }
  431.   end; (* echo *)
  432.  
  433.  
  434. function getch(*var r: char): boolean*);
  435.  
  436. (* gets a character, strips parity, returns true if it got a char which *)
  437. (* isn't Kermit SOH, false if it gets SOH or nothing after timeout *)
  438.  
  439.   begin
  440.     getch := false;
  441.     repeat
  442.     until (read_ch(inport,r)) or timeout;       (* wait for a character *)
  443.     if timeout then                             (* if wait too long then *)
  444.         exit(getch);                            (* get out of here *)
  445.     if parity <> nopar
  446.       then r := chr(aand(ord(r),127));          (* strip parity from char *)
  447.     getch := (r <> chr(soh));                   (* return true if not SOH *)
  448.   end; (* getch *)
  449.  
  450.  
  451. function getsoh(*: boolean*);
  452.  
  453. (* reads characters until it finds an SOH; returns false if has timed out *)
  454.  
  455. var ch: char;
  456.  
  457.   begin
  458.     getsoh := true;
  459.     repeat
  460.       repeat
  461.       until (read_ch(inport,ch)) or timeout; (* wait for a character *)
  462.       if timeout then
  463.         begin
  464.             getsoh := false;
  465.             exit(getsoh)
  466.           end; (* if *)
  467.         ch := chr(aand(ord(ch),127));            (* strip parity of char *)
  468.     until (ch = chr(SOH))                        (* if not SOH, get more *)
  469.   end; (* getsoh *)
  470.  
  471.  
  472. function getfil(*filename: string255): boolean*);
  473.  
  474. (* opens a file for writing *)
  475.  
  476.   begin
  477.     (*$I-*) (* turn i/o checking off *)
  478.     if f_is_binary
  479.       then
  480.         begin
  481.           rewrite(b_file,filename);
  482.           bufpos := 1           {new file... nothing in buffer}
  483.         end
  484.       else rewrite(t_file,filename);
  485.     (*$I-*) (* turn i/o checking on *)
  486.     getfil := (ioresult = 0)
  487.   end; (* getfil *)
  488.  
  489.  
  490. procedure writescreen(*s: string255*);
  491.  
  492. (* sets up the screen for receiving or sending files *)
  493.  
  494. begin
  495.    page(output);
  496.    gotoxy(0,titleline);
  497.    write('            Kermit UCSD p-System, Version ', version );
  498.    gotoxy(statuspos,statusline);
  499.    write(s);
  500.    gotoxy(0,packetline);
  501.    write('Number of Packets: ');
  502.    gotoxy(0,retryline);
  503.    write('Number of Tries: ');
  504.    gotoxy(0,fileline);
  505.    write('File Name: ');
  506. end; (* writescreen *)
  507.  
  508.  
  509. procedure refresh_screen(*numtry, num: integer*);
  510.  
  511. (* keeps track of packet count on screen *)
  512.  
  513. begin
  514.    gotoxy(retrypos,retryline);
  515.    write(numtry: 5);
  516.    gotoxy(packetpos,packetline);
  517.    write(num: 5)
  518. end; (* refresh_screen *)
  519.  
  520. $B OS_TIMER+
  521. procedure long_time(var t : time_value);
  522.  
  523.   {this procedure converts the "dual integer" values returned by time()
  524.    to a single "long integer" value, which it returns to the caller}
  525.  
  526.   var
  527.     i : 0..1;
  528.     hl : array [0..1] of integer;
  529.  
  530.   begin {long_time}
  531.     t := 0; time(hl[0],hl[1]);
  532.     for i := 0 to 1 do
  533.       begin
  534.         if hl[i] < 0 then t := t + 1;
  535.         t := 65536*t + hl[i]
  536.       end
  537.   end {long_time};
  538. $E OS_TIMER+
  539.  
  540. procedure set_timer{t : integer};    {added 26 Apr 89, RTC}
  541.  
  542.   {$B OS_TIMER-}
  543.   const counts_per_second = 1000;        {WARNING!! implementation dependant}
  544.   {$E OS_TIMER-}
  545.  
  546.   var long_t : time_value;
  547.  
  548.   begin {set_timer}
  549.     long_t := t; {convert to long format}
  550.     {$B OS_TIMER+}
  551.     long_time(time_limit); time_limit := time_limit + 60*long_t
  552.     {$E OS_TIMER+} {$B OS_TIMER-}
  553.     time_limit := counts_per_second*long_t
  554.     {$E OS_TIMER-}
  555.   end {set_timer};
  556.  
  557. function timeout {: boolean};        {added 26 Apr 89, RTC}
  558.  
  559.   {$B OS_TIMER+}
  560.   var this_time : time_value;
  561.   {$E OS_TIMER+}
  562.  
  563.   begin {timeout}
  564.     {$B OS_TIMER+}
  565.     long_time(this_time);
  566.     timeout := this_time > time_limit
  567.     {$E OS_TIMER+} {$B OS_TIMER-}
  568.     time_limit := time_limit - 1;
  569.     timeout := time_limit <= 0
  570.     {$E OS_TIMER-}
  571.   end {timeout};
  572.  
  573. procedure utl_version;
  574.  
  575. begin
  576.    write(my_version);
  577.   {$B OS_TIMER+}
  578.   write(' (with TIMER)');
  579.   {$E OS_TIMER+}
  580.   writeln
  581. end {utl_version};
  582.  
  583.  
  584. begin { body of unit kermutil }
  585.    { initialization code }
  586.    old_flush := syscom^.crtinfo.flush;
  587.    old_stop := syscom^.crtinfo.stop;
  588.    syscom^.crtinfo.flush := chr(255);  { effectively turning flush off }
  589.    syscom^.crtinfo.stop := chr(254);   { effectively turning stop off }
  590.  
  591.    ***;
  592.  
  593.    { termination code }
  594.    syscom^.crtinfo.flush := old_flush;  { turn flush back on }
  595.    syscom^.crtinfo.stop := old_stop     { turn stop back on }
  596. end. { kermutil }
  597.