]> git.tdb.fi Git - gldbg.git/blobdiff - source/gldbg.cpp
Add gldbg program
[gldbg.git] / source / gldbg.cpp
diff --git a/source/gldbg.cpp b/source/gldbg.cpp
new file mode 100644 (file)
index 0000000..f06496d
--- /dev/null
@@ -0,0 +1,110 @@
+/* $Id$
+
+This file is part of gldbg
+Copyright © 2009  Mikko Rasa, Mikkosoft Productions
+Distributed under the GPL
+*/
+
+#include <cstdlib>
+#include <cerrno>
+#include <cstring>
+#include <sys/poll.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <msp/core/except.h>
+#include <msp/fs/dir.h>
+#include <msp/io/print.h>
+#include <msp/strings/lexicalcast.h>
+#include "gldbg.h"
+#include "glprint.h"
+
+using namespace std;
+using namespace Msp;
+
+Application::RegApp<GlDbg> GlDbg::reg;
+
+GlDbg::GlDbg(int argc, char **argv):
+       pid(0),
+       sock_fd(-1),
+       glprint(glprint_new(0, 16384))
+{
+       libdir = FS::get_sys_lib_dir(argv[0], "gldbg");
+       args.assign(argv+1, argv+argc);
+}
+
+int GlDbg::main()
+{
+       catch_signal(SIGINT);
+       launch();
+
+       Application::main();
+}
+
+void GlDbg::tick()
+{
+       int status;
+       int ret = waitpid(pid, &status, WNOHANG);
+       if(ret==pid)
+       {
+               if(WIFEXITED(status) || WIFSIGNALED(status))
+               {
+                       IO::print("Target process exited\n");
+                       exit(0);
+               }
+       }
+
+       pollfd pfd = { sock_fd, POLLIN, 0 };
+       ret = poll(&pfd, 1, -1);
+       if(ret>0)
+       {
+               char rbuf[1024];
+               ret = read(sock_fd, rbuf, 1024);
+               if(ret>0)
+               {
+                       buffer.append(rbuf, ret);
+                       while(buffer.size()>buf_offset)
+                       {
+                               int ret = gldecoder_decode(glprint, buffer.data()+buf_offset, buffer.size()-buf_offset);
+                               if(ret<0)
+                                       break;
+                               buf_offset += ret;
+                               IO::print("%s\n", glprint_get_buffer(glprint));
+                       }
+                       if(buf_offset>8192)
+                       {
+                               buffer.erase(0, buf_offset);
+                               buf_offset=0;
+                       }
+               }
+       }
+}
+
+void GlDbg::launch()
+{
+       int fds[2];
+       socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
+       sock_fd = fds[0];
+
+       pid = fork();
+       if(pid==0)
+       {
+               string fd_str = lexical_cast(fds[1]);
+               setenv("LD_PRELOAD", (libdir/"glwrap.so").str().c_str(), true);
+               setenv("GLWRAP_FD", fd_str.c_str(), true);
+               close(fds[0]);
+               std::vector<char *> argv(args.size()+1);
+               for(unsigned i=0; i<args.size(); ++i)
+                       argv[i] = strdup(args[i].c_str());
+               argv[args.size()] = 0;
+               execvp(argv[0], &argv[0]);
+               ::exit(127);
+       }
+       else if(pid>0)
+       {
+               close(fds[1]);
+       }
+       else
+       {
+               throw SystemError("Could not launch process", errno);
+       }
+}