/*
* Copyright (c) 2002-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-unixcl.c,v 1.13 2005/10/24 22:47:09 ca Exp $")
#include "sm/assert.h"
#include "sm/error.h"
#include "sm/test.h"
#include "sm/io.h"
#include "sm/ctype.h"
#include "sm/types.h"
#include "sm/fcntl.h"
#include "sm/unixsock.h"
#include "sm/time.h"
#include "sm/signal.h"
#include <stdio.h>
extern char *optarg;
extern int optind;
extern int optopt;
extern int opterr;
static int Verbose;
#define SM_BUFSIZE 8192
static void
usage(const char *prg)
{
fprintf(stderr, "usage: %s [options] socket\n", prg);
fprintf(stderr, "open a connection to a server via a Unix domain socket for writing\n");
fprintf(stderr, "-r also read from socket\n");
fprintf(stderr, "-V increase verbosity\n");
exit(0);
}
/*
** CLIENT -- send data read from stdin over a socket (byte by byte)
** (yes, it's highly inefficient, but it's only a test program)
**
** Parameters:
** sockname -- name of socket or IP address
** rd -- also read?
** port -- use port (if IP address)
**
** Returns:
** none
*/
static void
client(char *sockname, bool rd, int port)
{
int fd;
int res, c;
char buf[2];
fd_set rdset;
timeval_T timeout;
int flags;
if (Verbose > 1)
fprintf(stderr, "clt: connect\n");
if (port > 0)
(void) net_client_connect(sockname, port, &fd);
else
(void) unix_client_connect(sockname, &fd);
if (Verbose > 1)
fprintf(stderr, "clt: connected=%d, errno=%d\n", fd, errno);
SM_TEST(fd >= 0);
if (fd < 0)
return;
buf[1] = '\0';
FD_ZERO(&rdset);
flags = fcntl(fd, F_GETFL, 0);
SM_TEST(flags != -1);
res = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
SM_TEST(res != -1);
while ((c = getchar()) != EOF)
{
buf[0] = (char) c;
res = write(fd, buf, 1);
SM_TEST(res == 1 || errno == EPIPE);
if (res != 1)
{
fprintf(stderr, "clt: write_fd failed=%x, errno=%d\n",
res, errno);
break;
}
if (rd)
{
do
{
FD_ZERO(&rdset);
FD_SET(fd, &rdset);
timeout.tv_sec = 0;
timeout.tv_usec = 0;
res = select(fd + 1, &rdset, NULL, NULL,
&timeout);
if (res == 1 && FD_ISSET(fd, &rdset))
{
c = read(fd, buf, 1);
if (c == 1)
{
fprintf(stdout, "%c", buf[0]);
}
/* EOF... */
if (c == 0)
rd = false;
}
} while (rd && res == 1 && FD_ISSET(fd, &rdset));
fflush(stdout);
}
}
if (rd)
{
do
{
FD_ZERO(&rdset);
FD_SET(fd, &rdset);
timeout.tv_sec = 1;
timeout.tv_usec = 0;
res = select(fd + 1, &rdset, NULL, NULL,
&timeout);
if (res == 1 && FD_ISSET(fd, &rdset))
{
c = read(fd, buf, 1);
if (c == 1)
{
fprintf(stdout, "%c", buf[0]);
}
/* EOF... */
if (c == 0)
rd = false;
}
} while (rd && res == 1 && FD_ISSET(fd, &rdset));
fflush(stdout);
}
close(fd);
}
int
main(int argc, char *argv[])
{
int c;
char *sockname, *prg;
int port;
bool rd;
prg = argv[0];
opterr = 0;
Verbose = 0;
port = 0;
sockname = NULL;
rd = false;
while ((c = getopt(argc, argv, "p:rV")) != -1)
{
switch (c)
{
case 'p':
port = atoi(optarg);
break;
case 'r':
rd = true;
break;
case 'V':
++Verbose;
break;
default:
usage(prg);
}
}
argc -= optind;
argv += optind;
if (argc < 1)
usage(prg);
sockname = argv[0];
--argc;
++argv;
signal(SIGPIPE, SIG_IGN);
sm_test_begin(argc, argv, "unix socket client");
client(sockname, rd, port);
c = sm_test_end();
return c;
}
syntax highlighted by Code2HTML, v. 0.9.1