ii

git clone https://orangeshoelaces.net/git/ii.git

1a3f996c88691eb50d3bd2654da967621b2f46ae

Author: Vasilii Kolobkov on 01/07/2019

Committer: Vasilii Kolobkov on 01/08/2019

Act as a pure protocol handler

Leave connection handling to other tools (e.g. socat, nc or
tcpclient). Expect server messages on standard input and provide and
send our messages via standard output.

Stats

ii.1 |  21 +-
ii.c | 170 ++------
2 files changed, 49 insertions(+), 142 deletions(-)

Patch

diff --git a/ii.1 b/ii.1
index 8e06af7..2ea973e 100644
--- a/ii.1
+++ b/ii.1
@@ -15,12 +15,12 @@ The basic idea of this is to be able to communicate with an IRC
 server with basic command line tools.
 For example if you will join a channel just do echo "/j #channel" > in
 and ii creates a new channel directory with in and out file.
+Connection to server is expected on standard input for server messages
+and standard output for ii messages.
 .SH SYNOPSIS
 .B ii
 .RB < \-s
 .IR servername >
-.RB [ \-p
-.IR port ]
 .RB [ \-k
 .IR "environment variable" ]
 .RB [ \-i
@@ -29,18 +29,10 @@ and ii creates a new channel directory with in and out file.
 .IR nickname ]
 .RB [ \-f
 .IR realname ]
-.RB < \-u
-.IR sockname >
 .SH OPTIONS
 .TP
 .BI \-s " servername"
-server to connect to, for example: irc.freenode.net
-.TP
-.BI \-u " sockname"
-connect to a UNIX domain socket instead of directly to a server.
-.TP
-.BI \-p " port"
-lets you override the default port (6667)
+server name, for example: irc.freenode.net
 .TP
 .BI \-k " environment variable"
 lets you specify an environment variable that contains your IRC password, e.g. IIPASS="foobar" ii -k IIPASS.
@@ -85,9 +77,6 @@ set the topic of a channel
 .LP
 Everything which is not a command will be posted into the channel or to the server.
 So if you need /who just write /WHO as described in RFC#1459 to the server in FIFO.
-.SH SSL PROTOCOL SUPPORT
-.LP
-For TLS/SSL protocol support you can connect to a local tunnel, for example with stunnel or socat.
 .SH CONTACT
 .LP
 Subscribe to the mailinglist and write to dev (at) suckless (dot) org for suggestions, fixes, etc.
@@ -95,6 +84,8 @@ Subscribe to the mailinglist and write to dev (at) suckless (dot) org for sugges
 ii engineers, see LICENSE file
 .SH SEE ALSO
 .BR echo (1),
-.BR tail (1)
+.BR tail (1),
+.BR socat (1),
+.BR nc(1)
 .SH BUGS
 Please report them!
diff --git a/ii.c b/ii.c
index 6c87314..2345214 100644
--- a/ii.c
+++ b/ii.c
@@ -1,16 +1,12 @@
 /* See LICENSE file for license details. */
 #include <sys/select.h>
-#include <sys/socket.h>
 #include <sys/stat.h>
 #include <sys/types.h>
-#include <sys/un.h>
 
 #include <ctype.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <limits.h>
-#include <netdb.h>
-#include <netinet/in.h>
 #include <pwd.h>
 #include <signal.h>
 #include <stdarg.h>
@@ -56,22 +52,20 @@ static int       channel_reopen(Channel *);
 static void      channel_rm(Channel *);
 static void      create_dirtree(const char *);
 static void      create_filepath(char *, size_t, const char *, const char *, const char *);
-static void      ewritestr(int, const char *);
-static void      handle_channels_input(int, Channel *);
-static void      handle_server_output(int);
+static void      ewritestr(const char *);
+static void      handle_channels_input(Channel *);
+static void      handle_server_output(void);
 static int       isnumeric(const char *);
