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