]> git.tdb.fi Git - gldbg.git/blob - source/gldbg.cpp
Add gldbg program
[gldbg.git] / source / gldbg.cpp
1 /* $Id$
2
3 This file is part of gldbg
4 Copyright © 2009  Mikko Rasa, Mikkosoft Productions
5 Distributed under the GPL
6 */
7
8 #include <cstdlib>
9 #include <cerrno>
10 #include <cstring>
11 #include <sys/poll.h>
12 #include <sys/socket.h>
13 #include <sys/wait.h>
14 #include <msp/core/except.h>
15 #include <msp/fs/dir.h>
16 #include <msp/io/print.h>
17 #include <msp/strings/lexicalcast.h>
18 #include "gldbg.h"
19 #include "glprint.h"
20
21 using namespace std;
22 using namespace Msp;
23
24 Application::RegApp<GlDbg> GlDbg::reg;
25
26 GlDbg::GlDbg(int argc, char **argv):
27         pid(0),
28         sock_fd(-1),
29         glprint(glprint_new(0, 16384))
30 {
31         libdir = FS::get_sys_lib_dir(argv[0], "gldbg");
32         args.assign(argv+1, argv+argc);
33 }
34
35 int GlDbg::main()
36 {
37         catch_signal(SIGINT);
38         launch();
39
40         Application::main();
41 }
42
43 void GlDbg::tick()
44 {
45         int status;
46         int ret = waitpid(pid, &status, WNOHANG);
47         if(ret==pid)
48         {
49                 if(WIFEXITED(status) || WIFSIGNALED(status))
50                 {
51                         IO::print("Target process exited\n");
52                         exit(0);
53                 }
54         }
55
56         pollfd pfd = { sock_fd, POLLIN, 0 };
57         ret = poll(&pfd, 1, -1);
58         if(ret>0)
59         {
60                 char rbuf[1024];
61                 ret = read(sock_fd, rbuf, 1024);
62                 if(ret>0)
63                 {
64                         buffer.append(rbuf, ret);
65                         while(buffer.size()>buf_offset)
66                         {
67                                 int ret = gldecoder_decode(glprint, buffer.data()+buf_offset, buffer.size()-buf_offset);
68                                 if(ret<0)
69                                         break;
70                                 buf_offset += ret;
71                                 IO::print("%s\n", glprint_get_buffer(glprint));
72                         }
73                         if(buf_offset>8192)
74                         {
75                                 buffer.erase(0, buf_offset);
76                                 buf_offset=0;
77                         }
78                 }
79         }
80 }
81
82 void GlDbg::launch()
83 {
84         int fds[2];
85         socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
86         sock_fd = fds[0];
87
88         pid = fork();
89         if(pid==0)
90         {
91                 string fd_str = lexical_cast(fds[1]);
92                 setenv("LD_PRELOAD", (libdir/"glwrap.so").str().c_str(), true);
93                 setenv("GLWRAP_FD", fd_str.c_str(), true);
94                 close(fds[0]);
95                 std::vector<char *> argv(args.size()+1);
96                 for(unsigned i=0; i<args.size(); ++i)
97                         argv[i] = strdup(args[i].c_str());
98                 argv[args.size()] = 0;
99                 execvp(argv[0], &argv[0]);
100                 ::exit(127);
101         }
102         else if(pid>0)
103         {
104                 close(fds[1]);
105         }
106         else
107         {
108                 throw SystemError("Could not launch process", errno);
109         }
110 }