diff options
author | epochqwert <epoch@53flpnlls43fcguy.onion> | 2015-03-31 12:48:40 -0500 |
---|---|---|
committer | epochqwert <epoch@53flpnlls43fcguy.onion> | 2015-03-31 12:48:40 -0500 |
commit | caf201027d08049dc12490349b9ebfd7e7a242f4 (patch) | |
tree | 77fdc44683cf35a223f8c445a976a6f100ed0b13 | |
download | libirc-caf201027d08049dc12490349b9ebfd7e7a242f4.tar.gz libirc-caf201027d08049dc12490349b9ebfd7e7a242f4.zip |
initial commit after splitting from segfault's repo.
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | Makefile | 15 | ||||
-rw-r--r-- | README.md | 1 | ||||
-rwxr-xr-x | examples/link | bin | 0 -> 8036 bytes | |||
-rw-r--r-- | examples/link.c | 134 | ||||
-rw-r--r-- | irc.h | 4 | ||||
-rw-r--r-- | libirc.c | 261 |
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 Binary files differnew file mode 100755 index 0000000..b40b8a9 --- /dev/null +++ b/examples/link 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); +} @@ -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; +} |