$SEARCH 'KRMWNDW', '*IO.', '*INTERFACE.'$ { This file, KRMRPT.TEXT, contains the error and status reporting modules used by all other Kermit modules. The following modules reside in this file: ERR_CODES Error code definitions KRMRPT Error and status reporting procedures The module KRMRPT includes the file KRMVERS.TEXT, which declares the version string constant VERSION_STRING. } { Module ERR_CODES defines the integer error code values that can be returned by a procedure to indicate whether it completed successfully, or, if not, what error occurred. Successful and warning error codes are odd (low order bit set), and indicate that all went reasonably well. Failing error codes are even (low order bit clear), and indicate that something happened that kept a routine from doing what it was supposed to. Function ERRSTR returns the error message string associated with the given error code. All Kermit modules have access to ERR_CODES. } module err_codes; export const error_string_length = 80; { Maximum length of error strings } { Facility code definitions. These codes identify the facility generating the error. } cmdfac = 1*128; { command interpreter } trmfac = 2*128; { terminal emulation code } iofac = 3*128; { IO error } krmfac = 4*128; { kermit protocol machine } { Status code definitions. Successful return codes are odd, those corresponding to error conditions are even. Returned by functions, etc. } success = 1; file_rcvd_ok = 3; { file received successfully } file_sent_ok = 5; { file transmitted successfully } inv_packet_type = 7; { unexpected packet type received } { Error condition status codes } { Codes returned by lookup_key in module command } ambig_keyword = 2; no_keyword = 4; { Codes returned by parse in module command } not_confirmed = 6; integer_error = 8; no_match = 10; non_digit = 12; { Non-digit character encountered } integer_overflow = 14; { Integer overflow } null_string = 16; { null string given as argument } parse_after_eol = 18; { parse called after eol parsed } { Codes returned by read_break in module command } back_past_field = 20; abort_line = 22; { Codes returned by Kermit protocol procedures in module krmguts } retry_exhausted = 24; timeout = 26; abort_file = 28; abort_group = 30; abort_errpack = 32; rcvd_bad_init = 34; cant_read_file = 36; cant_write_file = 38; cant_create_file = 40; cant_find_file = 42; type error_string = string[error_string_length]; function errstr ( errcode : integer ) : error_string; $page$ implement function errstr ( errcode : integer ) : error_string; { Returns the error string associated with each error. } var s : error_string; begin case errcode of success: s := 'Success'; inv_packet_type: s := 'Unexpected packet type received'; file_rcvd_ok: s := 'File received successfully'; file_sent_ok: s := 'File sent successfully'; { Codes returned by lookup_key } ambig_keyword: s := 'Ambiguous keyword'; no_keyword: s := 'No keywords match this input'; { Codes returned by parse } not_confirmed: s := 'Not confirmed'; integer_error: s := 'Error reading integer'; no_match: s := 'No defined keywords match this input'; non_digit: s := 'Non-digit character encountered'; integer_overflow: s := 'Integer overflow'; null_string: s := 'Null string given as argument'; parse_after_eol: s := 'Parse called after end of line parsed'; { Codes returned by read_break } back_past_field: s := 'Input deleted past beginning of field'; abort_line: s := 'Line aborted by CTRL-U'; { Codes returned by Kermit protocol procedures } retry_exhausted: s := 'Retry count exhausted'; timeout: s := 'Timeout'; abort_file: s := 'File transfer aborted by user'; abort_group: s := 'File group transfer aborted by user'; abort_errpack: s := 'Transfer aborted by error packet from remote'; cant_read_file: s := 'Cannot open file for reading'; cant_write_file: s := 'Cannot open file for writing'; cant_create_file: s := 'Cannot create file'; cant_find_file: s := 'File does not exist'; end; { case } errstr := s; end; { function errstr } end; { module err_codes } $PAGE$ { Module KRMRPT handles error and status reporting for the rest of Kermit. Basically, except for command echoing, anything that is displayed on the screen is put there by procedures in this module. These procedures do the proper text formatting, positioning, etc., and then call procedures in module WINDOWLIB (in file KRMWNDW.TEXT) to actually do the screen output. All Kermit modules have access to KRMRPT. } module krmrpt; import windowlib, err_codes; export $INCLUDE 'KRMVERS.TEXT'$ { This file has const declarations for the version variables VERSION_NUM and VERSION_DATE, which are string constants } var help_window, command_window, error_window, stat_window : window_ptr; type { Packet transfer statistics record } kermit_statistics = record NumSendPacks : integer; { number of packets sent } NumRecvPacks : integer; { number of packets received } NumACKsent : integer; { number of ACKs we've sent } NumNAKsent : integer; { number of NAKs we've sent } NumACKrecv : integer; { number of ACKs we've received } NumNAKrecv : integer; { number of NAKs we've received } NumBADrecv : integer; { number of non-ACKs we've received when } { waiting for an ACK } RunTime: integer; { elapsed time for current transaction } ChInFile : integer; { number of characters in file } ChInPack : integer; { number of characters in packets } packet_overhead : integer; { percent overhead of packetizing } effrate : integer; { effective baud rate of transfer } end; { record } KermitStates = (FileData,RecvInit,SendInit,Break, FileHeader,EOFile,Complete,Abort); Transfer_type = (Transmit, Receive, Invalid); procedure set_logfile( var fnm : string ); procedure get_logfile( var fnm : string ); procedure report_version; procedure report_status( var report : string ); procedure report_log( var report : string ); procedure report_error( code : integer; var where_msg : string ); procedure init_cmd_windows; procedure clear_status_window; procedure init_packet_display( runtype : transfer_type ); procedure clean_packet_display( runtype : transfer_type ); procedure report_send_packet( seq : integer ); procedure report_receive_file( var fnm : string ); procedure report_send_file( var fnm : string ); procedure report_packet_statistics( stats : kermit_statistics; runtype : transfer_type ); function check_error( code : integer; var where_msg : string ) : boolean; implement const send_packet_y = 2; packet_stat_x = 25; packet_stat_y = 4; stat_random_x = 0; stat_random_y = 14; file_report_x = 0; file_report_y = 0; var log_filename : string[50]; log_file : text; log_on : boolean; send_packet_x : integer; { window coords of send packet # } report : string[80]; rpos : integer; procedure set_logfile( var fnm : string ); begin if strlen(fnm) = 0 then begin log_on := false; log_filename := 'OFF'; end else begin log_on := true; log_filename := fnm; rewrite(log_file,log_filename); end; end; { procedure set_logfile } procedure get_logfile( var fnm : string ); begin fnm := log_filename; end; { procedure get_logfile } procedure report_version; var vs : string[80]; p : integer; { dummy for strwrite } begin strwrite(vs,1,p,VERSION_STRING); writeln_window_string(stat_window,vs); end; { procedure report_version } procedure report_status( var report : string ); begin writeln_window_string( stat_window, report ); end; { procedure report_status } procedure report_log( var report : string ); begin if log_on then writeln(log_file, report); end; { procedure report_status } procedure report_error( code : integer; var where_msg : string ); var report : string [80]; rpos : integer; begin setstrlen(report,0); if odd(code) then strwrite(report,1,rpos,errstr(code)) else strwrite(report,1,rpos,'?Error ',where_msg, ' - ', errstr(code)); clear_window(error_window); writeln_window_string( error_window, report ); end; { procedure report_error } $page$ procedure init_cmd_windows; begin stat_window := init_window(0,screen_x_max, 0,16); help_window := init_window(0,screen_x_max, 17,20); command_window := init_window(0,screen_x_max, 21,21); error_window := init_window(0,screen_x_max, 22,23); end; { procedure init_cmd_windows } procedure clear_status_window; begin clear_window(stat_window); end; { procedure clear_status_window } procedure init_packet_display( runtype : transfer_type ); var lab : string[80]; begin clear_window(stat_window); lab := 'Sending Packet # '; send_packet_x := strlen(lab); gotoxy_window(stat_window, 0, send_packet_y); writeln_window_string( stat_window, lab); clear_eol_window(stat_window); gotoxy_window( stat_window, 0, packet_stat_y ); setstrlen(report,0); strwrite(report,1,rpos,'Packets sent'); report_status(report); setstrlen(report,0); strwrite(report,1,rpos,'Packets received'); report_status(report); setstrlen(report,0); if runtype = transmit then strwrite(report,1,rpos,'Total chars. sent') else strwrite(report,1,rpos,'Total chars. rcvd'); report_status(report); setstrlen(report,0); if runtype = transmit then strwrite(report,1,rpos,'Data chars. sent') else strwrite(report,1,rpos,'Data chars. rcvd'); report_status(report); setstrlen(report,0); strwrite(report,1,rpos,'Overhead (%)'); report_status(report); setstrlen(report,0); strwrite(report,1,rpos,'Effective Rate'); report_status(report); setstrlen(report,0); strwrite(report,1,rpos,'Number of ACK'); report_status(report); setstrlen(report,0); strwrite(report,1,rpos,'Number of NAK'); report_status(report); IF (RunType = Transmit) THEN BEGIN setstrlen(report,0); strwrite(report,1,rpos,'Number of BAD'); report_status(report); END; gotoxy_window(stat_window, stat_random_x, stat_random_y); end; { procedure init_packet_display } procedure clean_packet_display( runtype : transfer_type ); begin gotoxy_window(stat_window, 0, send_packet_y); clear_eol_window(stat_window); end; { procedure clean_packet_display } procedure report_send_packet( seq : integer ); begin gotoxy_window(stat_window, send_packet_x, send_packet_y); setstrlen(report,0); strwrite(report,1,rpos,seq:1); write_window_string(stat_window, report); clear_eol_window(stat_window); gotoxy_window(stat_window, stat_random_x, stat_random_y); end; { report_send_packet } procedure report_send_file( var fnm : string ); begin gotoxy_window(stat_window, file_report_x, file_report_y); setstrlen(report,0); strwrite(report,1,rpos,'Sending file ',fnm); write_window_string(stat_window, report); clear_eol_window(stat_window); gotoxy_window(stat_window, stat_random_x, stat_random_y); end; { procedure report_send_file } procedure report_receive_file( var fnm : string ); begin gotoxy_window(stat_window, file_report_x, file_report_y); setstrlen(report,0); strwrite(report,1,rpos,'Receiving file ',fnm); write_window_string(stat_window, report); clear_eol_window(stat_window); gotoxy_window(stat_window, stat_random_x, stat_random_y); end; { procedure report_receive_file } procedure report_packet_statistics( stats : kermit_statistics; runtype : transfer_type ); var row : integer; procedure report_num( i : integer ); begin setstrlen(report,0); strwrite(report,1,rpos,i:5); gotoxy_window(stat_window, packet_stat_x, row); write_window_string(stat_window,report); row := row + 1; end; { procedure report_num } begin row := packet_stat_y; report_num(stats.NumSendPacks); report_num(stats.NumRecvPacks); report_num(stats.ChInPack); report_num(stats.ChInFile); report_num(stats.packet_overhead); report_num(stats.effrate); IF (RunType = Transmit) THEN BEGIN { for transmit } report_num(stats.NumACKrecv); report_num(stats.NumNAKrecv); report_num(stats.NumBADrecv); END { for transmit } ELSE BEGIN { for Receive } report_num(stats.NumACKsent); report_num(stats.NumNAKsent); END; { for Receive } gotoxy_window(stat_window, stat_random_x, stat_random_y); end; { procedure report_packet_statistics } $page$ { check_error Checks given condition code. Returns false if code is successful. If code is error code, prints associated error message and returns true. } function check_error( code : integer; var where_msg : string ) : boolean; var ret : boolean; begin ret := false; if not odd(code) { successful conditions are odd, failing (error) conditions are even } then begin report_error( code, where_msg ); ret := true; end; check_error := ret; end; { procedure check_error } end. { module krmrpt }