char *connv = "OS-9 Connect Command, 5A(06) 9 Oct 92"; /* C K 9 C O N -- Dumb terminal connection to remote system, for osk */ /* Modified from ckucon.c by Bob Larson (blarson@ecla.usc.edu) Edition: 5A(01) by Chris Hemsing ,Aachen, W Germany (chris@lfm.rwth-aachen.de): More efficient using sigmask, added character set translation Edition: 5A(02) 07/25/91 Chris Hemsing minor bug fixes, changes for gnu (ansi) C flow control on both sides Edition: 5A(03) 03/04/92 Chris Hemsing Kanji bug fix Edition: 5A(04) 08/20/92 Chris Hemsing flow control bug fix on return from local shell Edition: 5A(05) 10/01/92 Chris Hemsing added sending xon via escape character Edition: 5A(06) 10/09/92 Chris Hemsing escape back to local even on receive burst Author: Frank da Cruz (fdc@columbia.edu, FDCCU@CUVMA.BITNET), Columbia University Center for Computing Activities, 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. */ #include "ckcdeb.h" #include "ckcker.h" #include "ckcasc.h" #ifndef NOCSETS #include "ckcxla.h" /* Character set translation */ #endif /* NOCSETS */ #include /* Set/Get tty modes */ extern int local, speed, escape, duplex, parity, flow, seslog, mdmtyp; extern int errno, cmask, fmask, sosi, cmdmsk; extern char ttname[], sesfil[]; extern struct csinfo fcsinfo[]; static int active; /* Variables global to this module */ static char *chstr(); #define LBUFL 200 /* Line buffer */ CHAR lbuf[LBUFL]; /* C O N E C T -- Perform terminal connection */ #ifndef NOCSETS extern CHAR (*xls[MAXTCSETS+1][MAXFCSETS+1])(); /* Character set xlate */ extern CHAR (*xlr[MAXTCSETS+1][MAXFCSETS+1])(); /* functions. */ extern int language; /* Current language. */ extern struct langinfo langs[]; /* Language info. */ extern int tcsr, tcsl; /* Terminal character sets, remote & local.*/ static int langsv; /* Remember language */ static int tcs; /* Intermediate (xfer) char set */ 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 /* NOCSETS */ int shift = 0; /* SO/SI shift state */ static struct sgbuf opt; /* sgtty info... */ conect() { register 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 */ register int i; register int csave; /* Another copy of c */ char errmsg[50], *erp; int n,we_have_data; extern int ttypn; VOID doesc(); if (!local) { printf("Sorry, you must 'set line' first\n"); return(-2); } if (speed < 0) { printf("Sorry, you must 'set speed' first\n"); return(-2); } if ((escape < 0) || (escape > 0177)) { printf("Your escape character is not ASCII - %d\n",escape); return(-2); } if (ttopen(ttname,&local,mdmtyp,0) < 0) { erp = errmsg; sprintf(erp,"Sorry, can't open %s",ttname); perror(errmsg); return(-2); } printf("Connecting thru %s, speed %d.\n",ttname,speed); printf("The escape character is %s (%d).\n",chstr(escape),escape); printf("Type the escape character followed by C to get back,\n"); printf("or followed by ? to see other options.\n"); if (seslog) printf("(Session logged to %s.)\n",sesfil); /* Condition console terminal and communication line */ if (conbin(escape) < 0) { printf("Sorry, can't condition console terminal\n"); return(-2); } if (flow==1) { /*if xon/xoff you should have it running on both*/ if (_gs_opt(0,&opt) <0) /* Structure for restoring */ { printf("Sorry, can't condition console terminal\n"); return(-2); } opt.sg_xon = 0x11; opt.sg_xoff = 0x13; _ss_opt(0,&opt); _ss_opt(1,&opt); /* set new modes . */ } if (ttvt(speed,flow) < 0) { conres(); printf("Sorry, Can't condition communication line\n"); return(-2); } #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 */ /* Set up character set translations */ 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 */ shift = 0; /* Initial shift state. */ /* Main loop. 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). */ active = 1; while (active) { sigmask(1); /* increment signal mask, signals must */ _ss_ssig(0, SIGARB); /* be masked between _ss_sig and sleep*/ _ss_ssig(ttypn, SIGARB); sleep(0); _ss_rel(0, SIGARB); _ss_rel(ttypn, SIGARB); we_have_data = 1; while(we_have_data) /* loop while data on keybord or remote port*/ { /* do check console to get characters through */ we_have_data = 0; /* even if communication line receives a burst*/ if(_gs_rdy(0)>0) { we_have_data = 1; c = coninc(0) & cmdmsk; /* Get character from keyboard */ csave = c; if ((c & 0177) == escape) { /* Look for escape char */ c = coninc(0) & 0177; /* Got esc, get its arg */ doesc(c); /* And process it */ if (active == 0) break; /* immediately leave we_have_data loop to avoid burst receive */ } 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 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. */ if (ttoc(dopar(c)) > -1) { if (duplex) { /* Half duplex? */ conoc(csave); /* Yes, also echo it. */ if (seslog) /* And maybe log it. */ if (zchout(ZSFILE,c) < 0) seslog = 0; } } else { perror("\r\lCan't send character"); active = 0; } } /* end if ((c & 0177) == escape) */ } /* end if(_gs_rdy(0)>0) */ if ((n = ttchk()) > 0) { /* Any more left in buffer? */ we_have_data = 1; if (n > LBUFL) n = LBUFL; /* Get them all at once. */ if ((n = ttxin(n,lbuf)) > 0) { if (sosi) /* only one character at a time */ { for (i = 0; i < n; i++) { c = lbuf[i] & cmask; if (c == SO) { shift = 1; continue; } else if (c == SI) { shift = 0; continue; } if (shift) c = (c | 0200); #ifndef NOCSETS /* Translate character sets */ if (sxi) c = (*sxi)(c); if (rxi) c = (*rxi)(c); #endif /* NOCSETS */ c &= cmdmsk; /* Apply command mask. */ conoc(c); /* Output to screen */ if (seslog) zchout(ZSFILE,c); /* Log */ } } else /* All at once */ { for (i = 0; i < n; i++) { c = lbuf[i] & cmask; #ifndef NOCSETS /* Translate character sets */ if (sxi) c = (*sxi)(c); if (rxi) c = (*rxi)(c); #endif /* NOCSETS */ lbuf[i] = c & cmdmsk; /* Replace in buffer. */ if (seslog) zchout(ZSFILE,c); /* Log */ } conxo(n,(char *)lbuf); /* Output whole buffer at once */ } /* end SI/SO or not */ } /* end successful read on comm line */ } /* end data on communications line */ } /* end while(we_have_data) */ } /* end while(active) */ conres(); /* Reset the console. */ printf("[Back at Local System]\n"); #ifndef NOCSETS language = langsv; /* Restore language */ #endif /* NOCSETS */ return(1); } /* H C O N N E -- Give help message for connect. */ hconne() { int c; static char *hlpmsg[] = {"\ \r\lC to close the connection, or:\r", " 0 (zero) to send a null\r", " B to send a BREAK\r", " H to hangup and close connection\r", " S for status\r", " X to send an XON\r", " ! to push to local shell\r", " ? for help\r", " escape character twice to send the escape character.\r\l\r\l\r", "" }; conola(hlpmsg); /* Print the help message. */ conol("Command>"); /* Prompt for command. */ c = coninc(0) & 0177; /* Get character, strip any parity. */ conoc(c); /* Echo it. */ conoll(""); return(c); /* Return it. */ } /* C H S T R -- Make a printable string out of a character */ static char * chstr(c) int c; { static char s[8]; if (c < SP) sprintf(s,"CTRL-%c",ctl(c)); else sprintf(s,"'%c'\n",c); return(s); } /* D O E S C -- Process an escape character argument */ VOID doesc(c) char c; { CHAR d; CHAR temp[50]; 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\l"); return; case 'b': /* Send a BREAK signal */ case '\02': if (ttsndb()<0) conol("\r\nCan't send break\r\l"); return; case 'h': /* Hangup */ case '\010': tthang(); active = 0; conol("\r\l"); return; case '!': conres(); zshcmd(""); if (conbin(escape) < 0) { printf("Error returning to remote session\n"); active = 0; } if (flow==1) { /*if xon/xoff you should have it running on both*/ if ((_ss_opt(0,&opt) < 0)||(_ss_opt(1,&opt) < 0)) { printf("Error returning to remote session\n"); active = 0; } } return; case 's': /* Status */ conol("\r\lConnected thru "); conol(ttname); if (speed >= 0) { sprintf((char *)temp,", speed %d",speed); conol((char *)temp); } sprintf((char *)temp,", %d bits",(cmask == 0177) ? 7 : 8); 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 '?': /* Help */ c = hconne(); continue; case 'x': /* send xon */ ttoc(dopar(XON)); return; case '0': /* Send a null */ c = '\0'; d = dopar(c); ttoc(d); return; case SP: /* Space, ignore */ return; default: /* Other */ conoc(BEL); return; /* Invalid esc arg, beep */ } } }