URI: 
       added kris' sic.c and util.c temporarily, will need some time to see what will and won't be integrated into mainstream sic.c - sic - simple irc client
  HTML git clone git://git.suckless.org/sic
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
   DIR commit 14e430ac5b398e0c47f1d80f3c4f4b6386f545c2
   DIR parent 261dc71e58261c801e2be4db413e30b066ecf68f
  HTML Author: Anselm R Garbe <garbeam@gmail.com>
       Date:   Wed, 23 Sep 2009 14:32:20 +0100
       
       added kris' sic.c and util.c temporarily, will need some time to see what will and won't be integrated into mainstream sic.c
       Diffstat:
         A kris/sic.c                          |     223 ++++++++++++++++++++++++++++++
         A kris/util.c                         |      73 +++++++++++++++++++++++++++++++
       
       2 files changed, 296 insertions(+), 0 deletions(-)
       ---
   DIR diff --git a/kris/sic.c b/kris/sic.c
       @@ -0,0 +1,223 @@
       +/* ? 2005-2007 Anselm R. Garbe <garbeam at gmail dot com>
       + * ? 2007 Kris Maglione <fbsdaemon@gmail.com>
       + * ? 2005 Nico Golde <nico at ngolde dot de>
       + * See LICENSE file for license details.
       + */
       +#include <ctype.h>
       +#include <errno.h>
       +#include <stdarg.h>
       +#include <stdio.h>
       +#include <stdlib.h>
       +#include <string.h>
       +#include <time.h>
       +#include <unistd.h>
       +
       +#define nil ((void*)0)
       +typedef unsigned short ushort;
       +
       +#define PINGTIMEOUT 300
       +
       +static char*        host = "irc.oftc.net";
       +static ushort        port = 6667;
       +static char*        password;
       +static char        nick[32];
       +
       +static char bufin[4096];
       +static char bufout[4096];
       +static char channel[256];
       +static time_t trespond;
       +static FILE *srv;
       +
       +#define va_buf(buf, fmt) {\
       +        va_list ap; \
       +        \
       +        va_start(ap, fmt); \
       +        vsnprintf(buf, sizeof buf, fmt, ap); \
       +        va_end(ap); \
       +}
       +
       +#include "util.c"
       +
       +static void
       +pout(char *channel, char *fmt, ...) {
       +        static char timestr[18];
       +        time_t t;
       +
       +        va_buf(bufout, fmt);
       +
       +        t = time(nil);
       +        strftime(timestr, sizeof timestr, "%D %R", localtime(&t));
       +        fprintf(stdout, "%-12s: %s %s\n", channel, timestr, bufout);
       +}
       +
       +static void
       +sout(char *fmt, ...) {
       +        va_buf(bufout, fmt);
       +        fprintf(srv, "%s\r\n", bufout);
       +}
       +
       +static void
       +privmsg(char *channel, char *msg) {
       +        if(channel[0] == '\0') {
       +                pout("", "No channel to send to");
       +                return;
       +        }
       +        pout(channel, "<%s> %s", nick, msg);
       +        sout("PRIVMSG %s :%s", channel, msg);
       +}
       +
       +static void
       +parsein(char *msg) {
       +        char *p;
       +        char c;
       +
       +        if(msg[0] == '\0')
       +                return;
       +        msg = ctok(&msg, '\n');
       +        if(msg[0] != ':') {
       +                privmsg(channel, msg);
       +                return;
       +        }
       +        c = *++msg;
       +        if(!c || !isspace(msg[1]))
       +                sout("%s", msg);
       +        else {
       +                if(msg[1])
       +                        msg += 2;
       +                switch(c) {
       +                case 'j':
       +                        sout("JOIN %s", msg);
       +                        if(channel[0] == '\0')
       +                                strlcpy(channel, msg, sizeof channel);
       +                        break;
       +                case 'l':
       +                        p = tok(&msg);
       +                        if(!*p)
       +                                p = channel;
       +                        if(!*msg)
       +                                msg = "sic - 250 LOC are too much!";
       +                        sout("PART %s :%s", p, msg);
       +                        break;
       +                case 'm':
       +                        p = tok(&msg);
       +                        privmsg(p, msg);
       +                        break;
       +                case 's':
       +                        strlcpy(channel, msg, sizeof channel);
       +                        break;
       +                default:
       +                        sout("%c %s", c, msg);
       +                        break;
       +                }
       +        }
       +}
       +
       +static void
       +parsesrv(char *msg) {
       +        char *cmd, *p, *usr, *txt;
       +
       +        usr = host;
       +        if(!msg || !*msg)
       +                return;
       +        if(msg[0] == ':') {
       +                msg++;
       +                p = tok(&msg);
       +                if(!*msg)
       +                        return;
       +                usr = ctok(&p, '!');
       +        }
       +        txt = ctok(&msg, '\r');
       +        msg = ctok(&txt, ':');
       +        cmd = tok(&msg);
       +        if(!strcmp("PONG", cmd))
       +                return;
       +        if(!strcmp("PRIVMSG", cmd))
       +                pout(msg, "<%s> %s", usr, txt);
       +        else if(!strcmp("PING", cmd))
       +                sout("PONG %s", txt);
       +        else {
       +                pout(usr, ">< %s: %s", cmd, txt);
       +                if(!strcmp("NICK", cmd) && !strcmp(usr, nick))
       +                        strlcpy(nick, txt, sizeof nick);
       +        }
       +}
       +
       +int
       +main(int argc, char *argv[]) {
       +        int i, c;
       +        struct timeval tv;
       +        fd_set rd;
       +
       +        strlcpy(nick, getenv("USER"), sizeof nick);
       +        for(i = 1; i < argc; i++) {
       +                c = argv[i][1];
       +                if(argv[i][0] != '-' || argv[i][2])
       +                        c = -1;
       +                switch(c) {
       +                case 'h':
       +                        if(++i < argc) host = argv[i];
       +                        break;
       +                case 'p':
       +                        if(++i < argc) port = atoi(argv[i]);
       +                        break;
       +                case 'n':
       +                        if(++i < argc) strlcpy(nick, argv[i], sizeof nick);
       +                        break;
       +                case 'k':
       +                        if(++i < argc) password = argv[i];
       +                        break;
       +                case 'v':
       +                        eprint("sic-"VERSION", ? 2005-2007 Anselm R. Garbe, Nico Golde\n");
       +                default:
       +                        eprint("usage: sic [-h host] [-p port] [-n nick] [-k keyword] [-v]\n");
       +                }
       +        }
       +
       +        /* init */
       +        i = dial(host, port);
       +        srv = fdopen(i, "r+");
       +
       +        /* login */
       +        if(password)
       +                sout("PASS %s", password);
       +        sout("NICK %s", nick);
       +        sout("USER %s localhost %s :%s", nick, host, nick);
       +        fflush(srv);
       +
       +        setbuf(stdout, nil);
       +        setbuf(srv, nil);
       +
       +        for(;;) { /* main loop */
       +                FD_ZERO(&rd);
       +                FD_SET(0, &rd);
       +                FD_SET(fileno(srv), &rd);
       +                tv.tv_sec = 120;
       +                tv.tv_usec = 0;
       +                i = select(fileno(srv) + 1, &rd, 0, 0, &tv);
       +                if(i < 0) {
       +                        if(errno == EINTR)
       +                                continue;
       +                        eprint("sic: error on select():");
       +                }
       +                else if(i == 0) {
       +                        if(time(nil) - trespond >= PINGTIMEOUT)
       +                                eprint("sic shutting down: parse timeout\n");
       +                        sout("PING %s", host);
       +                        continue;
       +                }
       +                if(FD_ISSET(fileno(srv), &rd)) {
       +                        if(fgets(bufin, sizeof bufin, srv) == nil)
       +                                eprint("sic: remote host closed connection\n");
       +                        parsesrv(bufin);
       +                        trespond = time(nil);
       +                }
       +                if(FD_ISSET(0, &rd)) {
       +                        if(fgets(bufin, sizeof bufin, stdin) == nil)
       +                                eprint("sic: broken pipe\n");
       +                        parsein(bufin);
       +                }
       +        }
       +        return 0;
       +}
       +
       +
   DIR diff --git a/kris/util.c b/kris/util.c
       @@ -0,0 +1,73 @@
       +#include <netdb.h>
       +#include <netinet/in.h>
       +#include <sys/socket.h>
       +
       +static void
       +eprint(const char *fmt, ...) {
       +
       +        va_buf(bufout, fmt);
       +        fprintf(stderr, "%s", bufout);
       +
       +        if(fmt[0] && fmt[strlen(fmt)-1] == ':')
       +                fprintf(stderr, " %s\n", strerror(errno));
       +        exit(1);
       +}
       +
       +static int
       +dial(char *host, int port) {
       +        struct hostent *hp;
       +        static struct sockaddr_in addr;
       +        int i;
       +
       +        if((i = socket(AF_INET, SOCK_STREAM, 0)) < 0)
       +                eprint("sic: cannot connect host '%s':", host);
       +        if(nil == (hp = gethostbyname(host)))
       +                eprint("sic: cannot resolve hostname '%s': %s\n", host, hstrerror(h_errno));
       +        addr.sin_family = AF_INET;
       +        addr.sin_port = htons(port);
       +        memcpy(&addr.sin_addr, hp->h_addr, hp->h_length);
       +        if(connect(i, (struct sockaddr*)&addr, sizeof(struct sockaddr_in)))
       +                eprint("sic: cannot connect host '%s':", host);
       +        return i;
       +}
       +
       +#define strlcpy _strlcpy
       +static void
       +strlcpy(char *to, const char *from, int l) {
       +        strncpy(to, from, l-1);
       +        to[l-1] = '\0';
       +}
       +
       +static void
       +eat(char **s, int (*p)(int), int r) {
       +        char *q;
       +
       +        for(q=*s; *q && p(*q) == r; q++)
       +                ;
       +        *s = q;
       +}
       +
       +static char*
       +tok(char **s) {
       +        char *p;
       +
       +        eat(s, isspace, 1);
       +        p = *s;
       +        eat(s, isspace, 0);
       +        if(**s) *(*s)++ = '\0';
       +        return p;
       +}
       +
       +static char*
       +ctok(char **s, int c) {
       +        char *p, *q;
       +
       +        q = *s;
       +        for(p=q; *p && *p != c; p++)
       +                ;
       +        if(*p) *p++ = '\0';
       +        *s = p;
       +        return q;
       +}
       +
       +