1
/* $Id: plugin_pop3.c 728 2007-01-14 11:14:38Z michael $
2
* $URL: https://ssl.bulix.org/svn/lcd4linux/trunk/plugin_pop3.c $
4
* Plugin to check POP3 mail accounts
6
* Copyright (C) 2004 Javi Garcia Dominguez (aka Stolz) <javi@gsmlandia.com>
7
* Based on code from pop3check (C) 1999 http://sourceforge.net/projects/pop3check
8
* Simon Liddington <squidly@users.sourceforge.net> is the pop3check current maintainer.
9
* The pop3check original author is Steven Radack <steve@lconn.net>.
11
* Copyright (C) 2004 The LCD4Linux Team <lcd4linux-devel@users.sourceforge.net>
13
* This file is a pluging for LCD4Linux.
15
* LCD4Linux is free software; you can redistribute it and/or modify
16
* it under the terms of the GNU General Public License as published by
17
* the Free Software Foundation; either version 2, or (at your option)
20
* LCD4Linux is distributed in the hope that it will be useful,
21
* but WITHOUT ANY WARRANTY; without even the implied warranty of
22
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23
* GNU General Public License for more details.
25
* You should have received a copy of the GNU General Public License
26
* along with this program; if not, write to the Free Software
27
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
41
#include <sys/socket.h>
42
#include <sys/types.h>
43
/*#include <netinet/in.h> */
55
#define LOCKEDERR "-ERR account is locked by another session or for maintenance, try again."
58
#define MAX_NUM_ACCOUNTS 3
72
/************************ PROTOTYPES ********************************/
74
static struct check *check_node_alloc(void);
75
static void check_node_add(struct check **head, struct check *new_check);
76
static void check_destroy(struct check **head);
79
static void pop3_check_messages(struct check *hi, int verbose);
80
static void pop3_recv_crlf_terminated(int sockfd, char *buf, int size);
83
static int tcp_connect(struct check *hi);
86
/************************ GLOBAL ***********************************/
87
static char Section[] = "Plugin:POP3";
88
static struct check *head = NULL;
89
/********************************************************************/
92
/************************ LIST ***********************************/
94
static struct check *check_node_alloc(void)
96
struct check *new_check;
97
new_check = (struct check *) calloc(1, sizeof(struct check));
98
if (new_check == NULL) {
99
error("[POP3] out of memory\n");
104
static void check_node_add(struct check **head, struct check *new_check)
106
new_check->next = *head;
110
static void check_destroy(struct check **head)
114
iter = (*head)->next;
115
free((*head)->username);
116
free((*head)->password);
117
free((*head)->server);
124
/************************ POP3 ********************************/
125
static void pop3_check_messages(struct check *hi, int verbose)
130
if ((sockfd = tcp_connect(hi)) < 0) {
135
pop3_recv_crlf_terminated(sockfd, buf, sizeof(buf)); /* server greeting */
137
info("[POP3] %s -> %s\n", hi->server, buf);
139
snprintf(buf, sizeof(buf), "USER %s\r\n", hi->username);
140
write(sockfd, buf, strlen(buf));
141
buf[strlen(buf) - 1] = '\0';
143
info("[POP3] %s <- %s\n", hi->server, buf);
144
pop3_recv_crlf_terminated(sockfd, buf, sizeof(buf)); /* response from USER command */
146
info("[POP3] %s -> %s\n", hi->server, buf);
148
snprintf(buf, sizeof(buf), "PASS %s\r\n", hi->password);
149
write(sockfd, buf, strlen(buf));
151
info("[POP3] %s <- PASS ???\n", hi->server);
152
pop3_recv_crlf_terminated(sockfd, buf, sizeof(buf)); /* response from PASS command */
154
info("[POP3] %s -> %s\n", hi->server, buf);
156
if (strncmp(buf, LOCKEDERR, strlen(LOCKEDERR)) == 0) {
161
if (strncmp(buf, POPERR, strlen(POPERR)) == 0) {
162
error("[POP3] error logging into %s\n", hi->server);
163
error("[POP3] server responded: %s\n", buf);
169
snprintf(buf, sizeof(buf), "STAT\r\n");
170
write(sockfd, buf, strlen(buf));
172
info("[POP3] %s <- STAT\n", hi->server);
173
pop3_recv_crlf_terminated(sockfd, buf, sizeof(buf)); /* response from PASS command */
175
info("[POP3] %s -> %s\n", hi->server, buf);
178
hi->messages = atoi(strtok(NULL, " "));
180
snprintf(buf, sizeof(buf), "QUIT\r\n");
181
write(sockfd, buf, strlen(buf));
183
info("[POP3] %s <- QUIT\n", hi->server);
184
pop3_recv_crlf_terminated(sockfd, buf, sizeof(buf)); /* response from QUIT command */
186
info("[POP3] %s -> %s\n", hi->server, buf);
191
static void pop3_recv_crlf_terminated(int sockfd, char *buf, int size)
193
/* receive one line server responses terminated with CRLF */
196
memset(buf, 0, size);
197
while ((pos = strstr(buf, "\r\n")) == NULL)
198
bytes += read(sockfd, buf + bytes, size - bytes);
202
/************************ SOCKET ********************************/
203
static int tcp_connect(struct check *hi)
205
struct sockaddr_in addr;
206
struct hostent *he = gethostbyname(hi->server);
213
error("[POP3] Failed to lookup %s\n", hi->server);
217
memset((char *) &addr, 0, sizeof(struct sockaddr_in));
218
addr.sin_family = AF_INET;
219
memcpy(&(addr.sin_addr.s_addr), he->h_addr, he->h_length);
220
addr.sin_port = htons(hi->port);
222
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
227
if (connect(sockfd, (struct sockaddr *) &addr, sizeof(struct sockaddr)) < 0) {
237
static int getConfig(void)
239
struct check *node = NULL;
241
char *user = (char *) calloc(1, sizeof("user") + sizeof(int));
242
char *password = (char *) calloc(1, sizeof("password") + sizeof(int));
243
char *server = (char *) calloc(1, sizeof("server") + sizeof(int));
244
char *port = (char *) calloc(1, sizeof("port") + sizeof(int));
246
for (i = 1; i <= MAX_NUM_ACCOUNTS; i++) {
248
sprintf(user, "user%d", i);
249
sprintf(password, "password%d", i);
250
sprintf(server, "server%d", i);
251
sprintf(port, "port%d", i);
253
x = cfg_get(Section, server, "");
255
info("[POP3] No '%s.%s' entry from %s, disabling POP3 account #%d", Section, server, cfg_source(), i);
258
node = check_node_alloc();
264
x = cfg_get(Section, user, "");
266
info("[POP3] No '%s.%s' entry from %s, disabling POP3 account #%d", Section, user, cfg_source(), i);
270
x = cfg_get(Section, password, "");
272
info("[POP3] No '%s.%s' entry from %s, disabling POP3 account #%d", Section, password, cfg_source(),
277
if (cfg_number(Section, port, POP3PORT, 1, 65536, &node->port) < 1) {
278
info("[POP3] No '%s.%s' entry from %s, %d will be used for account #%d", Section, port,
279
cfg_source(), POP3PORT, i);
281
check_node_add(&head, node);
291
static int configure_pop3(void)
293
static int configured = 0;
300
/* by now, head should point to a list of all our accounts */
302
info("[POP3] %d POP3 accounts have been succesfully defined", n);
311
static void my_POP3check(RESULT * result, RESULT * check)
313
double param = R2N(check);
314
struct check *node = NULL;
317
if (configure_pop3() < 0) {
319
SetResult(&result, R_NUMBER, &value);
323
for (node = head; node; node = node->next) {
324
if (node->id == param)
327
if (node == NULL) { /*Inexistent account */
330
pop3_check_messages(node, 0);
331
value = (double) node->messages;
333
SetResult(&result, R_NUMBER, &value);
337
int plugin_init_pop3(void)
339
AddFunction("POP3check", 1, my_POP3check);
343
void plugin_exit_pop3(void)
345
check_destroy(&head);