101f3ea96SFrançois Revol#include <stdio.h>
201f3ea96SFrançois Revol#include <stdlib.h>
301f3ea96SFrançois Revol#include <string.h>
401f3ea96SFrançois Revol#include <unistd.h>
501f3ea96SFrançois Revol#include <OS.h>
601f3ea96SFrançois Revol#include <image.h>
701f3ea96SFrançois Revol#include <Application.h>
801f3ea96SFrançois Revol#include <StorageDefs.h>
901f3ea96SFrançois Revol#include <MessageFilter.h>
1001f3ea96SFrançois Revol#include <MessageRunner.h>
1101f3ea96SFrançois Revol#include <List.h>
1201f3ea96SFrançois Revol#include <Window.h>
1301f3ea96SFrançois Revol
1401f3ea96SFrançois Revolextern char **original_argv;
1501f3ea96SFrançois Revolextern char **argv_save;
1601f3ea96SFrançois Revolextern char **__libc_argv;
1701f3ea96SFrançois Revolextern int original_argc;
1801f3ea96SFrançois Revolextern int __libc_argc;
1901f3ea96SFrançois Revol
2001f3ea96SFrançois Revol#define MAX_VIEWS 10
2101f3ea96SFrançois Revol
2201f3ea96SFrançois Revolint gStartWin = 0;
2301f3ea96SFrançois Revolchar *gMatchViewNames[MAX_VIEWS];
2401f3ea96SFrançois Revolint gNumViewNames = 0;
2501f3ea96SFrançois Revol
2601f3ea96SFrançois Revolchar gExePath[B_PATH_NAME_LENGTH];
2701f3ea96SFrançois Revolimage_id gExeImg = -1;
2801f3ea96SFrançois Revolint (*gExeMainProc)(int argc, char **argv);
2901f3ea96SFrançois Revol
3001f3ea96SFrançois Revolthread_id gWaitForBAppThID = -1;
3101f3ea96SFrançois Revolsem_id gStdoutLock;
3201f3ea96SFrançois Revol
3301f3ea96SFrançois Revol//extern "C" EnqueueMessage__Q28BPrivate13BLooperTargetP8BMessage(BLooper *_this, BMessage *message);
3401f3ea96SFrançois Revol
3501f3ea96SFrançois Revol//EnqueueMessage__Q28BPrivate13BLooperTargetP8BMessage(BLooper *_this, BMessage *message);
3601f3ea96SFrançois Revol
3701f3ea96SFrançois RevolBMessageFilter *gAppFilter;
3801f3ea96SFrançois Revolbool quitting = false;
3901f3ea96SFrançois Revol
4001f3ea96SFrançois Revolfilter_result bapp_filter(BMessage *message,
4101f3ea96SFrançois Revol			  BHandler **target,
4201f3ea96SFrançois Revol			  BMessageFilter *filter)
4301f3ea96SFrançois Revol{
4401f3ea96SFrançois Revol  if (message->what == 'plop') /* our doesn't count */
4501f3ea96SFrançois Revol    return B_DISPATCH_MESSAGE;
4601f3ea96SFrançois Revol  acquire_sem(gStdoutLock);
4701f3ea96SFrançois Revol  fprintf(stdout, "\033[31mMessage for BApplication:\033[0m\n");
4801f3ea96SFrançois Revol  message->PrintToStream();
4901f3ea96SFrançois Revol  release_sem(gStdoutLock);
5001f3ea96SFrançois Revol  return B_DISPATCH_MESSAGE;
5101f3ea96SFrançois Revol}
5201f3ea96SFrançois Revol
5301f3ea96SFrançois Revolfilter_result bwin_filter(BMessage *message,
5401f3ea96SFrançois Revol			  BHandler **target,
5501f3ea96SFrançois Revol			  BMessageFilter *filter)
5601f3ea96SFrançois Revol{
5701f3ea96SFrançois Revol  BWindow *win;
5801f3ea96SFrançois Revol  BHandler *hand = NULL;
5901f3ea96SFrançois Revol  if (target)
6001f3ea96SFrançois Revol    hand = *target;
6101f3ea96SFrançois Revol  win = dynamic_cast<BWindow *>(filter->Looper());
6201f3ea96SFrançois Revol  acquire_sem(gStdoutLock);
6301f3ea96SFrançois Revol  fprintf(stdout,
6401f3ea96SFrançois Revol	  "\033[31mMessage for View \"%s\" of Window \"%s\":\033[0m\n",
6501f3ea96SFrançois Revol	  hand?hand->Name():NULL,
6601f3ea96SFrançois Revol	  win?win->Title():NULL);
6701f3ea96SFrançois Revol  message->PrintToStream();
6801f3ea96SFrançois Revol  release_sem(gStdoutLock);
6901f3ea96SFrançois Revol  return B_DISPATCH_MESSAGE;
7001f3ea96SFrançois Revol}
7101f3ea96SFrançois Revol
7201f3ea96SFrançois Revolclass MyHandler : public BHandler {
7301f3ea96SFrançois Revolpublic:
7401f3ea96SFrançois Revol  MyHandler();
7501f3ea96SFrançois Revol  ~MyHandler();
7601f3ea96SFrançois Revol  void MessageReceived(BMessage *msg);
7701f3ea96SFrançois Revolprivate:
7801f3ea96SFrançois Revol  BList fWindowList;
7901f3ea96SFrançois Revol};
8001f3ea96SFrançois Revol
8101f3ea96SFrançois RevolMyHandler::MyHandler()
8201f3ea96SFrançois Revol  :BHandler("spying handler")
8301f3ea96SFrançois Revol{
8401f3ea96SFrançois Revol  fWindowList.MakeEmpty();
8501f3ea96SFrançois Revol}
8601f3ea96SFrançois Revol
8701f3ea96SFrançois RevolMyHandler::~MyHandler()
8801f3ea96SFrançois Revol{
8901f3ea96SFrançois Revol}
9001f3ea96SFrançois Revol
9101f3ea96SFrançois Revolvoid MyHandler::MessageReceived(BMessage *msg)
9201f3ea96SFrançois Revol{
9301f3ea96SFrançois Revol  int i;
9401f3ea96SFrançois Revol  BMessageFilter *afilter;
9501f3ea96SFrançois Revol  switch (msg->what) {
9601f3ea96SFrançois Revol  case 'plop':
9701f3ea96SFrançois Revol    i = be_app->CountWindows();
9801f3ea96SFrançois Revol    for (; i; i--) {
9901f3ea96SFrançois Revol      BWindow *win = be_app->WindowAt(i-1);
10001f3ea96SFrançois Revol      if (win && !fWindowList.HasItem(win)) {
10101f3ea96SFrançois Revol	fWindowList.AddItem(win);
10201f3ea96SFrançois Revol	afilter = new BMessageFilter(B_ANY_DELIVERY,
10301f3ea96SFrançois Revol				     B_ANY_SOURCE,
10401f3ea96SFrançois Revol				     bwin_filter);
10501f3ea96SFrançois Revol	win->Lock();
10601f3ea96SFrançois Revol	win->AddCommonFilter(afilter);
10701f3ea96SFrançois Revol	win->Unlock();
10801f3ea96SFrançois Revol      }
10901f3ea96SFrançois Revol    }
11001f3ea96SFrançois Revol    break;
11101f3ea96SFrançois Revol  }
11201f3ea96SFrançois Revol  BHandler::MessageReceived(msg);
11301f3ea96SFrançois Revol}
11401f3ea96SFrançois Revol
11501f3ea96SFrançois Revolint32 wait_for_loopers(void *arg)
11601f3ea96SFrançois Revol{
11701f3ea96SFrançois Revol  MyHandler *myh;
11801f3ea96SFrançois Revol  /* wait for BApplication */
11901f3ea96SFrançois Revol  while (!be_app)
12001f3ea96SFrançois Revol    snooze(50000);
12101f3ea96SFrançois Revol  gAppFilter = new BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE, bapp_filter);
12201f3ea96SFrançois Revol  myh = new MyHandler;
12301f3ea96SFrançois Revol  be_app->Lock();
12401f3ea96SFrançois Revol  be_app->AddCommonFilter(gAppFilter);
12501f3ea96SFrançois Revol  be_app->AddHandler(myh);
12601f3ea96SFrançois Revol  be_app->Unlock();
12701f3ea96SFrançois Revol  new BMessageRunner(BMessenger(myh), new BMessage('plop'), 100000);
12801f3ea96SFrançois Revol
12901f3ea96SFrançois Revol  return 0;
13001f3ea96SFrançois Revol}
13101f3ea96SFrançois Revol
13201f3ea96SFrançois Revolstatic int usage(char *argv0)
13301f3ea96SFrançois Revol{
13401f3ea96SFrançois Revol  printf("usage:\n");
13501f3ea96SFrançois Revol  printf("%s app [args...]\n", argv0);
13601f3ea96SFrançois Revol  return 0;
13701f3ea96SFrançois Revol}
13801f3ea96SFrançois Revol
13901f3ea96SFrançois Revolint main(int argc, char **argv)
14001f3ea96SFrançois Revol{
14101f3ea96SFrançois Revol  int i;
14201f3ea96SFrançois Revol  status_t err;
14301f3ea96SFrançois Revol  char *trapp_name;
14401f3ea96SFrançois Revol  if (argc < 2)
14501f3ea96SFrançois Revol    return usage(argv[0]);
14601f3ea96SFrançois Revol  trapp_name = argv[0];
14701f3ea96SFrançois Revol
14801f3ea96SFrançois Revol  for (i = 1; i < argc; i++) {
14901f3ea96SFrançois Revol    if (strncmp(argv[i], "-", 1))
15001f3ea96SFrançois Revol      break;
15101f3ea96SFrançois Revol    else if (!strcmp(argv[i], "-view")) {
15201f3ea96SFrançois Revol      if (gNumViewNames >= MAX_VIEWS) {
15301f3ea96SFrançois Revol	printf("too many view names\n");
15401f3ea96SFrançois Revol	return 1;
15501f3ea96SFrançois Revol      }
15601f3ea96SFrançois Revol      i++;
15701f3ea96SFrançois Revol      if (i >= argc) {
15801f3ea96SFrançois Revol	printf("missing arg to -view\n");
15901f3ea96SFrançois Revol	return 1;
16001f3ea96SFrançois Revol      }
16101f3ea96SFrançois Revol      gMatchViewNames[gNumViewNames] = argv[i];
16201f3ea96SFrançois Revol      gNumViewNames++;
16301f3ea96SFrançois Revol    } else if (!strcmp(argv[i], "-firstw")) {
16401f3ea96SFrançois Revol      i++;
16501f3ea96SFrançois Revol      if (i >= argc) {
16601f3ea96SFrançois Revol	printf("missing arg to -firstw\n");
16701f3ea96SFrançois Revol	return 1;
16801f3ea96SFrançois Revol      }
16901f3ea96SFrançois Revol      gStartWin = atoi(argv[i]);
17001f3ea96SFrançois Revol    } else {
17101f3ea96SFrançois Revol      return usage(argv[0]);
17201f3ea96SFrançois Revol    }
17301f3ea96SFrançois Revol  }
17401f3ea96SFrançois Revol  if (argc - i < 1)
17501f3ea96SFrançois Revol    return usage(argv[0]);
17601f3ea96SFrançois Revol  argv += i;
17701f3ea96SFrançois Revol  argc -= i;
17801f3ea96SFrançois Revol
17901f3ea96SFrançois Revol  for (i = 0; i < argc; i++)
18001f3ea96SFrançois Revol    printf("argv[%d] = %s\n", i, argv[i]);
18101f3ea96SFrançois Revol  gExePath[0] = '\0';
18201f3ea96SFrançois Revol  if (strncmp(argv[0], "/", 1)) {
18301f3ea96SFrançois Revol    getcwd(gExePath, B_PATH_NAME_LENGTH-10);
18401f3ea96SFrançois Revol    strcat(gExePath, "/");
18501f3ea96SFrançois Revol  }
18601f3ea96SFrançois Revol  strncat(gExePath, argv[0], B_PATH_NAME_LENGTH-1-strlen(gExePath));
18701f3ea96SFrançois Revol  printf("cmd = %s\n", gExePath);
18801f3ea96SFrançois Revol  gExeImg = load_add_on(gExePath);
18901f3ea96SFrançois Revol  if (gExeImg < B_OK) {
19001f3ea96SFrançois Revol    fprintf(stderr, "load_add_on: %s\n", strerror(gExeImg));
19101f3ea96SFrançois Revol    return 1;
19201f3ea96SFrançois Revol  }
19301f3ea96SFrançois Revol
19401f3ea96SFrançois Revol  // original are static...
19501f3ea96SFrançois Revol  //printf("original: %d; %s\n", original_argc, *original_argv);
19601f3ea96SFrançois Revol  fprintf(stderr, "libc: %d; %s\n", __libc_argc, *__libc_argv);
19701f3ea96SFrançois Revol  fprintf(stderr, "save: %s\n", *argv_save);
19801f3ea96SFrançois Revol
19901f3ea96SFrançois Revol  //argv[0] = trapp_name;
20001f3ea96SFrançois Revol  __libc_argv = argv;
20101f3ea96SFrançois Revol  __libc_argc = argc;
20201f3ea96SFrançois Revol  argv_save = argv;
20301f3ea96SFrançois Revol
20401f3ea96SFrançois Revol  gStdoutLock = create_sem(1, "spybmsg_stdout_lock");
20501f3ea96SFrançois Revol
20601f3ea96SFrançois Revol  err = get_image_symbol(gExeImg, "main", B_SYMBOL_TYPE_TEXT, (void **)&gExeMainProc);
20701f3ea96SFrançois Revol  if (err < B_OK) {
20801f3ea96SFrançois Revol    fprintf(stderr, "get_image_symbol(main): %s\n", strerror(gExeImg));
20901f3ea96SFrançois Revol    return 1;
21001f3ea96SFrançois Revol  }
21101f3ea96SFrançois Revol  printf("main @ %p\n", gExeMainProc);
21201f3ea96SFrançois Revol
21301f3ea96SFrançois Revol  resume_thread(spawn_thread(wait_for_loopers,
21401f3ea96SFrançois Revol			     "waiting for BLoopers",
21501f3ea96SFrançois Revol			     B_NORMAL_PRIORITY, NULL));
21601f3ea96SFrançois Revol
21701f3ea96SFrançois Revol  i = gExeMainProc(argc, argv);
21801f3ea96SFrançois Revol
21901f3ea96SFrançois Revol  return i;
22001f3ea96SFrançois Revol}
22101f3ea96SFrançois Revol
222