/* Parse the NOTES_IGNKEY xtra field. You must free the memory allocated * in here: the buffer 'ignores[0]' and the array 'ignores'. */ int get_note_ignores(struct userrec *u, char ***ignores) { struct xtra_key *xk; char *buf, *p; int ignoresn; /* Hullo? sanity? */ if (!u) return 0; xk = getnotesentry(u); if (!xk) return 0; rmspace(xk->data); buf = user_malloc(strlen(xk->data) + 1); strcpy(buf, xk->data); p = buf; /* Split up the string into small parts */ *ignores = nmalloc(sizeof(char *) + 100); **ignores = p; ignoresn = 1; while ((p = strchr(p, ' ')) != NULL) { *ignores = nrealloc(*ignores, sizeof(char *) * (ignoresn + 1)); (*ignores)[ignoresn] = p + 1; ignoresn++; *p = 0; p++; } return ignoresn; }
/* nalloc() - service allocation request */ void* numa_allocator::nalloc(unsigned ssize) { // get cache-line alignment for request int alignment = (ssize <= cache_size / 2)? cache_size / 2: cache_size; /* if the last allocation was half a cache line and we want a full cache line, we move the free space pointer forward a half cache line so we don't spill over cache lines */ if(last_alloc_half && (alignment == cache_size)) { buf_cur = (char*)buf_cur + (cache_size / 2); last_alloc_half = false; } else if(!last_alloc_half && (alignment == cache_size / 2)) { last_alloc_half = true; } // get alignment size unsigned aligned_size = align(ssize, alignment); // reallocate if not enough space left if((char*)buf_cur + aligned_size > (char*)buf_start + buf_size) { nrealloc(); } // service allocation request buf_old = buf_cur; buf_cur = (char*)buf_cur + aligned_size; return buf_old; }
/* Increase number of filelist entries. */ static void filelist_add(filelist_t *flist, char *filename) { flist->tot++; flist->elements = nrealloc(flist->elements, flist->tot * sizeof(filelist_t)); FILELIST_LE(flist).fn = nmalloc(strlen(filename) + 1); strcpy(FILELIST_LE(flist).fn, filename); FILELIST_LE(flist).output = NULL; }
/* new botnet member */ int addparty(char *bot, char *nick, int chan, char flag, int sock, char *from, int *idx) { int i; Context; for (i = 0; i < parties; i++) { /* just changing the channel of someone already on? */ if (!strcasecmp(party[i].bot, bot) && (party[i].sock == sock)) { int oldchan = party[i].chan; party[i].chan = chan; party[i].timer = now; if (from[0]) { if (flag == ' ') flag = '-'; party[i].flag = flag; if (party[i].from) nfree(party[i].from); party[i].from = nmalloc(strlen(from) + 1); strcpy(party[i].from, from); } *idx = i; return oldchan; } } /* new member */ if (parties == maxparty) { maxparty += 50; party = (party_t *) nrealloc((void *) party, maxparty * sizeof(party_t)); } strncpy(party[parties].nick, nick, HANDLEN); party[parties].nick[HANDLEN] = 0; strncpy(party[parties].bot, bot, HANDLEN); party[parties].bot[HANDLEN] = 0; party[parties].chan = chan; party[parties].sock = sock; party[parties].status = 0; party[parties].away = 0; party[parties].timer = now; /* cope. */ if (from[0]) { if (flag == ' ') flag = '-'; party[parties].flag = flag; party[parties].from = nmalloc(strlen(from) + 1); strcpy(party[parties].from, from); } else { party[parties].flag = ' '; party[parties].from = nmalloc(10); strcpy(party[parties].from, "(unknown)"); } *idx = parties; parties++; return -1; }
static void schan_members_rename(struct llist_header *head, char *oldnick, char *newnick) { struct stats_member *m; m = llist_find(head, (void *)oldnick); if (!m) return; Assert(newnick); m->nick = nrealloc(m->nick, strlen(newnick) + 1); strcpy(m->nick, newnick); }
/* Add data to the end of filelist entry's output string */ static void filelist_addout(filelist_t *flist, char *desc) { if (FILELIST_LE(flist).output) { FILELIST_LE(flist).output = nrealloc(FILELIST_LE(flist).output, strlen(FILELIST_LE(flist).output) + strlen(desc) + 1); strcat(FILELIST_LE(flist).output, desc); } else { FILELIST_LE(flist).output = nmalloc(strlen(desc) + 1); strcpy(FILELIST_LE(flist).output, desc); } }
/* This function is called to enlarge the static sockettable in a thread. * It keeps the mainthread dcc table enlarging with the main thread sockettable * If this fails because the upper limit max_socks is reached, -1 is returned. * If this was called from the main thread, it updates the socklist variable * * increase_socks_max() can be called by Tcl threads */ int increase_socks_max() { struct threaddata *td = threaddata(); int osock = td->MAXSOCKS; if (max_socks < 1) max_socks = 1; if (td->MAXSOCKS == max_socks) { putlog(LOG_MISC, "*", "Maximum socket limit reached. Consider raising max-socks."); return -1; } td->MAXSOCKS += 10; if (td->MAXSOCKS > max_socks) td->MAXSOCKS = max_socks; if (td->socklist) td->socklist = nrealloc(td->socklist, sizeof(sock_list) * td->MAXSOCKS); else td->socklist = nmalloc(sizeof(sock_list) * td->MAXSOCKS); for (; osock < td->MAXSOCKS; osock++) td->socklist[osock].flags = SOCK_UNUSED; if (td->mainthread) { max_dcc = td->MAXSOCKS - 10; if (max_dcc < 1) max_dcc = 1; if (dcc) dcc = nrealloc(dcc, sizeof(struct dcc_t) * max_dcc); else dcc = nmalloc(sizeof(struct dcc_t) * max_dcc); socklist = td->socklist; } return 0; }
static void push_str(struct lexer *lex, char *str) { /* {{{ */ ptrdiff_t offset = lex->str_gc.curr - lex->str_gc.ptr; /* handle overflow */ if (offset >= (signed)lex->str_gc.size){ /* grow the stack to be twice as big as it was */ lex->str_gc.size <<= 1; lex->str_gc.ptr = nrealloc(lex->str_gc.ptr, sizeof(char *) * lex->str_gc.size); lex->str_gc.curr = lex->str_gc.ptr + offset; } *lex->str_gc.curr = str; /* set up the current 'cell' */ lex->str_gc.curr++; /* move on to the next 'cell' */ /* }}} */ }
static char *HEX(va_list ap) { int mem_size = MAX_STR_LEN; char *result = (char *)nmalloc(mem_size + 1); unsigned int data; int threshold; int nibble; int i, j; i = 0; VA_LOOP_BEGIN(ap, current) { data = (unsigned int)current->val.i; /* Simulate %02X specifier */ threshold = 7; j = 1; do { nibble = data >> 28; if (nibble != 0 && threshold == 7) threshold = j; if (j >= threshold) { if (i >= mem_size) { mem_size *= 2; result = (char *)nrealloc(result, mem_size + 1); } result[i++] = hex2ascii(nibble); } data <<= 4; ++j; } while (j <= 8); }
/* Read in a character, interpret it as a shortcut or toggle if * necessary, and return it. * Set ran_func to TRUE if we ran a function associated with a * shortcut key, and set finished to TRUE if we're done after running * or trying to run a function associated with a shortcut key. * refresh_func is the function we will call to refresh the edit window. */ int do_statusbar_input(bool *ran_func, bool *finished, void (*refresh_func)(void)) { int input; /* The character we read in. */ static int *kbinput = NULL; /* The input buffer. */ static size_t kbinput_len = 0; /* The length of the input buffer. */ const sc *s; bool have_shortcut = FALSE; const subnfunc *f; *ran_func = FALSE; *finished = FALSE; /* Read in a character. */ input = get_kbinput(bottomwin); #ifndef NANO_TINY if (input == KEY_WINCH) return KEY_WINCH; #endif #ifndef DISABLE_MOUSE /* If we got a mouse click and it was on a shortcut, read in the * shortcut character. */ if (func_key && input == KEY_MOUSE) { if (do_statusbar_mouse() == 1) input = get_kbinput(bottomwin); else { meta_key = FALSE; func_key = FALSE; input = ERR; } } #endif /* Check for a shortcut in the current list. */ s = get_shortcut(&input); /* If we got a shortcut from the current list, or a "universal" * statusbar prompt shortcut, set have_shortcut to TRUE. */ have_shortcut = (s != NULL); /* If we got a non-high-bit control key, a meta key sequence, or a * function key, and it's not a shortcut or toggle, throw it out. */ if (!have_shortcut) { if (is_ascii_cntrl_char(input) || meta_key || func_key) { beep(); meta_key = FALSE; func_key = FALSE; input = ERR; } } /* If we got a character, and it isn't a shortcut or toggle, * it's a normal text character. Display the warning if we're * in view mode, or add the character to the input buffer if * we're not. */ if (input != ERR && !have_shortcut) { /* If we're using restricted mode, the filename isn't blank, * and we're at the "Write File" prompt, disable text input. */ if (!ISSET(RESTRICTED) || openfile->filename[0] == '\0' || currmenu != MWRITEFILE) { kbinput_len++; kbinput = (int *)nrealloc(kbinput, kbinput_len * sizeof(int)); kbinput[kbinput_len - 1] = input; } } /* If we got a shortcut, or if there aren't any other characters * waiting after the one we read in, we need to display all the * characters in the input buffer if it isn't empty. */ if (have_shortcut || get_key_buffer_len() == 0) { if (kbinput != NULL) { /* Display all the characters in the input buffer at * once, filtering out control characters. */ char *output = charalloc(kbinput_len + 1); size_t i; bool got_enter; /* Whether we got the Enter key. */ for (i = 0; i < kbinput_len; i++) output[i] = (char)kbinput[i]; output[i] = '\0'; do_statusbar_output(output, kbinput_len, &got_enter, FALSE); free(output); /* Empty the input buffer. */ kbinput_len = 0; free(kbinput); kbinput = NULL; } if (have_shortcut) { if (s->scfunc == do_tab || s->scfunc == do_enter_void) ; else if (s->scfunc == total_refresh) total_statusbar_refresh(refresh_func); else if (s->scfunc == do_cut_text_void) { /* If we're using restricted mode, the filename * isn't blank, and we're at the "Write File" * prompt, disable Cut. */ if (!ISSET(RESTRICTED) || openfile->filename[0] == '\0' || currmenu != MWRITEFILE) do_statusbar_cut_text(); } else if (s->scfunc == do_left) do_statusbar_left(); else if (s->scfunc == do_right) do_statusbar_right(); #ifndef NANO_TINY else if (s->scfunc == do_prev_word_void) do_statusbar_prev_word(FALSE); else if (s->scfunc == do_next_word_void) do_statusbar_next_word(FALSE); #endif else if (s->scfunc == do_home) do_statusbar_home(); else if (s->scfunc == do_end) do_statusbar_end(); else if (s->scfunc == do_verbatim_input) { /* If we're using restricted mode, the filename * isn't blank, and we're at the "Write File" * prompt, disable verbatim input. */ if (!ISSET(RESTRICTED) || currmenu != MWRITEFILE || openfile->filename[0] == '\0') { bool got_enter; /* Whether we got the Enter key. */ do_statusbar_verbatim_input(&got_enter); /* If we got the Enter key, remove it from the input * buffer, set input to the key value for Enter, and * set finished to TRUE to indicate that we're done. */ if (got_enter) { get_input(NULL, 1); input = sc_seq_or(do_enter_void, 0); *finished = TRUE; } } } else if (s->scfunc == do_delete) { /* If we're using restricted mode, the filename * isn't blank, and we're at the "Write File" * prompt, disable Delete. */ if (!ISSET(RESTRICTED) || openfile->filename[0] == '\0' || currmenu != MWRITEFILE) do_statusbar_delete(); } else if (s->scfunc == do_backspace) { /* If we're using restricted mode, the filename * isn't blank, and we're at the "Write File" * prompt, disable Backspace. */ if (!ISSET(RESTRICTED) || openfile->filename[0] == '\0' || currmenu != MWRITEFILE) do_statusbar_backspace(); } else { /* Handle any other shortcut in the current menu, setting * ran_func to TRUE if we try to run their associated * functions and setting finished to TRUE to indicate * that we're done after running or trying to run their * associated functions. */ f = sctofunc((sc *) s); if (s->scfunc != NULL) { *ran_func = TRUE; if (f && (!ISSET(VIEW_MODE) || f->viewok) && f->scfunc != do_gotolinecolumn_void) f->scfunc(); } *finished = TRUE; } } } return input; }
/* Convert '.files' db to newest db. Returns 1 if a valid file is * found and could be converted, 0 in all other cases. * * '.files' is a text file which contains file records built up in the * following way: * '<filename> <nick> <tm> <gots>\n' * '- <comment>\n' * '- <comment>\n' * ... */ static int convert_old_files(char *path, char *newfiledb) { FILE *f, *fdb; char *s, *fn, *nick, *tm, *s1; filedb_entry *fdbe = NULL; int in_file = 0, i; struct stat st; s = nmalloc(strlen(path) + 8); sprintf(s, "%s/.files", path); f = fopen(s, "r"); my_free(s); if (f == NULL) return 0; fdb = fopen(newfiledb, "w+b"); if (!fdb) { putlog(LOG_MISC, "(!) Can't create filedb in %s", newfiledb); fclose(f); return 0; } lockfile(fdb); lockfile(f); filedb_initdb(fdb); putlog(LOG_FILES, "*", FILES_CONVERT, path); /* Scan contents of .files and painstakingly create .filedb entries */ while (!feof(f)) { s = nmalloc(121); s1 = s; fgets(s, 120, f); if (s[strlen(s) - 1] == '\n') s[strlen(s) - 1] = 0; if (!feof(f)) { fn = newsplit(&s1); rmspace(fn); if ((fn[0]) && (fn[0] != ';') && (fn[0] != '#')) { /* Not comment */ if (fn[0] == '-') { /* Adjust comment for current file */ if (in_file && fdbe) { rmspace(s); if (fdbe->desc) { fdbe->desc = nrealloc(fdbe->desc, strlen(fdbe->desc) + strlen(s) + 2); strcat(fdbe->desc, "\n"); } else fdbe->desc = nmalloc(strlen(s) + 2); strcat(fdbe->desc, s); } } else { if (fdbe) { /* File pending. Write to DB */ filedb_addfile(fdb, fdbe); free_fdbe(&fdbe); } fdbe = malloc_fdbe(); in_file = 1; nick = newsplit(&s1); rmspace(nick); tm = newsplit(&s1); rmspace(tm); rmspace(s1); i = strlen(fn) - 1; if (fn[i] == '/') fn[i] = 0; malloc_strcpy(fdbe->filename, fn); malloc_strcpy(fdbe->uploader, nick); fdbe->gots = atoi(s1); fdbe->uploaded = atoi(tm); sprintf(s, "%s/%s", path, fn); if (stat(s, &st) == 0) { /* File is okay */ if (S_ISDIR(st.st_mode)) { fdbe->stat |= FILE_DIR; if (nick[0] == '+') { char x[100]; /* Only do global flags, it's an old one */ struct flag_record fr = { FR_GLOBAL, 0, 0, 0, 0, 0 }; break_down_flags(nick + 1, &fr, NULL); build_flags(x, &fr, NULL); /* We only want valid flags */ malloc_strcpy_nocheck(fdbe->flags_req, x); } } fdbe->size = st.st_size; } else in_file = 0; /* skip */ } } } my_free(s); } if (fdbe) { /* File pending. Write to DB */ filedb_addfile(fdb, fdbe); free_fdbe(&fdbe); } fseek(fdb, 0L, SEEK_END); unlockfile(f); unlockfile(fdb); fclose(fdb); fclose(f); return 1; }
static int do_dcc_send(int idx, char *dir, char *fn, char *nick, int resend) { char *s = NULL, *s1 = NULL; int x; if (nick && strlen(nick) > NICKMAX) nick[NICKMAX] = 0; if (dccdir[0] == 0) { dprintf(idx, "DCC file transfers not supported.\n"); putlog(LOG_FILES, "*", "Refused dcc %sget %s from [%s]", resend ? "re" : "", fn, dcc[idx].nick); return 0; } if (strchr(fn, '/') != NULL) { dprintf(idx, "Filename cannot have '/' in it...\n"); putlog(LOG_FILES, "*", "Refused dcc %sget %s from [%s]", resend ? "re" : "", fn, dcc[idx].nick); return 0; } if (dir[0]) { s = nmalloc(strlen(dccdir) + strlen(dir) + strlen(fn) + 2); sprintf(s, "%s%s/%s", dccdir, dir, fn); } else { s = nmalloc(strlen(dccdir) + strlen(fn) + 1); sprintf(s, "%s%s", dccdir, fn); } if (!file_readable(s)) { dprintf(idx, "No such file.\n"); putlog(LOG_FILES, "*", "Refused dcc %sget %s from [%s]", resend ? "re" : "", fn, dcc[idx].nick); my_free(s); return 0; } if (!nick || !nick[0]) nick = dcc[idx].nick; /* Already have too many transfers active for this user? queue it */ if (at_limit(nick)) { char xxx[1024]; sprintf(xxx, "%d*%s%s", (int) strlen(dccdir), dccdir, dir); queue_file(xxx, fn, dcc[idx].nick, nick); dprintf(idx, "Queued: %s to %s\n", fn, nick); my_free(s); return 1; } if (copy_to_tmp) { char *tempfn = mktempfile(fn); /* Copy this file to /tmp, add a random prefix to the filename. */ s = nrealloc(s, strlen(dccdir) + strlen(dir) + strlen(fn) + 2); sprintf(s, "%s%s%s%s", dccdir, dir, dir[0] ? "/" : "", fn); s1 = nrealloc(s1, strlen(tempdir) + strlen(tempfn) + 1); sprintf(s1, "%s%s", tempdir, tempfn); my_free(tempfn); if (copyfile(s, s1) != 0) { dprintf(idx, "Can't make temporary copy of file!\n"); putlog(LOG_FILES | LOG_MISC, "*", "Refused dcc %sget %s: copy to %s FAILED!", resend ? "re" : "", fn, tempdir); my_free(s); my_free(s1); return 0; } } else { s1 = nrealloc(s1, strlen(dccdir) + strlen(dir) + strlen(fn) + 2); sprintf(s1, "%s%s%s%s", dccdir, dir, dir[0] ? "/" : "", fn); } s = nrealloc(s, strlen(dir) + strlen(fn) + 2); sprintf(s, "%s%s%s", dir, dir[0] ? "/" : "", fn); x = _dcc_send(idx, s1, nick, s, resend); if (x != DCCSEND_OK) wipe_tmp_filename(s1, -1); my_free(s); my_free(s1); return x; }
static void report_seenreq(char *channel, char *nick) { seenreq *l, *ll; seenreq_by *b, *bb; char *reply, *tmp; int nr; if (!tell_seens) return; ll = NULL; l = requests; reply = NULL; while (l) { if (!strcasecmp(l->nick, nick)) { reset_global_vars(); glob_slang = slang_find(coreslangs, slang_chanlang_get(chanlangs, channel)); glob_nick = nick; nr = count_seenreq(l->by); if (nr == 1) { glob_seenrequest = l; dprintf(DP_HELP, "NOTICE %s :%s\n", l->nick, SLONELOOK); } else { sortrequests(l); glob_seenrequest = l; glob_seenrequests = nr; tmp = SLMORELOOKS; reply = nmalloc(strlen(tmp) + 1); strcpy(reply, tmp); nr = 0; for (b = l->by; b; b = b->next) { nr++; reply = nrealloc(reply, strlen(reply) + ((nr == 1) ? 1 : 2) + strlen(b->who) + 1); sprintf(reply, "%s%s%s", reply, (nr == 1) ? " " : ", ", b->who); } tmp = SLLASTLOOK; reply = nrealloc(reply, strlen(reply) + 2 + strlen(tmp) + 1); sprintf(reply, "%s. %s", reply, tmp); dprintf(DP_HELP, "NOTICE %s :%s\n", l->nick, reply); nfree(reply); } b = l->by; while (b) { bb = b->next; nfree(b->who); nfree(b->host); nfree(b->chan); nfree(b); b = bb; } nfree(l->nick); if (ll) ll->next = l->next; else requests = l->next; nfree(l); if (ll) l = ll->next; else l = requests; } else { ll = l; l = l->next; } } }
/* do_seen(): Checks if someone matches the mask, and returns the reply * mask : first paramater (e.g. "G`Quann", "G`Quann", "*!*@*.isp.de", ...) * nick : nick of the one, who triggered the command * uhost: user@host of nick * chan : chan, where the command was triggered * bns : * 1 : do a botnet-seen if no matches are found * 0 : don't do a botnet-seen * -1 : return NULL instead of text, if no matches were found * (necessary for botnet seen) */ static char *do_seen(char *mask, char *nick, char *uhost, char *chan, int bns) { char hostbuf[UHOSTLEN + 1], *host, *newhost, *tmp, *dur; seendat *l; gseenres *r; int wild, nr; char bnquery[256]; struct userrec *u; struct laston_info *li; struct chanset_t *ch; Context; start_seentime_calc(); if (seen_reply) { nfree(seen_reply); seen_reply = NULL; } l = NULL; li = NULL; host = hostbuf; newhost = NULL; mask = newsplit(&mask); glob_query = mask; while (mask[0] == ' ') mask++; if (!mask[0]) { return SLNOPARAM; } if (strchr(mask, '?') || strchr(mask, '*')) { // if wildcard-searches ares not allowed, then either return // NULL (for botnet-seen), or a appropriate warning if (!wildcard_search) { if (bns == -1) return NULL; else return SLNOWILDCARDS; } else wild = 1; } else { if (strlen(mask) > seen_nick_len) // don't process if requested nick is too long return SLTOOLONGNICK; // (e.g. stop stupid jokes) if (!strcasecmp(mask, nick)) { return SLMIRROR; } // check if the nick is on the current channel if (onchan(mask, chan)) return SLONCHAN; if ((glob_othernick = handonchan(mask, chan))) return SLHANDONCHAN; // check if it is on any other channel if ((ch = onanychan(mask))) { #if EGG_IS_MIN_VER(10500) if (!secretchan(ch->dname)) { glob_otherchan = ch->dname; return SLONOTHERCHAN; } #else if (!secretchan(ch->name)) { glob_otherchan = ch->name; return SLONOTHERCHAN; } #endif } // check if the user who uses this handle is on the channel under // a different nick if ((ch = handonanychan(mask))) { #if EGG_IS_MIN_VER(10500) if (!secretchan(ch->dname)) { glob_otherchan = ch->dname; return SLONOTHERCHAN; } #else if (!secretchan(ch->name)) { glob_otherchan = ch->name; return SLONOTHERCHAN; } #endif } add_seenreq(mask, nick, uhost, chan, now); wild = 0; l = findseen(mask); // if there's a result, and if we don't want to search for the same user // under a different nick, just make a do_seennick on the result if (l && !fuzzy_search) { tmp = do_seennick(l); end_seentime_calc(); return tmp; } if (!l) { u = get_user_by_handle(userlist, mask); if (u) { li = get_user(&USERENTRY_LASTON, u); } if (!u || !li) { if (bns == -1) { // if bns is 0, then do_seen() was triggered by end_seentime_calc(); // a botnet seen function, which needs a clear return NULL; // NULL to detect if there was a result or not } tmp = SLNOTSEEN; if (bns && ((strlen(mask) + strlen(nick) + strlen(uhost) + strlen(chan) + 20) < 255)) { debug0("trying botnet seen"); if (bnsnick) nfree(bnsnick); if (bnschan) nfree(bnschan); bnsnick = nmalloc(strlen(nick) + 1); strcpy(bnsnick, nick); bnschan = nmalloc(strlen(chan) + 1); strcpy(bnschan, chan); sprintf(bnquery, "gseen_req %s %s %s %s", mask, nick, uhost, chan); botnet_send_zapf_broad(-1, botnetnick, NULL, bnquery); } } else { // we have a matching handle, no seen-entry, but a laston entry // in the userbase, so let's just return that one. dur = gseen_duration(now - li->laston); glob_laston = dur; tmp = SLPOORSEEN; seen_reply = nmalloc(strlen(tmp) + 1); strcpy(seen_reply, tmp); end_seentime_calc(); return seen_reply; } end_seentime_calc(); return tmp; } // now prepare the host for fuzzy-search if (strlen(l->host) < UHOSTLEN) { maskstricthost(l->host, host); host = strchr(host, '!') + 1; // strip nick from host for faster search } else { end_seentime_calc(); return "error, too long host"; } } if (l && (l->type == SEEN_CHPT)) { tmp = do_seennick(l); end_seentime_calc(); return tmp; } numresults = 0; // wildmatch_seens uses a global var to store hosts in it // (to prevent massive nmalloc/nfree-usage), so don't forget // to initialize and free it temp_wildmatch_host = my_malloc(1); wildmatch_seens(host, mask, wild); my_free(temp_wildmatch_host); temp_wildmatch_host = NULL; if (!results) { end_seentime_calc(); if (bns == -1) return NULL; // let the botnet seen function know, that seen failed return SLNOMATCH; } if (numresults >= max_matches) { end_seentime_calc(); free_seenresults(); return SLTOOMANYMATCHES; } sortresults(); if (strcasecmp(results->seen->nick, mask)) { // if the user's latest nick is not the nick for which we were searching, // say that there were multiple matches and display the latest one if (numresults == 1) tmp = SLONEMATCH; else if (numresults <= 20) tmp = SLLITTLEMATCHES; else tmp = SLMANYMATCHES; seen_reply = nmalloc(strlen(tmp) + 1); strcpy(seen_reply, tmp); nr = 0; for (r = results; (r && (nr < 20)); r = r->next) { nr++; if (nr > 1) { seen_reply = nrealloc(seen_reply, 1 + strlen(seen_reply) + 1 + strlen(r->seen->nick) + 1); strcat(seen_reply, ", "); } else { seen_reply = nrealloc(seen_reply, 1 + strlen(seen_reply) + strlen(r->seen->nick) + 1); strcat(seen_reply, " "); } strcat(seen_reply, r->seen->nick); } tmp = do_seennick(results->seen); seen_reply = nrealloc(seen_reply, 2 + strlen(seen_reply) + strlen(tmp) + 1); sprintf(seen_reply, "%s. %s", seen_reply, tmp); } else { // first result is the nick which we were searching for // just return the info for this nick and don't care about other results tmp = do_seennick(results->seen); seen_reply = nmalloc(strlen(tmp) + 1); strcpy(seen_reply, tmp); } free_seenresults(); end_seentime_calc(); return seen_reply; }