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 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 * 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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