collectd-flush: Determine default socket from configured localstatedir.
[collectd.git] / src / collectd-flush.c
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  **/
21
22 #if HAVE_CONFIG_H
23 # include "config.h"
24 #endif
25
26 #include "libcollectdclient/client.h"
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <errno.h>
31 #include <string.h>
32 #include <unistd.h>
33 #include <getopt.h>
34
35 #define DEFAULT_SOCK LOCALSTATEDIR"/run/"PACKAGE_NAME"-unixsock"
36
37 extern char *optarg;
38
39 static int flush (
40     const char *address,
41     const char *plugin,
42     const char *ident_str,
43     int timeout)
44 {
45   lcc_connection_t *connection;
46   lcc_identifier_t ident;
47
48   /* Pointer which is passed to lcc_flush.
49    * Either a null pointer or it points to ident */
50   lcc_identifier_t *identp;
51   int status;
52
53   connection = NULL;
54   status = lcc_connect(address, &connection);
55   if (status != 0) {
56     fprintf (stderr, "ERROR: Connecting to daemon at %s failed: %s.\n",
57         address, strerror (errno));
58     return 1;
59   }
60
61   identp = NULL;
62   if (ident_str != NULL && *ident_str != '\0') {
63     status = lcc_string_to_identifier (connection, &ident, ident_str);
64     if (status != 0) {
65       fprintf (stderr, "ERROR: Creating and identifier failed: %s.\n",
66           lcc_strerror(connection));
67       LCC_DESTROY (connection);
68
69       return 1;
70     }
71     identp = &ident;
72   }
73
74   status = lcc_flush (connection, plugin, identp, timeout);
75   if (status != 0) {
76     fprintf (stderr, "ERROR: Flushing failed: %s.\n",
77         lcc_strerror (connection));
78     LCC_DESTROY (connection);
79
80     return 1;
81   }
82
83   LCC_DESTROY (connection);
84
85   return 0;
86 }
87
88 static void exit_usage (const char *name, int status) {
89   fprintf ((status == 0) ? stdout : stderr,
90       "Usage: %s [options]\n\n"
91
92       "Available options:\n"
93       "  -s             Path to collectd's UNIX socket.\n"
94       "                 Default: "DEFAULT_SOCK"\n"
95       "  -p <plugin>    Plugin to be flushed.\n"
96       "  -i <id>        Flush data identified by <id> only (see below).\n"
97       "  -t <seconds>   Flush values older than this value only.\n"
98
99       "\n  -h             Display this help and exit.\n"
100
101       "\nIdentfiers:\n\n"
102
103       "An identifier (as accepted by the -i option) has the following\n"
104       "format:\n\n"
105
106       "  [<hostname>/]<plugin>[-<plugin_instance>]/<type>[-<type_instance>]\n\n"
107
108       "Hostname defaults to the local hostname if omitted (e.g., uptime/uptime).\n"
109       "No error is returned if the specified identifier does not exist.\n"
110
111       "\nExample:\n\n"
112
113       "  collectd-flush -p rrdtool -i somehost/cpu-0/cpu-wait\n\n"
114
115       "Flushes all CPU wait RRD values of the first CPU of the local host.\n"
116       "I.e., writes all pending RRD updates of that data-source to disk.\n"
117       , name);
118   exit (status);
119 }
120
121 /*
122  * Count how many occurences there are of a char in a string.
123  */
124 static int charoccurences (const char *str, char chr) {
125   int count = 0;
126   while (*str != '\0') {
127     if (*str == chr) {
128       count++;
129     }
130     str++;
131   }
132
133   return count;
134 }
135
136 int main (int argc, char **argv) {
137   char address[1024] = "unix:"DEFAULT_SOCK;
138   char *plugin = NULL;
139   char ident_str[1024] = "";
140   int timeout = -1;
141   char hostname[1024];
142
143   while (42) {
144     int c;
145
146     c = getopt (argc, argv, "s:p:i:ht:");
147
148     if (c == -1)
149       break;
150
151     switch (c) {
152       case 's':
153         snprintf (address, sizeof (address), "unix:%s", optarg);
154         address[sizeof (address) - 1] = '\0';
155         break;
156       case 'p':
157         plugin = optarg;
158         break;
159       case 'i':
160         if (charoccurences (optarg, '/') == 1) {
161           /* The user has omitted the hostname part of the identifier
162            * (there is only one '/' in the identifier)
163            * Let's add the local hostname */
164           if (gethostname (hostname, sizeof (hostname)) != 0) {
165             fprintf (stderr, "Could not get local hostname: %s", strerror (errno));
166             return 1;
167           }
168           /* Make sure hostname is zero-terminated */
169           hostname[sizeof (hostname) - 1] = '\0';
170           snprintf (ident_str, sizeof (ident_str), "%s/%s", hostname, optarg);
171           /* Make sure ident_str is zero terminated */
172           ident_str[sizeof(ident_str) - 1] = '\0';
173         } else {
174           strncpy (ident_str, optarg, sizeof (ident_str));
175           /* Make sure identifier is zero terminated */
176           ident_str[sizeof (ident_str) - 1] = '\0';
177         }
178         break;
179       case 't':
180         timeout = atoi (optarg);
181         break;
182       case 'h':
183         exit_usage (argv[0], 0);
184         break;
185       default:
186         exit_usage (argv[0], 1);
187     }
188   }
189
190   return flush(address, plugin, ident_str, timeout);
191 }
192
193 /* vim: set sw=2 ts=2 tw=78 expandtab : */
194