home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PASCAL / TPDOOR.ZIP / DOORIO.INC next >
Encoding:
Text File  |  1986-10-15  |  15.0 KB  |  418 lines

  1. {----------------------------------------------------------------------}
  2. {                                                                      }
  3. { Library:    DOORIO.INC                                               }
  4. { Purpose:    RBBS-PC DOORS Application Program I/O Support Library    }
  5. { Language:   Borland Turbo Pascal Version 3.00                        }
  6. {                                                                      }
  7. { Author:     Richard L. Tremmel, GTE/Florida                          }
  8. {             Genzral Service - Electronic Operations Support          }
  9. {             610 Zack St. MC-20, Tampa, FL 33601  Voice: 813-224-7127 }
  10. {             GTE Telenet: GTFL.EOS or contact me on the following:    }
  11. {             SUNSHINE RBBS 813-887-3984 or TAMIAMI RBBS 813-793-2392  }
  12. {                                                                      }
  13. { Notice:     This library is placed in the public domain and may be   }
  14. {             freely used by anyone for any purpose.  When using this  }
  15. {             code, please give credit to the original author and to   }
  16. {             anyone who has subsequently improved or modified it.     }
  17. {                                                                      }
  18. { History:    Version 1.00, 07/20/85 - Original by Richard L. Tremmel  }
  19. {                                                                      }
  20. {             Version 1.01, 07/23/85 - Modified by Richard L. Tremmel  }
  21. {                           Added "SNOOP" flag to allow monitoring of  }
  22. {                           user application.                          }
  23. {                                                                      }
  24. { Narrative:  This Turbo Pascal include library provides I/O support   }
  25. {             routines for use with the Remote Bulletin Board System   }
  26. {             for the IBM Personal Computer (RBBS-PC) "Doors" function.}
  27. {             Using these I/O routines and a program written in Turbo, }
  28. {             the "Doors" function of RBBS-PC can be implemented with  }
  29. {             complete system security.  The "CTTY CON" command is not }
  30. {             required and no unsolicited input ever gets to the oper- }
  31. {             ating system.                                            }
  32. {                                                                      }
  33. {             The I/O routines support carrier monitoring, user input  }
  34. {             time-out, and integer and real number input with range   }
  35. {             checking.  The I/O routines also support task switching  }
  36. {             during input/output waits to free up the system when run-}
  37. {             ning under MultiLink multitasking system by The Software }
  38. {             Link.                                                    }
  39. {                                                                      }
  40. {             The following is an example "Door" batch file for a Turbo}
  41. {             Pascal program called "TESTIO.COM" written using these   }
  42. {             I/O routines.  The system console is not redirected to an}
  43. {             async port which would make the system vulnerable.       }
  44. {                                                                      }
  45. {                 ECHO OFF                                             }
  46. {                 TESTIO                                               }
  47. {                 ECHO RETURNING TO RBBS-PC, WAIT... >COM1:            }
  48. {                 RBBS                                                 }
  49. {                                                                      }
  50. {---------------------------- (continued) -----------------------------}
  51. {.PA}
  52. {----------------------------------------------------------------------}
  53. {                                                                      }
  54. { Required:   The DOORIO.INC library requires the following type       }
  55. {             definition:                                              }
  56. {                                                                      }
  57. {                 LINETYPE : string[nnn] where 'nnn' is the max length }
  58. {                                        of any string input or output }
  59. {                                                                      }
  60. {             The DOORIO.INC library requires the following variables  }
  61. {             or constants to be defined:                              }
  62. {                                                                      }
  63. {                 DEBUG     true  = local console program testing      }
  64. {                           false = use async communications ports     }
  65. {                                                                      }
  66. {                 SNOOP     true  = copy async output to console       }
  67. {                           false = all output to async port only      }
  68. {                                                                      }
  69. {                 MLINK     true  = program is running under MultiLink }
  70. {                                   and should task switch during input}
  71. {                                   and output waits.                  }
  72. {                           false = program is NOT running under the   }
  73. {                                   MultiLink multi-tasking system     }
  74. {                                                                      }
  75. {                 CARRIER   true  = abort program on loss of carrier   }
  76. {                           false = ignore carrier condition           }
  77. {                                                                      }
  78. {                 ABORTABLE true  = allow ^C input to abort program    }
  79. {                           false = disable special ^C processing      }
  80. {                                                                      }
  81. {                 PORTN     : integer (async port number to use)       }
  82. {                                                                      }
  83. {                 TIMELIMIT : integer (input time-out in seconds)      }
  84. {                                                                      }
  85. {----------------------------------------------------------------------}
  86.  
  87. const
  88.       COM_CD_MASK                       = $80;           {carrier pres }
  89.       COM_DA_MASK                       = $01;           {data avail.  }
  90.       COM_TE_MASK                       = $20;           {xmit empty   }
  91.       COM_RESET_MASK                    = $04;           {reset modem  }
  92.       COM_ENABLE_MASK                   = $01;           {enable modem }
  93.       COM_DBR : array [1..2] of integer = ($03F8,$02F8); {data buffer  }
  94.       COM_MCR : array [1..2] of integer = ($03FC,$02FC); {modem control}
  95.       COM_LSR : array [1..2] of integer = ($03FD,$02FD); {line status  }
  96.       COM_MSR : array [1..2] of integer = ($03FE,$02FE); {modem status }
  97.  
  98. {$R+}         {Enable range checking                                   }
  99. {$V+}         {Enable var-parameter type checking                      }
  100. {.PA}
  101. {This procedure calls MultiLink and requests a task switch to free up  }
  102. {the system during input/output waits if MLINK is set to true.         }
  103.  
  104. procedure TASKSWITCH;
  105.  
  106. begin {TASKSWITCH}
  107.   if MLINK and not DEBUG
  108.     then
  109.       inline($B4/$02/ {MOV AH,2 ;request a task switch}
  110.              $CD/$7F) {INT 7FH  ;call MultiLink       }
  111. end; {TASKSWITCH}
  112.  
  113.  
  114.  
  115.  
  116.  
  117. {This function returns the system timer value as a real number.  The   }
  118. {system timer counts at a rate of 18.2065 counts per second.           }
  119.  
  120. function SYSTTIME : real;
  121.  
  122. const
  123.     WORD_FACTOR = 65536.00;
  124.  
  125. var
  126.     LOW, HIGH   : real;                           {temporary variable  }
  127.     TIMER_LOW   : integer absolute $0000 : $046C; {timer low  word     }
  128.     TIMER_HIGH  : integer absolute $0000 : $046E; {timer high word     }
  129.  
  130. begin {SYSTTIME}
  131.   if TIMER_LOW < 0
  132.     then
  133.       LOW := TIMER_LOW + WORD_FACTOR
  134.     else
  135.       LOW := TIMER_LOW;
  136.   if TIMER_HIGH < 0
  137.     then
  138.       HIGH := TIMER_HIGH + WORD_FACTOR
  139.     else
  140.       HIGH := TIMER_HIGH;
  141.   SYSTTIME := HIGH * WORD_FACTOR + LOW
  142. end; {SYSTTIME}
  143. {.PA}
  144. {This procedure checks async port number PORTN for the presence of     }
  145. {carrier if CARRIER checking is set to true.  If carrier is not present}
  146. {and is not restored within approximately one second, the program is   }
  147. {aborted.                                                              }
  148.  
  149. procedure CC;
  150.  
  151. begin {CC}
  152.   if CARRIER
  153.     then
  154.       if (port[COM_MSR[PORTN]] and COM_CD_MASK) = 0
  155.         then
  156.           begin
  157.             delay(1000);
  158.             if (port[COM_MSR[PORTN]] and COM_CD_MASK) = 0
  159.               then
  160.                 halt; {lost carrier}
  161.           end
  162. end; {CC}
  163.  
  164.  
  165.  
  166.  
  167.  
  168. {This function returns the character waiting status of async port      }
  169. {number PORTN.  True indicates that a character is waiting to be input.}
  170.  
  171. function CIS : boolean;
  172.  
  173. begin {CIS}
  174.   if DEBUG
  175.     then
  176.       CIS := keypressed
  177.     else
  178.       begin
  179.         CC;
  180.         CIS := (port[COM_LSR[PORTN]] and COM_DA_MASK) > 0
  181.       end
  182. end; {CIS}
  183. {.PA}
  184. {This procedure outputs character CH to async port number PORTN.  If   }
  185. {CARRIER is true it will verify that carrier is still present first.   }
  186.  
  187. procedure CO(CH:char);
  188.  
  189. begin {CO}
  190.   if DEBUG or SNOOP
  191.     then
  192.       write(trm,CH);
  193.   if not DEBUG
  194.     then
  195.       begin
  196.         CC;
  197.         while (port[COM_LSR[PORTN]] and COM_TE_MASK) = 0 do
  198.           TASKSWITCH;
  199.         port[COM_DBR[PORTN]] := byte(ord(CH))
  200.       end
  201. end; {CO}
  202.  
  203.  
  204.  
  205.  
  206.  
  207. {This procedure outputs a LINETYPE string LN to async port number PORTN}
  208.  
  209. procedure COL(LN:LINETYPE);
  210.  
  211. var
  212.     I : integer;
  213.  
  214. begin {COL}
  215.   for I := 1 to length(LN) do
  216.     CO(LN[I])
  217. end; {COL}
  218.  
  219.  
  220.  
  221.  
  222.  
  223. {This procedure outputs a LINETYPE string LN to async port number PORTN }
  224. {followed by a carriage return, line feed.                              }
  225.  
  226. procedure COLN(LN:LINETYPE);
  227.  
  228. begin {COLN}
  229.   COL (LN+^M+^J)
  230. end; {COLN}
  231. {.PA}
  232. {This procedure inputs character CH from async port number PORTN with  }
  233. {optional input time-out.  TIMELIMIT is expressed in seconds and if it }
  234. {is zero no time-out will occur.  It will also verify that carrier is  }
  235. {still present if CARRIER is set to true.  If ABORTABLE is set to true }
  236. {and a control-C is input, this procedure will abort the program.      }
  237.  
  238. procedure CI(var CH:char);
  239.  
  240. const
  241.       TICS_PER_SECOND                   = 18.2065;       {system clock }
  242.       COM_DA_MASK                       = $01;           {receiver data}
  243.       COM_DBR : array [1..2] of integer = ($03F8,$02F8); {data buffer  }
  244.       COM_LSR : array [1..2] of integer = ($03FD,$02FD); {line status  }
  245.  
  246. var
  247.     STOP : boolean;
  248.     STOPTIME : real;
  249.  
  250. begin {CI}
  251.   STOP := false;
  252.   STOPTIME := SYSTTIME + TIMELIMIT * TICS_PER_SECOND;
  253.   while not STOP do
  254.     begin
  255.       if (SYSTTIME>STOPTIME) and (TIMELIMIT<>0)
  256.         then
  257.           begin
  258.             COLN(^G+' INPUT TIMEOUT!');
  259.             halt
  260.           end;
  261.       if CIS
  262.         then
  263.           begin
  264.             if DEBUG
  265.               then
  266.                 read(kbd,CH)
  267.               else
  268.                 CH := chr(port[COM_DBR[PORTN]]);
  269.             STOP := true
  270.           end
  271.         else
  272.           TASKSWITCH
  273.     end; {while}
  274. if ABORTABLE and (chr(ord(CH) and $7F) = ^C)
  275.     then
  276.       begin
  277.         COLN(^G+'^C ABORTED BY USER');
  278.         halt
  279.       end
  280. end; {CI}
  281. {.PA}
  282. {This procedure inputs a LINETYPE string LN from async port number     }
  283. {PORTN with echo and optional time-out.  The TIMELIMIT is in seconds   }
  284. {and if it is zero no time-out will occur.  It will also verify that   }
  285. {carrier is still present if CARRIER is set to true.  If ABORTABLE is  }
  286. {set to true and a control-C is input, this procedure will abort the   }
  287. {program.  This procedure processes a control-H as a destructive back- }
  288. {space and a control-X as cancel and reenter.                          }
  289.  
  290. procedure CILN(var LN:LINETYPE);
  291.  
  292. var
  293.     I : integer;
  294.     CH : char;
  295.  
  296. begin {CILN}
  297.   LN := '';
  298.   repeat
  299.     CI(CH);
  300.     case CH of
  301.       ^H : begin
  302.              if length(LN) > 0
  303.                then
  304.                  COL (^H+' '+^H);
  305.              LN := copy(LN,1,length(LN)-1)
  306.            end;
  307.       ^M : CO(CH);
  308.       ^J : ;
  309.       ^X : begin
  310.              COLN('^X');
  311.              COL ('INPUT CANCELLED, REENTER: ');
  312.              LN := ''
  313.            end;
  314.     else
  315.       begin
  316.         CO(CH);
  317.         LN := LN+CH
  318.       end
  319.     end {case}
  320.   until CH = ^M;
  321.   CO(^J)
  322. end; {CILN}
  323. {.PA}
  324. {This procedure will output the LINETYPE string PROMPT as an input     }
  325. {prompt and input the real number NUMBER with optional range checking. }
  326. {if LOW=0 and HIGH=0 then no range checking will be performed.  Input  }
  327. {processing is the same as for procedure CILN.                         }
  328.  
  329. procedure CIREAL(PROMPT:LINETYPE; LOW,HIGH:real; var NUMBER:real);
  330.  
  331.   function LEFTJ(N:real) : LINETYPE; {real to left-justified string}
  332.  
  333.   var
  334.       TEMP : LINETYPE;
  335.  
  336.   begin {LEFTJ}
  337.     str(N,TEMP);
  338.     LEFTJ := TEMP
  339.   end; {LEFTJ}
  340.  
  341. var
  342.     LN : LINETYPE;
  343.     TEST : integer;
  344.  
  345. begin {CIREAL}
  346.   COL (PROMPT);
  347.   CILN(LN);
  348.   val(LN,NUMBER,TEST);
  349.   if (length(LN)=0) or (TEST<>0)
  350.     then
  351.       begin
  352.         COLN(^G+'Error: Non-numeric value entered, try again.');
  353.         COLN('');
  354.         CIREAL(PROMPT,LOW,HIGH,NUMBER)
  355.       end;
  356.   if (LOW=0) and (HIGH=0)
  357.     then
  358.     else
  359.       if (NUMBER<LOW) or ((NUMBER>HIGH) and (HIGH<>0))
  360.         then
  361.           begin
  362.             COL (^G+'Error: Expected a number ');
  363.             if NUMBER<LOW
  364.               then
  365.                 COLN('greater than or equal to '+LEFTJ(LOW))
  366.               else
  367.                 COLN('from '+LEFTJ(LOW)+' to '+LEFTJ(HIGH));
  368.             COLN('');
  369.             CIREAL(PROMPT,LOW,HIGH,NUMBER)
  370.           end
  371. end; {CIREAL}
  372. {.PA}
  373. {This procedure will output the LINETYPE string PROMPT as an input     }
  374. {prompt and input the integer NUMBER with optional range checking.     }
  375. {if HIGH=0 then no high range checking will be performed.  Input       }
  376. {processing is the same as for procedure CILN.                         }
  377.  
  378. procedure CIINT(PROMPT:LINETYPE; LOW,HIGH:integer; var NUMBER:integer);
  379.  
  380.   function LEFTJ(N:integer) : LINETYPE; {int to left-justified string  }
  381.  
  382.   var
  383.       TEMP : LINETYPE;
  384.  
  385.   begin {LEFTJ}
  386.     str(N,TEMP);
  387.     LEFTJ := TEMP
  388.   end; {LEFTJ}
  389.  
  390. var
  391.     R : real;
  392.  
  393. begin {CIINT}
  394.   CIREAL(PROMPT,0,0,R);
  395.   if R > maxint
  396.     then
  397.       begin
  398.         COLN(^G+'Error: Expected an integer less than 32768');
  399.         COLN('');
  400.         CIINT(PROMPT,LOW,HIGH,NUMBER);
  401.         R := LOW
  402.       end;
  403.   if (trunc(R)<>R) or (R<LOW) or ((R>HIGH) and (HIGH<>0))
  404.     then
  405.       begin
  406.         COL (^G+'Error: Expected an integer ');
  407.         if (trunc(R)<>R) or (R<LOW)
  408.           then
  409.             COLN('greater than or equal to '+LEFTJ(LOW))
  410.           else
  411.             COLN('from '+LEFTJ(LOW)+' to '+LEFTJ(HIGH));
  412.         COLN('');
  413.         CIINT(PROMPT,LOW,HIGH,NUMBER);
  414.         R := LOW
  415.       end;
  416.   NUMBER := trunc(R)
  417. end; {CIINT}
  418.