BSD 4_3 development
[unix-history] / usr / contrib / kermit / ckucon.c
CommitLineData
ee2abe03
C
1char *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
33extern int local, speed, escape, duplex, parity, flow, seslog, mdmtyp;
34extern int errno;
35extern char ttname[], sesfil[];
36extern CHAR dopar();
37
38int i, active; /* Variables global to this module */
39char *chstr();
40char temp[50];
41
42#define LBUFL 200 /* Line buffer */
43char lbuf[LBUFL];
44
45/* Connect state parent/child communication signal handlers */
46
47static jmp_buf env_con; /* Envir ptr for connect errors */
48
49static
50conn_int() { /* Modem read failure handler, */
51 longjmp(env_con,1); /* notifies parent process to stop */
52}
53\f
54/* C O N E C T -- Perform terminal connection */
55
56conect() {
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\f
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\f
163/* H C O N N E -- Give help message for connect. */
164
165hconne() {
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
189char *
190chstr(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\f
201/* D O E S C -- Process an escape character argument */
202
203doesc(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}