Example #1
0
int lcc_putval (lcc_connection_t *c, const lcc_value_list_t *vl) /* {{{ */
{
  char ident_str[6 * LCC_NAME_LEN];
  char ident_esc[12 * LCC_NAME_LEN];
  char command[1024] = "";
  lcc_response_t res;
  int status;
  size_t i;

  if ((c == NULL) || (vl == NULL) || (vl->values_len < 1)
      || (vl->values == NULL) || (vl->values_types == NULL))
  {
    lcc_set_errno (c, EINVAL);
    return (-1);
  }

  status = lcc_identifier_to_string (c, ident_str, sizeof (ident_str),
      &vl->identifier);
  if (status != 0)
    return (status);

  SSTRCATF (command, "PUTVAL %s",
      lcc_strescape (ident_esc, ident_str, sizeof (ident_esc)));

  if (vl->interval > 0)
    SSTRCATF (command, " interval=%i", vl->interval);

  if (vl->time > 0)
    SSTRCATF (command, "%u", (unsigned int) vl->time);
  else
    SSTRCAT (command, "N");

  for (i = 0; i < vl->values_len; i++)
  {
    if (vl->values_types[i] == LCC_TYPE_COUNTER)
      SSTRCATF (command, ":%"PRIu64, vl->values[i].counter);
    else if (vl->values_types[i] == LCC_TYPE_GAUGE)
    {
      if (isnan (vl->values[i].gauge))
        SSTRCPY (command, ":U");
      else
        SSTRCATF (command, ":%g", vl->values[i].gauge);
    }
  } /* for (i = 0; i < vl->values_len; i++) */

  status = lcc_sendreceive (c, command, &res);
  if (status != 0)
    return (status);

  if (res.status != 0)
  {
    LCC_SET_ERRSTR (c, "Server error: %s", res.message);
    lcc_response_free (&res);
    return (-1);
  }

  lcc_response_free (&res);
  return (0);
} /* }}} int lcc_putval */
Example #2
0
static int lcc_open_unixsocket (lcc_connection_t *c, const char *path) /* {{{ */
{
  struct sockaddr_un sa;
  int fd;
  int status;

  assert (c != NULL);
  assert (c->fh == NULL);
  assert (path != NULL);

  /* Don't use PF_UNIX here, because it's broken on Mac OS X (10.4, possibly
   * others). */
  fd = socket (AF_UNIX, SOCK_STREAM, /* protocol = */ 0);
  if (fd < 0)
  {
    lcc_set_errno (c, errno);
    return (-1);
  }

  memset (&sa, 0, sizeof (sa));
  sa.sun_family = AF_UNIX;
  strncpy (sa.sun_path, path, sizeof (sa.sun_path) - 1);

  status = connect (fd, (struct sockaddr *) &sa, sizeof (sa));
  if (status != 0)
  {
    lcc_set_errno (c, errno);
    close (fd);
    return (-1);
  }

  c->fh = fdopen (fd, "r+");
  if (c->fh == NULL)
  {
    lcc_set_errno (c, errno);
    close (fd);
    return (-1);
  }

  return (0);
} /* }}} int lcc_open_unixsocket */
Example #3
0
int lcc_flush (lcc_connection_t *c, const char *plugin, /* {{{ */
    lcc_identifier_t *ident, int timeout)
{
  char command[1024] = "";
  lcc_response_t res;
  int status;

  if (c == NULL)
  {
    lcc_set_errno (c, EINVAL);
    return (-1);
  }

  SSTRCPY (command, "FLUSH");

  if (timeout > 0)
    SSTRCATF (command, " timeout=%i", timeout);

  if (plugin != NULL)
  {
    char buffer[2 * LCC_NAME_LEN];
    SSTRCATF (command, " plugin=%s",
        lcc_strescape (buffer, plugin, sizeof (buffer)));
  }

  if (ident != NULL)
  {
    char ident_str[6 * LCC_NAME_LEN];
    char ident_esc[12 * LCC_NAME_LEN];

    status = lcc_identifier_to_string (c, ident_str, sizeof (ident_str), ident);
    if (status != 0)
      return (status);

    SSTRCATF (command, " identifier=%s",
        lcc_strescape (ident_esc, ident_str, sizeof (ident_esc)));
  }

  status = lcc_sendreceive (c, command, &res);
  if (status != 0)
    return (status);

  if (res.status != 0)
  {
    LCC_SET_ERRSTR (c, "Server error: %s", res.message);
    lcc_response_free (&res);
    return (-1);
  }

  lcc_response_free (&res);
  return (0);
} /* }}} int lcc_flush */
Example #4
0
int lcc_sort_identifiers (lcc_connection_t *c, /* {{{ */
    lcc_identifier_t *idents, size_t idents_num)
{
  if (idents == NULL)
  {
    lcc_set_errno (c, EINVAL);
    return (-1);
  }

  qsort (idents, idents_num, sizeof (*idents),
      (void *) lcc_identifier_compare);
  return (0);
} /* }}} int lcc_sort_identifiers */
Example #5
0
static int lcc_send (lcc_connection_t *c, const char *command) /* {{{ */
{
  int status;

  LCC_DEBUG ("send:    --> %s\n", command);

  status = fprintf (c->fh, "%s\r\n", command);
  if (status < 0)
  {
    lcc_set_errno (c, errno);
    return (-1);
  }

  return (0);
} /* }}} int lcc_send */
Example #6
0
int lcc_identifier_to_string (lcc_connection_t *c, /* {{{ */
    char *string, size_t string_size, const lcc_identifier_t *ident)
{
  if ((string == NULL) || (string_size < 6) || (ident == NULL))
  {
    lcc_set_errno (c, EINVAL);
    return (-1);
  }

  if (ident->plugin_instance[0] == 0)
  {
    if (ident->type_instance[0] == 0)
      snprintf (string, string_size, "%s/%s/%s",
          ident->host,
          ident->plugin,
          ident->type);
    else
      snprintf (string, string_size, "%s/%s/%s-%s",
          ident->host,
          ident->plugin,
          ident->type,
          ident->type_instance);
  }
  else
  {
    if (ident->type_instance[0] == 0)
      snprintf (string, string_size, "%s/%s-%s/%s",
          ident->host,
          ident->plugin,
          ident->plugin_instance,
          ident->type);
    else
      snprintf (string, string_size, "%s/%s-%s/%s-%s",
          ident->host,
          ident->plugin,
          ident->plugin_instance,
          ident->type,
          ident->type_instance);
  }

  string[string_size - 1] = 0;
  return (0);
} /* }}} int lcc_identifier_to_string */
Example #7
0
static int lcc_sendreceive (lcc_connection_t *c, /* {{{ */
    const char *command, lcc_response_t *ret_res)
{
  lcc_response_t res;
  int status;

  if (c->fh == NULL)
  {
    lcc_set_errno (c, EBADF);
    return (-1);
  }

  status = lcc_send (c, command);
  if (status != 0)
    return (status);

  memset (&res, 0, sizeof (res));
  status = lcc_receive (c, &res);
  if (status == 0)
    memcpy (ret_res, &res, sizeof (*ret_res));

  return (status);
} /* }}} int lcc_sendreceive */
Example #8
0
int lcc_string_to_identifier (lcc_connection_t *c, /* {{{ */
    lcc_identifier_t *ident, const char *string)
{
  char *string_copy;
  char *host;
  char *plugin;
  char *plugin_instance;
  char *type;
  char *type_instance;

  string_copy = strdup (string);
  if (string_copy == NULL)
  {
    lcc_set_errno (c, ENOMEM);
    return (-1);
  }

  host = string_copy;
  plugin = strchr (host, '/');
  if (plugin == NULL)
  {
    LCC_SET_ERRSTR (c, "Malformed identifier string: %s", string);
    free (string_copy);
    return (-1);
  }
  *plugin = 0;
  plugin++;

  type = strchr (plugin, '/');
  if (type == NULL)
  {
    LCC_SET_ERRSTR (c, "Malformed identifier string: %s", string);
    free (string_copy);
    return (-1);
  }
  *type = 0;
  type++;

  plugin_instance = strchr (plugin, '-');
  if (plugin_instance != NULL)
  {
    *plugin_instance = 0;
    plugin_instance++;
  }

  type_instance = strchr (type, '-');
  if (type_instance != NULL)
  {
    *type_instance = 0;
    type_instance++;
  }

  memset (ident, 0, sizeof (*ident));

  SSTRCPY (ident->host, host);
  SSTRCPY (ident->plugin, plugin);
  if (plugin_instance != NULL)
    SSTRCPY (ident->plugin_instance, plugin_instance);
  SSTRCPY (ident->type, type);
  if (type_instance != NULL)
    SSTRCPY (ident->type_instance, type_instance);

  free (string_copy);
  return (0);
} /* }}} int lcc_string_to_identifier */
Example #9
0
int lcc_listval (lcc_connection_t *c, /* {{{ */
    lcc_identifier_t **ret_ident, size_t *ret_ident_num)
{
  lcc_response_t res;
  size_t i;
  int status;

  lcc_identifier_t *ident;
  size_t ident_num;

  if (c == NULL)
    return (-1);

  if ((ret_ident == NULL) || (ret_ident_num == NULL))
  {
    lcc_set_errno (c, EINVAL);
    return (-1);
  }

  status = lcc_sendreceive (c, "LISTVAL", &res);
  if (status != 0)
    return (status);

  if (res.status != 0)
  {
    LCC_SET_ERRSTR (c, "Server error: %s", res.message);
    lcc_response_free (&res);
    return (-1);
  }

  ident_num = res.lines_num;
  ident = (lcc_identifier_t *) malloc (ident_num * sizeof (*ident));
  if (ident == NULL)
  {
    lcc_response_free (&res);
    lcc_set_errno (c, ENOMEM);
    return (-1);
  }

  for (i = 0; i < res.lines_num; i++)
  {
    char *time_str;
    char *ident_str;

    /* First field is the time. */
    time_str = res.lines[i];

    /* Set `ident_str' to the beginning of the second field. */
    ident_str = time_str;
    while ((*ident_str != ' ') && (*ident_str != '\t') && (*ident_str != 0))
      ident_str++;
    while ((*ident_str == ' ') || (*ident_str == '\t'))
    {
      *ident_str = 0;
      ident_str++;
    }

    if (*ident_str == 0)
    {
      lcc_set_errno (c, EILSEQ);
      status = -1;
      break;
    }

    status = lcc_string_to_identifier (c, ident + i, ident_str);
    if (status != 0)
      break;
  }

  lcc_response_free (&res);

  if (status != 0)
  {
    free (ident);
    return (-1);
  }

  *ret_ident = ident;
  *ret_ident_num = ident_num;

  return (0);
} /* }}} int lcc_listval */
Example #10
0
int lcc_getval (lcc_connection_t *c, lcc_identifier_t *ident, /* {{{ */
    size_t *ret_values_num, gauge_t **ret_values, char ***ret_values_names)
{
  char ident_str[6 * LCC_NAME_LEN];
  char ident_esc[12 * LCC_NAME_LEN];
  char command[14 * LCC_NAME_LEN];

  lcc_response_t res;
  size_t   values_num;
  gauge_t *values = NULL;
  char   **values_names = NULL;

  size_t i;
  int status;

  if (c == NULL)
    return (-1);

  if (ident == NULL)
  {
    lcc_set_errno (c, EINVAL);
    return (-1);
  }

  /* Build a commend with an escaped version of the identifier string. */
  status = lcc_identifier_to_string (c, ident_str, sizeof (ident_str), ident);
  if (status != 0)
    return (status);

  snprintf (command, sizeof (command), "GETVAL %s",
      lcc_strescape (ident_esc, ident_str, sizeof (ident_esc)));
  command[sizeof (command) - 1] = 0;

  /* Send talk to the daemon.. */
  status = lcc_sendreceive (c, command, &res);
  if (status != 0)
    return (status);

  if (res.status != 0)
  {
    LCC_SET_ERRSTR (c, "Server error: %s", res.message);
    lcc_response_free (&res);
    return (-1);
  }

  values_num = res.lines_num;

#define BAIL_OUT(e) do { \
  lcc_set_errno (c, (e)); \
  free (values); \
  if (values_names != NULL) { \
    for (i = 0; i < values_num; i++) { \
      free (values_names[i]); \
    } \
  } \
  free (values_names); \
  lcc_response_free (&res); \
  return (-1); \
} while (0)

  /* If neither the values nor the names are requested, return here.. */
  if ((ret_values == NULL) && (ret_values_names == NULL))
  {
    if (ret_values_num != NULL)
      *ret_values_num = values_num;
    lcc_response_free (&res);
    return (0);
  }

  /* Allocate space for the values */
  if (ret_values != NULL)
  {
    values = (gauge_t *) malloc (values_num * sizeof (*values));
    if (values == NULL)
      BAIL_OUT (ENOMEM);
  }

  if (ret_values_names != NULL)
  {
    values_names = (char **) calloc (values_num, sizeof (*values_names));
    if (values_names == NULL)
      BAIL_OUT (ENOMEM);
  }

  for (i = 0; i < res.lines_num; i++)
  {
    char *key;
    char *value;
    char *endptr;

    key = res.lines[i];
    value = strchr (key, '=');
    if (value == NULL)
      BAIL_OUT (EILSEQ);

    *value = 0;
    value++;

    if (values != NULL)
    {
      endptr = NULL;
      errno = 0;
      values[i] = strtod (value, &endptr);

      if ((endptr == value) || (errno != 0))
        BAIL_OUT (errno);
    }

    if (values_names != NULL)
    {
      values_names[i] = strdup (key);
      if (values_names[i] == NULL)
        BAIL_OUT (ENOMEM);
    }
  } /* for (i = 0; i < res.lines_num; i++) */

  if (ret_values_num != NULL)
    *ret_values_num = values_num;
  if (ret_values != NULL)
    *ret_values = values;
  if (ret_values_names != NULL)
    *ret_values_names = values_names;

  lcc_response_free (&res);

  return (0);
} /* }}} int lcc_getval */
Example #11
0
static int lcc_open_netsocket (lcc_connection_t *c, /* {{{ */
    const char *addr_orig)
{
  struct addrinfo ai_hints;
  struct addrinfo *ai_res;
  struct addrinfo *ai_ptr;
  char addr_copy[NI_MAXHOST];
  char *addr;
  char *port;
  int fd;
  int status;

  assert (c != NULL);
  assert (c->fh == NULL);
  assert (addr_orig != NULL);

  strncpy(addr_copy, addr_orig, sizeof(addr_copy));
  addr_copy[sizeof(addr_copy) - 1] = '\0';
  addr = addr_copy;

  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;

  port = NULL;
  if (*addr == '[') /* IPv6+port format */
  {
    /* `addr' is something like "[2001:780:104:2:211:24ff:feab:26f8]:12345" */
    addr++;

    port = strchr (addr, ']');
    if (port == NULL)
    {
      LCC_SET_ERRSTR (c, "malformed address: %s", addr_orig);
      return (-1);
    }
    *port = 0;
    port++;

    if (*port == ':')
      port++;
    else if (*port == 0)
      port = NULL;
    else
    {
      LCC_SET_ERRSTR (c, "garbage after address: %s", port);
      return (-1);
    }
  } /* if (*addr = ']') */
  else if (strchr (addr, '.') != NULL) /* Hostname or IPv4 */
  {
    port = strrchr (addr, ':');
    if (port != NULL)
    {
      *port = 0;
      port++;
    }
  }

  ai_res = NULL;
  status = getaddrinfo (addr,
                        port == NULL ? LCC_DEFAULT_PORT : port,
                        &ai_hints, &ai_res);
  if (status != 0)
  {
    LCC_SET_ERRSTR (c, "getaddrinfo: %s", gai_strerror (status));
    return (-1);
  }

  for (ai_ptr = ai_res; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
  {
    fd = socket (ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol);
    if (fd < 0)
    {
      status = errno;
      continue;
    }

    status = connect (fd, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
    if (status != 0)
    {
      status = errno;
      close (fd);
      continue;
    }

    c->fh = fdopen (fd, "r+");
    if (c->fh == NULL)
    {
      status = errno;
      close (fd);
      continue;
    }

    assert (status == 0);
    break;
  } /* for (ai_ptr) */

  if (status != 0)
  {
    lcc_set_errno (c, status);
    return (-1);
  }

  return (0);
} /* }}} int lcc_open_netsocket */
Example #12
0
static int lcc_receive (lcc_connection_t *c, /* {{{ */
    lcc_response_t *ret_res)
{
  lcc_response_t res;
  char *ptr;
  char buffer[4096];
  size_t i;

  memset (&res, 0, sizeof (res));

  /* Read the first line, containing the status and a message */
  ptr = fgets (buffer, sizeof (buffer), c->fh);
  if (ptr == NULL)
  {
    lcc_set_errno (c, errno);
    return (-1);
  }
  lcc_chomp (buffer);
  LCC_DEBUG ("receive: <-- %s\n", buffer);

  /* Convert the leading status to an integer and make `ptr' to point to the
   * beginning of the message. */
  ptr = NULL;
  errno = 0;
  res.status = (int) strtol (buffer, &ptr, 0);
  if ((errno != 0) || (ptr == &buffer[0]))
  {
    lcc_set_errno (c, errno);
    return (-1);
  }

  /* Skip white spaces after the status number */
  while ((*ptr == ' ') || (*ptr == '\t'))
    ptr++;

  /* Now copy the message. */
  strncpy (res.message, ptr, sizeof (res.message));
  res.message[sizeof (res.message) - 1] = 0;

  /* Error or no lines follow: We're done. */
  if (res.status <= 0)
  {
    memcpy (ret_res, &res, sizeof (res));
    return (0);
  }

  /* Allocate space for the char-pointers */
  res.lines_num = (size_t) res.status;
  res.status = 0;
  res.lines = (char **) malloc (res.lines_num * sizeof (char *));
  if (res.lines == NULL)
  {
    lcc_set_errno (c, ENOMEM);
    return (-1);
  }

  /* Now receive all the lines */
  for (i = 0; i < res.lines_num; i++)
  {
    ptr = fgets (buffer, sizeof (buffer), c->fh);
    if (ptr == NULL)
    {
      lcc_set_errno (c, errno);
      break;
    }
    lcc_chomp (buffer);
    LCC_DEBUG ("receive: <-- %s\n", buffer);

    res.lines[i] = strdup (buffer);
    if (res.lines[i] == NULL)
    {
      lcc_set_errno (c, ENOMEM);
      break;
    }
  }

  /* Check if the for-loop exited with an error. */
  if (i < res.lines_num)
  {
    while (i > 0)
    {
      i--;
      free (res.lines[i]);
    }
    free (res.lines);
    return (-1);
  }

  memcpy (ret_res, &res, sizeof (res));
  return (0);
} /* }}} int lcc_receive */