aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorepochqwert <epoch@53flpnlls43fcguy.onion>2015-03-31 12:48:40 -0500
committerepochqwert <epoch@53flpnlls43fcguy.onion>2015-03-31 12:48:40 -0500
commitcaf201027d08049dc12490349b9ebfd7e7a242f4 (patch)
tree77fdc44683cf35a223f8c445a976a6f100ed0b13
downloadlibirc-caf201027d08049dc12490349b9ebfd7e7a242f4.tar.gz
libirc-caf201027d08049dc12490349b9ebfd7e7a242f4.zip
initial commit after splitting from segfault's repo.
-rw-r--r--.gitignore1
-rw-r--r--Makefile15
-rw-r--r--README.md1
-rwxr-xr-xexamples/linkbin0 -> 8036 bytes
-rw-r--r--examples/link.c134
-rw-r--r--irc.h4
-rw-r--r--libirc.c261
7 files changed, 416 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..d792258
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+libirc.so
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..e6c38fb
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,15 @@
+LDFLAGS=-lirc -Llibirc
+CFLAGS=-fpic -shared -pedantic -Wall
+TARGET=libirc.so
+
+all: $(TARGET)
+
+$(TARGET):
+ $(CC) $(CFLAGS) -o $(TARGET) libirc.c
+
+clean:
+ rm -f libirc.so
+
+install:
+ cp $(TARGET) /usr/local/lib/$(TARGET)
+ cp irc.h /usr/local/include/irc.h
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..1f8c779
--- /dev/null
+++ b/README.md
@@ -0,0 +1 @@
+library for handling IRC stuff. duh.
diff --git a/examples/link b/examples/link
new file mode 100755
index 0000000..b40b8a9
--- /dev/null
+++ b/examples/link
Binary files differ
diff --git a/examples/link.c b/examples/link.c
new file mode 100644
index 0000000..c175595
--- /dev/null
+++ b/examples/link.c
@@ -0,0 +1,134 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <irc.h>
+
+#define mywrite(a,b) write(a,b,strlen(b))
+
+int *fds;
+char **chans;
+
+void extra_handler(int fd) {
+ return;
+}
+
+struct user {
+ char *nick;
+ char *user;
+ char *host;
+};
+
+void privmsg_others(int fd,char *msg) {
+ int i;
+ char tmp[512];
+ for(i=0;fds[i] != -1;i++) {
+ if(fds[i] != fd) {
+ snprintf(tmp,sizeof(tmp)-1,"PRIVMSG %s :%s\r\n",chans[fdtoi(fds[i])],msg);
+ write(fds[i],tmp,strlen(tmp));
+ }
+ }
+}
+
+void message_handler(int fd,char *from,struct user *user,char *line) {
+ int i;
+ char tmp[512];
+ if(!strcmp(from,chans[fdtoi(fd)])) {//don't want to be forwarding PMs. :P
+ snprintf(tmp,sizeof(tmp)-1,"<%s> %s",user->nick,line);
+ privmsg_others(fd,tmp);
+ }
+}
+
+void line_handler(int fd,char *line) {//this should be built into the libary?
+ char *s=line,*t=0,*u=0;
+ char *temp;
+ char tmp[512];
+ struct user *user=malloc(sizeof(struct user));
+ user->nick=0;
+ user->user=0;
+ user->host=0;
+ if(strchr(line,'\r')) *strchr(line,'\r')=0;
+ if(strchr(line,'\n')) *strchr(line,'\n')=0;
+ printf("line: '%s'\n",line);
+ if(line[0]==':') {
+ if((user->nick=strchr(line,':'))) {
+ *(user->nick)=0;
+ (user->nick)++;
+ }
+ }
+ if(user->nick) {
+ if((s=strchr((user->nick),' '))) {
+ *s=0;
+ s++;
+ if((t=strchr(s,' '))) {
+ *t=0;
+ t++;
+ if((u=strchr(t,' '))) {//:
+ *u=0;
+ u++;
+ }
+ }
+ }
+ if(((user->user)=strchr((user->nick),'!'))) {
+ *(user->user)=0;
+ (user->user)++;
+ if(((user->host)=strchr((user->user),'@'))) {
+ *(user->host)=0;
+ (user->host)++;
+ }
+ } else {
+ user->host=user->nick;
+ }
+ }
+ if(!user->user && s) {
+ if(!strcmp(s,"004")) {
+ snprintf(tmp,sizeof(tmp)-1,"JOIN %s\r\n",chans[fdtoi(fd)]);
+ temp=strchr(chans[fdtoi(fd)],' ');
+ if(temp) *temp=0;
+ mywrite(fd,tmp);
+ }
+ }
+ if(s && t && u) {
+ if(!strcmp(s,"PRIVMSG")) {
+ message_handler(fd,*t=='#'?t:user->nick,user,++u);
+ }
+ }
+ if(s && user->nick && t) {
+ if(!strcmp(s,"JOIN")) {
+ snprintf(tmp,sizeof(tmp)-1,"%cACTION %s has joined %s%c",1,user->nick,t+(*t==':'),1);
+ privmsg_others(fd,tmp);
+ }
+ if(!strcmp(s,"PART")) {
+ snprintf(tmp,sizeof(tmp)-1,"%cACTION %s has parted %s%c",1,user->nick,t+(*t==':'),1);
+ privmsg_others(fd,tmp);
+ }
+ if(!strcmp(s,"QUIT")) {
+ snprintf(tmp,sizeof(tmp)-1,"%cACTION %s has quited %s%c",1,user->nick,t+(*t==':'),1);
+ privmsg_others(fd,tmp);
+ }
+ }
+ free(user);
+}
+
+int fdtoi(int fd) {
+ int i;
+ for(i=0;fds[i] != -1;i++) {
+ if(fds[i] == fd) return i;
+ }
+ return -1;
+}
+
+int main(int argc,char *argv[]) {
+ fds=malloc(sizeof(int) * (argc+3) / 3);
+ chans=malloc(sizeof(char *) * (argc+3) / 3);
+ int i=0;
+ printf("%d\n",argc);
+ for(i=0;((i*3)+3)<argc;i++) {
+ printf("%d server: %s port: %s channel: %s\n",i,argv[(i*3)+1],argv[(i*3)+2],argv[(i*3)+3]);
+ fds[i]=serverConnect(argv[(i*3)+1],argv[(i*3)+2]);
+ chans[i]=strdup(argv[(i*3)+3]);
+ mywrite(fds[i],"NICK link8239\r\nUSER a b c :d\r\n");
+ }
+ fds[i]=-1;
+ //heh. you can write your own code for picking a different nick per server. fuck you.
+ runem(fds,line_handler,extra_handler);
+}
diff --git a/irc.h b/irc.h
new file mode 100644
index 0000000..231cd84
--- /dev/null
+++ b/irc.h
@@ -0,0 +1,4 @@
+int runit(int fd,void (*line_handler)(),void (*extra_handler)()) ;
+int ircConnect(char *serv,char *port,char *nick,char *user) ;
+int serverConnect(char *serv,char *port) ;
+char **line_cutter(int fd,char *line,struct user *user) ;
diff --git a/libirc.c b/libirc.c
new file mode 100644
index 0000000..376a483
--- /dev/null
+++ b/libirc.c
@@ -0,0 +1,261 @@
+#include <sys/time.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <sys/select.h>
+
+//#define DEBUG "epoch" //nick or channel to send debug info to.
+#define CHUNK 4096
+
+int main(int argc,char *argv[]) {
+ return 0;
+}
+
+#define SILLYLIMIT 256
+
+int serverConnect(char *serv,char *port) {
+ int rv;
+ int fd=0;
+ int n=1;
+ int try_ipv4=0;
+ char buf[SILLYLIMIT];
+ struct addrinfo hints, *servinfo, *p=0;
+ struct in_addr saddr;
+ struct in6_addr saddr6;
+ struct hostent *he;
+ memset(&hints,0,sizeof hints);
+ hints.ai_family=AF_INET;
+ hints.ai_socktype=SOCK_STREAM;
+ if((fd=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP)) < 0) {
+ perror("socket");
+ return -1;
+ }
+/*
+ for(try_ipv4=0;try_ipv4 < 2;try_ipv4++) {
+ if(!(he=gethostbyname2(
+ try_ipv4
+ ?inet_aton(serv,&saddr)
+ ?inet_ntoa(saddr)
+ :serv
+ :inet_pton(AF_INET6,serv,&saddr6)
+ ?inet_ntop(AF_INET6,&saddr6,buf,SILLYLIMIT)
+ :serv
+ ,try_ipv4?AF_INET:AF_INET6))) return -1;
+
+ for(;*(he->h_addr_list);he->h_addr_list++) {
+ printf("trying to connect to %s:%s attempt #%d\n",serv,port,n);
+ n++;
+*/
+// if((rv=getaddrinfo(he->h_addr_list,port,&hints,&servinfo)) != 0) {
+ if((rv=getaddrinfo(serv,port,&hints,&servinfo)) != 0) {
+ fprintf(stderr,"error resolving '%s'.\n",serv);
+ return -1;
+ }
+ for(p=servinfo;p;p=p->ai_next) {
+ if(connect(fd,p->ai_addr, p->ai_addrlen) < 0) {
+ perror("connect");
+ continue;
+ } else {
+ return fd;
+ }
+ }
+ //printf("trying a differnt address...\n");
+ //}
+ //printf("trying a different AF...\n");
+ //}
+ //printf("well, shit. how'd I get here?\n");
+ return -1;
+}
+
+int fdlen(int *fds) {
+ int i;
+ for(i=0;fds[i] != -1;i++);
+ return i+1;
+}
+
+int runem(int *fds,void (*line_handler)(),void (*extra_handler)()) {
+ int j;
+ int fdl=fdlen(fds);
+ fd_set master;
+ fd_set readfs;
+ struct timeval timeout;
+ int fdmax=0,n,s,i;
+ int fd;
+ char *backlogs[fdl];
+ char *t,*line=0;
+ int blsize=CHUNK;
+ int bllen=0;
+ char buffers[fdl][CHUNK];//THIS IS *NOT* NULL TERMINATED.
+ FD_ZERO(&master);
+ FD_ZERO(&readfs);
+ for(i=0;fds[i] != -1;i++) {
+ //if(!backlogs[i]) return 252;//wtf is this here for? ofc they're not set!
+ FD_SET(fds[i],&master);
+ backlogs[i]=malloc(CHUNK+1);
+ memset(backlogs[i],0,CHUNK);
+ memset(buffers[i],0,CHUNK);
+ fdmax=fds[i]>fdmax?fds[i]:fdmax;
+ }
+ int done=0;
+ while(!done) {
+ for(fd=0;fd<=fdmax;fd++) {
+ if(FD_ISSET(fd,&master)) {
+ if(extra_handler) extra_handler(fd);
+ }
+ }
+ readfs=master;
+ timeout.tv_sec=0;
+ timeout.tv_usec=1000;
+ if( select(fdmax+1,&readfs,0,0,&timeout) == -1 ) {
+ printf("\n!!!It is crashing here!!!\n\n");
+ perror("select");
+ return 1;
+ }
+ for(i=0;fds[i] != -1;i++) {
+ if(FD_ISSET(fds[i],&readfs)) {
+ if((n=recv(fds[i],buffers[i],CHUNK,0)) <= 0) {//read CHUNK bytes
+ fprintf(stderr,"recv: %d\n",n);
+ perror("recv");
+ return 2;
+ } else {
+ buffers[i][n]=0;//deff right.
+ if(bllen+n >= blsize) {//this is probably off...
+ blsize+=n;
+ t=malloc(blsize);
+ if(!t) {
+ printf("OH FUCK! MALLOC FAILED!\n");
+ exit(253);
+ }
+ memset(t,0,blsize);//optional?
+ memcpy(t,backlogs[i],blsize-n+1);//???
+ free(backlogs[i]);
+ backlogs[i]=t;
+ }
+ memcpy(backlogs[i]+bllen,buffers[i],n);
+ bllen+=n;
+ for(j=0,s=0;j<bllen;j++) {
+ if(backlogs[i][j]=='\n') {
+ line=malloc(j-s+3);//on linux it crashes without the +1 +3? weird. when did I do that?
+ if(!line) {
+ printf("ANOTHER malloc error!\n");
+ exit(254);
+ }
+ memcpy(line,backlogs[i]+s,j-s+2);
+ line[j-s+1]=0;//gotta null terminate this. line_handler expects it .
+ s=j+1;//the character after the newline.
+ if(!strncmp(line,"PING",4)) {
+ t=malloc(strlen(line));
+ strcpy(t,"PONG ");
+ strcat(t,line+6);
+ write(fds[i],t,strlen(t));
+ #ifdef DEBUG
+ printf("%s\nPONG %s\n",line,line+6);
+ write(fds[i],"PRIVMSG %s :PONG! w00t!\r\n",DEBUG,28);
+ #endif
+ } else if(!strncmp(line,"ERROR",5)) {
+ #ifdef DEBUG
+ printf("error: %s\n",line);
+ #endif
+ return 0;
+ } else {
+ line_handler(fds[i],line);
+ }
+ free(line);
+ }
+ }
+ //left shift the backlog so the last thing we got to is at the start
+ if(s > bllen) { //if the ending position is after the size of the backlog...
+ bllen=0;//fuck shifting. :P
+ } else {
+ for(j=s;j<=bllen;j++) {//should work.
+ backlogs[i][j-s]=backlogs[i][j];
+ }
+ bllen-=s;
+ }
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+//wrap runem to keep runit around :P
+int runit(int fd,void (*line_handler)(),void (*extra_handler)()) {
+ int fds[2];
+ fds[0]=fd;
+ fds[1]=-1;
+ return runem(fds,line_handler,extra_handler);
+}
+
+//not needed?
+int ircConnect(char *serv,char *port,char *nick,char *user) {
+ char sendstr[1024];
+ int fd;
+ fd=serverConnect(serv,port);
+ if(!fd) {
+ return 0;
+ }
+ snprintf(sendstr,sizeof(sendstr)-1,"NICK %s\r\nUSER %s\r\n",nick,user);
+ write(fd,sendstr,strlen(sendstr));
+ return fd;
+}
+
+struct user {
+ char *nick;
+ char *user;
+ char *host;
+};
+
+//this function mangles the input.
+//gotta free the returned pointer but not each pointer in the array.
+char **line_cutter(int fd,char *line,struct user *user) {
+ int i;
+ char **a=malloc(sizeof(char *) * 256);//heh.
+ memset(a,0,sizeof(char *) * 256);
+ if(!user) return 0;
+ user->nick=0;
+ user->user=0;
+ user->host=0;
+ if(!line) return 0;
+ if(strchr(line,'\r')) *strchr(line,'\r')=0;
+ if(strchr(line,'\n')) *strchr(line,'\n')=0;
+ if(line[0]==':') {
+ if((user->nick=strchr(line,':'))) {
+ *(user->nick)=0;
+ (user->nick)++;
+ }
+ }
+ if(user->nick) {
+
+ if((a[0]=strchr((user->nick),' '))) {
+ *a[0]=0;
+ a[0]++;
+ for(i=0;a[i+1]=strchr(a[i],' ');i++) {
+ *a[i+1]=0;
+ a[i+1]++;
+ if(*a[i+1] == ':') {//we're done.
+ *a[i+1]=0;
+ a[i+1]++;
+ break;
+ }
+ }
+ }
+
+ if(((user->user)=strchr((user->nick),'!'))) {
+ *(user->user)=0;
+ (user->user)++;
+ if(((user->host)=strchr((user->user),'@'))) {
+ *(user->host)=0;
+ (user->host)++;
+ }
+ } else {
+ user->host=user->nick;
+ }
+ }
+ return a;
+}