X-Git-Url: http://git.chise.org/gitweb/?a=blobdiff_plain;f=starttls.c;h=4159c5fc5d5adc252e39a35aba2e7c7a1322f5fa;hb=975f661941f6487aa3f7f61113fff6ac640beab7;hp=734339630b096fb14a4879e481ba5a0e64ba2be6;hpb=283a406693eb925f89a3e24ab3c22c928c3b9599;p=elisp%2Fstarttls.git diff --git a/starttls.c b/starttls.c index 7343396..4159c5f 100644 --- a/starttls.c +++ b/starttls.c @@ -29,6 +29,7 @@ #include #include #include +#include #include @@ -43,11 +44,12 @@ #include #include #include -#ifdef HAVE_POLL_H -#include -#endif -#define _GNU_SOURCE -#include "getopt.h" +#include +#include +#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); @@ -55,7 +57,8 @@ extern int tls_read(int, 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) @@ -69,31 +72,25 @@ 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; @@ -115,49 +112,65 @@ tcp_connect (hostname, service) 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; @@ -165,12 +178,14 @@ main (argc, argv) { {"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; @@ -182,15 +197,21 @@ main (argc, argv) 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; } @@ -207,87 +228,41 @@ main (argc, argv) 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: