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