Browse Source

Restructure of the code for clarity.

master
Thomas Mannay 7 years ago
parent
commit
c0d9536605
3 changed files with 119 additions and 132 deletions
  1. +3
    -5
      Makefile
  2. +4
    -4
      tubes.1
  3. +112
    -123
      tubes.c

+ 3
- 5
Makefile View File

@@ -1,13 +1,11 @@
CC=cc CC=cc
override CFLAGS+=-Wall -Wpedantic -O2
override CFLAGS+=-Wall -pedantic -O2
LDFLAGS=-lcrypto -lssl LDFLAGS=-lcrypto -lssl
PREFIX=/usr/local PREFIX=/usr/local
MANPREFIX=${PREFIX}/man
#Ubuntu uses the one below
#MANPREFIX=${PREFIX}/share/man
MANPREFIX=${PREFIX}/share/man


it: it:
${CC} tubes.c ${CFLAGS} ${LDFLAGS} -o tubes
${CC} -s tubes.c ${CFLAGS} ${LDFLAGS} -o tubes


install: it install: it
echo installing executable to ${DESTDIR}${PREFIX}/bin echo installing executable to ${DESTDIR}${PREFIX}/bin


+ 4
- 4
tubes.1 View File

@@ -1,4 +1,4 @@
.TH TUBES 1 tubes-1.1.0
.TH TUBES 1 tubes-1.1.1
.SH NAME .SH NAME
tubes \- irc pipes tubes \- irc pipes
.SH SYNOPSIS .SH SYNOPSIS
@@ -28,13 +28,13 @@ Use a host other than the default (chat.freenode.net)
Use a port other than the default (6667) Use a port other than the default (6667)
.TP .TP
.B \-v .B \-v
Prints version information and exits
Print version information and exit


