home *** CD-ROM | disk | FTP | other *** search
/ Beijing Paradise BBS Backup / PARADISE.ISO / software / BBSDOORW / PPL4C11.ZIP / TERM.C < prev    next >
Encoding:
C/C++ Source or Header  |  1995-11-18  |  13.9 KB  |  534 lines

  1. /*
  2. **                    --- term.c ---
  3. **
  4. **  EXAMPLE CODE: Terminal emulator. Can transfer files using
  5. **  ASCII, XMODEM, YMODEM, and ZMODEM protocols.
  6. **
  7. **  See TERM.CFG for configuration parameters.
  8. **
  9. **  Link with ALLOCSEG, TERM_IO, MODEM_IO, DIR_IO, CRC16, CRC32, DOS,
  10. **  AMODEM, XYMODEM, XYPACKET, SI, OPCODES, and WIN_IO. Files SI.C and
  11. **  OPCODES.C used for scripts only. See TERM makefiles and TERM.CFG.
  12. **
  13. **  Do NOT select YMODEM-G when using a null modem cable unless you are
  14. **  certain that RTS & CTS are reversed ( this is usually not true ).
  15. **
  16. **  This example program (not the PCL4C library) is donated to
  17. **  the Public Domain by MarshallSoft Computing, Inc. It is
  18. **  provided as an example of the use of the PCL4C.
  19. **
  20. */
  21.  
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <ctype.h>
  25. #include <fcntl.h>
  26. #include <string.h>
  27. #include <sys\types.h>
  28. #include <sys\stat.h>
  29. #include <malloc.h>
  30. #include <dos.h>
  31. #include <io.h>
  32. #include <conio.h>
  33. #include "term.cfg"
  34. #include "pcl4c.h"
  35. #include "ascii.h"
  36. #include "term.h"
  37. #include "dir_io.h"
  38. #include "term_io.h"
  39. #include "dos_io.h"
  40. #include "modem_io.h"
  41. #include "crc16.h"
  42. #include "crc32.h"
  43. #include "xymodem.h"
  44. #include "zmodem.h"
  45. #include "amodem.h"
  46. #include "term.h"
  47. #include "allocseg.h"
  48. #include "timing.h"
  49. #include "win_io.h"
  50. #if SCRIPTS
  51. #include "si.h"
  52. #endif
  53.  
  54. #define DEBUG 0
  55.  
  56. #define ATTN_CHAR  0x1a
  57. #define ABORT_CHAR CAN
  58.  
  59. #define FALSE 0
  60. #define TRUE !FALSE
  61. #define WORD unsigned int
  62.  
  63. #define NORMAL  0x07
  64. #define INVERSE 0x70
  65. #define MESSAGE_POS 48
  66.  
  67. /* local prototypes */
  68.  
  69. void ProcessESC(void);
  70. void ShowStatus(void);
  71. void StatusMsg(char,char *);
  72. void CheckWin(int);
  73. void SetASCII(void);
  74. void SetX(void);
  75. void SetY(void);
  76. void SetG(void);
  77. void SetZ(void);
  78.  
  79. /*** Global variables ***/
  80.  
  81. #define SIOBUF_SIZE 2048
  82. #define BLKBUF_SIZE 1024
  83.  
  84. int  LastError = 0;     /* last reported error # */
  85. int  Port;              /* current COM port [0..3] */
  86. char FileSpec[15];      /* file name specification */
  87. char FileName[15];      /* file name buffer */
  88. char Buffer[BLKBUF_SIZE];      /* 1K block buffer */
  89. char *BaudRate[10] =  {"300","600","1200","2400","4800","9600",
  90.                        "19200","38400","57600","115200"};
  91. int  BaudCode;          /* baud rate code ( index into BaudRate[] ) */
  92. char *ModelText[4] = {"Small","Compact","Medium","Large"};
  93. char NCGchar   = NAK;
  94. int  OneKflag  = FALSE;
  95. int  BatchFlag = FALSE;
  96. char Protocol  = 'X';
  97. char TermChar  = 0x00;
  98. int  CharPace  = 0;
  99. int  Timeout   = 10;
  100. int  EchoFlag  = TRUE;
  101. int  TraceFlag = FALSE;
  102. int  Stream    = FALSE;
  103.  
  104. int MultiUART = 0;
  105. int MultiIRQ = 0;
  106. int MultiStatus = 0;
  107.  
  108. /*** main program ***/
  109.  
  110. void main(int argc,char *argv[])
  111. {int DataFlag = FALSE;
  112.  char c;
  113.  int i, k;
  114.  int n, rc;
  115.  int Delta;         /* delta port status */
  116.  int Status;        /* port status */
  117.  int Version;
  118.  char Temp[81];
  119.  /* right number of parameters ? */
  120.  if((argc<3)||(argc>4))
  121.      {printf("Usage: 'TERM port baud' -- example 'TERM 1 9600 {script}'\n");
  122.       exit(1);
  123.      }
  124.  /* get port number from command line */
  125.  Port = atoi(argv[1]) - 1;
  126.  if((Port<0) || (Port>15))
  127.      {printf("Port must be 1 to 16\n");
  128.       exit(1);
  129.      }
  130.  /* get baud rate from command line */
  131.  BaudCode = BaudMatch(argv[2]);
  132.  if(BaudCode<0)
  133.      {printf("Cannot recognize baud rate = %s\n",argv[2]);
  134.       exit(1);
  135.      }
  136.  /* can ZMODEM stream ? */
  137.  if(BaudCode<=Baud19200) Stream = TRUE;
  138.  else Stream = FALSE;
  139.  
  140. #if 0
  141.  /*** Custom Configuration: 4 port card ***/
  142.  SioIRQ(COM1,IRQ4);
  143.  SioIRQ(COM2,IRQ3);
  144.  SioIRQ(COM3,IRQ4);
  145.  SioIRQ(COM4,IRQ3);
  146. #endif
  147.  
  148. #if 0
  149.  /*** Custom Configuration: DigiBoard PC/8 ***/
  150.  MultiUART = 0x100; MultiIRQ = IRQ5; MultiStatus = 0x140;
  151.  printf("Configuring DigiBoard as COM1-COM8 (IRQ%d) @ 0x%x",
  152.     MultiIRQ,MultiUART);
  153.  SioDelay(18);
  154.  /* use 0x140 for odd IRQs & 0x141 for even IRQs */
  155.  SioPorts(8,COM1,MultiStatus,DIGIBOARD);
  156.  /* set DigiBoard UART addresses */
  157.  ErrorCheck( SioUART(Port,MultiUART+8*Port) );
  158.  /* set DigiBoard for IRQ */
  159.  ErrorCheck( SioIRQ(Port,MultiIRQ) );
  160. #endif
  161.  
  162. #if 0
  163.  /*** Custom Configuration: BOCA 16 port dumbcard ***/
  164.  MultiUART = 0x280; MultiIRQ = IRQ11; MultiStatus = MultiUART + 7;
  165.  printf("Configuring BOCA Board as COM1-COM16 (IRQ%d) @ 0x%x",
  166.     MultiIRQ,MultiUART);
  167.  SioDelay(18);
  168.  /* use base port + 7 */
  169.  SioPorts(16,COM1,MultiStatus,BOCABOARD);
  170.  /* set BOCA Board UART addresses */
  171.  ErrorCheck( SioUART(Port,MultiUART+8*Port) );
  172.  /* set BOCA Board for IRQ */
  173.  ErrorCheck( SioIRQ(Port,MultiIRQ) );
  174. #endif
  175.  
  176.  /********************************************************/
  177.  
  178.  /* setup receive buffer */
  179.  ErrorCheck( SioRxBuf(Port,AllocSeg(2048),Size2K) );
  180.  if(SioInfo('I'))
  181.    {/* setup transmit buffer */
  182.     ErrorCheck( SioTxBuf(Port,AllocSeg(2048),Size2K) );
  183.    }
  184.  /* set parms & reset (initialize) COM port */
  185.  SioParms(Port,NoParity,OneStopBit,WordLength8);
  186.  /* reset port */
  187.  rc = SioReset(Port,BaudCode);
  188.  if(rc<0) rc = SioReset(Port,BaudCode);
  189.  if(rc<0)
  190.    {printf("Cannot reset COM%d\n",1+Port);
  191.     exit(1);
  192.    }
  193.  /* set DTR and RTS */
  194.  SioDTR(Port,'S');
  195.  SioRTS(Port,'S');
  196.  
  197.  /*
  198.  ** !!! Define window screens !!!
  199.  ** Use win_io function from now on
  200.  */
  201.  
  202.  /* define main screen window */
  203.  CheckWin( WinCreate(SCR_WIN,  0,0, 23,79) );
  204.  CheckWin( WinNormal(SCR_WIN) );
  205.  CheckWin( WinClear(SCR_WIN) );
  206.  /* define left status window */
  207.  CheckWin( WinCreate(LFT_WIN, 24,0, 24,30) );
  208.  CheckWin( WinInverse(LFT_WIN) );
  209.  CheckWin( WinClear(LFT_WIN) );
  210.  /* define right status window */
  211.  CheckWin( WinCreate(RGT_WIN, 24,32, 24,79) );
  212.  CheckWin( WinInverse(RGT_WIN) );
  213.  CheckWin( WinClear(RGT_WIN) );
  214.  
  215.  /* display status message */
  216.  ShowStatus();
  217.  /* display some info */
  218.  WinPutString(SCR_WIN,"TERM: 11/11/95 [C/C++]\n\n");
  219.  Version = SioInfo('V');
  220.  sprintf(Temp,"      Library: %d.%d\n",Version>>4,0x0f&Version);
  221.  WinPutString(SCR_WIN,Temp);
  222.  sprintf(Temp," Memory Model: %s\n",ModelText[3&SioInfo('M')] );
  223.  WinPutString(SCR_WIN,Temp);
  224.  strcpy(Temp,"   Interrupts: ");
  225.  if(SioInfo('I')) strcat(Temp,"YES\n");
  226.  else strcat(Temp,"NO\n");
  227.  WinPutString(SCR_WIN,Temp);
  228.  WinPutString(SCR_WIN,"   Parameters: 8N1\n");
  229. #if RTS_CTS_CONTROL
  230.  SioFlow(Port,10*ONE_SECOND);
  231.  WinPutString(SCR_WIN," Flow Control: YES\n");
  232. #else
  233.  WinPutString(SCR_WIN," Flow Control: NO\n");
  234. #endif
  235.  
  236.  /* Set FIFO level */
  237.  WinPutString(SCR_WIN,"   16550 UART: ");
  238.  if( SioFIFO(Port,LEVEL_14) ) WinPutString(SCR_WIN,"YES\n");
  239.  else WinPutString(SCR_WIN,"NO\n");
  240.  /* clear PCL4C receive buffer */
  241.  ErrorCheck( SioRxClear(Port) );
  242.  WinPutChar(SCR_WIN,'\n');
  243.  
  244.  /* wait for other end to say its ready */
  245.  WinPutString(SCR_WIN,"  <<Waiting for DSR>>\n");
  246.  while( !SioDSR(Port) )
  247.      {if(kbhit()||SioBrkKey()) MyExit(0,"Aborted by user");
  248.       WinPutChar(SCR_WIN,'.');
  249.       SioDelay(18);
  250.      }
  251.  WinPutString(SCR_WIN,"  <<DSR on>>\n");
  252.  
  253. #if RTS_CTS_CONTROL
  254.  WinPutString(SCR_WIN,"  <<Waiting for CTS>>\n");
  255.  while( !SioCTS(Port) )
  256.      {if(kbhit()||SioBrkKey()) MyExit(0,"Aborted by user");
  257.       WinPutChar(SCR_WIN,'.');
  258.       SioDelay(18);
  259.      }
  260.  WinPutString(SCR_WIN,"  <<CTS on>>\n");
  261. #endif
  262.  
  263. #if AT_COMMAND_SET
  264.  /* initialize (Hayes compatible) modem */
  265.  ModemSendTo(Port,4,"AT!");
  266.  ModemEcho(Port,10);
  267.  ModemSendTo(Port,4,"AT E1 S7=60 S11=60 V1 X1 Q0!");
  268.  if(ModemWaitFor(Port,5*ONE_SECOND,TRUE,"OK"))
  269.    {/* modem is ready */
  270.     WinPutString(SCR_WIN,"\n  <<MODEM READY>>");
  271.    }
  272.  else WinPutString(SCR_WIN,"\n  <<WARNING: Expected OK not received>>\n");
  273. #endif
  274.  SetX();
  275.  
  276. #if SCRIPTS
  277.  if(argc==4)
  278.    {/* call script interpreter */
  279.     sprintf(Temp,"Starting script %s\n",argv[3]);
  280.     WinPutString(SCR_WIN,Temp);
  281.     i = si(Port,argv[3],FALSE);
  282.     if(i<0) SaySiErr(i);
  283.    }
  284. #endif
  285.  
  286.  /* enter terminal loop */
  287.  SioRxClear(Port);
  288.  WinPutString(SCR_WIN,"  <<Entering terminal loop>>\n");
  289.  while(1)
  290.      {/* Control-BREAK ? */
  291.       if(SioBrkKey()) MyExit(0,"User pressed Ctrl-BREAK");
  292.       /* keep TX rolling */
  293.       SioTxFlush(Port);
  294.       /* was key pressed ? */
  295.       if(kbhit())
  296.           {/* read key press */
  297.            i = getch();
  298.            /* ^B sends BREAK */
  299.            if((char)i=='\02')
  300.                {/* send break */
  301.                 WriteMsg("Sending BREAK");
  302.                 SioBrkSig(Port,'A');
  303.                 SioDelay(10);
  304.                 SioBrkSig(Port,'C');
  305.                }
  306.            else if((char)i==ATTN_CHAR)
  307.                {/* process user's request */
  308.                 ProcessESC();
  309.                 ShowStatus();
  310.                 continue;
  311.                }
  312.            else CharPut(Port,(char)i);
  313.           }
  314.       /* was break detected ? */
  315.       if( SioBrkSig(Port,'D') ) WriteMsg("BREAK detected ");
  316.       /* check DSR */
  317.       if(TestDSR(Port))
  318.         {/* any incoming over serial port ? */
  319.          i = CharGet(Port,1);
  320.          if(i>-1)
  321.              {/* good character */
  322.               if(DataFlag&((i<0x20)||(i>0x7e)))
  323.                   {WinPutChar(SCR_WIN,'^');
  324.                    WinPutChar(SCR_WIN,(char)('@'+i));
  325.                   }
  326.               else WinPutChar(SCR_WIN,(char)i);
  327.              }
  328.         }
  329.      } /* end -- key pressed */
  330. }
  331.  
  332. /*** find baud rate string in table ***/
  333.  
  334. int BaudMatch(char *ptr)
  335. {int i;
  336.  /* find baud rate in table */
  337.  for(i=0;i<10;i++) if(strcmp(BaudRate[i],ptr)==0) return(i);
  338.  return(-1);
  339. }
  340.  
  341. /*** user pressed Escape */
  342.  
  343. void ProcessESC(void)
  344. {int i;
  345.  int rc;
  346.  int c1, c2;
  347.  char Answer[2]; /* answer array */
  348.  /* user pressed ATTN_CHAR */
  349.  Answer[0] = '?';
  350.  Answer[1] = '\0';
  351.  WriteMsg("Q)uit P)rotocol S)end R)eceive T)race: ");
  352.  ReadMsg(Answer,1,39);
  353.  if(strlen(Answer)) switch(toupper(Answer[0]))
  354.      {
  355.       case 'T':
  356.           /*SetIOtrace(TRUE);*/
  357.           TraceFlag = !TraceFlag;
  358.           WriteIntMsg("Trace = ",1&TraceFlag);
  359.           MsgEcho(TraceFlag);
  360.           break;
  361.       case 'P':
  362.           WriteMsg("A)scii X)modem Y)modem Z)modem: ");
  363.           ReadMsg(Answer,1,32);
  364.           if(strlen(Answer)) switch( toupper(Answer[0]) )
  365.                {case 'A':
  366.                     SetASCII();
  367.                     break;
  368.                 case 'X':
  369.                     SetX();
  370.                     break;
  371.                 case 'Y':
  372.                     SetY();
  373.                     break;
  374.                 case 'Z':
  375.                     SetZ();
  376.                     break;
  377. #if RTS_CTS_CONTROL
  378.                 case 'G':
  379.                     SetG();
  380.                     break;
  381. #endif
  382.                 default:
  383.                     WriteMsg("Must answer X, Y, or Z");
  384.                     break;
  385.                }
  386.           ShowStatus();
  387.           break;
  388.       case 'Q':
  389.           SetIOtrace(FALSE);
  390.           MyExit(0,"User QUIT");
  391.           break;
  392.       case 'R':
  393.           StatusMsg(ABORT_CHAR,"aborts");
  394.           *FileName = '\0';
  395.           switch(Protocol)
  396.              {case 'A':
  397.                  /* Ascii */
  398.                  RxAscii(Port,FileName,Buffer,BLKBUF_SIZE,SIOBUF_SIZE,FALSE,TermChar,Timeout,EchoFlag);
  399.                  break;
  400.               case 'X':
  401.                  XmodemRx(Port,FileName,Buffer,NCGchar);
  402.                  break;
  403.               case 'Y':
  404.                  YmodemRx(Port,Buffer,NCGchar);
  405.                  break;
  406.               case 'Z':
  407.                  ZmodemRx(Port,Stream);
  408.                  break;
  409.              }
  410.           while(kbhit()) getch();
  411.           break;
  412.       case 'S':
  413.           *FileName = '\0';
  414.           StatusMsg(ABORT_CHAR,"aborts");
  415.           switch(Protocol)
  416.              {case 'A': /* Ascii */
  417.                  TxAscii(Port,FileName,Buffer,BLKBUF_SIZE,FALSE,CharPace,TermChar,EchoFlag);
  418.                  break;
  419.               case 'X':
  420.                  XmodemTx(Port,FileName,Buffer,OneKflag);
  421.                  break;
  422.               case 'Y':
  423.                  YmodemTx(Port,FileName,Buffer);
  424.                  break;
  425.               case 'Z':
  426.                  ZmodemTx(Port,FileName,Stream);
  427.                  break;
  428.              }
  429.           while(kbhit()) getch();
  430.           break;
  431.      default:
  432.           WriteHexMsg("Must answer Q, P, S, R, or T, not ",*Answer);
  433.           break;
  434.     } /* end switch */
  435. }
  436.  
  437. /*** show menu message ***/
  438.  
  439. void StatusMsg(char Attn,char *Msg)
  440. {char Temp[50];
  441.  sprintf(Temp," COM%d %s %c [ ^%c %s ]",
  442.          1+Port,BaudRate[BaudCode],Protocol,Attn+'@',Msg);
  443.  WinClear(LFT_WIN);
  444.  WinPutString(LFT_WIN,Temp);
  445.  WinGetPos(SCR_WIN,NULL,NULL);
  446. }
  447.  
  448. void ShowStatus(void)
  449. {
  450.  StatusMsg(ATTN_CHAR,"for Menu");
  451. }
  452.  
  453. /*** exit program ***/
  454.  
  455. void MyExit(int code, char *msg)
  456. {int i, rc;
  457.  char Temp[80];
  458.  if(code<0)
  459.     {WinPutChar(SCR_WIN,' ');
  460.      SioError(code);
  461.      WinPutChar(SCR_WIN,'\n');
  462.     }
  463.  SioDone(Port);
  464.  sprintf(Temp,"\rTERMINATING: %s\n",msg);
  465.  WinPutString(SCR_WIN,Temp);
  466.  SetCursor(6,7);
  467.  exit(0);
  468. }
  469.  
  470. /*** check for error ***/
  471.  
  472. void ErrorCheck(int Code)
  473. {/* trap PCL error codes */
  474.  if(Code<0)
  475.      {
  476.       WinPutChar(SCR_WIN,' ');
  477.       SioError(Code);
  478.       SioDone(Port);
  479.       exit(1);
  480.      }
  481. } /* end ErrorCheck */
  482.  
  483. int GetBufSize(void)
  484. {int BufSize = SIOBUF_SIZE;
  485.  return BufSize;
  486. }
  487.  
  488. void CheckWin(int n)
  489. {if(n<0)
  490.   {printf("\nWin error %d\n\n",n);
  491.    exit(1);
  492.   }
  493. }
  494.  
  495. /* set protocol parameters */
  496.  
  497. void SetASCII(void)
  498. {Protocol = 'A';
  499.  TermChar = 0x18;  /* CAN or control-X */
  500.  CharPace = 0;     /* no inter-byte delay */
  501.  Timeout = 7;      /* timeout after 7 seconds */
  502.  EchoFlag = TRUE;  /* do local echo */
  503.  WriteMsg("Protocol = ASCII");
  504. }
  505.  
  506. void SetX(void)
  507. {Protocol = 'X';
  508.  OneKflag = FALSE;
  509.  BatchFlag = FALSE;
  510.  NCGchar = NAK;
  511.  WriteMsg("Protocol = XMODEM");
  512. }
  513.  
  514. void SetY(void)
  515. {Protocol = 'Y';
  516.  OneKflag = TRUE;
  517.  BatchFlag = TRUE;
  518.  NCGchar = 'C';
  519.  WriteMsg("Protocol = YMODEM");
  520. }
  521.  
  522. void SetG()
  523. {Protocol = 'G';
  524.  OneKflag = TRUE;
  525.  BatchFlag = TRUE;
  526.  NCGchar = 'G';
  527.  WriteMsg("Protocol = YMODEM-G");
  528. }
  529.  
  530. void SetZ(void)
  531. {Protocol = 'Z';
  532.  WriteMsg("Protocol = ZMODEM");
  533. }
  534.