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