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