This patch is part of my effort to create an easier API for hooks and for the 3rd party apps. Attaching testing app which can be compiled using this command:

$ gcc `pkg-config abrt --libs --cflags` -lreport abrt-problem.c -o abrt-problem


known problems:
- doesn't handle attaching files, hooks has to add read it and pass it's content as a problem_data item - probably shouldn't be part of libreport but ABRT, but if someone wants to write hook for ABRT he has to link libreport anyway because of dump_dir and problem_data...

Any comments welcome.

--Jirka



On 08/15/2012 09:02 PM, Jiri Moskovcak wrote:
---
  src/include/problem_data.h |  1 +
  src/lib/abrt_sock.c        | 89 +++++++++++++++++++++++++++++++++++++++++-----
  2 files changed, 82 insertions(+), 8 deletions(-)

diff --git a/src/include/problem_data.h b/src/include/problem_data.h
index d741b5d..0392e0f 100644
--- a/src/include/problem_data.h
+++ b/src/include/problem_data.h
@@ -89,6 +89,7 @@ char *problem_data_get_content_or_NULL(problem_data_t 
*problem_data, const char
  /* Aborts if key is not found: */
  char *problem_data_get_content_or_die(problem_data_t *problem_data, const 
char *key);

+int problem_data_send_to_abrt(problem_data_t* problem_data);

  /* Conversions between in-memory and on-disk formats */

diff --git a/src/lib/abrt_sock.c b/src/lib/abrt_sock.c
index b595208..d52b975 100644
--- a/src/lib/abrt_sock.c
+++ b/src/lib/abrt_sock.c
@@ -21,18 +21,37 @@

  #define SOCKET_FILE  VAR_RUN"/abrt/abrt.socket"

-static int connect_to_abrtd_and_call_DeleteDebugDump(const char *dump_dir_name)
+/* conencts to abrtd
+ * returns: socketfd
+ * -1 on error
+ */
+static int connect_to_abrtd_socket()
  {
-    int result = 1; /* error so far */
-
      int socketfd = xsocket(AF_UNIX, SOCK_STREAM, 0);
+    if (socketfd == -1)
+        return -1;
      /*close_on_exec_on(socketfd); - not needed, we are closing it soon */
      struct sockaddr_un local;
      memset(&local, 0, sizeof(local));
      local.sun_family = AF_UNIX;
      strcpy(local.sun_path, SOCKET_FILE);
      int r = connect(socketfd, (struct sockaddr*)&local, sizeof(local));
-    if (r == 0)
+    if (r != 0)
+        return -1;
+
+    return socketfd;
+}
+
+static int connect_to_abrtd_and_call_DeleteDebugDump(const char *dump_dir_name)
+{
+    int result = 1; /* error so far */
+    int socketfd = connect_to_abrtd_socket();
+    if (socketfd == -1)
+    {
+        VERB1 perror_msg("Can't connect to '%s'", SOCKET_FILE);
+        return result;
+    }
+    else
      {
          full_write(socketfd, "DELETE ", strlen("DELETE "));
          full_write(socketfd, dump_dir_name, strlen(dump_dir_name));
@@ -40,7 +59,7 @@ static int connect_to_abrtd_and_call_DeleteDebugDump(const 
char *dump_dir_name)
          shutdown(socketfd, SHUT_WR);

          char response[64];
-        r = full_read(socketfd, response, sizeof(response) - 1);
+        int r = full_read(socketfd, response, sizeof(response) - 1);
          if (r >= 0)
          {
              VERB1 log("Response via socket:'%.*s'", r, response);
@@ -51,13 +70,67 @@ static int connect_to_abrtd_and_call_DeleteDebugDump(const 
char *dump_dir_name)
              result = strncmp(response, "HTTP/1.1 200 ", strlen("HTTP/1.1 200 
"));
          }
      }
-    else
+
+    close(socketfd);
+
+    return result;
+}
+
+int problem_data_send_to_abrt(problem_data_t* problem_data)
+{
+    int result = 1; /* error so far */
+    int socketfd = connect_to_abrtd_socket();
+    if (socketfd == -1)
      {
          VERB1 perror_msg("Can't connect to '%s'", SOCKET_FILE);
+        return result;
      }
-    close(socketfd);
+    else
+    {
+        GHashTableIter iter;
+        char *name;
+        struct problem_item *value;
+        g_hash_table_iter_init(&iter, problem_data);

-    return result;
+        full_write(socketfd, "PUT / HTTP/1.1\r\n\r\n", strlen("PUT / 
HTTP/1.1\r\n\r\n"));
+        while (g_hash_table_iter_next(&iter, (void**)&name, (void**)&value))
+        {
+            if (value->flags & CD_FLAG_BIN)
+            {
+                /* sending files over the socket is not implemented yet */
+                log("Skipping binary file %s", name);
+                continue;
+            }
+
+            /* only files should contain '/' and those are handled earlier */
+            if (name[0] == '.' || strchr(name, '/'))
+            {
+                error_msg("Problem data field name contains disallowed chars: 
'%s'", name);
+                continue;
+            }
+
+            char* msg = xasprintf("%s=%s", name, value->content);
+            full_write(socketfd, msg, strlen(msg)+1 /* yes, +1 coz we want to 
send the trailing 0 */);
+            free(msg);
+        }
+        shutdown(socketfd, SHUT_WR);
+
+        char response[64];
+        int r = full_read(socketfd, response, sizeof(response) - 1);
+        if (r >= 0)
+        {
+            VERB1 log("Response via socket:'%.*s'", r, response);
+            /*  0123456789...  */
+            /* "HTTP/1.1 200 " */
+            response[5] = '1';
+            response[7] = '1';
+            result = strncmp(response, "HTTP/1.1 201 ", strlen("HTTP/1.1 201 
"));
+        }
+
+        close(socketfd);
+
+        return result;
+    }
  }

  int delete_dump_dir_possibly_using_abrtd(const char *dump_dir_name)


#include <libabrt.h>
#include <stdio.h>

int main(int argc, char **argv)
{
	problem_data_t *pd = problem_data_new();
	problem_data_add_text_editable(pd, "backtrace", "bar");
	problem_data_add_text_editable(pd, "TYPE", "test");
	problem_data_add_text_editable(pd, "ANALYZER", "test");
	problem_data_add_text_editable(pd, "UID", "0");
	problem_data_add_text_editable(pd, "PID", "1000");
	problem_data_add_text_editable(pd, "EXECUTABLE", "/usr/bin/gnome-terminal");
	problem_data_add_text_editable(pd, "reason", "reason is testing");
	//char *problem_id = problem_data_save(pd);
	//if (problem_id == NULL) {
	//    printf("Error: problem_id is null");
	//    return 1;
	//}
	int res = problem_data_send_to_abrt(pd);
	printf("problem data created: '%s'", res ? "failure" : "success");
	problem_data_free(pd);

	//printf("'%s'\n", problem_id);
	return 0;
}

Reply via email to