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