/* * Copyright (c) 2002, 2004, 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-rcbsrvclt.c,v 1.10 2005/05/31 21:00:28 ca Exp $") #include "sm/assert.h" #include "sm/error.h" #include "sm/test.h" #include "sm/memops.h" #include "sm/io.h" #include "sm/ctype.h" #include "sm/fcntl.h" #include "sm/rcb.h" #include "sm/unixsock.h" #include "sm/check.h" #include "t-rcb.h" #include /* ** RCB Server/Client ** This program acts as a server for RCBs. ** It accepts incoming connections, and starts function to deal ** with them (no thread, sequential operation). ** That function (connection()) reads one RCB, displays its content ** (see rcvrcb() in t-rcb-sr.c for details), then reads data from ** stdin, creates an RCB out of it and sends it to the client ** (see sendrcb() in t-rcb-sr.c for details). */ extern char *optarg; extern int optind; extern int optopt; extern int opterr; int Verbose; void usage(const char *prg) { fprintf(stderr, "usage: %s [options] socket\n", prg); exit(0); } /* dirty hack ahead: specify timeout for function call */ #define TMO #include "t-rcb-sr.c" /* ** CONNECTION -- receive and send rcb (alternating) ** ** Parameters: ** fd -- file descriptor ** ** Returns: ** none */ void connection(int fd, bool clientfirst) { sm_rcb_P rcb; sm_ret_T ret; ret = SM_SUCCESS; rcb = sm_rcb_new(NULL, SM_RCBSIZE, SM_MAXRCBSIZE); SM_TEST(rcb != NULL); if (rcb == NULL) goto done; do { if (clientfirst) { if (Verbose > 3) fprintf(stderr, "clt: rcb_rcv\n"); ret = rcvrcb(rcb, fd, true); if (sm_is_err(ret)) break; } clientfirst = true; if (Verbose > 3) fprintf(stderr, "src: sendrcb\n"); ret = sendrcb(rcb, fd); if (sm_is_err(ret)) break; } while (!sm_is_err(ret)); done: if (rcb != NULL) sm_rcb_free(rcb); } /* ** SERVER -- wait for connections ** ** Parameters: ** sockname -- name of socket ** ** Returns: ** none */ void server(char *sockname, bool clientfirst) { int fd, lfd, servfd; struct sockaddr addr; sockaddr_len_T addrlen; lfd = fd = servfd = -1; unlink(sockname); lfd = unix_server_listen(sockname, 10); SM_TEST(lfd >= 0); if (lfd < 0) return; for (;;) { addrlen = sizeof(addr); if (Verbose > 1) fprintf(stderr, "srv: accept\n"); fd = unix_server_accept(lfd, &addr, &addrlen); SM_TEST(fd >= 0); if (fd < 0) goto err; if (Verbose > 1) fprintf(stderr, "srv: accepted fd=%d\n", fd); connection(fd, clientfirst); (void) close(fd); } err: if (fd >= 0) close(fd); if (lfd >= 0) close(lfd); } int main(int argc, char *argv[]) { int c; bool clientfirst; char *sockname, *prg; opterr = 0; Verbose = 0; sockname = NULL; clientfirst = true; prg = argv[0]; while ((c = getopt(argc, argv, "cV")) != -1) { switch (c) { case 'V': ++Verbose; break; case 'c': clientfirst = false; break; default: usage(prg); } } sm_test_begin(argc, argv, "unix socket rcb server"); argc -= optind; argv += optind; if (argc <= 0) usage(prg); sockname = argv[0]; server(sockname, clientfirst); return sm_test_end(); }