/*
 * 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-passfd.c,v 1.6 2006/10/05 04:27:35 ca Exp $")
#include "sm/assert.h"
#include "sm/error.h"
#include "sm/test.h"
#include "sm/io.h"
#include "sm/ctype.h"
#include "sm/fcntl.h"
#include "prterr.h"
#include "sm/unixsock.h"
#include "sm/cmsg.h"

#include <stdio.h>

/*
**  Open a listening fd and pass it to another program.
**	write_fd()
*/

extern char *optarg;
extern int optind;
extern int optopt;
extern int opterr;

static int Verbose;
static short port = 1234;
static char *sockspec;
static char *exsock;

#define SM_BUFSIZE	8192

#define NSOCKET	"./rdwrfd"	/* socket to use to exchange fd */

#if MTA_USE_STATETHREADS
# define sm_sock_close(fd)	un_st_socket_close(fd)
# define SM_INVALID_SOCKET	NULL
# define SM_IS_INVALID_SOCKET(fd)	((fd) == NULL)
#else /* MTA_USE_STATETHREADS */
# define sm_sock_close(fd)	close(fd)
# define SM_INVALID_SOCKET	(-1)
# define SM_IS_INVALID_SOCKET(fd)	((fd) < 0)
#endif /* MTA_USE_STATETHREADS */

void
usage(const char *prg)
{
	fprintf(stderr, "usage: %s options\n", prg);
	fprintf(stderr, "-L socket-spec: open socket-spec for listening\n");
	fprintf(stderr, "-V: increase verbosity\n");
	exit(0);
}

/*
**  CLIENT -- send fd
**
**	Parameters:
**		none
**
**	Returns:
**		none
*/

void
client()
{
	int rdfd;
	fd_T fd;
	int res;
	char buf[SM_BUFSIZE];

	if (Verbose > 1)
		fprintf(stderr, "clt: connect\n");

	/* connect to server */
	(void) unix_client_connect(exsock, &fd);
	if (Verbose > 1)
		fprintf(stderr, "clt: connected=%d\n", fd);
	SM_TEST(fd >= 0);
	if (fd < 0)
		return;

	/* open file descriptor that will be sent to server */
	rdfd = net_server_listen(sockspec, port, 10);
	SM_TEST(rdfd >= 0);
	if (rdfd < 0)
		return;

	sm_snprintf(buf, sizeof(buf), "Send %d\n", rdfd);

	/* send rdfd to server */
	res = sm_write_fd(fd, (void *) buf, 1, rdfd);
	SM_TEST(res >= 0);
	if (sm_is_err(res))
		fprintf(stderr, "clt: write_fd failed=%x, errno=%d\n",
			res, errno);

	sm_sock_close(fd);
	sleep(1);
	close(rdfd);
}

int
main(int argc, char *argv[])
{
	int c;

	opterr = 0;
	Verbose = 0;
	sockspec = "127.0.0.1";
	exsock = NSOCKET;
	while ((c = getopt(argc, argv, "L:p:S:V")) != -1)
	{
		switch (c)
		{
		  case 'L':
			sockspec = strdup(optarg);
			break;
		  case 'p':
			port = atoi(optarg);
			break;
		  case 'S':
			exsock = strdup(optarg);
			break;
		  case 'V':
			++Verbose;
			break;
		  default:
			usage(argv[0]);
			return(1);
		}
	}
	sm_test_begin(argc, argv, "pass fd");

#if MTA_USE_STATETHREADS
	c = st_init();
	SM_TEST(c >= 0);
	if (c < 0)
		exit(c);
#endif /* MTA_USE_STATETHREADS */

	client();
	return sm_test_end();
}


syntax highlighted by Code2HTML, v. 0.9.1