#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <stdbool.h>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <netinet/in.h>
-#ifdef HAVE_POLL_H
-#include <sys/poll.h>
-#endif
-#define _GNU_SOURCE
-#include "getopt.h"
+#include <poll.h>
+#include <getopt.h>
+#include "getaddrinfo.h"
+#include "gettext.h"
+#include "inet_ntop.h"
+#include "strdup.h"
extern void tls_negotiate (int, const char *, const char *);
extern int tls_write(int, const char *, int);
extern int tls_pending();
static char *opt_cert_file = NULL, *opt_key_file = NULL;
-static int tls_fd;
+static bool opt_assuan = false;
+static int tls_fd = -1;
static void
usage (progname)
"Usage: %s [options] host port\n\n"
"Options:\n\n"
" --cert-file [file] specify certificate file\n"
- " --key-file [file] specify private key file\n",
+ " --key-file [file] specify private key file\n"
+ " --help show this help\n",
progname, PACKAGE, VERSION, progname);
}
static void
do_tls_negotiate(sig)
- int sig;
+ int sig;
{
- tls_negotiate(tls_fd, opt_cert_file, opt_key_file);
+ tls_negotiate (tls_fd, opt_cert_file, opt_key_file);
}
int
tcp_connect (hostname, service)
const char *hostname, *service;
{
- int server, false = 0;
-#ifdef HAVE_ADDRINFO
+ int server, _false = 0;
struct addrinfo *in, *in0, hints;
-#else
- struct hostent *host;
- struct servent *serv;
- struct sockaddr_in sin;
-#endif
-#ifdef HAVE_ADDRINFO
memset (&hints, 0, sizeof (hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
if (server < 0)
return -1;
-#else
- memset (&sin, 0, sizeof (sin));
- host = gethostbyname (hostname);
- if (!host)
- return -1;
- memcpy (&sin.sin_addr, host->h_addr, host->h_length);
- serv = getservbyname (service, "tcp");
- if (serv)
- sin.sin_port = serv->s_port;
- else if (isdigit (service[0]))
- sin.sin_port = htons (atoi (service));
- sin.sin_family = AF_INET;
- server = socket (sin.sin_family, SOCK_STREAM, 0);
- if (server == -1)
- return -1;
-
- if (connect (server, (struct sockaddr *)&sin, sizeof (sin)) < 0)
- {
- close (server);
- return -1;
- }
-#endif
- setsockopt (server, SOL_SOCKET, SO_KEEPALIVE, (const char *) &false,
- sizeof (false));
+ setsockopt (server, SOL_SOCKET, SO_KEEPALIVE, (const char *) &_false,
+ sizeof (_false));
return server;
}
int
+redirect (fd, buffer, nbuffer, write_function)
+ int fd;
+ char *buffer;
+ int nbuffer;
+ int (*write_function) (int, const char *, int);
+{
+ sigset_t mask, orig_mask;
+ struct pollfd writefds[1];
+ int wrote;
+ char *retry;
+
+ sigemptyset (&mask);
+ sigaddset (&mask, SIGALRM);
+
+ writefds[0].fd = fd;
+ writefds[0].events = POLLOUT;
+
+ for (retry = buffer; nbuffer > 0; nbuffer -= wrote, retry += wrote)
+ {
+ int ready;
+
+ sigprocmask (SIG_SETMASK, &mask, &orig_mask);
+ ready = poll (writefds, 1, -1);
+ sigprocmask (SIG_SETMASK, &orig_mask, NULL);
+ if (ready == -1 && errno != EINTR)
+ {
+ if (opt_assuan)
+ printf ("ERR 1 poll: %s\r\n", strerror (errno));
+ return 1;
+ }
+ wrote = (*write_function)(fd, retry, nbuffer);
+ if (wrote == -1)
+ {
+ if (opt_assuan)
+ printf ("ERR 1 write: %s\r\n", strerror (errno));
+ return 1;
+ }
+ }
+}
+
+int
main (argc, argv)
- int argc;
- char **argv;
+ int argc;
+ char **argv;
{
- int in = fileno (stdin), out = fileno (stdout),
+ int in = fileno (stdin), out = fileno (stdout),
nbuffer, wrote;
-#ifdef HAVE_POLL
- struct pollfd readfds[2], writefds[1];
-#else
- fd_set readfds, writefds;
-#endif
- char buffer[BUFSIZ], *retry;
+ struct pollfd readfds[2];
+ char buffer[BUFSIZ];
struct sigaction act;
+ sigset_t mask, orig_mask;
int this_option_optind = optind ? optind : 1;
int option_index = 0, c;
{
{"cert-file", 1, 0, 'c'},
{"key-file", 1, 0, 'k'},
+ {"help", 0, 0, 'h'},
+ {"assuan", 0, 0, 'A'},
{0, 0, 0, 0}
};
while (1)
{
- c = getopt_long (argc, argv, "c:k:", long_options, &option_index);
+ c = getopt_long (argc, argv, "c:k:hA", long_options, &option_index);
if (c == -1)
break;
case 'k':
opt_key_file = optarg;
break;
+ case 'h':
+ usage (argv[0]);
+ return 0;
+ case 'A':
+ opt_assuan = true;
+ break;
default:
- usage (basename (argv[0]));
+ usage (argv[0]);
return 1;
}
}
if (optind+2 != argc)
{
- usage (basename (argv[0]));
+ usage (argv[0]);
return 1;
}
act.sa_flags = SA_RESTART|SA_RESETHAND;
sigaction (SIGALRM, &act, NULL);
-#ifdef HAVE_POLL
+ sigemptyset (&mask);
+ sigaddset (&mask, SIGALRM);
+
readfds[0].fd = in;
readfds[1].fd = tls_fd;
readfds[0].events = POLLIN;
readfds[1].events = POLLIN;
- writefds[0].events = POLLOUT;
-#endif
while (1)
{
-#ifdef HAVE_POLL
- if (poll (readfds, 2, -1) == -1 && errno != EINTR)
-#else
- FD_ZERO (&readfds);
- FD_SET (tls_fd, &readfds);
- FD_SET (in, &readfds);
- if (select (tls_fd+1, &readfds, NULL, NULL, NULL) == -1
- && errno != EINTR )
-#endif
+ int ready;
+
+ sigprocmask (SIG_SETMASK, &mask, &orig_mask);
+ ready = poll (readfds, 2, -1);
+ sigprocmask (SIG_SETMASK, &orig_mask, NULL);
+ if (ready == -1 && errno != EINTR)
{
- perror ("poll");
+ if (opt_assuan)
+ printf ("ERR 1 poll: %s\r\n", strerror (errno));
return 1;
}
-#ifdef HAVE_POLL
if (readfds[0].revents & POLLIN)
-#else
- if (FD_ISSET (in, &readfds))
-#endif
{
nbuffer = read (in, buffer, sizeof buffer -1);
-
if (nbuffer == 0)
goto finish;
- for (retry = buffer; nbuffer > 0; nbuffer -= wrote, retry += wrote)
- {
-#ifdef HAVE_POLL
- writefds[0].fd = tls_fd;
- if (poll (writefds, 1, -1) == -1)
-#else
- FD_ZERO (&writefds);
- FD_SET (tls_fd, &writefds);
- if (select (tls_fd+1, NULL, &writefds, NULL, NULL) == -1)
-#endif
- {
- perror ("poll");
- return 1;
- }
- wrote = tls_write(tls_fd, retry, nbuffer);
- if (wrote < 0) goto finish;
- }
+ redirect (tls_fd, buffer, nbuffer, tls_write);
}
-#ifdef HAVE_POLL
if (readfds[1].revents & POLLIN)
-#else
- if (FD_ISSET (tls_fd, &readfds))
-#endif
- {
-readtop:
- nbuffer = tls_read(tls_fd, buffer, sizeof buffer -1);
+ do {
+ nbuffer = tls_read (tls_fd, buffer, sizeof buffer -1);
if (nbuffer == 0)
goto finish;
- for (retry = buffer; nbuffer > 0; nbuffer -= wrote, retry += wrote)
- {
-#ifdef HAVE_POLL
- writefds[0].fd = out;
- if (poll (writefds, 1, -1) == -1)
-#else
- FD_ZERO (&writefds);
- FD_SET (out, &writefds);
- if (select (out+1, NULL, &writefds, NULL, NULL) == -1)
-#endif
- {
- perror ("poll");
- return 1;
- }
- wrote = write (out, retry, nbuffer);
- if (wrote < 0) goto finish;
- }
- if (tls_pending())
- goto readtop;
- }
+ redirect (out, buffer, nbuffer, write);
+ } while (tls_pending ());
}
finish: