/***************************************************************************** POPular -- A POP3 server and proxy for large mail systems $Id: pcheck.c,v 1.12 2001/04/30 15:14:14 sqrt Exp $ http://www.remote.org/jochen/mail/popular/ ****************************************************************************** Copyright (C) 1999-2001 Jochen Topf This program 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 of the License, or (at your option) any later version. This program 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA *****************************************************************************/ #if HAVE_CONFIG_H # include #endif #include "popular.h" /* program name for error messages */ static char *prgname; /***************************************************************************** print_usage() *****************************************************************************/ void print_usage(void) { printf("Usage: %s [OPTION] ... -l|--get-load\n", prgname); printf(" or: %s [OPTION] ... -m|--get-mailbox MAILBOX\n", prgname); printf("Send request for load check or mailbox check to pcheckd.\n"); printf("Options:\n"); printf(" -s, --server=SERVER server host name or IP number (default: 127.0.0.1)\n"); printf(" -p, --port=PORT set server port (default: %d)\n", DEFAULT_PORT_CHECK); printf(" -t, --timeout=TIMEOUT set timeout (default: %d seconds)\n", DEFAULT_TIMEOUT_CHECK); printf(" --help print this help message\n"); printf(" --version print version information\n"); printf("\n"); } /***************************************************************************** main() *****************************************************************************/ int main(int argc, char *argv[]) { int s; struct sockaddr_in sa; char buf[MAXLEN_MAILCHECK]; fd_set fdset; int c, len, ret; int timeout=DEFAULT_TIMEOUT_CHECK; int checkport=DEFAULT_PORT_CHECK; char action=' '; char *server=NULL, *mailbox=NULL; struct hostent *host; static struct option long_options[] = { { "help", no_argument, 0, 0 }, { "version", no_argument, 0, 0 }, { "server", required_argument, 0, 's' }, { "port", required_argument, 0, 'p' }, { "timeout", required_argument, 0, 't' }, { "get-load", no_argument, 0, 'l' }, { "get-mailbox", required_argument, 0, 'm' }, { NULL, 0, 0, 0 } }; prgname = argv[0]; /* program name for error messages */ /*************************************************************************** Parse command line options. ***************************************************************************/ while (1) { int option_index = 0; c = getopt_long(argc, argv, "s:p:t:lm:", long_options, &option_index); if (c == -1) break; switch (c) { case 0: if (! strcmp(long_options[option_index].name, "version")) { printf("pcheck - POPular POP server suite %s\n", VERSION); exit(RCODE_OK); } else if (! strcmp(long_options[option_index].name, "help")) { print_usage(); exit(RCODE_OK); } else { fprintf(stderr, "%s: unknown option: %s\n", prgname, long_options[option_index].name); exit(RCODE_INTERNAL); } break; case 's': /* server */ server = optarg; break; case 'p': /* UDP port */ checkport = get_port(optarg); if (checkport < 0) { fprintf(stderr, "%s: port must be valid UDP port.\n", prgname); exit(RCODE_CMDLINE); } break; case 't': /* timeout */ timeout = get_int(optarg, 1, 60, -1, -2, DEFAULT_TIMEOUT_CHECK); if (timeout < 0) { fprintf(stderr, "%s: timeout must be between 1 and 60 seconds.\n", prgname); exit(RCODE_CMDLINE); } break; case 'l': /* load check */ if (action != ' ') { fprintf(stderr, "%s: only one of -l or -m allowed.\nTry `%s --help' for more information.\n", prgname, prgname); exit(RCODE_CMDLINE); } action = 'L'; break; case 'm': /* mailbox check */ if (action != ' ') { fprintf(stderr, "%s: only one of -l or -m allowed.\nTry `%s --help' for more information.\n", prgname, prgname); exit(RCODE_CMDLINE); } action = 'M'; mailbox = optarg; break; default: fprintf(stderr, "Try `%s --help' for more information.\n", prgname); exit(RCODE_CMDLINE); } } if (action == ' ') { fprintf(stderr, "%s: need either -l or -m. Try `%s --help' for more information.\n", prgname, prgname); exit(RCODE_CMDLINE); } if (optind != argc) { fprintf(stderr, "%s: invalid extra arguments.\nTry `%s --help' for more information.\n", prgname, prgname); exit(RCODE_CMDLINE); } /*************************************************************************** Find host address and "connect" to server. ***************************************************************************/ memset(&sa, 0, sizeof(sa)); sa.sin_family = AF_INET; sa.sin_port = htons(checkport); host = gethostbyname(server ? server : "127.0.0.1"); if (host == NULL || (host->h_addr_list)[0] == NULL) { fprintf(stderr, "%s: unknown host or IP number: '%s'\n", prgname, server ? server : "127.0.0.1"); exit(RCODE_ERR); } else { memcpy(&(sa.sin_addr.s_addr), host->h_addr_list[0], sizeof(sa.sin_addr.s_addr)); } if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { fprintf(stderr, "%s: socket open failed: %s\n", prgname, strerror(errno)); exit(RCODE_ERR); } if (connect(s, (struct sockaddr *) &sa, sizeof(sa)) < 0) { fprintf(stderr, "%s: connect failed: %s\n", prgname, strerror(errno)); exit(RCODE_ERR); } /*************************************************************************** Build request and send it to server. ***************************************************************************/ buf[0] = '*'; buf[1] = action; buf[2] = 0; if (action == 'L') { len = 2; } else if (action == 'M') { len = strlcat(buf, mailbox, sizeof(buf)); if (len >= sizeof(buf)) { fprintf(stderr, "%s: mailbox name too long\n", prgname); exit(RCODE_CMDLINE); } } else { /* should never be here... */ fprintf(stderr, "%s: internal error\n", prgname); exit(RCODE_INTERNAL); } if (send(s, buf, len, 0) != len) { fprintf(stderr, "%s: sendto failed: %s\n", prgname, strerror(errno)); exit(RCODE_ERR); } /*************************************************************************** Wait for answer from server and print it. ***************************************************************************/ memset(buf, 0, sizeof(buf)); FD_ZERO(&fdset); FD_SET(s, &fdset); ret = rel_select(&fdset, timeout, 0); if (ret < 0) { fprintf(stderr, "%s: select failed: %s\n", prgname, strerror(errno)); exit(RCODE_ERR); } if (FD_ISSET(s, &fdset)) { if ((recv(s, buf, sizeof(buf)-1, 0) < 0)) { fprintf(stderr, "%s: recv failed: %s\n", prgname, strerror(errno)); exit(RCODE_ERR); } else { printf("%s", buf); if (buf[0] == '-') exit(RCODE_ERR); else if (!strncmp("+OK 0", buf, 5)) exit(RCODE_OK); else if (!strncmp("+OK 3", buf, 5)) exit(RCODE_OK); else if (!strncmp("+OK 4", buf, 5)) exit(RCODE_OK); exit(RCODE_NO_MAILS); } } fprintf(stderr, "%s: timeout\n", prgname); exit(RCODE_ERR); } /** THE END *****************************************************************/