5ae8d6018d71204c171ec5661fd9b9d59a74b461
[collectd.git] / src / qmail.c
1 /**
2  * src/qmail_queue.c
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License as published by the
6  * Free Software Foundation; only version 2 of the License is applicable.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License along
14  * with this program; if not, write to the Free Software Foundation, Inc.,
15  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
16  *
17  * Authors:
18  *   Alessandro Iurlano <alessandro.iurlano@gmail.com>
19  **/
20
21 #include "collectd.h"
22 #include "common.h"
23 #include "plugin.h"       
24
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <fcntl.h>
28 #include <dirent.h>
29
30
31
32 static char * qmail_base_dir;
33
34 static const char *config_keys[] =
35 {
36         "QmailDir"
37 };
38 static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
39
40
41 static void qmail_queue_submit (gauge_t queued_messages, gauge_t todo_messages)
42 {
43   value_t values[1];
44   value_list_t vl = VALUE_LIST_INIT;
45
46   values[0].gauge = queued_messages;
47
48   vl.values = values;
49   vl.values_len = STATIC_ARRAY_SIZE (values);
50   vl.time = time (NULL);
51   strcpy (vl.host, hostname_g);
52   strcpy (vl.plugin, "qmail_queue");
53   strncpy (vl.plugin_instance, "messages",
54           sizeof (vl.plugin_instance));
55
56
57   plugin_dispatch_values ("gauge", &vl);
58
59   values[0].gauge = todo_messages;
60
61   vl.values = values;
62   vl.values_len = STATIC_ARRAY_SIZE (values);
63   vl.time = time (NULL);
64   strcpy (vl.host, hostname_g);
65   strcpy (vl.plugin, "qmail_queue");
66   strncpy (vl.plugin_instance, "todo",
67           sizeof (vl.plugin_instance));
68
69   plugin_dispatch_values ("gauge", &vl);
70 }
71
72 #define MAX_PATH_LEN 4096
73
74 static int count_files_in_dir(char * path) {
75   char *buf, *ebuf, *cp;
76   off_t base;
77   size_t bufsize;
78   int fd, nbytes;
79   struct stat sb;
80   struct dirent *dp;
81   int count=0;
82
83   if ((fd = open(path, O_RDONLY)) < 0) {
84     ERROR("cannot open %s", path);
85     return -1;
86   }
87   if (fstat(fd, &sb) < 0) {
88     ERROR("fstat");
89     return -1;
90   }
91   bufsize = sb.st_size;
92   if (bufsize < sb.st_blksize)
93     bufsize = sb.st_blksize;
94   if ((buf = malloc(bufsize)) == NULL) {
95     ERROR("cannot malloc %lu bytes", (unsigned long)bufsize);
96     return -1;
97   }
98   while ((nbytes = getdirentries(fd, buf, bufsize, &base)) > 0) {
99     ebuf = buf + nbytes;
100     cp = buf;
101     while (cp < ebuf) {
102       dp = (struct dirent *)cp;
103       if ( (dp->d_fileno!=0) && (dp->d_type!=DT_DIR) ) {
104         count++;
105       }
106       /*
107         if (dp->d_fileno != 0)
108         printf("%s\n", dp->d_name);*/
109       cp += dp->d_reclen;
110     }
111   }
112   if (nbytes < 0) {
113     ERROR("getdirentries");
114     return -1;
115   }
116   free(buf);
117   close(fd);
118
119   return count;
120 }
121 static int count_files_in_tree(char * path) {
122
123   char *buf, *ebuf, *cp;
124   off_t base;
125   size_t bufsize;
126   int fd, nbytes;
127   struct stat sb;
128   struct dirent *dp;
129   int files_in_tree=0;
130   int path_len=strlen(path);
131   if ((fd = open(path, O_RDONLY)) < 0) {
132     WARNING("cannot open %s", path);
133     return -1;
134   }
135   if (fstat(fd, &sb) < 0) {
136     WARNING( "fstat");
137     return -1;
138   }
139   bufsize = sb.st_size;
140   if (bufsize < sb.st_blksize)
141     bufsize = sb.st_blksize;
142   if ((buf = malloc(bufsize)) == NULL) {
143     ERROR("cannot malloc %lu bytes", (unsigned long)bufsize);
144     return -1;
145   }
146   while ((nbytes = getdirentries(fd, buf, bufsize, &base)) > 0) {
147     ebuf = buf + nbytes;
148     cp = buf;
149     while (cp < ebuf) {
150       int ret_value;
151       dp = (struct dirent *)cp;
152       //WARNING("Looking file %s\n", dp->d_name);
153       if ((dp->d_fileno!=0) && (dp->d_type==DT_DIR) && strcmp(dp->d_name,".") && strcmp(dp->d_name,"..") ) {
154         snprintf(path+path_len,MAX_PATH_LEN-path_len,"%s",dp->d_name);
155         ret_value=count_files_in_dir(path);
156         if (ret_value!=-1)
157           files_in_tree+=ret_value;
158         else
159           return -1;
160       }
161       /*
162         if (dp->d_fileno != 0)
163         printf("%s\n", dp->d_name);*/
164       cp += dp->d_reclen;
165     }
166   }
167   if (nbytes < 0) {
168     ERROR("getdirentries");
169     return -1;
170   }
171   free(buf);
172   close(fd);
173   return files_in_tree;  
174 }
175
176 static int queue_len_read (void)
177 {
178   char path[MAX_PATH_LEN];
179   int path_len;
180   //  struct dirent *root_entry, *node_entry;
181   int messages_in_queue, messages_todo;
182   
183   messages_in_queue=0;
184   messages_todo=0;
185   snprintf(path,MAX_PATH_LEN,"%s/queue/mess/",qmail_base_dir);
186   //WARNING("PATH TO READ: %s\n",path);
187   path_len=strlen(path);
188   if (path[path_len]!='/') {
189     strcat(path,"/");
190     path_len=strlen(path);
191   }
192
193   messages_in_queue=count_files_in_tree(path);
194
195   snprintf(path,MAX_PATH_LEN,"%s/queue/todo/",qmail_base_dir);
196   //WARNING("PATH TO READ: %s\n",path);
197   messages_todo=count_files_in_tree(path);
198   if ( (messages_todo!=-1) && (messages_in_queue!=-1) ) {
199     qmail_queue_submit(messages_in_queue,messages_todo);
200     return 0;
201   }
202   else return -1;
203 }
204
205 static int qmail_config (const char *key, const char *val)
206 {
207    if (strcasecmp ("QmailDir", key) == 0)
208      {
209         free(qmail_base_dir);
210         qmail_base_dir=strdup(val);
211         WARNING("Setting Qmail base dir to %s\n", qmail_base_dir);
212      }
213 }
214
215 void module_register (void)
216 {
217   qmail_base_dir=strdup("/var/qmail");
218   plugin_register_config ("qmail_queue", qmail_config,
219                         config_keys, config_keys_num);
220  
221   plugin_register_read ("qmail_queue", queue_len_read);
222 } /* void module_register */