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 3.3 (Berkeley) 06/29/88"; 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 Host[ACK_SEQUENCE-1] |= ATTR_MDT; 477 if (putascii(ACK_SEQUENCE, a_ack_sequence, ACK_SEQUENCE_LENGTH, 1) == -1) { 478 return -1; 479 } 480 return 0; 481 } 482 483 static int 484 formatted_correct() 485 { 486 if ((find_input_area(SEND_SEQUENCE-1) != SEND_SEQUENCE) || 487 (find_input_area(SEND_SEQUENCE) != ACK_SEQUENCE) || 488 (find_input_area(ACK_SEQUENCE) != CHECKSUM) || 489 (find_input_area(CHECKSUM) != DATA)) { 490 return -1; 491 } else { 492 return 0; 493 } 494 } 495 496 497 main(argc, argv) 498 int argc; 499 char *argv[]; 500 { 501 register int i; 502 int data_length, input_length; 503 char ascii[8]; /* Lots of room */ 504 FILE *outfile; 505 char *data; 506 char *argv0 = argv[0]; 507 508 argc--; 509 argv++; 510 /* Process any flags */ 511 while (argc && (argv[0][0] == '-')) { 512 switch (argv[0][1]) { 513 case 'v': 514 verbose = 1; 515 break; 516 case 'b': 517 blocks = 1; 518 break; 519 } 520 argc--; 521 argv++; 522 } 523 524 if ((argc) < 2) { 525 fprintf(stderr, 526 "usage: %s [-b] [-v] local.file remote.file [remote.options]\n", 527 argv0); 528 exit(1); 529 } 530 531 /* Open the local file */ 532 if ((outfile = fopen(argv[0], "w")) == NULL) { 533 perror("fopen"); 534 exit(2); 535 } 536 argc--; 537 argv++; 538 539 if (initialize() == -1) { 540 return -1; 541 } 542 543 /* build the command line */ 544 data = data_array; 545 strcpy(data, "TNCOMP SEND"); 546 data += strlen(data); 547 while (argc--) { 548 *data++ = ' '; 549 strcpy(data, argv[0]); 550 data += strlen(argv[0]); 551 argv++; 552 } 553 if (verbose) { 554 printf("%s\n", data_array); 555 } 556 if (get_screen() == -1) { 557 return -1; 558 } 559 data_length = strlen(data_array); 560 if ((i = find_input_area(0)) == -1) { /* Get an input area */ 561 if (send_key(clear_index) == -1) { 562 return -1; 563 } 564 if ((i = find_input_area(0)) == -1) { /* Try again */ 565 fprintf(stderr, "Unable to enter command line.\n"); 566 return -1; 567 } 568 } 569 if (i == 0) { 570 Host[ScreenSize-1] |= ATTR_MDT; 571 } else { 572 Host[i-1] |= ATTR_MDT; 573 } 574 if (putascii(i, data_array, data_length, 1) == -1) { 575 return -1; 576 } 577 if (send_key(enter_index) == -1) { 578 return -1; 579 } 580 do { 581 if (get_screen() == -1) { 582 return -1; 583 } 584 } while (formatted_correct() == -1); 585 586 do { 587 if (get_screen() == -1) { 588 return -1; 589 } 590 /* For each screen */ 591 if (formatted_correct() == -1) { 592 fprintf(stderr, "Bad screen written by host.\n"); 593 return -1; 594 } 595 /* If MDT isn't reset in the sequence number, go around again */ 596 if (Host[ACK_SEQUENCE-1]&ATTR_MDT) { 597 if (wait_for_ps_or_oia() == -1) { 598 return -1; 599 } 600 continue; 601 } 602 getascii(SEND_SEQUENCE, a_send_sequence, SEND_SEQUENCE_LENGTH); 603 send_sequence = atoi(a_send_sequence); 604 getascii(CHECKSUM, a_checksum, CHECKSUM_LENGTH); 605 checksum = atoi(a_checksum); 606 getascii(DATA, data_array, DATA_LENGTH); 607 data = data_array; 608 if (send_sequence != (ack_sequence+1)) { 609 if (ack() == -1) { 610 return -1; 611 } 612 data = "1234"; /* Keep loop from failing */ 613 if (send_key(enter_index) == -1) { 614 return -1; 615 } 616 if (get_screen() == -1) { 617 return -1; 618 } 619 continue; 620 } 621 622 data_length = DATA_LENGTH; 623 while (data_length && memcmp(data, " EOF", 4) 624 && memcmp(data, " ", 4)) { 625 memcpy(ascii, data, 4); 626 data += 4; 627 data_length -= 4; 628 ascii[4] = 0; 629 input_length = atoi(ascii); 630 /* CMS can't live with zero length records */ 631 if ((input_length > 1) || 632 ((input_length == 1) && (data[0] != ' '))) { 633 if (fwrite(data, sizeof (char), 634 input_length, outfile) == 0) { 635 perror("fwrite"); 636 exit(9); 637 } 638 } 639 fprintf(outfile, "\n"); 640 data += input_length; 641 data_length -= input_length; 642 } 643 644 ack_sequence = send_sequence; 645 if (blocks) { 646 printf("#"); 647 fflush(stdout); 648 } 649 if (ack() == -1) { 650 return -1; 651 } 652 if (send_key(enter_index) == -1) { 653 return -1; 654 } 655 } while (memcmp(data, " EOF", 4)); 656 657 if (blocks) { 658 printf("\n"); 659 } 660 if (terminate() == -1) { 661 return -1; 662 } 663 return 0; 664 } 665