1a8e2bd9d3e83cee4c589f6d574ecd281295212d
[collectd.git] / src / qmail.c
1 /**
2  * collectd - src/qmail.c
3  * Copyright (C) 2008  Alessandro Iurlano
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  * Author:
19  *   Alessandro Iurlano <alessandro.iurlano at gmail.com>
20  **/
21
22 #include "collectd.h"
23 #include "common.h"
24 #include "plugin.h"       
25
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <fcntl.h>
29 #include <dirent.h>
30
31 #define DEFAULT_BASE_DIR "/var/qmail"
32
33 static char *qmail_base_dir;
34
35 static const char *config_keys[] =
36 {
37   "QmailDir"
38 };
39 static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
40
41 static void qmail_submit (const char *plugin_instance, gauge_t value)
42 {
43   value_t values[1];
44   value_list_t vl = VALUE_LIST_INIT;
45
46   values[0].gauge = value;
47
48   vl.values = values;
49   vl.values_len = STATIC_ARRAY_SIZE (values);
50   vl.time = time (NULL);
51   sstrncpy (vl.host, hostname_g, sizeof (vl.host));
52   sstrncpy (vl.type, "gauge", sizeof (vl.type));
53   sstrncpy (vl.plugin, "qmail", sizeof (vl.plugin));
54   sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
55
56   plugin_dispatch_values (&vl);
57 } /* void qmail_submit */
58
59 static int count_files_in_subtree (const char *path, int depth)
60 {
61   DIR *dh;
62   struct dirent *de;
63   int status;
64
65   char **subdirs;
66   size_t subdirs_num;
67
68   int count;
69   int i;
70
71   dh = opendir (path);
72   if (dh == NULL)
73   {
74     ERROR ("qmail plugin: opendir (%s) failed.", path);
75     return (-1);
76   }
77
78   subdirs = NULL;
79   subdirs_num = 0;
80
81   count = 0;
82   while ((de = readdir (dh)) != NULL)
83   {
84     char abs_path[4096];
85     struct stat statbuf;
86
87     ssnprintf (abs_path, sizeof (abs_path), "%s/%s", path, de->d_name);
88
89     status = lstat (abs_path, &statbuf);
90     if (status != 0)
91     {
92       ERROR ("qmail plugin: stat (%s) failed.", abs_path);
93       continue;
94     }
95
96     if (S_ISREG (statbuf.st_mode))
97     {
98       count++;
99     }
100     else if (S_ISDIR (statbuf.st_mode))
101     {
102       char **temp;
103
104       temp = (char **) realloc (subdirs, sizeof (char *) * (subdirs_num + 1));
105       if (temp == NULL)
106       {
107         ERROR ("qmail plugin: realloc failed.");
108         continue;
109       }
110       subdirs = temp;
111
112       subdirs[subdirs_num] = strdup (abs_path);
113       if (subdirs[subdirs_num] == NULL)
114       {
115         ERROR ("qmail plugin: strdup failed.");
116         continue;
117       }
118       subdirs_num++;
119     }
120   }
121
122   closedir (dh);
123   dh = NULL;
124
125   if (depth > 0)
126   {
127     for (i = 0; i < subdirs_num; i++)
128     {
129       status = count_files_in_subtree (subdirs[i], depth - 1);
130       if (status > 0)
131         count += status;
132     }
133   }
134
135   for (i = 0; i < subdirs_num; i++)
136   {
137     sfree (subdirs[i]);
138   }
139   sfree (subdirs);
140
141   return (count);
142 } /* int count_files_in_subtree */
143
144 static int read_queue_length (const char *queue_name, const char *path)
145 {
146   int64_t num_files;
147
148   num_files = count_files_in_subtree (path, /* depth = */ 1);
149   if (num_files < 0)
150   {
151     ERROR ("qmail plugin: Counting files in `%s' failed.", path);
152     return (-1);
153   }
154
155   qmail_submit (queue_name, (gauge_t) num_files);
156   return (0);
157 } /* int read_queue_length */
158
159 static int queue_len_read (void)
160 {
161   char path[4096];
162   int success;
163   int status;
164
165   success = 0;
166   
167   ssnprintf (path, sizeof (path), "%s/queue/mess",
168       (qmail_base_dir != NULL)
169       ? qmail_base_dir
170       : DEFAULT_BASE_DIR);
171
172   status = read_queue_length ("messages", path);
173   if (status == 0)
174     success++;
175
176   ssnprintf (path, sizeof (path), "%s/queue/todo",
177       (qmail_base_dir != NULL)
178       ? qmail_base_dir
179       : DEFAULT_BASE_DIR);
180
181   status = read_queue_length ("todo", path);
182   if (status == 0)
183     success++;
184
185   if (success > 0)
186     return 0;
187   return (-1);
188 } /* int queue_len_read */
189
190 static int qmail_config (const char *key, const char *val)
191 {
192   if (strcasecmp ("QmailDir", key) == 0)
193   {
194     size_t qmail_base_dir_len;
195
196     sfree (qmail_base_dir);
197     qmail_base_dir = strdup(val);
198     if (qmail_base_dir == NULL)
199     {
200       ERROR ("qmail plugin: strdup failed.");
201       return (1);
202     }
203
204     qmail_base_dir_len = strlen (qmail_base_dir);
205     while ((qmail_base_dir_len > 0)
206         && (qmail_base_dir[qmail_base_dir_len - 1] == '/'))
207     {
208       qmail_base_dir[qmail_base_dir_len - 1] = 0;
209       qmail_base_dir_len--;
210     }
211
212     if (qmail_base_dir_len == 0)
213     {
214       ERROR ("qmail plugin: QmailDir is invalid.");
215       sfree (qmail_base_dir);
216       qmail_base_dir = NULL;
217       return (1);
218     }
219   }
220   else
221   {
222     return (-1);
223   }
224
225   return (0);
226 } /* int qmail_config */
227
228 void module_register (void)
229 {
230   plugin_register_config ("qmail", qmail_config,
231       config_keys, config_keys_num);
232   plugin_register_read ("qmail", queue_len_read);
233 } /* void module_register */
234
235 /*
236  * vim: set sw=2 sts=2 et :
237  */