/* * 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-rcbsrv.c,v 1.16 2005/04/14 17:14:02 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 "t-rcb.h" #include extern char *optarg; extern int optind; extern int optopt; extern int opterr; static int Verbose; void usage(const char *prg) { fprintf(stderr, "usage: %s [options] socket\n", prg); exit(0); } /* ** RCB_RECEIVE -- receive rcb ** ** Parameters: ** fd -- file descriptor ** ** Returns: */ sm_ret_T rcb_receive(int fd, uint rcbsize, uint maxrcbsize, uint elems, uint32_t rt, uint sleeptime) { sm_ret_T ret; uint32_t val, len; size_t i; sm_rcb_P rcb; char buf[SM_RCBSIZE]; ret = SM_SUCCESS; val = 0; len = 0; rcb = sm_rcb_new(NULL, rcbsize, maxrcbsize); SM_TEST(rcb != NULL); if (rcb == NULL) { ret = sm_err_temp(ENOMEM); goto done; } do { ret = sm_rcb_open_rcv(rcb); SM_TEST(sm_is_success(ret)); if (sleeptime > 0) sleep(sleeptime); do { ret = sm_rcb_rcv(fd, rcb, 16); if (Verbose > 2) fprintf(stderr, "rcb_rcv: ret=%x\n", ret); } while (ret > 0); if (ret < 0) break; ret = sm_rcb_close_rcv(rcb); SM_TEST(ret == SM_SUCCESS); if (elems > 0) { checkrcb(rcb, elems, rt); } else { ret = sm_rcb_open_dec(rcb); SM_TEST(sm_is_success(ret)); if (!sm_is_success(ret)) break; ret = sm_rcb_getuint32(rcb, &val); SM_TEST(sm_is_success(ret)); if (!sm_is_success(ret)) break; if (Verbose > 1) fprintf(stderr, "srv: total length=%d\n", val); if (Verbose > 2) { fprintf(stderr, "srv: len=%d\n", (int) rcb->sm_rcb_len); fprintf(stderr, "srv: rw=%d\n", rcb->sm_rcb_rw); fprintf(stderr, "srv: first=%u\n", *((uint32_t *) (rcb->sm_rcb_base))); } /* have to agree on record types with sender ... */ do { if (Verbose > 2) fprintf(stderr, "srv: rd=%d\n", rcb->sm_rcb_rw); ret = sm_rcb_getuint32(rcb, &len); SM_TEST(sm_is_success(ret)); if (!sm_is_success(ret)) break; if (Verbose > 1) fprintf(stderr, "srv: got length=%d\n", len); ret = sm_rcb_getuint32(rcb, &val); SM_TEST(sm_is_success(ret)); if (!sm_is_success(ret)) break; if (Verbose > 1) fprintf(stderr, "srv: got rectype=%d\n", val); /* XXX: bit 1: string or int? */ if (val & 0x01) { ret = sm_rcb_getuint32(rcb, &val); SM_TEST(sm_is_success(ret)); if (!sm_is_success(ret)) break; if (Verbose > 1) fprintf(stderr, "srv: got val=%d\n", val); printf("I=%d\n", val); } else if (len < sizeof(buf) - 1) { sm_memzero(buf, sizeof(buf)); ret = sm_rcb_getn(rcb, (uchar *) buf, len); SM_TEST(sm_is_success(ret)); if (!sm_is_success(ret)) break; if (Verbose > 1) fprintf(stderr, "srv: got buf=%d\n", buf[0]); printf("S="); for (i = 0; i < len; i++) if (ISPRINT(buf[i])) putchar(buf[i]); else printf(" %02x ", buf[i]); putchar('\n'); } else break; if (Verbose > 2) fprintf(stderr, "srv: next: rd=%d, len=%d\n", rcb->sm_rcb_rw, (int) rcb->sm_rcb_len); } while (rcb->sm_rcb_rw < (int) rcb->sm_rcb_len); ret = sm_rcb_close_dec(rcb); SM_TEST(ret == SM_SUCCESS); } } while (sm_is_success(ret)); done: if (rcb != NULL) sm_rcb_free(rcb); if (val != END_OF_TRANSMISSION && ret == SM_IO_EOF) ret = SM_SUCCESS; return ret; } /* ** URCBSERVER -- wait for connections ** ** Parameters: ** sockname -- name of socket ** ** Returns: ** none */ void urcbserver(char *sockname, uint rcbsize, uint maxrcbsize, uint elems, uint32_t rt, uint sleeptime) { int fd, lfd, servfd; sm_ret_T ret; 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; do { 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); ret = rcb_receive(fd, rcbsize, maxrcbsize, elems, rt , sleeptime); (void) close(fd); } while (sm_is_success(ret)); err: if (fd >= 0) close(fd); if (lfd >= 0) close(lfd); } int main(int argc, char *argv[]) { int c; uint elems, rcbsize, maxrcbsize, sleeptime; uint32_t rt; char *sockname, *prg; opterr = 0; Verbose = 0; sockname = NULL; elems = 0; rt = 0; sleeptime = 0; rcbsize = SM_RCBSIZE; maxrcbsize = SM_MAXRCBSIZE; prg = argv[0]; while ((c = getopt(argc, argv, "e:m:r:s:w:V")) != -1) { switch (c) { case 'e': elems = atoi(optarg); break; case 'm': maxrcbsize = atoi(optarg); break; case 'r': rt = atoi(optarg); break; case 's': rcbsize = atoi(optarg); break; case 'w': sleeptime = atoi(optarg); break; case 'V': ++Verbose; 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]; urcbserver(sockname, rcbsize, maxrcbsize, elems, rt, sleeptime); return sm_test_end(); }