/* * iroffer by David Johnson (PMG) * Copyright (C) 1998-2005 David Johnson * * By using this file, you agree to the terms and conditions set * forth in the GNU General Public License. More information is * available in the README file. * * If you received this file without documentation, it can be * downloaded from http://iroffer.org/ * * @(#) iroffer_utilities.c 1.205@(#) * pmg@wellington.i202.centerclick.org|src/iroffer_utilities.c|20051123201144|35346 * */ /* include the headers */ #include "iroffer_config.h" #include "iroffer_defines.h" #include "iroffer_headers.h" #include "iroffer_globals.h" #include "dinoex_utilities.h" const char* strstrnocase (const char *str1, const char *match1) { char *str, *match; const char *retval; str = mycalloc(strlen(str1)+1); match = mycalloc(strlen(match1)+1); strncpy(str,str1,strlen(str1)+1); caps(str); strncpy(match,match1,strlen(match1)+1); caps(match); retval = strstr(str, match); if (retval) { retval = str1 + (retval - str); } mydelete(str); mydelete(match); return retval; } char* getpart2(const char *line, int howmany, const char *src_function, const char *src_file, int src_line) { char *part; int li; int plen; int hi; li=0; for (hi = 1; hi < howmany; hi++) { while (line[li] != ' ') { if (line[li] == '\0') { return NULL; } else { li++; } } li++; } if (line[li] == '\0') { return NULL; } for (plen=0; (line[li] != ' ') && (line[li] != '\0'); plen++, li++) ; li -= plen; part = mymalloc2(plen+1, 0, src_function, src_file, src_line); memcpy(part, line+li, plen); part[plen] = '\0'; return part; } /* respect quotes */ /* Iroffer lamm */ char* getpartquotes2(const char *line, int howmany, const char *src_function, const char *src_file, int src_line) { char *part; int li; int plen; int hi; int inquotes; li=0; inquotes=0; for (hi = 1; hi < howmany; hi++) { while (line[li] != ' ' || inquotes == 1 ) { if (line[li] == '\0') { return NULL; } else { if (line[li]== '"') { inquotes ^= 1; } li++; } } li++; } if (line[li] == '\0') { return NULL; } for (plen=0; (line[li] != ' ' || inquotes == 1) && (line[li] != '\0'); plen++, li++) if (line[li] == '"') inquotes ^= 1; li -= plen; part = mymalloc2(plen+1, 1, src_function, src_file, src_line); memcpy(part, line+li, plen); return part; } char* caps(char *text) { int i; if (text) for (i=0; i= 'a' && text[i] <= 'z' ) text[i] = text[i]-32; return text; } char* nocaps(char *text) { int i; if (text) for (i=0; i= 'A' && text[i] <= 'Z' ) text[i] = text[i]+32; return text; } char* sizestr(int spaces, off_t num) { #define SIZESTR_SIZE 5 char *str = mycalloc(SIZESTR_SIZE); if (num >= 1024*1024*1024*1000ULL) { /* >1000GB */ snprintf(str, SIZESTR_SIZE, "%2.1fT", (((float)num)/(1024.0*1024.0*1024.0*1024.0))); } else if (num >= 1024*1024*1024*10ULL) { /* >10GB */ snprintf(str, SIZESTR_SIZE, "%3.0fG", (((float)num)/(1024.0*1024.0*1024.0))); } else if (num >= 1024*1024*1000) { /* >1000MB */ snprintf(str, SIZESTR_SIZE, "%2.1fG", (((float)num)/(1024.0*1024.0*1024.0))); } else if (num >= 1024*1024*10) { /* >10MB */ snprintf(str, SIZESTR_SIZE, spaces ? "%3.0fM" : "%.0fM", (((float)num)/(1024.0*1024.0))); } else if (num >= 1024*1000) { /* >1000KB */ snprintf(str, SIZESTR_SIZE, "%2.1fM", (((float)num)/(1024.0*1024.0))); } else if (num >= 1024) { /* >1KB */ snprintf(str, SIZESTR_SIZE, spaces ? "%3.0fK" : "%.0fK", (((float)num)/1024.0)); } else if (num >= 1) { /* <1KB */ snprintf(str, SIZESTR_SIZE, spaces ? " <1K" : "<1K"); } else { snprintf(str,SIZESTR_SIZE, spaces ? " 0" : "0"); } return str; } void getos (void) { struct utsname u1; updatecontext(); if ( uname(&u1) < 0) outerror(OUTERROR_TYPE_CRASH,"Couldn't Get Your OS Type"); printf("** You Are Running %s %s on a %s",u1.sysname,u1.release,u1.machine); mylog(CALLTYPE_NORMAL,"You Are Running %s %s on a %s",u1.sysname,u1.release,u1.machine); gdata.osstring = mymalloc(strlen(u1.sysname) + strlen(u1.release) + 2); sprintf(gdata.osstring, "%s %s", u1.sysname, u1.release); /* verify we are who we were configured for, and set config */ #if defined(_OS_Linux) if (strcmp(u1.sysname,"Linux")) outerror(OUTERROR_TYPE_WARN_LOUD,"Configured for Linux but not running Linux?!?"); printf(", Good\n"); #elif defined(_OS_FreeBSD) || \ defined(_OS_OpenBSD) || \ defined(_OS_NetBSD) || \ defined(_OS_BSDI) || \ defined(_OS_BSD_OS) if (strcmp(u1.sysname,"FreeBSD") && strcmp(u1.sysname,"OpenBSD") && strcmp(u1.sysname,"BSD/OS") && strcmp(u1.sysname,"NetBSD")) outerror(OUTERROR_TYPE_WARN_LOUD,"Configured for *BSD but not running *BSD?!?"); printf(", Good\n"); #elif defined(_OS_SunOS) if (strcmp(u1.sysname,"SunOS")) outerror(OUTERROR_TYPE_WARN_LOUD,"Configured for Solaris but not running Solaris?!?"); printf(", Good\n"); #elif defined(_OS_HPUX) if (strcmp(u1.sysname,"HP-UX")) outerror(OUTERROR_TYPE_WARN_LOUD,"Configured for HP-UX but not running HP-UX?!?"); printf(", Good\n"); #elif defined(_OS_IRIX) if (strcmp(u1.sysname,"IRIX")) outerror(OUTERROR_TYPE_WARN_LOUD,"Configured for IRIX but not running IRIX?!?"); printf(", Good\n"); #elif defined(_OS_IRIX64) if (strcmp(u1.sysname,"IRIX64")) outerror(OUTERROR_TYPE_WARN_LOUD,"Configured for IRIX64 but not running IRIX64?!?"); printf(", Good\n"); #elif defined(_OS_OSF1) if (strcmp(u1.sysname,"OSF1")) outerror(OUTERROR_TYPE_WARN_LOUD,"Configured for OSF1 but not running OSF1?!?"); printf(", Good\n"); #elif defined(_OS_Rhapsody) if (strcmp(u1.sysname,"Rhapsody")) outerror(OUTERROR_TYPE_WARN_LOUD,"Configured for Rhapsody but not running Rhapsody?!?"); printf(", Good\n"); #elif defined(_OS_Darwin) if (strcmp(u1.sysname,"Darwin")) outerror(OUTERROR_TYPE_WARN_LOUD,"Configured for Darwin but not running Darwin?!?"); printf(", Good\n"); #elif defined(_OS_AIX) if (strcmp(u1.sysname,"AIX")) outerror(OUTERROR_TYPE_WARN_LOUD,"Configured for AIX but not running AIX?!?"); printf(", Good\n"); #elif defined(_OS_CYGWIN) if (strncmp(u1.sysname,"CYGWIN",6)) { outerror(OUTERROR_TYPE_WARN_LOUD,"Configured for CYGWIN but not running CYGWIN?!?"); } { int count,v1=0,v2=0,v3=0; count = sscanf(u1.release,"%d.%d.%d",&v1,&v2,&v3); if ( (v1 < 1) || ((v1 == 1) && (v2 < 5)) || ((v1 == 1) && (v2 == 5) && (v3 < 3)) ) { printf(", Too Old\n"); outerror(OUTERROR_TYPE_CRASH,"CYGWIN too old (1.5.3 or greater required)"); } } printf(", Good\n"); #else printf(", I don't know of that!\n"); #endif } void outerror (outerror_type_e type, const char *format, ...) { char tempstr[maxtextlength]; va_list args; int ioutput_options = OUT_S|OUT_L|OUT_D; int len; /* can't log an error if the error was due to logging */ if (type & OUTERROR_TYPE_NOLOG) { ioutput_options &= ~OUTERROR_TYPE_NOLOG; } type &= ~OUTERROR_TYPE_NOLOG; updatecontext(); va_start(args, format); len = vsnprintf(tempstr, maxtextlength, format, args); va_end(args); if ((len < 0) || (len >= maxtextlength)) { snprintf(tempstr, maxtextlength-1, "OUTERROR-INT: Output too large, ignoring!"); } if (!gdata.background && !gdata.attop) gototop(); if ( type == OUTERROR_TYPE_CRASH ) { ioutput(CALLTYPE_NORMAL,ioutput_options,COLOR_RED|COLOR_BOLD,"ERROR: %s",tempstr); tostdout_disable_buffering(1); uninitscreen(); if (gdata.background) { printf("** ERROR: %s\n\n",tempstr); } mylog(CALLTYPE_NORMAL,"iroffer exited (Error)\n\n"); if (gdata.pidfile) unlink(gdata.pidfile); exit(1); } else if (type == OUTERROR_TYPE_WARN_LOUD ) { ioutput(CALLTYPE_NORMAL,ioutput_options,COLOR_RED|COLOR_BOLD,"WARNING: %s",tempstr); } else if (type == OUTERROR_TYPE_WARN ) { ioutput(CALLTYPE_NORMAL,ioutput_options,COLOR_RED,"WARNING: %s",tempstr); } } char* getdatestr(char* str, time_t Tp, int len) { struct tm *localt = NULL; size_t llen; if (Tp == 0) { Tp = gdata.curtime; } localt = localtime(&Tp); llen = strftime (str, len, "%Y-%m-%d-%H:%M:%S", localt); if ((llen == 0) || (llen == len)) { str[0] = '\0'; } return str; } char* getuptime(char *str, int type, time_t fromwhen, int len) { int days, hours, mins; long temp; int llen; updatecontext(); temp = (gdata.curtime-fromwhen)/60; days = temp/60/24; hours = temp/60 - (24*days); mins = temp - (60*hours) - (24*60*days); if (type) { llen = snprintf(str, len, "%dD %dH %dM", days, hours, mins); } else { llen = snprintf(str, len, "%d Days %d Hrs and %d Min", days, hours, mins); } if ((llen < 0) || (llen >= len)) { str[0] = '\0'; } return str; } void mylog(calltype_e type, const char *format, ...) { char tempstr[maxtextlength]; va_list args; int len; if (gdata.logfile == NULL) { return; } if (gdata.logfd == FD_UNUSED) { gdata.logfd = open(gdata.logfile, O_WRONLY | O_CREAT | O_APPEND | ADDED_OPEN_FLAGS, CREAT_PERMISSIONS); if (gdata.logfd < 0) { outerror(OUTERROR_TYPE_WARN_LOUD | OUTERROR_TYPE_NOLOG, "Cant Access Log File '%s': %s", gdata.logfile,strerror(errno)); gdata.logfd = FD_UNUSED; return; } } if ((type == CALLTYPE_NORMAL) || (type == CALLTYPE_MULTI_FIRST)) { write(gdata.logfd,"** ",3); getdatestr(tempstr,0,maxtextlength); write(gdata.logfd,tempstr,strlen(tempstr)); write(gdata.logfd,": ",2); } va_start(args, format); len = vsnprintf(tempstr, maxtextlength, format, args); va_end(args); if ((len < 0) || (len >= maxtextlength)) { outerror(OUTERROR_TYPE_WARN_LOUD | OUTERROR_TYPE_NOLOG, "MYLOG-INT: Output too large, ignoring!"); return; } write(gdata.logfd,tempstr,strlen(tempstr)); if ((type == CALLTYPE_NORMAL) || (type == CALLTYPE_MULTI_END)) { write(gdata.logfd,"\n",1); } return; } unsigned long atoul (const char *str) { unsigned long num,temp; int i,j; if (str == NULL) return 0; num = 0; for (i=strlen(str)-1; i>=0; i--) { temp = (str[i]-'0'); for (j=strlen(str)-1; j>i; j--) temp *= 10; num += temp; } return num; } unsigned long long atoull (const char *str) { unsigned long long num,temp; int i,j; if (str == NULL) return 0; num = 0; for (i=strlen(str)-1; i>=0; i--) { temp = (str[i]-'0'); for (j=strlen(str)-1; j>i; j--) temp *= 10; num += temp; } return num; } void ioutput(calltype_e type, int dest, unsigned int color_flags, const char *format, ...) { va_list args; va_start(args, format); vioutput(type, dest, color_flags, format, args); va_end(args); } void vioutput(calltype_e type, int dest, unsigned int color_flags, const char *format, va_list ap) { char tempstr[maxtextlength]; int len; dccchat_t *chat; len = vsnprintf(tempstr,maxtextlength,format,ap); if ((len < 0) || (len >= maxtextlength)) { snprintf(tempstr, maxtextlength-1, "IOUTPUT-INT: Output too large, ignoring!"); } /* screen */ if (!gdata.background && (dest & OUT_S)) { if (!gdata.attop) gototop(); if ((type == CALLTYPE_NORMAL) || (type == CALLTYPE_MULTI_FIRST)) { if (!gdata.nocolor && (color_flags != COLOR_NO_COLOR)) { tostdout("\x1b[%d;%dm", (color_flags & COLOR_BOLD) ? 1 : 0, (color_flags & ~COLOR_BOLD)); } if (gdata.timestampconsole) { char tempstr2[maxtextlength]; getdatestr(tempstr2,0,maxtextlength); tostdout("** %s: ",tempstr2); } else { tostdout("** "); } } tostdout("%s",tempstr); if ((type == CALLTYPE_NORMAL) || (type == CALLTYPE_MULTI_END)) { if (!gdata.nocolor && (color_flags != COLOR_NO_COLOR)) { tostdout("\x1b[0m\n"); } else { tostdout("\n"); } } } /* log */ if (dest & OUT_L) mylog(type,"%s",tempstr); /* dcc chat */ if (dest & OUT_D) { for (chat = irlist_get_head(&gdata.dccchats); chat; chat = irlist_get_next(chat)) { if (chat->status == DCCCHAT_CONNECTED) { if ((type == CALLTYPE_NORMAL) || (type == CALLTYPE_MULTI_FIRST)) { writedccchat(chat, 0, "--> "); } writedccchat(chat, 0, "%s", tempstr); if ((type == CALLTYPE_NORMAL) || (type == CALLTYPE_MULTI_END)) { writedccchat(chat, 0, "\n"); } } } } } void privmsg_slow(const char *nick, const char *format, ...) { va_list args; va_start(args, format); vprivmsg_slow(nick, format, args); va_end(args); } void vprivmsg_slow(const char *nick, const char *format, va_list ap) { char tempstr[maxtextlength]; int len; if (!nick) return; len = vsnprintf(tempstr,maxtextlength,format,ap); if ((len < 0) || (len >= maxtextlength)) { outerror(OUTERROR_TYPE_WARN,"PRVMSG-SLOW: Output too large, ignoring!"); return; } writeserver(WRITESERVER_SLOW, "PRIVMSG %s :%s", nick, tempstr); } void privmsg_fast(const char *nick, const char *format, ...) { va_list args; va_start(args, format); vprivmsg_fast(nick, format, args); va_end(args); } void vprivmsg_fast(const char *nick, const char *format, va_list ap) { char tempstr[maxtextlength]; int len; if (!nick) return; len = vsnprintf(tempstr,maxtextlength,format,ap); if ((len < 0) || (len >= maxtextlength)) { outerror(OUTERROR_TYPE_WARN,"PRVMSG-FAST: Output too large, ignoring!"); return; } writeserver(WRITESERVER_FAST, "PRIVMSG %s :%s", nick, tempstr); } void privmsg(const char *nick, const char *format, ...) { va_list args; va_start(args, format); vprivmsg(nick, format, args); va_end(args); } void vprivmsg(const char *nick, const char *format, va_list ap) { char tempstr[maxtextlength]; int len; if (!nick) return; len = vsnprintf(tempstr,maxtextlength,format,ap); if ((len < 0) || (len >= maxtextlength)) { outerror(OUTERROR_TYPE_WARN,"PRVMSG: Output too large, ignoring!"); return; } writeserver(WRITESERVER_NORMAL, "PRIVMSG %s :%s", nick, tempstr); } void notice_slow(const char *nick, const char *format, ...) { va_list args; va_start(args, format); vnotice_slow(nick, format, args); va_end(args); } void vnotice_slow(const char *nick, const char *format, va_list ap) { char tempstr[maxtextlength]; int len; if (!nick) return; len = vsnprintf(tempstr,maxtextlength,format,ap); if ((len < 0) || (len >= maxtextlength)) { outerror(OUTERROR_TYPE_WARN,"NOTICE-SLOW: Output too large, ignoring!"); return; } writeserver(WRITESERVER_SLOW, "NOTICE %s :%s", nick, tempstr); } void notice_fast(const char *nick, const char *format, ...) { va_list args; va_start(args, format); vnotice_fast(nick, format, args); va_end(args); } void vnotice_fast(const char *nick, const char *format, va_list ap) { char tempstr[maxtextlength]; int len; if (!nick) return; len = vsnprintf(tempstr,maxtextlength,format,ap); if ((len < 0) || (len >= maxtextlength)) { outerror(OUTERROR_TYPE_WARN,"NOTICE-FAST: Output too large, ignoring!"); return; } writeserver(WRITESERVER_FAST, "NOTICE %s :%s", nick, tempstr); } void notice(const char *nick, const char *format, ...) { va_list args; va_start(args, format); vnotice(nick, format, args); va_end(args); } void vnotice(const char *nick, const char *format, va_list ap) { char tempstr[maxtextlength]; int len; if (!nick) return; len = vsnprintf(tempstr,maxtextlength,format,ap); if ((len < 0) || (len >= maxtextlength)) { outerror(OUTERROR_TYPE_WARN,"NOTICE: Output too large, ignoring!"); return; } writeserver(WRITESERVER_NORMAL, "NOTICE %s :%s", nick, tempstr); } char* hostmasktoregex(const char *str) { char *tempstr; int i,j; int maxlen; updatecontext(); if (!str) return NULL; maxlen = 2 + (strlen(str) * 11); tempstr = mycalloc(maxlen+1); tempstr[0] = '^'; for (i=0,j=1; i= 'a' && str[i] <= 'z') || (str[i] >= 'A' && str[i] <= 'Z') || (str[i] >= '0' && str[i] <= '9') ) tempstr[j] = str[i]; else if (str[i] == '?') tempstr[j] = '.'; else if (str[i] == '*') { tempstr[j] = '.'; j++; tempstr[j] = '*'; } else if (str[i] == '#') { tempstr[j] = '['; j++; tempstr[j] = '0'; j++; tempstr[j] = '-'; j++; tempstr[j] = '9'; j++; tempstr[j] = ']'; j++; tempstr[j] = '['; j++; tempstr[j] = '0'; j++; tempstr[j] = '-'; j++; tempstr[j] = '9'; j++; tempstr[j] = ']'; j++; tempstr[j] = '*'; } else { tempstr[j] = '\\'; j++; tempstr[j] = str[i]; } } tempstr[j] = '$'; tempstr[j+1] = '\0'; return tempstr; } int verifyhost(irlist_t *list, const char *hmask) { regex_t *ah; updatecontext(); ah = irlist_get_head(list); while (ah) { if (!regexec(ah,hmask,0,NULL,0)) { return 1; } ah = irlist_get_next(ah); } return 0; } int verifypass(const char *testpass) { #ifndef NO_CRYPT char *pwout; updatecontext(); if ( !gdata.adminpass || !testpass ) return 0; if ( strlen(gdata.adminpass) < 13 || strlen(testpass) < 5 || strlen(testpass) > 59 ) return 0; pwout = crypt(testpass,gdata.adminpass); if (strcmp(pwout,gdata.adminpass)) return 0; #else if ( !gdata.adminpass || !testpass ) return 0; if (strcmp(testpass,gdata.adminpass)) return 0; #endif return 1; } char* getfline(char* str, int slen, int descr, int ret) { char *tempbuf; int i, j, len; updatecontext(); tempbuf = mycalloc(slen); j = 0; str[0] = '\0'; while((len = read(descr,tempbuf,slen)) > 0) { for (i=0; i= slen) { outerror(OUTERROR_TYPE_WARN,"Line too long, truncating"); } else { str[j] = tempbuf[i]; j++; } } } } mydelete(tempbuf); return NULL; } int packnumtonum(const char *a) { if (!a) return 0; if (a[0] == '#') a++; return atoi(a); } int sstrlen (const char *p) { if (!p) return -1; return ((int)(strlen(p))); } char dayofweektomask(const char a) { switch (a) { case 'U': return 0x01; case 'M': return 0x02; case 'T': return 0x04; case 'W': return 0x08; case 'R': return 0x10; case 'F': return 0x20; case 'S': return 0x40; default: return 0x00; } return 0; } /* reverse a string */ char *strrev(char *str) { int i,len; char c; len = sstrlen(str); for (i=0; i= 0x20 && a <= 0x7E ) return 1; else return 0; } char onlyprintable(char a) { if ( a >= 0x20 && a <= 0x7E ) return a; else return '.'; } static unsigned long mycalloc_hash(void *ptr) { unsigned long retval; retval = 0xAA; retval ^= ((unsigned long)ptr >> 0) & 0xFF; retval ^= ((unsigned long)ptr >> 8) & 0xFF; retval ^= ((unsigned long)ptr >> 16) & 0xFF; retval ^= ((unsigned long)ptr >> 24) & 0xFF; return retval & (MEMINFOHASHSIZE-1); } static void meminfo_grow(int grow) { meminfo_t *newmeminfo; int cc; int dd; int len; int i; int start; len = MEMINFOHASHSIZE * sizeof(meminfo_t) * (gdata.meminfo_depth+grow); newmeminfo = calloc(len,1); /* replace zero entry */ if (gdata.meminfo) { gdata.meminfo[0].ptr = NULL; gdata.meminfo[0].alloctime = 0; gdata.meminfo[0].size = 0; gdata.meminfo[0].src_func = NULL; gdata.meminfo[0].src_file = NULL; gdata.meminfo[0].src_line = 0; } else { /* first time, count item #0 */ gdata.meminfo_count++; } newmeminfo[0].ptr = newmeminfo; newmeminfo[0].alloctime = gdata.curtime; newmeminfo[0].size = len; newmeminfo[0].src_func = __FUNCTION__; newmeminfo[0].src_file = __FILE__; newmeminfo[0].src_line = __LINE__; for (cc=0; cc 0) { ioutput(CALLTYPE_NORMAL,OUT_S,COLOR_NO_COLOR,"growing meminfo from %d to %d", gdata.meminfo_depth-grow, gdata.meminfo_depth); } return; } void* mymalloc2(int len, int zero, const char *src_function, const char *src_file, int src_line) { void *t = NULL; int i; unsigned long start; updatecontext(); t = zero ? calloc(len,1) : malloc(len); if (t == NULL) { outerror(OUTERROR_TYPE_CRASH,"Couldn't Allocate Memory!!"); } if (gdata.meminfo_count >= ((MEMINFOHASHSIZE * gdata.meminfo_depth) / 2)) { meminfo_grow(gdata.meminfo_depth/3 + 1); } start = mycalloc_hash(t) * gdata.meminfo_depth; for (i=0; gdata.meminfo[(i+start)%(MEMINFOHASHSIZE * gdata.meminfo_depth)].ptr; i++) ; i = (i+start)%(MEMINFOHASHSIZE * gdata.meminfo_depth); gdata.meminfo[i].ptr = t; gdata.meminfo[i].alloctime = gdata.curtime; gdata.meminfo[i].size = len; gdata.meminfo[i].src_func = src_function; gdata.meminfo[i].src_file = src_file; gdata.meminfo[i].src_line = src_line; gdata.meminfo_count++; return t; } void mydelete2(void *t) { unsigned char *ut = (unsigned char *)t; int i; unsigned long start; updatecontext(); if (t == NULL) return; start = mycalloc_hash(t) * gdata.meminfo_depth; for (i=0; (i<(MEMINFOHASHSIZE * gdata.meminfo_depth) && (gdata.meminfo[(i+start)%(MEMINFOHASHSIZE * gdata.meminfo_depth)].ptr != t)); i++) ; if (i == (MEMINFOHASHSIZE * gdata.meminfo_depth)) { outerror(OUTERROR_TYPE_WARN_LOUD,"Pointer 0x%8.8lX not found in meminfo database while trying to free!!",(long)t); outerror(OUTERROR_TYPE_WARN_LOUD,"Please report this error to http://iroffer-lamm.sf.net/"); for(i=0; i<(12*12); i+=12) { outerror(OUTERROR_TYPE_WARN_LOUD," : %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X = \"%c%c%c%c%c%c%c%c%c%c%c%c\"", ut[i+0], ut[i+1], ut[i+2], ut[i+3], ut[i+4], ut[i+5], ut[i+6], ut[i+7], ut[i+8], ut[i+9], ut[i+10], ut[i+11], onlyprintable(ut[i+0]), onlyprintable(ut[i+1]), onlyprintable(ut[i+2]), onlyprintable(ut[i+3]), onlyprintable(ut[i+4]), onlyprintable(ut[i+5]), onlyprintable(ut[i+6]), onlyprintable(ut[i+7]), onlyprintable(ut[i+8]), onlyprintable(ut[i+9]), onlyprintable(ut[i+10]), onlyprintable(ut[i+11])); } outerror(OUTERROR_TYPE_WARN_LOUD,"Aborting Program! (core file should be generated)"); abort(); /* getting a core file will help greatly */ } else { free(t); i = (i+start)%(MEMINFOHASHSIZE * gdata.meminfo_depth); gdata.meminfo[i].ptr = NULL; gdata.meminfo[i].alloctime = 0; gdata.meminfo[i].size = 0; gdata.meminfo[i].src_func = NULL; gdata.meminfo[i].src_file = NULL; gdata.meminfo[i].src_line = 0; gdata.meminfo_count--; } if ((gdata.meminfo_depth > 1) && (gdata.meminfo_count < ((MEMINFOHASHSIZE * gdata.meminfo_depth) / 8))) { meminfo_grow(-1); } return; } char* removenonprintable(char *str1) { int i; unsigned char *str = (unsigned char*)str1; if (!str) return NULL; for (i=0; i= 0x20 && str[i] <= 0x7E) || (str[i] >= 0xA1) || str[i] == 0x01 || /* ctcp */ str[i] == 0x02 || /* bold */ str[i] == 0x03 || /* color */ str[i] == 0x09 || /* tab */ str[i] == 0x0A || /* return */ str[i] == 0x0D || /* return */ str[i] == 0x0F || /* end formatting */ str[i] == 0x16 || /* inverse */ str[i] == 0x1F )) /* underline */ str[i] = '.'; } return (char *)str; } char* removenonprintablectrl(char *str1) { int i; unsigned char *str = (unsigned char*)str1; if (!str) return NULL; for (i=0; i= 0x20 && str[i] <= 0x7E) || (str[i] >= 0xA1))) str[i] = ' '; } return (char *)str; } char* removenonprintablefile(char *str) { int i; char last='.'; if (!str) return NULL; for (i=0; i= 0x7E) str[i] = '_'; if (str[i] < 0x28) str[i] = '_'; switch (str[i]) { case 0x2F: case 0x3A: case 0x3D: case 0x3F: case 0x40: case 0x5C: case 0x60: case 0x7C: str[i] = '_'; } if (last == '.' && str[i] == '.') str[i] = '_'; last = str[i]; } return str; } int doesfileexist(const char *f) { int fd; updatecontext(); if (!f) return 0; if ((fd = open(f,O_RDONLY | O_CREAT | O_EXCL | ADDED_OPEN_FLAGS, CREAT_PERMISSIONS)) < 0 && errno == EEXIST) return 1; else if (fd < 0) return 0; close(fd); unlink(f); return 0; } void checkadminpass(void) { #ifndef NO_CRYPT int err=0,i; updatecontext(); if (!gdata.adminpass || strlen(gdata.adminpass) < 13) err++; for (i=0; !err && i= 'a' && gdata.adminpass[i] <= 'z') || (gdata.adminpass[i] >= 'A' && gdata.adminpass[i] <= 'Z') || (gdata.adminpass[i] >= '0' && gdata.adminpass[i] <= '9') || (gdata.adminpass[i] == '.') || (gdata.adminpass[i] == '$') || (gdata.adminpass[i] == '/'))) err++; } if (err) outerror(OUTERROR_TYPE_CRASH,"adminpass is not encrypted!"); #endif } void updatecontext_f(const char *file, const char *func, int line) { context_t *c; if (gdata.crashing) { return; } gdata.context_cur_ptr++; if (gdata.context_cur_ptr > (2*MAXCONTEXTS)) gdata.context_cur_ptr = gdata.context_cur_ptr % MAXCONTEXTS; c = &gdata.context_log[gdata.context_cur_ptr % MAXCONTEXTS]; c->file = file; c->func = func; c->line = line; if (gdata.debug > 0) { gettimeofday(&c->tv, NULL); } else { c->tv.tv_sec = 0; c->tv.tv_usec = 0; } } void dumpcontext(void) { int i; context_t *c; for (i=0; ifunc ? c->func : "UNKNOWN", c->file ? c->file : "UNKNOWN", c->line, (unsigned long)c->tv.tv_sec, (unsigned long)c->tv.tv_usec); } return; } #define gdata_common CALLTYPE_NORMAL,OUT_S|OUT_L|OUT_D,COLOR_NO_COLOR #define gdata_string(x) ((x) ? (x) : "") #define gdata_print_number(format,name) \ ioutput(gdata_common, "GDATA * " #name ": " format, gdata. name); #define gdata_print_number_cast(format,name,type) \ ioutput(gdata_common, "GDATA * " #name ": " format, (type) gdata. name); #define gdata_print_string(name) \ ioutput(gdata_common, "GDATA * " #name ": %s", gdata_string(gdata. name)); #define gdata_print_int(name) gdata_print_number("%d", name) #define gdata_print_uint(name) gdata_print_number("%u", name) #define gdata_print_long(name) gdata_print_number("%ld", name) #define gdata_print_ulong(name) gdata_print_number("%lu", name) #define gdata_print_float(name) gdata_print_number("%.5f", name) #define gdata_print_number_array(format,name) \ { if (gdata. name [ii]) { ioutput(gdata_common, "GDATA * " #name "[%d]: " format, ii, gdata. name [ii]); } } #define gdata_print_string_array(name) \ { if (gdata. name [ii]) { ioutput(gdata_common, "GDATA * " #name "[%d]: %s", ii, gdata_string(gdata. name [ii])); } } #define gdata_print_number_array_item(format,name,item) \ { if (gdata. name [ii] . item) { ioutput(gdata_common, "GDATA * " #name "[%d]: " #item "=" format, ii, gdata. name [ii] . item); } } #define gdata_print_number_array_item_cast(format,name,item,type) \ { if (gdata. name [ii] . item) { ioutput(gdata_common, "GDATA * " #name "[%d]: " #item "=" format, ii, (type) gdata. name [ii] . item); } } #define gdata_print_string_array_item(name,item) \ { if (gdata. name [ii] . item) { ioutput(gdata_common, "GDATA * " #name "[%d]: " #item "=%s", ii, gdata_string(gdata. name [ii] . item)); } } #define gdata_print_number_array_itemptr(format,name,item) \ { if (gdata. name [ii] -> item) { ioutput(gdata_common, "GDATA * " #name "[%d]: " #item "=" format, ii, gdata. name [ii] -> item); } } #define gdata_print_string_array_itemptr(name,item) \ { if (gdata. name [ii] -> item) { ioutput(gdata_common, "GDATA * " #name "[%d]: " #item "=%s", ii, gdata_string(gdata. name [ii] -> item)); } } #define gdata_print_int_array(name) gdata_print_number_array("%d", name) #define gdata_print_uint_array(name) gdata_print_number_array("%u", name) #define gdata_print_long_array(name) gdata_print_number_array("%ld", name) #define gdata_print_ulong_array(name) gdata_print_number_array("%lu", name) #define gdata_print_float_array(name) gdata_print_number_array("%.5f", name) #define gdata_irlist_iter_start(name, type) \ { type *iter; ioutput(gdata_common, "GDATA * " #name ":"); for(iter=irlist_get_head(&gdata. name); iter; iter=irlist_get_next(iter)) { #define gdata_irlist_iter_end } } #define gdata_iter_as_print_number(format) \ ioutput(gdata_common, " : " format, iter); #define gdata_iter_as_print_number_cast(format,type) \ ioutput(gdata_common, " : " format, (type) iter); #define gdata_iter_as_print_string \ ioutput(gdata_common, " : %s", gdata_string(iter)); #define gdata_iter_as_print_int(name) gdata_iter_as_print_number("%d", name) #define gdata_iter_as_print_uint(name) gdata_iter_as_print_number("%u", name) #define gdata_iter_as_print_long(name) gdata_iter_as_print_number("%ld", name) #define gdata_iter_as_print_ulong(name) gdata_iter_as_print_number("%lu", name) #define gdata_iter_as_print_float(name) gdata_iter_as_print_number("%.5f", name) #define gdata_iter_print_number(format,name) \ ioutput(gdata_common, " " #name ": " format, iter-> name); #define gdata_iter_print_number_cast(format,name,type) \ ioutput(gdata_common, " " #name ": " format, (type) iter-> name); #define gdata_iter_print_string(name) \ ioutput(gdata_common, " " #name ": %s", gdata_string(iter-> name)); #define gdata_iter_print_int(name) gdata_iter_print_number("%d", name) #define gdata_iter_print_uint(name) gdata_iter_print_number("%u", name) #define gdata_iter_print_long(name) gdata_iter_print_number("%ld", name) #define gdata_iter_print_ulong(name) gdata_iter_print_number("%lu", name) #define gdata_iter_print_float(name) gdata_iter_print_number("%.5f", name) void dumpgdata(void) { int ii; ioutput(gdata_common,"GDATA DUMP BEGIN"); gdata_print_int(transfermethod); ioutput(gdata_common,"GDATA * connectionmethod: how=%d host=%s port=%d passwd=%s vhost=%s", (int)gdata.connectionmethod.how, gdata_string(gdata.connectionmethod.host), (int)gdata.connectionmethod.port, gdata_string(gdata.connectionmethod.password), gdata_string(gdata.connectionmethod.vhost)); for (ii=0; iiname, gdata_string(iter->key)); ioutput(gdata_common," : flags=%d plsittime=%d plistoffset=%d", iter->flags, iter->plisttime, iter->plistoffset); gdata_iter_print_string(headline); gdata_irlist_iter_end; gdata_irlist_iter_start(msglog, msglog_t); ioutput(gdata_common," : when=%ld hostmask=%s message=%s", (long)iter->when, gdata_string(iter->hostmask), gdata_string(iter->message)); gdata_irlist_iter_end; gdata_irlist_iter_start(dccchats, dccchat_t); ioutput(gdata_common, " : status=%d fd=%d", iter->status, iter->fd); ioutput(gdata_common, " : lastcontact=%ld connecttime=%ld", (long)iter->lastcontact, (long)iter->connecttime); ioutput(gdata_common, " : localport=%d remoteport=%d localip=0x%.8lX remoteip=0x%.8lX", iter->localport, iter->remoteport, iter->localip, iter->remoteip); gdata_iter_print_string(nick); gdata_irlist_iter_end; gdata_print_int(num_dccchats); gdata_print_number_cast("%d",curtime,int); /* readset writeset */ gdata_print_float(record); gdata_print_float(sentrecord); gdata_print_number("%" LLPRINTFMT "u", totalsent); gdata_print_long(totaluptime); gdata_print_int(debug); gdata_print_int(exiting); gdata_print_int(crashing); for (ii=0; iihostmask, iter->flags, iter->bucket, (long)iter->lastcontact); gdata_irlist_iter_end; gdata_irlist_iter_start(xdccs, xdcc); gdata_iter_print_string(file); gdata_iter_print_string(desc); gdata_iter_print_string(note); ioutput(gdata_common, " : ptr=0x%.8lX gets=%d minspeed=%.1f maxspeed=%.1f st_size=%" LLPRINTFMT "d", (unsigned long)iter, iter->gets, iter->minspeed, iter->maxspeed, (long long)iter->st_size); /* st_dev st_ino */ ioutput(gdata_common, " : fd=%d fd_count=%d fd_loc=%" LLPRINTFMT "d", iter->file_fd, iter->file_fd_count, (long long)iter->file_fd_location); ioutput(gdata_common, " : has_md5=%d md5sum=" MD5_PRINT_FMT, iter->has_md5sum, MD5_PRINT_DATA(iter->md5sum)); gdata_iter_print_string(group); gdata_iter_print_string(group_desc); gdata_iter_print_string(lock); ioutput(gdata_common, " : dlimit max=%d used=%d", iter->dlimit_max, iter->dlimit_used); gdata_iter_print_string(dlimit_desc); #ifdef HAVE_MMAP { mmap_info_t *iter2; ioutput(gdata_common, " : mmaps:"); for(iter2 = irlist_get_head(&iter->mmaps); iter2; iter2 = irlist_get_next(iter2)) { ioutput(gdata_common, " : ptr=%p ref_count=%d mmap_ptr=%p mmap_offset=0x%.8" LLPRINTFMT "X mmap_size=0x%.8" LLPRINTFMT "X", iter2, iter2->ref_count, iter2->mmap_ptr, (unsigned long long)iter2->mmap_offset, (unsigned long long)iter2->mmap_size); } } #endif gdata_irlist_iter_end; gdata_irlist_iter_start(mainqueue, pqueue); gdata_iter_print_string(nick); gdata_iter_print_string(hostname); ioutput(gdata_common, " : xpack=0x%.8lX queuedtime=%ld", (unsigned long)iter->xpack, (long)iter->queuedtime); ioutput(gdata_common," : restrictsend_bad=%ld" , (long)iter->restrictsend_bad ); gdata_irlist_iter_end; gdata_irlist_iter_start(trans, transfer); ioutput(gdata_common, " : listen=%d client=%d id=%d", iter->listensocket, iter->clientsocket, iter->id); ioutput(gdata_common, " : sent=%" LLPRINTFMT "d got=%" LLPRINTFMT "d lastack=%" LLPRINTFMT "d curack=%" LLPRINTFMT "d resume=%" LLPRINTFMT "d speedamt=%" LLPRINTFMT "d tx_bucket=%li", (long long)iter->bytessent, (long long)iter->bytesgot, (long long)iter->lastack, (long long)iter->curack, (long long)iter->startresume, (long long)iter->lastspeedamt, (long)iter->tx_bucket); ioutput(gdata_common, " : lastcontact=%ld connecttime=%ld lastspeed=%.1f pack=0x%.8lX", (long)iter->lastcontact, (long)iter->connecttime, iter->lastspeed, (unsigned long)iter->xpack); ioutput(gdata_common, " : listenport=%d remoteport=%d localip=0x%.8lX remoteip=0x%.8lX", iter->listenport, iter->remoteport, iter->localip, iter->remoteip); ioutput(gdata_common, " : restrictsend_bad=%ld" , (long)iter->restrictsend_bad ); #ifdef HAVE_MMAP ioutput(gdata_common, " : mmap_info=%p", iter->mmap_info); #endif /* severaddress */ gdata_iter_print_string(nick); gdata_iter_print_string(caps_nick); gdata_iter_print_string(hostname); ioutput(gdata_common, " : nomin=%d nomax=%d reminded=%d overlimit=%d tr_status=%d", iter->nomin, iter->nomax, iter->reminded, iter->overlimit, iter->tr_status); gdata_irlist_iter_end; gdata_irlist_iter_start(uploads, upload); ioutput(gdata_common, " : client=%d file=%d ul_status=%d", iter->clientsocket, iter->filedescriptor, iter->ul_status); ioutput(gdata_common, " : got=%" LLPRINTFMT "d totalsize=%" LLPRINTFMT "d resume=%" LLPRINTFMT "d speedamt=%" LLPRINTFMT "d", (long long)iter->bytesgot, (long long)iter->totalsize, (long long)iter->resumesize, (long long)iter->lastspeedamt); ioutput(gdata_common, " : lastcontact=%ld connecttime=%ld lastspeed=%.1f", (long)iter->lastcontact, (long)iter->connecttime, iter->lastspeed); ioutput(gdata_common, " : localport=%d remoteport=%d localip=0x%.8lX remoteip=0x%.8lX", iter->localport, iter->remoteport, iter->localip, iter->remoteip); gdata_iter_print_string(nick); gdata_iter_print_string(hostname); gdata_iter_print_string(file); gdata_irlist_iter_end; gdata_irlist_iter_start(listen_ports, ir_listen_port_item_t); gdata_iter_print_number_cast("%hu",port,unsigned short int); gdata_iter_print_number_cast("%u",listen_time,unsigned int); gdata_irlist_iter_end; gdata_print_number("%p", md5build.xpack); gdata_print_int(md5build.file_fd); /* meminfo */ #if !defined(NO_CHROOT) gdata_print_string(chrootdir); #endif #if !defined(NO_SETUID) gdata_print_string(runasuser); #endif ioutput(gdata_common,"GDATA DUMP END"); } void clearmemberlist(channel_t *c) { /* clear members list */ if (gdata.debug > 2) { ioutput(CALLTYPE_NORMAL,OUT_S,COLOR_NO_COLOR, "clearing %s",c->name); } irlist_delete_all(&c->members); return; } int isinmemberlist(const char *nick) { member_t *member; channel_t *ch; updatecontext(); if (gdata.debug > 2) { ioutput(CALLTYPE_NORMAL,OUT_S,COLOR_NO_COLOR, "checking for %s",nick); } ch = irlist_get_head(&gdata.channels); while(ch) { member = irlist_get_head(&ch->members); while(member) { if (!strcasecmp(caps(member->nick),nick)) { return 1; } member = irlist_get_next(member); } ch = irlist_get_next(ch); } return 0; } void addtomemberlist(channel_t *c, const char *nick) { member_t *member; char prefixes[MAX_PREFIX] = {}; updatecontext(); if (gdata.debug > 2) { ioutput(CALLTYPE_NORMAL,OUT_S,COLOR_NO_COLOR, "adding %s to %s",nick,c->name); } /* find any prefixes */ more: if (*nick) { int pi; for (pi = 0; (pi < MAX_PREFIX && gdata.prefixes[pi].p_symbol); pi++) { if (*nick == gdata.prefixes[pi].p_symbol) { for (pi = 0; (pi < MAX_PREFIX && prefixes[pi] && prefixes[pi] != *nick); pi++) ; if (pi < MAX_PREFIX) { prefixes[pi] = *nick; } nick++; goto more; } } } /* is in list for this channel already? */ member = irlist_get_head(&c->members); while(member) { if (!strcasecmp(member->nick,nick)) { break; } member = irlist_get_next(member); } if (!member) { /* add it */ member = irlist_add(&c->members, sizeof(member_t) + strlen(nick)); strcpy(member->nick, nick); memcpy(member->prefixes, prefixes, sizeof(prefixes)); } return; } void removefrommemberlist(channel_t *c, const char *nick) { member_t *member; updatecontext(); if (gdata.debug > 2) { ioutput(CALLTYPE_NORMAL,OUT_S,COLOR_NO_COLOR, "removing %s from %s",nick,c->name); } /* is in list for this channel? */ member = irlist_get_head(&c->members); while(member) { if (!strcasecmp(member->nick,nick)) { irlist_delete(&c->members, member); return; } member = irlist_get_next(member); } /* not found */ return; } void changeinmemberlist_mode(channel_t *c, const char *nick, char mode, int add) { member_t *member; int pi; updatecontext(); if (gdata.debug > 2) { ioutput(CALLTYPE_NORMAL, OUT_S, COLOR_NO_COLOR, "%s prefix %c on %s in %s", add ? "adding" : "removing", mode, nick, c->name); } /* is in list for this channel? */ member = irlist_get_head(&c->members); while(member) { if (!strcasecmp(member->nick,nick)) { break; } member = irlist_get_next(member); } if (member) { if (add) { for (pi = 0; (pi < MAX_PREFIX && member->prefixes[pi] && member->prefixes[pi] != mode); pi++) ; if (pi < MAX_PREFIX) { member->prefixes[pi] = mode; } } else { for (pi = 0; (pi < MAX_PREFIX && member->prefixes[pi]); pi++) { if (member->prefixes[pi] == mode) { for (pi++; pi < MAX_PREFIX; pi++) { member->prefixes[pi-1] = member->prefixes[pi]; } member->prefixes[MAX_PREFIX-1] = '\0'; break; } } } } return; } void changeinmemberlist_nick(channel_t *c, const char *oldnick, const char *newnick) { member_t *oldmember; member_t *newmember; updatecontext(); if (gdata.debug > 2) { ioutput(CALLTYPE_NORMAL,OUT_S,COLOR_NO_COLOR, "changing %s to %s in %s",oldnick,newnick,c->name); } /* find old in list for this channel */ oldmember = irlist_get_head(&c->members); while(oldmember) { if (!strcasecmp(oldmember->nick,oldnick)) { break; } oldmember = irlist_get_next(oldmember); } /* add it */ newmember = irlist_add(&c->members, sizeof(member_t) + strlen(newnick)); strcpy(newmember->nick, newnick); if (oldmember) { memcpy(newmember->prefixes, oldmember->prefixes, sizeof(oldmember->prefixes)); irlist_delete(&c->members, oldmember); } else { /* this shouldn't happen, set no prefixes */ memset(newmember->prefixes, 0, sizeof(newmember->prefixes)); } return; } int set_socket_nonblocking (int s, int nonblock) { long current; current = fcntl(s, F_GETFL, 0); if (current == -1) { return -1; } if (nonblock) return fcntl(s, F_SETFL, current | O_NONBLOCK); else return fcntl(s, F_SETFL, current & ~O_NONBLOCK); } void set_loginname(void) { struct passwd *p; p = getpwuid(geteuid()); if (p == NULL || p->pw_name == NULL) { #if !defined(NO_SETUID) if (gdata.runasuser) { gdata.loginname = mycalloc(strlen(gdata.runasuser)+1); strcpy(gdata.loginname,gdata.runasuser); } else #endif { outerror(OUTERROR_TYPE_WARN_LOUD,"Couldn't Get username, specify loginname in config file"); gdata.loginname = mycalloc(strlen("UNKNOWN"+1)); strcpy(gdata.loginname,"UNKNOWN"); } } else { gdata.loginname = mycalloc(strlen(p->pw_name)+1); strcpy(gdata.loginname,p->pw_name); } } int is_fd_readable(int fd) { int ret; fd_set readfds; struct timeval timeout; FD_ZERO(&readfds); FD_SET(fd, &readfds); timeout.tv_sec = 0; timeout.tv_usec = 0; ret = select(fd+1, &readfds, NULL, NULL, &timeout); if (ret < 0) { return 0; } if (FD_ISSET(fd, &readfds)) { return 1; } return 0; } int is_fd_writeable(int fd) { int ret; fd_set writefds; struct timeval timeout; FD_ZERO(&writefds); FD_SET(fd, &writefds); timeout.tv_sec = 0; timeout.tv_usec = 0; ret = select(fd+1, NULL, &writefds, NULL, &timeout); if (ret < 0) { return 0; } if (FD_ISSET(fd, &writefds)) { return 1; } return 0; } #ifdef NO_SNPRINTF int snprintf(char *str, size_t n, const char *format, ... ) { va_list args; int actlen; char mysnprintf_buff[1024*10]; va_start(args, format); actlen = vsprintf(mysnprintf_buff,format,args); va_end(args); strncpy(str,mysnprintf_buff,min2(n-1,actlen)); str[min2(n-1,actlen)] = '\0'; return min2(n-1,actlen); } int vsnprintf(char *str, size_t n, const char *format, va_list ap ) { int actlen; char mysnprintf_buff[1024*10]; actlen = vsprintf(mysnprintf_buff,format,ap); strncpy(str,mysnprintf_buff,min2(n-1,actlen)); str[min2(n-1,actlen)] = '\0'; return min2(n-1,actlen); } #endif #ifdef NO_STRCASECMP #include int strcasecmp(const char *s1, const char *s2) { while (*s1 && (tolower(*s1) == tolower(*s2))) { s1++; s2++; } return tolower(*s1) - tolower(*s2); } #endif #ifdef NO_STRSIGNAL const char *strsignal(int sig) { switch (sig) { case SIGBUS: return "sigbus"; case SIGABRT: return "sigabrt"; case SIGILL: return "sigill"; case SIGFPE: return "sigfpe"; case SIGSEGV: return "sigsegv"; case SIGTERM: return "sigterm"; case SIGINT: return "sigint"; case SIGUSR1: return "sigusr1"; case SIGUSR2: return "sigusr2"; default: return "unknown"; } } #endif char* convert_to_unix_slash(char *ss) { int ii; for (ii=0; ; ii++) { if (ss[ii] == '\\') { ss[ii] = '/'; } else if (ss[ii] == '\0') { return ss; } } } #define IRLIST_INT_TO_EXT(p) ((irlist_item_t *)p + 1) #define IRLIST_INT_TO_EXT_CONST(p) ((const irlist_item_t *)p + 1) #define IRLIST_EXT_TO_INT(p) ((irlist_item_t *)p - 1) #define IRLIST_EXT_TO_INT_CONST(p) ((const irlist_item_t *)p - 1) void* irlist_add2(irlist_t *list, unsigned int size, const char *src_function, const char *src_file, int src_line) { irlist_item_t *iitem; updatecontext(); iitem = mymalloc2(sizeof(irlist_item_t) + size, 1, src_function, src_file, src_line); irlist_insert_tail(list, IRLIST_INT_TO_EXT(iitem)); return IRLIST_INT_TO_EXT(iitem); } void irlist_insert_head(irlist_t *list, void *item) { irlist_item_t *iitem = IRLIST_EXT_TO_INT(item); updatecontext(); assert(!iitem->next); assert(!iitem->prev); if (!list->size) { assert(!list->head); assert(!list->tail); list->tail = iitem; } else { assert(list->head); assert(list->tail); assert(!list->head->prev); assert(!list->tail->next); list->head->prev = iitem; } iitem->next = list->head; iitem->prev = NULL; list->head = iitem; list->size++; return; } void irlist_insert_tail(irlist_t *list, void *item) { irlist_item_t *iitem = IRLIST_EXT_TO_INT(item); updatecontext(); assert(!iitem->next); assert(!iitem->prev); if (!list->size) { assert(!list->head); assert(!list->tail); list->head = iitem; } else { assert(list->head); assert(list->tail); assert(!list->head->prev); assert(!list->tail->next); list->tail->next = iitem; } iitem->next = NULL; iitem->prev = list->tail; list->tail = iitem; list->size++; return; } void irlist_insert_before(irlist_t *list, void *item, void *before_this) { irlist_item_t *iitem = IRLIST_EXT_TO_INT(item); irlist_item_t *ibefore = IRLIST_EXT_TO_INT(before_this); updatecontext(); assert(list->size > 0); assert(!iitem->next); assert(!iitem->prev); if (ibefore->prev) { iitem->prev = ibefore->prev; iitem->prev->next = iitem; } else { assert(list->head == ibefore); list->head = iitem; } ibefore->prev = iitem; iitem->next = ibefore; list->size++; return; } void irlist_insert_after(irlist_t *list, void *item, void *after_this) { irlist_item_t *iitem = IRLIST_EXT_TO_INT(item); irlist_item_t *iafter = IRLIST_EXT_TO_INT(after_this); updatecontext(); assert(list->size > 0); assert(!iitem->next); assert(!iitem->prev); if (iafter->next) { iitem->next = iafter->next; iitem->next->prev = iitem; } else { assert(list->tail == iafter); list->tail = iitem; } iafter->next = iitem; iitem->prev = iafter; list->size++; return; } void* irlist_delete(irlist_t *list, void *item) { irlist_item_t *iitem = IRLIST_EXT_TO_INT(item); void *retval; updatecontext(); retval = irlist_remove(list, item); mydelete(iitem); return retval; } void* irlist_remove(irlist_t *list, void *item) { irlist_item_t *iitem = IRLIST_EXT_TO_INT(item); irlist_item_t *next; updatecontext(); assert(list->size > 0); assert(list->head); assert(list->tail); next = iitem->next; if (list->head == iitem) { assert(!iitem->prev); list->head = iitem->next; } if (list->tail == iitem) { assert(!iitem->next); list->tail = iitem->prev; } if (iitem->next) { assert(iitem->next->prev == iitem); iitem->next->prev = iitem->prev; } if (iitem->prev) { assert(iitem->prev->next == iitem); iitem->prev->next = iitem->next; } iitem->next = NULL; iitem->prev = NULL; list->size--; assert(list->size >= 0); if (next) { return IRLIST_INT_TO_EXT(next); } else { return NULL; } } void irlist_delete_all(irlist_t *list) { void *cur; updatecontext(); for (cur = irlist_get_head(list); cur; cur = irlist_delete(list, cur)); assert(list->size == 0); assert(!list->head); assert(!list->tail); return; } void* irlist_get_head(const irlist_t *list) { updatecontext(); if (list->head) { assert(list->size > 0); assert(list->tail); assert(!list->head->prev); return IRLIST_INT_TO_EXT(list->head); } else { assert(list->size == 0); assert(!list->tail); return NULL; } } void* irlist_get_tail(const irlist_t *list) { updatecontext(); if (list->tail) { assert(list->size > 0); assert(list->head); assert(!list->tail->next); return IRLIST_INT_TO_EXT(list->tail); } else { assert(list->size == 0); assert(!list->head); return NULL; } } void* irlist_get_next(const void *cur) { const irlist_item_t *iitem = IRLIST_EXT_TO_INT_CONST(cur); if (iitem->next) { assert(iitem->next->prev == iitem); return IRLIST_INT_TO_EXT(iitem->next); } else { return NULL; } } void* irlist_get_prev(const void *cur) { const irlist_item_t *iitem = IRLIST_EXT_TO_INT_CONST(cur); updatecontext(); if (iitem->prev) { assert(iitem->prev->next == iitem); return IRLIST_INT_TO_EXT(iitem->prev); } else { return NULL; } } int irlist_size(const irlist_t *list) { updatecontext(); assert(list->size >= 0); return list->size; } void* irlist_get_nth(irlist_t *list, int nth) { irlist_item_t *iitem; updatecontext(); assert(nth >= 0); for (iitem = list->head; (iitem && nth--); iitem = iitem->next) ; if (iitem) { return IRLIST_INT_TO_EXT(iitem); } else { return NULL; } } int irlist_sort_cmpfunc_string(void *userdata, const void *a, const void *b) { return strcmp((const char *)a, (const char *)b); } int irlist_sort_cmpfunc_int(void *userdata, const void *a, const void *b) { int ai, bi; ai = *(const int*)a; bi = *(const int*)b; return ai - bi; } int irlist_sort_cmpfunc_off_t(void *userdata, const void *a, const void *b) { off_t ai, bi; ai = *(const off_t*)a; bi = *(const off_t*)b; return ai - bi; } void irlist_sort(irlist_t *list, int (*cmpfunc)(void *userdata, const void *a, const void *b), void *userdata) { irlist_t newlist = {}; void *cur, *try; while ((cur = irlist_get_head(list))) { irlist_remove(list, cur); try = irlist_get_head(&newlist); if (!try) { irlist_insert_head(&newlist, cur); continue; } while (try) { if (cmpfunc(userdata, cur, try) < 0) { irlist_insert_before(&newlist, cur, try); break; } try = irlist_get_next(try); } if (!try) { irlist_insert_tail(&newlist, cur); } } *list = newlist; return; } transfer* does_tr_id_exist(int tr_id) { transfer *tr; tr = irlist_get_head(&gdata.trans); while(tr) { if (tr->id == tr_id) { return tr; } tr = irlist_get_next(tr); } return NULL; } int get_next_tr_id(void) { transfer *tr; while(1) { gdata.next_tr_id++; gdata.next_tr_id %= max2((MAXTRANS * 3) / 2, 1000); gdata.next_tr_id = max2(1,gdata.next_tr_id); tr = does_tr_id_exist(gdata.next_tr_id); if (!tr) { return gdata.next_tr_id; } } } void ir_listen_port_connected(ir_uint16 port) { ir_listen_port_item_t *lp; lp = irlist_get_head(&gdata.listen_ports); while(lp) { if (lp->port == port) { if (gdata.debug > 0) { ioutput(CALLTYPE_NORMAL,OUT_S,COLOR_YELLOW, "listen complete port %d", port); } lp = irlist_delete(&gdata.listen_ports, lp); } else { lp = irlist_get_next(lp); } } return; } static int ir_listen_port_is_in_list(ir_uint16 port) { int retval = 0; ir_listen_port_item_t *lp; lp = irlist_get_head(&gdata.listen_ports); while(lp) { if ((lp->listen_time + LISTEN_PORT_REUSE_TIME) < gdata.curtime) { if (gdata.debug > 0) { ioutput(CALLTYPE_NORMAL,OUT_S,COLOR_YELLOW, "listen expire port %d", lp->port); } lp = irlist_delete(&gdata.listen_ports, lp); } else { if (lp->port == port) { retval = 1; } lp = irlist_get_next(lp); } } return retval; } int ir_bind_listen_socket(int fd, struct sockaddr_in *sa) { ir_listen_port_item_t *lp; int retry; int max; ir_uint16 port; SIGNEDSOCK int addrlen; max = (MAXTRANS+MAXUPLDS+MAXCHATS+irlist_size(&gdata.listen_ports)); for (retry = 0; retry < max; retry++) { if (gdata.tcprangestart) { port = gdata.tcprangestart + retry; if (ir_listen_port_is_in_list(port)) { continue; } sa->sin_port = htons(port); } else { sa->sin_port = htons(0); } if (bind(fd, (struct sockaddr *)sa, sizeof(struct sockaddr_in)) < 0) { if (!gdata.tcprangestart) { /* give up */ retry = max; break; } } else { break; } } if (retry == max) { return -1; } addrlen = sizeof (struct sockaddr_in); if ((getsockname (fd, (struct sockaddr *)sa, &addrlen)) < 0) { outerror(OUTERROR_TYPE_WARN_LOUD,"Couldn't get Port Number, Aborting"); return -1; } if (gdata.debug > 0) { ioutput(CALLTYPE_NORMAL,OUT_S,COLOR_YELLOW, "listen got port %d", ntohs(sa->sin_port)); } lp = irlist_add(&gdata.listen_ports,sizeof(ir_listen_port_item_t)); lp->port = ntohs(sa->sin_port); lp->listen_time = gdata.curtime; return 0; } int ir_boutput_write(ir_boutput_t *bout, const void *buffer, int buffer_len) { ir_boutput_segment_t *segment; int cur; int len; const unsigned char *buffer_c = (const unsigned char*)buffer; cur = 0; begin_again: segment = irlist_get_tail(&bout->segments); if (!segment) { /* first */ segment = irlist_add(&bout->segments, sizeof(ir_boutput_segment_t)); } while (cur < buffer_len) { assert(segment->begin <= segment->end); assert(segment->begin <= IR_BOUTPUT_SEGMENT_SIZE); assert(segment->end <= IR_BOUTPUT_SEGMENT_SIZE); if (segment->end == IR_BOUTPUT_SEGMENT_SIZE) { /* segment is full */ if ((bout->flags & BOUTPUT_NO_LIMIT) || (irlist_size(&bout->segments) < IR_BOUTPUT_MAX_SEGMENTS)) { segment = irlist_add(&bout->segments, sizeof(ir_boutput_segment_t)); } else { /* too much data in buffer, attempt flush */ if (!(bout->flags & BOUTPUT_NO_FLUSH) && (ir_boutput_attempt_flush(bout) > 0)) { /* flush wrote something so start over fresh */ goto begin_again; } /* unable to flush, drop characters */ bout->count_dropped += buffer_len - cur; return cur; } } len = min2(IR_BOUTPUT_SEGMENT_SIZE - segment->end, buffer_len - cur); if (bout->md5sum) { MD5Update(bout->md5sum, buffer_c+cur, len); } memcpy(segment->buffer+segment->end, buffer_c+cur, len); cur += len; segment->end += len; bout->count_written += len; } return buffer_len; } int ir_boutput_need_flush(ir_boutput_t *bout) { return irlist_size(&bout->segments); } int ir_boutput_attempt_flush(ir_boutput_t *bout) { ir_boutput_segment_t *segment; int count = 0; if (bout->flags & BOUTPUT_NO_FLUSH) { return 0; } while ((segment = irlist_get_head(&bout->segments))) { int retval; assert(segment->begin <= segment->end); assert(segment->begin <= IR_BOUTPUT_SEGMENT_SIZE); assert(segment->end <= IR_BOUTPUT_SEGMENT_SIZE); retval = write(bout->fd, segment->buffer + segment->begin, segment->end - segment->begin); if ((retval < 0) && (errno != EAGAIN)) { /* write failure */ count = -1; break; } else if (retval < 0) { /* EAGAIN, that's all for now */ break; } else { segment->begin += retval; count += retval; bout->count_flushed += retval; } assert(segment->begin <= segment->end); if (segment->begin == segment->end) { irlist_delete(&bout->segments, segment); } } return count; } void ir_boutput_init(ir_boutput_t *bout, int fd, int flags) { memset(bout, 0, sizeof(*bout)); bout->fd = fd; bout->flags = flags; if (bout->flags & BOUTPUT_MD5SUM) { bout->md5sum = mycalloc(sizeof(struct MD5Context)); MD5Init(bout->md5sum); } return; } void ir_boutput_set_flags(ir_boutput_t *bout, int flags) { bout->flags = flags; if ((bout->flags & BOUTPUT_MD5SUM) && (!bout->md5sum)) { bout->md5sum = mycalloc(sizeof(struct MD5Context)); MD5Init(bout->md5sum); } else if (!(bout->flags & BOUTPUT_MD5SUM) && bout->md5sum) { mydelete(bout->md5sum); } return; } const char *transferlimit_type_to_string(transferlimit_type_e type) { switch (type) { case TRANSFERLIMIT_DAILY: return "daily"; case TRANSFERLIMIT_WEEKLY: return "weekly"; case TRANSFERLIMIT_MONTHLY: return "monthly"; default: return "unknown"; } } void ir_boutput_delete(ir_boutput_t *bout) { irlist_delete_all(&bout->segments); mydelete(bout->md5sum); memset(bout, 0, sizeof(*bout)); return; } void ir_boutput_get_md5sum(ir_boutput_t *bout, MD5Digest digest) { if (bout->md5sum) { MD5Final(digest, bout->md5sum); bout->flags &= ~BOUTPUT_MD5SUM; mydelete(bout->md5sum); } return; } /* iroffer-lamm: add-ons */ /* -------------- RACING START ---------------- */ /* Manipulated Places: admin.c - added u_race and u_unrace admin.c - u_add: xd->race = 0; statefile.c - read_statefile: xd->race = 0; admin.c - u_remove: if (xd->race) u_unrace(u); headers.c - struct xdcc: int race; long racetimer; float lastff; int first; int second; int finishes; headers.c - function declerations: void r_show(int num); void r_finish(transfer * const t); iroffer.c - four second loop: i = 1; xd = irlist_get_head(&gdata.xdccs); while(xd) { if (xd->race) r_show(i); i++; xd = irlist_get_next(xd); } iroffer_transfer.c - in t_flushed: if (tr->xpack->race && !tr->startresume) r_finish(tr); */ void r_show (int num) { xdcc *xd; transfer *tr; transfer *trfirst; transfer *trsecond; int first,second,lastfirst,lastsecond; channel_t *ch; float f, ff = -1.0, fs = -1.0; char *tempstr; char *tempstr2; xd = irlist_get_nth(&gdata.xdccs, num-1); lastfirst = xd->first; lastsecond = xd->second; trfirst = NULL; trsecond = NULL; tr = irlist_get_head(&gdata.trans); while(tr) { if (!tr->startresume && xd->file == tr->xpack->file && tr->tr_status == TRANSFER_STATUS_SENDING) { f = ((float)tr->bytessent)*100.0/((float)tr->xpack->st_size); if (f > ff) { trsecond = trfirst; fs = ff; trfirst = tr; ff = f; } else if (f > fs) { trsecond = tr; fs = f; } } tr = irlist_get_next(tr); } if (trfirst!=NULL) first=trfirst->id; else first=-1; if (trsecond!=NULL) second=trsecond->id; else second=-1; if (lastfirst!=first || (xd->lastff < -1.0) || ((xd->lastff < 25.0) && (25.0 < ff)) || ((xd->lastff < 50.0) && (50.0 < ff)) || ((xd->lastff < 75.0) && (75.0 < ff)) ) { xd->lastff = ff; xd->first=first; xd->second=second; tempstr = mycalloc(maxtextlength); tempstr2 = mycalloc(maxtextlength); if (first != -1) { snprintf(tempstr2,maxtextlength-2,"[\2RACE\2] %s is %s for Pack #%i - %s - with %.1f%%%%", trfirst->nick,lastfirst!=first?"new leader":"leading",num,xd->desc,ff); if (trfirst->lastspeed) snprintf(tempstr,maxtextlength-2,"%s at %.1fK/s",tempstr2,trfirst->lastspeed); else strncpy(tempstr,tempstr2,maxtextlength-1); if (second != -1) { snprintf(tempstr2,maxtextlength-2,"%s %s followed by %s with %.1f%%%%",tempstr, lastsecond!=second?"now":"still",trsecond->nick,fs); if (trsecond->lastspeed) snprintf(tempstr,maxtextlength-2,"%s at %.1fK/s",tempstr2,trsecond->lastspeed); else strncpy (tempstr, tempstr2, maxtextlength - 1); } else strncat(tempstr," followed by noone.",maxtextlength-strlen(tempstr)-1); } else snprintf(tempstr,maxtextlength-2,"[\2RACE\2] Noone Racing for Pack #%i - %s [%.1fKB]", num,xd->desc,((float)xd->st_size)/1024.0); ch = irlist_get_head(&gdata.channels); while(ch) { if (ch->flags & CHAN_ONCHAN) privmsg(ch->name, tempstr); ch = irlist_get_next(ch); } ioutput(CALLTYPE_NORMAL,OUT_S,COLOR_YELLOW,"[RACE] Status-Output for Pack #%i",num); mydelete(tempstr2); mydelete(tempstr); } } void r_finish (transfer * const t) { channel_t *ch; long timetook; char *tempstr = mycalloc (maxtextlength); char *tempstr2 = mycalloc (maxtextlength); timetook = gdata.curtime - t->connecttime - 1; if (timetook < 1) timetook = 1; t->xpack->race--; t->xpack->finishes++; #define r_f t->xpack->finishes switch (r_f) { case 1: snprintf(tempstr2,maxtextlength-2,"[\2RACE Winner\2] %s won the race on %s!",t->nick,t->xpack->desc); break; case 2: snprintf(tempstr2,maxtextlength-2,"[\2RACE Second\2] %s made the second place on %s!",t->nick,t->xpack->desc); break; case 3: snprintf(tempstr2,maxtextlength-2,"[\2RACE Third\2] %s came in third for %s!",t->nick,t->xpack->desc); break; default: snprintf(tempstr2,maxtextlength-2,"[\2RACE %i%s Place\2] %s finished %s.", r_f,(r_f%10==1 && r_f%100!=11)?"st":(r_f%10==2 && r_f%100!=12)?"nd":(r_f%10==3 && r_f%100!=13)?"rd":"th", t->nick, t->xpack->desc); break; } snprintf(tempstr,maxtextlength-2,"%s It took %li %s %li %s at %0.1f K/s.",tempstr2, (timetook < 3600) ? timetook / 60 : timetook / 60 / 60, (timetook < 3600) ? "min" : "hr", (timetook < 3600) ? timetook % 60 : (timetook / 60) % 60, (timetook < 3600) ? "sec" : "min", ((float) t->xpack->st_size) / 1024.0 / ((float) timetook)); if (!t->xpack->race) { strncpy(tempstr2,tempstr,maxtextlength - 1); snprintf(tempstr,maxtextlength-2,"%s [\2RACE Finished\2]",tempstr2); ioutput(CALLTYPE_NORMAL,OUT_S,COLOR_YELLOW,"[RACE Finished] %s made place %i on %s.",t->nick,r_f,t->xpack->desc); } else ioutput(CALLTYPE_NORMAL, OUT_S, COLOR_YELLOW,"[RACE] %s made place %i on %s.", t->nick, r_f, t->xpack->desc); ch = irlist_get_head(&gdata.channels); while(ch) { if (ch->flags & CHAN_ONCHAN) privmsg(ch->name, tempstr); ch = irlist_get_next(ch); } mydelete (tempstr2); mydelete (tempstr); } /* iroffer-lamm: @find and long !list */ int noticeresults(const char *nick, const char *match) { int i, j, k, len; char *tempstr = mycalloc(maxtextlength); char *sizestrstr; char *tempr; regex_t *regexp = mycalloc(sizeof(regex_t)); xdcc *xd; len = k = 0; tempr = hostmasktoregex(match); if (!regcomp(regexp, tempr, REG_ICASE | REG_NOSUB)) { i = 1; xd = irlist_get_head(&gdata.xdccs); while (xd) { if (!regexec(regexp, xd->file, 0, NULL, 0) || !regexec(regexp, xd->desc, 0, NULL, 0) || !regexec(regexp, xd->note, 0, NULL, 0)) { if (!k) { if (gdata.slotsmax - irlist_size(&gdata.trans) < 0) j = irlist_size(&gdata.trans); else j = gdata.slotsmax; snprintf(tempstr, maxtextlength - 1, "XDCC SERVER - Slot%s:[%i/%i]", j != 1 ? "s" : "", j - irlist_size(&gdata.trans), j); len = strlen(tempstr); if (gdata.slotsmax <= irlist_size(&gdata.trans)) { snprintf(tempstr + len, maxtextlength - 1 - len, ", Queue:[%i/%i]", irlist_size(&gdata.mainqueue), gdata.queuesize); len = strlen(tempstr); } if (gdata.transferminspeed > 0) { snprintf(tempstr + len, maxtextlength - 1 - len, ", Min:%1.1fKB/s", gdata.transferminspeed); len = strlen(tempstr); } if (gdata.transfermaxspeed > 0) { snprintf(tempstr + len, maxtextlength - 1 - len, ", Max:%1.1fKB/s", gdata.transfermaxspeed); len = strlen(tempstr); } if (gdata.maxb) { snprintf(tempstr + len, maxtextlength - 1 - len, ", Cap:%i.0KB/s", gdata.maxb / 4); len = strlen(tempstr); } snprintf(tempstr + len, maxtextlength - 1 - len, " - /msg %s xdcc send #x -", gdata.user_nick); len = strlen(tempstr); if (gdata.dccserverport) { snprintf(tempstr + len, maxtextlength - 1 - len, " /dccserver +s on %i -", gdata.dccserverport); len = strlen(tempstr); } if (!strcmp(match, "*")) snprintf(tempstr + len, maxtextlength - 1 - len, " Packs:"); else snprintf(tempstr + len, maxtextlength - 1 - len, " Found:"); len = strlen(tempstr); } sizestrstr = sizestr(0, xd->st_size); snprintf(tempstr + len, maxtextlength - 1 - len, " #%i:%s,%s", i, xd->desc, sizestrstr); if (strlen(tempstr) > 400) { snprintf(tempstr + len, maxtextlength - 1 - len, " [...]"); notice_slow(nick, tempstr); snprintf(tempstr, maxtextlength - 2, "[...] #%i:%s,%s", i, xd->desc, sizestrstr); } len = strlen(tempstr); mydelete(sizestrstr); k++; } i++; xd = irlist_get_next(xd); } } if (k) notice_slow(nick, tempstr); mydelete(tempr); mydelete(regexp); mydelete(tempstr); return k; } /* End of File */