1: char *connv = "Connect Command for Unix, V4C(014) 29 Jul 85"; 2: 3: /* C K U C O N -- Dumb terminal connection to remote system, for Unix */ 4: /* 5: This module should work under all versions of Unix. It calls externally 6: defined system-dependent functions for i/o, but depends upon the existence 7: of the fork() function. 8: 9: Author: Frank da Cruz (SY.FDC@CU20B), 10: Columbia University Center for Computing Activities, January 1985. 11: Copyright (C) 1985, Trustees of Columbia University in the City of New York. 12: Permission is granted to any individual or institution to use, copy, or 13: redistribute this software so long as it is not sold for profit, provided this 14: copyright notice is retained. 15: 16: Enhanced by H. Fischer to detect when child process (modem reader) 17: reports that the communications line has been broken and hang up. 18: Also enhanced to allow escaping from connect state to command 19: interpreter, to allow sending/receiving without breaking connection. 20: */ 21: 22: #include <stdio.h> 23: #include <ctype.h> /* Character types */ 24: #include "ckcdeb.h" 25: #include "ckcker.h" 26: #include <signal.h> 27: #include <setjmp.h> 28: 29: #ifndef SIGUSR1 30: #define SIGUSR1 16 31: #endif 32: 33: extern int local, speed, escape, duplex, parity, flow, seslog, mdmtyp; 34: extern int errno; 35: extern char ttname[], sesfil[]; 36: extern CHAR dopar(); 37: 38: int i, active; /* Variables global to this module */ 39: char *chstr(); 40: char temp[50]; 41: 42: #define LBUFL 200 /* Line buffer */ 43: char lbuf[LBUFL]; 44: 45: /* Connect state parent/child communication signal handlers */ 46: 47: static jmp_buf env_con; /* Envir ptr for connect errors */ 48: 49: static 50: conn_int() { /* Modem read failure handler, */ 51: longjmp(env_con,1); /* notifies parent process to stop */ 52: } 53: 54: /* C O N E C T -- Perform terminal connection */ 55: 56: conect() { 57: int pid, /* process id of child (modem reader) */ 58: parent_id, /* process id of parent (keyboard reader) */ 59: n; 60: int c; /* c is a character, but must be signed 61: integer to pass thru -1, which is the 62: modem disconnection signal, and is 63: different from the character 0377 */ 64: char errmsg[50], *erp; 65: 66: if (!local) { 67: printf("Sorry, you must 'set line' first\n"); 68: return(-2); 69: } 70: if (speed < 0) { 71: printf("Sorry, you must 'set speed' first\n"); 72: return(-2); 73: } 74: if ((escape < 0) || (escape > 0177)) { 75: printf("Your escape character is not ASCII - %d\n",escape); 76: return(-2); 77: } 78: if (ttopen(ttname,&local,mdmtyp) < 0) { 79: erp = errmsg; 80: sprintf(erp,"Sorry, can't open %s",ttname); 81: perror(errmsg); 82: return(-2); 83: } 84: printf("Connecting thru %s, speed %d.\r\n",ttname,speed); 85: printf("The escape character is %s (%d).\r\n",chstr(escape),escape); 86: printf("Type the escape character followed by C to get back,\r\n"); 87: printf("or followed by ? to see other options.\r\n"); 88: if (seslog) printf("(Session logged to %s.)\r\n",sesfil); 89: 90: /* Condition console terminal and communication line */ 91: 92: if (conbin(escape) < 0) { 93: printf("Sorry, can't condition console terminal\n"); 94: return(-2); 95: } 96: if (ttvt(speed,flow) < 0) { 97: conres(); 98: printf("Sorry, Can't condition communication line\n"); 99: return(-2); 100: } 101: 102: /* cont'd... */ 103: 104: /* ...connect, cont'd */ 105: 106: 107: parent_id = getpid(); /* get parent id for signalling */ 108: pid = fork(); /* All ok, make a fork */ 109: if (pid) { 110: active = 1; /* This fork reads, sends keystrokes */ 111: if (!setjmp(env_con)) { /* comm error in child process */ 112: signal(SIGUSR1,conn_int); /* routine for child process exit */ 113: while (active) { 114: c = coninc(0) & 0177; /* Get character from keyboard */ 115: if (c == escape) { /* Look for escape char */ 116: c = coninc(0) & 0177; /* Got esc, get its arg */ 117: doesc(c); /* And process it */ 118: } else { /* Ordinary character */ 119: if (ttoc(dopar(c)) > -1) { 120: if (duplex) { /* Half duplex? */ 121: conoc(c); /* Yes, also echo it. */ 122: if (seslog) /* And maybe log it. */ 123: if (zchout(ZSFILE,c) < 0) seslog = 0; 124: } 125: } else { 126: perror("\r\nCan't send character"); 127: active = 0; 128: } 129: } 130: } 131: } /* Come here on death of child */ 132: kill(pid,9); /* Done, kill inferior fork. */ 133: wait(0); /* Wait till gone. */ 134: conres(); /* Reset the console. */ 135: printf("[Back at Local System]\n"); 136: return(0); 137: 138: } else { /* Inferior reads, prints port input */ 139: 140: while (1) { /* Fresh read, wait for a character */ 141: if ((c = ttinc(0)) < 0) { /* Comm line hangup detected */ 142: if (errno == 9999) /* this value set by ckutio.c myread */ 143: printf("\r\nCommunications disconnect "); 144: else perror("\r\nCan't get character"); 145: kill(parent_id,SIGUSR1); /* notify parent. */ 146: pause(); /* Wait to be killed by parent. */ 147: } 148: c &= 0177; /* Got a char, strip parity, etc */ 149: conoc(c); /* Put it on the screen. */ 150: if (seslog) zchout(ZSFILE,c); /* If logging, log it. */ 151: while ((n = ttchk()) > 0) { /* Any more left in buffer? */ 152: if (n > LBUFL) n = LBUFL; /* Get them all at once. */ 153: if ((n = ttxin(n,lbuf)) > 0) { 154: for (i = 0; i < n; i++) lbuf[i] &= 0177; /* Strip */ 155: conxo(n,lbuf); /* Output */ 156: if (seslog) zsoutx(ZSFILE,lbuf,n); /* Log */ 157: } 158: } 159: } 160: } 161: } 162: 163: /* H C O N N E -- Give help message for connect. */ 164: 165: hconne() { 166: int c; 167: static char *hlpmsg[] = {"\ 168: \r\nC to close the connection, or:", 169: "\r\n 0 (zero) to send a null", 170: "\r\n B to send a BREAK", 171: "\r\n H to hangup and close connection", 172: "\r\n S for status", 173: "\r\n ? for help", 174: "\r\n escape character twice to send the escape character.\r\n\r\n", 175: "" }; 176: 177: conola(hlpmsg); /* Print the help message. */ 178: conol("Command>"); /* Prompt for command. */ 179: c = coninc(0); 180: conoc(c); /* Echo it. */ 181: conoll(""); 182: c &= 0177; /* Strip any parity. */ 183: return(c); /* Return it. */ 184: } 185: 186: 187: /* C H S T R -- Make a printable string out of a character */ 188: 189: char * 190: chstr(c) int c; { 191: static char s[8]; 192: char *cp = s; 193: 194: if (c < SP) { 195: sprintf(cp,"CTRL-%c",ctl(c)); 196: } else sprintf(cp,"'%c'\n",c); 197: cp = s; 198: return(cp); 199: } 200: 201: /* D O E S C -- Process an escape character argument */ 202: 203: doesc(c) char c; { 204: CHAR d; 205: 206: c &= 0177; 207: while (1) { 208: if (c == escape) { /* Send escape character */ 209: d = dopar(c); ttoc(d); return; 210: } else /* Or else look it up below. */ 211: if (isupper(c)) c = tolower(c); 212: 213: switch (c) { 214: 215: case 'c': /* Close connection */ 216: case '\03': 217: active = 0; conol("\r\n"); return; 218: 219: case 'b': /* Send a BREAK signal */ 220: case '\02': 221: ttsndb(); return; 222: 223: case 'h': /* Hangup */ 224: case '\010': 225: tthang(); active = 0; conol("\r\n"); return; 226: 227: case 's': /* Status */ 228: case '\023': 229: conol("\r\nConnected thru "); 230: conol(ttname); 231: if (speed >= 0) { 232: sprintf(temp,", speed %d",speed); conol(temp); 233: } 234: if (parity) { 235: conol(", "); 236: switch (parity) { 237: case 'e': conol("even"); break; 238: case 'o': conol("odd"); break; 239: case 's': conol("space"); break; 240: case 'm': conol("mark"); break; 241: } 242: conol(" parity"); 243: } 244: if (seslog) { 245: conol(", logging to "); conol(sesfil); 246: } 247: conoll(""); return; 248: 249: case '?': /* Help */ 250: c = hconne(); continue; 251: 252: case '0': /* Send a null */ 253: c = '\0'; d = dopar(c); ttoc(d); return; 254: 255: case SP: /* Space, ignore */ 256: return; 257: 258: default: /* Other */ 259: conoc(BEL); return; /* Invalid esc arg, beep */ 260: } 261: } 262: }