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; }