qmail plugin: Don't recurse into ".", ".." and other directories beginning with a...
[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[PATH_MAX];
85     struct stat statbuf;
86
87     if (de->d_name[0] == '.')
88       continue;
89
90     ssnprintf (abs_path, sizeof (abs_path), "%s/%s", path, de->d_name);
91
92     status = lstat (abs_path, &statbuf);
93     if (status != 0)
94     {
95       ERROR ("qmail plugin: stat (%s) failed.", abs_path);
96       continue;
97     }
98
99     if (S_ISREG (statbuf.st_mode))
100     {
101       count++;
102     }
103     else if (S_ISDIR (statbuf.st_mode))
104     {
105       char **temp;
106
107       temp = (char **) realloc (subdirs, sizeof (char *) * (subdirs_num + 1));
108       if (temp == NULL)
109       {
110         ERROR ("qmail plugin: realloc failed.");
111         continue;
112       }
113       subdirs = temp;
114
115       subdirs[subdirs_num] = strdup (abs_path);
116       if (subdirs[subdirs_num] == NULL)
117       {
118         ERROR ("qmail plugin: strdup failed.");
119         continue;
120       }
121       subdirs_num++;
122     }
123   }
124
125   closedir (dh);
126   dh = NULL;
127
128   if (depth > 0)
129   {
130     for (i = 0; i < subdirs_num; i++)
131     {
132       status = count_files_in_subtree (subdirs[i], depth - 1);
133       if (status > 0)
134         count += status;
135     }
136   }
137
138   for (i = 0; i < subdirs_num; i++)
139   {
140     sfree (subdirs[i]);
141   }
142   sfree (subdirs);
143
144   return (count);
145 } /* int count_files_in_subtree */
146
147 static int read_queue_length (const char *queue_name, const char *path)
148 {
149   int64_t num_files;
150
151   num_files = count_files_in_subtree (path, /* depth = */ 1);
152   if (num_files < 0)
153   {
154     ERROR ("qmail plugin: Counting files in `%s' failed.", path);
155     return (-1);
156   }
157
158   qmail_submit (queue_name, (gauge_t) num_files);
159   return (0);
160 } /* int read_queue_length */
161
162 static int queue_len_read (void)
163 {
164   char path[4096];
165   int success;
166   int status;
167
168   success = 0;
169   
170   ssnprintf (path, sizeof (path), "%s/queue/mess",
171       (qmail_base_dir != NULL)
172       ? qmail_base_dir
173       : DEFAULT_BASE_DIR);
174
175   status = read_queue_length ("messages", path);
176   if (status == 0)
177     success++;
178
179   ssnprintf (path, sizeof (path), "%s/queue/todo",
180       (qmail_base_dir != NULL)
181       ? qmail_base_dir
182       : DEFAULT_BASE_DIR);
183
184   status = read_queue_length ("todo", path);
185   if (status == 0)
186     success++;
187
188   if (success > 0)
189     return 0;
190   return (-1);
191 } /* int queue_len_read */
192
193 static int qmail_config (const char *key, const char *val)
194 {
195   if (strcasecmp ("QmailDir", key) == 0)
196   {
197     size_t qmail_base_dir_len;
198
199     sfree (qmail_base_dir);
200     qmail_base_dir = strdup(val);
201     if (qmail_base_dir == NULL)
202     {
203       ERROR ("qmail plugin: strdup failed.");
204       return (1);
205     }
206
207     qmail_base_dir_len = strlen (qmail_base_dir);
208     while ((qmail_base_dir_len > 0)
209         && (qmail_base_dir[qmail_base_dir_len - 1] == '/'))
210     {
211       qmail_base_dir[qmail_base_dir_len - 1] = 0;
212       qmail_base_dir_len--;
213     }
214
215     if (qmail_base_dir_len == 0)
216     {
217       ERROR ("qmail plugin: QmailDir is invalid.");
218       sfree (qmail_base_dir);
219       qmail_base_dir = NULL;
220       return (1);
221     }
222   }
223   else
224   {
225     return (-1);
226   }
227
228   return (0);
229 } /* int qmail_config */
230
231 void module_register (void)
232 {
233   plugin_register_config ("qmail", qmail_config,
234       config_keys, config_keys_num);
235   plugin_register_read ("qmail", queue_len_read);
236 } /* void module_register */
237
238 /*
239  * vim: set sw=2 sts=2 et :
240  */