Commit | Line | Data |
---|---|---|
ee2abe03 C |
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 | \f | |
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 | \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 | ||
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 | \f | |
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 | } |