/*****************************************************************************
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 <jochen@remote.org>
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 <config.h>
#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 *****************************************************************/
syntax highlighted by Code2HTML, v. 0.9.1