diff options
author | epoch <epoch@hacking.allowed.org> | 2014-02-05 04:27:07 -0600 |
---|---|---|
committer | epoch <epoch@hacking.allowed.org> | 2014-02-05 04:27:07 -0600 |
commit | 8ea60384731c92fe1daa64160f6cacc33177066d (patch) | |
tree | d68c6d74cab9b5d76562d386da5addba15eca40f | |
parent | 517add9afbc9ffbc0cf3425074ecb093fa59fdca (diff) | |
download | segfault-8ea60384731c92fe1daa64160f6cacc33177066d.tar.gz segfault-8ea60384731c92fe1daa64160f6cacc33177066d.zip |
first useful commit. hopefully it compiles...
-rwxr-xr-x | compile.sh | 33 | ||||
-rwxr-xr-x | libirc/compile.sh | 3 | ||||
-rw-r--r-- | libirc/irc.h | 2 | ||||
-rw-r--r-- | libirc/libirc.c | 181 | ||||
-rw-r--r-- | libirc/libirc.o | bin | 0 -> 3488 bytes | |||
-rwxr-xr-x | libirc/libirc.so | bin | 0 -> 7585 bytes | |||
-rwxr-xr-x | runme.sh | 4 | ||||
-rwxr-xr-x | segfault | bin | 0 -> 26258 bytes | |||
-rw-r--r-- | segfault.c | 1002 | ||||
-rwxr-xr-x | shell | 5 | ||||
-rw-r--r-- | testing.c | 65 |
11 files changed, 1295 insertions, 0 deletions
diff --git a/compile.sh b/compile.sh new file mode 100755 index 0000000..a920ae2 --- /dev/null +++ b/compile.sh @@ -0,0 +1,33 @@ +#!/bin/sh +#clean it out so I quit restarting after a failed compile. >.< +INSTALL_DIR="/home/segfault/" +rm segfault +echo '#!/bin/sh' > shell +echo '# this file is generated by compile.sh. do not edit directly' >> shell +echo 'cd "'`pwd`'"' >> shell +echo 'kill `pgrep -P 1 -f "tail -f ./files/cmd_in"`' >> shell +echo 'setuidgid segfault tail -f ./files/cmd_in | setuidgid segfault su -l segfault > ./files/cmd_out 2>&1' >> shell +chmod +x shell +echo '#define CHDIR "'`pwd`'"' > config.h + +#if [ -e /usr/lib/libirc.so ]; then +# gcc -Wall -o segfault segfault.c -lirc +# rm -r /var/www/source/segfault/* +# cd /home/epoch/projects/c_/wargaming-libirc +# ./compile.sh +# cd /root/services/segfault +# cp * /var/www/source/segfault/ +# mkdir /var/www/source/segfault/scripts +# cp scripts/* /var/www/source/segfault/scripts/ +# cd /var/www/source/ +# tar -czf segfault.tgz segfault + + mkdir $INSTALL_DIR/files + mkfifo $INSTALL_DIR/files/cmd_in + mkfifo $INSTALL_DIR/files/cmd_out + cd libirc + ./compile.sh + cd .. + gcc -Wall -o segfault segfault.c -lirc -Llibirc -Ilibirc + +rm config.h diff --git a/libirc/compile.sh b/libirc/compile.sh new file mode 100755 index 0000000..0ff547d --- /dev/null +++ b/libirc/compile.sh @@ -0,0 +1,3 @@ +#!/bin/sh +gcc -fpic -c libirc.c +gcc -shared -o libirc.so *.o diff --git a/libirc/irc.h b/libirc/irc.h new file mode 100644 index 0000000..7741f75 --- /dev/null +++ b/libirc/irc.h @@ -0,0 +1,2 @@ +int runit(int fd,void (*line_handler)(),void (*extra_handler)()) ; +int ircConnect(char *serv,char *port,char *nick,char *user) ; diff --git a/libirc/libirc.c b/libirc/libirc.c new file mode 100644 index 0000000..ab93113 --- /dev/null +++ b/libirc/libirc.c @@ -0,0 +1,181 @@ +#include <sys/time.h> +#include <string.h> +#include <stdlib.h> +#include <sys/select.h> +#include <stdio.h> +#include <netinet/in.h> +#include <netdb.h> +#include <sys/socket.h> +#include <arpa/inet.h> + +//#define DEBUG //comment me out to disable. +#define CHUNK 16 + +static int serverConnect(char *serv,char *port) { + struct addrinfo hints, *servinfo, *p; + int rv; + memset(&hints,0,sizeof hints); + hints.ai_family=AF_INET; + hints.ai_socktype=SOCK_STREAM; + + int fd=0; + + fd=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP); + if(fd < 0) { + perror("socket"); + return fd; + } + if((rv=getaddrinfo(serv,port,&hints,&servinfo)) != 0) { + fprintf(stderr,"error resolving '%s'.\n",serv); + return 0; + } + for(p=servinfo;p;p=p->ai_next) { + if (connect(fd,p->ai_addr, p->ai_addrlen) < 0) { + perror("connect"); + continue; + } + break; + } + if(!p) { + return 0; + } + return fd; +} + +static int haschar(char *s,char c) { + int i; + for(i=0;s[i];i++) { + if(s[i]==c) return 1; + } + return 0; +} + +int runit(int fd,void (*line_handler)(),void (*extra_handler)()) { + FILE *fp; + fd_set master; + fd_set readfs; + struct timeval timeout; + int fdmax; + int n; + int s; + int i; + int good=0; + char *backlog=malloc(CHUNK+1); + if(!backlog) return 252; + char *t; + char *line=0; + int blsize=CHUNK; + int bllen=0; + char buffer[CHUNK];//THIS IS *NOT* NULL TERMINATED. + FD_ZERO(&master); + FD_ZERO(&readfs); + FD_SET(fd,&master); + fdmax=fd; + fp=fdopen(fd,"rw"); + memset(backlog,0,CHUNK); + memset(buffer,0,CHUNK); + if(fd) { + int done=0; +// printf("starting main loop.\n"); + while(!done) { + extra_handler(fd); + readfs=master; + timeout.tv_sec=0; + timeout.tv_usec=1000; +// printf("trying select. %d\n",time(0)); + if( select(fdmax+1,&readfs,0,0,&timeout) == -1 ) { + printf("\n!!!It is crashing here!!!\n\n"); + perror("select"); + return 1; + } + if(FD_ISSET(fd,&readfs)) { +// printf("An fd is set!!!\n"); + if((n=recv(fd,buffer,CHUNK,0)) <= 0) {//read CHUNK bytes + fprintf(stderr,"recv: %d\n",n); + perror("recv"); + return 2; + } else { +// printf("%d bytes read\n",n); + buffer[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,backlog,blsize-n+1);//??? + free(backlog); + backlog=t; + } + memcpy(backlog+bllen,buffer,n); + bllen+=n; +// write(1,backlog,bllen); +// write(1,"\n",1); + for(i=0,s=0;i<bllen;i++) { + if(backlog[i]=='\n') { + line=malloc(i-s+3);//on linux it crashes without the +1 + if(!line) { + printf("ANOTHER malloc error!\n"); + exit(254); + } + memcpy(line,backlog+s,i-s+2); +// printf("NEWLINE!\n"); + line[i-s+1]=0;//gotta null terminate this. line_handler expects it. +// printf("libirc: !!! %s !!!\n",line); + s=i+1;//the character after the newline. + if(!strncmp(line,"PING",4)) { + //write(fd,"PONG ",5); + //write(fd,line+6,strlen(line)-6); + fprintf(fp,"PING %s\r\n",line+6);//a whole FILE * and fdopen JUST for this??? oi... + fflush(fp); +#ifdef DEBUG + printf("%s\nPONG %s\n",line,line+6); + write(fd,"PRIVMSG epoch :PONG! w00t!\r\n",28); +#endif + } else if(!strncmp(line,"ERROR",5)) { +#ifdef DEBUG + printf("error: %s\n",line); +#endif + return 0; + } else { + line_handler(fd,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(i=s;i<=bllen;i++) {//should work. + backlog[i-s]=backlog[i]; + } + bllen-=s; + } + } + } + } + } else { + return 0; + } +} + +//:hack.thebackupbox.net 433 * sysbot :Nickname is already in use. +//Need to have it check for this. +//and try a nick? +//or something... +//I don't want to add any string parsing to this function. :/ +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; +} + diff --git a/libirc/libirc.o b/libirc/libirc.o Binary files differnew file mode 100644 index 0000000..bfabfb8 --- /dev/null +++ b/libirc/libirc.o diff --git a/libirc/libirc.so b/libirc/libirc.so Binary files differnew file mode 100755 index 0000000..c333bd8 --- /dev/null +++ b/libirc/libirc.so diff --git a/runme.sh b/runme.sh new file mode 100755 index 0000000..bd434d4 --- /dev/null +++ b/runme.sh @@ -0,0 +1,4 @@ +#!/bin/sh +export LD_LIBRARY_PATH=`pwd`/libirc +./shell& +./segfault bot_$$ diff --git a/segfault b/segfault Binary files differnew file mode 100755 index 0000000..4a18bb0 --- /dev/null +++ b/segfault diff --git a/segfault.c b/segfault.c new file mode 100644 index 0000000..f3721b4 --- /dev/null +++ b/segfault.c @@ -0,0 +1,1002 @@ +#include <stdio.h> +#include <stdarg.h> +#include <signal.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> +#include <irc.h> +#include <time.h> +#include "config.h" + +#define SERVER "192.168.0.2" +#define PORT "6667" +#define NICK "SegFault" + +#define LINE_LIMIT line_limit + +#define LINES_SENT_LIMIT 1 + +#define LINELEN 400 + +#define RAWLOG "./files/rawlog" +#define LOG "./files/log" +#define NEWS_PIPE "./files/news" +#define LINKS_FILE "/var/www/docs/IRClinks.txt" +#define NEWS_FILE "/var/www/cgi-bin/info/news.html" +#define PID_FILE "./files/my.pid" + +#define MAXTAILS 400 //just to have it more than the system default. + +#define BS 502 + +//!c uses 56 for its tail. +// 56 = 32 + 16 + 8 = 0x38 = 0x20+0x10+0x8 = SPAM | BEGIN | MSG +#define TAILO_RAW (0x1) +#define TAILO_EVAL (0x2) +#define TAILO_CLOSE (0x4) +#define TAILO_MSG (0x8) +#define TAILO_BEGIN (0x10) +#define TAILO_SPAM (0x20) //Spam control is enabled for this stream. +#define TAILO_ENDMSG (0x40) //show a message when the tail reaches the end of a chunk +#define TAILO_Q_EVAL (TAILO_EVAL|TAILO_CLOSE|TAILO_BEGIN) //0x2+0x4+0x10= 2+4+16=22 + + +int start_time; +char *redo; +int redirect_to_fd; +int line_limit; +int debug; +timer_t timer; +int lines_sent; + +//this should add a line to an outgoing queue? +void mywrite(int fd,char *b) { + if(!b) return; + if(fd<0) return; + write(fd,b,strlen(b)); + lines_sent++; +} + +void ircmode(int fd,char *channel,char *mode,char *nick) { + int sz=5+strlen(channel)+1+strlen(mode)+1+strlen(nick)+3;//"MODE ", " ", " ","\r\n\0" + char *hrm=malloc(sz+1); + if(!hrm) return (void)mywrite(fd,"QUIT :malloc error 1! holy shit!\r\n"); + snprintf(hrm,sz,"MODE %s %s %s\r\n",channel,mode,nick); + write(fd,hrm,strlen(hrm)); + free(hrm); +} + +void privmsg(int fd,char *who,char *msg) { + int i=0; + char *chunk; + if(!who) { + who="epoch"; + msg="didn't have a who. sending this."; + } + if(!msg) { + who="epoch"; + msg="didn't have a message. sending this."; + } + if(!msg && !who) { + who="epoch"; + msg="didn't have a message or a who. sending this."; + } + int sz; + int cs; + for(i=0;i<strlen(msg);i+=LINELEN) { + cs=(strlen(msg+i)<=LINELEN)?strlen(msg+i):LINELEN; + sz=8+strlen(who)+2+cs+3;//"PRIVMSG ", " :", "\r\n\0"; + char *hrm=malloc(sz); + if(!hrm) return (void)mywrite(fd,"QUIT :malloc error 2! holy shit!\r\n"); + chunk=strndup(msg+i, cs ); + snprintf(hrm,sz+1,"PRIVMSG %s :%s\r\n",who,chunk); + mywrite(fd,hrm);//not this... + free(hrm); + free(chunk); + } +} + +struct tail { + FILE *fp; + char *file; + char *to; + char *args; + char opt; + unsigned int inode; + int lines; +} tailf[MAXTAILS]; + +void message_handler(int fd,char *from,char *nick,char *msg,int redones); +void c_untail(int fd,char *from, char *file); + +char *format_magic(int fd,char *from,char *nick,char *orig_fmt,char *arg) { + int i; + int c=1; + char *fmt=strdup(orig_fmt); + for(i=0;fmt[i];i++) { + if(fmt[i] == '%') { + i++; + switch(fmt[i]) { + case 0: + printf("error! last character is a '%%'!!!\n"); + exit(1); + case 'u': + case 'f': + case 's': + c++; + } + } + } + char **args=malloc((sizeof(char *)) * (c + 1)); + c=0; + for(i=0;fmt[i];i++) { + if(fmt[i] == '%') { + i++; + switch(fmt[i]) { + case 0: + printf("error! last character is a '%%'!!!\n"); + exit(1); + case 'u': + args[c]=nick; + fmt[i]='s'; + c++; + break; + case 'f': + args[c]=from; + fmt[i]='s'; + c++; + break; + case 's': + args[c]=arg; + c++; + break; + } + } + } +// args[c]=0; +// for(i=0;i<c;i++) { +// printf("args[%d]=%s\n",i,args[i]); +// } +// printf("format string: %s\nc: %d\n",fmt,c); + int sz=vprintf(fmt,(va_list)args)+1; +// printf("\nsize: %d\n",sz); + char *output=malloc(sz); + vsnprintf(output,sz,fmt,(va_list)args); + free(fmt); + return output; +} + +//get rid of this? +char *good_format_string(int fd,char *from,char *line) { + int i; + char tmp[256]; + int scount=0; + for(i=0;line[i];i++) { + if(line[i] == '%') { + if(!line[i+1]) { + privmsg(fd,from,"bad format string. you have a % as the last character."); + return 0; + } + if(line[i+1] == 's') scount++; + if( (line[i+1] != 's' && line[i+1] != '%') || (line[i+1] == 's' && scount>1)) { + privmsg(fd,from,"can only use %s and only once."); + snprintf(tmp,sizeof(tmp)-1,"bad format string: %s",line); + privmsg(fd,from,tmp); + return 0; + } + i++; + } + } + return line; +} +//this has a LOT of shit in it. +unsigned long oldtime; + +void extra_handler(int fd) { + if(oldtime == time(0) && lines_sent > LINES_SENT_LIMIT) {//if it is still the same second, skip this function. + return; + } else {//different second. reset count. + lines_sent=0; + } + int i; + int tmpo; + static int mmerp=0; + char tmp[BS+1]; + char *tmp2; + + if(redirect_to_fd != -1) { + fd=redirect_to_fd; + } + + for(i=0;i<MAXTAILS;i++) { + if(tailf[i].fp) { + if(feof(tailf[i].fp)) { + clearerr(tailf[i].fp); + if(tailf[i].opt & TAILO_CLOSE) {//use for eval + c_untail(fd,tailf[i].to,tailf[i].file); + return; + } + } + tmpo=ftell(tailf[i].fp); + if(!(tailf[i].opt & TAILO_BEGIN)) { + if(fseek(tailf[i].fp,0,SEEK_END) == -1) { + while(fgetc(tailf[i].fp) != -1);//this is used on named pipes usually. + } + } + if(ftell(tailf[i].fp) < tmpo) { + privmsg(fd,tailf[i].to,"tailed file shrank! resetting to NEW eof."); + } else { + fseek(tailf[i].fp,tmpo,SEEK_SET);//??? + } + if(tailf[i].lines != -1) { + if(fgets(tmp,BS-1,tailf[i].fp) ) {//for some reason using sizeof(tmp) didn't work. >_> + tailf[i].lines++; + mmerp=0; + if(strchr(tmp,'\r')) *strchr(tmp,'\r')=0; + if(strchr(tmp,'\n')) *strchr(tmp,'\n')=0; + if(tailf[i].opt & TAILO_EVAL) {//eval + if(tailf[i].args) { //only format magic evaled file lines if they have args. + tmp2=format_magic(fd,tailf[i].to,NICK,tmp,tailf[i].args); + } else { + tmp2=strdup(tmp); + if(!tmp2) return perror("ZOMG malloc error in eval section!!!"); + } + message_handler(fd,tailf[i].to,NICK,tmp2,0); // FIX ME?!? don't use NICK... make it a global for segfault's nick. + free(tmp2); + } + if(tailf[i].opt & TAILO_RAW) {//raw + tmp2=malloc(strlen(tmp)+3); + snprintf(tmp2,strlen(tmp)+3,"%s\r\n",tmp); + mywrite(fd,tmp2); + free(tmp2); + } + if(tailf[i].opt & TAILO_MSG) {//just msg the lines. + privmsg(fd,tailf[i].to,tmp); + } + if(tailf[i].lines >= LINE_LIMIT && (tailf[i].opt & TAILO_SPAM)) { + tailf[i].lines=-1; //lock it. + privmsg(fd,tailf[i].to,"--more--"); + } + } else { + if(tailf[i].lines != 0 && (tailf[i].opt & TAILO_ENDMSG)) { + privmsg(fd,tailf[i].to,"---------- TAILO_ENDMSG border ----------"); + } + tailf[i].lines=0; + } + } else { + //don't PM in here. shows a LOT of shit. + } + } + } +} + +void file_tail(int fd,char *from,char *file,char *args,char opt) { + int i,j; + int fdd; + char tmp[256]; + struct stat st; + for(i=0;i<MAXTAILS;i++) { + if(tailf[i].fp == 0) { + break; + } + } + if(i == MAXTAILS -1) { + exit(3); + } + fdd=open(file,O_RDONLY|O_NONBLOCK,0);//HAVE to open named pipes as nonblocking. + fstat(fdd,&st); + for(j=0;j<MAXTAILS;j++) { + if(tailf[j].fp && tailf[j].file && tailf[j].inode) { + if(tailf[j].inode == st.st_ino) { + if(debug) privmsg(fd,from,"THIS FILE IS ALREADY BEING TAILED ELSEWHERE!"); + //i=j; + //break;//reuse it. + //return; + } + } + } + if(!(tailf[i].fp=fdopen(fdd,"r"))) { + snprintf(tmp,sizeof(tmp),"failed to open file: %s\n",file); + privmsg(fd,from,tmp); + } else { + fcntl(fileno(tailf[i].fp),F_SETFL,O_NONBLOCK); + if(!(opt & TAILO_BEGIN)) fseek(tailf[i].fp,0,SEEK_END); + tailf[i].to=malloc(strlen(from)+1); + if(!tailf[i].to) return (void)mywrite(fd,"QUIT :malloc error 3!!!\r\n"); + strcpy(tailf[i].to,from); + tailf[i].file=malloc(strlen(file)+1); + if(!tailf[i].file) return (void)mywrite(fd,"QUIT :malloc error 4!!!\r\n"); + tailf[i].opt=opt; + tailf[i].inode=st.st_ino; + tailf[i].args=args?strdup(args):0; + if(args) if(!tailf[i].args) return (void)mywrite(fd,"QUIT :malloc error 5!!! (well, strdup)\r\n"); + tailf[i].lines=0; + strcpy(tailf[i].file,file); + } +} + +void c_botup(int fd,char *from) { + char tmp[256]; + snprintf(tmp,sizeof(tmp)-1,"botup: %lu",time(0)-start_time); + privmsg(fd,from,tmp); +} + +void c_leettail(int fd,char *from,char *file) { + short a=file[0]-'0'; + short b=file[1]-'0'; + short c=(a*10)+(b); + char *args; + if((args=strchr(file,' '))) { + *args=0; + args++; + } + file_tail(fd,from,file+2,args,c); +} + +void c_changetail(int fd,char *from,char *line) { + char *merp; + int i; + //if(line == 0) return mywrite(fd,"QUIT :line == 0 in changetail\r\n"); + //if(from == 0) return mywrite(fd,"QUIT :from == 0 in changetail\r\n"); + if((merp=strchr(line,' '))) { + *merp=0; + merp++; + } + for(i=0;i<MAXTAILS;i++) { + //if(tailf[i].file == 0) return mywrite(fd,"QUIT :tailf[i].file == 0 in changetail\r\n"); + if(tailf[i].file) { + if(!strcmp(tailf[i].file,line)) { + free(tailf[i].to); + tailf[i].to=strdup(merp); + return; + } + } + } + privmsg(fd,from,"error"); +} + +void startup_stuff(int fd) { + mywrite(fd,"OPER g0d WAFFLEIRON\r\n"); + mywrite(fd,"JOIN #cmd\r\n"); + c_leettail(fd,"#cmd","22./scripts/startup"); +} + +struct alias { + char *original; + char *target; + struct alias *prev;// doubly linked list. + struct alias *next; +} *a_start,*a_end; + +#if 0 ////////////////////////// HASH TABLE SHIT ///////////////////////////////// + +unsigned short hash(char *v) {//maybe use a seeded rand()? :) yay FreeArtMan. + unsigned short h=0; + //I only need the first two bytes hashed anyway. I'll make this better later. + h=((*v)<<8)+(v?*(v+1):0); + return h; +} + +struct hitem {//with a stick + char *key + struct *alias value;//run through this linked list if it isn't the right one. +}; + +struct **hitem hashtable; + +void inittable() { + int i; + hashtable=malloc(sizeof(char *)*TSIZE); + if(!hashtable) return (void *)fprintf(stderr,"malloc error 6 in hash table.\n"); + for(i=0;i<TSIZE;i++) { + hashtable[i]=0; + } +} + +void setkey_h(char *key,struct alias *value) { + unsigned short h=hash(key); + printf("setting: %s(%d)=a struct that contains a lot of shit.\n",key,h,value); + if(!hashtable[h]) { //empty bucket! + hashtable[h]=malloc(sizeof(struct item)); + + hashtable[h]->key=key; + hashtable[h]->value=value;//strdup this + return; + } + //filled bucket... oh shit. + if(!strcmp(hashtable[h]->key,key)) { //same key. just change the value. + hashtable[h]->value=value;//free previous and strdup. + return; + } + else { //collision! add to the linked list. + for + } +} + +#endif ///////////////////////// HASH TABLE SHIT ///////////////////////////////// + +void debug_time(int fd,char *from,char *msg) { + char tmp[100]; +// struct itimerspec whattime; + if(debug) { +// timer_gettime(timer,&whattime); +// snprintf(tmp,511,"%d.%d %d.%d", +// whattime.it_interval.tv_sec, +// whattime.it_value.tv_nsec, +// whattime.it_value.tv_sec, +// whattime.it_value.tv_nsec); + snprintf(tmp,99,"%lu %s",time(0),msg?msg:"(no message)");//time() returns time_t which on BSD is a long. + privmsg(fd,from,tmp); + } +} + + +//CONVERT +void c_aliases(int fd,char *from,char *line) { + struct alias *m; + char tmp[512]; + int i=0,j=0; +// debug_time(fd,from); + if(!line){ + privmsg(fd,from,"usage: !aliases [search-term]"); + return; + } + for(m=a_start;m;m=m->next) { + if(strcasestr(m->target,line) || strcasestr(m->original,line)) { + snprintf(tmp,sizeof(tmp)-1,"%s -> %s",m->original,m->target); + privmsg(fd,from,tmp); + i++; + } + j++; + } + snprintf(tmp,sizeof(tmp)-1,"found %d of %d aliases",i,j); + privmsg(fd,from,tmp); +// debug_time(fd,from); +} + +//CONVERT +void c_rmalias(int fd,char *from,char *line) { + struct alias *m; + for(m=a_start;m;m=m->next) { + if(!strcmp(line,m->original)) { + if(m->next == 0) { + a_end=m->prev; + } + if(m->prev == 0) { + a_start=m->next; + free(m->target); + free(m->original); + free(m); + } + else { + m->prev->next=m->next; + } + privmsg(fd,from,"alias deleted"); + return; + } + } + privmsg(fd,from,"alias not found"); + return; +} + +void c_kill(int fd,char *from,char *line) { + char *csig=line; + char *cpid=strchr(line,' '); + if(cpid) { + *cpid=0; + cpid++; + } else { + privmsg(fd,from,"usage: !kill signum pid"); + return; + } + int sig=atoi(csig); + int pid=atoi(cpid); + if(sig && pid) { + if(kill(pid,sig)) privmsg(fd,from,"kill error"); + else privmsg(fd,from,"signal sent"); + } else { + privmsg(fd,from,"pid or sig is 0. something is odd."); + } +} + +//CONVERT +void c_alias(int fd,char *from,char *line) { + char *derp=strchr(line,' '); + struct alias *tmp; + char tmps[256]; + if(!derp) { + for(tmp=a_start;tmp;tmp=tmp->next) { + if(!strcmp(line,tmp->original)) { + privmsg(fd,from,tmp->target); + return; + } + } + privmsg(fd,from,"not an alias."); + return; + } + //line=good_format_string(fd,from,line); + if(!line) return; + *derp=0; + for(tmp=a_start;tmp;tmp=tmp->next) { + if(!strcmp(line,tmp->original)) { + snprintf(tmps,sizeof(tmps)-1,"duplicate alias: %s",line); + privmsg(fd,from,tmps); + return; + } + } + tmp=a_end; + struct alias *tmp2=malloc(sizeof(struct alias)+20); + if(!tmp2) return (void)mywrite(fd,"QUIT :malloc error 7!!!\r\n"); + if(a_end == 0) { + a_end=tmp2; + a_start=tmp2; + a_end->prev=0; + } else { + a_end->next=tmp2; + a_end=tmp2; + a_end->prev=tmp; + } + a_end->target=strdup(derp+1); + a_end->original=strdup(line); + a_end->next=0; +} + +void c_id(int fd,char *from) { + char tmp[512]; + snprintf(tmp,sizeof(tmp)-1,"u:%d g:%d eu:%d eg:%d",getuid(),getgid(),geteuid(),getegid()); + privmsg(fd,from,tmp); +} + +void c_leetuntail(int fd,char *from,char *line) { + char *frm=line; + char *file=0; + int frmN=0; + int i; + char tmp[512]; + if((file=strchr(line,' '))) { + *file=0; + file++; + } + if(file) { + if(*frm == '*') { + for(i=0;i<MAXTAILS;i++) { + if(tailf[i].fp && !strcmp(tailf[i].file,file)) { + //c_untail(fd,tailf[i].to,file); + fclose(tailf[i].fp); + tailf[i].fp=0; + free(tailf[i].to); + free(tailf[i].file); + return; + } + } + snprintf(tmp,sizeof(tmp)-1,"%s from %s not being tailed.",file,frm); + privmsg(fd,from,tmp); + } else { + c_untail(fd,frm,file); + } + } else { + frmN=atoi(frm); + if(frmN < MAXTAILS && tailf[frmN].fp) { + fclose(tailf[frmN].fp); + tailf[frmN].fp=0; + free(tailf[frmN].to); + free(tailf[frmN].file); + snprintf(tmp,sizeof(tmp)-1,"untailed file tail #%d.",frmN); + } else { + snprintf(tmp,sizeof(tmp)-1,"file tail #%d isn't a valid number.",frmN); + } + privmsg(fd,from,tmp); + } +} + +void c_tailunlock(int fd,char *from,char *file) { + int i; + for(i=0;i<MAXTAILS;i++) { + if(tailf[i].fp) { + if(!strcmp(file,tailf[i].file)) { + tailf[i].lines=0; + return; + } + } + } + privmsg(fd,from,"file not found in the tail list."); +} + +void c_untail(int fd,char *from, char *file) { + int i; + for(i=0;i<MAXTAILS;i++) { + if(tailf[i].fp) { + if(!strcmp(from,tailf[i].to) && !strcmp(file,tailf[i].file)) { + fclose(tailf[i].fp); + tailf[i].fp=0; + free(tailf[i].to); + free(tailf[i].file); + //privmsg(fd,from,"tailed file no longer being tailed."); + return; + } + } + } + privmsg(fd,from,"I don't know what file you're talking about."); + privmsg(fd,from,"You have to be in the same channel that the tail was set in."); +} + +char append_file(int fd,char *from,char *file,char *line,unsigned short nl) { + int fdd; + char tmp[512]; + char derp[2]; + derp[0]=(char)nl; + derp[1]=0; + FILE *fp; + if(line == 0) return mywrite(fd,"QUIT :line == 0 in append_file\r\n"),-1; + fdd=open(file,O_WRONLY|O_NONBLOCK|O_APPEND|O_CREAT,0640);//HAVE to open named pipes as nonblocking. + if(fdd == -1) { + snprintf(tmp,sizeof(tmp)-1,"Couldn't open file (%s) fd:%d for a LOT of modes... figure out out.",file,fdd); + privmsg(fd,from,tmp); + privmsg(fd,from,strerror(errno)); + return 0; + } + if(!(fp=fdopen(fdd,"a"))) { + snprintf(tmp,sizeof(tmp)-1,"Couldn't fdopen file (%s) fd:%d for appending.",file,fdd); + privmsg(fd,from,tmp); + privmsg(fd,from,strerror(errno)); + return 0; + } + fcntl(fileno(fp),F_SETFL,O_NONBLOCK); + fseek(fp,0,SEEK_END);//is this right for named pipes? + //if(fprintf(fp,"%s%s",line,(char *) + // ( nl != 0 ? + // &nl : + // (unsigned short *)"" ) + if(fprintf(fp,"%s\n",line + ) < 0) { + privmsg(fd,from,"error writing to file."); + return 0; + } + fflush(fp);//??? + fflush(fp); + fclose(fp); + return 1; +} + +void c_leetappend(int fd,char *from,char *msg) { + unsigned short nl; + char *file=msg; + char *snl=0; + char *line=0; + if((snl=strchr(msg,' '))) { + *snl=0; + snl++; + if((line=strchr(snl,' '))) { + *line=0; + line++; + } + } + if(!snl || !line) { + privmsg(fd,from,"usage: !leetappend file EOL-char-dec line-to-put"); + return; + } + nl=((snl[0]-'0')*10)+((snl[1]-'0')); + append_file(fd,from,file,line,nl); +} + +char *tailmode_to_txt(int mode) {//this needs to be updated. + if(mode & TAILO_RAW) return "raw"; + if(mode & TAILO_MSG) return "msg"; + if(mode & TAILO_EVAL) return "eval"; + return "undef"; +} + +void c_tails(int fd,char *from) { + int i; + int l; + char *tmp; + //privmsg(fd,from,"filename@filepos --msg|raw-> IRCdestination"); + for(i=0;i<MAXTAILS;i++) { + if(tailf[i].fp) { + l=(strlen(tailf[i].file) + strlen(tailf[i].to) + 50);//??? hack. fix it. + tmp=malloc(l); + if(!tmp) return (void)mywrite(fd,"QUIT :malloc error 8\r\n"); + snprintf(tmp,l,"%s [i:%d] @ %ld (%d) --[%s(%02x)]--> %s",tailf[i].file,tailf[i].inode,ftell(tailf[i].fp),tailf[i].lines,tailmode_to_txt(tailf[i].opt),tailf[i].opt,tailf[i].to); + privmsg(fd,from,tmp); + free(tmp); + } + } +} + +char recording,recording_raw; + +void c_record(int fd,char *from,char *line) { + if(*line == '0') { + privmsg(fd,from,"no longer recording IRC."); + recording=0; + return; + } + if(*line == '1') { + recording=1; + unlink(LOG); + privmsg(fd,from,"recording IRC."); + return; + } + privmsg(fd,from,recording?"1":"0"); +} + +void c_rawrecord(int fd,char *from,char *line) { + if(*line == '0') { + privmsg(fd,from,"no longer recording raw IRC."); + recording_raw=0; + return; + } + if(*line == '1') { + recording_raw=1; + unlink(RAWLOG); + privmsg(fd,from,"recording raw IRC."); + return; + } + privmsg(fd,from,recording_raw?"1":"0"); +} + + +void c_leetsetout(int fd,char *from,char *msg) { + if(redirect_to_fd != -1) close(redirect_to_fd); + redirect_to_fd=open(msg+3,((msg[0]-'0')*100) + ((msg[1]-'0')*10) + (msg[2]-'0'),022); + if(redirect_to_fd == -1) { + privmsg(fd,from,"failed to open file as redirect:"); + privmsg(fd,from,msg+3); + } +} + +void c_linelimit(int fd,char *from,char *msg) { + char tmp[256]; + //struct itimerspec settime; + //settime.it_interval.tv_sec=0; + //settime.it_interval.tv_nsec=10; + //settime.it_value.tv_nsec=0; + //settime.it_value.tv_nsec=10; + if(!msg) { + snprintf(tmp,255,"current spam line limit: %d (debug: %d)",line_limit,debug); + privmsg(fd,from,tmp); + } + else { + if(atoi(msg) > 1) { + line_limit=atoi(msg); + snprintf(tmp,255,"spam line limit set to: %d",line_limit); + privmsg(fd,from,tmp); + } else { + privmsg(fd,from,"please set the limit to > 1... oi. (btw, debug has been flipped)"); + debug^=1; +// if(debug) { +// if(timer_create(CLOCK_REALTIME,SIGEV_NONE,&timer) == -1) { +// privmsg(fd,from,(debug=0,"error making debug timer. shit.")); +// } +// if(timer_settime(timer,0,&settime,&settime) == -1) { +// privmsg(fd,from,(debug=0,"error setting debug timer. shit.")); +// } +// } +// else if(timer_delete(timer) == -1) { +// privmsg(fd,from,"error deleting timer. shit."); +// } + } + } +} + +void c_resetout(int fd,char *from) { + redirect_to_fd=-1; + privmsg(fd,from,"output reset"); +} + +void message_handler(int fd,char *from,char *nick,char *msg,int redones) { + struct alias *m; + char *tmp2; + char tmp[512]; + int sz; + //debug_time(fd,from); + if(redirect_to_fd != -1) { + fd=redirect_to_fd; + } + if(recording) { + debug_time(fd,from,"writing to log..."); + append_file(fd,"raw",LOG,msg,'\n'); + debug_time(fd,from,"finished writing to log."); + } + if(*msg != '!') { + return; + } + + //this section could probably be made a LOT shorter with + //an array of structs that contain command and function pointer. + //... meh. it'd just be a LITTLE bit shorter. + + // this still seems horrible though. all those constants in there that are just strlen()s... + if(!strncmp(msg,"!leetsetout ",12)) { + c_leetsetout(fd,from,msg+12); + } + else if(!strncmp(msg,"!whoami",7)) { + privmsg(fd,from,nick); + } + else if(!strncmp(msg,"!whereami",9)) { + privmsg(fd,from,from); + } + else if(!strncmp(msg,"!resetout",9)) { + c_resetout(fd,from); + } + else if(!strncmp(msg,"!botup",6)) { + c_botup(fd,from); + } + else if(!strncmp(msg,"!linelimit",10)) { + c_linelimit(fd,from,*(msg+10)?msg+11:0); + } + else if(!strncmp(msg,"!tailunlock ",12)) { + c_tailunlock(fd,from,msg+12); + } + else if(!strncmp(msg,"!changetail ",12)) { + c_changetail(fd,from,msg+12); + } + else if(!strncmp(msg,"!tails",6)) { + c_tails(fd,from); + } + else if(!strncmp(msg,"!record ",8)) { + c_record(fd,from,msg+8); + } + else if(!strncmp(msg,"!rawrecord ",11)) { + c_rawrecord(fd,from,msg+11); + } + else if(!strncmp(msg,"!leettail ",10)) { + c_leettail(fd,from,msg+10); + } + else if(!strncmp(msg,"!leetuntail ",12)) { + c_leetuntail(fd,from,msg+12); + } + else if(!strncmp(msg,"!leetappend ",12)) { + c_leetappend(fd,from,msg+12); + } + else if(!strncmp(msg,"!untail ",8)) { + c_untail(fd,from,msg+8); + } + else if(!strncmp(msg,"!raw ",5)) { + tmp2=malloc(strlen(msg)-5+3); + snprintf(tmp2,strlen(msg)-5+2,"%s\r\n",msg+5); + mywrite(fd,tmp2); + free(tmp2); + //write(fd,msg+5,strlen(msg)-5); + //write(fd,"\r\n",2); + } + else if(!strncmp(msg,"!say ",5)) { + privmsg(fd,from,msg+5); + } + else if(!strncmp(msg,"!id",3)) { + c_id(fd,from); + } + else if(!strncmp(msg,"!kill ",6)) { + c_kill(fd,from,msg+6); + } + else if(!strncmp(msg,"!alias ",7)) { + c_alias(fd,from,msg+7); + } + else if(!strncmp(msg,"!rmalias ",9)) { + c_rmalias(fd,from,msg+9); + } + else if(!strncmp(msg,"!aliases",8)) { + c_aliases(fd,from,*(msg+8)?msg+9:0); + } + else if(redones < 5) { + debug_time(fd,from,"checking aliases..."); + //CONVERT + for(m=a_start;m;m=m->next) {//optimize this. hash table? + if(!strncmp(msg,m->original,strlen(m->original)) && (msg[strlen(m->original)]==' ' || msg[strlen(m->original)] == 0)) {//this allows !c to get called when using !c2 if !c2 is defined after !c. >_> + sz=(strlen(msg)-strlen(m->original)+strlen(m->target)+1); + //redo=malloc(sz); + //if(!redo) (void *)mywrite(fd,"QUIT :malloc error 9!!!\r\n"); + //this is where the format string is used... + //generate an array based on the format string containing %N stuff in the right order. + // %u = user, %f = from (user/channel) + // handling it here would be a bitch. maybe + // redo=apply_alias(fd,from,sz,m->target) ??? new function would probably be good. + redo=format_magic(fd,from,nick,m->target,*(msg+strlen(m->original)+1)=='\n'?"":(msg+strlen(m->original)+1)); + //snprintf(redo,sz,m->target,*(msg+strlen(m->original)+1)=='\n'?"":(msg+strlen(m->original)+1) ); + message_handler(fd,from,nick,redo,redones+1); + free(redo); + redo=0; + return; + } + } + debug_time(fd,from,"finished checking aliases. not found."); + //privmsg(fd,from,msg); + // '!c ' + (msg - '!'); +// sz=(strlen(msg)+4); +// redo=malloc(sz); +// if(!redo) (void *)mywrite(fd,"QUIT :malloc error 10!!!\r\n"); +// snprintf(redo,sz-1,"!c %s",msg+1); +// privmsg(fd,from,redo); +// message_handler(fd,from,nick,redo,redones+1); +// free(redo); + redo=0; + snprintf(tmp,sizeof(tmp),"unknown command: %s",msg); + privmsg(fd,from,tmp); +// privmsg(fd,from,"I don't know what you're talking about, man."); + } + if(redones >=5) { + privmsg(fd,from,"too much recursion."); + } + //debug_time(fd,from); +} + +void line_handler(int fd,char *line) {//this should be built into the libary? + //static int flag=0; + //char *a=":hacking.allowed.org 366 "; + char *s=line; + char *nick=0,*name=0,*host=0; + char *t=0,*u=0; + if(strchr(line,'\r')) *strchr(line,'\r')=0; + if(strchr(line,'\n')) *strchr(line,'\n')=0; + //:nick!name@host MERP DERP :message + //strchr doesn't like null pointers. :/ why not just take them and return null? + //check that I haven't gone past the end of the string? nah. it should take care of itself. + if(recording_raw) { + append_file(fd,"epoch",RAWLOG,line,'\n'); + } + if((nick=strchr(line,':'))) { + *nick=0; + nick++; + if((name=strchr(nick,'!'))) { + *name=0; + name++; + if((host=strchr(name,'@'))) { + *host=0; + host++; + if((s=strchr(host,' '))) { + *s=0; + s++; + if((t=strchr(s,' '))) { + *t=0; + t++; + if((u=strchr(t,' '))) {//: + *u=0; + u++; + } + } + } + } + } + } + //printf("<%s!%s@%s> '%s' '%s' '%s'\n",nick,name,host,s,t,u); + //if(to_file!=0) { + // fd= + //} + if(s && t && u) { + if(!strcmp(s,"PRIVMSG")) { + u++; + if(*t == '#')//channel. + message_handler(fd,t,nick,u,0); + else + message_handler(fd,nick,nick,u,0); + } + } + if(s && nick && t) { + if(!strcmp(s,"JOIN")) { + ircmode(fd,t+1,"+v",nick); + } + } +} + +int main(int argc,char *argv[]) { + int fd; + int c; + chdir("/home/segfault"); + redirect_to_fd=-1; + debug=0; + lines_sent=0; + line_limit=25; + recording=0; + recording_raw=0; + start_time=time(0); + a_start=0; + a_end=0; + redo=0; + printf("starting segfault...\n"); + for(c=0;c<MAXTAILS;c++) tailf[c].fp=0; + fd=ircConnect(SERVER,PORT,argc>1?argv[1]:NICK,"segfault segfault segfault :segfault"); + startup_stuff(fd); + return runit(fd,line_handler,extra_handler); +} @@ -0,0 +1,5 @@ +#!/bin/sh +# this file is generated by compile.sh. do not edit directly +cd "/root/services/segfault" +kill `pgrep -P 1 -f "tail -f ./files/cmd_in"` +setuidgid segfault tail -f ./files/cmd_in | setuidgid segfault su -l segfault > ./files/cmd_out 2>&1 diff --git a/testing.c b/testing.c new file mode 100644 index 0000000..63c2620 --- /dev/null +++ b/testing.c @@ -0,0 +1,65 @@ +#include <stdio.h> + +char *format_magic(char *from,char *nick,char *fmt,char *arg); + +int main(int argc,char *argv[]) { + char *o=format_magic("#default","epoch",argv[1],argv[2]); + printf("%s\n",o); + return 0; +} + +char *format_magic(char *from,char *nick,char *fmt,char *arg) { + int i; + int j; + int c=1; + for(i=0;fmt[i];i++) { + if(fmt[i] == '%') { + i++; + switch(fmt[i]) { + case 0: + printf("error! last character is a '%'!!!\n"); + exit(1); + case 'u': + case 'f': + case 's': + c++; + } + } + } + char **args=malloc((sizeof(char *)) * (c + 1)); + c=0; + for(i=0;fmt[i];i++) { + if(fmt[i] == '%') { + i++; + switch(fmt[i]) { + case 0: + printf("error! last character is a '%'!!!\n"); + exit(1); + case 'u': + args[c]=nick; + fmt[i]='s'; + c++; + break; + case 'f': + args[c]=from; + fmt[i]='s'; + c++; + break; + case 's': + args[c]=arg; + c++; + break; + } + } + } +// args[c]=0; +// for(i=0;i<c;i++) { +// printf("args[%d]=%s\n",i,args[i]); +// } +// printf("format string: %s\nc: %d\n",fmt,c); + int sz=vprintf(fmt,args)+1; +// printf("\nsize: %d\n",sz); + char *output=malloc(sz); + vsnprintf(output,sz,fmt,args); + return output; +} |