14 Commits
0.3 ... 0.6

5 changed files with 68 additions and 81 deletions

View File

@ -1,2 +1,5 @@
de32c537aaf66554894712563ffba8d9bc4c2714 0.1
56350a01f27753cfbdbb3dbc25f2a53dd4c2ac45 0.2
d77f00af559258679a0fad5d264685d663e6975a 0.3
a3549fb4c72ff0edb816c8c29be7ff289db5b003 0.4
70d49a37b35695f2f771bddaf309f05ea60af8bc 0.5

10
README
View File

@ -1,11 +1,11 @@
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
@ -16,11 +16,7 @@ Afterwards enter the following command to build and install sic
$ make clean install
Running sic
-----------
Simply invoke the 'sic' command with the required arguments.
Configuration
-------------
No configuration is needed.

View File

@ -1,5 +1,5 @@
# sic version
VERSION = 0.3
VERSION = 0.6
# Customize below to fit your system

10
sic.1
View File

@ -3,11 +3,11 @@
sic \- simple irc client
.SH SYNOPSIS
.B sic
.RB [ \-s <server> ]
.RB [ \-p <port> ]
.RB [ \-n <nick> ]
.RB [ \-k <keyword> ]
.RB [ \-f <fullname> ]
.RB [ \-s " <server>"]
.RB [ \-p " <port>"]
.RB [ \-n " <nick>"]
.RB [ \-k " <keyword>"]
.RB [ \-f " <fullname>"]
.RB [ \-v ]
.SH DESCRIPTION
.B sic

124
sic.c
View File

