#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 int tls_fd = -1;
static void
usage (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
-socket_connect (hostname, service)
+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 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 sigaction act;
+ sigset_t orig_mask;
int this_option_optind = optind ? optind : 1;
int option_index = 0, c;
opt_key_file = optarg;
break;
default:
- usage (basename (argv[0]));
+ usage (argv[0]);
return 1;
}
}
if (optind+2 != argc)
{
- usage (basename (argv[0]));
+ usage (argv[0]);
return 1;
}
- tls_fd = socket_connect (argv[optind], argv[optind+1]);
+ tls_fd = tcp_connect (argv[optind], argv[optind+1]);
if (tls_fd < 0)
{
- perror ("socket_connect");
+ perror ("tcp_connect");
return 1;
}
memset (&act, 0, sizeof (act));
act.sa_handler = do_tls_negotiate;
sigemptyset (&act.sa_mask);
+ sigaddset (&act.sa_mask, SIGALRM);
act.sa_flags = SA_RESTART|SA_RESETHAND;
sigaction (SIGALRM, &act, NULL);
-#ifdef HAVE_POLL
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, &act.sa_mask, &orig_mask);
+ ready = poll (readfds, 2, -1);
+ sigprocmask (SIG_SETMASK, &orig_mask, NULL);
+ if (ready == -1 && errno != EINTR)
{
perror ("poll");
return 1;
}
-#ifdef HAVE_POLL
if (readfds[0].revents & POLLIN)
-#else
- if (FD_ISSET (in, &readfds))
-#endif
{
nbuffer = read (in, buffer, sizeof buffer -1);
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
+ sigprocmask (SIG_SETMASK, &act.sa_mask, &orig_mask);
+ ready = poll (writefds, 1, -1);
+ sigprocmask (SIG_SETMASK, &orig_mask, NULL);
+ if (ready == -1 && errno != EINTR)
{
perror ("poll");
return 1;
if (wrote < 0) goto finish;
}
}
-#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);
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
+ sigprocmask (SIG_SETMASK, &act.sa_mask, &orig_mask);
+ ready = poll (writefds, 1, -1);
+ sigprocmask (SIG_SETMASK, &orig_mask, NULL);
+ if (ready == -1 && errno != EINTR)
{
perror ("poll");
return 1;