#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /*// just in case your system doesn't have strndup char *strndup(char *s,int l) { char *r=strdup(s); r[l]=0; return r; } */ //might want to change some of these. #define TSIZE 65535 #define SERVER "127.0.0.1" #define PORT "6667" #define NICK "SegFault" //override with argv[1] #define MYUSER "segfault" #define LINES_SENT_LIMIT 1 #define LINELEN 400 #define SEGHOMELEN 1024 #define RAWLOG "./files/rawlog" #define LOG "./files/log" #define BS 4096 // !c uses 56 for its tail. // 56 == 32 + 16 + 8 == 0x38 == 0x20+0x10+0x8 == SPAM | BEGIN | MSG #define TAILO_RAW 1 // r output gets sent directly to server #define TAILO_EVAL 2 // e interpret the lines read from the tail as if they were messages to segfault #define TAILO_CLOSE 4 // c close the file at EOF, default is to leave it open. #define TAILO_MSG 8 // m output gets sent as a PM to the place the tail was made. #define TAILO_BEGIN 16 // b start the tail at the beginning of the file instead of the end. #define TAILO_SPAM 32 // s Spam control is enabled for this stream. #define TAILO_ENDMSG 64 // n show a message when the tail reaches the end of a chunk #define TAILO_FORMAT 128// f formatting? #define TAILO_Q_EVAL (TAILO_EVAL|TAILO_CLOSE|TAILO_BEGIN) //0x2+0x4+0x10 = 2+4+16 = 22 #define TAILO_Q_COUT (TAILO_SPAM|TAILO_BEGIN|TAILO_MSG) //0x20+0x10+0x8 = 32+16+8 = 56 #define PRIVMSG_LINE_LIMIT 0 struct user *myuser; char pid[6]; char mode_magic; char trigger_char; int start_time; char *redo; int redirect_to_fd; int line_limit; int debug; timer_t timer; int lines_sent; unsigned long oldtime; int maxtails; int currentmaxtails; char seghome[SEGHOMELEN]; struct hashtable alias; struct hashtable builtin; union hack { void (*func)(int,...); void *data; }; void (*func)(int fd,...); struct tail { FILE *fp; char *file; char *to; char *args; struct user *user; unsigned short opt; unsigned int inode; int lines; } *tailf; char *shitlist[] = { 0 }; void message_handler(int fd,char *from,struct user *user,char *msg,int redones); void c_leetuntail(int fd,char *from,char *line,...); //this function isn't with the rest of them because... meh. char *tailmode_to_txt(int mode) { char *modes="recmbsnf"; int i,j=0; char *m=malloc(strlen(modes)); for(i=0;i PRIVMSG_LINE_LIMIT) break; } } //try to shorten this up sometime... char *format_magic(int fd,char *from,struct user *user,char *orig_fmt,char *arg) { int i=0,j=1,sz=0,c=1; char *output,*fmt,*argCopy; char **args,**notargs; char *argN[10],randC[10][2]={"0","1","2","3","4","5","6","7","8","9"}; if(!arg) arg="%s"; if(!(argCopy=strdup(arg))) return 0; for(argN[0]=argCopy;argCopy[i] && i<10;i++) { if(argCopy[i] == ' ') { argN[j]=argCopy+i; argN[j][0]=0; argN[j]++; j++; } } for(;j<10;j++) { argN[j]="(null)";//fill up the rest to prevent null deref. } if(!orig_fmt) return 0; if(!(fmt=strdup(orig_fmt))) return 0; for(i=0;fmt[i];i++) { if(fmt[i] == '%') { i++; switch(fmt[i]) { case '~':case 'p':case 'n':case 'h':case 'u':case 'f':case 's': case 'm':case '%':case '0':case '1':case '2':case '3':case '4': case '5':case '6':case '7':case '8':case '9':case 'r': c++; default: break; } } } args=malloc((sizeof(char *)) * (c + 1)); notargs=malloc((sizeof(char *)) * (c + 2)); c=0; for(j=0,i=0;fmt[i];i++) { if(fmt[i] == '%') { i++; switch(fmt[i]) { case '~':case 'p':case 'n':case 'h':case 'u':case 'f':case 's': case 'm':case '%':case '0':case '1':case '2':case '3':case '4': case '5':case '6':case '7':case '8':case '9':case 'r': args[c]=((fmt[i]=='n')?(user->nick?user->nick:"user->nick"): ((fmt[i]=='u')?(user->user?user->user:"user->user"): ((fmt[i]=='~')?seghome: ((fmt[i]=='h')?(user->host?user->host:"user->host"): ((fmt[i]=='f')?(from?from:"from"): ((fmt[i]=='p')?pid: ((fmt[i]=='m')?(myuser->nick?myuser->nick:"myuser->nick")://and here. ((fmt[i]=='s')?(arg?arg:"arg"): ((fmt[i]=='0')?argN[0]: ((fmt[i]=='1')?argN[1]: ((fmt[i]=='2')?argN[2]: ((fmt[i]=='3')?argN[3]: /* I bet */ ((fmt[i]=='4')?argN[4]: /* you */ ((fmt[i]=='5')?argN[5]: /* hate */ ((fmt[i]=='6')?argN[6]: /* this, */ ((fmt[i]=='7')?argN[7]: /* dontcha? :)*/ ((fmt[i]=='8')?argN[8]: ((fmt[i]=='9')?argN[9]: ((fmt[i]=='r')?randC[rand()%10]:"%" ))))))))))))))))))); fmt[i-1]=0; if(!(fmt+j)) exit(68); if(!(notargs[c]=strdup(fmt+j))) exit(66); if(!args[c]) exit(200+c); sz+=strlen(args[c]); sz+=strlen(notargs[c]); c++; j=i+1; } } } if(!(fmt+j)) exit(69); if(!(notargs[c]=strdup(fmt+j))) exit(67); sz+=strlen(notargs[c]); output=malloc(sz+1); output[0]=0; for(i=0;i 0);//this is used on named pipes usually. } } void eofp(FILE *fp) { if(fseek(fp,0,SEEK_END) == -1) { while(fgetc(fp) != -1);//this is used on named pipes usually. } clearerr(fp); } //this function got scary. basically handles all the tail magic. //feature creature void extra_handler(int fd) { int tmpo,i; char tmp[BS+1]; char *tmp2; //if(oldtime == time(0) && lines_sent > LINES_SENT_LIMIT) {//if it is still the same second, skip this function. // return; //} else { // lines_sent=0; //} //oldtime=time(0);//this might fix it? if(redirect_to_fd != -1) { fd=redirect_to_fd; } for(i=0;i= line_limit && (tailf[i].opt & TAILO_SPAM)) { tailf[i].lines=-1; //lock it. privmsg(fd,tailf[i].to,"--more--"); } } } else { //don't PM in here. shows a LOT of shit. } } } } void file_tail(int fd,char *from,char *file,char *args,int opt,struct user *user) { int i; int fdd; char tmp[256]; struct stat st; if(*file == '#') { from=file; file=strchr(file,':'); if(file) {*file=0; file++; } } if((fdd=open(file,O_RDONLY|O_NONBLOCK,0)) == -1) { snprintf(tmp,sizeof(tmp)-1,"file_tail: %s: (%s) fd:%d",strerror(errno),file,fdd); privmsg(fd,"#cmd",tmp); return; } if(debug) { snprintf(tmp,sizeof(tmp)-1,"file_tail opened file '%s' with fd: %d / %d / %d",file,fdd,currentmaxtails,maxtails); privmsg(fd,"#cmd",tmp); } fstat(fdd,&st); // <-- is this needed? /* for(j=0;j= currentmaxtails) { currentmaxtails=i+1;} if(!(tailf[i].fp=fdopen(fdd,"r"))) { snprintf(tmp,sizeof(tmp),"file_tail: failed to fdopen(%s)\n",file); privmsg(fd,from,tmp); } else { fcntl(fdd,F_SETFL,O_NONBLOCK); if(!(opt & TAILO_BEGIN)) { eofp(tailf[i].fp); } if(!from) exit(73); if(tailf[i].to) { snprintf(tmp,sizeof(tmp),"tailf[%d].to: %s from: %s",i,tailf[i].to,from); privmsg(fd,"#default",tmp); free(tailf[i].to); //commenting this out stopped a buffer overflow. >_> weird. tailf[i].to=0; } tailf[i].to=strdup(from);//if this properly free()d before being assigned to? if(!tailf[i].to) { mywrite(fd,"QUIT :malloc error 3!!!\r\n"); return; } if(!file) exit(74); tailf[i].file=strdup(file); if(!tailf[i].file) { mywrite(fd,"QUIT :malloc error 4!!!\r\n"); return; } tailf[i].opt=opt; tailf[i].inode=st.st_ino; tailf[i].user=malloc(sizeof(struct user)); tailf[i].user->nick=strdup(user->nick); tailf[i].user->user=strdup(user->user); tailf[i].user->host=strdup(user->host); if(!tailf[i].user) { mywrite(fd,"QUIT :malloc error 4.5!!! (a strdup again)\r\n"); return; } tailf[i].args=args?strdup(args):0; if(args) { if(!tailf[i].args) { mywrite(fd,"QUIT :malloc error 5!!! (well, strdup)\r\n"); return; } } tailf[i].lines=0; } } void c_botup(int fd,char *from,...) { char tmp[256]; snprintf(tmp,sizeof(tmp)-1,"botup: %llu",time(0)-start_time); privmsg(fd,from,tmp); } void c_leettail(int fd,char *from,char *file,struct user *user,...) { int a; int b; int c; int d; int n; if(!file) { privmsg(fd,from,"!leettail NNfilename"); privmsg(fd,from,"!leettail NNNfilename"); privmsg(fd,from,"!leettail NN#channel:filename"); privmsg(fd,from,"!leettail NNN#channel:filename"); return; } if(file[0]) { if(file[1]) { if(file[2]) { // }else { privmsg(fd,from,"usage1: !leettail NN filename"); privmsg(fd,from,"usage2: !leettail NNN filename"); return; }}} a=file[0]-'0'; b=file[1]-'0'; c=file[2]-'0'; if(c >= 0 && c <= 9) { d=(a*100)+(b*10)+(c); n=3; } else { d=(a*10)+(b); n=2; } char *args; if(file[0]==' ') file++; if((args=strchr(file,' '))) { *args=0; args++; } file_tail(fd,from,file+n,args,d,user); } void c_changetail(int fd,char *from,char *line,struct user *user,...) { struct stat st; char *merp=0; char tmp[512]; int i; int fdd; char *mode=0; if(!line) { privmsg(fd,from,"usage: !changetail filename target tailmode"); return; } if((merp=strchr(line,' '))) { *merp=0; merp++; if((mode=strchr(merp,' '))) { *mode=0; mode++; } } if((fdd=open(line,O_RDONLY|O_NONBLOCK,0)) == -1) { snprintf(tmp,sizeof(tmp)-1,"changetail: %s: (%s) fd:%d",strerror(errno),line,fdd); privmsg(fd,"#cmd",tmp); return; } if(debug) { snprintf(tmp,sizeof(tmp)-1,"changetail opened file '%s' with fd: %d / %d / %d\n",line,fdd,currentmaxtails,maxtails); privmsg(fd,"#cmd",tmp); } fstat(fdd,&st); close(fdd); for(i=0;ill;m;m=m->next) { if(strcasestr(m->original,line) || *line=='*') { snprintf(tmp,sizeof(tmp)-1," %s -> %p",m->original,m->target); privmsg(fd,from,tmp); j++; } k++; } } snprintf(tmp,sizeof(tmp)-1,"found %d of %d in builtins",j,k); privmsg(fd,from,tmp); } void c_amnesia(int fd,char *from,...) {//forget aliases ht_freevalues(&alias); ht_destroy(&alias); inittable(&alias,TSIZE); } void c_lobotomy(int fd,char *from,...) {//forget builtins ht_destroy(&builtin); inittable(&builtin,TSIZE); //don't put this as a builtin by default. :P gotta hack that out. } void c_aliases_h(int fd,char *from,char *line,...) { char tmp[512]; struct entry *m; int i,j=0,k=0; if(!line){ privmsg(fd,from,"usage: !aliases [search-term]"); return; } for(i=0;ikeys[i]); //privmsg(fd,from,tmp); for(m=alias.bucket[alias.keys[i]]->ll;m;m=m->next) { if(strcasestr(m->target,line) || strcasestr(m->original,line)) { snprintf(tmp,sizeof(tmp)-1," %s -> %s",m->original,(char *)m->target); privmsg(fd,from,tmp); j++; } k++; } } snprintf(tmp,sizeof(tmp)-1,"found %d of %d aliases",j,k); privmsg(fd,from,tmp); } void c_alias_h(int fd,char *from,char *line,...) { char tmps[512]; if(!line) { printf("usage: !alias command [other_command]"); return; } char *derp=strchr(line,' '); struct entry *tmp; if(!derp) { if((tmp=ht_getnode(&alias,line)) != NULL) { snprintf(tmps,sizeof(tmps)," %s",(char *)tmp->target); privmsg(fd,from,tmps); } else { snprintf(tmps,sizeof(tmps),"'%s' not an alias.",line); privmsg(fd,from,tmps); } return; } *derp=0; derp++; if((tmp=ht_getnode(&alias,line))) { free(tmp->target); } if(!derp) exit(77); ht_setkey(&alias,line,strdup(derp)); } void c_kill(int fd,char *from,char *line,...) { if(!line) { privmsg(fd,from,"usage: !kill signum pid"); return; } char *csig=line; char *cpid=strchr(line,' '); int sig,pid; if(cpid) { *cpid=0; cpid++; } else { privmsg(fd,from,"usage: !kill signum pid"); return; } sig=atoi(csig); 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."); } } 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,...) { if(!line) { privmsg(fd,from,"usage: !leetuntail [target|*] filename"); return; } char *frm=line; char *file; int i; if((file=strchr(line,' '))) { *file=0; file++; } else { file=line; frm="."; } if(file) { for(i=0;i %s",tailf[i].file,tailf[i].inode,ftell(tailf[i].fp),tailf[i].lines,x,tailf[i].opt,tailf[i].to); free(x); privmsg(fd,from,tmp); free(tmp); } } if(!at_least_one) { privmsg(fd,from,"I don't have any tails. :("); } } char *recording,recording_raw; void c_record(int fd,char *from,char *line,...) { if(!line) { privmsg(fd,from,"usage: !record 0|1"); return; } if(*line == '0' && *(line+1) == 0) { if(recording) free(recording); privmsg(fd,from,"no longer recording IRC."); recording=0; return; } else { recording=strdup(line); unlink(LOG); privmsg(fd,from,"recording IRC."); } privmsg(fd,from,recording?"1":"0"); } void c_rawrecord(int fd,char *from,char *line,...) { if(!line) { privmsg(fd,from,"usage: !rawrecord 0|1"); return; } 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(!msg) { privmsg(fd,from,"usage: don't"); // privmsg(fd,from,"usage: NNNfilename"); return; } char tmp[512]; 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) { snprintf(tmp,sizeof(tmp)-1,"leetsetout: %s: (%s) fd:%d",strerror(errno),msg+3,redirect_to_fd); privmsg(fd,"#cmd",tmp); return; } if(debug) { snprintf(tmp,sizeof(tmp)-1,"leetsetout opened file '%s' with fd: %d / %d / %d\n",msg+3,redirect_to_fd,currentmaxtails,maxtails); privmsg(fd,"#cmd",tmp); } } void c_linelimit(int fd,char *from,char *msg,...) { char tmp[256]; if(!msg) { snprintf(tmp,255,"current spam line limit: %d (debug: %d)",line_limit,debug); privmsg(fd,from,tmp); } else { if(msg[0] == 'a') { mode_magic^=1; privmsg(fd,from,"mode_magic flipped. happy easter!"); } if(msg[0]=='!') { if(msg[1]) { trigger_char=msg[1]; privmsg(fd,from,"trigger_char set. more easter!"); } } if(atoi(msg) > 0) { line_limit=atoi(msg); snprintf(tmp,255,"spam line limit set to: %d",line_limit); privmsg(fd,from,tmp); } else if(atoi(msg) < 0) { privmsg(fd,from,"hidden feature! negative line limit flips debug bit."); debug^=1; } else { privmsg(fd,from,"something else!"); } } } void c_resetout(int fd,char *from,...) { redirect_to_fd=-1; privmsg(fd,from,"output reset"); } void c_raw(int fd,char *from,char *msg,...) { char *tmp2; if(!msg) { privmsg(fd,from,"usage: !raw stuff-to-send-to-server"); return; } tmp2=malloc(strlen(msg)+4); snprintf(tmp2,strlen(msg)+3,"%s\r\n",msg); mywrite(fd,tmp2); free(tmp2); } void c_say(int fd,char *from,char *msg,...) { if(!msg) msg="usage: !say message"; privmsg(fd,from,msg); } void c_nick(int fd,char *from,char *msg,...) { if(!msg) { privmsg(fd,from,"usage: !nick new-nick-to-try"); return; } free(myuser->nick); if(!msg) exit(78); myuser->nick=strdup(msg); irc_nick(fd,myuser->nick); } void message_handler(int fd,char *from,struct user *user,char *msg,int redones) { struct entry *m; union hack lol; char lambdad; char *command; char *oldcommand; char *args; char tmp[512]; char *tmp2; int len; int sz; //privmsg(fd,"#debug",msg); //debug_time(fd,from); if(user->nick) { if(strcmp(user->nick,myuser->nick)) { for(sz=0;shitlist[sz];sz++) { if(!strcmp(shitlist[sz],user->nick)) { return; } } } } if(redirect_to_fd != -1) { fd=redirect_to_fd; } if(recording) { debug_time(fd,from,"writing to log..."); //snprintf(tmp,sizeof(tmp)-1,"<%s> %s",user->nick,msg); tmp2=format_magic(fd,from,user,recording,msg); append_file(fd,user->nick,LOG,tmp2,'\n'); free(tmp2); debug_time(fd,from,"finished writing to log."); } len=strchr(msg,'*')?strchr(msg,'*')-msg:strlen(myuser->nick); if(!strncmp(msg,myuser->nick,len)) { if(msg[len] == '*') len++; if(msg[len] == ',' || msg[len] == ':') { if(msg[len+1] == ' ') { msg+=len+1; msg[0]=trigger_char; } } } //if(*msg == trigger_char) *msg='!'; //if(*msg != '!') { // return; //} if(!msg) exit(71); oldcommand=strdup(msg); command=oldcommand; if(*command == trigger_char) { command++; } else { free(oldcommand); return; } if((args=strchr(command,' '))) { *args=0; args++; } while(!strncmp(command,"lambda",6)) { command+=8; if((args=strchr(command,' '))) { *args=0; args++; } args=format_magic(fd,from,user,args,args); lambdad=1; } if((lol.data=ht_getvalue(&builtin,command))) { func=lol.func; func(fd,from,args,user); if(lambdad) {free(args);} } else if(redones < 5) { debug_time(fd,from,"checking aliases..."); command--;// :> if((m=ht_getnode(&alias,command)) != NULL) { sz=(strlen(msg)-strlen(m->original)+strlen(m->target)+1); redo=format_magic(fd,from,user,m->target,*(msg+strlen(m->original)+1)=='\n'?"":(msg+strlen(m->original)+1)); message_handler(fd,from,user,redo,redones+1); free(redo); redo=0; free(oldcommand); return; } debug_time(fd,from,"finished checking aliases. not found."); redo=0; if(debug) { snprintf(tmp,sizeof(tmp)-1,"command not found: '%s' with args '%s'",command,args); privmsg(fd,from,tmp); } } if(redones >5) { privmsg(fd,from,"I don't know if I'll ever get out of this alias hole you're telling me to dig. Fuck this."); } free(oldcommand); } void line_handler(int fd,char *line) {//this should be built into the libary? char tmp[512]; struct user *user=malloc(sizeof(struct user)); if(recording_raw) { append_file(fd,"epoch",RAWLOG,line,'\n'); } //line will be mangled by the cutter. char **a=line_cutter(fd,line,user); if(!user->user && a[0]) { //server message //:armitage.hacking.allowed.org 353 asdf = #default :@SegFault @FreeArtMan @foobaz @wall @Lamb3_13 @gizmore @blackh0le strcpy(tmp,"!"); strcat(tmp,a[0]); if(ht_getnode(&alias,tmp) == NULL && ht_getnode(&alias,"!###") != NULL) { strcpy(tmp,"!###"); // privmsg(fd,*a[1]=='#'?a[1]:user->nick,a[0]); } if(ht_getnode(&alias,tmp) != NULL) { strcat(tmp," "); strcat(tmp,a[2]);//lol. fixme. user->nick=strdup("epoch"); user->user=strdup("epoch"); user->host=strdup("localhost"); message_handler(fd,"#cmd",user,tmp,1); free(user->nick); free(user->user); free(user->host); } } if(a[0] && a[1] && a[2]) { if(!strcmp(a[0],"PRIVMSG") && strcmp(user->nick,myuser->nick)) { if(strcmp(user->nick,myuser->nick)) { message_handler(fd,*a[1]=='#'?a[1]:user->nick,user,a[2],0); } else { if(debug) privmsg(fd,*a[2]=='#'?a[2]:user->nick,"This server has an echo"); } } } if(a[0] && user->nick && a[1]) { if(!strcmp(a[0],"JOIN")) { irc_mode(fd,a[1],"+o",user->nick); } if(!strcmp(a[0],"MODE") && mode_magic) { if(a[2]) { if(*a[2] == '-') {//auto-give modes back that are removed in front of segfault. *a[2]='+'; irc_mode(fd,a[1],a[2],""); } } } if(!strcmp(a[0],"NICK") && a[1]) { if(!strcmp(user->nick,myuser->nick)) { free(myuser->nick); if(!a[1]) exit(79); if(!(myuser->nick=strdup(a[1]))) exit(179); } } } free(user); free(a); } int main(int argc,char *argv[]) { int fd; struct passwd *pwd; struct rlimit nofile; char *s,*p; int c; inittable(&builtin,TSIZE); #define BUILDIN(a,b) ht_setkey(&builtin,a,(void *)((union hack){(void (*)(int,...))b}.data)) BUILDIN("builtin",c_builtin); BUILDIN("builtins",c_builtins); BUILDIN("raw",c_raw); BUILDIN("leetsetout",c_leetsetout); BUILDIN("resetout",c_resetout); BUILDIN("botup",c_botup); BUILDIN("linelimit",c_linelimit); BUILDIN("nick",c_nick); BUILDIN("tailunlock",c_tailunlock); BUILDIN("istaillocked",c_istaillocked); BUILDIN("changetail",c_changetail); BUILDIN("tails",c_tails); BUILDIN("record",c_record); BUILDIN("rawrecord",c_rawrecord); BUILDIN("leettail",c_leettail); BUILDIN("leetuntail",c_leetuntail); BUILDIN("leetappend",c_leetappend); BUILDIN("say",c_say); BUILDIN("id",c_id); BUILDIN("kill",c_kill); BUILDIN("alias",c_alias_h); BUILDIN("aliases",c_aliases_h); BUILDIN("lobotomy",c_lobotomy); BUILDIN("amnesia",c_amnesia); mode_magic=0; trigger_char='!'; redirect_to_fd=-1; debug=0; lines_sent=0; line_limit=25; recording=0; recording_raw=0; start_time=time(0); redo=0; inittable(&alias,TSIZE); if(getrlimit(RLIMIT_NOFILE,&nofile) == -1) { printf("couldn't get max open files limit.\n"); exit(0); } else { maxtails=nofile.rlim_max; currentmaxtails=4; tailf=malloc(sizeof(struct tail) * (maxtails + 1)); } myuser=malloc(sizeof(struct user)); myuser->nick=strdup(argc>1?argv[1]:NICK); myuser->host="I_dunno";//??? snprintf(pid,6,"%d",getpid()); printf("starting segfault...\n"); if(!getuid() || !geteuid()) { s=getenv("seguser"); pwd=getpwnam(s?s:MYUSER); if(!pwd) { printf("I'm running with euid or uid of 0 and I can't find myself."); return 0; } setgroups(0,0); setgid(pwd->pw_gid); setuid(pwd->pw_uid); } else { pwd=getpwuid(getuid()); printf("going to run segfault as user %s\n",pwd->pw_name); if(!pwd) { printf("well, shit. I don't know who I am."); return 0; } } myuser->user=strdup(pwd->pw_name); for(c=0;cnick, // "segfault segfault segfault :segfault"); printf("cd %s\n",pwd->pw_dir); chdir(getenv("seghome")?getenv("seghome"):pwd->pw_dir); getcwd(seghome,SEGHOMELEN); prestartup_stuff(fd); return runit(fd,line_handler,extra_handler); }