/* * Copyright (c) 2002 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. * * $Id: clt2.c,v 1.3 2006/02/16 19:19:40 ca Exp $ */ #include #include #include #include #include #include #include #include #include #include #include #include #include "st.h" #if !HAVE_SNPRINTF # define snprintf sm_snprintf # include "sm/string.h" #endif /* !HAVE_SNPRINTF */ #define IOBUFSIZE (16*1024) #define REPS 10 #ifndef INADDR_NONE #define INADDR_NONE 0xffffffff #endif #define SEC2USEC(s) ((s)*1000000LL) #define REQUEST_TIMEOUT SEC2USEC(3) static char *prog; /* Program name */ static struct sockaddr_in rmt_addr; /* Remote address */ static int debug = 0; static st_netfd_t rmt_nfd = NULL; static void print_sys_error(const char *msg) { fprintf(stderr, "%s: %s: %s\n", prog, msg, strerror(errno)); } static void read_address(const char *str, struct sockaddr_in *sin) { char host[128], *p; struct hostent *hp; short port; strlcpy(host, str, sizeof(host)); if ((p = strchr(host, ':')) == NULL) { fprintf(stderr, "%s: invalid address: %s\n", prog, host); exit(1); } *p++ = '\0'; port = (short) atoi(p); if (port < 1) { fprintf(stderr, "%s: invalid port: %s\n", prog, p); exit(1); } memset(sin, 0, sizeof(struct sockaddr_in)); sin->sin_family = AF_INET; sin->sin_port = htons(port); if (host[0] == '\0') { sin->sin_addr.s_addr = INADDR_ANY; return; } sin->sin_addr.s_addr = inet_addr(host); if (sin->sin_addr.s_addr == INADDR_NONE) { /* not dotted-decimal */ if ((hp = gethostbyname(host)) == NULL) { fprintf(stderr, "%s: can't resolve address: %s\n", prog, host); exit(1); } memcpy(&sin->sin_addr, hp->h_addr, hp->h_length); } } static int con2srv(void) { int sock; char buf[IOBUFSIZE]; /* Connect to remote host */ if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) { snprintf(buf, sizeof(buf), "socket=%d", sock); print_sys_error(buf); goto done; } if ((rmt_nfd = st_netfd_open_socket(sock)) == NULL) { snprintf(buf, sizeof(buf), "st_netfd_open_socket"); print_sys_error(buf); close(sock); goto done; } if (st_connect(rmt_nfd, (struct sockaddr *)&rmt_addr, sizeof(rmt_addr), REQUEST_TIMEOUT) < 0) { snprintf(buf, sizeof(buf), "connect"); print_sys_error(buf); st_netfd_close(rmt_nfd); goto done; } if (debug > 2) fprintf(stderr, "client: connected\n"); return 1; done: return -1; } static void * wrsrv(void *arg) { int n, r, l; char buf[IOBUFSIZE]; for (n = 0; n < REPS; n++) { snprintf(buf, sizeof(buf), "CMD %d\n", n); l = strlen(buf); r = st_write(rmt_nfd, buf, l, REQUEST_TIMEOUT); if (r != l) { fprintf(stderr, "error write s='%s' n=%d, l=%d, r=%d, errno=%d\n", buf, n, l, r, errno); return NULL; } st_usleep(1); } return NULL; } static void * rdsrv(void *arg) { int n; char buf[IOBUFSIZE]; while (1) { n = st_read(rmt_nfd, buf, IOBUFSIZE, REQUEST_TIMEOUT); if (n <= 0) { fprintf(stderr, "error read n=%d, errno=%d\n", n, errno); goto fail; } if (debug > 3) { fprintf(stderr, "rcvd: \""); write(STDERR_FILENO, buf, n); fprintf(stderr, "\"\n"); } while (n > 0) if (buf[--n] == 'Q') return NULL; st_usleep(1); } fail: return NULL; } int main(int argc, char *argv[]) { st_thread_t thr1; extern char *optarg; int opt, r, raddr, *rv; prog = argv[0]; raddr = 0; /* Parse arguments */ while((opt = getopt(argc, argv, "c:d:hr:t:S")) != -1) { switch (opt) { case 'd': debug = atoi(optarg); if (debug < 0) { fprintf(stderr, "%s: invalid number for debug: %s\n", prog, optarg); exit(1); } break; case 'r': read_address(optarg, &rmt_addr); if (rmt_addr.sin_addr.s_addr == INADDR_ANY) { fprintf(stderr, "%s: invalid remote address: %s\n", prog, optarg); exit(1); } raddr = 1; break; case 'h': case '?': fprintf(stderr, "Usage: %s -l <[host]:port> -r " "[-S]\n", prog); exit(1); } } if (!raddr) { fprintf(stderr, "%s: remote address required\n", prog); exit(1); } if (debug) fprintf(stderr, "%s: starting client\n", prog); /* Initialize the ST library */ if (st_init() < 0) { print_sys_error("st_init"); exit(1); } if (con2srv() < 0) exit(1); thr1 = st_thread_create(wrsrv, (void *) 1, 1, 0); if (NULL == thr1) { print_sys_error("st_thread_create"); exit(1); } rdsrv((void *) 2); r = st_thread_join(thr1, (void **) &rv); if (rmt_nfd != NULL) { st_netfd_close(rmt_nfd); rmt_nfd = NULL; } return 0; }