char *connv = "CONNECT Command for Atari ST, 5A(031) 20 Jul 92"; /* C K S C O N -- Dumb terminal connection to remote system, for Atari ST */ /* Author: Frank da Cruz (fdc@columbia.edu, FDCCU@CUVMA.BITNET), Columbia University Center for Computing Activities. First released January 1985. Copyright (C) 1985, 1992, Trustees of Columbia University in the City of New York. Permission is granted to any individual or institution to use this software as long as it is not sold for profit. This copyright notice must be retained. This software may not be included in commercial products without written permission of Columbia University. Extensive modifications for Atari ST by: Bruce Moore (mooreb@iccgcc.decnet.ab.com). */ #include "ckcdeb.h" /* Common things */ /* Kermit-specific includes */ #include "ckcasc.h" /* ASCII characters */ #include "ckcker.h" /* Kermit things */ #include "ckucmd.h" /* For xxesc() prototype */ #include "ckcnet.h" /* Network symbols */ #ifndef NOCSETS #include "ckcxla.h" /* Character set translation */ #endif /* NOCSETS */ #include #define _auxis() (!! Bconstat(1)) #define _auxos() (!! Bcostat(1)) #define _auxin() Bconin(1) #define _auxout(x) Bconout(1,x) #define _conis() (!! Bconstat(2)) #define _conos() (!! Bcostat(2)) #define _necin() Bconin(2) #define _conout(x) Bconout(2,x) #define AUXSIZE 2048 #define CONSIZE 128 static char auxbuf[AUXSIZE]; /* Buffer for chars *from* aux port */ static char conbuf[CONSIZE]; /* Buffer for chars *from* console port */ static int auxsize = 0; /* Number of chars in auxbuf */ static int consize = 0; /* Number of chars in conbuf */ static char *auxfil = &auxbuf[0]; /* Fill end of aux queue */ static char *auxend = &auxbuf[AUXSIZE-1]; /* End of auxbuf */ static char *auxfls = &auxbuf[0]; /* Flush end of aux queue */ static char *confil = &conbuf[0]; /* Fill end of console queue */ static char *conend = &conbuf[CONSIZE-1]; /* End of conbuf */ static char *confls = &conbuf[0]; /* Flush end of console queue */ #define conoc(x) {*auxfil++ =(x);if(auxfil>auxend)auxfil= &auxbuf[0];auxsize++;} #define ttoc(x) {*confil++ =(x);if(confil>conend)confil= &conbuf[0];consize++;} /* Internal function prototypes */ _PROTOTYP( VOID doesc, (char) ); _PROTOTYP( VOID logchar, (char) ); _PROTOTYP( int hconne, (void) ); /* External variables */ extern int local, escape, duplex, parity, flow, seslog, sessft, debses, mdmtyp, ttnproto, cmask, cmdmsk, network, nettype, deblog, sosi, tnlm, xitsta, what, ttyfd, quiet, backgrd; extern long speed; extern char ttname[], sesfil[], myhost[]; #ifndef NOSETKEY /* Keyboard mapping */ extern KEY *keymap; /* Single-character key map */ extern MACRO *macrotab; /* Key macro pointer table */ static MACRO kmptr = NULL; /* Pointer to current key macro */ #endif /* NOSETKEY */ /* Global variables local to this module */ static int quitnow = 0, /* Q was typed */ dohangup = 0, /* H was typed */ goterr = 0, /* I/O error flag */ active = 0, /* Lower fork active flag */ shift = 0; /* SO/SI shift state */ static char kbuf[10], *kbp; /* Keyboard buffer & pointer */ #define LBUFL 200 /* Line buffer length */ #define TMPLEN 50 /* Temp buffer length */ static char temp[TMPLEN]; #ifdef DYNAMIC static char *lbuf; /* Line buffer */ #else static char lbuf[LBUFL]; #endif /* DYNAMIC */ /* C O N E C T -- Perform terminal connection */ /* Character-set items */ #ifndef NOCSETS #ifdef CK_ANSIC /* ANSI C prototypes... */ extern CHAR (*xls[MAXTCSETS+1][MAXFCSETS+1])(CHAR); /* Character set */ extern CHAR (*xlr[MAXTCSETS+1][MAXFCSETS+1])(CHAR); /* translation functions */ static CHAR (*sxo)(CHAR); /* Local translation functions */ static CHAR (*rxo)(CHAR); /* for output (sending) terminal chars */ static CHAR (*sxi)(CHAR); /* and for input (receiving) terminal chars. */ static CHAR (*rxi)(CHAR); #else /* Not ANSI C... */ extern CHAR (*xls[MAXTCSETS+1][MAXFCSETS+1])(); /* Character set */ extern CHAR (*xlr[MAXTCSETS+1][MAXFCSETS+1])(); /* translation functions. */ static CHAR (*sxo)(); /* Local translation functions */ static CHAR (*rxo)(); /* for output (sending) terminal chars */ static CHAR (*sxi)(); /* and for input (receiving) terminal chars. */ static CHAR (*rxi)(); #endif /* CK_ANSIC */ extern int language; /* Current language. */ static int langsv; /* For remembering language setting. */ extern struct csinfo fcsinfo[]; /* File character set info. */ extern int tcsr, tcsl; /* Terminal character sets, remote & local. */ static int tcs; /* Intermediate ("transfer") character set. */ #endif /* NOCSETS */ int conect() { int c; /* c is a character, but must be signed integer to pass thru -1, which is the modem disconnection signal, and is different from the character 0377 */ int c2; /* A copy of c */ int csave; /* Another copy of c */ int eschit = 0; if (!local) { printf("Sorry, you must SET LINE first\n"); return(0); } if (speed < 0L && network == 0) { printf("Sorry, you must SET SPEED first\n"); return(0); } if (ttyfd < 0) { /* If communication device not open */ debug(F111,"ckucon opening",ttname,0); /* Open it now */ if (ttopen(ttname,&local,mdmtyp,0) < 0) { sprintf(temp,"Sorry, can't open %s",ttname); perror(temp); debug(F110,"ckucon open failure",temp,0); return(0); } } dohangup = 0; if (!quiet) printf("Connecting to %s",ttname); if (speed > -1L && !quiet) printf(", speed %ld",speed); if (!quiet) { printf(".\r\nThe escape character is %s (ASCII %d).\r\n", dbchr(escape),escape); printf("Type the escape character followed by C to get back,\r\n"); printf("or followed by ? to see other options.\r\n"); if (seslog) { printf("(Session logged to %s, ",sesfil); printf("%s)\r\n", sessft ? "binary" : "text"); } if (debses) printf("Debugging Display...)\r\n"); } /* Condition console terminal and communication line */ if (conbin(escape) < 0) { printf("Sorry, can't condition console terminal\n"); return(0); } debug(F101,"connect cmask","",cmask); debug(F101,"connect cmdmsk","",cmdmsk); goterr = 0; if (ttvt(speed,flow) < 0) { /* Try virtual terminal mode again. */ conres(); /* Failure is fatal. */ printf("Sorry, Can't condition communication line\n"); return(0); } debug(F101,"connect ttvt ok, escape","",escape); #ifdef DYNAMIC if (!(lbuf = malloc(LBUFL+1))) { /* Allocate input line buffer */ printf("Sorry, CONNECT input buffer can't be allocated\n"); return(0); } #endif /* DYNAMIC */ #ifndef NOCSETS /* Set up character set translations */ #ifdef KANJI /* Kanji not supported yet */ if (fcsinfo[tcsr].alphabet == AL_JAPAN || fcsinfo[tcsl].alphabet == AL_JAPAN ) { tcs = TC_TRANSP; } else #endif /* KANJI */ #ifdef CYRILLIC if (fcsinfo[tcsl].alphabet == AL_CYRIL) { tcs = TC_CYRILL; } else #endif /* CYRILLIC */ tcs = TC_1LATIN; if (tcsr == tcsl) { /* Remote and local sets the same? */ sxo = rxo = NULL; /* If so, no translation. */ sxi = rxi = NULL; } else { /* Otherwise, set up */ sxo = xls[tcs][tcsl]; /* translation function */ rxo = xlr[tcs][tcsr]; /* pointers for output functions */ sxi = xls[tcs][tcsr]; /* and for input functions. */ rxi = xlr[tcs][tcsl]; } /* This is to prevent use of zmstuff() and zdstuff() by translation functions. They only work with disk i/o, not with communication i/o. Luckily Russian translation functions don't do any stuffing... */ langsv = language; #ifndef NOCYRIL if (language != L_RUSSIAN) #endif /* NOCYRIL */ language = L_USASCII; #endif /* NOCSETS */ what = W_CONNECT; /* Keep track of what we're doing */ active = 1; /* Connect mode active */ /* Here is the big loop that gets characters from the keyboard and sends them out the communication device. There are two components to the communication path: the connection from the keyboard to C-Kermit, and from C-Kermit to the remote computer. The treatment of the 8th bit of keyboard characters is governed by SET COMMAND BYTESIZE (cmdmsk). The treatment of the 8th bit of characters sent to the remote is governed by SET TERMINAL BYTESIZE (cmask). This distinction was introduced in edit C-Kermit 5A(164). */ while (active) { #ifndef NOSETKEY if (kmptr) { /* Have current macro? */ if ((c = (CHAR) *kmptr++) == NUL) { /* Get char from it */ kmptr = NULL; /* If no more chars, */ continue; /* reset pointer and continue */ } } else /* No macro... */ #endif /* NOSETKEY */ if (_conis()) { /* If character available from keyboard */ c = _necin(); /* Get character from keyboard */ c &= cmdmsk; /* Do any requested masking */ #ifndef NOSETKEY /* Note: kmptr is NULL if we got character c from the keyboard, and it is not NULL if it came from a macro. In the latter case, we must avoid expanding it again. */ if (!kmptr && macrotab[c]) { /* Macro definition for c? */ kmptr = macrotab[c]; /* Yes, set up macro pointer */ continue; /* and restart the loop, */ } else c = keymap[c]; /* else use single-char keymap */ #endif /* NOSETKEY */ csave = c; /* Save char before translation */ if (eschit) { doesc(c); /* Process escape argument */ eschit = 0; } else if ( #ifndef NOSETKEY !kmptr && #endif /* NOSETKEY */ ((c & 0x7f) == escape)) { /* Look for escape char */ debug(F000,"connect got escape","",c); eschit++; } else { /* Ordinary character */ #ifndef NOCSETS /* Translate character sets */ if (sxo) c = (*sxo)(c); /* From local to intermediate. */ if (rxo) c = (*rxo)(c); /* From intermediate to remote. */ #endif /* NOCSETS */ /* * If Shift-In/Shift-Out is selected and we have a 7-bit connection, * handle shifting here. */ if (sosi) { /* Shift-In/Out selected? */ if (cmask == 0177) { /* In 7-bit environment? */ if (c & 0200) { /* 8-bit character? */ if (shift == 0) { /* If not shifted, */ ttoc(dopar(SO)); /* shift. */ shift = 1; } } else { if (shift == 1) { /* 7-bit character */ ttoc(dopar(SI)); /* If shifted, */ shift = 0; /* unshift. */ } } } if (c == SO) shift = 1; /* User typed SO */ if (c == SI) shift = 0; /* User typed SI */ } c &= cmask; /* Apply Kermit-to-host mask now. */ /* Send the character that the user typed. */ ttoc(dopar(c)); if (duplex) { /* Half duplex? */ if (debses) conol(dbchr(csave)); else conoc(csave); /* Buffer char to screen, too */ if (seslog) { /* And maybe log it too */ c2 = csave; if (sessft == 0 && csave == '\r') c2 = '\n'; logchar(c2); } } } } while (_auxis()) { /* While chars avail from comm line */ c = _auxin(); /* Get a character from comm line */ if (debses) { /* Output character to screen */ conol(dbchr(c)); /* debugging */ } else { /* or regular... */ c &= cmask; /* Do first masking */ if (sosi /* Handle SI/SO */ #ifndef NOCSETS || tcsl != tcsr #endif /* NOCSETS */ ) { if (c == SO) { /* Shift Out */ shift = 1; continue; } else if (c == SI) { /* Shift In */ shift = 0; continue; } if (shift) c |= 0200; } #ifndef NOCSETS /* Translate character sets */ if (sxi) c = (*sxi)(c); if (rxi) c = (*rxi)(c); #endif c &= cmdmsk; /* Apply command mask */ conoc(c); /* Buffer the character */ if (seslog) logchar(c); /* Take care of session log */ } } while (auxsize && _conos()) { /* Output aux chars to the screen */ c = *auxfls++; if (auxfls > auxend) auxfls = &auxbuf[0]; auxsize--; _conout(c); /* Put it on the screen. */ } if (consize && _auxos()) { /* Output keyboard chars to aux port */ c = *confls++; if (confls > conend) confls = &conbuf[0]; consize--; _auxout(c); } } conres(); /* Reset the console. */ if (quitnow) doexit(GOOD_EXIT, xitsta); /* Exit now if requested */ if (dohangup) { /* If hangup requested, do that */ tthang(); dohangup = 0; } if (!quiet) printf("[Back at Local System]"); printf("\n"); what = W_NOTHING; /* So console modes set right. */ #ifndef NOCSETS language = langsv; /* Restore language */ #endif /* NOCSETS */ #ifdef DYNAMIC if (lbuf) free(lbuf); /* Free allocated memory */ #endif /* DYNAMIC */ return(1); } /* H C O N N E -- Give help message for connect. */ hconne() { int c; static char *hlpmsg[] = {"\ \r\n C to return to the C-Kermit prompt, or:", "\r\n 0 (zero) to send a null", "\r\n B to send a BREAK", "\r\n U to hangup and return to the C-Kermit prompt", "\r\n Q to hangup and quit Kermit", "\r\n S for status", "\r\n ! to push to local shell", "\r\n \\ backslash escape:", "\r\n \\nnn decimal character code", "\r\n \\Onnn octal character code", "\r\n \\Xhh hexadecimal character code", "\r\n terminate with carriage return.", "\r\n ? for help", "\r\n escape character twice to send the escape character", "\r\n space-bar to resume the CONNECT command\r\n\r\n", "" }; conol("\r\nPress C to return to "); conol("the C-Kermit prompt"); conol(", or:"); conola(hlpmsg); /* Print the help message. */ conol("Command>"); /* Prompt for command. */ c = _necin() & 0177; /* Get character, strip any parity. */ /* No key mapping or translation here */ if (c != CMDQ) conoll(""); return(c); /* Return it. */ } /* D O E S C -- Process an escape character argument */ VOID #ifdef CK_ANSIC doesc(char c) #else doesc(c) char c; #endif /* CK_ANSIC */ /* doesc */ { CHAR d; while (1) { if (c == escape) { /* Send escape character */ d = dopar(c); ttoc(d); return; } else /* Or else look it up below. */ if (isupper(c)) c = tolower(c); switch(c) { case 'c': /* Close connection */ case '\03': active = 0; conol("\r\n"); return; case 'b': /* Send a BREAK signal */ case '\02': ttsndb(); return; case 'u': /* Hangup */ case '\010': dohangup = 1; active = 0; conol("\r\nHanging up "); return; case 'q': quitnow = 1; active = 0; conol("\r\n"); return; case 's': /* Status */ conol("\r\nConnected thru "); conol(ttname); if (speed >= 0L) { sprintf(temp,", speed %ld",speed); conol(temp); } sprintf(temp,", %d terminal bits",(cmask == 0177) ? 7 : 8); conol(temp); if (parity) { conol(", "); switch (parity) { case 'e': conol("even"); break; case 'o': conol("odd"); break; case 's': conol("space"); break; case 'm': conol("mark"); break; } conol(" parity"); } if (seslog) { conol(", logging to "); conol(sesfil); } conoll(""); return; case 'h': /* Help */ case '?': /* Help */ c = hconne(); continue; case '0': /* Send a null */ c = '\0'; d = dopar(c); ttoc(d); return; case '@': /* Start inferior command processor */ case '!': conres(); /* Put console back to normal */ zshcmd(""); /* Fork a shell. */ if (conbin(escape) < 0) { printf("Error resuming CONNECT session\n"); active = 0; } return; case SP: /* Space, ignore */ return; default: /* Other */ if (c == CMDQ) { /* Backslash escape */ int x; kbp = kbuf; *kbp++ = c; while (((c = (_necin() & cmdmsk)) != '\r') && (c != '\n')) *kbp++ = c; *kbp = NUL; kbp = kbuf; x = xxesc(&kbp); /* Interpret it */ if (x >= 0) { /* No key mapping here */ c = dopar(x); ttoc(c); return; } else { /* Invalid backslash code. */ conoc(BEL); return; } } conoc(BEL); return; /* Invalid esc arg, beep */ } } } VOID #ifdef CK_ANSIC logchar(char c) #else logchar(c) char c; #endif /* CK_ANSIC */ /* logchar */ { /* Log character c to session log */ if (seslog) if ((sessft != 0) || (c != '\r' && c != '\0' && c != XON && c != XOFF)) if (zchout(ZSFILE,c) < 0) { conoll(""); conoll("ERROR WRITING SESSION LOG, LOG CLOSED!"); seslog = 0; } }