-static void      loginkey(int, const char *);
-static void      loginuser(int, const char *, const char *);
-static void      proc_channels_input(int, Channel *, char *);
-static void      proc_channels_privmsg(int, Channel *, char *);
-static void      proc_server_cmd(int, char *);
+static void      loginkey(const char *);
+static void      loginuser(const char *, const char *);
+static void      proc_channels_input(Channel *, char *);
+static void      proc_channels_privmsg(Channel *, char *);
+static void      proc_server_cmd(char *);
 static int       read_line(int, char *, size_t);
-static void      run(int, const char *);
+static void      run(const char *);
 static void      setup(void);
 static void      sighandler(int);
-static int       tcpopen(const char *, const char *);
 static size_t    tokenize(char **, size_t, char *, int);
-static int       udsopen(const char *);
 static void      usage(void);
 
 static int      isrunning = 1;
@@ -86,21 +80,20 @@ static char     msg[IRC_MSG_MAX];  /* message buf used for communication */
 static void
 usage(void)
 {
-	fprintf(stderr, "usage: %s <-s host> [-i <irc dir>] [-p <port>] "
-	        "[-u <sockname>] [-n <nick>] [-k <password>] "
-	        "[-f <fullname>]\n", argv0);
+	fprintf(stderr, "usage: %s <-s host> [-i <irc dir>] "
+	        "[-n <nick>] [-k <password>] [-f <fullname>]\n", argv0);
 	exit(1);
 }
 
 static void
-ewritestr(int fd, const char *s)
+ewritestr(const char *s)
 {
 	size_t len, off = 0;
 	int w = -1;
 
 	len = strlen(s);
 	for (off = 0; off < len; off += w) {
-		if ((w = write(fd, s + off, len - off)) == -1)
+		if ((w = write(STDOUT_FILENO, s + off, len - off)) == -1)
 			break;
 		off += w;
 	}
@@ -320,81 +313,18 @@ channel_leave(Channel *c)
 }
 
 static void
-loginkey(int ircfd, const char *key)
+loginkey(const char *key)
 {
 	snprintf(msg, sizeof(msg), "PASS %s\r\n", key);
-	ewritestr(ircfd, msg);
+	ewritestr(msg);
 }
 
 static void
-loginuser(int ircfd, const char *host, const char *fullname)
+loginuser(const char *host, const char *fullname)
 {
 	snprintf(msg, sizeof(msg), "NICK %s\r\nUSER %s localhost %s :%s\r\n",
 	         nick, nick, host, fullname);
-	puts(msg);
-	ewritestr(ircfd, msg);
-}
-
-static int
-udsopen(const char *uds)
-{
-	struct sockaddr_un sun;
-	size_t len;
-	int fd;
-
-	if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
-		fprintf(stderr, "%s: socket: %s\n", argv0, strerror(errno));
-		exit(1);
-	}
-
-	sun.sun_family = AF_UNIX;
-	if (strlcpy(sun.sun_path, uds, sizeof(sun.sun_path)) >= sizeof(sun.sun_path)) {
-		fprintf(stderr, "%s: UNIX domain socket path truncation\n", argv0);
-		exit(1);
-	}
-	len = strlen(sun.sun_path) + 1 + sizeof(sun.sun_family);
-	if (connect(fd, (struct sockaddr *)&sun, len) == -1) {
-		fprintf(stderr, "%s: connect: %s\n", argv0, strerror(errno));
-		exit(1);
-	}
-	return fd;
-}
-
-static int
-tcpopen(const char *host, const char *service)
-{
-	struct addrinfo hints, *res = NULL, *rp;
-	int fd = -1, e;
-
-	memset(&hints, 0, sizeof(hints));
-	hints.ai_family = AF_UNSPEC; /* allow IPv4 or IPv6 */
-	hints.ai_flags = AI_NUMERICSERV; /* avoid name lookup for port */
-	hints.ai_socktype = SOCK_STREAM;
-
-	if ((e = getaddrinfo(host, service, &hints, &res))) {
-		fprintf(stderr, "%s: getaddrinfo: %s\n", argv0, gai_strerror(e));
-		exit(1);
-	}
-
-	for (rp = res; rp; rp = rp->ai_next) {
-		fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
-		if (fd == -1)
-			continue;
-		if (connect(fd, res->ai_addr, res->ai_addrlen) == -1) {
-			close(fd);
-			fd = -1;
-			continue;
-		}
-		break; /* success */
-	}
-	if (fd == -1) {
-		fprintf(stderr, "%s: could not connect to %s:%s: %s\n",
-			argv0, host, service, strerror(errno));
-		exit(1);
-	}
-
-	freeaddrinfo(res);
-	return fd;
+	ewritestr(msg);
 }
 
 static int
