1 | /* |
---|
2 | * Copyright 1993, 1994, 1995 by Paul Mattes. |
---|
3 | * Permission to use, copy, modify, and distribute this software and its |
---|
4 | * documentation for any purpose and without fee is hereby granted, |
---|
5 | * provided that the above copyright notice appear in all copies and that |
---|
6 | * both that copyright notice and this permission notice appear in |
---|
7 | * supporting documentation. |
---|
8 | */ |
---|
9 | |
---|
10 | /* |
---|
11 | * trace_ds.c |
---|
12 | * 3270 data stream tracing. |
---|
13 | * |
---|
14 | */ |
---|
15 | |
---|
16 | #include "globals.h" |
---|
17 | #include <X11/StringDefs.h> |
---|
18 | #include <X11/Xaw/Dialog.h> |
---|
19 | #include <errno.h> |
---|
20 | #include <signal.h> |
---|
21 | #include <time.h> |
---|
22 | #if defined(__STDC__) |
---|
23 | #include <stdarg.h> |
---|
24 | #else |
---|
25 | #include <varargs.h> |
---|
26 | #endif |
---|
27 | #include <fcntl.h> |
---|
28 | #include "3270ds.h" |
---|
29 | #include "appres.h" |
---|
30 | #include "resources.h" |
---|
31 | #include "ctlr.h" |
---|
32 | |
---|
33 | #include "ctlrc.h" |
---|
34 | #include "menubarc.h" |
---|
35 | #include "popupsc.h" |
---|
36 | #include "printc.h" |
---|
37 | #include "savec.h" |
---|
38 | #include "tablesc.h" |
---|
39 | #include "telnetc.h" |
---|
40 | #include "trace_dsc.h" |
---|
41 | #include "utilc.h" |
---|
42 | |
---|
43 | /* Externals */ |
---|
44 | extern char *build; |
---|
45 | |
---|
46 | /* Statics */ |
---|
47 | static int dscnt = 0; |
---|
48 | static int tracewindow_pid = -1; |
---|
49 | |
---|
50 | /* Globals */ |
---|
51 | FILE *tracef = (FILE *) 0; |
---|
52 | struct timeval ds_ts; |
---|
53 | Boolean trace_skipping = False; |
---|
54 | |
---|
55 | char * |
---|
56 | unknown(value) |
---|
57 | unsigned char value; |
---|
58 | { |
---|
59 | static char buf[64]; |
---|
60 | |
---|
61 | (void) sprintf(buf, "unknown[0x%x]", value); |
---|
62 | return buf; |
---|
63 | } |
---|
64 | |
---|
65 | /* display a (row,col) */ |
---|
66 | char * |
---|
67 | rcba(baddr) |
---|
68 | int baddr; |
---|
69 | { |
---|
70 | static char buf[16]; |
---|
71 | |
---|
72 | (void) sprintf(buf, "(%d,%d)", baddr/COLS + 1, baddr%COLS + 1); |
---|
73 | return buf; |
---|
74 | } |
---|
75 | |
---|
76 | char * |
---|
77 | see_ebc(ch) |
---|
78 | unsigned char ch; |
---|
79 | { |
---|
80 | static char buf[8]; |
---|
81 | |
---|
82 | switch (ch) { |
---|
83 | case FCORDER_NULL: |
---|
84 | return "NULL"; |
---|
85 | case FCORDER_SUB: |
---|
86 | return "SUB"; |
---|
87 | case FCORDER_DUP: |
---|
88 | return "DUP"; |
---|
89 | case FCORDER_FM: |
---|
90 | return "FM"; |
---|
91 | case FCORDER_FF: |
---|
92 | return "FF"; |
---|
93 | case FCORDER_CR: |
---|
94 | return "CR"; |
---|
95 | case FCORDER_NL: |
---|
96 | return "NL"; |
---|
97 | case FCORDER_EM: |
---|
98 | return "EM"; |
---|
99 | case FCORDER_EO: |
---|
100 | return "EO"; |
---|
101 | } |
---|
102 | if (ebc2asc[ch]) |
---|
103 | (void) sprintf(buf, "%c", ebc2asc[ch]); |
---|
104 | else |
---|
105 | (void) sprintf(buf, "\\%o", ch); |
---|
106 | return buf; |
---|
107 | } |
---|
108 | |
---|
109 | char * |
---|
110 | see_aid(code) |
---|
111 | unsigned char code; |
---|
112 | { |
---|
113 | switch (code) { |
---|
114 | case AID_NO: |
---|
115 | return "NoAID"; |
---|
116 | case AID_ENTER: |
---|
117 | return "Enter"; |
---|
118 | case AID_PF1: |
---|
119 | return "PF1"; |
---|
120 | case AID_PF2: |
---|
121 | return "PF2"; |
---|
122 | case AID_PF3: |
---|
123 | return "PF3"; |
---|
124 | case AID_PF4: |
---|
125 | return "PF4"; |
---|
126 | case AID_PF5: |
---|
127 | return "PF5"; |
---|
128 | case AID_PF6: |
---|
129 | return "PF6"; |
---|
130 | case AID_PF7: |
---|
131 | return "PF7"; |
---|
132 | case AID_PF8: |
---|
133 | return "PF8"; |
---|
134 | case AID_PF9: |
---|
135 | return "PF9"; |
---|
136 | case AID_PF10: |
---|
137 | return "PF10"; |
---|
138 | case AID_PF11: |
---|
139 | return "PF11"; |
---|
140 | case AID_PF12: |
---|
141 | return "PF12"; |
---|
142 | case AID_PF13: |
---|
143 | return "PF13"; |
---|
144 | case AID_PF14: |
---|
145 | return "PF14"; |
---|
146 | case AID_PF15: |
---|
147 | return "PF15"; |
---|
148 | case AID_PF16: |
---|
149 | return "PF16"; |
---|
150 | case AID_PF17: |
---|
151 | return "PF17"; |
---|
152 | case AID_PF18: |
---|
153 | return "PF18"; |
---|
154 | case AID_PF19: |
---|
155 | return "PF19"; |
---|
156 | case AID_PF20: |
---|
157 | return "PF20"; |
---|
158 | case AID_PF21: |
---|
159 | return "PF21"; |
---|
160 | case AID_PF22: |
---|
161 | return "PF22"; |
---|
162 | case AID_PF23: |
---|
163 | return "PF23"; |
---|
164 | case AID_PF24: |
---|
165 | return "PF24"; |
---|
166 | case AID_OICR: |
---|
167 | return "OICR"; |
---|
168 | case AID_MSR_MHS: |
---|
169 | return "MSR_MHS"; |
---|
170 | case AID_SELECT: |
---|
171 | return "Select"; |
---|
172 | case AID_PA1: |
---|
173 | return "PA1"; |
---|
174 | case AID_PA2: |
---|
175 | return "PA2"; |
---|
176 | case AID_PA3: |
---|
177 | return "PA3"; |
---|
178 | case AID_CLEAR: |
---|
179 | return "Clear"; |
---|
180 | case AID_SYSREQ: |
---|
181 | return "SysReq"; |
---|
182 | case AID_QREPLY: |
---|
183 | return "QueryReplyAID"; |
---|
184 | default: |
---|
185 | return unknown(code); |
---|
186 | } |
---|
187 | } |
---|
188 | |
---|
189 | char * |
---|
190 | see_attr(fa) |
---|
191 | unsigned char fa; |
---|
192 | { |
---|
193 | static char buf[256]; |
---|
194 | char *paren = "("; |
---|
195 | |
---|
196 | buf[0] = '\0'; |
---|
197 | |
---|
198 | if (fa & 0x04) { |
---|
199 | (void) strcat(buf, paren); |
---|
200 | (void) strcat(buf, "protected"); |
---|
201 | paren = ","; |
---|
202 | if (fa & 0x08) { |
---|
203 | (void) strcat(buf, paren); |
---|
204 | (void) strcat(buf, "skip"); |
---|
205 | paren = ","; |
---|
206 | } |
---|
207 | } else if (fa & 0x08) { |
---|
208 | (void) strcat(buf, paren); |
---|
209 | (void) strcat(buf, "numeric"); |
---|
210 | paren = ","; |
---|
211 | } |
---|
212 | switch (fa & 0x03) { |
---|
213 | case 0: |
---|
214 | break; |
---|
215 | case 1: |
---|
216 | (void) strcat(buf, paren); |
---|
217 | (void) strcat(buf, "detectable"); |
---|
218 | paren = ","; |
---|
219 | break; |
---|
220 | case 2: |
---|
221 | (void) strcat(buf, paren); |
---|
222 | (void) strcat(buf, "intensified"); |
---|
223 | paren = ","; |
---|
224 | break; |
---|
225 | case 3: |
---|
226 | (void) strcat(buf, paren); |
---|
227 | (void) strcat(buf, "nondisplay"); |
---|
228 | paren = ","; |
---|
229 | break; |
---|
230 | } |
---|
231 | if (fa & 0x20) { |
---|
232 | (void) strcat(buf, paren); |
---|
233 | (void) strcat(buf, "modified"); |
---|
234 | paren = ","; |
---|
235 | } |
---|
236 | if (strcmp(paren, "(")) |
---|
237 | (void) strcat(buf, ")"); |
---|
238 | else |
---|
239 | (void) strcpy(buf, "(default)"); |
---|
240 | |
---|
241 | return buf; |
---|
242 | } |
---|
243 | |
---|
244 | static char * |
---|
245 | see_highlight(setting) |
---|
246 | unsigned char setting; |
---|
247 | { |
---|
248 | switch (setting) { |
---|
249 | case XAH_DEFAULT: |
---|
250 | return "default"; |
---|
251 | case XAH_NORMAL: |
---|
252 | return "normal"; |
---|
253 | case XAH_BLINK: |
---|
254 | return "blink"; |
---|
255 | case XAH_REVERSE: |
---|
256 | return "reverse"; |
---|
257 | case XAH_UNDERSCORE: |
---|
258 | return "underscore"; |
---|
259 | case XAH_INTENSIFY: |
---|
260 | return "intensify"; |
---|
261 | default: |
---|
262 | return unknown(setting); |
---|
263 | } |
---|
264 | } |
---|
265 | |
---|
266 | char * |
---|
267 | see_color(setting) |
---|
268 | unsigned char setting; |
---|
269 | { |
---|
270 | static char *color_name[] = { |
---|
271 | "neutralBlack", |
---|
272 | "blue", |
---|
273 | "red", |
---|
274 | "pink", |
---|
275 | "green", |
---|
276 | "turquoise", |
---|
277 | "yellow", |
---|
278 | "neutralWhite", |
---|
279 | "black", |
---|
280 | "deepBlue", |
---|
281 | "orange", |
---|
282 | "purple", |
---|
283 | "paleGreen", |
---|
284 | "paleTurquoise", |
---|
285 | "grey", |
---|
286 | "white" |
---|
287 | }; |
---|
288 | |
---|
289 | if (setting == XAC_DEFAULT) |
---|
290 | return "default"; |
---|
291 | else if (setting < 0xf0 || setting > 0xff) |
---|
292 | return unknown(setting); |
---|
293 | else |
---|
294 | return color_name[setting - 0xf0]; |
---|
295 | } |
---|
296 | |
---|
297 | static char * |
---|
298 | see_transparency(setting) |
---|
299 | unsigned char setting; |
---|
300 | { |
---|
301 | switch (setting) { |
---|
302 | case XAT_DEFAULT: |
---|
303 | return "default"; |
---|
304 | case XAT_OR: |
---|
305 | return "or"; |
---|
306 | case XAT_XOR: |
---|
307 | return "xor"; |
---|
308 | case XAT_OPAQUE: |
---|
309 | return "opaque"; |
---|
310 | default: |
---|
311 | return unknown(setting); |
---|
312 | } |
---|
313 | } |
---|
314 | |
---|
315 | static char * |
---|
316 | see_validation(setting) |
---|
317 | unsigned char setting; |
---|
318 | { |
---|
319 | static char buf[64]; |
---|
320 | char *paren = "("; |
---|
321 | |
---|
322 | (void) strcpy(buf, ""); |
---|
323 | if (setting & XAV_FILL) { |
---|
324 | (void) strcat(buf, paren); |
---|
325 | (void) strcat(buf, "fill"); |
---|
326 | paren = ","; |
---|
327 | } |
---|
328 | if (setting & XAV_ENTRY) { |
---|
329 | (void) strcat(buf, paren); |
---|
330 | (void) strcat(buf, "entry"); |
---|
331 | paren = ","; |
---|
332 | } |
---|
333 | if (setting & XAV_TRIGGER) { |
---|
334 | (void) strcat(buf, paren); |
---|
335 | (void) strcat(buf, "trigger"); |
---|
336 | paren = ","; |
---|
337 | } |
---|
338 | if (strcmp(paren, "(")) |
---|
339 | (void) strcat(buf, ")"); |
---|
340 | else |
---|
341 | (void) strcpy(buf, "(none)"); |
---|
342 | return buf; |
---|
343 | } |
---|
344 | |
---|
345 | static char * |
---|
346 | see_outline(setting) |
---|
347 | unsigned char setting; |
---|
348 | { |
---|
349 | static char buf[64]; |
---|
350 | char *paren = "("; |
---|
351 | |
---|
352 | (void) strcpy(buf, ""); |
---|
353 | if (setting & XAO_UNDERLINE) { |
---|
354 | (void) strcat(buf, paren); |
---|
355 | (void) strcat(buf, "underline"); |
---|
356 | paren = ","; |
---|
357 | } |
---|
358 | if (setting & XAO_RIGHT) { |
---|
359 | (void) strcat(buf, paren); |
---|
360 | (void) strcat(buf, "right"); |
---|
361 | paren = ","; |
---|
362 | } |
---|
363 | if (setting & XAO_OVERLINE) { |
---|
364 | (void) strcat(buf, paren); |
---|
365 | (void) strcat(buf, "overline"); |
---|
366 | paren = ","; |
---|
367 | } |
---|
368 | if (setting & XAO_LEFT) { |
---|
369 | (void) strcat(buf, paren); |
---|
370 | (void) strcat(buf, "left"); |
---|
371 | paren = ","; |
---|
372 | } |
---|
373 | if (strcmp(paren, "(")) |
---|
374 | (void) strcat(buf, ")"); |
---|
375 | else |
---|
376 | (void) strcpy(buf, "(none)"); |
---|
377 | return buf; |
---|
378 | } |
---|
379 | |
---|
380 | char * |
---|
381 | see_efa(efa, value) |
---|
382 | unsigned char efa; |
---|
383 | unsigned char value; |
---|
384 | { |
---|
385 | static char buf[64]; |
---|
386 | |
---|
387 | switch (efa) { |
---|
388 | case XA_ALL: |
---|
389 | (void) sprintf(buf, " all(%x)", value); |
---|
390 | break; |
---|
391 | case XA_3270: |
---|
392 | (void) sprintf(buf, " 3270%s", see_attr(value)); |
---|
393 | break; |
---|
394 | case XA_VALIDATION: |
---|
395 | (void) sprintf(buf, " validation%s", see_validation(value)); |
---|
396 | break; |
---|
397 | case XA_OUTLINING: |
---|
398 | (void) sprintf(buf, " outlining(%s)", see_outline(value)); |
---|
399 | break; |
---|
400 | case XA_HIGHLIGHTING: |
---|
401 | (void) sprintf(buf, " highlighting(%s)", see_highlight(value)); |
---|
402 | break; |
---|
403 | case XA_FOREGROUND: |
---|
404 | (void) sprintf(buf, " foreground(%s)", see_color(value)); |
---|
405 | break; |
---|
406 | case XA_CHARSET: |
---|
407 | (void) sprintf(buf, " charset(%x)", value); |
---|
408 | break; |
---|
409 | case XA_BACKGROUND: |
---|
410 | (void) sprintf(buf, " background(%s)", see_color(value)); |
---|
411 | break; |
---|
412 | case XA_TRANSPARENCY: |
---|
413 | (void) sprintf(buf, " transparency(%s)", see_transparency(value)); |
---|
414 | break; |
---|
415 | default: |
---|
416 | (void) sprintf(buf, " %s[0x%x]", unknown(efa), value); |
---|
417 | } |
---|
418 | return buf; |
---|
419 | } |
---|
420 | |
---|
421 | char * |
---|
422 | see_efa_only(efa) |
---|
423 | unsigned char efa; |
---|
424 | { |
---|
425 | switch (efa) { |
---|
426 | case XA_ALL: |
---|
427 | return "all"; |
---|
428 | case XA_3270: |
---|
429 | return "3270"; |
---|
430 | case XA_VALIDATION: |
---|
431 | return "validation"; |
---|
432 | case XA_OUTLINING: |
---|
433 | return "outlining"; |
---|
434 | case XA_HIGHLIGHTING: |
---|
435 | return "highlighting"; |
---|
436 | case XA_FOREGROUND: |
---|
437 | return "foreground"; |
---|
438 | case XA_CHARSET: |
---|
439 | return "charset"; |
---|
440 | case XA_BACKGROUND: |
---|
441 | return "background"; |
---|
442 | case XA_TRANSPARENCY: |
---|
443 | return "transparency"; |
---|
444 | default: |
---|
445 | return unknown(efa); |
---|
446 | } |
---|
447 | } |
---|
448 | |
---|
449 | char * |
---|
450 | see_qcode(id) |
---|
451 | unsigned char id; |
---|
452 | { |
---|
453 | static char buf[64]; |
---|
454 | |
---|
455 | switch (id) { |
---|
456 | case QR_CHARSETS: |
---|
457 | return "CharacterSets"; |
---|
458 | case QR_IMP_PART: |
---|
459 | return "ImplicitPartition"; |
---|
460 | case QR_SUMMARY: |
---|
461 | return "Summary"; |
---|
462 | case QR_USABLE_AREA: |
---|
463 | return "UsableArea"; |
---|
464 | case QR_COLOR: |
---|
465 | return "Color"; |
---|
466 | case QR_HIGHLIGHTING: |
---|
467 | return "Highlighting"; |
---|
468 | case QR_REPLY_MODES: |
---|
469 | return "ReplyModes"; |
---|
470 | case QR_ALPHA_PART: |
---|
471 | return "AlphanumericPartitions"; |
---|
472 | case QR_DDM: |
---|
473 | return "DistributedDataManagement"; |
---|
474 | default: |
---|
475 | (void) sprintf(buf, "unknown[0x%x]", id); |
---|
476 | return buf; |
---|
477 | } |
---|
478 | } |
---|
479 | |
---|
480 | /* Data Stream trace print, handles line wraps */ |
---|
481 | |
---|
482 | static char tdsbuf[4096]; |
---|
483 | #define TDS_LEN 75 |
---|
484 | |
---|
485 | static void |
---|
486 | trace_ds_s(s) |
---|
487 | char *s; |
---|
488 | { |
---|
489 | int len = strlen(s); |
---|
490 | Boolean nl = False; |
---|
491 | |
---|
492 | if (!toggled(DS_TRACE)) |
---|
493 | return; |
---|
494 | |
---|
495 | if (s && s[len-1] == '\n') { |
---|
496 | len--; |
---|
497 | nl = True; |
---|
498 | } |
---|
499 | while (dscnt + len >= 75) { |
---|
500 | int plen = 75-dscnt; |
---|
501 | |
---|
502 | (void) fprintf(tracef, "%.*s ...\n... ", plen, s); |
---|
503 | dscnt = 4; |
---|
504 | s += plen; |
---|
505 | len -= plen; |
---|
506 | } |
---|
507 | if (len) { |
---|
508 | (void) fprintf(tracef, "%.*s", len, s); |
---|
509 | dscnt += len; |
---|
510 | } |
---|
511 | if (nl) { |
---|
512 | (void) fprintf(tracef, "\n"); |
---|
513 | dscnt = 0; |
---|
514 | } |
---|
515 | } |
---|
516 | |
---|
517 | #if defined(__STDC__) |
---|
518 | void |
---|
519 | trace_ds(char *fmt, ...) |
---|
520 | #else |
---|
521 | void |
---|
522 | trace_ds(va_alist) |
---|
523 | va_dcl |
---|
524 | #endif |
---|
525 | { |
---|
526 | va_list args; |
---|
527 | |
---|
528 | #if defined(__STDC__) |
---|
529 | va_start(args, fmt); |
---|
530 | #else |
---|
531 | char *fmt; |
---|
532 | va_start(args); |
---|
533 | fmt = va_arg(args, char *); |
---|
534 | #endif |
---|
535 | /* print out remainder of message */ |
---|
536 | (void) vsprintf(tdsbuf, fmt, args); |
---|
537 | trace_ds_s(tdsbuf); |
---|
538 | va_end(args); |
---|
539 | } |
---|
540 | |
---|
541 | static Widget trace_shell = (Widget)NULL; |
---|
542 | static int trace_reason; |
---|
543 | |
---|
544 | /* Callback for "OK" button on trace popup */ |
---|
545 | /*ARGSUSED*/ |
---|
546 | static void |
---|
547 | tracefile_callback(w, client_data, call_data) |
---|
548 | Widget w; |
---|
549 | XtPointer client_data; |
---|
550 | XtPointer call_data; |
---|
551 | { |
---|
552 | char *tfn; |
---|
553 | char *tracecmd; |
---|
554 | char *full_cmd; |
---|
555 | long clock; |
---|
556 | extern char *command_string; |
---|
557 | extern int children; |
---|
558 | |
---|
559 | if (w) |
---|
560 | tfn = XawDialogGetValueString((Widget)client_data); |
---|
561 | else |
---|
562 | tfn = (char *)client_data; |
---|
563 | tfn = do_subst(tfn, True, True); |
---|
564 | if (strchr(tfn, '\'') || |
---|
565 | ((int)strlen(tfn) > 0 && tfn[strlen(tfn)-1] == '\\')) { |
---|
566 | popup_an_error("Illegal file name: %s\n", tfn); |
---|
567 | XtFree(tfn); |
---|
568 | return; |
---|
569 | } |
---|
570 | tracef = fopen(tfn, "a"); |
---|
571 | if (tracef == (FILE *)NULL) { |
---|
572 | popup_an_errno(errno, tfn); |
---|
573 | XtFree(tfn); |
---|
574 | return; |
---|
575 | } |
---|
576 | (void) SETLINEBUF(tracef); |
---|
577 | (void) fcntl(fileno(tracef), F_SETFD, 1); |
---|
578 | |
---|
579 | /* Display current status */ |
---|
580 | clock = time((long *)0); |
---|
581 | (void) fprintf(tracef, "Trace started %s", ctime(&clock)); |
---|
582 | (void) fprintf(tracef, " Version: %s\n", build); |
---|
583 | save_yourself(); |
---|
584 | (void) fprintf(tracef, " Command: %s\n", command_string); |
---|
585 | (void) fprintf(tracef, " Model %s", model_name); |
---|
586 | (void) fprintf(tracef, ", %s display", |
---|
587 | appres.mono ? "monochrome" : "color"); |
---|
588 | if (appres.extended) |
---|
589 | (void) fprintf(tracef, ", extended data stream"); |
---|
590 | if (!appres.mono) |
---|
591 | (void) fprintf(tracef, ", %scolor", |
---|
592 | appres.m3279 ? "full " : "pseudo-"); |
---|
593 | if (appres.charset) |
---|
594 | (void) fprintf(tracef, ", %s charset", appres.charset); |
---|
595 | if (appres.apl_mode) |
---|
596 | (void) fprintf(tracef, ", APL mode"); |
---|
597 | (void) fprintf(tracef, "\n"); |
---|
598 | if (CONNECTED) |
---|
599 | (void) fprintf(tracef, " Connected to %s, port %u\n", |
---|
600 | current_host, current_port); |
---|
601 | |
---|
602 | /* Start the monitor window */ |
---|
603 | tracecmd = get_resource(ResTraceCommand); |
---|
604 | if (!tracecmd || !strcmp(tracecmd, "none")) |
---|
605 | goto done; |
---|
606 | switch (tracewindow_pid = fork()) { |
---|
607 | case 0: /* child process */ |
---|
608 | full_cmd = xs_buffer("%s <'%s'", tracecmd, tfn); |
---|
609 | (void) execlp("xterm", "xterm", "-title", tfn, |
---|
610 | "-sb", "-e", "/bin/sh", "-c", full_cmd, CN); |
---|
611 | (void) perror("exec(xterm)"); |
---|
612 | _exit(1); |
---|
613 | default: /* parent */ |
---|
614 | ++children; |
---|
615 | break; |
---|
616 | case -1: /* error */ |
---|
617 | popup_an_errno(errno, "fork()"); |
---|
618 | break; |
---|
619 | } |
---|
620 | |
---|
621 | done: |
---|
622 | XtFree(tfn); |
---|
623 | |
---|
624 | /* We're really tracing, turn the flag on. */ |
---|
625 | appres.toggle[trace_reason].value = True; |
---|
626 | appres.toggle[trace_reason].changed = True; |
---|
627 | menubar_retoggle(&appres.toggle[trace_reason]); |
---|
628 | |
---|
629 | if (w) |
---|
630 | XtPopdown(trace_shell); |
---|
631 | |
---|
632 | /* Snap the current TELNET options. */ |
---|
633 | if (net_snap_options()) { |
---|
634 | (void) fprintf(tracef, " TELNET state:\n"); |
---|
635 | trace_netdata('<', obuf, obptr - obuf); |
---|
636 | } |
---|
637 | |
---|
638 | /* Dump the screen contents and modes into the trace file. */ |
---|
639 | if (CONNECTED && formatted) { |
---|
640 | (void) fprintf(tracef, " Screen contents:\n"); |
---|
641 | ctlr_snap_buffer(); |
---|
642 | space3270out(2); |
---|
643 | net_add_eor(obuf, obptr - obuf); |
---|
644 | obptr += 2; |
---|
645 | trace_netdata('<', obuf, obptr - obuf); |
---|
646 | } |
---|
647 | if (CONNECTED && ctlr_snap_modes()) { |
---|
648 | (void) fprintf(tracef, " 3270 modes:\n"); |
---|
649 | space3270out(2); |
---|
650 | net_add_eor(obuf, obptr - obuf); |
---|
651 | obptr += 2; |
---|
652 | trace_netdata('<', obuf, obptr - obuf); |
---|
653 | } |
---|
654 | |
---|
655 | (void) fprintf(tracef, " Data stream:\n"); |
---|
656 | } |
---|
657 | |
---|
658 | /* Open the trace file. */ |
---|
659 | static void |
---|
660 | tracefile_on(reason, tt) |
---|
661 | int reason; |
---|
662 | enum toggle_type tt; |
---|
663 | { |
---|
664 | char tracefile[256]; |
---|
665 | |
---|
666 | if (tracef) |
---|
667 | return; |
---|
668 | |
---|
669 | (void) sprintf(tracefile, "%s/x3trc.%d", appres.trace_dir, |
---|
670 | getpid()); |
---|
671 | trace_reason = reason; |
---|
672 | if (tt == TT_INITIAL) { |
---|
673 | tracefile_callback((Widget)NULL, tracefile, PN); |
---|
674 | return; |
---|
675 | } |
---|
676 | if (trace_shell == NULL) { |
---|
677 | trace_shell = create_form_popup("trace", |
---|
678 | tracefile_callback, (XtCallbackProc)NULL, True); |
---|
679 | XtVaSetValues(XtNameToWidget(trace_shell, "dialog"), |
---|
680 | XtNvalue, tracefile, |
---|
681 | NULL); |
---|
682 | } |
---|
683 | |
---|
684 | /* Turn the toggle _off_ until the popup succeeds. */ |
---|
685 | appres.toggle[reason].value = False; |
---|
686 | appres.toggle[reason].changed = True; |
---|
687 | |
---|
688 | popup_popup(trace_shell, XtGrabExclusive); |
---|
689 | } |
---|
690 | |
---|
691 | /* Close the trace file. */ |
---|
692 | static void |
---|
693 | tracefile_off() |
---|
694 | { |
---|
695 | long clock; |
---|
696 | |
---|
697 | clock = time((long *)0); |
---|
698 | (void) fprintf(tracef, "Trace stopped %s", ctime(&clock)); |
---|
699 | if (tracewindow_pid != -1) |
---|
700 | (void) kill(tracewindow_pid, SIGTERM); |
---|
701 | tracewindow_pid = -1; |
---|
702 | (void) fclose(tracef); |
---|
703 | tracef = (FILE *) NULL; |
---|
704 | } |
---|
705 | |
---|
706 | /*ARGSUSED*/ |
---|
707 | void |
---|
708 | toggle_dsTrace(t, tt) |
---|
709 | struct toggle *t; |
---|
710 | enum toggle_type tt; |
---|
711 | { |
---|
712 | /* If turning on trace and no trace file, open one. */ |
---|
713 | if (toggled(DS_TRACE) && !tracef) |
---|
714 | tracefile_on(DS_TRACE, tt); |
---|
715 | |
---|
716 | /* If turning off trace and not still tracing events, close the |
---|
717 | trace file. */ |
---|
718 | else if (!toggled(DS_TRACE) && !toggled(EVENT_TRACE)) |
---|
719 | tracefile_off(); |
---|
720 | |
---|
721 | if (toggled(DS_TRACE)) |
---|
722 | (void) gettimeofday(&ds_ts, (struct timezone *)NULL); |
---|
723 | } |
---|
724 | |
---|
725 | /*ARGSUSED*/ |
---|
726 | void |
---|
727 | toggle_eventTrace(t, tt) |
---|
728 | struct toggle *t; |
---|
729 | enum toggle_type tt; |
---|
730 | { |
---|
731 | /* If turning on event debug, and no trace file, open one. */ |
---|
732 | if (toggled(EVENT_TRACE) && !tracef) |
---|
733 | tracefile_on(EVENT_TRACE, tt); |
---|
734 | |
---|
735 | /* If turning off event debug, and not tracing the data stream, |
---|
736 | close the trace file. */ |
---|
737 | else if (!toggled(EVENT_TRACE) && !toggled(DS_TRACE)) |
---|
738 | tracefile_off(); |
---|
739 | } |
---|
740 | |
---|
741 | /* Screen trace file support. */ |
---|
742 | |
---|
743 | static Widget screentrace_shell = (Widget)NULL; |
---|
744 | static FILE *screentracef = (FILE *)0; |
---|
745 | |
---|
746 | /* |
---|
747 | * Screen trace function, called when the host clears the screen. |
---|
748 | */ |
---|
749 | static void |
---|
750 | do_screentrace() |
---|
751 | { |
---|
752 | register int i; |
---|
753 | |
---|
754 | if (fprint_screen(screentracef, False)) { |
---|
755 | for (i = 0; i < COLS; i++) |
---|
756 | (void) fputc('=', screentracef); |
---|
757 | (void) fputc('\n', screentracef); |
---|
758 | } |
---|
759 | } |
---|
760 | |
---|
761 | void |
---|
762 | trace_screen() |
---|
763 | { |
---|
764 | trace_skipping = False; |
---|
765 | |
---|
766 | if (!toggled(SCREEN_TRACE) | !screentracef) |
---|
767 | return; |
---|
768 | do_screentrace(); |
---|
769 | } |
---|
770 | |
---|
771 | /* Called from ANSI emulation code to log a single character. */ |
---|
772 | void |
---|
773 | trace_char(c) |
---|
774 | char c; |
---|
775 | { |
---|
776 | if (!toggled(SCREEN_TRACE) | !screentracef) |
---|
777 | return; |
---|
778 | (void) fputc(c, screentracef); |
---|
779 | } |
---|
780 | |
---|
781 | /* |
---|
782 | * Called when disconnecting in ANSI mode, to finish off the trace file |
---|
783 | * and keep the next screen clear from re-recording the screen image. |
---|
784 | * (In a gross violation of data hiding and modularity, trace_skipping is |
---|
785 | * manipulated directly in ctlr_clear()). |
---|
786 | */ |
---|
787 | void |
---|
788 | trace_ansi_disc() |
---|
789 | { |
---|
790 | int i; |
---|
791 | |
---|
792 | (void) fputc('\n', screentracef); |
---|
793 | for (i = 0; i < COLS; i++) |
---|
794 | (void) fputc('=', screentracef); |
---|
795 | (void) fputc('\n', screentracef); |
---|
796 | |
---|
797 | trace_skipping = True; |
---|
798 | } |
---|
799 | |
---|
800 | /* Callback for "OK" button on screentrace popup */ |
---|
801 | /*ARGSUSED*/ |
---|
802 | static void |
---|
803 | screentrace_callback(w, client_data, call_data) |
---|
804 | Widget w; |
---|
805 | XtPointer client_data; |
---|
806 | XtPointer call_data; |
---|
807 | { |
---|
808 | char *tfn; |
---|
809 | |
---|
810 | if (w) |
---|
811 | tfn = XawDialogGetValueString((Widget)client_data); |
---|
812 | else |
---|
813 | tfn = (char *)client_data; |
---|
814 | tfn = do_subst(tfn, True, True); |
---|
815 | screentracef = fopen(tfn, "a"); |
---|
816 | if (screentracef == (FILE *)NULL) { |
---|
817 | popup_an_errno(errno, tfn); |
---|
818 | XtFree(tfn); |
---|
819 | return; |
---|
820 | } |
---|
821 | XtFree(tfn); |
---|
822 | (void) SETLINEBUF(screentracef); |
---|
823 | (void) fcntl(fileno(screentracef), F_SETFD, 1); |
---|
824 | |
---|
825 | /* We're really tracing, turn the flag on. */ |
---|
826 | appres.toggle[SCREEN_TRACE].value = True; |
---|
827 | appres.toggle[SCREEN_TRACE].changed = True; |
---|
828 | menubar_retoggle(&appres.toggle[SCREEN_TRACE]); |
---|
829 | |
---|
830 | if (w) |
---|
831 | XtPopdown(screentrace_shell); |
---|
832 | } |
---|
833 | |
---|
834 | /* Callback for second "OK" button on screentrace popup */ |
---|
835 | /*ARGSUSED*/ |
---|
836 | static void |
---|
837 | onescreen_callback(w, client_data, call_data) |
---|
838 | Widget w; |
---|
839 | XtPointer client_data; |
---|
840 | XtPointer call_data; |
---|
841 | { |
---|
842 | char *tfn; |
---|
843 | |
---|
844 | if (w) |
---|
845 | tfn = XawDialogGetValueString((Widget)client_data); |
---|
846 | else |
---|
847 | tfn = (char *)client_data; |
---|
848 | tfn = do_subst(tfn, True, True); |
---|
849 | screentracef = fopen(tfn, "a"); |
---|
850 | if (screentracef == (FILE *)NULL) { |
---|
851 | popup_an_errno(errno, tfn); |
---|
852 | XtFree(tfn); |
---|
853 | return; |
---|
854 | } |
---|
855 | (void) fcntl(fileno(screentracef), F_SETFD, 1); |
---|
856 | XtFree(tfn); |
---|
857 | |
---|
858 | /* Save the current image, once. */ |
---|
859 | do_screentrace(); |
---|
860 | |
---|
861 | /* Close the file, we're done. */ |
---|
862 | (void) fclose(screentracef); |
---|
863 | screentracef = (FILE *)NULL; |
---|
864 | |
---|
865 | if (w) |
---|
866 | XtPopdown(screentrace_shell); |
---|
867 | } |
---|
868 | |
---|
869 | /*ARGSUSED*/ |
---|
870 | void |
---|
871 | toggle_screenTrace(t, tt) |
---|
872 | struct toggle *t; |
---|
873 | enum toggle_type tt; |
---|
874 | { |
---|
875 | char tracefile[256]; |
---|
876 | |
---|
877 | if (toggled(SCREEN_TRACE)) { |
---|
878 | (void) sprintf(tracefile, "%s/x3scr.%d", appres.trace_dir, |
---|
879 | getpid()); |
---|
880 | if (tt == TT_INITIAL) { |
---|
881 | screentrace_callback((Widget)NULL, tracefile, PN); |
---|
882 | return; |
---|
883 | } |
---|
884 | if (screentrace_shell == NULL) { |
---|
885 | screentrace_shell = create_form_popup("screentrace", |
---|
886 | screentrace_callback, onescreen_callback, True); |
---|
887 | XtVaSetValues(XtNameToWidget(screentrace_shell, "dialog"), |
---|
888 | XtNvalue, tracefile, |
---|
889 | NULL); |
---|
890 | } |
---|
891 | appres.toggle[SCREEN_TRACE].value = False; |
---|
892 | appres.toggle[SCREEN_TRACE].changed = True; |
---|
893 | popup_popup(screentrace_shell, XtGrabExclusive); |
---|
894 | } else { |
---|
895 | if (ctlr_any_data() && !trace_skipping) |
---|
896 | do_screentrace(); |
---|
897 | (void) fclose(screentracef); |
---|
898 | } |
---|
899 | } |
---|