i am a dumb dummy
[oweals/gnunet.git] / src / monkey / gnunet-monkey.c
index 3d93a51128a0c47a73ab6d5952daa64390aac0d6..f3dc238c8a606d02314fbf762510c5f98246dab6 100644 (file)
 #include <unistd.h> //usleep
 #include <libesmtp.h>
 #include "gdbmi.h"
+#include "platform.h"
+#include "gnunet_common.h"
+#include "gnunet_getopt_lib.h"
+#include "gnunet_program_lib.h"
+
+extern void sendMail (const char *messageContents);
+static const char* mode;
+static const char* dumpFileName;
+static const char* binaryName;
+static int ret = 0;
 
 void cb_console(const char *str, void *data)
 {
@@ -40,7 +50,7 @@ void cb_from(const char *str, void *data)
  printf("<< %s\n",str);
 }
 
-volatile int async_c=0;
+static int async_c=0;
 
 void cb_async(mi_output *o, void *data)
 {
@@ -48,6 +58,31 @@ void cb_async(mi_output *o, void *data)
  async_c++;
 }
 
+
+static void dumpText(const char* message)
+{
+       FILE* file = fopen(dumpFileName, "w");
+       GNUNET_assert(NULL != file);
+       fprintf(file,"%s", message);
+       fclose(file);
+}
+
+
+void send_bug_mail(mi_stop* sr, mi_frames* f)
+{
+       char *message;
+       GNUNET_asprintf(&message, 
+                       "Bug detected in file:%s\nfunction:%s\nline:%d\nreason:%s\nreceived signal:%s\n%s\n",
+                       f->file, f->func, f->line, mi_reason_enum_to_str(sr->reason), sr->signal_name, sr->signal_meaning);
+       if (strcasecmp(mode, "mail") == 0)
+               sendMail(message);
+       else
+               dumpText(message);
+       
+       GNUNET_free (message);
+}
+
+
 int wait_for_stop(mi_h *h)
 {
  int res=1;
@@ -60,13 +95,10 @@ int wait_for_stop(mi_h *h)
  sr=mi_res_stop(h);
  if (sr)
    {
-    printf("Stopped, reason: %s\n",mi_reason_enum_to_str(sr->reason));
-    printf("Received signal name: %s\n", sr->signal_name);
-    printf("Received signal meaning: %s\n", sr->signal_meaning);
-    //printf("In file: %s\n", sr->frame->file);
-    //printf("Line Number: %d\n", sr->frame->line);
     f = gmi_stack_info_frame(h);
+    send_bug_mail(sr, f);
     mi_free_stop(sr);
+    res = 0;
    }
  else
    {
@@ -77,83 +109,138 @@ int wait_for_stop(mi_h *h)
  return res;
 }
 
-int main(int argc, char *argv[])
-{
- mi_aux_term *xterm_tty=NULL;
- /* This is like a file-handle for fopen.
-    Here we have all the state of gdb "connection". */
- mi_h *h;
 
- /* Connect to gdb child. */
- h=mi_connect_local();
- if (!h)
-   {
-    printf("Connect failed\n");
-    return 1;
-   }
- printf("Connected to gdb!\n");
-
- /* Set all callbacks. */
- mi_set_console_cb(h,cb_console,NULL);
- mi_set_target_cb(h,cb_target,NULL);
- mi_set_log_cb(h,cb_log,NULL);
- mi_set_async_cb(h,cb_async,NULL);
- mi_set_to_gdb_cb(h,cb_to,NULL);
- mi_set_from_gdb_cb(h,cb_from,NULL);
-
- /* Set the name of the child and the command line aguments. */
- if (!gmi_set_exec(h,"bug_null_pointer_exception", NULL))
-   {
-    printf("Error setting exec y args\n");
-    mi_disconnect(h);
-    return 1;
-   }
 
- /* Tell gdb to attach the child to a terminal. */
- if (!gmi_target_terminal(h, ttyname(STDIN_FILENO)))
-   {
-    printf("Error selecting target terminal\n");
-    mi_disconnect(h);
-    return 1;
-   }
-
- /* Run the program. */
- if (!gmi_exec_run(h))
-   {
-    printf("Error in run!\n");
-    mi_disconnect(h);
-    return 1;
-   }
- /* Here we should be stopped when the program crashes */
- if (!wait_for_stop(h))
-   {
-    mi_disconnect(h);
-    return 1;
-   }
-
- /* Continue execution. */
- if (!gmi_exec_continue(h))
-   {
-    printf("Error in continue!\n");
-    mi_disconnect(h);
-    return 1;
-   }
- /* Here we should be terminated. */
- if (!wait_for_stop(h))
-   {
-    mi_disconnect(h);
-    return 1;
-   }
+/**
+ * Main function that will be run by the scheduler.
+ *
+ * @param cls closure
+ * @param args remaining command-line arguments
+ * @param cfgfile name of the configuration file used (for saving, can be NULL!)
+ * @param c configuration
+ */
+static void
+run (void *cls,
+     char *const *args,
+     const char *cfgfile,
+     const struct GNUNET_CONFIGURATION_Handle *c)
+{
+       mi_aux_term *xterm_tty=NULL;
+       
+       /* This is like a file-handle for fopen.
+           Here we have all the state of gdb "connection". */
+        mi_h *h;
+
+        /* Connect to gdb child. */
+        h=mi_connect_local();
+        if (!h)
+          {
+           printf("Connect failed\n");
+           ret = 1;
+           return;
+          }
+        printf("Connected to gdb!\n");
+
+        /* Set all callbacks. */
+        mi_set_console_cb(h,cb_console,NULL);
+        mi_set_target_cb(h,cb_target,NULL);
+        mi_set_log_cb(h,cb_log,NULL);
+        mi_set_async_cb(h,cb_async,NULL);
+        mi_set_to_gdb_cb(h,cb_to,NULL);
+        mi_set_from_gdb_cb(h,cb_from,NULL);
+
+        /* Set the name of the child and the command line aguments. */
+        if (!gmi_set_exec(h, binaryName, NULL))
+          {
+           printf("Error setting exec y args\n");
+           mi_disconnect(h);
+           ret = 1;
+           return;
+          }
+
+        /* Tell gdb to attach the child to a terminal. */
+        if (!gmi_target_terminal(h, ttyname(STDIN_FILENO)))
+          {
+           printf("Error selecting target terminal\n");
+           mi_disconnect(h);
+           ret = 1;
+           return;
+          }
+
+        /* Run the program. */
+        if (!gmi_exec_run(h))
+          {
+           printf("Error in run!\n");
+           mi_disconnect(h);
+           ret = 1;
+           return;
+          }
+        /* Here we should be stopped when the program crashes */
+        if (!wait_for_stop(h))
+          {
+           mi_disconnect(h);
+           ret = 1;
+           return;
+          }
+
+        /* Continue execution. */
+        if (!gmi_exec_continue(h))
+          {
+           printf("Error in continue!\n");
+           mi_disconnect(h);
+           ret = 1;
+           return;
+          }
+        /* Here we should be terminated. */
+        if (!wait_for_stop(h))
+          {
+           mi_disconnect(h);
+           ret = 1;
+           return;
+          }
+
+        /* Exit from gdb. */
+        gmi_gdb_exit(h);
+        /* Close the connection. */
+        mi_disconnect(h);
+        /* Wait 5 seconds and close the auxiliar terminal. */
+        printf("Waiting 5 seconds\n");
+        sleep(5);
+        gmi_end_aux_term(xterm_tty);
+}
 
- /* Exit from gdb. */
- gmi_gdb_exit(h);
- /* Close the connection. */
- mi_disconnect(h);
- /* Wait 5 seconds and close the auxiliar terminal. */
- printf("Waiting 5 seconds\n");
- sleep(5);
- gmi_end_aux_term(xterm_tty);
 
- return 0;
+int main(int argc, char *argv[])
+{
+       /*
+        * FIXME: 
+        * Command should accept email address to which monkey sends the debugging report.
+        * The email address can also be read from the configuration file.
+        */
+ static const struct GNUNET_GETOPT_CommandLineOption options[] = {
+     {'m', "mode", NULL, gettext_noop ("monkey's mode of operation: options are \"text\" or \"email\""),
+      GNUNET_YES, &GNUNET_GETOPT_set_string, &mode},
+     {'b', "binary", NULL, gettext_noop ("binary for program to debug with monkey"),
+      GNUNET_YES, &GNUNET_GETOPT_set_string, &binaryName},
+     {'o', "output", NULL, gettext_noop ("path to file to dump monkey's output in case of working in text mode"),
+      GNUNET_YES, &GNUNET_GETOPT_set_string, &dumpFileName},
+      GNUNET_GETOPT_OPTION_END
+   };
+ if (argc < 2) {
+        printf("%s", "Monkey should take arguments: Use --help to get a list of options.\n");
+        return 1;
+ }
+ if (GNUNET_OK == GNUNET_PROGRAM_run (argc,
+                       argv,
+                       "gnunet-monkey",
+                       gettext_noop
+                       ("Automatically debug a service"),
+                       options, &run, NULL))
+     {
+       return ret;
+     }
+
+     return 1;
 }