diff -r ec556de589a3 sic.c
--- a/sic.c	Wed Sep 23 12:52:13 2009 -0400
+++ b/sic.c	Thu Sep 24 02:29:19 2009 +0200
@@ -17,20 +17,20 @@
 #define VERSION "dev"
 #endif
 
+static int dial(char *host, char *port);
 static void die(const char *errstr, ...);
-static void printl(char *channel, char *msg);
+static void printl(char *channel, const char *fmt, ...);
 static void privmsg(char *channel, char *msg);
 static void parsein(char *msg);
 static void parsesrv(char *msg);
-static int readl(int fd, unsigned int len, char *buf);
+static char *readl(FILE *in);
 
 static char *host = "irc6.oftc.net";
 static char *port = "6667";
 static char nick[32];
 
-static char bufin[MAXMSG], bufout[MAXMSG];
 static char channel[256];
-static int srv;
+static FILE *srv;
 static time_t trespond;
 
 void
@@ -43,49 +43,47 @@
 }
 
 void
-printl(char *channel, char *msg) {
+printl(char *channel, const char *fmt, ...) {
 	static char timestr[18];
 	time_t t = time(0);
+	va_list ap;
 	strftime(timestr, sizeof timestr, "%D %R", localtime(&t));
-	fprintf(stdout, "%-12.12s: %s %s\n", channel, timestr, msg);
+	printf("%-12.12s: %s ", channel, timestr);
+	va_start(ap, fmt);
+	vprintf(fmt, ap);
+	va_end(ap);
 }
 
 void
 privmsg(char *channel, char *msg) {
 	if(channel[0] == '\0')
 		return;
-	snprintf(bufout, sizeof bufout, "<%s> %s", nick, msg);
-	printl(channel, bufout);
-	snprintf(bufout, sizeof bufout, "PRIVMSG %s :%s\r\n", channel, msg);
-	write(srv, bufout, strlen(bufout));
+	printl(channel, "<%s> %s\n", nick, msg);
+	fprintf(srv, "PRIVMSG %s :%s\r\n", channel, msg);
 }
 
 void
 parsein(char *msg) {
 	char *p = NULL;
+	if(msg == NULL)
+		die("error: broken pipe\n");
 	if(msg[0] == '\0')
 		return;
-	if(msg[0] != ':') {
+	if(msg[0] != ':')
 		privmsg(channel, msg);
-		return;
-	}
-	if(strncmp(msg + 1, "j ", 2) == 0 && (msg[3] == '#'))
-		snprintf(bufout, sizeof bufout, "JOIN %s\r\n", msg + 3);
+	else if(strncmp(msg + 1, "j ", 2) == 0 && (msg[3] == '#'))
+		fprintf(srv, "JOIN %s\r\n", msg + 3);
 	else if(strncmp(msg + 1, "l ", 2) == 0)
-		snprintf(bufout, sizeof bufout, "PART %s :sic - 250 LOC are too much!\r\n", msg + 3);
+		fprintf(srv, "PART %s :sic - 250 LOC are too much!\r\n", msg + 3);
 	else if(strncmp(msg + 1, "m ", 2) == 0) {
 		if((p = strchr(msg + 3, ' ')))
 			*(p++) = '\0';
 		privmsg(msg + 3, p);
-		return;
 	}
-	else if(strncmp(msg + 1, "s ", 2) == 0) {
+	else if(strncmp(msg + 1, "s ", 2) == 0)
 		strncpy(channel, msg + 3, sizeof channel - 1);
-		return;
-	}
 	else
-		snprintf(bufout, sizeof bufout, "%s\r\n", msg + 1);
-	write(srv, bufout, strlen(bufout));
+		fprintf(srv, "%s\r\n", msg + 1);
 }
 
 void
@@ -94,7 +92,9 @@
 
 	txt = NULL;
 	usr = host;
-	if(msg == NULL || *msg == '\0' )
+	if(msg == NULL)
+		die("error: remote host closed connection\n");
+	if(*msg == '\0')
 		return;
 	if(msg[0] != ':')
 		cmd = msg;
@@ -107,9 +107,6 @@
 		if((p = strchr(usr, '!')))
 			*p = '\0';
 	}
-	for(p = cmd; *p != '\0'; p++) /* remove CRLFs */
-		if(*p == '\r' || *p == '\n')
-			*p = '\0';
 	if((p = strchr(cmd, ':'))) {
 		*p = '\0';
 		txt = ++p;
@@ -123,46 +120,49 @@
 		chan = ++p;
 		for(; *p != '\0' && *p != ' '; p++);
 		*p = '\0';
-		snprintf(bufout, sizeof bufout, "<%s> %s", usr, txt);
-		printl(chan, bufout);
+		printl(chan, "<%s> %s\n", usr, txt);
 	}
-	else if(strncmp("PING", cmd, 4) == 0 && txt != NULL) {
-		snprintf(bufout, sizeof bufout, "PONG %s\r\n", txt);
-		write(srv, bufout, strlen(bufout));
-	}
+	else if(strncmp("PING", cmd, 4) == 0 && txt != NULL)
+		fprintf(srv, "PONG %s\r\n", txt);
 	else {
-		if (txt != NULL)
-			(void) snprintf(bufout, sizeof bufout, ">< %s: %s", cmd, txt);
-		else
-			(void) snprintf(bufout, sizeof bufout, ">< %s: ", cmd);
-		printl(usr, bufout);
-		if(strncmp("NICK", cmd, 4) == 0 && strncmp(usr, nick, sizeof nick) == 0 && txt != NULL)
+		printl(usr, ">< %s: %s\n", cmd, txt ? txt : "");
+		if(strncmp("NICK", cmd, 4) == 0 && strcmp(usr, nick) == 0 && txt != NULL)
 			strncpy(nick, txt, sizeof nick - 1);
 	}
 }
 
