dmc

dynamic mail client
git clone git://git.suckless.org/dmc
Log | Files | Refs | README | LICENSE

sock.c (2179B)


      1 /* dmc - dynamic mail client
      2  * See LICENSE file for copyright and license details.
      3  */
      4 
      5 #include <stdio.h>
      6 #include <string.h>
      7 #include <unistd.h>
      8 #include <poll.h>
      9 #include <stdarg.h>
     10 #include <netdb.h>
     11 #include <arpa/inet.h>
     12 #include <sys/socket.h>
     13 #include <netinet/in.h>
     14 
     15 #if HAVE_SSL
     16 #include <openssl/ssl.h>
     17 static SSL_CTX *ctx;
     18 static SSL *sfd;
     19 #endif
     20 static int ssl = 0;
     21 static int fd = -1;
     22 
     23 int sock_ssl (int fd) {
     24 #if HAVE_SSL
     25 	// TODO Check certificate
     26 	SSL_library_init ();
     27 	SSL_load_error_strings ();
     28 	OpenSSL_add_all_algorithms ();
     29 	ctx = SSL_CTX_new (SSLv23_method ());
     30 	sfd = SSL_new (ctx);
     31 	SSL_set_fd (sfd, fd);
     32 	if (SSL_connect (sfd) < 1)
     33 		return -1;
     34 #endif
     35 	return fd;
     36 }
     37 
     38 int sock_connect(const char *host, int port, int ssl_enable) {
     39 	struct sockaddr_in sa;
     40 	struct hostent *he;
     41 	int s = socket (AF_INET, SOCK_STREAM, 0);
     42 	ssl = ssl_enable, fd = -1;
     43 	if (s != -1) {
     44 		memset (&sa, 0, sizeof (sa));
     45 		sa.sin_family = AF_INET;
     46 		he = (struct hostent *)gethostbyname (host);
     47 		if (he != (struct hostent*)0) {
     48 			sa.sin_addr = *((struct in_addr *)he->h_addr);
     49 			sa.sin_port = htons (port);
     50 			if (!connect (s, (const struct sockaddr*)&sa, sizeof (struct sockaddr)))
     51 				fd = ssl ? sock_ssl (s) : s;
     52 		}
     53 		if (fd == -1)
     54 			close (s);
     55 	}
     56 	return fd;
     57 }
     58 
     59 int sock_ready() {
     60 #if HAVE_SSL
     61 	if (ssl && SSL_pending (sfd))
     62 		return 1;
     63 #endif
     64 	struct pollfd fds[1];
     65 	fds[0].fd = fd;
     66 	fds[0].events = POLLIN|POLLPRI;
     67 	fds[0].revents = POLLNVAL|POLLHUP|POLLERR;
     68 	return poll (fds, 1, 1000);
     69 }
     70 
     71 void sock_close() {
     72 #if HAVE_SSL
     73 	SSL_CTX_free (ctx);
     74 	SSL_free (sfd);
     75 #endif
     76 	close (fd);
     77 }
     78 
     79 int sock_write(const char *str) {
     80 #if HAVE_SSL
     81 	if (ssl)
     82 		return SSL_write (sfd, str, strlen(str));
     83 #endif
     84 	return write (fd, str, strlen(str));
     85 }
     86 
     87 int sock_printf(const char *fmt, ...) {
     88 	va_list ap;
     89 	int ret = -1;
     90 	char buf[1024];
     91 	va_start (ap, fmt);
     92 	vsnprintf (buf, sizeof (buf), fmt, ap);
     93 	// XXX check len
     94 	ret = sock_write (buf);
     95 	va_end (ap);
     96 	return ret;
     97 }
     98 
     99 int sock_read (char *buf, int len) {
    100 	int ret;
    101 	memset (buf, 0, len+1);
    102 #if HAVE_SSL
    103 	if (ssl) ret = SSL_read (sfd, buf, len);
    104 	else
    105 #endif
    106 	ret = read (fd, buf, len);
    107 	if (ret>0)
    108 		buf[ret] = '\0';
    109 	return ret;
    110 }