src/librrdc.c: rrdd_connect: Allow connecting to arbitrary addresses.
[rrdd.git] / src / librrdc.c
index 25d0afa..0e2281d 100644 (file)
@@ -22,8 +22,6 @@
 #include "rrdd.h"
 #include "rrdc.h"
 
-#define SOCK_TEMPLATE "/tmp/rrdc.sock.XXXXXX"
-
 static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
 static int sd;
 static FILE *sh;
@@ -60,11 +58,14 @@ static int buffer_add_value (const char *value,
   return (buffer_add_string (temp, buffer_ret, buffer_size_ret));
 } /* int buffer_add_value */
 
-int rrdd_connect (const char *path)
+static int rrdd_connect_unix (const char *path)
 {
   struct sockaddr_un sa;
   int status;
 
+  if (path == NULL)
+    path = RRDD_SOCK_PATH;
+
   pthread_mutex_lock (&lock);
 
   if (sh != NULL)
@@ -106,6 +107,81 @@ int rrdd_connect (const char *path)
   pthread_mutex_unlock (&lock);
 
   return (0);
+} /* int rrdd_connect_unix */
+
+int rrdd_connect (const char *addr)
+{
+  struct addrinfo ai_hints;
+  struct addrinfo *ai_res;
+  struct addrinfo *ai_ptr;
+  int status;
+
+  if (addr == NULL)
+    addr = RRDD_SOCK_PATH;
+
+  if (strncmp ("unix:", addr, strlen ("unix:")) == 0)
+    return (rrdd_connect_unix (addr + strlen ("unix:")));
+  else if (addr[0] == '/')
+    return (rrdd_connect_unix (addr));
+
+  pthread_mutex_lock (&lock);
+
+  if (sh != NULL)
+  {
+    pthread_mutex_unlock (&lock);
+    return (0);
+  }
+
+  memset (&ai_hints, 0, sizeof (ai_hints));
+  ai_hints.ai_flags = 0;
+#ifdef AI_ADDRCONFIG
+  ai_hints.ai_flags |= AI_ADDRCONFIG;
+#endif
+  ai_hints.ai_family = AF_UNSPEC;
+  ai_hints.ai_socktype = SOCK_STREAM;
+
+  ai_res = NULL;
+  status = getaddrinfo (addr, DEFAULT_PORT, &ai_hints, &ai_res);
+  if (status != 0)
+  {
+    pthread_mutex_unlock (&lock);
+    return (status);
+  }
+
+  for (ai_ptr = ai_res; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+  {
+    sd = socket (ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol);
+    if (sd < 0)
+    {
+      status = errno;
+      sd = -1;
+      continue;
+    }
+
+    status = connect (sd, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
+    if (status != 0)
+    {
+      status = errno;
+      close (sd);
+      sd = -1;
+      continue;
+    }
+
+    sh = fdopen (sd, "w+");
+    if (sh == NULL)
+    {
+      status = errno;
+      close (sd);
+      sd = -1;
+      continue;
+    } 
+
+    assert (status == 0);
+    break;
+  } /* for (ai_ptr) */
+  pthread_mutex_unlock (&lock);
+
+  return (status);
 } /* int rrdd_connect */
 
 int rrdd_disconnect (void)
@@ -155,14 +231,29 @@ int rrdd_update (const char *filename, int values_num,
   if (sh == NULL)
   {
     pthread_mutex_unlock (&lock);
-    return (-1);
+    return (ENOTCONN);
   }
 
   status = write (sd, buffer, sizeof (buffer) - buffer_size);
 
+  status = read (sd, buffer, sizeof (buffer));
+  if (status < 0)
+  {
+    status = errno;
+    pthread_mutex_unlock (&lock);
+    return (status);
+  }
+  else if (status == 0)
+  {
+    pthread_mutex_unlock (&lock);
+    return (ENODATA);
+  }
+
+  status = atoi (buffer);
+
   pthread_mutex_unlock (&lock);
 
-  return (0);
+  return (status);
 } /* int rrd_update_daemon */
 
 /*