types_list: fix carriage return sign
[collectd.git] / src / protocols.c
1 /**
2  * collectd - src/protocols.c
3  * Copyright (C) 2009  Florian octo Forster
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  *   Florian octo Forster <octo at verplant.org>
20  **/
21
22 #include "collectd.h"
23 #include "common.h"
24 #include "plugin.h"
25 #include "utils_ignorelist.h"
26
27 #if !KERNEL_LINUX
28 # error "No applicable input method."
29 #endif
30
31 #define SNMP_FILE "/proc/net/snmp"
32 #define NETSTAT_FILE "/proc/net/netstat"
33
34 /*
35  * Global variables
36  */
37 static const char *config_keys[] =
38 {
39   "Value",
40   "IgnoreSelected",
41 };
42 static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
43
44 static ignorelist_t *values_list = NULL;
45
46 /* 
47  * Functions
48  */
49 static void submit (const char *protocol_name,
50     const char *str_key, const char *str_value)
51 {
52   value_t values[1];
53   value_list_t vl = VALUE_LIST_INIT;
54
55   char *tmp_ptr;
56
57   errno = 0;
58   tmp_ptr = NULL;
59   values[0].counter = (counter_t) strtoll (str_value, &tmp_ptr,
60       /* base = */ 0);
61   if ((errno != 0) || (tmp_ptr == str_value))
62   {
63     ERROR ("protocols plugin: Parsing string as integer failed: %s",
64         str_value);
65     return;
66   }
67
68   vl.values = values;
69   vl.values_len = 1;
70   sstrncpy (vl.host, hostname_g, sizeof (vl.host));
71   sstrncpy (vl.plugin, "protocols", sizeof (vl.plugin));
72   sstrncpy (vl.plugin_instance, protocol_name, sizeof (vl.plugin_instance));
73   sstrncpy (vl.type, "protocol_counter", sizeof (vl.type));
74   sstrncpy (vl.type_instance, str_key, sizeof (vl.type_instance));
75
76   plugin_dispatch_values (&vl);
77 } /* void submit */
78
79 static int read_file (const char *path)
80 {
81   FILE *fh;
82   char key_buffer[4096];
83   char value_buffer[4096];
84   char *key_ptr;
85   char *value_ptr;
86   char *key_fields[256];
87   char *value_fields[256];
88   int key_fields_num;
89   int value_fields_num;
90   int status;
91   int i;
92
93   fh = fopen (path, "r");
94   if (fh == NULL)
95   {
96     ERROR ("protocols plugin: fopen (%s) failed: %s.",
97         path, sstrerror (errno, key_buffer, sizeof (key_buffer)));
98     return (-1);
99   }
100
101   status = -1;
102   while (42)
103   {
104     clearerr (fh);
105     key_ptr = fgets (key_buffer, sizeof (key_buffer), fh);
106     if (key_ptr == NULL)
107     {
108       if (feof (fh) != 0)
109       {
110         status = 0;
111         break;
112       }
113       else if (ferror (fh) != 0)
114       {
115         ERROR ("protocols plugin: Reading from %s failed.", path);
116         break;
117       }
118       else
119       {
120         ERROR ("protocols plugin: fgets failed for an unknown reason.");
121         break;
122       }
123     } /* if (key_ptr == NULL) */
124
125     value_ptr = fgets (value_buffer, sizeof (value_buffer), fh);
126     if (value_ptr == NULL)
127     {
128       ERROR ("protocols plugin: read_file (%s): Could not read values line.",
129           path);
130       break;
131     }
132
133     key_ptr = strchr (key_buffer, ':');
134     if (key_ptr == NULL)
135     {
136       ERROR ("protocols plugin: Could not find protocol name in keys line.");
137       break;
138     }
139     *key_ptr = 0;
140     key_ptr++;
141
142     value_ptr = strchr (value_buffer, ':');
143     if (value_ptr == NULL)
144     {
145       ERROR ("protocols plugin: Could not find protocol name "
146           "in values line.");
147       break;
148     }
149     *value_ptr = 0;
150     value_ptr++;
151
152     if (strcmp (key_buffer, value_buffer) != 0)
153     {
154       ERROR ("protocols plugin: Protocol names in keys and values lines "
155           "don't match: `%s' vs. `%s'.",
156           key_buffer, value_buffer);
157       break;
158     }
159
160
161     key_fields_num = strsplit (key_ptr,
162         key_fields, STATIC_ARRAY_SIZE (key_fields));
163     value_fields_num = strsplit (value_ptr,
164         value_fields, STATIC_ARRAY_SIZE (value_fields));
165
166     if (key_fields_num != value_fields_num)
167     {
168       ERROR ("protocols plugin: Number of fields in keys and values lines "
169           "don't match: %i vs %i.",
170           key_fields_num, value_fields_num);
171       break;
172     }
173
174     for (i = 0; i < key_fields_num; i++)
175     {
176       if (values_list != NULL)
177       {
178         char match_name[2 * DATA_MAX_NAME_LEN];
179
180         ssnprintf (match_name, sizeof (match_name), "%s:%s",
181             key_buffer, key_fields[i]);
182
183         if (ignorelist_match (values_list, match_name))
184           continue;
185       } /* if (values_list != NULL) */
186
187       submit (key_buffer, key_fields[i], value_fields[i]);
188     } /* for (i = 0; i < key_fields_num; i++) */
189   } /* while (42) */
190
191   fclose (fh);
192
193   return (status);
194 } /* int read_file */
195
196 static int protocols_read (void)
197 {
198   int status;
199   int success = 0;
200
201   status = read_file (SNMP_FILE);
202   if (status == 0)
203     success++;
204
205   status = read_file (NETSTAT_FILE);
206   if (status == 0)
207     success++;
208
209   if (success == 0)
210     return (-1);
211
212   return (0);
213 } /* int protocols_read */
214
215 static int protocols_config (const char *key, const char *value)
216 {
217   if (values_list == NULL)
218     values_list = ignorelist_create (/* invert = */ 1);
219
220   if (strcasecmp (key, "Value") == 0)
221   {
222     ignorelist_add (values_list, value);
223   }
224   else if (strcasecmp (key, "IgnoreSelected") == 0)
225   {
226     int invert = 1;
227     if (IS_TRUE (value))
228       invert = 0;
229     ignorelist_set_invert (values_list, invert);
230   }
231   else
232   {
233     return (-1);
234   }
235
236   return (0);
237 } /* int protocols_config */
238
239 void module_register (void)
240 {
241   plugin_register_config ("protocols", protocols_config,
242       config_keys, config_keys_num);
243   plugin_register_read ("protocols", protocols_read);
244 } /* void module_register */
245
246 /* vim: set sw=2 sts=2 et : */