#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)
{
printf("<< %s\n",str);
}
-volatile int async_c=0;
+static int async_c=0;
void cb_async(mi_output *o, void *data)
{
}
+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;
- 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);
- sendMail(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);
}
return res;
}
-int main(int argc, char *argv[])
-{
- mi_aux_term *xterm_tty=NULL;
- const char* binaryName;
-
- binaryName = argv[1];
- GNUNET_assert(NULL != binaryName);
-
- /* 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, binaryName, 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;
}