@@ -446,16 +376,16 @@ channel_print(Channel *c, const char *buf)
 }
 
 static void
-proc_channels_privmsg(int ircfd, Channel *c, char *buf)
+proc_channels_privmsg(Channel *c, char *buf)
 {
 	snprintf(msg, sizeof(msg), "<%s> %s", nick, buf);
 	channel_print(c, msg);
 	snprintf(msg, sizeof(msg), "PRIVMSG %s :%s\r\n", c->name, buf);
-	ewritestr(ircfd, msg);
+	ewritestr(msg);
 }
 
 static void
-proc_channels_input(int ircfd, Channel *c, char *buf)
+proc_channels_input(Channel *c, char *buf)
 {
 	char *p = NULL;
 	size_t buflen;
@@ -463,7 +393,7 @@ proc_channels_input(int ircfd, Channel *c, char *buf)
 	if (buf[0] == '\0')
 		return;
 	if (buf[0] != '/') {
-		proc_channels_privmsg(ircfd, c, buf);
+		proc_channels_privmsg(c, buf);
 		return;
 	}
 
@@ -488,7 +418,7 @@ proc_channels_input(int ircfd, Channel *c, char *buf)
 				channel_join(&buf[3]);
 			} else if (p) {
 				if ((c = channel_join(&buf[3])))
-					proc_channels_privmsg(ircfd, c, p + 1);
+					proc_channels_privmsg(c, p + 1);
 				return;
 			}
 			break;
@@ -520,7 +450,7 @@ proc_channels_input(int ircfd, Channel *c, char *buf)
 			else
 				snprintf(msg, sizeof(msg),
 				         "PART %s :leaving\r\n", c->name);
-			ewritestr(ircfd, msg);
+			ewritestr(msg);
 			channel_leave(c);
 			return;
 			break;
@@ -530,7 +460,7 @@ proc_channels_input(int ircfd, Channel *c, char *buf)
 			else
 				snprintf(msg, sizeof(msg),
 				         "QUIT %s\r\n", "bye");
-			ewritestr(ircfd, msg);
+			ewritestr(msg);
 			isrunning = 0;
 			return;
 			break;
@@ -543,11 +473,11 @@ proc_channels_input(int ircfd, Channel *c, char *buf)
 		snprintf(msg, sizeof(msg), "%s\r\n", &buf[1]);
 	}
 	if (msg[0] != '\0')
-		ewritestr(ircfd, msg);
+		ewritestr(msg);
 }
 
 static void
-proc_server_cmd(int fd, char *buf)
+proc_server_cmd(char *buf)
 {
 	Channel *c;
 	const char *channel;
@@ -595,7 +525,7 @@ proc_server_cmd(int fd, char *buf)
 		return;
 	} else if (!strcmp("PING", argv[TOK_CMD])) {
 		snprintf(msg, sizeof(msg), "PONG %s\r\n", argv[TOK_TEXT]);
-		ewritestr(fd, msg);
+		ewritestr(msg);
 		return;
 	} else if (!argv[TOK_NICKSRV] || !argv[TOK_USER]) {
 		/* server command */
@@ -682,7 +612,7 @@ read_line(int fd, char *buf, size_t bufsiz)
 }
 
 static void
-handle_channels_input(int ircfd, Channel *c)
+handle_channels_input(Channel *c)
 {
 	char buf[IRC_MSG_MAX];
 
@@ -691,22 +621,20 @@ handle_channels_input(int ircfd, Channel *c)
 			channel_rm(c);
 		return;
 	}