.SH FILES .SH FILES
The incoming and outgoing FIFO buffers are stored in /tmp and are named for The incoming and outgoing FIFO buffers are stored in /tmp and are named for
the server tubes is connected to with .in or .out appended to the end. the server tubes is connected to with .in or .out appended to the end.
~/.tubes.err is used to store a string explaining why tubes has exited, if any.
~/.tubes.err is used to store an error string if tubes exits with -1.
.SH RETURN VALUE .SH RETURN VALUE
Returns -1 when something has gone wrong or 0 on success.
Returns -1 on error, 0 on success.
.SH AUTHOR .SH AUTHOR
Copyright \(co 2016 Thomas Mannay <audiobarrier@openmailbox.org>. Copyright \(co 2016 Thomas Mannay <audiobarrier@openmailbox.org>.

+ 112
- 123
tubes.c View File

@@ -1,7 +1,4 @@
/**
* See the LICENSE file for licensing information
*/

/* See the LICENSE file for licensing information */
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/socket.h> #include <sys/socket.h>
@@ -19,33 +16,92 @@
#include <unistd.h> #include <unistd.h>


#define PING_TIMEOUT 240 #define PING_TIMEOUT 240
#define VERSION "1.1.0"
#define VERSION "1.1.1"


static char *server = "chat.freenode.net";
static char port[6] = "6667";
static FILE *log;
static SSL_CTX *ctx; static SSL_CTX *ctx;
static SSL *ssl; static SSL *ssl;
static char *server = "chat.freenode.net";
static int port = 6667;
static FILE *log;
static short use_ssl = 0; static short use_ssl = 0;
static unsigned int last_response; static unsigned int last_response;


/* connect to irc server */
int dial(char *server, char *port);
/* get SSL up and running */
int sslify(int *sockfd);
/* set up the error logging file */
FILE *slog(char *file);
/* mop up so we exit cleanly */
void mop(void);
FILE *
slog(char *file)
{
const char *home = getenv("HOME");
char path[100];
FILE *fp;

snprintf(path, 100, "%s/%s", home, file);
mknod(path, 0 | 0666, 0);
fp = fopen(path, "w");


int main(int argc, char **argv)
return fp;
}

int
dial(char *server, int port)
{
int sockfd, err;
struct addrinfo hints, *serv;

char tmp[8];
snprintf(tmp, 8, "%d", port);

memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
if ((err = getaddrinfo(server, tmp, &hints, &serv)) != 0) {
fprintf(log, "getaddrinfo: %s\n", gai_strerror(err));
return -1;
} else if ((sockfd = socket(serv->ai_family, serv->ai_socktype,
serv->ai_protocol)) == -1) {
fprintf(log, "tubes: error on socket()\n");
return -1;
} else if (connect(sockfd, serv->ai_addr, serv->ai_addrlen) == -1) {
fprintf(log, "tubes: error on connect().\n");
close(sockfd);
return -1;
}
freeaddrinfo(serv);

return sockfd;
}

int
sslify(int *sockfd)
{
int r;

SSL_library_init();
SSL_load_error_strings();

ctx = SSL_CTX_new(SSLv23_client_method());
SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3
| SSL_OP_SINGLE_DH_USE);
ssl = SSL_new(ctx);
SSL_set_fd(ssl, *sockfd);
SSL_set_connect_state(ssl);

if ((r = SSL_connect(ssl)) < 1) {
fprintf(log, "sslify: %s\n", strerror(SSL_get_error(ssl, r)));
SSL_CTX_free(ctx);
return -1;
}

return 0;
}

int
main(int argc, char **argv)
{ {
int sockfd, in, out; int sockfd, in, out;
int maxfd; int maxfd;
fd_set rd; fd_set rd;
struct timeval tv; struct timeval tv;
char buf[512]; char buf[512];
int i, r;
int i, r, status;


for (i = 1; i < argc; i++) { for (i = 1; i < argc; i++) {
char c = argv[i][1]; char c = argv[i][1];
@@ -54,7 +110,7 @@ int main(int argc, char **argv)
switch (c) { switch (c) {
case 'S': case 'S':
use_ssl = 1; use_ssl = 1;
snprintf(port, 6, "6697");
port = 6697;
break; break;
case 's': case 's':
if (++i < argc) if (++i < argc)
@@ -62,47 +118,44 @@ int main(int argc, char **argv)
break; break;
case 'p': case 'p':
if (++i < argc) if (++i < argc)
snprintf(port, 6, "%s", argv[i]);
port = atoi(argv[i]);
break; break;
case 'v':
fprintf(stderr, "tubes-%s © 2016 Thomas Mannay\n", VERSION);
exit(0);
case 'v': /* fall through */
default: default:
fprintf(stderr,
"usage: tubes [-S] [-s server] [-p port] [-v]\n");
fprintf(stderr, "tubes-%s © 2016 Thomas Mannay\n", VERSION);
exit(0); exit(0);
} }
} }


if ((log = slog(".tubes.err")) == NULL) { if ((log = slog(".tubes.err")) == NULL) {
fprintf(stderr, "tubes: error on slog()");
fprintf(stderr, "error on slog()");
exit(-1); exit(-1);
} }

if (daemon(0, 0) == -1) { if (daemon(0, 0) == -1) {
fprintf(log, "tubes: error on daemon()\n");
fprintf(log, "error on daemon()\n");
exit(-1); exit(-1);
} }


if ((sockfd = dial(server, port)) == -1) if ((sockfd = dial(server, port)) == -1)
exit(-1); exit(-1);

if (use_ssl && sslify(&sockfd) == -1) if (use_ssl && sslify(&sockfd) == -1)
exit(-1); exit(-1);


snprintf(buf, 512, "/tmp/%s.in", server); snprintf(buf, 512, "/tmp/%s.in", server);
unlink(buf); unlink(buf);
mknod(buf, S_IFIFO | 0660, 0);
in = open(buf, O_RDWR | O_NONBLOCK);
mkfifo(buf, 0660);
if ((in = open(buf, O_RDWR | O_NONBLOCK)) < 0) {
fprintf(log, "in: error on open()\n");
exit(-1);
}
snprintf(buf, 512, "/tmp/%s.out", server); snprintf(buf, 512, "/tmp/%s.out", server);
unlink(buf); unlink(buf);
mknod(buf, S_IFIFO | 0660, 0);
out = open(buf, O_RDWR);

atexit(mop);
mkfifo(buf, 0660);
if ((out = open(buf, O_RDWR)) < 0) {
fprintf(log, "out: error on open()\n");
exit(-1);
}


for (;;) {
for (status = 0;;) {
FD_ZERO(&rd); FD_ZERO(&rd);
maxfd = (out >= sockfd) ? out : sockfd; maxfd = (out >= sockfd) ? out : sockfd;
FD_SET(out, &rd); FD_SET(out, &rd);
@@ -114,13 +167,13 @@ int main(int argc, char **argv)
if (r < 0) { if (r < 0) {
if (errno == EINTR) if (errno == EINTR)
continue; continue;
fprintf(log, "tubes: error on select()\n");
exit(-1);
} else if (r == 0) {
if (time(NULL) - last_response >= PING_TIMEOUT) {
fprintf(log, "tubes: ping timeout\n");
exit(-1);
}
fprintf(log, "error on select()\n");
status = -1;
break;
} else if (r == 0 && last_response-time(NULL) >= PING_TIMEOUT) {
fprintf(log, "ping timeout\n");
status = -1;
break;
} }
if (FD_ISSET(out, &rd)) if (FD_ISSET(out, &rd))
if ((i = read(out, buf, sizeof(buf))) > 0) { if ((i = read(out, buf, sizeof(buf))) > 0) {
@@ -144,91 +197,26 @@ int main(int argc, char **argv)
i = recv(sockfd, buf, sizeof(buf), 0); i = recv(sockfd, buf, sizeof(buf), 0);
if (i != -1) { if (i != -1) {
if (i == 0) { if (i == 0) {
fprintf(log, "tubes: connection closed\n");
close(sockfd);
if (use_ssl)
SSL_CTX_free(ctx);
exit(0);
fprintf(log, "connection closed\n");
break;
} }
buf[i] = 0; buf[i] = 0;
if (write(in, buf, strlen(buf)) < 0) { if (write(in, buf, strlen(buf)) < 0) {
if (errno == EINTR) if (errno == EINTR)
continue; continue;
fprintf(log, "tubes: error on write()\n");
exit(-1);
fprintf(log, "error on write()\n");
status = -1;
break;
} }
last_response = time(NULL); last_response = time(NULL);
} }
} }
} }


return 0;
}

int dial(char *server, char *port)
{
int sockfd, err;
struct addrinfo hints, *serv;

memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
if ((err = getaddrinfo(server, port, &hints, &serv)) != 0) {
fprintf(log, "getaddrinfo: %s\n", gai_strerror(err));
return -1;
} else if ((sockfd = socket(serv->ai_family, serv->ai_socktype,
serv->ai_protocol)) == -1) {
fprintf(log, "tubes: error on socket()\n");
return -1;
} else if (connect(sockfd, serv->ai_addr, serv->ai_addrlen) == -1) {
fprintf(log, "tubes: error on connect().\n");
close(sockfd);
return -1;
}
freeaddrinfo(serv);

return sockfd;
}

int sslify(int *sockfd)
{
int r;

SSL_library_init();
SSL_load_error_strings();

ctx = SSL_CTX_new(SSLv23_client_method());
SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3
| SSL_OP_SINGLE_DH_USE);
ssl = SSL_new(ctx);
SSL_set_fd(ssl, *sockfd);
SSL_set_connect_state(ssl);

if ((r = SSL_connect(ssl)) < 1) {
fprintf(log, "tubes: %s\n", strerror(SSL_get_error(ssl, r)));
SSL_CTX_free(ctx);
return -1;
}

return 0;
}

FILE *slog(char *file)
{
const char *home = getenv("HOME");
char path[100];
FILE *fp;

snprintf(path, 100, "%s/%s", home, file);
mknod(path, 0 | 0666, 0);
fp = fopen(path, "w");

return fp;
}

void mop(void)
{
char str[512];
close(sockfd);
close(in);
close(out);
fclose(log);


ERR_free_strings(); ERR_free_strings();
EVP_cleanup(); EVP_cleanup();
@@ -236,8 +224,9 @@ void mop(void)
SSL_free(ssl); SSL_free(ssl);
SSL_CTX_free(ctx); SSL_CTX_free(ctx);


snprintf(str, 512, "/tmp/%s.in", server);
unlink(str);
snprintf(str, 512, "/tmp/%s.out", server);
unlink(str);
snprintf(buf, 512, "/tmp/%s.in", server);
unlink(buf);
snprintf(buf, 512, "/tmp/%s.out", server);
unlink(buf);
exit(status);
} }

Loading…
Cancel
Save