src/Makefile: Build and ship (in the tarball) the collectd-flush manpage.
[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
118       "\n"PACKAGE" "VERSION", http://collectd.org/\n"
119       "by Florian octo Forster <octo@verplant.org>\n"
120       "for contributions see `AUTHORS'\n"
121       , name);
122   exit (status);
123 }
124
125 /*
126  * Count how many occurences there are of a char in a string.
127  */
128 static int charoccurences (const char *str, char chr) {
129   int count = 0;
130   while (*str != '\0') {
131     if (*str == chr) {
132       count++;
133     }
134     str++;
135   }
136
137   return count;
138 }
139
140 int main (int argc, char **argv) {
141   char address[1024] = "unix:"DEFAULT_SOCK;
142   char *plugin = NULL;
143   char ident_str[1024] = "";
144   int timeout = -1;
145   char hostname[1024];
146
147   while (42) {
148     int c;
149
150     c = getopt (argc, argv, "s:p:i:ht:");
151
152     if (c == -1)
153       break;
154
155     switch (c) {
156       case 's':
157         snprintf (address, sizeof (address), "unix:%s", optarg);
158         address[sizeof (address) - 1] = '\0';
159         break;
160       case 'p':
161         plugin = optarg;
162         break;
163       case 'i':
164         if (charoccurences (optarg, '/') == 1) {
165           /* The user has omitted the hostname part of the identifier
166            * (there is only one '/' in the identifier)
167            * Let's add the local hostname */
168           if (gethostname (hostname, sizeof (hostname)) != 0) {
169             fprintf (stderr, "Could not get local hostname: %s", strerror (errno));
170             return 1;
171           }
172           /* Make sure hostname is zero-terminated */
173           hostname[sizeof (hostname) - 1] = '\0';
174           snprintf (ident_str, sizeof (ident_str), "%s/%s", hostname, optarg);
175           /* Make sure ident_str is zero terminated */
176           ident_str[sizeof(ident_str) - 1] = '\0';
177         } else {
178           strncpy (ident_str, optarg, sizeof (ident_str));
179           /* Make sure identifier is zero terminated */
180           ident_str[sizeof (ident_str) - 1] = '\0';
181         }
182         break;
183       case 't':
184         timeout = atoi (optarg);
185         break;
186       case 'h':
187         exit_usage (argv[0], 0);
188         break;
189       default:
190         exit_usage (argv[0], 1);
191     }
192   }
193
194   return flush(address, plugin, ident_str, timeout);
195 }
196
197 /* vim: set sw=2 ts=2 tw=78 expandtab : */
198