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