1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <unistd.h>
5#include <OS.h>
6#include <image.h>
7#include <Application.h>
8#include <StorageDefs.h>
9#include <MessageFilter.h>
10#include <MessageRunner.h>
11#include <List.h>
12#include <Window.h>
13
14extern char **original_argv;
15extern char **argv_save;
16extern char **__libc_argv;
17extern int original_argc;
18extern int __libc_argc;
19
20#define MAX_VIEWS 10
21
22int gStartWin = 0;
23char *gMatchViewNames[MAX_VIEWS];
24int gNumViewNames = 0;
25
26char gExePath[B_PATH_NAME_LENGTH];
27image_id gExeImg = -1;
28int (*gExeMainProc)(int argc, char **argv);
29
30thread_id gWaitForBAppThID = -1;
31sem_id gStdoutLock;
32
33//extern "C" EnqueueMessage__Q28BPrivate13BLooperTargetP8BMessage(BLooper *_this, BMessage *message);
34
35//EnqueueMessage__Q28BPrivate13BLooperTargetP8BMessage(BLooper *_this, BMessage *message);
36
37BMessageFilter *gAppFilter;
38bool quitting = false;
39
40filter_result bapp_filter(BMessage *message,
41			  BHandler **target,
42			  BMessageFilter *filter)
43{
44  if (message->what == 'plop') /* our doesn't count */
45    return B_DISPATCH_MESSAGE;
46  acquire_sem(gStdoutLock);
47  fprintf(stdout, "\033[31mMessage for BApplication:\033[0m\n");
48  message->PrintToStream();
49  release_sem(gStdoutLock);
50  return B_DISPATCH_MESSAGE;
51}
52
53filter_result bwin_filter(BMessage *message,
54			  BHandler **target,
55			  BMessageFilter *filter)
56{
57  BWindow *win;
58  BHandler *hand = NULL;
59  if (target)
60    hand = *target;
61  win = dynamic_cast<BWindow *>(filter->Looper());
62  acquire_sem(gStdoutLock);
63  fprintf(stdout,
64	  "\033[31mMessage for View \"%s\" of Window \"%s\":\033[0m\n",
65	  hand?hand->Name():NULL,
66	  win?win->Title():NULL);
67  message->PrintToStream();
68  release_sem(gStdoutLock);
69  return B_DISPATCH_MESSAGE;
70}
71
72class MyHandler : public BHandler {
73public:
74  MyHandler();
75  ~MyHandler();
76  void MessageReceived(BMessage *msg);
77private:
78  BList fWindowList;
79};
80
81MyHandler::MyHandler()
82  :BHandler("spying handler")
83{
84  fWindowList.MakeEmpty();
85}
86
87MyHandler::~MyHandler()
88{
89}
90
91void MyHandler::MessageReceived(BMessage *msg)
92{
93  int i;
94  BMessageFilter *afilter;
95  switch (msg->what) {
96  case 'plop':
97    i = be_app->CountWindows();
98    for (; i; i--) {
99      BWindow *win = be_app->WindowAt(i-1);
100      if (win && !fWindowList.HasItem(win)) {
101	fWindowList.AddItem(win);
102	afilter = new BMessageFilter(B_ANY_DELIVERY,
103				     B_ANY_SOURCE,
104				     bwin_filter);
105	win->Lock();
106	win->AddCommonFilter(afilter);
107	win->Unlock();
108      }
109    }
110    break;
111  }
112  BHandler::MessageReceived(msg);
113}
114
115int32 wait_for_loopers(void *arg)
116{
117  MyHandler *myh;
118  /* wait for BApplication */
119  while (!be_app)
120    snooze(50000);
121  gAppFilter = new BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE, bapp_filter);
122  myh = new MyHandler;
123  be_app->Lock();
124  be_app->AddCommonFilter(gAppFilter);
125  be_app->AddHandler(myh);
126  be_app->Unlock();
127  new BMessageRunner(BMessenger(myh), new BMessage('plop'), 100000);
128
129  return 0;
130}
131
132static int usage(char *argv0)
133{
134  printf("usage:\n");
135  printf("%s app [args...]\n", argv0);
136  return 0;
137}
138
139int main(int argc, char **argv)
140{
141  int i;
142  status_t err;
143  char *trapp_name;
144  if (argc < 2)
145    return usage(argv[0]);
146  trapp_name = argv[0];
147
148  for (i = 1; i < argc; i++) {
149    if (strncmp(argv[i], "-", 1))
150      break;
151    else if (!strcmp(argv[i], "-view")) {
152      if (gNumViewNames >= MAX_VIEWS) {
153	printf("too many view names\n");
154	return 1;
155      }
156      i++;
157      if (i >= argc) {
158	printf("missing arg to -view\n");
159	return 1;
160      }
161      gMatchViewNames[gNumViewNames] = argv[i];
162      gNumViewNames++;
163    } else if (!strcmp(argv[i], "-firstw")) {
164      i++;
165      if (i >= argc) {
166	printf("missing arg to -firstw\n");
167	return 1;
168      }
169      gStartWin = atoi(argv[i]);
170    } else {
171      return usage(argv[0]);
172    }
173  }
174  if (argc - i < 1)
175    return usage(argv[0]);
176  argv += i;
177  argc -= i;
178
179  for (i = 0; i < argc; i++)
180    printf("argv[%d] = %s\n", i, argv[i]);
181  gExePath[0] = '\0';
182  if (strncmp(argv[0], "/", 1)) {
183    getcwd(gExePath, B_PATH_NAME_LENGTH-10);
184    strcat(gExePath, "/");
185  }
186  strncat(gExePath, argv[0], B_PATH_NAME_LENGTH-1-strlen(gExePath));
187  printf("cmd = %s\n", gExePath);
188  gExeImg = load_add_on(gExePath);
189  if (gExeImg < B_OK) {
190    fprintf(stderr, "load_add_on: %s\n", strerror(gExeImg));
191    return 1;
192  }
193
194  // original are static...
195  //printf("original: %d; %s\n", original_argc, *original_argv);
196  fprintf(stderr, "libc: %d; %s\n", __libc_argc, *__libc_argv);
197  fprintf(stderr, "save: %s\n", *argv_save);
198
199  //argv[0] = trapp_name;
200  __libc_argv = argv;
201  __libc_argc = argc;
202  argv_save = argv;
203
204  gStdoutLock = create_sem(1, "spybmsg_stdout_lock");
205
206  err = get_image_symbol(gExeImg, "main", B_SYMBOL_TYPE_TEXT, (void **)&gExeMainProc);
207  if (err < B_OK) {
208    fprintf(stderr, "get_image_symbol(main): %s\n", strerror(gExeImg));
209    return 1;
210  }
211  printf("main @ %p\n", gExeMainProc);
212
213  resume_thread(spawn_thread(wait_for_loopers,
214			     "waiting for BLoopers",
215			     B_NORMAL_PRIORITY, NULL));
216
217  i = gExeMainProc(argc, argv);
218
219  return i;
220}
221
222