diff options
Diffstat (limited to 'plugin_pop3.c')
-rw-r--r-- | plugin_pop3.c | 336 |
1 files changed, 336 insertions, 0 deletions
diff --git a/plugin_pop3.c b/plugin_pop3.c new file mode 100644 index 0000000..9d7c35e --- /dev/null +++ b/plugin_pop3.c @@ -0,0 +1,336 @@ +/* $Id: plugin_pop3.c,v 1.1 2004/04/08 11:59:26 reinelt Exp $ + * + * Plugin to check POP3 mail accounts + * + * Copyright 2004 Javi Garcia Dominguez (aka Stolz) <javi@gsmlandia.com> + * Based on code from pop3check (c) 1999 http://sourceforge.net/projects/pop3check + * Simon Liddington <squidly@users.sourceforge.net> is the pop3check current maintainer. + * The pop3check original author is Steven Radack <steve@lconn.net>. + * + * Copyright 2004 The LCD4Linux Team <lcd4linux-devel@users.sourceforge.net> + * + * This file is a pluging for LCD4Linux. + * + * LCD4Linux is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * LCD4Linux is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + * $Log: plugin_pop3.c,v $ + * Revision 1.1 2004/04/08 11:59:26 reinelt + * added plugin_pop3 from Javi + * + */ + + +#include "config.h" +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include "debug.h" +#include "plugin.h" +#include "cfg.h" + +//added +#include <sys/socket.h> +#include <sys/types.h> +//#include <netinet/in.h> +#include <netdb.h> +#include <unistd.h> +//#include <pwd.h> +#include <stdio.h> +// + +#ifdef WITH_DMALLOC +#include <dmalloc.h> +#endif + +//POP 3 +#define POPERR "-ERR" +#define LOCKEDERR "-ERR account is locked by another session or for maintenance, try again." +#define BUFSIZE 8192 +#define POP3PORT 110 +#define MAX_NUM_ACCOUNTS 3 +// + +static struct check { + int id; + char *username; + char *password; + char *server; + int port; + int messages; + struct check *next; +}; + +// ************************ PROTOTYPES ******************************** +// list +static struct check *check_node_alloc(void); +void check_node_add(struct check **head, struct check *new_check); +void check_destroy(struct check **head); +// pop3 +void pop3_check_messages(struct check *hi,int verbose); +void pop3_recv_crlf_terminated(int sockfd, char *buf, int size); +// socket +int tcp_connect(struct check *hi); +// ************************ GLOBAL *********************************** +static char Section[] = "Plugin:POP3"; +static struct check *head = NULL; +// ******************************************************************** +static void my_POP3check (RESULT *result, RESULT *check) +{ + double value; + double param=R2N(check); + + struct check *node = NULL; + + for (node = head; node; node = node->next) + { + if (node->id == param) + break; + } + if (node == NULL) //Inexistent account + value=-1.0; + else + pop3_check_messages(node,0); + value = (double)node->messages; + SetResult(&result, R_NUMBER, &value); +} + +static int getConfig (void) +{ + struct check *node = NULL; + int i,n=0; + char *user= (char *)calloc(1, sizeof("user")+sizeof(int)); + char *password= (char *)calloc(1, sizeof("password")+sizeof(int)); + char *server=(char *)calloc(1, sizeof("server")+sizeof(int)); + char *port= (char *)calloc(1, sizeof("port")+sizeof(int)); + + for (i =1;i <= MAX_NUM_ACCOUNTS; i++) + { + sprintf(user,"user%d",i); + sprintf(password,"password%d",i); + sprintf(server,"server%d",i); + sprintf(port,"port%d",i); + + char *x = cfg_get (Section, server, ""); + if (*x=='\0') + { + info ("[POP3] No '%s.%s' entry from %s, disabling POP3 account #%d", Section, server, cfg_source(),i); + free(x); + } + else + { + node = check_node_alloc(); + node->id = i; + node->server = x; + node->messages = 0; + node->next = NULL; + + x = cfg_get (Section, user, ""); + if (*x=='\0') + { + info ("[POP3] No '%s.%s' entry from %s, disabling POP3 account #%d", Section, user, cfg_source(),i); + free(x); + } + else + { + node->username = x; + x = cfg_get (Section, password, ""); + if (*x=='\0') + { + info ("[POP3] No '%s.%s' entry from %s, disabling POP3 account #%d", Section, password, cfg_source(),i); + free(x); + } + else + { + node->password = x; + if (cfg_number(Section, port, POP3PORT, 1, 65536, &node->port)<1) + info("[POP3] No '%s.%s' entry from %s, %d will be used for account #%d", Section, port, cfg_source(),POP3PORT,i); + check_node_add(&head, node); + n++; + } + } + } + } + return(n); +} + +int plugin_init_pop3(void) +{ + + int n = getConfig(); + // by now, head should point to a list of all our accounts + if (head) + { + info("[POP3] %d POP3 accounts have been succesfully defined",n); + AddFunction ("POP3check", 1, my_POP3check); + } + return 0; +} + +void plugin_exit_pop3(void) +{ + check_destroy(&head); +} + +// ************************ LIST *********************************** +static struct check *check_node_alloc(void) +{ + struct check *new_check; + new_check = (struct check *)calloc(1, sizeof(struct check)); + if (new_check == NULL) + { + error( "[POP3] out of memory\n"); + } + return new_check; +} + + void check_node_add(struct check **head, struct check *new_check) +{ + new_check->next = *head ; + *head = new_check; +} + +void check_destroy(struct check **head) +{ + struct check *iter; + while (*head) + { + iter = (*head)->next; + free((*head)->username); + free((*head)->password); + free((*head)->server); + free(*head); + *head = iter; + } + *head = NULL; +} + +// ************************ POP3 ******************************** +void pop3_check_messages(struct check *hi,int verbose) +{ + char buf[BUFSIZE]; + int sockfd; + + if ((sockfd = tcp_connect(hi)) < 0) + { + hi->messages = -1; + return; + } + + pop3_recv_crlf_terminated(sockfd, buf, sizeof(buf)); /* server greeting */ + if (verbose) + info("[POP3] %s -> %s\n", hi->server, buf); + + snprintf(buf, sizeof(buf), "USER %s\r\n", hi->username); + write(sockfd, buf, strlen(buf)); + buf[strlen(buf)-1] = '\0'; + if (verbose) + info("[POP3] %s <- %s\n", hi->server, buf); + pop3_recv_crlf_terminated(sockfd, buf, sizeof(buf)); /* response from USER command */ + if (verbose) + info("[POP3] %s -> %s\n", hi->server, buf); + + snprintf(buf, sizeof(buf), "PASS %s\r\n", hi->password); + write(sockfd, buf, strlen(buf)); + if (verbose) + info("[POP3] %s <- PASS ???\n", hi->server); + pop3_recv_crlf_terminated(sockfd, buf, sizeof(buf)); /* response from PASS command */ + if (verbose) + info("[POP3] %s -> %s\n", hi->server, buf); + + if (strncmp(buf, LOCKEDERR, strlen(LOCKEDERR)) == 0) + { + hi->messages = -2; + close(sockfd); + return; + } + if (strncmp(buf, POPERR, strlen(POPERR)) == 0) + { + error("[POP3] error logging into %s\n", hi->server); + error("[POP3] server responded: %s\n", buf); + hi->messages = -1; + close(sockfd); + return; + } + + snprintf(buf, sizeof(buf), "STAT\r\n"); + write(sockfd, buf, strlen(buf)); + if (verbose) + info("[POP3] %s <- STAT\n", hi->server); + pop3_recv_crlf_terminated(sockfd, buf, sizeof(buf)); /* response from PASS command */ + if (verbose) + info("[POP3] %s -> %s\n", hi->server, buf); + + strtok(buf, " "); + hi->messages = atoi(strtok(NULL, " ")); + + snprintf(buf, sizeof(buf), "QUIT\r\n"); + write(sockfd, buf, strlen(buf)); + if (verbose) + info("[POP3] %s <- QUIT\n", hi->server); + pop3_recv_crlf_terminated(sockfd, buf, sizeof(buf)); /* response from QUIT command */ + if (verbose) + info("[POP3] %s -> %s\n", hi->server, buf); + + close(sockfd); +} + +void pop3_recv_crlf_terminated(int sockfd, char *buf, int size) +{ +/* receive one line server responses terminated with CRLF */ + char *pos; + int bytes = 0; + memset(buf, 0, size); + while ((pos = strstr(buf, "\r\n")) == NULL) + bytes += read(sockfd, buf+bytes, size-bytes); + *pos = '\0'; +} + +// ************************ SOCKET ******************************** +int tcp_connect(struct check *hi) +{ + struct sockaddr_in addr; + struct hostent *he = gethostbyname(hi->server); + int sockfd; + + if (hi == NULL) + return -1; + + if (!he) + { + error("[POP3] Failed to lookup %s\n",hi->server); + return(-1); + } + + memset((char *)&addr, 0, sizeof(struct sockaddr_in)); + addr.sin_family = AF_INET; + memcpy(&(addr.sin_addr.s_addr), he->h_addr, he->h_length); + addr.sin_port = htons(hi->port); + + if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) + { + perror("socket()"); + return(-1); + } + + if (connect(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr)) < 0) + { + perror("connect()"); + close(sockfd); + return(-1); + } + + return(sockfd); +} |