1 /**
2 * collectd-flush - src/collectd-flush.c
3 * Copyright (C) 2010 Håkon J Dugstad Johnsen
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; only version 2 of the License is applicable.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 *
18 * Authors:
19 * Håkon J Dugstad Johnsen <hakon-dugstad.johnsen at telenor.com>
20 **/
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <errno.h>
25 #include <string.h>
26 #include <unistd.h>
27 #include <getopt.h>
29 #include "libcollectdclient/client.h"
31 extern char *optarg;
33 static int flush (
34 const char *address,
35 const char *plugin,
36 const char *ident_str,
37 int timeout)
38 {
39 lcc_connection_t *connection;
40 lcc_identifier_t ident;
42 /* Pointer which is passed to lcc_flush.
43 * Either a null pointer or it points to ident */
44 lcc_identifier_t *identp;
45 int status;
47 connection = NULL;
48 status = lcc_connect(address, &connection);
49 if (status != 0) {
50 fprintf (stderr, "ERROR: Connecting to daemon at %s failed: %s.\n",
51 address, strerror (errno));
52 return 1;
53 }
55 identp = NULL;
56 if (ident_str != NULL && *ident_str != '\0') {
57 status = lcc_string_to_identifier (connection, &ident, ident_str);
58 if (status != 0) {
59 fprintf (stderr, "ERROR: Creating and identifier failed: %s.\n",
60 lcc_strerror(connection));
61 LCC_DESTROY (connection);
63 return 1;
64 }
65 identp = &ident;
66 }
68 status = lcc_flush (connection, plugin, identp, timeout);
69 if (status != 0) {
70 fprintf (stderr, "ERROR: Flushing failed: %s.\n",
71 lcc_strerror (connection));
72 LCC_DESTROY (connection);
74 return 1;
75 }
77 LCC_DESTROY (connection);
79 return 0;
80 }
82 static void exit_usage (const char *name, int status) {
83 fprintf ((status == 0) ? stdout : stderr, "Usage: %s [options]\n"
84 "\n"
85 "Valid options are:\n"
86 " -h, --help Display this help message.\n"
87 " -s, --socket=<socket> Path to collectd's UNIX socket. Default: /var/run/collectd-unixsock\n"
88 " -p, --plugin=<plugin> Plugin to flush _to_ (not from). Example: rrdtool\n"
89 " -i, --identifier=<identifier>\n"
90 " Only flush data specified by <identifier>, which has the format: \n"
91 "\n"
92 " [<hostname>/]<plugin>[-<plugin_instance>]/<type>[-<type_instance>]\n"
93 "\n"
94 " Hostname defaults to the local hostname if omitted.\n"
95 " No error is returned if the specified identifier does not exist.\n"
96 " Examples: uptime/uptime\n"
97 " somehost/cpu-0/cpu-wait\n"
98 " -t, --timeout=<timeout> Only flush values older than this timeout.\n", name);
99 exit (status);
100 }
102 /*
103 * Count how many occurences there are of a char in a string.
104 */
105 static int charoccurences (const char *str, char chr) {
106 int count = 0;
107 while (*str != '\0') {
108 if (*str == chr) {
109 count++;
110 }
111 str++;
112 }
114 return count;
115 }
117 int main (int argc, char **argv) {
118 char address[1024] = "unix:/var/run/collectd-unixsock";
119 char *plugin = NULL;
120 char ident_str[1024] = "";
121 int timeout = -1;
122 char hostname[1024];
123 char c;
125 static struct option long_options[] =
126 {
127 {"help", no_argument, 0, 'h'},
128 {"socket", required_argument, 0, 's'},
129 {"plugin", required_argument, 0, 'p'},
130 {"identifier", required_argument, 0, 'i'},
131 {"timeout", required_argument, 0, 't'}
132 };
133 int option_index = 0;
136 while ((c = getopt_long (argc, argv, "s:p:i:ht:", long_options, &option_index)) != -1) {
137 switch (c) {
138 case 's':
139 snprintf (address, sizeof (address), "unix:%s", optarg);
140 break;
141 case 'p':
142 plugin = optarg;
143 break;
144 case 'i':
145 if(charoccurences(optarg, '/') == 1) {
146 /* The user has omitted the hostname part of the identifier
147 * (there is only one '/' in the identifier)
148 * Let's add the local hostname */
149 if(gethostname(hostname, sizeof(hostname)) != 0) {
150 fprintf (stderr, "Could not get local hostname: %s", strerror(errno));
151 return 1;
152 }
153 /* Make sure hostname is zero-terminated */
154 hostname[sizeof(hostname)-1] = '\0';
155 snprintf (ident_str, sizeof (ident_str), "%s/%s", hostname, optarg);
156 /* Make sure ident_str is zero terminated */
157 ident_str[sizeof(ident_str)-1] = '\0';
158 } else {
159 strncpy(ident_str, optarg, sizeof (ident_str));
160 /* Make sure identifier is zero terminated */
161 ident_str[sizeof(ident_str)-1] = '\0';
162 }
163 break;
164 case 't':
165 timeout = atoi (optarg);
166 break;
167 case 'h':
168 exit_usage (argv[0], 0);
169 default:
170 exit_usage (argv[0], 1);
171 }
172 }
174 return flush(address, plugin, ident_str, timeout);
175 }
177 /* vim: set sw=2 ts=2 tw=78 expandtab : */