/* Check for a trace file rollover event. */ void trace_rollover_check(void) { if (tracef == NULL || tracef_max == 0) return; /* See if we've reached a rollover point. */ if (tracef_size >= tracef_max) { char *alt_filename; char *new_header; #if defined(_WIN32) /*[*/ char *period; #endif /*]*/ /* Close up this file. */ wtrace("Trace rolled over\n"); fclose(tracef); tracef = NULL; /* Unlink and rename the alternate file. */ #if defined(_WIN32) /*[*/ period = strrchr(tracefile_name, '.'); if (period != CN) alt_filename = xs_buffer("%.*s-%s", period - tracefile_name, tracefile_name, period); else #endif /*]*/ alt_filename = xs_buffer("%s-", tracefile_name); (void) unlink(alt_filename); (void) rename(tracefile_name, alt_filename); Free(alt_filename); alt_filename = CN; tracef = fopen(tracefile_name, "w"); if (tracef == (FILE *)NULL) { popup_an_errno(errno, "%s", tracefile_name); return; } /* Initialize it. */ tracef_size = 0L; (void) SETLINEBUF(tracef); new_header = create_tracefile_header("rolled over"); do_ts = True; wtrace(new_header); Free(new_header); } }
int main(int, char**) #endif { try { ConsoleWindow console("Console", 160, 1000); ConsoleLogger logger; Server server; server.exec(); return 0; } catch (Exception e) { #ifdef WIN32 #ifdef UNICODE std::string trace = e.get_message_and_stack_trace(); std::wstring wtrace(trace.begin(), trace.end()); MessageBox(0, wtrace.c_str(), TEXT("Unhandled Exception"), MB_OK); #else MessageBox(0, e.get_message_and_stack_trace().c_str(), TEXT("Unhandled Exception"), MB_OK); #endif #else Console::write_line("Unhandled exception: %1", e.get_message_and_stack_trace()); #endif return 1; } }
/* Close the trace file. */ static void tracefile_off(void) { wtrace("Trace stopped\n"); #if !defined(_WIN32) /*[*/ if (tracewindow_pid != -1) (void) kill(tracewindow_pid, SIGKILL); tracewindow_pid = -1; #else /*][*/ if (tracewindow_handle != NULL) { TerminateProcess(tracewindow_handle, 0); CloseHandle(tracewindow_handle); tracewindow_handle = NULL; } #endif /*]*/ stop_tracing(); }
/* Callback for "OK" button on trace popup */ static void tracefile_callback(Widget w, XtPointer client_data, XtPointer call_data _is_unused) { char *tfn = CN; int devfd = -1; #if defined(X3270_DISPLAY) /*[*/ int pipefd[2]; Boolean just_piped = False; #endif /*]*/ char *buf; #if defined(X3270_DISPLAY) /*[*/ if (w) tfn = XawDialogGetValueString((Widget)client_data); else #endif /*]*/ tfn = (char *)client_data; tfn = do_subst(tfn, DS_VARS | DS_TILDE | DS_UNIQUE); if (strchr(tfn, '\'') || ((int)strlen(tfn) > 0 && tfn[strlen(tfn)-1] == '\\')) { popup_an_error("Illegal file name: %s", tfn); Free(tfn); goto done; } tracef_max = 0; if (!strcmp(tfn, "stdout")) { tracef = stdout; } else { #if defined(X3270_DISPLAY) /*[*/ FILE *pipefile = NULL; if (!strcmp(tfn, "none") || !tfn[0]) { just_piped = True; if (!appres.trace_monitor) { popup_an_error("Must specify a trace file " "name"); free(tfn); goto done; } } if (appres.trace_monitor) { if (pipe(pipefd) < 0) { popup_an_errno(errno, "pipe() failed"); Free(tfn); goto done; } pipefile = fdopen(pipefd[1], "w"); if (pipefile == NULL) { popup_an_errno(errno, "fdopen() failed"); (void) close(pipefd[0]); (void) close(pipefd[1]); Free(tfn); goto done; } (void) SETLINEBUF(pipefile); (void) fcntl(pipefd[1], F_SETFD, 1); } if (just_piped) { tracef = pipefile; } else #endif /*]*/ { Boolean append = False; #if defined(X3270_DISPLAY) /*[*/ tracef_pipe = pipefile; #endif /*]*/ /* Get the trace file maximum. */ get_tracef_max(); /* Open and configure the file. */ if ((devfd = get_devfd(tfn)) >= 0) tracef = fdopen(dup(devfd), "a"); else if (!strncmp(tfn, ">>", 2)) { append = True; tracef = fopen(tfn + 2, "a"); } else tracef = fopen(tfn, "w"); if (tracef == (FILE *)NULL) { popup_an_errno(errno, "%s", tfn); #if defined(X3270_DISPLAY) /*[*/ fclose(tracef_pipe); (void) close(pipefd[0]); (void) close(pipefd[1]); #endif /*]*/ Free(tfn); goto done; } tracef_size = ftello(tracef); Replace(tracefile_name, NewString(append? tfn + 2: tfn)); (void) SETLINEBUF(tracef); #if !defined(_WIN32) /*[*/ (void) fcntl(fileno(tracef), F_SETFD, 1); #endif /*]*/ } } #if defined(X3270_DISPLAY) /*[*/ /* Start the monitor window */ if (tracef != stdout && appres.trace_monitor) { switch (tracewindow_pid = fork_child()) { case 0: /* child process */ { char cmd[64]; (void) snprintf(cmd, sizeof(cmd), "cat <&%d", pipefd[0]); (void) execlp("xterm", "xterm", "-title", just_piped? "trace": tfn, "-sb", "-e", "/bin/sh", "-c", cmd, CN); } (void) perror("exec(xterm) failed"); _exit(1); default: /* parent */ (void) close(pipefd[0]); ++children; break; case -1: /* error */ popup_an_errno(errno, "fork() failed"); break; } } #endif /*]*/ #if defined(_WIN32) && defined(C3270) /*[*/ /* Start the monitor window. */ if (tracef != stdout && appres.trace_monitor && is_installed) { STARTUPINFO startupinfo; PROCESS_INFORMATION process_information; char *path; char *args; (void) memset(&startupinfo, '\0', sizeof(STARTUPINFO)); startupinfo.cb = sizeof(STARTUPINFO); startupinfo.lpTitle = tfn; (void) memset(&process_information, '\0', sizeof(PROCESS_INFORMATION)); path = xs_buffer("%scatf.exe", instdir); args = xs_buffer("\"%scatf.exe\" \"%s\"", instdir, tfn); if (CreateProcess( path, args, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &startupinfo, &process_information) == 0) { popup_an_error("CreateProcess(%s) failed: %s", path, win32_strerror(GetLastError())); Free(path); Free(args); } else { Free(path); Free(args); tracewindow_handle = process_information.hProcess; CloseHandle(process_information.hThread); } } #endif /*]*/ Free(tfn); /* We're really tracing, turn the flag on. */ appres.toggle[trace_reason].value = True; appres.toggle[trace_reason].changed = True; menubar_retoggle(&appres.toggle[trace_reason], trace_reason); /* Display current status. */ buf = create_tracefile_header("started"); do_ts = False; wtrace("%s", buf); Free(buf); done: #if defined(X3270_DISPLAY) /*[*/ if (w) XtPopdown(trace_shell); #endif /*]*/ return; }
/* Create a trace file header. */ static char * create_tracefile_header(const char *mode) { char *buf; /* Create a buffer and redirect output. */ buf = Malloc(MAX_HEADER_SIZE); tracef_bufptr = buf; /* Display current status */ wtrace("Trace %s\n", mode); wtrace(" Version: %s\n", build); wtrace(" %s\n", build_options()); save_yourself(); wtrace(" Command: %s\n", command_string); wtrace(" Model %s, %d rows x %d cols", model_name, maxROWS, maxCOLS); #if defined(X3270_INTERACTIVE) && !defined(_WIN32) /*[*/ wtrace(", %s display", appres.mono ? "monochrome" : "color"); #endif /*]*/ if (appres.extended) wtrace(", extended data stream"); wtrace(", %s emulation", appres.m3279 ? "color" : "monochrome"); wtrace(", %s charset", get_charset_name()); if (appres.apl_mode) wtrace(", APL mode"); wtrace("\n"); #if !defined(_WIN32) /*[*/ wtrace(" Locale codeset: %s\n", locale_codeset); #else /*][*/ wtrace(" ANSI codepage: %d\n", GetACP()); # if defined(_WIN32) /*[*/ wtrace(" Local codepage: %d\n", appres.local_cp); # endif /*]*/ #endif /*]*/ wtrace(" Host codepage: %d", (int)(cgcsgid & 0xffff)); #if defined(X3270_DBCS) /*[*/ if (dbcs) wtrace("+%d", (int)(cgcsgid_dbcs & 0xffff)); #endif /*]*/ wtrace("\n"); #if defined(_WIN32) && (defined(C3270) || defined(S3270)) /*[*/ wtrace(" AppData: %s\n", myappdata? myappdata: "(null)"); wtrace(" Install dir: %s\n", instdir? instdir: "(null)"); wtrace(" Desktop: %s\n", mydesktop? mydesktop: "(null)"); #endif /*]*/ if (CONNECTED) wtrace(" Connected to %s, port %u\n", current_host, current_port); /* Snap the current TELNET options. */ if (net_snap_options()) { wtrace(" TELNET state:\n"); trace_netdata('<', obuf, obptr - obuf); } /* Dump the screen contents and modes into the trace file. */ if (CONNECTED) { /* * Note that if the screen is not formatted, we do not * attempt to save what's on it. However, if we're in * 3270 SSCP-LU or NVT mode, we'll do a dummy, empty * write to ensure that the display is in the right * mode. */ if (IN_3270) { wtrace(" Screen contents (%s3270) %sformatted:\n", IN_E? "TN3270E-": "", formatted? "": "un"); obptr = obuf; #if defined(X3270_TN3270E) /*[*/ (void) net_add_dummy_tn3270e(); #endif /*]*/ ctlr_snap_buffer(); space3270out(2); net_add_eor(obuf, obptr - obuf); obptr += 2; trace_netdata('<', obuf, obptr - obuf); obptr = obuf; if (ctlr_snap_modes()) { wtrace(" 3270 modes:\n"); space3270out(2); net_add_eor(obuf, obptr - obuf); obptr += 2; trace_netdata('<', obuf, obptr - obuf); } } #if defined(X3270_TN3270E) /*[*/ else if (IN_E) { obptr = obuf; (void) net_add_dummy_tn3270e(); wtrace(" Screen contents (%s):\n", IN_SSCP? "SSCP-LU": "TN3270E-NVT"); if (IN_SSCP) ctlr_snap_buffer_sscp_lu(); else if (IN_ANSI) ansi_snap(); space3270out(2); net_add_eor(obuf, obptr - obuf); obptr += 2; trace_netdata('<', obuf, obptr - obuf); if (IN_ANSI) { wtrace(" NVT modes:\n"); obptr = obuf; ansi_snap_modes(); trace_netdata('<', obuf, obptr - obuf); } } #endif /*]*/ #if defined(X3270_ANSI) /*[*/ else if (IN_ANSI) { obptr = obuf; wtrace(" Screen contents (NVT):\n"); ansi_snap(); trace_netdata('<', obuf, obptr - obuf); wtrace(" NVT modes:\n"); obptr = obuf; ansi_snap_modes(); trace_netdata('<', obuf, obptr - obuf); } #endif /*]*/ } wtrace(" Data stream:\n"); /* Return the buffer. */ tracef_bufptr = CN; return buf; }
/* * This function is careful to do line breaks based on wchar_t's, not * bytes, so multi-byte characters are traced properly. * However, it doesn't know that DBCS characters are two columns wide, so it * will get those wrong and break too late. To get that right, it needs some * sort of function to tell it that a wchar_t is double-width, which we lack at * the moment. * * If wchar_t's are Unicode, it could perhaps use some sort of heuristic based * on which plane the character is in. */ static void trace_ds_s(char *s, Boolean can_break) { int len = strlen(s); int len0 = len + 1; int wlen; Boolean nl = False; wchar_t *w_buf; /* wchar_t translation of s */ wchar_t *w_cur; /* current wchar_t pointer */ wchar_t *w_chunk; /* transient wchar_t buffer */ char *mb_chunk; /* transient multibyte buffer */ if (!toggled(TRACING) || tracef == NULL || !len) return; /* Allocate buffers for chunks of output data. */ mb_chunk = Malloc(len0); w_chunk = (wchar_t *)Malloc(len0 * sizeof(wchar_t)); /* Convert the input string to wchar_t's. */ w_buf = (wchar_t *)Malloc(len0 * sizeof(wchar_t)); wlen = mbstowcs(w_buf, s, len); if (wlen < 0) Error("trace_ds_s: mbstowcs failed"); w_cur = w_buf; /* Check for a trailing newline. */ if (len && s[len-1] == '\n') { wlen--; nl = True; } if (!can_break && dscnt + wlen >= 75) { wtrace("...\n... "); dscnt = 0; } while (dscnt + wlen >= 75) { int plen = 75-dscnt; int mblen; if (plen) { memcpy(w_chunk, w_cur, plen * sizeof(wchar_t)); w_chunk[plen] = 0; mblen = wcstombs(mb_chunk, w_chunk, len0); if (mblen <= 0) Error("trace_ds_s: wcstombs 1 failed"); } else { mb_chunk[0] = '\0'; mblen = 0; } wtrace("%.*s ...\n... ", mblen, mb_chunk); dscnt = 4; w_cur += plen; wlen -= plen; } if (wlen) { int mblen; memcpy(w_chunk, w_cur, wlen * sizeof(wchar_t)); w_chunk[wlen] = 0; mblen = wcstombs(mb_chunk, w_chunk, len0); if (mblen <= 0) Error("trace_ds_s: wcstombs 2 failed"); wtrace("%.*s", mblen, mb_chunk); dscnt += wlen; } if (nl) { wtrace("\n"); dscnt = 0; } Free(mb_chunk); Free(w_buf); Free(w_chunk); }
/* Start tracing, using the specified file. */ void tracefile_ok(const char *tfn) { int devfd = -1; #if !defined(_WIN32) /*[*/ int pipefd[2]; bool just_piped = false; #endif /*]*/ char *buf; char *stfn; stfn = do_subst(tfn, DS_VARS | DS_TILDE | DS_UNIQUE); if (strchr(stfn, '\'') || ((int)strlen(stfn) > 0 && stfn[strlen(stfn)-1] == '\\')) { popup_an_error("Illegal file name: %s", tfn); Free(stfn); goto done; } tracef_max = 0; if (!strcmp(stfn, "stdout")) { tracef = stdout; } else { #if !defined(_WIN32) /*[*/ FILE *pipefile = NULL; if (!strcmp(stfn, "none") || !stfn[0]) { just_piped = true; if (!appres.trace_monitor) { popup_an_error("Must specify a trace file name"); free(stfn); goto done; } } if (appres.trace_monitor) { if (pipe(pipefd) < 0) { popup_an_errno(errno, "pipe() failed"); Free(stfn); goto done; } pipefile = fdopen(pipefd[1], "w"); if (pipefile == NULL) { popup_an_errno(errno, "fdopen() failed"); (void) close(pipefd[0]); (void) close(pipefd[1]); Free(stfn); goto done; } (void) SETLINEBUF(pipefile); (void) fcntl(pipefd[1], F_SETFD, 1); } if (just_piped) { tracef = pipefile; } else #endif /*]*/ { bool append = false; #if !defined(_WIN32) /*[*/ tracef_pipe = pipefile; #endif /*]*/ /* Get the trace file maximum. */ get_tracef_max(); /* Open and configure the file. */ if ((devfd = get_devfd(stfn)) >= 0) tracef = fdopen(dup(devfd), "a"); else if (!strncmp(stfn, ">>", 2)) { append = true; tracef = fopen(stfn + 2, "a"); } else { tracef = fopen(stfn, "w"); } if (tracef == NULL) { popup_an_errno(errno, "%s", stfn); #if !defined(_WIN32) /*[*/ fclose(tracef_pipe); (void) close(pipefd[0]); (void) close(pipefd[1]); #endif /*]*/ Free(stfn); goto done; } tracef_size = ftello(tracef); Replace(tracefile_name, NewString(append? stfn + 2: stfn)); (void) SETLINEBUF(tracef); #if !defined(_WIN32) /*[*/ (void) fcntl(fileno(tracef), F_SETFD, 1); #endif /*]*/ } } /* Start the monitor window. */ if (tracef != stdout && appres.trace_monitor && product_has_display()) { #if !defined(_WIN32) /*[*/ start_trace_window(just_piped? NULL: stfn, pipefd); #else /*][*/ if (windirs_flags && GD_CATF) { start_trace_window(stfn); } #endif /*]*/ } Free(stfn); /* We're really tracing, turn the flag on. */ set_toggle(trace_reason, true); menubar_retoggle(trace_reason); /* Display current status. */ buf = create_tracefile_header("started"); wtrace(false, "%s", buf); Free(buf); done: return; }
/* Create a trace file header. */ static char * create_tracefile_header(const char *mode) { char *buf; int i; /* Create a buffer and redirect output. */ buf = Malloc(MAX_HEADER_SIZE); tracef_bufptr = buf; /* Display current status */ wtrace(true, "Trace %s\n", mode); wtrace(false, " Version: %s\n", build); wtrace(false, " %s\n", build_options()); save_yourself(); wtrace(false, " Command: %s\n", command_string); wtrace(false, " Model %s, %d rows x %d cols", model_name, maxROWS, maxCOLS); wtrace(false, ", %s display", appres.interactive.mono? "monochrome": "color"); if (appres.extended) { wtrace(false, ", extended data stream"); } wtrace(false, ", %s emulation", appres.m3279 ? "color" : "monochrome"); wtrace(false, ", %s charset", get_charset_name()); if (appres.apl_mode) { wtrace(false, ", APL mode"); } wtrace(false, "\n"); #if !defined(_WIN32) /*[*/ wtrace(false, " Locale codeset: %s\n", locale_codeset); #else /*][*/ wtrace(false, " ANSI codepage: %d\n", GetACP()); # if defined(_WIN32) /*[*/ wtrace(false, " Local codepage: %d\n", appres.local_cp); # endif /*]*/ #endif /*]*/ wtrace(false, " Host codepage: %d", (int)(cgcsgid & 0xffff)); if (dbcs) { wtrace(false, "+%d", (int)(cgcsgid_dbcs & 0xffff)); } wtrace(false, "\n"); #if defined(_WIN32) /*[*/ wtrace(false, " Docs: %s\n", mydocs3270? mydocs3270: "(null)"); wtrace(false, " Install dir: %s\n", instdir? instdir: "(null)"); wtrace(false, " Desktop: %s\n", mydesktop? mydesktop: "(null)"); #endif /*]*/ wtrace(false, " Toggles:"); for (i = 0; toggle_names[i].name != NULL; i++) { if (toggle_supported(toggle_names[i].index) && !toggle_names[i].is_alias && toggled(toggle_names[i].index)) { wtrace(false, " %s", toggle_names[i].name); } } wtrace(false, "\n"); if (CONNECTED) { wtrace(false, " Connected to %s, port %u\n", current_host, current_port); } /* Snap the current TELNET options. */ if (net_snap_options()) { wtrace(false, " TELNET state:\n"); trace_netdata('<', obuf, obptr - obuf); } /* Dump the screen contents and modes into the trace file. */ if (CONNECTED) { /* * Note that if the screen is not formatted, we do not * attempt to save what's on it. However, if we're in * 3270 SSCP-LU or NVT mode, we'll do a dummy, empty * write to ensure that the display is in the right * mode. */ if (IN_3270) { wtrace(false, " Screen contents (%s3270) %sformatted:\n", IN_E? "TN3270E-": "", formatted? "": "un"); obptr = obuf; (void) net_add_dummy_tn3270e(); ctlr_snap_buffer(); space3270out(2); net_add_eor(obuf, obptr - obuf); obptr += 2; trace_netdata('<', obuf, obptr - obuf); obptr = obuf; if (ctlr_snap_modes()) { wtrace(false, " 3270 modes:\n"); space3270out(2); net_add_eor(obuf, obptr - obuf); obptr += 2; trace_netdata('<', obuf, obptr - obuf); } } else if (IN_E) { obptr = obuf; (void) net_add_dummy_tn3270e(); wtrace(false, " Screen contents (%s):\n", IN_SSCP? "SSCP-LU": "TN3270E-NVT"); if (IN_SSCP) { ctlr_snap_buffer_sscp_lu(); } else if (IN_NVT) { nvt_snap(); } space3270out(2); net_add_eor(obuf, obptr - obuf); obptr += 2; trace_netdata('<', obuf, obptr - obuf); if (IN_NVT) { wtrace(false, " NVT modes:\n"); obptr = obuf; nvt_snap_modes(); trace_netdata('<', obuf, obptr - obuf); } } else if (IN_NVT) { obptr = obuf; wtrace(false, " Screen contents (NVT):\n"); nvt_snap(); trace_netdata('<', obuf, obptr - obuf); wtrace(false, " NVT modes:\n"); obptr = obuf; nvt_snap_modes(); trace_netdata('<', obuf, obptr - obuf); } } wtrace(false, " Data stream:\n"); /* Return the buffer. */ tracef_bufptr = NULL; return buf; }