#include <ctype.h>
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/syscall.h>
static char *nick = "cbot_git";
static char *hostname = "irc.freenode.net";
static char *port = "6667";
static char *channel = "#mainlv";
static int conn;
#define IO_STR str_cat_buf
#define SYSC_WRITE(FD,X) write(FD,X,strlen(X));
#define SYSC_WRITE_O(FD,STR) write(FD,(STR).str,(STR).sz);write(0,"<< ",4);write(0,(STR).str,(STR).sz);
#define SYSC_WRITE_I(FD,STR) write(FD,(STR).str,(STR).sz);write(0,">> ",4);write(0,(STR).str,(STR).sz);
#define SYSC_WRITE_IO0(FD) write(FD,(IO_STR).str,(IO_STR).sz);write(0,"<< ",4);write(0,(IO_STR).str,(IO_STR).sz);
#define BUF_0(BUF) (BUF).sz=0;
#define BUF_ADD_STR(BUF,X) str_cat(BUF,X);
#define BUF_ADD_CHAR(BUF,C) {(BUF).str[(BUF).sz]=C;(BUF).sz+=1;}
#define BUF_CHAR(BUF,IDX) (BUF).str[IDX]
#define BUF_SZ(BUF) (BUF).sz
#define BUF_MAX(BUF) ((BUF).sz==BUF_MAX_SZ)
#define BUF_SET0(BUF) (BUF).str[(BUF).sz]=0;
#define BUF_STRCMP(BUF,STR) (!strncmp((BUF).str,STR,strlen(STR)))
#define STR_0() (IO_STR).sz=0;
#define STR_ADD(X) str_cat((&IO_STR),X);
#define BUF_MAX_SZ 1024
typedef struct pos_str
{
int sz;
char str[BUF_MAX_SZ+1];
} pos_str;
pos_str str_cat_buf;
pos_str str_buf;
pos_str serv_read;
pos_str serv_write;
#define TOK_CMP(IDX,STR) ((strlen(STR)==strlen(tok[IDX].s)) && !(strncmp(tok[IDX].s,STR,strlen(STR))))
#define TOK_NUM 20
typedef struct token
{
char *s, *e;
} token;
static int tok_cnt=0;
token tok[TOK_NUM];
char* skip(char *s, char c)
{
while(*s != c && *s != '\0')
{
s++;
}
if(*s != '\0')
{
*s++ = '\0';
}
return s;
}
int str_cat(pos_str *buf, char *str)
{
int i;
int pos=0;
int len = strlen(str);
pos = buf->sz;
for (i=0;(i<len)&&(pos+i<BUF_MAX_SZ);i++)
{
buf->str[pos+i] = str[i];
}
buf->sz = pos+i;
return pos;
}
int print_str(int fd, char *str)
{
int ret = 0;
int len = strlen(str);
write(fd, str, len);
return ret;
}
/*
return fd!=ifconnection there
*/
int irc_connect( char *hostname, char *port )
{
int fd=0;
struct addrinfo serv, *res;
memset(&serv, 0, sizeof(serv));
serv.ai_family = AF_INET;
serv.ai_socktype = SOCK_STREAM;
getaddrinfo(hostname, port, &serv, &res);
fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
connect(fd, res->ai_addr, res->ai_addrlen);
return fd;
}
int main()
{
int i,j,m,len;
int ret;
char ch;
int wordcount;
char *user, *command, *where, *message, *iter, *start, *sep;
print_str(0,"Start programm\n");
//connect to server
conn = irc_connect( hostname, port );
if (conn<1)
{
SYSC_WRITE(1,"Cannot connect\n");
return -1;
}
//send USER command
STR_0();
STR_ADD("USER ");
STR_ADD(nick);
STR_ADD(" 0 0 :");
STR_ADD(nick);
STR_ADD("\r\n");
SYSC_WRITE_IO0(conn);
//send NICK command
STR_0();
STR_ADD("NICK ");
STR_ADD(nick);
STR_ADD("\r\n");
SYSC_WRITE_IO0(conn);
BUF_0(str_buf);
//server communication loop
while (ret=read(conn, serv_read.str, BUF_MAX_SZ))
{
serv_read.sz = ret;
serv_read.str[ret];
//SYSC_WRITE_I(0,serv_read);
//parse to get commands
for (i=0;i<BUF_SZ(serv_read);i++)
{
BUF_ADD_CHAR(str_buf,BUF_CHAR(serv_read,i));
ch = BUF_CHAR(serv_read,i);
if ((i>0
&& (BUF_CHAR(serv_read,i) == '\n')
&& (BUF_CHAR(serv_read,i-1) == '\r'))
||
(BUF_MAX(str_buf)))
{
BUF_SET0(str_buf);
len = BUF_SZ(str_buf);
//printf("len = %d\n",len);
SYSC_WRITE_I(0,str_buf);
//BUF_0(str_buf);
//check if ping then answer to ping
//if (BUF_STRCMP(str_buf,"PING"))
//{
// STR_0();
// STR_ADD("PONG\r\n")
// SYSC_WRITE_IO0(conn);
//} else
if (BUF_CHAR(str_buf,0) == ':')
{
#define START 1
#define START_WORD 2
#define CONTINUE 3
#define MESSAGE 4
#define END 5
int state = START;
//printf("TOKENIZING\n");
//tokenize string
tok_cnt = 0;
iter = str_buf.str;
for (j=0;j<len;j++)
{
switch(state)
{
case START:
//printf("START %d %02x\n",j,iter[j]);
if (iter[j]==' ')
{
break;
}
if (iter[j]=='\0')
{
state = END;
break;
}
state = START_WORD;
break;
case START_WORD:
//printf("WORD\n");
tok[tok_cnt].s = iter+j;
if (iter[j]==' ')
{
tok[tok_cnt].e = iter+j-1;
tok_cnt += 1;
state = START;
break;
}
if (iter[j]=='\0')
{
tok[tok_cnt].e = iter+j-1;
tok_cnt += 1;
state = END;
break;
}
if (iter[j]==':')
{
tok[tok_cnt].s = iter+j;
//tok_cnt += 1;
state = MESSAGE;
break;
}
state = CONTINUE;
break;
case CONTINUE:
//printf("CONTINUE\n");
if ((iter[j]!=' ')&&(iter[j]!='\0'))
{
state = CONTINUE;
break;
}
if (iter[j]=='\0')
{
tok[tok_cnt].e = iter+j-1;
tok_cnt += 1;
state = END;
break;
}
if (iter[j]==' ')
{
tok[tok_cnt].e = iter+j-1;
tok_cnt += 1;
state = START_WORD;
break;
}
//printf("Unknown state\n");
break;
case MESSAGE:
//printf("MESSAGE\n");
if ((iter[j]=='\0')||(iter[j]=='\n')||(iter[j]=='\r'))
{
tok[tok_cnt].e = iter+j-1;
tok_cnt += 1;
state = END;
break;
}
state = MESSAGE;
break;
case END:
//printf("END\n");
break;
default:
printf("ERR STATE %d\n",state);
return 0;
};
}
if ((state==CONTINUE)||(state==MESSAGE))
{
tok[tok_cnt].e = iter+j-1;
tok_cnt += 1;
}
for (j=0;j<tok_cnt;j++)
{
write(0,tok[j].s,tok[j].e-tok[j].s+1);
*(tok[j].e+1)=0x0;
write(0,"]\n",2);
}
if (tok_cnt < 2 ) continue;
//replay on commands
printf("CMD: %s\n",tok[1].s);
if (TOK_CMP(1,"NOTICE?"))
{
STR_0();
STR_ADD(tok[1].s);//command
STR_ADD(" ");
STR_ADD(tok[2].s)
STR_ADD(" ");
STR_ADD(tok[3].s);//message
STR_ADD("\r\n");
SYSC_WRITE_IO0(conn);
} else if (TOK_CMP(1,"PING"))
{
STR_0();
STR_ADD("PONG :");
STR_ADD(tok[0].s);
STR_ADD("\r\n");
SYSC_WRITE_IO0(conn);
} else if (TOK_CMP(1,"PRIVMSG"))
{
//join command
if (TOK_CMP(3,":JOIN"))
{
STR_0();
STR_ADD("JOIN ");
STR_ADD(channel)
STR_ADD("\r\n");
SYSC_WRITE_IO0(conn);
//echo
} else
{
//if there is chan name then ech to chan
if (tok[2].s[0]=='#')
{
STR_0();
STR_ADD(tok[1].s);//command
STR_ADD(" ");
STR_ADD(tok[2].s);
STR_ADD(" :");
STR_ADD(tok[3].s+1);
STR_ADD("\r\n");
SYSC_WRITE_IO0(conn);
} else
{
//get user name
sep = strchr(tok[0].s,'!');
tok[0].s[sep-tok[0].s] = 0x0;
STR_0();
STR_ADD(tok[1].s);//command
STR_ADD(" ");
STR_ADD(tok[0].s)
STR_ADD(" :");
//STR_ADD(tok[2].s);
//STR_ADD("-");
STR_ADD(tok[3].s+1);//message
STR_ADD("\r\n");
SYSC_WRITE_IO0(conn);
}
}
}
}
BUF_0(str_buf);
}
}
}
print_str(0,"End program\n");
return 0;
}