/* * 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 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; }