summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Yu <tlyu@mit.edu>2011-12-12 20:46:24 +0000
committerTom Yu <tlyu@mit.edu>2011-12-12 20:46:24 +0000
commit5fa98cdabb89a772e138c9e68b475f33458c8ef0 (patch)
treeec972dd2b136cc1fa869c161fe68da9aac3d4258
parentdb0db11147deb5767cccb46820401c2754a7ed16 (diff)
downloadkrb5-5fa98cdabb89a772e138c9e68b475f33458c8ef0.tar.gz
krb5-5fa98cdabb89a772e138c9e68b475f33458c8ef0.tar.xz
krb5-5fa98cdabb89a772e138c9e68b475f33458c8ef0.zip
kfw leash: add -console option to create console for debug output
Signed-off-by: Kevin Wasserman <kevin.wasserman@painless-security.com> ticket: 7050 git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@25570 dc483132-0cff-0310-8789-dd5450dbe970
-rw-r--r--src/windows/leash/Leash.cpp7
-rw-r--r--src/windows/leash/Makefile.in1
-rw-r--r--src/windows/leash/out2con.cpp126
-rw-r--r--src/windows/leash/out2con.h38
4 files changed, 172 insertions, 0 deletions
diff --git a/src/windows/leash/Leash.cpp b/src/windows/leash/Leash.cpp
index 88ee7356a..1f12e913e 100644
--- a/src/windows/leash/Leash.cpp
+++ b/src/windows/leash/Leash.cpp
@@ -26,6 +26,7 @@
#include "mitwhich.h"
#include <leasherr.h>
#include "lglobals.h"
+#include "out2con.h"
#include <krb5.h>
#include <com_err.h>
@@ -305,6 +306,11 @@ BOOL CLeashApp::InitInstance()
{
autoInit = TRUE;
}
+ else if (0 == stricmp(optionParam+1, "console") ||
+ 0 == stricmp(optionParam+1, "c"))
+ {
+ CreateConsoleEcho();
+ }
else
{
MessageBox(hMsg,
@@ -312,6 +318,7 @@ BOOL CLeashApp::InitInstance()
"'-renew' or '-r' to perform ticket renewal (and exit)\n"
"'-destroy' or '-d' to perform ticket destruction (and exit)\n"
"'-autoinit' or '-a' to perform automatic ticket initialization\n"
+ "'-console' or '-c' to attach a console for debugging\n"
"'-ms2mit' or '-import' or '-m' to perform ticket importation (and exit)",
"Leash Error", MB_OK);
return FALSE;
diff --git a/src/windows/leash/Makefile.in b/src/windows/leash/Makefile.in
index 1edf6b45e..997f2259b 100644
--- a/src/windows/leash/Makefile.in
+++ b/src/windows/leash/Makefile.in
@@ -45,6 +45,7 @@ OBJS= \
$(OUTPRE)LeashView.obj \
$(OUTPRE)lglobals.obj \
$(OUTPRE)MainFrm.obj \
+ $(OUTPRE)out2con.obj \
$(OUTPRE)StdAfx.obj \
$(OUTPRE)AfsProperties.obj \
$(OUTPRE)VSroutines.obj \
diff --git a/src/windows/leash/out2con.cpp b/src/windows/leash/out2con.cpp
new file mode 100644
index 000000000..f7a1d35a9
--- /dev/null
+++ b/src/windows/leash/out2con.cpp
@@ -0,0 +1,126 @@
+#include "out2con.h"
+
+#include <windows.h>
+#include <stdio.h>
+#include <io.h>
+
+class ConsoleEcho
+{
+public:
+ ConsoleEcho();
+ ~ConsoleEcho();
+
+private:
+ DWORD ThreadLoop();
+
+ static DWORD WINAPI ThreadFunc(void* param);
+
+ FILE m_originalStdout;
+ int m_stdoutfd;
+ int m_pipefd;
+ HANDLE m_hReadPipe, m_hWritePipe;
+ HANDLE m_hThread;
+
+ static const int BUFSIZE=512;
+};
+
+
+ConsoleEcho *
+CreateConsoleEcho()
+{
+ return new ConsoleEcho;
+}
+
+void
+DestroyConsoleEcho(ConsoleEcho *echo)
+{
+ delete echo;
+}
+
+
+DWORD WINAPI ConsoleEcho::ThreadFunc(void* param)
+{
+ return ((ConsoleEcho*)(param))->ThreadLoop();
+}
+
+
+DWORD ConsoleEcho::ThreadLoop()
+{
+ DWORD dwRead, dwWritten;
+ CHAR chBuf[BUFSIZE];
+ BOOL bSuccess = FALSE;
+ // Note that the following does not work when running in the msvc2010
+ // debugger with redirected output; you still get the redirected file
+ // handle, not the console:
+ //HANDLE hConsoleStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
+ // This seems to be more reliable:
+ HANDLE hConsoleStdOut = CreateFile("CONOUT$",
+ GENERIC_WRITE,
+ FILE_SHARE_WRITE,
+ NULL, OPEN_EXISTING, 0, 0);
+ for (;;) {
+ // read from redirected stdout
+ bSuccess = ReadFile(m_hReadPipe, chBuf, BUFSIZE, &dwRead, NULL);
+ if (!bSuccess || (dwRead == 0))
+ break;
+
+ // write to console
+ WriteFile(hConsoleStdOut, chBuf, dwRead, &dwWritten, NULL);
+ // also write to original stdout
+ if (m_stdoutfd>=0) {
+ _write(m_stdoutfd, chBuf, dwRead);
+ // _commit() causes assert if m_stdoutfd is a device (e.g., console or NUL).
+ if (!_isatty(m_stdoutfd))
+ _commit(m_stdoutfd);
+ }
+ }
+ CloseHandle(hConsoleStdOut);
+ return 0;
+}
+
+ConsoleEcho::ConsoleEcho()
+{
+ // setup console
+ AllocConsole();
+ // create pipe
+ CreatePipe(&m_hReadPipe, &m_hWritePipe, NULL, 0);
+ // save original stdout to preserve commandline-specified redirection
+ m_stdoutfd = _fileno(stdout);
+ // and copy the whole damn FILE structure so we can restore it
+ // when we're done. I don't know any other way to restore the
+ // crazy windows gui default '-2' filedesc stdout.
+ m_originalStdout = *stdout;
+ // hook up the write end of our pipe to stdout
+ m_pipefd = _open_osfhandle((intptr_t)m_hWritePipe, 0);
+ // take our os file handle and allocate a crt FILE for it
+ FILE* fp = _fdopen(m_pipefd, "w");
+ // copy to stdout
+ *stdout = *fp;
+ // now slam the allocated FILE's _flag to zero to mark it as free without
+ // actually closing the os file handle and pipe
+ fp->_flag = 0;
+
+ // disable buffering
+ setvbuf(stdout, NULL, _IONBF, 0);
+
+ // Create a thread to process our pipe, forwarding output
+ // to both the console and the original stdout
+ m_hThread = CreateThread(NULL, 0, &ThreadFunc, this, 0, NULL);
+}
+
+ConsoleEcho::~ConsoleEcho()
+{
+ // fclose() unfortunately immediately invalidates the read pipe before the
+ // pipe thread has a chance to flush it, so don't do that.
+ //fclose(stdout);
+
+ // instead, just slam the original stdout
+ *stdout = m_originalStdout;
+ //printf("Safe to printf now and no longer echoed to console.\n");
+ // Close write pipe
+ _close(m_pipefd);
+ // and wait here for pipe thread to exit
+ WaitForSingleObject(m_hThread, 1000);
+ // now close read pipe as well
+ CloseHandle(m_hReadPipe);
+}
diff --git a/src/windows/leash/out2con.h b/src/windows/leash/out2con.h
new file mode 100644
index 000000000..ebd3859d3
--- /dev/null
+++ b/src/windows/leash/out2con.h
@@ -0,0 +1,38 @@
+#ifndef OUT2CON_H
+#define OUT2CON_H
+
+/* Call CreateConsoleEcho() to create a console and begin echoing stdout to it.
+ * The original stream (if any) will still receive output from stdout.
+ * Call DestroyConsoleEcho() to stop echoing stdout to the console.
+ * The original stream continues to receive stdout.
+ *
+ * WARNING: it is not safe to use stdout from another thread during
+ * CreateConsoleEcho() or DestroyConsoleEcho()
+ */
+
+class ConsoleEcho;
+
+ConsoleEcho *
+CreateConsoleEcho();
+
+void
+DestroyConsoleEcho(ConsoleEcho *consoleEcho);
+
+// Convenience class to automatically echo to console within a scope
+class AutoConsoleEcho
+{
+public:
+ AutoConsoleEcho() : m_echo(CreateConsoleEcho())
+ {
+ }
+
+ ~AutoConsoleEcho()
+ {
+ DestroyConsoleEcho(m_echo);
+ }
+private:
+ ConsoleEcho* m_echo;
+};
+
+
+#endif