BSD 4_3_Tahoe release
[unix-history] / usr / src / ucb / tn3270 / utilities / tnrecv.c
CommitLineData
1913c751 1/*
0de390c0
KB
2 * Copyright (c) 1988 Regents of the University of California.
3 * All rights reserved.
1913c751 4 *
0de390c0 5 * Redistribution and use in source and binary forms are permitted
ca67e7b4
C
6 * provided that this notice is preserved and that due credit is given
7 * to the University of California at Berkeley. The name of the University
8 * may not be used to endorse or promote products derived from this
9 * software without specific prior written permission. This software
10 * is provided ``as is'' without express or implied warranty.
1913c751
GM
11 */
12
13#ifndef lint
0de390c0
KB
14char copyright[] =
15"@(#) Copyright (c) 1988 Regents of the University of California.\n\
16 All rights reserved.\n";
17#endif /* not lint */
18
19#ifndef lint
ca67e7b4 20static char sccsid[] = "@(#)tnrecv.c 3.2 (Berkeley) 3/28/88";
0de390c0 21#endif /* not lint */
1913c751 22
b6e18d58 23#include <stdio.h>
a0fc22ba 24
4718d085 25#include <api/apilib.h>
138011c0 26
b6e18d58
GM
27#include "tncomp.h"
28
29
4718d085 30#include "../ctlr/api.h"
b6e18d58
GM
31#include "../ctlr/function.h"
32#include "../ctlr/hostctlr.h"
33#include "../ctlr/oia.h"
34#include "../ctlr/screen.h"
35
4718d085
GM
36#include "../api/disp_asc.h"
37#include "../api/astosc.h"
b6e18d58
GM
38
39#include "../general/general.h"
40
41ScreenImage Host[MAXSCREENSIZE];
42
43static char
85659f3c
GM
44 a_send_sequence[SEND_SEQUENCE_LENGTH+1],
45 a_ack_sequence[ACK_SEQUENCE_LENGTH+1],
46 a_checksum[CHECKSUM_LENGTH+1],
47 data_array[DATA_LENGTH+1];
b6e18d58
GM
48
49static int
50 verbose,
85659f3c 51 blocks,
b6e18d58
GM
52 enter_index,
53 clear_index,
54 ScreenSize,
55 session_id;
56
57static unsigned int
58 send_sequence,
85659f3c 59 ack_sequence = -1,
b6e18d58
GM
60 checksum;
61
62api_perror(string)
63char *string;
64{
65 fprintf(stderr, "Error: [0x%x/0x%x:0x%x/0x%x] from %s.\n",
66 api_sup_fcn_id, api_sup_errno,
67 api_fcn_fcn_id, api_fcn_errno, string);
68}
69
70
71char *
72session_type(type)
73int type;
74{
75 switch (type) {
76 case TYPE_WSCTL:
77 return "work station control";
78 case TYPE_DFT:
79 return "distributed function terminal";
80 case TYPE_CUT:
81 return "control unit terminal";
82 case TYPE_NOTEPAD:
83 return "notepad";
84 case TYPE_PC:
85 return "personal computer";
86 default:
87 return "(UNKNOWN)";
88 }
89}
90
85659f3c
GM
91static int
92wait_for_ps_or_oia()
93{
94#if defined(unix)
95 return api_ps_or_oia_modified();
96#endif /* defined(unix) */
97}
98
99
b6e18d58
GM
100static int
101wait_for_unlock()
102{
103 OIA oia;
104 ReadOiaGroupParms re;
85659f3c 105 static char zeroes[sizeof oia.input_inhibited] = { 0 };
b6e18d58
GM
106
107 do {
108 re.rc = re.function_id = 0;
109 re.session_id = session_id;
110 re.oia_buffer = (char far *) &oia;
111 re.oia_group_number = API_OIA_ALL_GROUPS;
112 if (api_read_oia_group(&re) == -1) {
113 api_perror("api_read_oia_group");
114 return -1;
115 } else if (verbose) {
116 if (IsOiaReady3274(&oia)) {
117 printf("3274 ready, ");
118 }
119 if (IsOiaMyJob(&oia)) {
120 printf("my job, ");
121 }
122 if (IsOiaInsert(&oia)) {
123 printf("insert mode, ");
124 }
125 if (IsOiaSystemLocked(&oia)) {
126 printf("system locked, ");
127 }
128 if (IsOiaTWait(&oia)) {
129 printf("terminal wait, ");
130 }
131 printf("are some bits from the OIA.\n");
132 }
85659f3c
GM
133 /* We turned this on, so turn it off now */
134 ResetOiaApiInhibit(&oia);
135 if (memcmp(zeroes, oia.input_inhibited, sizeof oia.input_inhibited)) {
136 if (wait_for_ps_or_oia() == -1) {
137 return -1;
138 }
139 }
140 } while (memcmp(zeroes, oia.input_inhibited, sizeof oia.input_inhibited));
b6e18d58
GM
141 return 0;
142}
143
144static int
145initialize()
146{
147 QuerySessionIdParms id;
148 QuerySessionParametersParms pa;
149 QuerySessionCursorParms cu;
150 ConnectToKeyboardParms conn;
151 DisableInputParms disable;
152 NameArray namearray;
153
154 if (api_init() == 0) {
155 fprintf(stderr, "API function not available.\n");
156 return -1;
157 }
158
159 id.rc = 0;
160 id.function_id = 0;
161 id.option_code = ID_OPTION_BY_NAME;
162 id.data_code = 'E';
163 id.name_array = &namearray;
164 namearray.length = sizeof namearray;
165 if (api_query_session_id(&id)) {
166 api_perror("api_query_session_id");
167 } else if (namearray.number_matching_session == 0) {
168 fprintf(stderr, "query_session_id: No matching sessions!\n");
169 return -1;
170 } else if (verbose) {
171 printf("Session short name 0x%x, type is ",
172 namearray.name_array_element.short_name);
173 printf("%s", session_type(namearray.name_array_element.type));
174 printf(", session ID is: 0x%x\n",
175 namearray.name_array_element.session_id);
176 }
177 session_id = namearray.name_array_element.session_id;
178
179 pa.rc = pa.function_id = 0;
180 pa.session_id = session_id;
181 if (api_query_session_parameters(&pa) == -1) {
182 api_perror("api_query_session_parameters");
183 return -1;
184 } else if (verbose) {
185 printf("Session type %s, ", session_type(pa.session_type));
186 if (pa.session_characteristics&CHARACTERISTIC_EAB) {
187 printf(" has EAB, ");
188 }
189 if (pa.session_characteristics&CHARACTERISTIC_PSS) {
190 printf(" has PSS, ");
191 }
192 printf("%d rows, %d columns ", pa.rows, pa.columns);
193 if (pa.presentation_space) {
194 printf("presentation space at 0x%x:0x%x.\n",
195 FP_SEG(pa.presentation_space), FP_OFF(pa.presentation_space));
196 } else {
197 printf("(no direct presentation space access).\n");
198 }
199 }
200 ScreenSize = pa.rows*pa.columns;
201 if (pa.session_characteristics&CHARACTERISTIC_EAB) {
202 fprintf(stderr,
203 "tncomp utilities not designed to work with extended attribute buffers.\n");
204 return -1;
205 }
206
207 if (verbose) {
208 cu.rc = cu.function_id = 0;
209 cu.session_id = session_id;
210 if (api_query_session_cursor(&cu) == -1) {
211 api_perror("api_query_session_cursor");
212 } else {
213 printf("cursor");
214 if (cu.cursor_type&CURSOR_INHIBITED_AUTOSCROLL) {
215 printf(" inhibited autoscroll");
216 }
217 if (cu.cursor_type&CURSOR_INHIBITED) {
218 printf(" inhibited");
219 }
220 if (cu.cursor_type&CURSOR_BLINKING) {
221 printf(" blinking");
222 } else {
223 printf(" not blinking");
224 }
225 if (cu.cursor_type&CURSOR_BOX) {
226 printf(" box ");
227 } else {
228 printf(" not box ");
229 }
230 printf("at row %d, column %d.\n",
231 cu.row_address, cu.column_address);
232 }
233 }
234
235 conn.rc = conn.function_id = 0;
236 conn.session_id = session_id;
237 conn.event_queue_id = conn.input_queue_id = 0;
238 conn.intercept_options = 0;
239 if (api_connect_to_keyboard(&conn) == -1) {
240 api_perror("api_connect_to_keyboard");
241 } else if (verbose) {
242 if (conn.first_connection_identifier) {
243 printf("First keyboard connection.\n");
244 } else {
245 printf("Not first keyboard connection.\n");
246 }
247 }
248
249 disable.rc = disable.function_id = 0;
250 disable.session_id = session_id;
251 disable.connectors_task_id = 0;
252 if (api_disable_input(&disable) == -1) {
253 api_perror("api_disable_input");
254 return -1;
255 } else if (verbose) {
256 printf("Disabled.\n");
257 }
258
259 if ((enter_index = ascii_to_index("ENTER")) == -1) {
260 return -1;
261 }
262 if ((clear_index = ascii_to_index("CLEAR")) == -1) {
263 return -1;
264 }
265
266 return 0; /* all ok */
267}
268
269static int
270send_key(index)
271int index;
272{
273 WriteKeystrokeParms wr;
274 extern struct astosc astosc[];
275
276 wait_for_unlock();
277
278 wr.rc = wr.function_id = 0;
279 wr.session_id = session_id;
280 wr.connectors_task_id = 0;
281 wr.options = OPTION_SINGLE_KEYSTROKE;
282 wr.number_of_keys_sent = 0;
283 wr.keystroke_specifier.keystroke_entry.scancode = astosc[index].scancode;
284 wr.keystroke_specifier.keystroke_entry.shift_state
285 = astosc[index].shiftstate;
286 if (api_write_keystroke(&wr) == -1) {
287 api_perror("api_write_keystroke");
288 return -1;
289 } else if (wr.number_of_keys_sent != 1) {
290 fprintf(stderr, "write_keystroke claims to have sent %d keystrokes.\n",
291 wr.number_of_keys_sent);
292 return -1;
293 } else if (verbose) {
294 printf("Keystroke sent.\n");
295 }
85659f3c
GM
296 if (wait_for_ps_or_oia() == -1) {
297 return -1;
298 }
b6e18d58
GM
299 return 0;
300}
301
302static int
303terminate()
304{
305 EnableInputParms enable;
306 DisconnectFromKeyboardParms disc;
307
308 enable.rc = enable.function_id = 0;
309 enable.session_id = session_id;
310 enable.connectors_task_id = 0;
311 if (api_enable_input(&enable) == -1) {
312 api_perror("api_enable");
313 return -1;
314 } else if (verbose) {
315 printf("Enabled.\n");
316 }
317
318 disc.rc = disc.function_id = 0;
319 disc.session_id = session_id;
320 disc.connectors_task_id = 0;
321 if (api_disconnect_from_keyboard(&disc) == -1) {
322 api_perror("api_disconnect_from_keyboard");
323 return -1;
324 } else if (verbose) {
325 printf("Disconnected from keyboard.\n");
326 }
327
328 (void) api_finish();
329
330 return 0;
331}
332
333
334static int
335get_screen()
336{
337 CopyStringParms copy;
338 /* Time copy services */
339
340 wait_for_unlock();
341
342 copy.copy_mode = 0;
343 copy.rc = copy.function_id = 0;
344 copy.source.session_id = session_id;
345 copy.source.buffer = 0;
346 copy.source.characteristics = 0;
347 copy.source.session_type = TYPE_DFT;
348 copy.source.begin = 0;
349
350 copy.source_end = ScreenSize;
351
352 copy.target.session_id = 0;
353 copy.target.buffer = (char *) &Host[0];
354 copy.target.characteristics = 0;
355 copy.target.session_type = TYPE_DFT;
356
357 if (api_copy_string(&copy) == -1) {
358 api_perror("api_copy_string");
359 return -1;
360 }
361 return 0;
362}
85659f3c
GM
363
364
365put_at(offset, from, length, attribute)
b6e18d58
GM
366int offset;
367char *from;
368int length;
369{
370 CopyStringParms copy;
b6e18d58
GM
371
372 wait_for_unlock();
373
374 copy.copy_mode = 0;
375 copy.rc = copy.function_id = 0;
376 copy.source.session_id = 0;
377 copy.source.buffer = from;
378 copy.source.characteristics = 0;
379 copy.source.session_type = TYPE_DFT;
380 copy.source.begin = 0;
381
382 copy.source_end = length-1;
383
384 copy.target.session_id = session_id;
385 copy.target.buffer = 0;
386 copy.target.characteristics = 0;
387 copy.target.session_type = TYPE_DFT;
388 copy.target.begin = offset;
389
390 if (api_copy_string(&copy) == -1) {
391 api_perror("api_copy_string");
392 return -1;
393 }
394 return 0;
395}
396
397static void
398translate(input, output, table, length)
399char *input, *output, table[];
400int length;
401{
402 unsigned char *indices = (unsigned char *) input;
403
404 while (length--) {
405 *output++ = table[*indices++];
406 }
407}
408
409static int
85659f3c
GM
410find_input_area(from)
411int from;
a0fc22ba 412{
55417bd3 413#define FieldDec(p) (0) /* We don't really use this */
b6e18d58
GM
414 register int i, attr;
415
85659f3c 416 for (i = from; i < MAXSCREENSIZE; ) {
b6e18d58
GM
417 if (IsStartField(i)) {
418 attr = FieldAttributes(i);
419 i++;
420 if (!IsProtectedAttr(i, attr)) {
421 return i;
422 }
423 } else {
424 i++;
a0fc22ba
GM
425 }
426 }
b6e18d58
GM
427 return -1;
428}
429
430
431static void
432getascii(offset, to, length)
433int offset; /* Where in screen */
434char *to; /* Where it goes to */
435int length; /* Where to put it */
436{
437 translate(Host+offset, to, disp_asc, length);
a0fc22ba
GM
438}
439
b6e18d58 440static int
85659f3c 441putascii(offset, from, length, before)
b6e18d58
GM
442int offset; /* Where in screen */
443char *from; /* Where it comes from */
444int length; /* Where to put it */
85659f3c 445int before; /* How much else should go */
b6e18d58
GM
446{
447 translate(from, Host+offset, asc_disp, length);
85659f3c
GM
448 if (put_at(offset-before,
449 (char *) Host+offset-before, length+before) == -1) {
b6e18d58
GM
450 return -1;
451 }
452 return 0;
453}
a0fc22ba 454
b6e18d58
GM
455static int
456ack()
457{
85659f3c
GM
458 static char ack_blanks[sizeof a_ack_sequence] = {0};
459
460 if (ack_blanks[0] == 0) {
461 int i;
462
463 for (i = 0; i < sizeof ack_blanks; i++) {
464 ack_blanks[i] = ' ';
465 }
466 }
467
468 memcpy(a_ack_sequence, ack_blanks, sizeof a_ack_sequence);
b6e18d58
GM
469 sprintf(a_ack_sequence, "%d", ack_sequence);
470 a_ack_sequence[strlen(a_ack_sequence)] = ' ';
85659f3c
GM
471 Host[ACK_SEQUENCE-1] |= ATTR_MDT;
472 if (putascii(ACK_SEQUENCE, a_ack_sequence, ACK_SEQUENCE_LENGTH, 1) == -1) {
b6e18d58
GM
473 return -1;
474 }
475 return 0;
476}
85659f3c
GM
477
478static int
479formatted_correct()
480{
481 if ((find_input_area(SEND_SEQUENCE-1) != SEND_SEQUENCE) ||
482 (find_input_area(SEND_SEQUENCE) != ACK_SEQUENCE) ||
483 (find_input_area(ACK_SEQUENCE) != CHECKSUM) ||
484 (find_input_area(CHECKSUM) != DATA)) {
485 return -1;
486 } else {
487 return 0;
488 }
489}
490
491
a0fc22ba
GM
492main(argc, argv)
493int argc;
494char *argv[];
495{
b6e18d58 496 register int i;
a0fc22ba
GM
497 int data_length, input_length;
498 char ascii[8]; /* Lots of room */
a0fc22ba 499 FILE *outfile;
b6e18d58 500 char *data;
9039852a 501 char *argv0 = argv[0];
b6e18d58 502
d65ad751
GM
503 argc--;
504 argv++;
b6e18d58 505 /* Process any flags */
9039852a 506 while (argc && (argv[0][0] == '-')) {
d65ad751 507 switch (argv[0][1]) {
b6e18d58
GM
508 case 'v':
509 verbose = 1;
85659f3c
GM
510 break;
511 case 'b':
512 blocks = 1;
513 break;
b6e18d58 514 }
d65ad751
GM
515 argc--;
516 argv++;
b6e18d58 517 }
a0fc22ba 518
d65ad751 519 if ((argc) < 2) {
9039852a
GM
520 fprintf(stderr,
521 "usage: %s [-b] [-v] local.file remote.file [remote.options]\n",
522 argv0);
a0fc22ba
GM
523 exit(1);
524 }
525
526 /* Open the local file */
d65ad751 527 if ((outfile = fopen(argv[0], "w")) == NULL) {
a0fc22ba
GM
528 perror("fopen");
529 exit(2);
530 }
d65ad751
GM
531 argc--;
532 argv++;
b6e18d58
GM
533
534 if (initialize() == -1) {
535 return -1;
536 }
537
a0fc22ba
GM
538 /* build the command line */
539 data = data_array;
b6e18d58 540 strcpy(data, "TNCOMP SEND");
a0fc22ba 541 data += strlen(data);
d65ad751 542 while (argc--) {
a0fc22ba 543 *data++ = ' ';
d65ad751
GM
544 strcpy(data, argv[0]);
545 data += strlen(argv[0]);
546 argv++;
a0fc22ba 547 }
b6e18d58
GM
548 if (verbose) {
549 printf("%s\n", data_array);
550 }
551 if (get_screen() == -1) {
552 return -1;
553 }
554 data_length = strlen(data_array);
e8c5b85c 555 if ((i = find_input_area(0)) == -1) { /* Get an input area */
b6e18d58
GM
556 if (send_key(clear_index) == -1) {
557 return -1;
558 }
85659f3c 559 if ((i = find_input_area(0)) == -1) { /* Try again */
b6e18d58
GM
560 fprintf(stderr, "Unable to enter command line.\n");
561 return -1;
562 }
563 }
85659f3c
GM
564 if (i == 0) {
565 Host[ScreenSize-1] |= ATTR_MDT;
566 } else {
567 Host[i-1] |= ATTR_MDT;
568 }
569 if (putascii(i, data_array, data_length, 1) == -1) {
b6e18d58
GM
570 return -1;
571 }
572 if (send_key(enter_index) == -1) {
573 return -1;
574 }
575 do {
576 if (get_screen() == -1) {
577 return -1;
578 }
85659f3c 579 } while (formatted_correct() == -1);
a0fc22ba 580
b6e18d58 581 do {
85659f3c
GM
582 if (get_screen() == -1) {
583 return -1;
584 }
b6e18d58 585 /* For each screen */
85659f3c
GM
586 if (formatted_correct() == -1) {
587 fprintf(stderr, "Bad screen written by host.\n");
588 return -1;
589 }
590 /* If MDT isn't reset in the sequence number, go around again */
591 if (Host[ACK_SEQUENCE-1]&ATTR_MDT) {
592 if (wait_for_ps_or_oia() == -1) {
593 return -1;
594 }
595 continue;
596 }
597 getascii(SEND_SEQUENCE, a_send_sequence, SEND_SEQUENCE_LENGTH);
b6e18d58 598 send_sequence = atoi(a_send_sequence);
85659f3c 599 getascii(CHECKSUM, a_checksum, CHECKSUM_LENGTH);
b6e18d58 600 checksum = atoi(a_checksum);
85659f3c 601 getascii(DATA, data_array, DATA_LENGTH);
b6e18d58
GM
602 data = data_array;
603 if (send_sequence != (ack_sequence+1)) {
85659f3c
GM
604 if (ack() == -1) {
605 return -1;
606 }
b6e18d58
GM
607 data = "1234"; /* Keep loop from failing */
608 if (send_key(enter_index) == -1) {
609 return -1;
610 }
611 if (get_screen() == -1) {
612 return -1;
613 }
614 continue;
a0fc22ba 615 }
b6e18d58 616
85659f3c
GM
617 data_length = DATA_LENGTH;
618 while (data_length && memcmp(data, " EOF", 4)
619 && memcmp(data, " ", 4)) {
b6e18d58 620 memcpy(ascii, data, 4);
85659f3c
GM
621 data += 4;
622 data_length -= 4;
b6e18d58
GM
623 ascii[4] = 0;
624 input_length = atoi(ascii);
85659f3c
GM
625 /* CMS can't live with zero length records */
626 if ((input_length > 1) ||
627 ((input_length == 1) && (data[0] != ' '))) {
b6e18d58 628 if (fwrite(data, sizeof (char),
85659f3c 629 input_length, outfile) == 0) {
b6e18d58
GM
630 perror("fwrite");
631 exit(9);
632 }
a0fc22ba 633 }
b6e18d58
GM
634 fprintf(outfile, "\n");
635 data += input_length;
636 data_length -= input_length;
637 }
85659f3c
GM
638
639 ack_sequence = send_sequence;
640 if (blocks) {
641 printf("#");
642 fflush(stdout);
643 }
644 if (ack() == -1) {
b6e18d58 645 return -1;
a0fc22ba 646 }
85659f3c 647 if (send_key(enter_index) == -1) {
b6e18d58
GM
648 return -1;
649 }
85659f3c 650 } while (memcmp(data, " EOF", 4));
b6e18d58 651
85659f3c
GM
652 if (blocks) {
653 printf("\n");
654 }
b6e18d58
GM
655 if (terminate() == -1) {
656 return -1;
a0fc22ba 657 }
b6e18d58 658 return 0;
a0fc22ba 659}