1 /* TN5250 - An implementation of the 5250 telnet protocol.
2 * Copyright (C) 1997-2008 Michael Madore
3 *
4 * This file is part of TN5250.
5 *
6 * TN5250 is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2.1, or (at your option)
9 * any later version.
10 *
11 * TN5250 is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this software; see the file COPYING. If not, write to
18 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
19 * Boston, MA 02111-1307 USA
20 *
21 */
22 #include "tn5250-private.h"
23
24 /* External declarations of initializers for each type of stream. */
25 extern int tn5250_telnet_stream_init (Tn5250Stream *This);
26 extern int tn3270_telnet_stream_init (Tn5250Stream *This);
27 #ifdef HAVE_LIBSSL
28 extern int tn5250_ssl_stream_init (Tn5250Stream *This);
29 #endif
30 #ifndef NDEBUG
31 extern int tn5250_debug_stream_init (Tn5250Stream *This);
32 #endif
33
34 /* This structure and the stream_types[] array defines what types of
35 * streams we can create. */
36 struct _Tn5250StreamType {
37 const char *prefix;
38 int (* init) (Tn5250Stream *This);
39 };
40
41 typedef struct _Tn5250StreamType Tn5250StreamType;
42
43 static const Tn5250StreamType stream_types[] = {
44 #ifndef NDEBUG
45 { "debug:", tn5250_debug_stream_init },
46 #endif
47 { "telnet:", tn5250_telnet_stream_init },
48 { "tn5250:", tn5250_telnet_stream_init },
49 #ifdef HAVE_LIBSSL
50 { "ssl:", tn5250_ssl_stream_init },
51 { "telnet-ssl:", tn5250_ssl_stream_init },
52 { "telnets:", tn5250_ssl_stream_init },
53 #endif
54 { NULL, NULL }
55 };
56
streamInit(Tn5250Stream * This,long timeout)57 static void streamInit(Tn5250Stream *This, long timeout)
58 {
59 This->options = 0;
60 This->status = 0;
61 This->config = NULL;
62 This->connect = NULL;
63 This->disconnect = NULL;
64 This->handle_receive = NULL;
65 This->send_packet = NULL;
66 This->destroy = NULL;
67 This->record_count = 0;
68 This->records = This->current_record = NULL;
69 This->sockfd = (SOCKET_TYPE) - 1;
70 This->msec_wait = timeout;
71 This->streamtype = TN5250_STREAM;
72 This->rcvbufpos = 0;
73 This->rcvbuflen = -1;
74 tn5250_buffer_init(&(This->sb_buf));
75 }
76
77 /****f* lib5250/tn5250_stream_open
78 * NAME
79 * tn5250_stream_open
80 * SYNOPSIS
81 * ret = tn5250_stream_open (to);
82 * INPUTS
83 * const char * to - `URL' of host to connect to.
84 * Tn5250Config * config - config to associate w/stream
85 * DESCRIPTION
86 * Opens a 5250 stream to the specified host. URL is of the format
87 * [protocol]:host:[port], where protocol is currently one of the following:
88 *
89 * telnet - connect using tn5250 protocol
90 * tn5250 - connect using tn5250 protocol
91 * debug - read recorded session from debug file
92 *
93 * This is maintained by a protocol -> function mapping. Each protocol has
94 * an associated function which is responsible for initializing the stream.
95 * Stream initialization sets up protocol specific functions to handle
96 * communication with the host system.
97 *
98 * The next protocol to add is SNA. This will allow the emulator to use
99 * APPC (LU 6.2) to establish a session with the AS/400.
100 *****/
tn5250_stream_open(const char * to,Tn5250Config * config)101 Tn5250Stream *tn5250_stream_open (const char *to, Tn5250Config *config)
102 {
103 Tn5250Stream *This = tn5250_new(Tn5250Stream, 1);
104 const Tn5250StreamType *iter;
105 const char *postfix;
106 int ret;
107
108 if (This != NULL) {
109
110 streamInit(This, 0);
111
112 if (config != NULL)
113 tn5250_stream_config(This, config);
114
115 /* Figure out the stream type. */
116 iter = stream_types;
117 while (iter->prefix != NULL) {
118 if (strlen (to) >= strlen(iter->prefix)
119 && !memcmp (iter->prefix, to, strlen (iter->prefix))) {
120 /* Found the stream type, initialize it. */
121 ret = (* (iter->init)) (This);
122 if (ret != 0) {
123 tn5250_stream_destroy (This);
124 return NULL;
125 }
126 break;
127 }
128 iter++;
129 }
130
131 /* If we haven't found a type, assume telnet. */
132 if (iter->prefix == NULL) {
133 ret = tn5250_telnet_stream_init (This);
134 if (ret != 0) {
135 tn5250_stream_destroy (This);
136 return NULL;
137 }
138 postfix = to;
139 } else
140 postfix = to + strlen (iter->prefix);
141
142 /* Connect */
143 ret = (* (This->connect)) (This, postfix);
144 if (ret == 0)
145 return This;
146
147 tn5250_stream_destroy (This);
148 }
149 return NULL;
150 }
151
152 /****f* lib5250/tn5250_stream_host
153 * NAME
154 * tn5250_stream_host
155 * SYNOPSIS
156 * ret = tn5250_stream_host (masterSock);
157 * INPUTS
158 * SOCKET_TYPE masterSock - Master socket
159 * DESCRIPTION
160 * DOCUMENT ME!!!
161 *****/
tn5250_stream_host(SOCKET_TYPE masterfd,long timeout,int streamtype)162 Tn5250Stream *tn5250_stream_host (SOCKET_TYPE masterfd, long timeout,
163 int streamtype)
164 {
165 Tn5250Stream *This = tn5250_new(Tn5250Stream, 1);
166 int ret;
167
168 if (This != NULL) {
169 streamInit(This, timeout);
170 if(streamtype == TN5250_STREAM)
171 {
172 /* Assume telnet stream type. */
173 ret = tn5250_telnet_stream_init (This);
174 }
175 else
176 {
177 ret = tn3270_telnet_stream_init (This);
178 }
179 if (ret != 0) {
180 tn5250_stream_destroy (This);
181 return NULL;
182 }
183 /* Accept */
184 printf("masterfd = %d\n", masterfd);
185 ret = (* (This->accept)) (This, masterfd);
186 if (ret == 0)
187 return This;
188
189 tn5250_stream_destroy (This);
190 }
191 return NULL;
192 }
193
194
195 /****f* lib5250/tn5250_stream_config
196 * NAME
197 * tn5250_stream_config
198 * SYNOPSIS
199 * tn5250_stream_config (This, config);
200 * INPUTS
201 * Tn5250Stream * This - Stream object.
202 * Tn5250Config * config - Configuration object.
203 * DESCRIPTION
204 * Associates a stream with a configuration object. The stream uses the
205 * configuration object at run time to determine how to operate.
206 *****/
tn5250_stream_config(Tn5250Stream * This,Tn5250Config * config)207 int tn5250_stream_config (Tn5250Stream *This, Tn5250Config *config)
208 {
209 /* Always reference before unreferencing, in case it's the same
210 * object. */
211 tn5250_config_ref (config);
212 if (This->config != NULL)
213 tn5250_config_unref (This->config);
214 This->config = config;
215 return 0;
216 }
217
218 /****f* lib5250/tn5250_stream_destroy
219 * NAME
220 * tn5250_stream_destroy
221 * SYNOPSIS
222 * tn5250_stream_destroy (This);
223 * INPUTS
224 * Tn5250Stream * This -
225 * DESCRIPTION
226 * DOCUMENT ME!!!
227 *****/
tn5250_stream_destroy(Tn5250Stream * This)228 void tn5250_stream_destroy(Tn5250Stream * This)
229 {
230 /* Call particular stream type's destroy handler. */
231 if (This->destroy)
232 (* (This->destroy)) (This);
233
234 /* Free the environment. */
235 if (This->config != NULL)
236 tn5250_config_unref (This->config);
237 tn5250_buffer_free(&(This->sb_buf));
238 tn5250_record_list_destroy(This->records);
239 free(This);
240 }
241
242 /****f* lib5250/tn5250_stream_get_record
243 * NAME
244 * tn5250_stream_get_record
245 * SYNOPSIS
246 * ret = tn5250_stream_get_record (This);
247 * INPUTS
248 * Tn5250Stream * This -
249 * DESCRIPTION
250 * DOCUMENT ME!!!
251 *****/
tn5250_stream_get_record(Tn5250Stream * This)252 Tn5250Record *tn5250_stream_get_record(Tn5250Stream * This)
253 {
254 Tn5250Record *record;
255 int offset;
256
257 record = This->records;
258 TN5250_ASSERT(This->record_count >= 1);
259 TN5250_ASSERT(record != NULL);
260
261 This->records = tn5250_record_list_remove(This->records, record);
262 This->record_count--;
263
264 if(This->streamtype == TN5250_STREAM)
265 {
266 TN5250_ASSERT(tn5250_record_length(record)>= 10);
267 offset = 6 + tn5250_record_data(record)[6];
268 }
269 else
270 {
271 offset = 0;
272 }
273
274 TN5250_LOG(("tn5250_stream_get_record: offset = %d\n", offset));
275 tn5250_record_set_cur_pos(record, offset);
276
277 return record;
278 }
279
280 /****f* lib5250/tn5250_stream_setenv
281 * NAME
282 * tn5250_stream_setenv
283 * SYNOPSIS
284 * tn5250_stream_setenv (This, name, value);
285 * INPUTS
286 * Tn5250Stream * This -
287 * const char * name -
288 * const char * value -
289 * DESCRIPTION
290 * Set an 'environment' string. This is made to look like setenv().
291 *****/
tn5250_stream_setenv(Tn5250Stream * This,const char * name,const char * value)292 void tn5250_stream_setenv(Tn5250Stream * This, const char *name, const char *value)
293 {
294 char *name_buf;
295 if (This->config == NULL) {
296 This->config = tn5250_config_new ();
297 TN5250_ASSERT (This->config != NULL);
298 }
299 name_buf = (char*)malloc (strlen (name) + 10);
300 strcpy (name_buf, "env.");
301 strcat (name_buf, name);
302 tn5250_config_set (This->config, name_buf, value);
303 free (name_buf);
304 }
305
306 /****f* lib5250/tn5250_stream_getenv
307 * NAME
308 * tn5250_stream_getenv
309 * SYNOPSIS
310 * ret = tn5250_stream_getenv (This, name);
311 * INPUTS
312 * Tn5250Stream * This -
313 * const char * name -
314 * DESCRIPTION
315 * Retrieve the value of a 5250 environment string.
316 *****/
tn5250_stream_getenv(Tn5250Stream * This,const char * name)317 const char *tn5250_stream_getenv(Tn5250Stream * This, const char *name)
318 {
319 char *name_buf;
320 const char *val;
321
322 if (This->config == NULL)
323 return NULL;
324
325 name_buf = (char*)malloc (strlen (name) + 10);
326 strcpy (name_buf, "env.");
327 strcat (name_buf, name);
328 val = tn5250_config_get (This->config, name_buf);
329 free (name_buf);
330 return val;
331 }
332
333 /****f* lib5250/tn5250_stream_unsetenv
334 * NAME
335 * tn5250_stream_unsetenv
336 * SYNOPSIS
337 * tn5250_stream_unsetenv (This, name);
338 * INPUTS
339 * Tn5250Stream * This -
340 * const char * name -
341 * DESCRIPTION
342 * Unset a 5250 environment string.
343 *****/
tn5250_stream_unsetenv(Tn5250Stream * This,const char * name)344 void tn5250_stream_unsetenv(Tn5250Stream * This, const char *name)
345 {
346 char *name_buf;
347 if (This->config == NULL)
348 return; /* Nothing to unset. */
349
350 name_buf = (char*)malloc (strlen (name) + 10);
351 strcpy (name_buf, "env.");
352 strcat (name_buf, name);
353 tn5250_config_unset (This->config, name_buf);
354 free (name_buf);
355 }
356
tn5250_stream_socket_handle(Tn5250Stream * This)357 int tn5250_stream_socket_handle (Tn5250Stream *This)
358 {
359 return (int) This->sockfd;
360 }
361
362 /* vi:set sts=3 sw=3: */
363