@ -1,9 +1,7 @@
/*
* (C)opyright MMV-MMVI Anselm R. Garbe <garbeam at gmail dot com>
/* (C)opyright MMV-MMVI Anselm R. Garbe <garbeam at gmail dot com>
* (C)opyright MMV-MMVI Nico Golde <nico at ngolde dot de>
* See LICENSE file for license details.
*/
#include <errno.h>
#include <netdb.h>
#include <netinet/in.h>
@ -32,10 +30,10 @@ static int srv;
static time_t trespond;
static int
getline(int fd, unsigned int len, char *buf)
{
getline(int fd, unsigned int len, char *buf) {
unsigned int i = 0;
char c;
do {
if(read(fd, &c, sizeof(char)) != sizeof(char))
return -1;
@ -47,18 +45,16 @@ getline(int fd, unsigned int len, char *buf)
}
static void
pout(char *channel, char *msg)
{
pout(char *channel, char *msg) {
static char timestr[18];
time_t t = time(0);
strftime(timestr, sizeof(timestr), "%a %R", localtime(&t));
strftime(timestr, sizeof(timestr), "%F %R", localtime(&t));
fprintf(stdout, "%-8.8s: %s %s\n", channel, timestr, msg);
}
static void
privmsg(char *channel, char *msg)
{
privmsg(char *channel, char *msg) {
snprintf(bufout, sizeof(bufout), "<%s> %s", nick, msg);
pout(channel, bufout);
snprintf(bufout, sizeof(bufout), "PRIVMSG %s :%s\r\n", channel, msg);
@ -66,8 +62,7 @@ privmsg(char *channel, char *msg)
}
static void
parsein(char *msg)
{
parsein(char *msg) {
char *p;
if(msg[0] == 0)
@ -81,7 +76,7 @@ parsein(char *msg)
else if(!strncmp(msg + 1, "l ", 2))
snprintf(bufout, sizeof(bufout), "PART %s :sic\r\n", &msg[3]);
else if(!strncmp(msg + 1, "m ", 2)) {
if(p = strchr(&msg[3], ' '))
if((p = strchr(&msg[3], ' ')))
*(p++) = 0;
privmsg(&msg[3], p);
return;
@ -91,7 +86,7 @@ parsein(char *msg)
return;
}
else if(!strncmp(msg + 1, "t ", 2)) {
if(p = strchr(&msg[3], ' '))
if((p = strchr(&msg[3], ' ')))
*(p++) = 0;
snprintf(bufout, sizeof(bufout), "TOPIC %s :%s\r\n", &msg[3], p);
}
@ -101,8 +96,7 @@ parsein(char *msg)
}
static unsigned int
tokenize(char **result, unsigned int reslen, char *str, char delim)
{
tokenize(char **result, unsigned int reslen, char *str, char delim) {
char *p, *n;
unsigned int i = 0;
@ -127,26 +121,25 @@ tokenize(char **result, unsigned int reslen, char *str, char delim)
}
static void
parsesrv(char *msg)
{
parsesrv(char *msg) {
char *argv[Tlast], *cmd, *p;
int i;
if(!msg || !(*msg))
return;
for(i = 0; i < Tlast; i++)
argv[i] = NULL;
/*
<bufout> ::= [':' <prefix> <SPACE> ] <command> <params> <crlf>
<prefix> ::= <servername> | <nick> [ '!' <user> ] [ '@' <server> ]
<command> ::= <letter> { <letter> } | <number> <number> <number>
<SPACE> ::= ' ' { ' ' }
<params> ::= <SPACE> [ ':' <trailing> | <middle> <params> ]
<middle> ::= <Any *non-empty* sequence of octets not including SPACE
or NUL or CR or LF, the first of which may not be ':'>
<trailing> ::= <Any, possibly *empty*, sequence of octets not including NUL or CR or LF>
<crlf> ::= CR LF
/* <bufout> ::= [':' <prefix> <SPACE> ] <command> <params> <crlf>
* <prefix> ::= <servername> | <nick> [ '!' <user> ] [ '@' <server> ]
* <command> ::= <letter> { <letter> } | <number> <number> <number>
* <SPACE> ::= ' ' { ' ' }
* <params> ::= <SPACE> [ ':' <trailing> | <middle> <params> ]
* <middle> ::= <Any *non-empty* sequence of octets not including SPACE
* or NUL or CR or LF, the first of which may not be ':'>
* <trailing> ::= <Any, possibly *empty*, sequence of octets not including NUL or CR or LF>
* <crlf> ::= CR LF
*/
if(msg[0] == ':') { /* check prefix */
p = strchr(msg, ' ');
@ -160,29 +153,28 @@ parsesrv(char *msg)
}
} else
cmd = msg;
/* remove CRLFs */
for(p = cmd; p && *p != 0; p++)
if(*p == '\r' || *p == '\n')
*p = 0;
if((p = strchr(cmd, ':'))) {
*p = 0;
argv[Ttext] = ++p;
}
tokenize(&argv[Tcmd], Tlast - Tcmd, cmd, ' ');
if(!strncmp("PONG", argv[Tcmd], 5)) {
if(!strncmp("PONG", argv[Tcmd], 5))
return;
} else if(!strncmp("PING", argv[Tcmd], 5)) {
else if(!strncmp("PING", argv[Tcmd], 5)) {
snprintf(bufout, sizeof(bufout), "PONG %s\r\n", argv[Ttext]);
write(srv, bufout, strlen(bufout));
return;
} else if(!argv[Tnick] || !argv[Tuser]) { /* server command */
}
else if(!argv[Tnick] || !argv[Tuser]) { /* server command */
snprintf(bufout, sizeof(bufout), "%s", argv[Ttext] ? argv[Ttext] : "");
pout(server, bufout);
return;
} else if(!strncmp("ERROR", argv[Tcmd], 6))
}
else if(!strncmp("ERROR", argv[Tcmd], 6))
snprintf(bufout, sizeof(bufout), "-!- error %s",
argv[Ttext] ? argv[Ttext] : "unknown");
else if(!strncmp("JOIN", argv[Tcmd], 5)) {
@ -194,10 +186,12 @@ parsesrv(char *msg)
argv[Tchan] = argv[Ttext];
snprintf(bufout, sizeof(bufout), "-!- %s(%s) has joined %s",
argv[Tnick], argv[Tuser], argv[Ttext]);
} else if(!strncmp("PART", argv[Tcmd], 5)) {
}
else if(!strncmp("PART", argv[Tcmd], 5)) {
snprintf(bufout, sizeof(bufout), "-!- %s(%s) has left %s",
argv[Tnick], argv[Tuser], argv[Tchan]);
} else if(!strncmp("MODE", argv[Tcmd], 5))
}
else if(!strncmp("MODE", argv[Tcmd], 5))
snprintf(bufout, sizeof(bufout), "-!- %s changed mode/%s -> %s %s",
argv[Tnick], argv[Tcmd + 1],
argv[Tcmd + 2], argv[Tcmd + 3]);
@ -228,8 +222,7 @@ parsesrv(char *msg)
}
int
main(int argc, char *argv[])
{
main(int argc, char *argv[]) {
int i;
struct timeval tv;
struct hostent *hp;
@ -238,34 +231,31 @@ main(int argc, char *argv[])
fd_set rd;
nick = fullname = getenv("USER");
for(i = 1; (i < argc) && (argv[i][0] == '-'); i++) {
switch (argv[i][1]) {
default:
for(i = 1; i < argc; i++)
if(!strncmp(argv[i], "-s", 3)) {
if(++i < argc) server = argv[i];
}
else if(!strncmp(argv[i], "-p", 3)) {
if(++i < argc) port = (unsigned short)atoi(argv[i]);
}
else if(!strncmp(argv[i], "-n", 3)) {
if(++i < argc) nick = argv[i];
}
else if(!strncmp(argv[i], "-k", 3)) {
if(++i < argc) password = argv[i];
}
else if(!strncmp(argv[i], "-f", 3)) {
if(++i < argc) fullname = argv[i];
}
else if(!strncmp(argv[i], "-v", 3)) {
fputs("sic-"VERSION", (C)opyright MMVI Anselm R. Garbe\n", stdout);
exit(EXIT_SUCCESS);
}
else {
fputs("usage: sic [-s server] [-p port] [-n nick]"
" [-k keyword] [-f fullname] [-v]\n", stderr);
exit(EXIT_FAILURE);
break;
case 's':
server = argv[++i];
break;
case 'p':
port = (unsigned short)atoi(argv[++i]);
break;
case 'n':
nick = argv[++i];
break;
case 'k':
password = argv[++i];
break;
case 'f':
fullname = argv[++i];
break;
case 'v':
fputs("sic-"VERSION", (C)opyright MMVI Anselm R. Garbe\n", stdout);
exit(EXIT_SUCCESS);
break;
}
}
/* init */
if((srv = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
@ -284,7 +274,6 @@ main(int argc, char *argv[])
fprintf(stderr, "sic: cannot connect server '%s'\n", server);
exit(EXIT_FAILURE);
}
/* login */
if(password)
snprintf(bufout, sizeof(bufout),
@ -294,11 +283,11 @@ main(int argc, char *argv[])
snprintf(bufout, sizeof(bufout), "NICK %s\r\nUSER %s localhost %s :%s\r\n",
nick, nick, server, fullname);
write(srv, bufout, strlen(bufout));
snprintf(ping, sizeof(ping), "PING %s\r\n", server);
channel[0] = 0;
setbuf(stdout, NULL); /* unbuffered stdout */
for(;;) {
for(;;) { /* main loop */
FD_ZERO(&rd);
FD_SET(0, &rd);
FD_SET(srv, &rd);
@ -312,7 +301,7 @@ main(int argc, char *argv[])
exit(EXIT_FAILURE);
} else if(i == 0) {
if(time(NULL) - trespond >= PINGTIMEOUT) {
pout(server, "-!- sic shutting down: parseing timeout");
pout(server, "-!- sic shutting down: parse timeout");
exit(EXIT_FAILURE);
}
write(srv, ping, strlen(ping));
@ -334,6 +323,5 @@ main(int argc, char *argv[])
parsein(bufin);
}
}
return 0;
}