From 759063908d19e592f0d3bb3759964cec35114c8c Mon Sep 17 00:00:00 2001 From: "Anselm R. Garbe" Date: Mon, 17 Jul 2006 18:17:31 +0200 Subject: [PATCH] initial commit --- LICENSE | 22 ++++ Makefile | 53 ++++++++ README | 26 ++++ config.mk | 15 +++ sic | Bin 0 -> 22978 bytes sic.1 | 57 ++++++++ sic.c | 387 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ sic.o | Bin 0 -> 19984 bytes 8 files changed, 560 insertions(+) create mode 100644 LICENSE create mode 100644 Makefile create mode 100644 README create mode 100644 config.mk create mode 100755 sic create mode 100644 sic.1 create mode 100644 sic.c create mode 100644 sic.o diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..c64b537 --- /dev/null +++ b/LICENSE @@ -0,0 +1,22 @@ +MIT/X Consortium License + +(C)opyright MMV-MMVI Anselm R. Garbe +(C)opyright MMV Nico Golde + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..9c11042 --- /dev/null +++ b/Makefile @@ -0,0 +1,53 @@ +# ii - irc it - simple but flexible IRC client +# (C)opyright MMV Anselm R. Garbe, Nico Golde + +include config.mk + +SRC = sic.c +OBJ = ${SRC:.c=.o} +MAN1 = sic.1 +BIN = sic + +all: options sic + @echo built sic + +options: + @echo ii build options: + @echo "LIBS = ${LIBS}" + @echo "CFLAGS = ${CFLAGS}" + @echo "LDFLAGS = ${LDFLAGS}" + @echo "CC = ${CC}" + +.c.o: + @echo CC $< + @${CC} -c ${CFLAGS} $< + +clean: + rm -f sic *.o core sic-${VERSION}.tar.gz + +dist: clean + @mkdir -p sic-${VERSION} + @cp -R Makefile README LICENSE config.mk sic.c sic.1 sic-${VERSION} + @tar -cf sic-${VERSION}.tar sic-${VERSION} + @gzip sic-${VERSION}.tar + @rm -rf sic-${VERSION} + +sic: ${OBJ} + @echo LD $@ + @${CC} -o $@ ${OBJ} ${LDFLAGS} + +install: all + @mkdir -p ${DESTDIR}${PREFIX}/bin + @cp -f ${BIN} ${DESTDIR}${PREFIX}/bin + @echo installed executable files to ${DESTDIR}${PREFIX}/bin + @mkdir -p ${DESTDIR}${MANPREFIX}/man1 + @cp -f ${MAN1} ${DESTDIR}${MANPREFIX}/man1 + @echo installed manual pages to ${DESTDIR}${MANPREFIX}/man1 + +uninstall: + for i in ${BIN}; do \ + rm -f ${DESTDIR}${PREFIX}/bin/`basename $$i`; \ + done + for i in ${MAN1}; do \ + rm -f ${DESTDIR}${MANPREFIX}/man1/`basename $$i`; \ + done diff --git a/README b/README new file mode 100644 index 0000000..09a06c7 --- /dev/null +++ b/README @@ -0,0 +1,26 @@ +sic - simple irc client +----------------------- + +sic is an extremly fast, small and simple irc client. It reads commands from +standard input and prints all server output to standard output. It multiplexes +also all channel traffic into one output, that you don't have to switch +different channel buffers, that's actually a feature. + +Installation +------------ +Edit config.mk to match your local setup. sic is installed into +/usr/local by default. + +Afterwards enter the following command to build and install sic +(if necessary as root): + + $ make clean install + +Running sic +----------- +Simply invoke the 'sic' command with the required arguments. + + +Configuration +------------- +No configuration is needed. diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..6b45112 --- /dev/null +++ b/config.mk @@ -0,0 +1,15 @@ +# Customize to fit your system + +# paths +PREFIX = /usr/local +MANPREFIX = ${PREFIX}/share/man + +VERSION = 0.0 + +# includes and libs +LIBS = -L${PREFIX}/lib -L/usr/lib -lc + +# compiler +CFLAGS = -g -Wall -O2 -I${PREFIX}/include -I/usr/include \ + -DVERSION=\"${VERSION}\" +LDFLAGS = -g ${LIBS} diff --git a/sic b/sic new file mode 100755 index 0000000000000000000000000000000000000000..bceff5b894e32f0fea64da1f7983c43a6d3965ea GIT binary patch literal 22978 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 E0eKCVB>(^b literal 0 HcmV?d00001 diff --git a/sic.1 b/sic.1 new file mode 100644 index 0000000..06cf0db --- /dev/null +++ b/sic.1 @@ -0,0 +1,57 @@ +.TH SIC 1 sic-0.0 +.SH NAME +sic \- simple irc client +.SH SYNOPSIS +.B sic +.RB \-a +.IR address +.RB [ \-n +.IR nick ] +.RB [ \-f +.IR fullname ] +.RB [ \-p +.IR password ] +.RB [ \-v ] +.SH DESCRIPTION +.B sic +is an extremly fast, small and simple irc client. It reads commands from +standard input and prints all server output to standard output. It multiplexes +also all channel traffic into one output, that you don't have to switch +different channel buffers, that's actually a feature. +.SH OPTIONS +.TP +.BI \-a " address " +Lets you specify the address which +.B sic +uses to listen for connections. The syntax for +.I address +is taken (along with many other profound ideas) from the Plan 9 operating +system and has the form +.B tcp!hostname!port +for tcp sockets. +.BI \-p " password" +Specifies the password to authenticate the nick on the server. +.TP +.BI \-n " nick " +Specifies the nick name (default: $USER). +.TP +.BI \-f " fullname " +Specifies the full name. +.BI \-v +Prints version information to standard output, then exits. +.SH COMMANDS +.TP +.FN /j " #channel/user " +join/query a channel/user +.TP +.FN /l " #channel " +leave a channel/query +.TP +.FN /m " #channel/user msg " +write a message to #channel/user +.FN /t " topic" +set the channel topic +.TP +Everything which is not a command will simply be posted into the channel or to +the server. +.TP diff --git a/sic.c b/sic.c new file mode 100644 index 0000000..4ec3a75 --- /dev/null +++ b/sic.c @@ -0,0 +1,387 @@ +/* + * (C)opyright MMV-MMVI Anselm R. Garbe + * (C)opyright MMV-MMVI Nico Golde + * See LICENSE file for license details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PING_TIMEOUT 300 +#define MAXMSG 4096 + +enum { TOK_NICKSRV = 0, TOK_USER, TOK_CMD, TOK_CHAN, TOK_ARG, TOK_TEXT, TOK_LAST }; + +static int irc; +static time_t last_response; +static char nick[32]; /* might change while running */ +static char message[MAXMSG]; /* message buf used for communication */ +static char *host = NULL; + +static int +tcpopen(char *address) +{ + int fd = 0; + char *port; + struct sockaddr_in addr = { 0 }; + struct hostent *hp; + unsigned int prt; + + if((host = strchr(address, '!'))) + *(host++) = 0; + + if(!(port = strrchr(host, '!'))) + return -1; + *port = 0; + port++; + if(sscanf(port, "%d", &prt) != 1) + return -1; + + /* init */ + if((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) + return -1; + hp = gethostbyname(host); + addr.sin_family = AF_INET; + addr.sin_port = htons(prt); + bcopy(hp->h_addr, &addr.sin_addr, hp->h_length); + + if(connect(fd, (struct sockaddr *) &addr, + sizeof(struct sockaddr_in))) { + close(fd); + return -1; + } + return fd; +} + +unsigned int +tokenize(char **result, unsigned int reslen, char *str, char delim) +{ + char *p, *n; + unsigned int i = 0; + + if(!str) + return 0; + for(n = str; *n == delim; n++); + p = n; + for(i = 0; *n != 0;) { + if(i == reslen) + return i; + if(*n == delim) { + *n = 0; + if(strlen(p)) + result[i++] = p; + p = ++n; + } else + n++; + } + if((i < reslen) && (p < n) && strlen(p)) + result[i++] = p; + return i; /* number of tokens */ +} + +static void +print_out(char *channel, char *buf) +{ + static char buft[18]; + time_t t = time(0); + + strftime(buft, sizeof(buft), "%F %R", localtime(&t)); + fprintf(stdout, "%s: %s %s\n", channel, buft, buf); +} + +static void +proc_channels_privmsg(char *channel, char *buf) +{ + snprintf(message, MAXMSG, "<%s> %s", nick, buf); + print_out(channel, message); + snprintf(message, MAXMSG, "PRIVMSG %s :%s\r\n", channel, buf); + write(irc, message, strlen(message)); +} + +static void +proc_channels_input(char *buf) +{ + char *p; + + if((p = strchr(buf, ' '))) + *(p++) = 0; + if(buf[0] != '/' && buf[0] != 0) { + proc_channels_privmsg(buf, p); + return; + } + if((p = strchr(&buf[3], ' '))) + *(p++) = 0; + switch (buf[1]) { + case 'j': + if(buf[3] == '#') + snprintf(message, MAXMSG, "JOIN %s\r\n", &buf[3]); + else if(p) { + proc_channels_privmsg(&buf[3], p + 1); + return; + } + break; + case 't': + snprintf(message, MAXMSG, "TOPIC %s :%s\r\n", &buf[3], p); + break; + case 'l': + if(p) + snprintf(message, MAXMSG, "PART %s :%s\r\n", &buf[3], p); + else + snprintf(message, MAXMSG, "PART %s :sic - 300 SLOC are too much\r\n", &buf[3]); + write(irc, message, strlen(message)); + return; + break; + default: + snprintf(message, MAXMSG, "%s\r\n", &buf[1]); + break; + } + write(irc, message, strlen(message)); +} + +static void +proc_server_cmd(char *buf) +{ + char *argv[TOK_LAST], *cmd, *p; + int i; + if(!buf || *buf=='\0') + return; + + for(i = 0; i < TOK_LAST; i++) + argv[i] = NULL; + + /* + ::= [':' ] + ::= | [ '!' ] [ '@' ] + ::= { } | + ::= ' ' { ' ' } + ::= [ ':' | ] + ::= + ::= + ::= CR LF + */ + if(buf[0] == ':') { /* check prefix */ + p = strchr(buf, ' '); + *p = 0; + for(++p; *p == ' '; p++); + cmd = p; + argv[TOK_NICKSRV] = &buf[1]; + if((p = strchr(buf, '!'))) { + *p = 0; + argv[TOK_USER] = ++p; + } + } else + cmd = buf; + + /* remove CRLFs */ + for(p = cmd; p && *p != 0; p++) + if(*p == '\r' || *p == '\n') + *p = 0; + + if((p = strchr(cmd, ':'))) { + *p = 0; + argv[TOK_TEXT] = ++p; + } + tokenize(&argv[TOK_CMD], TOK_LAST - TOK_CMD, cmd, ' '); + + if(!strncmp("PONG", argv[TOK_CMD], 5)) { + return; + } else if(!strncmp("PING", argv[TOK_CMD], 5)) { + snprintf(message, MAXMSG, "PONG %s\r\n", argv[TOK_TEXT]); + write(irc, message, strlen(message)); + return; + } else if(!argv[TOK_NICKSRV] || !argv[TOK_USER]) { /* server command */ + snprintf(message, MAXMSG, "%s", argv[TOK_TEXT] ? argv[TOK_TEXT] : ""); + print_out(0, message); + return; + } else if(!strncmp("ERROR", argv[TOK_CMD], 6)) + snprintf(message, MAXMSG, "-!- error %s", + argv[TOK_TEXT] ? argv[TOK_TEXT] : "unknown"); + else if(!strncmp("JOIN", argv[TOK_CMD], 5)) { + if(argv[TOK_TEXT]!=NULL){ + p = strchr(argv[TOK_TEXT], ' '); + if(p) + *p = 0; + } + argv[TOK_CHAN] = argv[TOK_TEXT]; + snprintf(message, MAXMSG, "-!- %s(%s) has joined %s", + argv[TOK_NICKSRV], argv[TOK_USER], argv[TOK_TEXT]); + } else if(!strncmp("PART", argv[TOK_CMD], 5)) { + snprintf(message, MAXMSG, "-!- %s(%s) has left %s", + argv[TOK_NICKSRV], argv[TOK_USER], argv[TOK_CHAN]); + } else if(!strncmp("MODE", argv[TOK_CMD], 5)) + snprintf(message, MAXMSG, "-!- %s changed mode/%s -> %s %s", + argv[TOK_NICKSRV], argv[TOK_CMD + 1], + argv[TOK_CMD + 2], argv[TOK_CMD + 3]); + else if(!strncmp("QUIT", argv[TOK_CMD], 5)) + snprintf(message, MAXMSG, "-!- %s(%s) has quit \"%s\"", + argv[TOK_NICKSRV], argv[TOK_USER], + argv[TOK_TEXT] ? argv[TOK_TEXT] : ""); + else if(!strncmp("NICK", argv[TOK_CMD], 5)) + snprintf(message, MAXMSG, "-!- %s changed nick to %s", + argv[TOK_NICKSRV], argv[TOK_TEXT]); + else if(!strncmp("TOPIC", argv[TOK_CMD], 6)) + snprintf(message, MAXMSG, "-!- %s changed topic to \"%s\"", + argv[TOK_NICKSRV], argv[TOK_TEXT] ? argv[TOK_TEXT] : ""); + else if(!strncmp("KICK", argv[TOK_CMD], 5)) + snprintf(message, MAXMSG, "-!- %s kicked %s (\"%s\")", + argv[TOK_NICKSRV], argv[TOK_ARG], + argv[TOK_TEXT] ? argv[TOK_TEXT] : ""); + else if(!strncmp("NOTICE", argv[TOK_CMD], 7)) + snprintf(message, MAXMSG, "-!- \"%s\")", + argv[TOK_TEXT] ? argv[TOK_TEXT] : ""); + else if(!strncmp("PRIVMSG", argv[TOK_CMD], 8)) + snprintf(message, MAXMSG, "<%s> %s", + argv[TOK_NICKSRV], argv[TOK_TEXT] ? argv[TOK_TEXT] : ""); + if(!argv[TOK_CHAN] || !strncmp(argv[TOK_CHAN], nick, strlen(nick))) + print_out(argv[TOK_NICKSRV], message); + else + print_out(argv[TOK_CHAN], message); +} + +static int +read_line(int fd, unsigned int res_len, char *buf) +{ + unsigned int i = 0; + char c; + do { + if(read(fd, &c, sizeof(char)) != sizeof(char)) + return -1; + buf[i++] = c; + } + while(c != '\n' && i < res_len); + buf[i - 1] = 0; /* eliminates '\n' */ + return 0; +} + +static void +handle_server_output() +{ + static char buf[MAXMSG]; + if(read_line(irc, MAXMSG, buf) == -1) { + perror("sic: remote host closed connection"); + exit(EXIT_FAILURE); + } + proc_server_cmd(buf); +} + +int +main(int argc, char *argv[]) +{ + char address[256]; + char *password = NULL; + char *fullname = NULL; + char ping_msg[512], buf[MAXMSG]; + int i, n, r, maxfd; + struct passwd *spw = getpwuid(getuid()); + struct timeval tv; + fd_set rd; + + if(!spw) { + fprintf(stderr,"sic: getpwuid() failed\n"); + exit(EXIT_FAILURE); + } + snprintf(nick, sizeof(nick), "%s", spw->pw_name); + + if(argc == 2 && argv[1][0] == '-' && argv[1][1] == 'h') + goto Usage; + + address[0] = 0; + for(i = 1; (i + 1 < argc) && (argv[i][0] == '-'); i++) { + switch (argv[i][1]) { + default: +Usage: + fputs("usage: sic -a address [-n nick] [-f fullname] [-p password] [-v]\n", + stdout); + exit(EXIT_FAILURE); + break; + case 'a': + strncpy(address, argv[++i], sizeof(address)); + break; + case 'n': + snprintf(nick, sizeof(nick), "%s", argv[++i]); + break; + case 'p': + password = argv[++i]; + break; + case 'f': + fullname = argv[++i]; + break; + } + } + + if(!address[0]) + goto Usage; + + if((irc = tcpopen(address)) == -1) { + fprintf(stderr, "sic: cannot connect server '%s'\n", address); + exit(EXIT_FAILURE); + } + /* login */ + if(password) + snprintf(message, MAXMSG, + "PASS %s\r\nNICK %s\r\nUSER %s localhost %s :%s\r\n", + password, nick, nick, host, fullname ? fullname : nick); + else + snprintf(message, MAXMSG, "NICK %s\r\nUSER %s localhost %s :%s\r\n", + nick, nick, host, fullname ? fullname : nick); + write(irc, message, strlen(message)); + + snprintf(ping_msg, sizeof(ping_msg), "PING %s\r\n", host); + for(;;) { + FD_ZERO(&rd); + maxfd = irc; + FD_SET(0, &rd); + FD_SET(irc, &rd); + tv.tv_sec = 120; + tv.tv_usec = 0; + r = select(maxfd + 1, &rd, 0, 0, &tv); + if(r < 0) { + if(errno == EINTR) + continue; + perror("sic: error on select()"); + exit(EXIT_FAILURE); + } else if(r == 0) { + if(time(NULL) - last_response >= PING_TIMEOUT) { + print_out(NULL, "-!- sic shutting down: ping timeout"); + exit(EXIT_FAILURE); + } + write(irc, ping_msg, strlen(ping_msg)); + continue; + } + if(FD_ISSET(irc, &rd)) { + handle_server_output(); + last_response = time(NULL); + } + if(FD_ISSET(0, &rd)) { + i = n = 0; + for(;;) { + if((i = getchar()) == EOF) { + perror("sic: broken pipe"); + exit(EXIT_FAILURE); + } + if(i == '\n' || n >= sizeof(buf) - 1) + break; + buf[n++] = i; + } + buf[n] = 0; + proc_channels_input(buf); + } + } + + return 0; +} diff --git a/sic.o b/sic.o new file mode 100644 index 0000000000000000000000000000000000000000..a79c11238da7c7f696cab166c0b1602da663afcd GIT binary patch literal 19984 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�e$4oak^#U*a7%`xz|i6}(+MM^P&@(m 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 Ygg#g3H9}t`G^S6*Gn9jT*THf4zu0Y9!T