-int
-readl(int fd, unsigned int len, char *buf) {
-	unsigned int i = 0;
-	char c = '\0';
-
-	do {
-		if(read(fd, &c, sizeof(char)) != (ssize_t) sizeof(char))
-			return -1;
-		buf[i++] = c;
-	}
-	while(c != '\n' && i < len);
-	buf[i - 1] = '\0';
-	return 0;
+char *readl(FILE *in) {
+	static char bufin[MAXMSG];
+	if(!fgets(bufin, sizeof bufin, in))
+		return NULL;
+	bufin[strcspn(bufin, "\r\n")] = '\0';
+	return bufin;
 }
 
+int dial(char *host, char *port) {
+	int s = -1;
+	struct addrinfo hints = {0}, *res, *r;
+	hints.ai_family = AF_UNSPEC;
+	hints.ai_socktype = SOCK_STREAM;
+	if(getaddrinfo(host, port, &hints, &res) != 0)
+		die("error: cannot resolve hostname '%s'\n", host);
+	for(r = res; r; r = r->ai_next) {
+		if((s = socket(r->ai_family, r->ai_socktype, r->ai_protocol)) == -1)
+			continue;
+		if(connect(s, r->ai_addr, r->ai_addrlen) == 0)
+			break;
+		close(s);
+	}
+	freeaddrinfo(res);
+	if(!r)
+		die("error: cannot connect to host '%s'\n", host);
+	return s;
+}
 
 int
 main(const int argc, char *const argv[]) {
 	int i;
 	struct timeval tv;
-	static struct addrinfo hints, *res, *r;
-	char ping[256];
 	fd_set rd;
 	char *password = NULL;
 
@@ -186,42 +186,24 @@
 			die("usage: sic [-h host] [-p port] [-n nick] [-k keyword] [-v]\n");
 
 	/* init */
-	memset(&hints, 0, sizeof hints);
-	hints.ai_family = AF_UNSPEC;
-	hints.ai_socktype = SOCK_STREAM;
-	if(getaddrinfo(host, port, &hints, &res) != 0)
-		die("error: cannot resolve hostname '%s'\n", host);
-	for(r = res; r; r = r->ai_next) {
-		if((srv = socket(r->ai_family, r->ai_socktype, r->ai_protocol)) == -1)
-			continue;
-		if(connect(srv, r->ai_addr, r->ai_addrlen) == 0)
-			break;
-		close(srv);
-	}
-	freeaddrinfo(res);
-	if(!r)
-		die("error: cannot connect to host '%s'\n", host);
+	srv = fdopen(dial(host, port), "r+");
 
 	/* login */
 	if (password)
-		snprintf(bufout, sizeof bufout,
-		        "PASS %s\r\nNICK %s\r\nUSER %s localhost %s :%s\r\n",
-		        password, nick, nick, host, nick);
-	else
-		snprintf(bufout, sizeof bufout, "NICK %s\r\nUSER %s localhost %s :%s\r\n",
-		         nick, nick, host, nick);
-	write(srv, bufout, strlen(bufout));
-	snprintf(ping, sizeof ping, "PING %s\r\n", host);
+		fprintf(srv, "PASS %s\r\n", password);
+	setbuf(srv, NULL);
+	fprintf(srv, "NICK %s\r\nUSER %s localhost %s :%s\r\n",
+		nick, nick, host, nick);
 	channel[0] = '\0';
 	setbuf(stdout, NULL); /* unbuffered stdout */
 
 	for(;;) { /* main loop */
 		FD_ZERO(&rd);
 		FD_SET(0, &rd);
-		FD_SET(srv, &rd);
+		FD_SET(fileno(srv), &rd);
 		tv.tv_sec = 120;
 		tv.tv_usec = 0;
-		i = select(srv + 1, &rd, 0, 0, &tv);
+		i = select(fileno(srv) + 1, &rd, 0, 0, &tv);
 		if(i < 0) {
 			if(errno == EINTR)
 				continue;
@@ -230,20 +212,15 @@
 		else if(i == 0) {
 			if(time(NULL) - trespond >= PINGTIMEOUT)
 				die("error: sic shutting down: parse timeout\n");
-			write(srv, ping, strlen(ping));
+			fprintf(srv, "PING %s\r\n", host);
 			continue;
 		}
-		if(FD_ISSET(srv, &rd) != 0) {
-			if(readl(srv, sizeof bufin, bufin) == -1)
-				die("error: remote host closed connection\n");
-			parsesrv(bufin);
+		if(FD_ISSET(fileno(srv), &rd) != 0) {
+			parsesrv(readl(srv));
 			trespond = time(NULL);
 		}
-		if(FD_ISSET(0, &rd) != 0) {
-			if(readl(0, sizeof bufin, bufin) == -1)
-				die("error: broken pipe\n");
-			parsein(bufin);
-		}
+		if(FD_ISSET(0, &rd) != 0)
+			parsein(readl(stdin));
 	}
 	return 0;
 }
