/*
 * Copyright (c) 2003-2005 Sendmail, Inc. and its suppliers.
 *	All rights reserved.
 *
 * By using this file, you agree to the terms and conditions set
 * forth in the LICENSE file which can be found at the top level of
 * the sendmail distribution.
 */

#include "sm/generic.h"
SM_RCSID("@(#)$Id: t-net-cl.c,v 1.7 2005/03/30 20:54:57 ca Exp $")
#include "sm/assert.h"
#include "sm/error.h"
#include "sm/test.h"
#include "sm/io.h"
#include "sm/ctype.h"
#include "smi-net.h"
#include "sm/unixsock.h"

#include <stdio.h>

static char *nsocket = "./cltsrv";

#if 0
#include "timing.h"
#include "t-net-common.c"
#else /* 0 */
#define SM_DEFPORT	2525
static int Verbose;

void
usage(const char *prg)
{
	fprintf(stderr, "usage: %s options\n", prg);
	fprintf(stderr, "-p port: port to use [default: %d]\n", SM_DEFPORT);
	fprintf(stderr, "-r n: read data first (n: timeout in seconds)\n");
	fprintf(stderr, "-u: use UNIX socket instead of INET\n");
	fprintf(stderr, "-U socket: use Unix domain socket [default: %s]\n",
		nsocket);
	fprintf(stderr, "-V: increase verbosity\n");
	exit(0);
}
#endif /* 0 */

/*
**  CLIENT -- write "QUIT\r\n" to localhost:port
**	This is a hack to connect to a SMTP server to figure out whether
**	it is accepting connections (at least).
**
**	Parameters:
**		port -- port
**		net -- use an INET (or LOCAL) socket
**		readfirst -- read first some data
**
**	Returns:
**		none
*/

int
client(int port, bool net, int readfirst)
{
	int fd;
	sm_ret_T ret;
	char buf[] = "QUIT\r\n";

	if (Verbose > 1)
		fprintf(stderr, "clt: connect\n");
	if (net)
		(void) net_client_connect("127.0.0.1", port, &fd);
	else
		(void) unix_client_connect(nsocket, &fd);
	if (Verbose > 1)
		fprintf(stderr, "clt: connected=%d\n", fd);
	SM_TEST(fd >= 0);
	if (fd < 0)
		return 1;

	if (readfirst > 0)
	{
		int r, nfds;
		ssize_t rd;
		fd_set readfds;
		struct timeval timeout;
		char rdbuf[256];

		FD_ZERO(&readfds);
		FD_SET(fd, &readfds);
		nfds = fd + 1;
		timeout.tv_usec = 0;
		timeout.tv_sec = readfirst;
		r = sm_fd_nonblock(fd, true);
		SM_TEST(r == SM_SUCCESS);
		do
		{
			r = select(nfds, &readfds, NULL, &readfds, &timeout);
			if (r > 0 && FD_ISSET(fd, &readfds))
			{
				/* read something... */
				rd = read(fd, rdbuf, sizeof(rdbuf));
			}
		} while (r == -1 && errno == EINTR);
		if (r == 0 || r == -1)
		{
			close(fd);
			return 1;
		}
	}

	ret = write(fd, buf, sizeof(buf));
	SM_TEST(ret == sizeof(buf));
	close(fd);
	return 0;
}

int
main(int argc, char *argv[])
{
	bool clt, any;
	int c, port, readfirst;
	bool net;
	sm_ret_T res;

	opterr = 0;
	clt = true;
	any = false;
	port = SM_DEFPORT;
	Verbose = 0;
	net = true;
	readfirst = 0;
	while ((c = getopt(argc, argv, "p:r:uU:V")) != -1)
	{
		any = true;
		switch (c)
		{
		  case 'p':
			port = atoi(optarg);
			if (port <= 0)
				usage(argv[0]);
			break;
		  case 'r':
			readfirst = atoi(optarg);
			break;
		  case 'u':
			net = false;
			break;
		  case 'U':
			nsocket = strdup(optarg);
			if (nsocket == NULL)
			{
				fprintf(stderr, "out of memory");
				return 1;
			}
			net = false;
			break;
		  case 'V':
			++Verbose;
			break;
		  default:
			usage(argv[0]);
			return 1;
		}
	}
	sm_test_begin(argc, argv, "test net 0");
	res = net_startup();
	SM_TEST(sm_is_success(res));
	if (!sm_is_success(res))
		return sm_test_end();
	c = client(port, net, readfirst);
	net_shutdown();
	sm_test_end();
	return c;
}


syntax highlighted by Code2HTML, v. 0.9.1