home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / victor9000.zip / vickermit.c next >
Text File  |  1991-04-18  |  56KB  |  2,055 lines

  1. /************************************************************************
  2. *                                    *
  3. *            VICTOR  VERSION 1.0                *
  4. *                                    *
  5. *************************************************************************/
  6. /************************************************************************
  7. *                                    *
  8. *                KERMIT                    *
  9. *                                    *
  10. *    This implementation is based on the sample implementation    *
  11. *    supplied in chapter 2 of the Kermit Protocol Manual. This    *
  12. *    version of Kermit was code (copied) and augmented (my own    *
  13. *    ideas) by:                            *
  14. *            W. Hertha                    *
  15. *            Victor Technologies (Canada) Ltd.        *
  16. *            55 Savage Drive                    *
  17. *            Cambridge, Ontario, Canada            *
  18. *            N1R 5T1                        *
  19. *                                    *
  20. *    Thanks are in order to Dr. Joe Angel of the University of     *
  21. *    Saskatchewan for taking care of all the details of  getting    *
  22. *    the code  and documentation,  and providing a DEC TOPS 20    *
  23. *    system to "talk" to and his  efforts  in the debugging of    *
  24. *    this product.                            * 
  25. *                                    *
  26. *************************************************************************
  27. *                                    *
  28. * This implementation is missing (or varies in)the following        *
  29. * - The SET command is implemented using softkeys            *
  30. * - Only ASCII files may be transmitted                    *
  31. * - Server functions are not implemented                *
  32. * - There is limited massaging of the file name supplied by the host    *
  33. *   thus hosts with weird naming conventions may cause problems on a    *
  34. *   receive                                *
  35. *                                    *
  36. *************************************************************************/
  37.  
  38. /************************************************************************
  39. *                                    *
  40. *            Coding Conventions                *
  41. *                                    *
  42. * This is a list of conventions                        *
  43. * [1] All #define names are capitalised                    *
  44. * [2] All global variables have the first character capitalised        *
  45. * [3] Local variables, function names are in lower case            *
  46. * [4] Other than a module prolog, in-line commenting is limited        *
  47. *                                    *
  48. *************************************************************************/
  49.  
  50. /************************************************************************
  51. *                                    *
  52. * System dependancies                            *
  53. *                                    *
  54. * An attempt has been made to reduce system dependancies. The areas    *
  55. * which are system dependant are as follows:                *
  56. *    1.  Serial port interfaceing                    *
  57. *    2.  CRT display interfaceing                    *
  58. *    3.  File system    (MS-DOS file naming conventions)        *
  59. *                                    *
  60. * Serial Port Interface                            *
  61. * In order to reduce the effects, all interfaceing to the serial port    *
  62. * is done through a series of routines grouped together towards the    *
  63. * end of the listing.                             *
  64. *                                    *
  65. * CRT display interface                            *
  66. * Here also most of the interfaces to the display is performed by     *
  67. * low level routine. In fact many are actually just defines. Defines    *
  68. * where used so that systems that do not support VT-52 escape sequences    *
  69. * may replace these with functions. It is worth while to note the    *
  70. * following features of the display (further information may be found    *
  71. * in the Operators Reference Guide or the Supplemental Technical    *
  72. * Reference material).                            *
  73. * 1.  Screen addressing is 1 relative, that is HOME is (1,1)        *
  74. *                                    *
  75. *************************************************************************/
  76.  
  77. #include "stdio.h"
  78.  
  79. #define    MAXPACK        94        /* Maximum Packet Size */
  80.  
  81. #define    SOH        '\001'        /* Start of header */
  82. #define SP        ' '        /* Space */
  83. #define CR        '\015'        /* Carriage Return */
  84. #define    LF        '\012'        /* Line feed */
  85. #define    BEL        '\007'        /* Bell */
  86. #define    BS        '\010'        /* Back Space */
  87. #define DEL        '\177'        /* Delete (Rubout) */
  88. #define    REQCAN        '?'
  89.  
  90. #define MAXTRY        5        /* # of times to retry a package */
  91.  
  92. #define    MYQUOTE        '#'        /* Quote Character used Locally */
  93. #define    MYPAD        0        /* Number of Padding characters */
  94. #define MYPCHAR        0        /* Local padding character */
  95. #define    MYEOL        CR        /* Local End-Of-Line character */
  96. #define MYTIME        10        /* Local time out time in seconds */
  97.  
  98. #define PORTA        0        /* Code for port A */
  99. #define PORTB        1        /* Code for Port B */
  100. #define CR2        2        /* Code for control register 2 */
  101. #define CR3        3
  102. #define CR4        4
  103. #define CR5        5
  104.  
  105. #define    RX        1        /* Receive character available */
  106. #define TX        4        /* Send buffer empty */
  107. #define    DCD        8        /* Data Carrier Detect */
  108.  
  109. #define    SEND        1        /* Sending mode code */
  110. #define RECEIVE        2        /* Receiving mode code */
  111.  
  112. #define    STATUS_LINE    25        /* Line number of status line on CRT */
  113. #define    SHOW_BASE    5        /* Starting line of "Show" data */
  114. #define    POS_MAXPACK    0+SHOW_BASE
  115. #define    POS_MYPCHAR    1+SHOW_BASE
  116. #define    POS_MYPAD     2+SHOW_BASE
  117. #define    POS_MYTIME    3+SHOW_BASE
  118. #define    POS_MYEOL    4+SHOW_BASE
  119. #define    POS_MYQUOTE    5+SHOW_BASE
  120. #define    POS_WARN    6+SHOW_BASE
  121. #define    POS_ECHO    7+SHOW_BASE
  122. #define    POS_BAUD    8+SHOW_BASE
  123. #define    POS_BREAK    9+SHOW_BASE
  124. #define    POS_PORT    10+SHOW_BASE
  125.  
  126. #define    ENDFIL        '\034'        /* End of Logical file */
  127. #define    ENDSEC        '\035'        /* End of help message section */
  128. #define    ENDPAG        '\037'        /* End of page */
  129. #define    ENDSS        '\003'        /* End of subsection */
  130. #define    ENQUIRE        '\005'        /* Enquirey during help */
  131.  
  132. #define    ROOT_H        1        /* Root help */
  133. #define    SET_H        2
  134. #define    ON_H        3
  135. #define    ECHO_H        4
  136. #define    WARN_H        5
  137. #define    BAUD_H        6
  138. #define    TRACE_H        7
  139. #define    GETCP_H        8
  140.  
  141. #define tochar(ch)    (char) (ch + ' ')
  142. #define unchar(ch)    (ch - ' ')
  143. #define ctl(ch)        ((ch ^ 64) & 0x0ff)
  144. /************************************************************************
  145. *    Get character from keyboard but do not echo
  146. */
  147. #define    getnec()    (bdos(7) & 0x0ff)
  148. /************************************************************************
  149. *    Get keyboard status
  150. */
  151. #define    getkbs()    (bdos(11) & 0x0ff)
  152. /************************************************************************
  153. *    Clear keyboard buffer
  154. */
  155. #define clrkb()        for (;getkbs();getnec())
  156. /************************************************************************
  157. *    Get MSDOS Version ID
  158. */
  159. #define dosid()        ((bdos(30) >> 8) & 0x0ff)
  160. /************************************************************************
  161. *    Put a string to standard output
  162. */
  163. #define    putstr(str)    puts(str,stdout)
  164. /************************************************************************
  165. *    Put a string in inverse video to standard output
  166. */
  167. #define    putistr(str)    printf("\033p%s\033q",str)
  168. /************************************************************************
  169. *    Put out a menu on the 25th line
  170. */
  171. #define    putmenu(str)    printf("\033j\033x1\033Y8 \033K%s\033y1\033k",str)
  172. /************************************************************************
  173. *    Turn on the cursor
  174. */
  175. #define    cursr_on()    puts("\033y5",stdout)
  176. /************************************************************************
  177. *    Turn off cursor
  178. */
  179. #define    cursr_off()    puts("\033x5",stdout)
  180. /************************************************************************
  181. *    Clear to end of line X starting at column Y
  182. */
  183. #define    clear_eol(x,y)    printf("\033Y%c%c\033K",x+31,y+31)
  184. /************************************************************************
  185. *    Clear the screen
  186. */
  187. #define    clear_screen()    puts("\033E",stdout)
  188. /************************************************************************
  189. *    Move the cursor to home position
  190. */
  191. #define    home()        puts("\033H",stdout)
  192. /************************************************************************
  193. *    Position cursor at row X, column Y
  194. */
  195. #define    pos(x,y)    printf("\033Y%c%c",x+31,y+31)
  196. /************************************************************************
  197. *    Position cursor at row X, column Y and output character    ch
  198. */
  199. #define    plotc(x,y,ch)    printf("\033Y%c%c%c",x+31,y+31,ch)
  200. /************************************************************************
  201. *    Position cursor at row X, column Y and output inverse video character ch
  202. */
  203. #define    plotic(x,y,ch)    printf("\033Y%c%c\033p%c\033q",x+31,y+31,ch)
  204. /************************************************************************
  205. *    Position cursor at row X, column Y and output decimal (integer) number
  206. */
  207. #define    plotd(x,y,n)    printf("\033Y%c%c%d",x+31,y+31,n)
  208. /************************************************************************
  209. *    Position cursor at row X, column Y and output Unsigned long
  210. */
  211. #define    plotU(x,y,n)    printf("\033Y%c%c%U",x+31,y+31,n)
  212. /************************************************************************
  213. *    Position cursor at row X, column Y and output string s
  214. */
  215. #define plotstr(x,y,str)    printf("\033Y%c%c%s",x+31,y+31,str)
  216. /************************************************************************
  217. *    Position cursor at row X, column Y and output inverse video string s
  218. */
  219. #define plotistr(x,y,str)    printf("\033Y%c%c\033p%s\033q",x+31,y+31,str)
  220. /************************************************************************
  221. *    Position cursor at row X, column Y and output inverse video string s
  222. */
  223. #define plotustr(x,y,str)    printf("\033Y%c%c\0330%s\0331",x+31,y+31,str)
  224. /************************************************************************
  225. *    Check status of port
  226. */
  227. #define    sstatus(s,p)    (peek(p+2,0x0e004) & s)
  228.  
  229. /* */
  230. /************************************************************************
  231. *                                    *
  232. *        Defintion of Global Variables                *
  233. *                                    *
  234. *************************************************************************/
  235.  
  236. typedef    struct {
  237.     int    si;            /* Position in (send)trace buffer */
  238.     int    smnum[256];        /* (Send) message number */
  239.     char    smtype[256];        /* (Send) message type */
  240.     int    ri;            /* Position in (receive) trace buffer */
  241.     int    rmnum[256];        /* (Receive) message number */
  242.     char    rmtype[256];        /* (Receive) message type */
  243.     } TRACE_BUF;
  244.  
  245. TRACE_BUF
  246.     Trace;
  247.  
  248. int
  249.     Size,                /* Size of Present data */
  250.     N,                /* Message Number */
  251.     Rpsiz,                /* Maximum Receive packet size */
  252.     Spsiz,                /* Maximum Send Packet Size  */
  253.     Pad,                /* How much padding to send */
  254.     Timint,                /* Time out for remote host */
  255.     Numtry,                /* Number of retries for a package */
  256.     Oldtry;                /* Times Previous package retried */
  257.  
  258. char
  259.     State,                /* Present state of the automaton */
  260.     Padchar,            /* Padding character to send */
  261.     Eol,                /* End-of-line character to send */
  262.     Quote,                /* Quote character in in-coming data */
  263.     Filnam[50],            /* The file name */
  264.     Recpkt[MAXPACK],        /* Receive packet buffer */
  265.     Packet[MAXPACK];        /* Packet buffer */
  266.  
  267. int
  268.     Mypad        = MYPAD,
  269.     Mytime        = MYTIME,
  270.     Maxpack        = MAXPACK;
  271.  
  272. char
  273.     Break        = '\03',    /* Break code for DEC */
  274.     Mydel        = DEL,
  275.     Mypchar        = MYPCHAR,
  276.     Myquote        = MYQUOTE,
  277.     Myeol        = MYEOL;
  278.  
  279. int
  280.     Msdos20        = FALSE,    /* Operating system */
  281.     Display        = FALSE,    /* Display data as it is transmitted */
  282.     Echo        = FALSE,    /* Local Echo ON */
  283.     Warn        = TRUE,        /* File warning */
  284.     Port        = PORTA,    /* Serial Port to perform I/O */
  285.     Speed        = B1200;    /* Baud Rate */
  286.  
  287. unsigned char
  288.     Rate[] ={4,1,            /* 300 baud */
  289.         0x082,0,        /* 600 baud */
  290.         0x041,0,        /* 1200 baud */
  291.         0x020,0,        /* 2400 baud */
  292.         0x010,0,        /* 4800 baud */
  293.         0x008,0 },        /* 9600 baud */
  294.     cr2[2]    = {0x10, 0x10},
  295.     cr3[2]    = {0xe1, 0xe1},
  296.     cr4[2]    = {0x44, 0x44},
  297.     cr5[2]    = {0xea, 0xea};
  298.     
  299. FILE    *Fptr;                /* File pointer */
  300.  
  301. unsigned long int
  302.     Nch,                /* Number of characters transmitted */
  303.     Nmess;                /* Number of messages(Packetes) transmitted */
  304.  
  305. jmp_buf    escape;                /* Define environment of Longjump */
  306.  
  307. int    Msem;                /* Message semaphore */
  308. /* */
  309. /************************************************************************
  310. *                                    *
  311. *                MESSAGES                *
  312. *                                    *
  313. *************************************************************************/
  314.  
  315. char    *Pa[] = {
  316.         "Packet Size",
  317.         "Padding Character",
  318.         "Number of Padding characters",
  319.         "Time out (seconds)",
  320.         "End of Line character",
  321.         "Quote Character",
  322.         "File Warning",
  323.         "Local Echo",
  324.         "Baud Rate",
  325.         "Break Character",
  326.         "Port"};
  327.  
  328. char    *Ba[] = {
  329.         "300 Baud ",
  330.         "600 Baud ",
  331.         "1200 Baud",
  332.         "2400 Baud",
  333.         "4800 Baud",
  334.         "9600 Baud"};
  335.  
  336. char    Startms[] ="\033w\033H\033E\033i1";
  337. char    Endms[]      ="\033H\033z";
  338. char    Sys_id[]  ="KERMIT VICTOR 9000 ";
  339.  
  340. char    Root_m[]  ="\033p1 EXIT   \033q \033p2 SEND   \033q\
  341.  \033p3 RECEIVE\033q \033p4 SET    \033q \033p5 SHOW   \033q\
  342.  \033p6 TRACE  \033q \033p7 HELP   \033q \033p8 EXEC   \033q";
  343.  
  344. char    Set_m[]   ="\033p1 BAUD   \033q   \033p2 ECHO   \033q\
  345.    \033p3 WARNING\033q   \033p4 PARAMS.\033q   \033p5        \033q\
  346.    \033p6 RETURN \033q   \033p7 HELP   \033q";
  347.  
  348. char    Onoff_m[] ="\033p1 YES    \033q   \033p2 NO     \033q\
  349.    \033p         \033q   \033p         \033q   \033p         \033q\
  350.    \033p6 RETURN \033q   \033p7 HELP   \033q";
  351.  
  352. char    Baud_m[] ="\033p1 300    \033q   \033p2 600    \033q\
  353.    \033p3 1200   \033q   \033p4 2400   \033q   \033p5 4800   \033q\
  354.    \033p6 9600   \033q   \033p7 HELP   \033q";
  355.  
  356. char    Show_m[] ="\033p Hit <RETURN> to continue\033q";
  357.  
  358. char    Help_m[] ="\033p Hit <RETURN> to continue\033q";
  359.  
  360. char    Trace_m[] ="\033p1 PAGE   \033q   \033p2 NEXT   \033q\
  361.    \033p3 PREV.  \033q   \033p4        \033q   \033p5        \033q\
  362.    \033p6 RETURN \033q   \033p7 HELP   \033q";
  363.  
  364. char    Parm_m[] =" ";
  365.  
  366. char    Getcp_m[] ="\033p1 ENTER  \033q   \033p2NUMERIC \033q\
  367.    \033p3        \033q   \033p4        \033q   \033p5        \033q\
  368.    \033p6        \033q   \033p7 HELP   \033q";
  369.  
  370. char    Getnp_m[] ="\033p Hit <RETURN> to enter \033q";
  371.  
  372. /* */
  373. /************************************************************************
  374. *                                    *
  375. *            MAIN LINE OF KERMIT                *
  376. *                                    *
  377. *************************************************************************/
  378.  
  379. main(){
  380.     int i,j;
  381.  
  382.     putstr(Startms);
  383.     for (i=80,j=strlen(Sys_id)+81; i > 30; --i, --j){
  384.         plotstr(5,i,Sys_id);
  385.         clear_eol(5,j);
  386.     }
  387.     portopen(PORTA,Speed);
  388.     Msdos20 = (dosid() >= 2)?TRUE: FALSE;
  389.     termem();
  390.     putstr(Endms);
  391. }
  392. portopen(port,baud)
  393. int port;
  394. {
  395.     Port = port;
  396.     portinit(port);
  397.     sbaud(baud,port);
  398.     if (sstatus(DCD,port))
  399.         putstr("\n\n\nConnection to host established\n");
  400.     else{
  401.         putchar(BEL);
  402.         putstr("\n\n\nConnection to host NOT established\n");
  403.     }
  404. }
  405. /* */
  406. /************************************************************************
  407. *                                    *
  408. *            THE  PROTOCOL                    *
  409. *                                    *
  410. *************************************************************************/
  411. /************************************************************************
  412. *                                    *
  413. * Module:    send                            *
  414. * Purpose:    To set up environment to perform a file send        *
  415. * Interface:    send()                            *
  416. * Parameters:    None                            *
  417. * Globals:    Filnam (char[]): File name(s) to send            *
  418. *                                    *
  419. *************************************************************************/
  420.  
  421. send()
  422. {
  423.     while (TRUE){
  424.         Nmess = 0;
  425.         Nch = 0;
  426.         putmenu("Name of file to Send: ");
  427.         Size = getln(Filnam);
  428.         minit("SEND FILE",Filnam);
  429.         if (sendsw() == TRUE){
  430.         clrkb();
  431.         putmenu("File transfer complete  Do you wish to Send more files (y/n): ");
  432.         switch (getnec()){
  433.         case 'N':
  434.         case 'n':    return;
  435.         }
  436.         }else{            /* An error occurred */
  437.         clrkb();
  438.         putmenu("ERROR DURING FILE TRANSFER (A)bort or (C)ontinue");
  439.         switch(getnec()){
  440.         case 'A':
  441.         case 'a':    return;
  442.         }
  443.          }
  444.     }
  445. }
  446.  
  447. /************************************************************************
  448. *                                    *
  449. * Module:    sendsw                            *
  450. * Purpose:    To maintain the file sending sub-automoton        *
  451. * Interface:    sendsw()                        *
  452. * Parameters:    None                            *
  453. * Globals:    State (char): State of machine                *
  454. *        Numtry (int): Number of retries                *
  455. *                                    *
  456. *************************************************************************/
  457.  
  458. sendsw()
  459. {
  460.     char sinit(), sfile(), sdata(), seof(), sbreak();
  461.  
  462.     State = 'S';            /* Initialise to start state */
  463.     N = 0;                /* Initialise message number */
  464.     Numtry = 0;            /* Initialise Number of trys */
  465.     setjmp (escape);        /* Return here if time out */
  466.     while (TRUE){
  467.         switch (State){
  468.         case 'D': State = sdata();
  469.               break;
  470.         case 'F': State = sfile();
  471.               break;
  472.         case 'Z': State = seof();
  473.               break;
  474.         case 'S': State = sinit();
  475.               break;
  476.         case 'B': State = sbreak();
  477.               break;
  478.         case 'C': return(TRUE);
  479.         case 'A': return(FALSE);
  480.         default:  return(FALSE);
  481.         }
  482.     }
  483. }
  484.  
  485. /************************************************************************
  486. *                                    *
  487. * Module:    sinit()                            *
  488. * Purpose:    To initialise connection with the host.            *
  489. * Interface:    sinit()                            *
  490. * Parameters:                                *
  491. *  Input:    None                            *
  492. *  Output:    Through function name (char)                *
  493. * Globals:                                *
  494. *        Eol (char): End of line character for host        *
  495. *        Quote (char): Quote character for host            *
  496. *        Numtry (int): Number of attempts/retries to contact    *
  497. *            the host.                    *
  498. *        Packet (char[]): Packet to be sent            *
  499. *        Recpkt (char[]): Packet received from host        *
  500. *        N (int): Message number                    *
  501. *        Fptr (->FILE): Pointer to file                *
  502. *                                    *
  503. *************************************************************************/
  504.  
  505. char sinit()
  506. {
  507.     int    num,
  508.         len;
  509.     FILE    *fopen();
  510.     char    abort();
  511.  
  512.     if (Numtry++ > MAXTRY)
  513.         return(abort("Maximum number of retries exceeded - INIT"));
  514.     spar(Packet);            /* Setup packet for host */
  515.     spack('S',N,6,Packet);        /* Send it to the host */
  516.     switch (rpack(&len,&num,Recpkt)){
  517.     case 'N': if (N != num--)
  518.             return(State);
  519.     case 'Y': if (N != num)
  520.             return(State);
  521.           rpar(Recpkt);        /* Get the initialisation info */
  522.           if (Eol == 0)
  523.             Eol = '\n';
  524.           if (Quote == 0)
  525.             Quote = '#';
  526.           Numtry = 0;
  527.           Nch = 0;
  528.           Nmess = 0;
  529.           N = (N + 1) % 64;
  530.           return( ((Fptr=fopen(Filnam,"rb")) == 0)?
  531.             abort("Unable to open file"):
  532.             'F'        /* Ok- File opened */
  533.             );
  534.     case FALSE:
  535.           return(State);
  536.     case 'E': return (abort(Recpkt));
  537.     default:  return(abort("Unexpected response - INIT"));
  538.     }
  539. }
  540.  
  541. /************************************************************************
  542. *                                    *
  543. * Module:    sfile                            *
  544. * Purpose:    To send file name to host                *
  545. * Interface:    sfile()                            *
  546. * Parameters:                                *
  547. *  Input:    None                            *
  548. *  Output:    Through function name (char):                *
  549. * Globals:                                *
  550. *        Numtry (int): number of trys                *
  551. *        Filnam (char[]): File name to send            *
  552. *        N (int): Message number                    *
  553. *        Recpkt (char[]): Received packet            *
  554. *        Packet (char[]): Packet to send                *
  555. *        Size (int): Size of data sent from host            *
  556. *                                    *
  557. *************************************************************************/
  558.  
  559. char sfile()
  560. {
  561.     int    num,
  562.         len;
  563.     char    abort();
  564.  
  565.     if (Numtry++ > MAXTRY)
  566.         return(abort("Maximum number of retries - SEND FILE"));
  567.     for (len=0; Filnam[len] != '\0'; len++);  /* get length of name */
  568.     len++;
  569.     spack('F',N,len,Filnam);
  570.     switch (rpack(&len,&num,Recpkt)){
  571.     case 'N': if (N != num--)
  572.             return(State);
  573.     case 'Y': if (N != num)
  574.             return(State);
  575.           Numtry = 0;
  576.           N = (N + 1) % 64;
  577.           Size = bufill(Packet);
  578.           return('D');
  579.     case FALSE:
  580.           return(State);
  581.     case 'E': return(abort(Recpkt));
  582.     default:  return(abort("Unexpected response - SEND FILE"));
  583.     }
  584. }
  585.  
  586. /************************************************************************
  587. *                                    *
  588. * Module:    sdata                            *
  589. * Purpose:    To send data to the host (generally file contents)    *
  590. * Interface:    sdata()                            *
  591. * Parameters:                                *
  592. *  Input:    None                            *
  593. *  Output:    Through function name (char):                *
  594. * Globals:                                *
  595. *        Numtry (int): Number of tries                *
  596. *        Packet (char[]): packet data sent to host        *
  597. *        Recpkt (char[]): Packet sent from host            *
  598. *        N (int): Message number                    *
  599. *        Size (int): Size of packet (amount of data) received    *
  600. *                                    *
  601. *************************************************************************/
  602.  
  603. char sdata()
  604. {
  605.     int    num,
  606.         len;
  607.     char    abort();
  608.  
  609.     if (Numtry++ > MAXTRY)
  610.         return(abort("Maximum number of retries - SEND DATA"));
  611.     spack('D',N,Size,Packet);
  612.     switch(rpack(&len,&num,Recpkt)){
  613.     case 'N': if (N != num--)
  614.             return(State);
  615.     case 'Y': if (N != num)
  616.             return(State);
  617.           Nch += Size;
  618.           Numtry = 0;
  619.           N = (N + 1) % 64;
  620.           return (((Size = bufill(Packet)) == EOF)?
  621.             'Z':
  622.             'D'
  623.             );
  624.     case FALSE:
  625.           return(State);
  626.     case 'E': return(abort(Recpkt));
  627.     default:  return(abort("Unexpected response - SEND DATA"));
  628.     }
  629. }
  630.  
  631. /************************************************************************
  632. *                                    *
  633. * Module:    seof                            *
  634. * Purpose:    To send an EOF Packet                    *
  635. * Interface:    seof()                            *
  636. * Parameters:                                *
  637. *  Input:    None                            *
  638. *  Ouptut:    Through function name (char)                *
  639. * Globals:                                *
  640. *        Numtry (int): Number of tries                *
  641. *        Packet (char[]): Packet                    *
  642. *                                    *
  643. *************************************************************************/
  644.  
  645. char seof()
  646. {
  647.     int    num,
  648.         len;
  649.     char    abort();
  650.  
  651.     if (Numtry++ > MAXTRY)
  652.         return(abort("Maximum number of retries - SEND EOF"));
  653.     spack('Z',N,0,Packet);
  654.     switch (rpack(&len,&num,Recpkt)){
  655.     case 'N': if (N != num--)
  656.             return(State);
  657.     case 'Y': if (N != num)
  658.             return(State);
  659.           Numtry = 0;
  660.           N = (N + 1) % 64;
  661.           return ((gnxtfl() == EOF)?'B':'F');
  662.     case FALSE:
  663.           return(State);
  664.     case 'E': return(abort(Recpkt));
  665.     default:  return(abort("Unexpected response - SEND EOF"));
  666.     }
  667. }
  668.  
  669. /************************************************************************
  670. *                                    *
  671. * Module:    sbreak                            *
  672. * Purpose:    To send a break (end of transmission) package        *
  673. * Interface:    sbreak()                        *
  674. *                                    *
  675. *************************************************************************/
  676.  
  677. char sbreak()
  678. {
  679.     int    num,
  680.         len;
  681.     char    abort();
  682.  
  683.     if (Numtry++ > MAXTRY)
  684.         return(abort("Maximum number of retries - SEND EOT"));
  685.     spack('B',N,0,Packet);
  686.     switch(rpack(&len,&num,Recpkt)){
  687.     case 'N': if (N != num--)
  688.             return(State);
  689.     case 'Y': if (N != num)
  690.             return(State);
  691.           Numtry = 0;
  692.           N = (N + 1) % 64;
  693.           return('C');
  694.     case FALSE:
  695.           return(State);
  696.     case 'E': return(abort(Recpkt));
  697.     default:  return(abort("Unexpected response - SEND EOT"));
  698.     }
  699. }
  700.  
  701. /************************************************************************
  702. *                                    *
  703. * Module:    spack                            *
  704. * Purpose:    To assemble and send out the supplied Package        *
  705. * Interface:    spack(type,num,len,data)                *
  706. *  Input:    type (char): Type of package                *
  707. *        num (int): Message number                *
  708. *        len (int): Size (length) of massage data        *
  709. *        data (char[]): Data to be packaged            *
  710. *  Output:    None                            *
  711. *                                    *
  712. ************************************************************************/
  713.  
  714. spack(type,num,len,data)
  715. char type,data[];
  716. int num,len;
  717. {
  718.     int    i,
  719.         chksum;
  720.     char    abort();
  721.  
  722.     if (getkbs() && (getnec() == REQCAN)){
  723.         State = abort("Message Break");
  724.         longjmp(escape);
  725.     }
  726.     plotc(9,66,'S');
  727.     prpack(SEND,len,num,type,data);
  728.     for (i=1; i <= Pad; i++)
  729.         sputc(Padchar,Port);
  730.     sputc(SOH,Port);
  731.     chksum = tochar(len+3);
  732.     sputc(tochar(len+3),Port);
  733.     chksum += tochar(num);
  734.     sputc(tochar(num),Port);
  735.     chksum += type;
  736.     sputc(type,Port);
  737.     for (i=0; i < len; i++){
  738.         sputc(data[i],Port);
  739.         chksum += data[i] & 0x0ff;    /* Prevent Sign extension */
  740.     }
  741.     chksum = (chksum + ((chksum & 192) /64)) & 63;
  742.     sputc(tochar(chksum),Port);
  743.     sputc(Eol,Port);
  744.     Trace.smtype[Trace.si] = type;
  745.     Trace.smnum[Trace.si] = num;
  746.     if (++Trace.si > 255)
  747.         Trace.si = 0;
  748.     Nmess++;
  749.     plotc(9,66,'W');
  750. }
  751.  
  752. /************************************************************************
  753. *                                    *
  754. * Module:    rpack                            *
  755. * Purpose:    To wait for the receipt of a package            *
  756. * Interface:    rpack(len,num,data)                    *
  757. *  Input:    len (int): Length of message (data portion)        *
  758. *        num (int): Message Number                *
  759. *        data (char[]): Vector which maintaines data received    *
  760. *                                    *
  761. *************************************************************************/
  762.  
  763. rpack(len,num,data)
  764. int *len, *num;
  765. char *data;
  766. {
  767.     static int semaphore;
  768.     int    i,
  769.         fld,
  770.         chksum,
  771.         t,
  772.         type;
  773.     char    abort();
  774.  
  775.     chksum = 0;
  776.     t = 0;
  777.     plotc(9,66,'R');
  778.     while ((t=sgetc(Port)) != SOH);
  779.  
  780.     for (fld=1; fld <= 5; fld++){
  781.         if (fld != 5 || i != 0)
  782.         if ((t=sgetc(Port)) == SOH) fld = 0;
  783.         if (fld <= 3) chksum += t;
  784.         switch (fld){
  785.         case 0:    chksum = 0;
  786.             break;
  787.         case 1:    *len = unchar(t)-3;
  788.             break;
  789.         case 2:    *num = unchar(t);
  790.             break;
  791.         case 3:    type = t;
  792.             break;
  793.         case 4:    for (i=0; i < *len; i++){
  794.                 if (i != 0)
  795.                 if ((t=sgetc(Port)) == SOH){
  796.                     fld = -1;
  797.                         break;
  798.                 }
  799.                 chksum += t;
  800.                 data[i] = t;
  801.             }
  802.             break;
  803.         case 5:    chksum = (chksum + ((chksum & 192) / 64)) & 63;
  804.             break;
  805.         }
  806.     }
  807.     if (getkbs() && (getnec() == REQCAN)){
  808.         State = abort("Message Break");
  809.         longjmp(escape);
  810.     }
  811.     Trace.rmtype[Trace.ri] = type;
  812.     Trace.rmnum[Trace.ri] = *num;
  813.     if (++Trace.ri > 255)
  814.         Trace.ri = 0;
  815.     Nmess++;
  816.     prpack(RECEIVE,*len,*num,type,data,chksum);
  817.     plotc(9,66,'W');
  818.     if (chksum != unchar(t)){
  819.         clear_eol(5,1);
  820.         putchar(BEL);
  821.         plotistr(5,5,"Bad Checksum");
  822.         semaphore = TRUE;
  823.         return(FALSE);
  824.     }
  825.     if (semaphore){
  826.         semaphore = FALSE;
  827.         clear_eol(5,1);
  828.     }
  829.     return(type);
  830. }
  831.  
  832. /************************************************************************
  833. *                                    *
  834. * Module:    receive                            *
  835. * Purpose:    To set up environment to receive a file            *
  836. * Interface:    receive()                        *
  837. * Parameters:    None                            *
  838. * Globals:    Filnam (char[]): Name of file to receive        *
  839. *                                    *
  840. *************************************************************************/
  841.  
  842. receive()
  843. {
  844.     while (TRUE){
  845.         Nmess = 0;
  846.         Nch = 0;
  847.         putmenu(" Name of file to Receive: ");
  848.         Size = getln(Filnam);
  849.         minit("RECEIVE FILE",Filnam);
  850.         if (recsw() == TRUE){
  851.         clrkb();
  852.         putmenu(" File transfer complete Do you wish to Receive more files (y/n): ");
  853.         switch (getnec()){
  854.         case 'N':
  855.         case 'n':    return;
  856.         }
  857.         }else{            /* An error occurred */
  858.         clrkb();
  859.         putmenu("ERROR DURING FILE TRANSFER (A)bort or (C)ontinue");
  860.         switch(getnec()){
  861.         case 'A':
  862.         case 'a':    return;
  863.         }
  864.         }
  865.     }
  866. }
  867.  
  868. /************************************************************************
  869. *                                    *
  870. * Module:    recsw                            *
  871. * Purpose:    To maintain the receive file automoton            *
  872. * Interface:    recsw()                            *
  873. *                                    *
  874. *************************************************************************/
  875.  
  876. recsw()
  877. {
  878.     char rinit(), rfile(), rdata();
  879.  
  880.     State = 'R';
  881.     N = 0;
  882.     Numtry = 0;
  883.     if (setjmp (escape))        /* Return here on SIO time out */
  884.         spack('N',N,0,0);    /* Send NAK */
  885.     while (TRUE){
  886.         switch(State){
  887.         case 'D':
  888.             State = rdata();
  889.             break;
  890.         case 'F':
  891.             State = rfile();
  892.             break;
  893.         case 'R':
  894.             State = rinit();
  895.             break;
  896.         case 'C':
  897.             return(TRUE);
  898.         case 'A':
  899.             return(FALSE);
  900.         default:
  901.             return(FALSE);
  902.         }
  903.     }
  904. }
  905.  
  906. /************************************************************************
  907. *                                    *
  908. * Module:    rinit                            *
  909. * Purpose:    To initialise the conection to the host            *
  910. * Interface:    rinit()                            *
  911. *                                    *
  912. *************************************************************************/
  913.  
  914. char rinit()
  915. {
  916.     int    len,
  917.         num;
  918.     char    abort();
  919.  
  920.     if (Numtry++ > MAXTRY)
  921.         return(abort("Maximum number of retries - RECEIVE INIT"));
  922.     switch (rpack(&len,&num,Packet) ){
  923.     case 'S': N = num;
  924.           rpar(Packet);
  925.           spar(Packet);
  926.           spack('Y',N,6,Packet);
  927.           Oldtry = Numtry;
  928.           Numtry = 0;
  929.           Nch = 0;
  930.           Nmess = 0;
  931.           N = (N + 1) % 64;
  932.           return('F');
  933.     case 'N': spack('Y',num,0,0);
  934.           return(State);
  935.     case FALSE:
  936.           spack('N',num,0,0);
  937.           return(State);
  938.     case 'E': return(abort(Packet));
  939.     default:  return(abort("Unexpected response - RECEIVE INIT"));
  940.     }
  941. }
  942.  
  943. /************************************************************************
  944. *                                    *
  945. * Module:    rfile                            *
  946. * Purpose;    To receive a file from the host                *
  947. * Interface:    rfile()                            *
  948. *                                    *
  949. *************************************************************************/
  950.  
  951. char rfile()
  952. {
  953.     int    num,
  954.         len;
  955.     char    abort();
  956.  
  957.     if (Numtry++ > MAXTRY)
  958.         return(abort("Maximum number of retries - RECEIVE FILE"));
  959.     switch ( rpack(&len,&num,Packet) ){
  960.     case 'S': if (Oldtry++ > MAXTRY)
  961.             return(abort("Maximum number of attempts - RECEIVE FILE"));
  962.           if (num == N-1){
  963.             spar(Packet);
  964.             spack('Y',num,6,Packet);
  965.             Numtry = 0;
  966.             return(State);
  967.            }else
  968.             return(abort("Message number mismatch - RECEIVE FILE"));
  969.     case 'Z': if (Oldtry++ > MAXTRY)
  970.             return(abort("Maximum number of attempts - RECEIVE FILE"));
  971.           if (num == N-1){
  972.             spack('Y',num,0,0);
  973.             Numtry = 0;
  974.             return(State);
  975.           }else
  976.             return(abort("Message number mismatch - RECEIVE FILE"));
  977.     case 'F': if (num != N)
  978.             return(abort("Message number mismatch - RECEIVE FILE"));
  979.           if (getfil(Filnam) == FALSE)
  980.             return(abort("Unable to open file"));
  981.           spack('Y',N,0,0);
  982.           Oldtry = Numtry;
  983.           Numtry = 0;
  984.           N = (N + 1) % 64;
  985.           return('D');
  986.     case 'B': if (num != N)
  987.             return(abort("Message number mismatch - RECEIVE FILE"));
  988.           spack('Y',N,0,0);
  989.           return('C');
  990.     case 'N': spack('Y',num,0,0);
  991.           return(State);
  992.     case FALSE:
  993.           spack('N',num,0,0);
  994.           return(State);
  995.     case 'E': return(abort(Packet));
  996.     default:  return(abort("Unexpected response - RECEIVE FILE"));
  997.     }
  998. }
  999.  
  1000. /************************************************************************
  1001. *                                    *
  1002. * Module:    rdata                            *
  1003. * Purpose;    To receive data from the host                *
  1004. * Interface:    rdata()                            *
  1005. *                                    *
  1006. *************************************************************************/
  1007.  
  1008. char rdata()
  1009. {
  1010.     int    i,
  1011.         num,
  1012.         len;
  1013.     char    abort();
  1014.  
  1015.     if (Numtry++ > MAXTRY)
  1016.         return(abort("Maximum number of retries - RECEIVE DATA"));
  1017.     switch ( rpack(&len,&num,Packet) ){
  1018.     case 'D': if (num != N){
  1019.             if (Oldtry++ > MAXTRY)
  1020.                 return(abort("Maximum number of attempts - RECEIVE DATA"));
  1021.             if (num == N-1){
  1022.                 spack('Y',num,0,0);
  1023.                 Numtry = 0;
  1024.                 return(State);
  1025.             }else
  1026.             return(abort("Message number mismatch - RECEIVE DATA"));
  1027.           }
  1028.           Nch += len;
  1029.           bufemp(Packet,Fptr,len);
  1030.           spack('Y',N,0,0);
  1031.           Oldtry = Numtry;
  1032.           Numtry = 0;
  1033.           N = (N + 1) % 64;
  1034.           return('D');
  1035.     case 'Z': if (num != N)
  1036.             return(abort("Message number mismatch - RECEIVE DATA"));
  1037.           i = (fclose(Fptr) == -1)?
  1038.             abort("Unable to close file"):
  1039.             'F';
  1040.           spack('Y',num,0,0);
  1041.           N = (N + 1) % 64;
  1042.           return(i);
  1043.     case 'F': if (Oldtry++ > MAXTRY)
  1044.             return(abort("Maximum number of attempts - RECEIVE DATA"));
  1045.           if (num != N-1){
  1046.              spack('Y',N,0,0);
  1047.             Numtry = 0;
  1048.             return(State);
  1049.           }else
  1050.             return(abort("Message number mismatch - RECEIVE DATA"));
  1051.     case 'B': if (num != N)
  1052.             return(abort("Message number mismatch - RECEIVE DATA"));
  1053.           spack('Y',N,0,0);
  1054.           return('C');
  1055.     case 'N': spack('Y',num,0,0);
  1056.           return(State);
  1057.     case FALSE:
  1058.           spack('N',num,0,0);
  1059.           return(State);
  1060.     case 'E': return(abort(Packet));
  1061.     default:  return(abort("Unexpected response - RECEIVE DATA"));
  1062.     }
  1063. }
  1064. /* */
  1065. /************************************************************************
  1066. *                                    *
  1067. *            TERMINAL EMULATION ROUTINES            *
  1068. *                                    *
  1069. *************************************************************************/
  1070.  
  1071. /************************************************************************
  1072. *                                    *
  1073. * Module:    termem                            *
  1074. * Purpose:    To emulate a terminal                    *
  1075. * Interface:    termem()                        *
  1076. *                                    *
  1077. *************************************************************************/
  1078.  
  1079. termem()
  1080. {
  1081.     unsigned char    ch;
  1082.  
  1083.     putmenu(Root_m);
  1084.     setjmp (escape);
  1085.     while (TRUE){
  1086.         if (getkbs()){        /* Check for character @ keyboard */
  1087.         if (((ch=getnec()) >= F1) && (ch <= F8)){
  1088.             clear_screen();
  1089. /*            cursr_off();*/
  1090.             switch (ch){
  1091.             case F1:    return;
  1092.             case F2:    send();
  1093.                 break;
  1094.             case F3:    receive();
  1095.                 break;
  1096.             case F4:    set();
  1097.                 break;
  1098.             case F5:    show();
  1099.                 getnec();
  1100.                 break;
  1101.             case F6:    dtrace();
  1102.                 break;
  1103.             case F7:    help(ROOT_H);
  1104.                 break;
  1105.             case F8:    putchar('!');
  1106.                 docmd();
  1107.             }
  1108.             clear_screen();
  1109.             putmenu(Root_m);
  1110.             home();
  1111. /*            cursr_on();*/
  1112.         }else{
  1113.             sputc(((ch == REQCAN)?Break:ch),Port);
  1114.             if (Echo)
  1115.             putchar(ch);
  1116.         }
  1117.         }else if ((ch=scheck(Port)) > 0){
  1118.         putchar(ch&0x07f);    /* Else echo chararacter from Port */
  1119.         }
  1120.     }
  1121. }
  1122. /************************************************************************
  1123. *                                    *
  1124. * Module:    docmd()                            *
  1125. * Purpose:    To execute a MS-DOS command                *
  1126. * Input:    None                            *
  1127. * Output:    None                            *
  1128. *                                    *
  1129. *************************************************************************/
  1130. docmd()
  1131. {
  1132.     struct regval {int ax,bx,cx,dx,si,di,ds,es;} srv,rrv;
  1133.     char line[256];
  1134.  
  1135.     if (!Msdos20){
  1136.         putstr("Requires MSDOS 2.0 or greater ... request ignored\n");
  1137.     }else
  1138.         putstr("Feature not implemented at this time\n");
  1139.     putmenu(Help_m);
  1140.     getnec();
  1141. }        
  1142. /************************************************************************
  1143. *                                    *
  1144. * Module:    dtrace()                        *
  1145. * Purpose:    To display trace information collected during data    *
  1146. *        transmition                        *
  1147. * Input:    Trace: Trace buffer (Global data)            *
  1148. * Output:    None                            *
  1149. *                                    *
  1150. *************************************************************************/
  1151.  
  1152. dtrace()
  1153. {
  1154.     int        j,
  1155.             d,
  1156.             k,
  1157.             i;
  1158.  
  1159.     printf("\033Y!7\0330Local\0331\033Y!L\0330Host\0331\033Y7 ");
  1160.     putmenu(Trace_m);
  1161.     for (i=Trace.si-1, j=(i+1) & 0x0ff;
  1162.         Trace.smtype[i] != 'S' && Trace.rmtype[i] != 'S' && i != j; \
  1163.         i = (i - 1) & 0x0ff);
  1164.     if (i == j){
  1165.         printf("\n No transactions in Trace Buffer");
  1166.     }else{
  1167.         Trace.smtype[j] = 0;    /* Mark top of list */
  1168.         d = (Trace.smtype[i] == 'S')?SEND: RECEIVE;
  1169.         j = 10;
  1170.         i = (Trace.si - 1) & 0x0ff;
  1171.         while (TRUE){
  1172.         if (d == SEND){
  1173.             printf("\033Y# \033M\033Y7D<------- %c(%d)",\
  1174.                 Trace.rmtype[i],Trace.rmnum[i]);
  1175.             printf("\033Y# \033M\033Y77%c(%d) ------->",\
  1176.                 Trace.smtype[i],Trace.smnum[i]);
  1177.         }else{
  1178.             printf("\033Y# \033M\033Y77%c(%d) ------->",\
  1179.                     Trace.smtype[i],Trace.smnum[i]);
  1180.             printf("\033Y# \033M\033Y7D<------- %c(%d)",\
  1181.                     Trace.rmtype[i],Trace.rmnum[i]);
  1182.         }
  1183.         if ((Trace.smtype[i] == 'S') || (Trace.rmtype[i] == 'S'))
  1184.             break;
  1185.         i = (i - 1) & 0x0ff;
  1186.         while (--j < 1){
  1187.             switch  (getnec()){
  1188.             case F1:
  1189.             j = 10;
  1190.             break;
  1191.             case F2:
  1192.             break;
  1193.             case F3:
  1194.             printf("\033j");
  1195.             k = (i + 11) & 0x0ff;
  1196.             if (d == SEND){
  1197.                 printf("\033Y# \033L\033Y#7%c(%d) ------->",\
  1198.                         Trace.smtype[k],Trace.smnum[k]);
  1199.                 printf("\033Y# \033L\033Y#D<------- %c(%d)",\
  1200.                         Trace.rmtype[k],Trace.rmnum[k]);
  1201.             }else{
  1202.                 printf("\033Y# \033L\033Y#D<------- %c(%d)",\
  1203.                         Trace.rmtype[k],Trace.rmnum[k]);
  1204.                 printf("\033Y# \033L\033Y#7%c(%d) ------->",\
  1205.                         Trace.smtype[k],Trace.smnum[k]);
  1206.             }
  1207.             printf("\033k");
  1208.             if (Trace.smtype[i] != 0)
  1209.                 i = (i + 1) & 0x0ff;
  1210.             continue;
  1211.             case F6:
  1212.             return;
  1213.             case F7:
  1214.             help(TRACE_H);
  1215.                 break;
  1216.             default:
  1217.                 putchar(BEL);
  1218.             continue;
  1219.             }
  1220.             break;
  1221.         }
  1222.         }
  1223.     }
  1224.     getnec();
  1225. }
  1226. prtrace(d,i,l)
  1227. int d,i,l;
  1228. {
  1229. }
  1230.             
  1231. /************************************************************************
  1232. *                                    *
  1233. * Module:    set                            *
  1234. * Purpose:    To set or reset system variable                *
  1235. * Interface:    set()                            *
  1236. *                                     *
  1237. *************************************************************************/
  1238.  
  1239. set()
  1240. {
  1241.     show();
  1242.     while (TRUE){
  1243.         putmenu(Set_m);
  1244.         switch (getnec()){
  1245.         case F1:    set_baud();
  1246.             break;
  1247.         case F2:    set_echo();
  1248.             break;
  1249.         case F3:    set_warning();
  1250.             break;
  1251.         case F4:    set_parms();
  1252.             break;
  1253.         case F6:    return;
  1254.         case F7:    help(SET_H);
  1255.             show();
  1256.             break;
  1257.         default:    putchar(BEL);
  1258.         }
  1259.     }
  1260. }
  1261. set_baud()
  1262. {
  1263.      plotistr(POS_BAUD,4,Pa[8]);
  1264.     plotistr(POS_BAUD,50,Ba[Speed]);
  1265.     while (TRUE){
  1266.         putmenu(Baud_m);
  1267.         switch (getnec()){
  1268.         case F1:    Speed = B300;
  1269.             break;
  1270.         case F2:    Speed = B600;
  1271.             break;
  1272.         case F3:    Speed = B1200;
  1273.             break;
  1274.         case F4:    Speed = B2400;
  1275.             break;
  1276.         case F5:    Speed = B4800;
  1277.             break;
  1278.         case F6:    Speed = B9600;
  1279.             break;
  1280.         case F7:    help(BAUD_H);
  1281.             show();
  1282.             continue;
  1283.         default:    putchar(BEL);
  1284.             continue;
  1285.         }
  1286.         break;
  1287.     }
  1288.     sbaud(Speed,Port);
  1289.     clear_eol(POS_BAUD,1);
  1290.     plotstr(POS_BAUD,4,Pa[8]);
  1291.     plotstr(POS_BAUD,50,Ba[Speed]);
  1292. }
  1293.  
  1294. set_echo()
  1295. {
  1296.     plotistr(POS_ECHO,4,Pa[7]);
  1297.     plotistr(POS_ECHO,50,(Echo)?"YES":"NO ");
  1298.     while (TRUE){
  1299.         putmenu(Onoff_m);
  1300.         switch (getnec()){
  1301.         case F1:    Echo = TRUE;
  1302.             break;
  1303.         case F2:    Echo = FALSE;
  1304.             break;
  1305.         case F6:    break;
  1306.         case F7:    help(ECHO_H);
  1307.             show();
  1308.             continue;
  1309.         default:    putchar(BEL);
  1310.             continue;
  1311.         }
  1312.         break;
  1313.     }
  1314.     clear_eol(POS_ECHO,1);
  1315.     plotstr(POS_ECHO,4,Pa[7]);
  1316.     plotstr(POS_ECHO,50,(Echo)?"YES":"NO ");
  1317. }
  1318.  
  1319. set_warning()
  1320. {
  1321.     plotistr(POS_WARN,4,Pa[6]);
  1322.     plotistr(POS_WARN,50,(Warn)?"YES":"NO ");
  1323.     while (TRUE){
  1324.         putmenu(Onoff_m);
  1325.         switch (getnec()){
  1326.         case F1:    Warn = TRUE;
  1327.             break;
  1328.         case F2:    Warn = FALSE;
  1329.             break;
  1330.         case F6:    break;
  1331.         case F7:    help(WARN_H);
  1332.             show();
  1333.             continue;
  1334.         default:    putchar(BEL);
  1335.             continue;
  1336.         }
  1337.         break;
  1338.     }
  1339.     clear_eol(POS_WARN,1);
  1340.     plotstr(POS_WARN,4,Pa[6]);
  1341.     plotstr(POS_WARN,50,(Warn)?"YES":"NO ");
  1342. }
  1343.  
  1344. set_parms()
  1345. {
  1346. /*    cursr_on();*/
  1347.     putmenu(Parm_m);
  1348.     pos(POS_MAXPACK,50);
  1349.     Maxpack = getnp(Maxpack,MAXPACK);
  1350.     putmenu(Parm_m);
  1351.     pos(POS_MYPCHAR,50);
  1352.     Mypchar = getcp(Mypchar);
  1353.     putmenu(Parm_m);
  1354.     pos(POS_MYPAD,50);
  1355.     Mypad = getnp(Mypad,NULL);
  1356.     putmenu(Parm_m);
  1357.     pos(POS_MYTIME,50);
  1358.     Mytime = getnp(Mytime,NULL);
  1359.     putmenu(Parm_m);
  1360.     pos(POS_MYEOL,50);
  1361.     Myeol = getcp(Myeol);
  1362.     putmenu(Parm_m);
  1363.     pos(POS_MYQUOTE,50);
  1364.     Myquote = getcp(Myquote);
  1365.     pos(POS_BREAK,50);
  1366.     Break = getcp(Break);
  1367. /*    cursr_off();*/
  1368. }
  1369.  
  1370. show()
  1371. {
  1372.     int i;
  1373.  
  1374.     clear_screen();
  1375.     putmenu(Show_m);
  1376.     for (i=0; i < 11;i++){
  1377.         plotistr(SHOW_BASE+i,4,Pa[i]);
  1378.         plotstr(SHOW_BASE+i,4,Pa[i]);
  1379.     }
  1380.     plotd(POS_MAXPACK,50,Maxpack);
  1381.     plotstr(POS_MYPCHAR,50,(Mypchar < ' ')?"^":" ");
  1382.     plotc(POS_MYPCHAR,51,(Mypchar < ' ')?Mypchar+'@':Mypchar);
  1383.     plotd(POS_MYPAD,50,Mypad);
  1384.     plotd(POS_MYTIME,50,Mytime);
  1385.     plotstr(POS_MYEOL,50,(Myeol < ' ')?"^":" ");
  1386.     plotc(POS_MYEOL,51,(Myeol < ' ')?Myeol+'@':Myeol);
  1387.     plotstr(POS_MYQUOTE,50,(Myquote < ' ')?"^":" ");
  1388.     plotc(POS_MYQUOTE,51,(Myquote < ' ')?Myquote+'@':Myquote);
  1389.     plotstr(POS_WARN,50,(Warn)?"YES":"NO ");
  1390.     plotstr(POS_ECHO,50,(Echo)?"YES":"NO ");
  1391.     plotstr(POS_BAUD,50,Ba[Speed]);
  1392.     plotstr(POS_BREAK,50,(Break < ' ')?"^":" ");
  1393.     plotc(POS_BREAK,51,(Break < ' ')?Break+'@':Break);
  1394.     plotstr(POS_PORT,50,(Port == PORTA)?"PORT A":"PORT B ");
  1395. }
  1396. /************************************************************************
  1397. *                                    *
  1398. * Module:    help                            *
  1399. * Purpose:    To print out help messages                *
  1400. * Interface:    help(message)                        *
  1401. *  Input:    message (->char): Help message to be printed        *
  1402. *  Output:    None                            *
  1403. *                                    *
  1404. *************************************************************************/
  1405. help(message)
  1406. int message;
  1407. {
  1408.     FILE    *fp;
  1409.     int    i;
  1410.     int    ch;
  1411.  
  1412.     clear_screen();
  1413.     putmenu(Help_m);
  1414.     if ((fp=fopen("KERMIT.HEP","r")) != 0){
  1415.         i = 0;
  1416.         while (i != message){
  1417.         while (getc(fp) != ENDSEC);
  1418.             ++i;
  1419.         }
  1420.         while (TRUE){
  1421.         switch (ch=getc(fp)){
  1422.         case ENDPAG:            
  1423.             getnec();
  1424.             clear_screen();
  1425.             continue;
  1426.         case ENDSEC:
  1427.         case ENDSS:
  1428.         case ENDFIL:
  1429.         case EOF:
  1430.             break;
  1431.         case ENQUIRE:
  1432.             i = getnp(1,NULL);
  1433.             putmenu(Help_m);
  1434.             while (i > 0){
  1435.                 switch (ch=getc(fp)){
  1436.                 case ENDSEC:
  1437.                 case ENDFIL:
  1438.                 case EOF:
  1439.                         ungetc(ch,fp);
  1440.                         break;
  1441.                 case ENDSS:
  1442.                         --i;
  1443.                         break;
  1444.                 }
  1445.             }
  1446.             clear_screen();
  1447.             continue;    
  1448.         case '\n':
  1449.             if ((ch=getc(fp)) == ';'){
  1450.                 while (getc(fp) != '\n');
  1451.                 ungetc('\n',fp);
  1452.             }else{
  1453.                 putchar('\n');
  1454.                 ungetc(ch,fp);
  1455.             }
  1456.             continue;
  1457.         default:
  1458.             putchar(ch);
  1459.             continue;
  1460.         }
  1461.         break;
  1462.         }
  1463.         fclose(fp);
  1464.     }else{
  1465.         putstr("Help file not found");
  1466.     }        
  1467.     getnec();
  1468. }                
  1469. /* */
  1470. /************************************************************************
  1471. *                                    *
  1472. *                UTILITES                *
  1473. *                                    *
  1474. *************************************************************************/
  1475. /************************************************************************
  1476. *                                    *
  1477. * Module:    abort                            *
  1478. * Purpose:    To print out the abort message, return an Abort        *
  1479. *        code, and send an Error packet to the host.        *
  1480. * Interface:    abort(message)                        *
  1481. *  Input:    message (->char): Message to be printed            *
  1482. *  Output:    Through function name (char):                *
  1483. *        'A': Abort code                        *
  1484. *                                    *
  1485. *************************************************************************/
  1486.  
  1487. char abort(message)
  1488. char *message;
  1489. {
  1490.     clear_eol(5,1);
  1491.     plotistr(5,(38-(strlen(message)/2)),message);
  1492.     spack('E',N,strlen(message),message);
  1493.     return('A');
  1494. }
  1495.  
  1496. /************************************************************************
  1497. *                                    *
  1498. * Module:    basenm                            *
  1499. * Purpose:    To strip off any device specifiers and/or path names    *
  1500. *        supplied with the file name.                *
  1501. * Interface:    basenm(fname)                        *
  1502. *  Input:    fname (->char): Name of file                *
  1503. *  Output:    Through function name (->char):                *
  1504. *        pointer to position of "base name"            *
  1505. *                                    *
  1506. *************************************************************************/
  1507.  
  1508. char *basenm(fname)
  1509. char fname[];
  1510. {
  1511.     int  i,j,k;
  1512.  
  1513.     for (j=strlen( &fname[ (fname[1] == ':')? 2: 0 ] ), k = j;
  1514.         (j >= 0) && (fname[j] != '/') ; --j);
  1515.     for (i=j; i < k; i++){
  1516.         if (fname[i] == '.'){
  1517.         if (i+3 < k){
  1518.             fname[i+4] = '\0';
  1519.             break;
  1520.         }
  1521.         }
  1522.     }
  1523.     return(&fname[j+1]);
  1524. }        
  1525. /************************************************************************
  1526. *                                    *
  1527. * Module:    bufemp                            *
  1528. * Purpose:    To write data received to the appropriate file        *
  1529. * Interface:    bufemp(buffer,filptr,len)                *
  1530. *                                    *
  1531. *************************************************************************/
  1532.  
  1533. bufemp(buffer,filptr,len)
  1534. char buffer[];
  1535. FILE *filptr;
  1536. int len;
  1537. {
  1538.     int    i,
  1539.         t;
  1540.  
  1541.     for (i=0; i < len; i++){
  1542.         if ((t=buffer[i]) == Myquote){
  1543.             if ((t=buffer[++i]) != Myquote)
  1544.                 t = ctl(t);
  1545.         }
  1546.         fputc(t,filptr);
  1547.     }
  1548. }
  1549.  
  1550. /************************************************************************
  1551. *                                    *
  1552. * Module:    bufill                            *
  1553. * Purpose:    To get data from a file                    *
  1554. * Interface:    bufill(buffer)                        *
  1555. *                                    *
  1556. *************************************************************************/
  1557.  
  1558. bufill(buffer)
  1559. char buffer[];
  1560. {
  1561.     int    i,
  1562.         t;
  1563.  
  1564.     i = 0;
  1565.     while ((t = fgetc(Fptr)) != EOF){
  1566.         t &= 0x07f;
  1567.         if (t < SP || t == DEL || t == Quote){
  1568.             buffer[i++] = Quote;
  1569.             if (t != Quote)
  1570.                 t = ctl(t);
  1571.         }
  1572.         buffer[i++] = t;
  1573.         if (i >= Spsiz-6)
  1574.             return(i);
  1575.     }
  1576.     if (i == 0)
  1577.         return(EOF);
  1578.     return(i);
  1579. }
  1580. /************************************************************************
  1581. *                                    *
  1582. * Module:    getcp                            *
  1583. * Purpose:    To get a character from the keyboard            *
  1584. * Interface:    getcp(d)                        *
  1585. *  Input:    d (integer): Default value, if nothing entered        *
  1586. *  Output:    Through function name:                    *
  1587. *        Keyed, or default value                    *
  1588. *                                    *
  1589. *************************************************************************/
  1590.  
  1591. getcp(d)
  1592. int d;
  1593. {
  1594.     int    c,j;
  1595.  
  1596.     c = -1;
  1597. /*    cursr_on();*/
  1598.     putmenu(Getcp_m);
  1599.     while(TRUE){
  1600.         switch(j=getnec()){
  1601.         case F1:/*    cursr_off();*/
  1602.             return((c == -1)?d:c);
  1603.         case F2:    return(getnp(0,128));
  1604.         case F7:    help(GETCP_H);
  1605.             show();
  1606.             putmenu(Getcp_m);
  1607.             break;
  1608.         default:    if (j < ' ')
  1609.                 printf("^%c",j+'@');
  1610.             else
  1611.                 putchar(j);
  1612.             c = j;
  1613.         }
  1614.     }
  1615. }
  1616. /************************************************************************
  1617. *                                    *
  1618. * Module:    getfil                            *
  1619. * Purpose:    To open a file for data received from host        *
  1620. * Interface:    getfil(filenm)                        *
  1621. *                                    *
  1622. *************************************************************************/
  1623.  
  1624. getfil(filenm)
  1625. char *filenm;
  1626. {
  1627.     FILE    *fopen();
  1628.     char    *fln,
  1629.         *basenm();
  1630.  
  1631.     if (*filenm == '\0'){        /* Default to name sent by host */
  1632.         fln = basenm(Packet);
  1633.         pos(5,(38-(14+strlen(fln))/2));
  1634.         putistr("RECEIVE FILE: ");
  1635.         putistr(fln);
  1636.     }else
  1637.         fln = filenm;
  1638.     if (fopen(fln,"r") != 0){    /* File already exists */
  1639.         while (Warn){
  1640.         putmenu("File already exists. Do you want to (C)ontinue, (A)bort, or (R)ename: ");
  1641.             switch (getnec()){
  1642.             case 'A':
  1643.             case 'a':
  1644.             return(FALSE);
  1645.             case 'C':
  1646.             case 'c':
  1647.                 break;
  1648.             case 'R':
  1649.             case 'r':
  1650.             clear_eol(5,1);
  1651.                 plotstr(5,1,"Enter new filename: ");
  1652.             getln(filenm);
  1653.             return(getfil(filenm));
  1654.             default:
  1655.             putchar(BEL);
  1656.             plotistr(5,1,"Invalid entry       ");
  1657.             continue;
  1658.             }
  1659.             break;
  1660.         }
  1661.     }
  1662.     return ( ((Fptr=fopen(fln,"wb")) == 0)? FALSE: TRUE);
  1663. }
  1664.  
  1665. /************************************************************************
  1666. *                                    *
  1667. * Module:    getlc                            *
  1668. * Purpose:    To get the current Line/Column position of the cursor    *
  1669. * Interface:    getlc(line,column)                    *
  1670. *  Input:    line (->char): Pointer to integer variable        *
  1671. *        column (->char): Pointer to integer variable        *
  1672. *  Output:    Line (->char): Current line position (0 releative)    *
  1673. *        column (->char): Current column position (0 rel)    *
  1674. *                                    *
  1675. *************************************************************************/
  1676.  
  1677. getlc(line,column)
  1678. char *line,*column;
  1679. {
  1680.     printf("\033n");        /*send out control code to CRT */
  1681.     getnec();            /* By pass garbage ... \033Y */
  1682.     getnec();
  1683.     *line = getnec();        /* Get information we want */
  1684.     *column = getnec();
  1685. }
  1686.  
  1687. /************************************************************************
  1688. *                                    *
  1689. * Module:    getln                            *
  1690. * Purpose:    To get a line from standard input            *
  1691. * Interface:    getln(line)                        *
  1692. *  Input:    line (->char[]): Pointer to vector which receives    *
  1693. *            keyed data                    *
  1694. *  Output:    Through function name (integer):            *
  1695. *        Number of characters entered                *
  1696. *                                    *
  1697. *************************************************************************/
  1698.  
  1699. getln(line)
  1700. char line[];
  1701. {
  1702.     int i;
  1703.  
  1704.     for (i=0; (line[i]=getchar()) != '\n';++i);
  1705.     line[i] = '\0';
  1706.     return(i);
  1707. }
  1708.  
  1709. /************************************************************************
  1710. *                                    *
  1711. * Module:    getnp                            *
  1712. * Purpose:    To get a number (decimal) from the keyboard        *
  1713. * Interface:    getnp(default,max)                    *
  1714. *  Input:    d (integer): Default value, if nothing entered        *
  1715. *        max (integer): Maximun value. If NULL, then no maximum    *
  1716. *  Output:    Through function name:                    *
  1717. *        Keyed, or default value                    *
  1718. *                                    *
  1719. *************************************************************************/
  1720.  
  1721. getnp(d,max)
  1722. int d,max;
  1723. {
  1724.     int    i,
  1725.         j,
  1726.         k;
  1727.  
  1728. /*    cursr_on();*/
  1729.     i = 0;
  1730.     k = 0;
  1731.     while(TRUE){
  1732.         putmenu(Getnp_m);
  1733.         while ((j=getnec()) != CR){
  1734.         if (j >= '0' && j <= '9'){
  1735.             k++;
  1736.             putchar(j);
  1737.             i = (i * 10) + (j - '0');
  1738.         }else if (j == BS){
  1739.             i /= 10;
  1740.             printf("%c %c",BS,BS);
  1741.         }else if (j == '\030'){    /* Handle Control X */
  1742.             while (k-- > 0)
  1743.             printf("%c %c",BS,BS);
  1744.             i = 0;
  1745.             k = 0;
  1746.         }else
  1747.             putchar(BEL);
  1748.         }
  1749.         if (k == 0){
  1750.         i = d;
  1751.         break;
  1752.         }
  1753.         if ((max == 0) || (k <= max))
  1754.         break;
  1755.         putchar(BEL);
  1756.         putmenu("Entry too large");
  1757.     }
  1758. /*    cursr_off();*/
  1759.     return(i);
  1760. }
  1761.  
  1762. /************************************************************************
  1763. *                                    *
  1764. * Module:    gnxtfl                            *
  1765. * Purpose:    To get the next file in a group, if there is one    *
  1766. * Interface:    gnxtfl()                        *
  1767. *                                    *
  1768. *************************************************************************/
  1769.  
  1770. gnxtfl()
  1771. {
  1772.     return(EOF);
  1773. }
  1774. /************************************************************************
  1775. *                                    *
  1776. * Module:    minit()                            *
  1777. * Purpose:    To initialise the message screen for data communications*
  1778. * Input:    message: Message type (Sending/receiving)        *
  1779. *        name:    File name involved                *
  1780. * Output:    None                            *
  1781. *                                    *
  1782. *************************************************************************/
  1783.  
  1784. minit(message,name)
  1785. char *message,*name;
  1786. {
  1787.     int x,y;
  1788.  
  1789.     clear_screen();
  1790.     putmenu(Startms);
  1791.     pos(5,(38-(strlen(message)+strlen(name))/2));
  1792.     putistr("RECEIVE FILE: ");
  1793.     putistr(name);
  1794.     plotstr(7,30,"Transmision Statistics");
  1795.     plotustr(8,1,
  1796. "                 Send    Receive           Accumulated Data              ");
  1797.     plotstr(9,1,"Message Type:");
  1798.     plotstr(10,1,"Message Number:");
  1799.     plotstr(11,1,"Data Length:");
  1800.     plotstr(9,40,"Transmision State:");
  1801.     plotstr(10,40,"Number of Messages:");
  1802.     plotstr(11,40,"Number of Characters:");
  1803.     Trace.si = 0;
  1804.     Trace.ri = 0;
  1805.     Msem = TRUE;
  1806. }
  1807. /************************************************************************
  1808. *                                    *
  1809. * Module:    prpack                            *
  1810. * Purpose:    To print a packet                    *
  1811. * Interface:    prpack(len,num,type,data,chksum)            *
  1812. *  Input:    len (int): Length of data to be sent            *
  1813. *        num (int): Message number                *
  1814. *        type (char): Type of message                *
  1815. *        data (char[]): Data to be sent                *
  1816. *        chksum (int): Check sum being sent            *
  1817. *  Output:    None                            *
  1818. *                                    *
  1819. *************************************************************************/
  1820.  
  1821. prpack(state,len,num,type,data)
  1822. int state,len,num;
  1823. char type,data[];
  1824. {
  1825.     int    i,ch;
  1826.     static    y;
  1827.  
  1828.     ch = (state == SEND)?18: 27;
  1829.     plotc(9,ch,type);
  1830.     plotd(10,ch,num);
  1831.     plotd(11,ch,len);
  1832.     plotU(10,66,Nmess);
  1833.     plotU(11,66,Nch);
  1834.     if (Display){
  1835.         if (Msem == TRUE){
  1836.         Msem = FALSE;
  1837.         y = 32;
  1838.         }
  1839.         for (i=0; i < len; i++){
  1840.         if ((ch=data[i]) == Myquote){
  1841.             if ((ch=data[++i]) != Myquote)
  1842.             if ((ch=ctl(ch&0x0ff)) == LF){
  1843.                 y = 32;
  1844.                 plotstr(11,0,"\033M\033Y6 ");
  1845.                 ch = CR;
  1846.             }
  1847.         }
  1848.         plotc(23,y++,ch);
  1849.         }
  1850.     }
  1851. }
  1852.  
  1853. /************************************************************************
  1854. *                                    *
  1855. * Module:    rpar                            *
  1856. * Purpose:    To receive initialisation parameters from host        *
  1857. *  Input:    data: Parameters sent by host.                *
  1858. *  Output:    Spsiz, Timint, Pad, Padchar, Eol, Quote are set        *
  1859. *                                    *
  1860. *************************************************************************/
  1861.  
  1862. rpar(data)
  1863. char data[];
  1864. {
  1865.     Spsiz = unchar(data[0]);
  1866.     Timint = unchar(data[1]);
  1867.     Pad = unchar(data[2]);
  1868.     Padchar = ctl(data[3]);
  1869.     Eol = unchar(data[4]);
  1870.     Quote = data[5];
  1871. }
  1872.  
  1873. /************************************************************************
  1874. *                                    *
  1875. * Module:    spar                            *
  1876. * Purpose:    To send initialisation parameters to the host        *
  1877. * Input:    Spsiz, Timint, Pad, Padchar, Eol, Quote are set        *
  1878. * Output:    data: Parameters to send to the host            *
  1879. *                                    *
  1880. *************************************************************************/
  1881.  
  1882. spar(data)
  1883. char data[];
  1884. {
  1885.     data[0] = tochar(Maxpack);
  1886.     data[1] = tochar(Mytime);
  1887.     data[2] = tochar(Mypad);
  1888.     data[3] = ctl(Mypchar);
  1889.     data[4] = tochar(Myeol);
  1890.     data[5] = Myquote;
  1891. }
  1892. /* */
  1893. /************************************************************************
  1894. *                                    *
  1895. *            SERIAL I/O UTILITIES                *
  1896. *                                    *
  1897. *************************************************************************/
  1898.  
  1899. /************************************************************************
  1900. *                                    *
  1901. * Module:    sbaud                            *
  1902. * Purpose:    To set the baud rate                    *
  1903. * Interface:    sbaud(baud,port)                    *
  1904. *  Input:    baud (int): Baud rate:    0 = 300 baud            *
  1905. *                    1 = 600 baud            *
  1906. *                    2 = 1200 Baud            *
  1907. *                    3 = 2400 baud            *
  1908. *                    4 = 4800 baud            *
  1909. *                    5 = 9600 baud            *
  1910. *        port (int): Serial Port:0 = Port A            *
  1911. *                    1 = Port B            *
  1912. *  Output:    None                            *
  1913. *                                    *
  1914. *************************************************************************/
  1915.  
  1916. sbaud(baud,port)
  1917. int baud, port;
  1918. {
  1919.     pokeb(3,0x0e002, ((port == PORTA)? 0x036: 0x076));
  1920.     baud *= 2;
  1921.     pokeb(port,0x0e002,Rate[baud]);
  1922.     pokeb(port,0x0e002,Rate[baud+1]);
  1923. }
  1924.  
  1925. /************************************************************************
  1926. *                                    *
  1927. * Module:    scheck                            *
  1928. * Purpose:    To check if a character is available at the port    *
  1929. *        and return it if there is one                *
  1930. * Interface:    scheck(port)                        *
  1931. * Parameters:                                *
  1932. *  Input:    port (int): Port id: 0 = Port A                *
  1933. *                     1 = Port B                *
  1934. *  Output:    Through function name (int):                *
  1935. *        Character found,or FALSE (i.e. 0)            *
  1936. *                                    *
  1937. *************************************************************************/
  1938.  
  1939. scheck(port)
  1940. int port;
  1941. {
  1942.     return( (sstatus(RX,port))?        /* Check status */
  1943.         (peek(port,0x0e004) & 0x0ff):    /* Return character */
  1944.         0
  1945.         );
  1946. }
  1947. /************************************************************************
  1948. *                                    *
  1949. * Module:    sgetc                            *
  1950. * Purpose:    To get a character from the serial port            *
  1951. * Interface:    sgetc(port)                        *
  1952. * Parameters:                                *
  1953. *  Input:    port (int): Port id: 0 = Port A                *
  1954. *                     1 = Port B                *
  1955. *  Output:    Through function name (char):                *
  1956. *        Character read at port                    *
  1957. *                                    *
  1958. *************************************************************************/
  1959. sgetc(port)
  1960. int port;
  1961. {
  1962.     unsigned    timer,
  1963.             ch;
  1964.  
  1965.     while (TRUE){
  1966.             for (timer=0;--timer > 0 && (sstatus(RX,port) == FALSE););
  1967.         if (timer == 0){
  1968.         if (getkbs()){    /* TRUE if character present */
  1969.             if ((ch=getnec()) == CR){
  1970.             longjmp (escape,RECEIVE);
  1971.             }else if (ch == DEL){
  1972.             State = abort("Time out on Input");
  1973.             longjmp (escape,RECEIVE);
  1974.             }
  1975.         }else
  1976.             putchar(BEL);
  1977.         }else
  1978.         return(peek(port,0x0e004) & 0x07f);
  1979.     }
  1980. }
  1981.  
  1982. /************************************************************************
  1983. *                                    *
  1984. * Module:    sputc                            *
  1985. * Purpose:    To put a character out to the serial port        *
  1986. * Interface:    sputc(ch,port)                        *
  1987. * Parameters:                                *
  1988. *  Input:    ch (char): Character to output                *
  1989. *        port (int): Port id: 0 = Port A                *
  1990. *                     1 = Port B                *
  1991. *  Output:    None                            *
  1992. *                                    *
  1993. *************************************************************************/
  1994.  
  1995. sputc(ch,port)
  1996. char ch;
  1997. int port;
  1998. {
  1999.     unsigned    timer,
  2000.             c;
  2001.  
  2002.     while (TRUE){
  2003.         for (timer=0;--timer > 0 && sstatus(TX,port) == FALSE;);
  2004.         if (timer == 0){    /* If timed out */
  2005.         if (getkbs()){
  2006.             if ((c=getnec()) == CR)
  2007.             longjmp (escape,SEND);
  2008.             else if (c == DEL){
  2009.             State = abort("Time out on Output");
  2010.             longjmp (escape,SEND);
  2011.             }
  2012.         }else
  2013.             putchar(BEL);
  2014.         }else{
  2015.         pokeb(port,0x0e004,ch & 0x07f);
  2016.         break;
  2017.         }
  2018.     }
  2019. }
  2020.  
  2021. /************************************************************************
  2022. *                                    *
  2023. * Module:    portinit                        *
  2024. * Purpose:    To initialise the specified port            *
  2025. * Interface:    portinit(port)                        *
  2026. *  Input:    port (int): Id of port to initialise:    0 = Port A    *
  2027. *                            1 = Port B    *
  2028. *  Output:    None                            *
  2029. *                                    *
  2030. *************************************************************************/
  2031.  
  2032. portinit(port)
  2033. int port;
  2034. {
  2035.     int    control;
  2036.  
  2037.     control = port + 2;        /* Move to "Control" addresses */
  2038.     pokeb(control,0x0e004,0x018);    /* Channel Reset */
  2039.  
  2040.     pokeb(control,0x0e004,CR2);    /* Address control register 2 */
  2041.     pokeb(control,0x0e004,cr2[port]);
  2042.  
  2043.     pokeb(control,0x0e004,CR4);    /* Address control register 4 */
  2044.     pokeb(control,0x0e004,cr4[port]);
  2045.  
  2046.     pokeb(control,0x0e004,CR3);    /* Address control register 3 */
  2047.     pokeb(control,0x0e004,cr3[port]);
  2048.  
  2049.     pokeb(control,0x0e004,CR5);    /* Address control register 5 */
  2050.     pokeb(control,0x0e004,cr5[port]);
  2051.  
  2052.     pokeb(control,0x0e004,0x011);    /* Disable interupts */
  2053.     pokeb(control,0x0e004,0);
  2054. }
  2055.