summaryrefslogtreecommitdiff
path: root/mini_irc/mini_irc.c
diff options
context:
space:
mode:
authorFreeArtMan <dos21h@gmail.com>2016-08-21 10:14:02 +0100
committerFreeArtMan <dos21h@gmail.com>2016-08-21 10:14:02 +0100
commit4945e55956878279f04562fe55f48d8071bb5e46 (patch)
treeaf89a45b108471531cf250ff6c593b1a84c143ce /mini_irc/mini_irc.c
parente6add15b639d94ddf9cc0f00e2e0d12ebbae5597 (diff)
downloadcode-snippets-4945e55956878279f04562fe55f48d8071bb5e46.tar.gz
code-snippets-4945e55956878279f04562fe55f48d8071bb5e46.zip
Mini irc 'bot' supports 3 commands. Also can do echo replay on PM or chat message
Diffstat (limited to 'mini_irc/mini_irc.c')
-rw-r--r--mini_irc/mini_irc.c373
1 files changed, 373 insertions, 0 deletions
diff --git a/mini_irc/mini_irc.c b/mini_irc/mini_irc.c
new file mode 100644
index 0000000..326c9e8
--- /dev/null
+++ b/mini_irc/mini_irc.c
@@ -0,0 +1,373 @@
+#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;
+} \ No newline at end of file