home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / c-kermit / ckscon.c < prev    next >
C/C++ Source or Header  |  2020-01-01  |  16KB  |  540 lines

  1. char *connv = "CONNECT Command for Atari ST, 5A(031) 20 Jul 92";
  2. /*  C K S C O N  --  Dumb terminal connection to remote system, for Atari ST */
  3. /*
  4.   Author: Frank da Cruz (fdc@columbia.edu, FDCCU@CUVMA.BITNET),
  5.   Columbia University Center for Computing Activities.
  6.   First released January 1985.
  7.   Copyright (C) 1985, 1992, Trustees of Columbia University in the City of New
  8.   York.  Permission is granted to any individual or institution to use this
  9.   software as long as it is not sold for profit.  This copyright notice must be
  10.   retained.  This software may not be included in commercial products without
  11.   written permission of Columbia University.
  12.   Extensive modifications for Atari ST by:
  13.   Bruce Moore (mooreb@iccgcc.decnet.ab.com).
  14. */
  15.  
  16. #include "ckcdeb.h"            /* Common things */
  17.  
  18. /* Kermit-specific includes */
  19.  
  20. #include "ckcasc.h"            /* ASCII characters */
  21. #include "ckcker.h"            /* Kermit things */
  22. #include "ckucmd.h"            /* For xxesc() prototype */
  23. #include "ckcnet.h"            /* Network symbols */
  24. #ifndef NOCSETS
  25. #include "ckcxla.h"            /* Character set translation */
  26. #endif /* NOCSETS */
  27.  
  28. #include <osbind.h>
  29. #define _auxis() (!! Bconstat(1))
  30. #define _auxos() (!! Bcostat(1))
  31. #define _auxin() Bconin(1)
  32. #define _auxout(x) Bconout(1,x)
  33.  
  34. #define _conis() (!! Bconstat(2))
  35. #define _conos() (!! Bcostat(2))
  36. #define _necin() Bconin(2)
  37. #define _conout(x) Bconout(2,x)
  38.  
  39. #define AUXSIZE 2048
  40. #define CONSIZE 128
  41. static char auxbuf[AUXSIZE];    /* Buffer for chars *from* aux port */
  42. static char conbuf[CONSIZE];    /* Buffer for chars *from* console port */
  43. static int auxsize = 0;        /* Number of chars in auxbuf */
  44. static int consize = 0;        /* Number of chars in conbuf */
  45. static char *auxfil = &auxbuf[0];    /* Fill end of aux queue */
  46. static char *auxend = &auxbuf[AUXSIZE-1];    /* End of auxbuf */
  47. static char *auxfls = &auxbuf[0];    /* Flush end of aux queue */
  48. static char *confil = &conbuf[0];    /* Fill end of console queue */
  49. static char *conend = &conbuf[CONSIZE-1];    /* End of conbuf */
  50. static char *confls = &conbuf[0];    /* Flush end of console queue */
  51. #define conoc(x) {*auxfil++ =(x);if(auxfil>auxend)auxfil= &auxbuf[0];auxsize++;}
  52. #define ttoc(x) {*confil++ =(x);if(confil>conend)confil= &conbuf[0];consize++;}
  53.  
  54. /* Internal function prototypes */
  55.  
  56. _PROTOTYP( VOID doesc, (char) );
  57. _PROTOTYP( VOID logchar, (char) );
  58. _PROTOTYP( int hconne, (void) );
  59.  
  60. /* External variables */
  61.  
  62. extern int local, escape, duplex, parity, flow, seslog, sessft, debses,
  63.  mdmtyp, ttnproto, cmask, cmdmsk, network, nettype, deblog, sosi, tnlm,
  64.  xitsta, what, ttyfd, quiet, backgrd;
  65. extern long speed;
  66. extern char ttname[], sesfil[], myhost[];
  67.  
  68. #ifndef NOSETKEY            /* Keyboard mapping */
  69. extern KEY *keymap;            /* Single-character key map */
  70. extern MACRO *macrotab;            /* Key macro pointer table */
  71. static MACRO kmptr = NULL;        /* Pointer to current key macro */
  72. #endif /* NOSETKEY */
  73.  
  74. /* Global variables local to this module */
  75.   
  76. static int quitnow = 0,            /* <esc-char>Q was typed */
  77.   dohangup = 0,                /* <esc-char>H was typed */
  78.   goterr = 0,                /* I/O error flag */
  79.   active = 0,                /* Lower fork active flag */
  80.   shift = 0;                /* SO/SI shift state */
  81.  
  82. static char kbuf[10], *kbp;        /* Keyboard buffer & pointer */
  83. #define LBUFL 200            /* Line buffer length */
  84. #define TMPLEN 50            /* Temp buffer length */
  85. static char temp[TMPLEN];
  86. #ifdef DYNAMIC
  87. static char *lbuf;            /* Line buffer */
  88. #else
  89. static char lbuf[LBUFL];
  90. #endif /* DYNAMIC */
  91.  
  92. /*  C O N E C T  --  Perform terminal connection  */
  93.  
  94. /* Character-set items */
  95.  
  96. #ifndef NOCSETS
  97. #ifdef CK_ANSIC /* ANSI C prototypes... */
  98. extern CHAR (*xls[MAXTCSETS+1][MAXFCSETS+1])(CHAR); /* Character set */
  99. extern CHAR (*xlr[MAXTCSETS+1][MAXFCSETS+1])(CHAR); /* translation functions */
  100. static CHAR (*sxo)(CHAR);    /* Local translation functions */
  101. static CHAR (*rxo)(CHAR);    /* for output (sending) terminal chars */
  102. static CHAR (*sxi)(CHAR);    /* and for input (receiving) terminal chars. */
  103. static CHAR (*rxi)(CHAR);
  104. #else /* Not ANSI C... */
  105. extern CHAR (*xls[MAXTCSETS+1][MAXFCSETS+1])();    /* Character set */
  106. extern CHAR (*xlr[MAXTCSETS+1][MAXFCSETS+1])();    /* translation functions. */
  107. static CHAR (*sxo)();        /* Local translation functions */
  108. static CHAR (*rxo)();        /* for output (sending) terminal chars */
  109. static CHAR (*sxi)();        /* and for input (receiving) terminal chars. */
  110. static CHAR (*rxi)();
  111. #endif /* CK_ANSIC */
  112. extern int language;        /* Current language. */
  113. static int langsv;        /* For remembering language setting. */
  114. extern struct csinfo fcsinfo[]; /* File character set info. */
  115. extern int tcsr, tcsl;        /* Terminal character sets, remote & local. */
  116. static int tcs;            /* Intermediate ("transfer") character set. */
  117. #endif /* NOCSETS */
  118.  
  119. int
  120. conect() {
  121.     int c;            /* c is a character, but must be signed 
  122.                    integer to pass thru -1, which is the
  123.                    modem disconnection signal, and is
  124.                    different from the character 0377 */
  125.     int c2;            /* A copy of c */
  126.     int csave;            /* Another copy of c */
  127.  
  128.     int eschit = 0;
  129.  
  130.     if (!local) {
  131.     printf("Sorry, you must SET LINE first\n");
  132.     return(0);
  133.     }
  134.     if (speed < 0L && network == 0) {
  135.     printf("Sorry, you must SET SPEED first\n");
  136.     return(0);
  137.     }
  138.  
  139.     if (ttyfd < 0) {            /* If communication device not open */
  140.     debug(F111,"ckucon opening",ttname,0); /* Open it now */
  141.     if (ttopen(ttname,&local,mdmtyp,0) < 0) {
  142.         sprintf(temp,"Sorry, can't open %s",ttname);
  143.         perror(temp);
  144.         debug(F110,"ckucon open failure",temp,0);
  145.         return(0);
  146.     }
  147.     }
  148.     dohangup = 0;
  149.     if (!quiet) printf("Connecting to %s",ttname);
  150.     if (speed > -1L && !quiet) printf(", speed %ld",speed);
  151.  
  152.     if (!quiet) {
  153.     printf(".\r\nThe escape character is %s (ASCII %d).\r\n",
  154.            dbchr(escape),escape);
  155.     printf("Type the escape character followed by C to get back,\r\n");
  156.     printf("or followed by ? to see other options.\r\n");
  157.     if (seslog) {
  158.         printf("(Session logged to %s, ",sesfil);
  159.         printf("%s)\r\n", sessft ? "binary" : "text");
  160.     }
  161.     if (debses) printf("Debugging Display...)\r\n");
  162.     }
  163.  
  164. /* Condition console terminal and communication line */    
  165.  
  166.     if (conbin(escape) < 0) {
  167.     printf("Sorry, can't condition console terminal\n");
  168.     return(0);
  169.     }
  170.     debug(F101,"connect cmask","",cmask);
  171.     debug(F101,"connect cmdmsk","",cmdmsk);
  172.     goterr = 0;
  173.  
  174.     if (ttvt(speed,flow) < 0) {    /* Try virtual terminal mode again. */
  175.     conres();            /* Failure is fatal. */
  176.     printf("Sorry, Can't condition communication line\n");
  177.     return(0);
  178.     }
  179.     debug(F101,"connect ttvt ok, escape","",escape);
  180. #ifdef DYNAMIC
  181.     if (!(lbuf = malloc(LBUFL+1))) {    /* Allocate input line buffer */
  182.     printf("Sorry, CONNECT input buffer can't be allocated\n");
  183.     return(0);
  184.     }
  185. #endif /* DYNAMIC */
  186.  
  187. #ifndef NOCSETS
  188. /* Set up character set translations */
  189.  
  190. #ifdef KANJI
  191. /* Kanji not supported yet */
  192.     if (fcsinfo[tcsr].alphabet == AL_JAPAN ||
  193.     fcsinfo[tcsl].alphabet == AL_JAPAN ) {
  194.     tcs = TC_TRANSP;
  195.     } else
  196. #endif /* KANJI */
  197. #ifdef CYRILLIC
  198.       if (fcsinfo[tcsl].alphabet == AL_CYRIL) {
  199.       tcs = TC_CYRILL;
  200.       } else
  201. #endif /* CYRILLIC */
  202.     tcs = TC_1LATIN;
  203.  
  204.     if (tcsr == tcsl) {            /* Remote and local sets the same? */
  205.     sxo = rxo = NULL;        /* If so, no translation. */
  206.     sxi = rxi = NULL;
  207.     } else {                /* Otherwise, set up */
  208.     sxo = xls[tcs][tcsl];        /* translation function */
  209.     rxo = xlr[tcs][tcsr];        /* pointers for output functions */
  210.     sxi = xls[tcs][tcsr];        /* and for input functions. */
  211.     rxi = xlr[tcs][tcsl];
  212.     }
  213. /*
  214.   This is to prevent use of zmstuff() and zdstuff() by translation functions.
  215.   They only work with disk i/o, not with communication i/o.  Luckily Russian
  216.   translation functions don't do any stuffing...
  217. */
  218.     langsv = language;
  219. #ifndef NOCYRIL
  220.     if (language != L_RUSSIAN)
  221. #endif /* NOCYRIL */
  222.       language = L_USASCII;
  223. #endif /* NOCSETS */
  224.  
  225.     what = W_CONNECT;        /* Keep track of what we're doing */
  226.     active = 1;            /* Connect mode active */
  227.  
  228. /*
  229.   Here is the big loop that gets characters from the keyboard and sends them
  230.   out the communication device.  There are two components to the communication
  231.   path: the connection from the keyboard to C-Kermit, and from C-Kermit to
  232.   the remote computer.  The treatment of the 8th bit of keyboard characters
  233.   is governed by SET COMMAND BYTESIZE (cmdmsk).  The treatment of the 8th bit
  234.   of characters sent to the remote is governed by SET TERMINAL BYTESIZE
  235.   (cmask).   This distinction was introduced in edit C-Kermit 5A(164).
  236. */
  237.     while (active) {
  238. #ifndef NOSETKEY
  239.     if (kmptr) {        /* Have current macro? */
  240.         if ((c = (CHAR) *kmptr++) == NUL) { /* Get char from it */
  241.         kmptr = NULL;    /* If no more chars,  */
  242.         continue;    /* reset pointer and continue */
  243.         }
  244.     } else            /* No macro... */
  245. #endif /* NOSETKEY */
  246.     if (_conis()) {        /* If character available from keyboard */
  247.         c = _necin();    /* Get character from keyboard */
  248.         c &= cmdmsk;    /* Do any requested masking */
  249.  
  250. #ifndef NOSETKEY
  251. /*
  252.   Note: kmptr is NULL if we got character c from the keyboard, and it is
  253.   not NULL if it came from a macro.  In the latter case, we must avoid
  254.   expanding it again.
  255. */
  256.         if (!kmptr && macrotab[c]) { /* Macro definition for c? */
  257.         kmptr = macrotab[c];     /* Yes, set up macro pointer */
  258.         continue;             /* and restart the loop, */
  259.         } else c = keymap[c];         /* else use single-char keymap */
  260. #endif /* NOSETKEY */
  261.         csave = c;        /* Save char before translation */
  262.  
  263.         if (eschit) {
  264.         doesc(c);            /* Process escape argument */
  265.         eschit = 0;
  266.         } else if (
  267. #ifndef NOSETKEY
  268.         !kmptr &&
  269. #endif /* NOSETKEY */
  270.         ((c & 0x7f) == escape)) { /* Look for escape char */
  271.         debug(F000,"connect got escape","",c);
  272.         eschit++;
  273.         } else {        /* Ordinary character */
  274. #ifndef NOCSETS
  275.         /* Translate character sets */
  276.         if (sxo) c = (*sxo)(c); /* From local to intermediate. */
  277.         if (rxo) c = (*rxo)(c); /* From intermediate to remote. */
  278. #endif /* NOCSETS */
  279. /*
  280.  * If Shift-In/Shift-Out is selected and we have a 7-bit connection,
  281.  * handle shifting here.
  282.  */
  283.         if (sosi) {            /* Shift-In/Out selected? */
  284.             if (cmask == 0177) {    /* In 7-bit environment? */
  285.             if (c & 0200) {        /* 8-bit character? */
  286.                 if (shift == 0) {    /* If not shifted, */
  287.                 ttoc(dopar(SO)); /* shift. */
  288.                 shift = 1;
  289.                 }
  290.             } else {
  291.                 if (shift == 1) {        /* 7-bit character */
  292.                 ttoc(dopar(SI));    /* If shifted, */
  293.                 shift = 0;        /* unshift. */
  294.                 }
  295.             }
  296.             }
  297.             if (c == SO) shift = 1;    /* User typed SO */
  298.             if (c == SI) shift = 0;    /* User typed SI */
  299.         }
  300.         c &= cmask;    /* Apply Kermit-to-host mask now. */
  301.  
  302.         /* Send the character that the user typed. */
  303.  
  304.         ttoc(dopar(c));
  305.         if (duplex) {        /* Half duplex? */
  306.             if (debses)
  307.             conol(dbchr(csave));
  308.             else
  309.             conoc(csave);    /* Buffer char to screen, too */
  310.             if (seslog) {    /* And maybe log it too */
  311.             c2 = csave;
  312.             if (sessft == 0 && csave == '\r')
  313.                 c2 = '\n';
  314.             logchar(c2);
  315.             }
  316.         }
  317.         }
  318.     }
  319.  
  320.     while (_auxis()) {        /* While chars avail from comm line */
  321.         c = _auxin();        /* Get a character from comm line */
  322.         if (debses) {        /* Output character to screen */
  323.         conol(dbchr(c));    /* debugging */
  324.         } else {            /* or regular... */
  325.         c &= cmask;        /* Do first masking */
  326.         if (sosi        /* Handle SI/SO */
  327. #ifndef NOCSETS
  328.                 || tcsl != tcsr
  329. #endif /* NOCSETS */
  330.                 ) {
  331.             if (c == SO) {    /* Shift Out */
  332.             shift = 1;
  333.             continue;
  334.             } else if (c == SI) { /* Shift In */
  335.             shift = 0;
  336.             continue;
  337.             }
  338.             if (shift) c |= 0200;
  339.         }
  340. #ifndef NOCSETS
  341.         /* Translate character sets */
  342.         if (sxi) c = (*sxi)(c);
  343.         if (rxi) c = (*rxi)(c);
  344. #endif
  345.         c &= cmdmsk;        /* Apply command mask */
  346.         conoc(c);        /* Buffer the character */
  347.         if (seslog) logchar(c);    /* Take care of session log */
  348.         }
  349.     }
  350.  
  351.     while (auxsize && _conos()) {    /* Output aux chars to the screen */
  352.         c = *auxfls++;
  353.         if (auxfls > auxend)
  354.         auxfls = &auxbuf[0];
  355.         auxsize--;
  356.         _conout(c);            /* Put it on the screen. */
  357.     }
  358.  
  359.     if (consize && _auxos()) {    /* Output keyboard chars to aux port */
  360.         c = *confls++;
  361.         if (confls > conend)
  362.         confls = &conbuf[0];
  363.         consize--;
  364.         _auxout(c);
  365.     }
  366.     }
  367.     conres();            /* Reset the console. */
  368.     if (quitnow)
  369.     doexit(GOOD_EXIT, xitsta);    /* Exit now if requested */
  370.     if (dohangup) {        /* If hangup requested, do that */
  371.     tthang();
  372.     dohangup = 0;
  373.     }
  374.     if (!quiet) printf("[Back at Local System]");
  375.     printf("\n");
  376.     what = W_NOTHING;        /* So console modes set right. */
  377. #ifndef NOCSETS
  378.     language = langsv;        /* Restore language */
  379. #endif /* NOCSETS */
  380. #ifdef DYNAMIC
  381.     if (lbuf) free(lbuf);        /* Free allocated memory */
  382. #endif /* DYNAMIC */
  383.     return(1);
  384. }
  385.  
  386. /*  H C O N N E  --  Give help message for connect.  */
  387.  
  388. hconne() {
  389.     int c;
  390.     static char *hlpmsg[] = {"\
  391. \r\n  C to return to the C-Kermit prompt, or:",
  392. "\r\n  0 (zero) to send a null",
  393. "\r\n  B to send a BREAK",
  394. "\r\n  U to hangup and return to the C-Kermit prompt",
  395. "\r\n  Q to hangup and quit Kermit",
  396. "\r\n  S for status",
  397. "\r\n  ! to push to local shell",
  398. "\r\n  \\ backslash escape:",
  399. "\r\n    \\nnn decimal character code",
  400. "\r\n    \\Onnn octal character code",
  401. "\r\n    \\Xhh  hexadecimal character code",
  402. "\r\n    terminate with carriage return.",
  403. "\r\n  ? for help",
  404. "\r\n escape character twice to send the escape character",
  405. "\r\n space-bar to resume the CONNECT command\r\n\r\n",
  406. "" };
  407.  
  408.     conol("\r\nPress C to return to ");
  409.     conol("the C-Kermit prompt");
  410.     conol(", or:");
  411.     conola(hlpmsg);            /* Print the help message. */
  412.     conol("Command>");            /* Prompt for command. */
  413.     c = _necin() & 0177;        /* Get character, strip any parity. */
  414.     /* No key mapping or translation here */
  415.     if (c != CMDQ)
  416.       conoll("");
  417.     return(c);                /* Return it. */
  418. }
  419.  
  420.  
  421. /*  D O E S C  --  Process an escape character argument  */
  422.  
  423. VOID
  424. #ifdef CK_ANSIC
  425. doesc(char c)
  426. #else
  427. doesc(c) char c;
  428. #endif /* CK_ANSIC */
  429. /* doesc */ {
  430.     CHAR d;
  431.  
  432.     while (1) {
  433.     if (c == escape) {        /* Send escape character */
  434.         d = dopar(c); ttoc(d); return;
  435.         } else                /* Or else look it up below. */
  436.         if (isupper(c)) c = tolower(c);
  437.  
  438.     switch(c) {
  439.  
  440.     case 'c':            /* Close connection */
  441.     case '\03':
  442.         active = 0; conol("\r\n"); return;
  443.  
  444.     case 'b':            /* Send a BREAK signal */
  445.     case '\02':
  446.         ttsndb(); return;
  447.  
  448.     case 'u':            /* Hangup */
  449.     case '\010':
  450.         dohangup = 1; active = 0; conol("\r\nHanging up "); return;
  451.  
  452.     case 'q':
  453.         quitnow = 1; active = 0; conol("\r\n"); return;
  454.  
  455.     case 's':            /* Status */
  456.         conol("\r\nConnected thru ");
  457.         conol(ttname);
  458.         if (speed >= 0L) {
  459.         sprintf(temp,", speed %ld",speed); conol(temp);
  460.         }
  461.         sprintf(temp,", %d terminal bits",(cmask == 0177) ? 7 : 8);
  462.         conol(temp);
  463.         if (parity) {
  464.         conol(", ");
  465.         switch (parity) {
  466.             case 'e': conol("even");  break;
  467.             case 'o': conol("odd");   break;
  468.             case 's': conol("space"); break;
  469.             case 'm': conol("mark");  break;
  470.         }
  471.         conol(" parity");
  472.         }
  473.         if (seslog) {
  474.         conol(", logging to "); conol(sesfil);
  475.             }
  476.         conoll(""); return;
  477.  
  478.     case 'h':            /* Help */
  479.     case '?':            /* Help */
  480.         c = hconne(); continue;
  481.  
  482.     case '0':            /* Send a null */
  483.         c = '\0'; d = dopar(c); ttoc(d); return;
  484.  
  485.     case '@':            /* Start inferior command processor */
  486.     case '!':
  487.         conres();            /* Put console back to normal */
  488.         zshcmd("");            /* Fork a shell. */
  489.         if (conbin(escape) < 0) {
  490.         printf("Error resuming CONNECT session\n");
  491.         active = 0;
  492.         }
  493.         return;
  494.  
  495.     case SP:            /* Space, ignore */
  496.         return;
  497.  
  498.     default:            /* Other */
  499.         if (c == CMDQ) {        /* Backslash escape */
  500.         int x;
  501.         kbp = kbuf;
  502.         *kbp++ = c;
  503.         while (((c = (_necin() & cmdmsk)) != '\r') && (c != '\n'))
  504.           *kbp++ = c;
  505.         *kbp = NUL; kbp = kbuf;
  506.         x = xxesc(&kbp);    /* Interpret it */
  507.         if (x >= 0) {        /* No key mapping here */
  508.             c = dopar(x);
  509.             ttoc(c);
  510.             return;
  511.         } else {        /* Invalid backslash code. */
  512.             conoc(BEL);
  513.             return;
  514.         }
  515.         }
  516.         conoc(BEL); return;     /* Invalid esc arg, beep */
  517.         }
  518.     }
  519. }
  520.  
  521. VOID
  522. #ifdef CK_ANSIC
  523. logchar(char c)
  524. #else
  525. logchar(c) char c;
  526. #endif /* CK_ANSIC */
  527. /* logchar */ {            /* Log character c to session log */
  528.     if (seslog) 
  529.       if ((sessft != 0) ||
  530.       (c != '\r' &&
  531.        c != '\0' &&
  532.        c != XON &&
  533.        c != XOFF))
  534.     if (zchout(ZSFILE,c) < 0) {
  535.         conoll("");
  536.         conoll("ERROR WRITING SESSION LOG, LOG CLOSED!");
  537.         seslog = 0;
  538.     }
  539. }
  540.