-	proc_channels_input(ircfd, c, buf);
+	proc_channels_input(c, buf);
 }
 
 static void
-handle_server_output(int ircfd)
+handle_server_output()
 {
 	char buf[IRC_MSG_MAX];
 
-	if (read_line(ircfd, buf, sizeof(buf)) == -1) {
+	if (read_line(STDIN_FILENO, buf, sizeof(buf)) == -1) {
 		fprintf(stderr, "%s: remote host closed connection: %s\n",
 		        argv0, strerror(errno));
 		exit(1);
 	}
-	fprintf(stdout, "%lu %s\n", (unsigned long)time(NULL), buf);
-	fflush(stdout);
-	proc_server_cmd(ircfd, buf);
+	proc_server_cmd(buf);
 }
 
 static void
@@ -728,7 +656,7 @@ setup(void)
 }
 
 static void
-run(int ircfd, const char *host)
+run(const char *host)
 {
 	Channel *c, *tmp;
 	fd_set rdset;
@@ -738,9 +666,9 @@ run(int ircfd, const char *host)
 
 	snprintf(ping_msg, sizeof(ping_msg), "PING %s\r\n", host);
 	while (isrunning) {
-		maxfd = ircfd;
+		maxfd = STDIN_FILENO;
 		FD_ZERO(&rdset);
-		FD_SET(ircfd, &rdset);
+		FD_SET(STDIN_FILENO, &rdset);
 		for (c = channels; c; c = c->next) {
 			if (c->fdin > maxfd)
 				maxfd = c->fdin;
@@ -759,17 +687,17 @@ run(int ircfd, const char *host)
 				channel_print(channelmaster, "-!- ii shutting down: ping timeout");
 				exit(2); /* status code 2 for timeout */
 			}
-			ewritestr(ircfd, ping_msg);
+			ewritestr(ping_msg);
 			continue;
 		}
-		if (FD_ISSET(ircfd, &rdset)) {
-			handle_server_output(ircfd);
+		if (FD_ISSET(STDIN_FILENO, &rdset)) {
+			handle_server_output();
 			last_response = time(NULL);
 		}
 		for (c = channels; c; c = tmp) {
 			tmp = c->next;
 			if (FD_ISSET(c->fdin, &rdset))
-				handle_channels_input(ircfd, c);
+				handle_channels_input(c);
 		}
 	}
 }
@@ -780,9 +708,8 @@ main(int argc, char *argv[])
 	Channel *c, *tmp;
 	struct passwd *spw;
 	const char *key = NULL, *fullname = NULL, *host = "";
-	const char *uds = NULL, *service = "6667";
 	char prefix[PATH_MAX];
-	int ircfd, r;
+	int r;
 
 	/* use nickname and home dir of user by default */
 	if (!(spw = getpwuid(getuid()))) {
@@ -805,15 +732,9 @@ main(int argc, char *argv[])
 	case 'n':
 		strlcpy(nick, EARGF(usage()), sizeof(nick));
 		break;
-	case 'p':
-		service = EARGF(usage());
-		break;
 	case 's':
 		host = EARGF(usage());
 		break;
-	case 'u':
-		uds = EARGF(usage());
-		break;
 	default:
 		usage();
 		break;
@@ -822,11 +743,6 @@ main(int argc, char *argv[])
 	if (!*host)
 		usage();
 
-	if (uds)
-		ircfd = udsopen(uds);
-	else
-		ircfd = tcpopen(host, service);
-
 #ifdef __OpenBSD__
 	/* OpenBSD pledge(2) support */
 	if (pledge("stdio rpath wpath cpath dpath", NULL) == -1) {
@@ -844,10 +760,10 @@ main(int argc, char *argv[])
 
 	channelmaster = channel_add(""); /* master channel */
 	if (key)
-		loginkey(ircfd, key);
-	loginuser(ircfd, host, fullname && *fullname ? fullname : nick);
+		loginkey(key);
+	loginuser(host, fullname && *fullname ? fullname : nick);
 	setup();
-	run(ircfd, host);
+	run(host);
 	if (channelmaster)
 		channel_leave(channelmaster);