void logfile_close(void) { if (!logf) return; char date[50] = ""; egg_strftime(date, sizeof date, "%c %Z", gmtime(&now)); fprintf(logf, "--- Log session end: %s ---\n", date); fclose(logf); logf = NULL; }
bool logfile_open() { if (!(logf = fopen(".l", "a"))) return 0; if (!init_log_exit) { init_log_exit = 1; atexit(logfile_close); } char date[50] = ""; egg_strftime(date, sizeof date, "%c %Z", gmtime(&now)); fprintf(logf, "--- Log session begin: %s ---\n", date); return 1; }
/* * srd="+" : index * srd="-" : read all msgs * else : read msg in list : (ex: .notes read 5-9;12;13;18-) * idx=-1 : /msg */ static void notes_read(char *hand, char *nick, char *srd, int idx) { FILE *f; char s[601], *to, *dt, *from, *s1, wt[100]; time_t tt; int ix = 1; int ir = 0; int rd[128]; /* Is it enough ? */ int i; if (srd[0] == 0) srd = "-"; if (!notefile[0]) { if (idx >= 0) dprintf(idx, "%s.\n", NOTES_NO_MESSAGES); else dprintf(DP_HELP, "NOTICE %s :%s.\n", nick, NOTES_NO_MESSAGES); return; } f = fopen(notefile, "r"); if (f == NULL) { if (idx >= 0) dprintf(idx, "%s.\n", NOTES_NO_MESSAGES); else dprintf(DP_HELP, "NOTICE %s :%s.\n", nick, NOTES_NO_MESSAGES); return; } notes_parse(rd, srd); while (!feof(f) && fgets(s, 600, f)) { i = strlen(s); if (i > 0 && s[i - 1] == '\n') s[i - 1] = 0; if (!feof(f)) { rmspace(s); if ((s[0]) && (s[0] != '#') && (s[0] != ';')) { /* Not comment */ s1 = s; to = newsplit(&s1); if (!egg_strcasecmp(to, hand)) { int lapse; from = newsplit(&s1); dt = newsplit(&s1); tt = atoi(dt); egg_strftime(wt, 14, "%b %d %H:%M", localtime(&tt)); dt = wt; lapse = (int) ((now - tt) / 86400); if (lapse > note_life - 7) { if (lapse >= note_life) strcat(dt, NOTES_EXPIRE_TODAY); else sprintf(&dt[strlen(dt)], NOTES_EXPIRE_XDAYS, note_life - lapse, (note_life - lapse) == 1 ? "" : "S"); } if (srd[0] == '+') { if (idx >= 0) { if (ix == 1) dprintf(idx, "### %s:\n", NOTES_WAITING); dprintf(idx, " %2d. %s (%s)\n", ix, from, dt); } else dprintf(DP_HELP, "NOTICE %s :%2d. %s (%s)\n", nick, ix, from, dt); } else if (notes_in(rd, ix)) { if (idx >= 0) dprintf(idx, "%2d. %s (%s): %s\n", ix, from, dt, s1); else dprintf(DP_HELP, "NOTICE %s :%2d. %s (%s): %s\n", nick, ix, from, dt, s1); ir++; } ix++; } } } } fclose(f); if ((srd[0] != '+') && (ir == 0) && (ix > 1)) { if (idx >= 0) dprintf(idx, "%s.\n", NOTES_NOT_THAT_MANY); else dprintf(DP_HELP, "NOTICE %s :%s.\n", nick, NOTES_NOT_THAT_MANY); } if (srd[0] == '+') { if (ix == 1) { if (idx >= 0) dprintf(idx, "%s.\n", NOTES_NO_MESSAGES); else dprintf(DP_HELP, "NOTICE %s :%s.\n", nick, NOTES_NO_MESSAGES); } else { if (idx >= 0) dprintf(idx, "### %s\n", (ix != 2) ? NOTES_DCC_USAGE_READ : NOTES_DCC_USAGE_READ2); else dprintf(DP_HELP, "NOTICE %s :%s: %d\n", nick, MISC_TOTAL, ix - 1); } } else if ((ir == 0) && (ix == 1)) { if (idx >= 0) dprintf(idx, "%s.\n", NOTES_NO_MESSAGES); else dprintf(DP_HELP, "NOTICE %s :%s.\n", nick, NOTES_NO_MESSAGES); } }
/* Outputs a sorted list of files/directories matching the mask, * to idx. */ static void filedb_ls(FILE *fdb, int idx, char *mask, int showall) { int ok = 0, cnt = 0, is = 0; char s1[81], *p = NULL; struct flag_record user = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 }; filedb_entry *fdbe = NULL; filelist_t *flist = NULL; flist = filelist_new(); filedb_readtop(fdb, NULL); fdbe = filedb_getfile(fdb, ftell(fdb), GET_FULL); while (fdbe) { ok = 1; if (fdbe->stat & FILE_UNUSED) ok = 0; if (ok && (fdbe->stat & FILE_DIR) && fdbe->flags_req) { /* Check permissions */ struct flag_record req = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 }; break_down_flags(fdbe->flags_req, &req, NULL); get_user_flagrec(dcc[idx].user, &user, dcc[idx].u.file->chat->con_chan); if (!flagrec_ok(&req, &user)) { ok = 0; } } if (ok) is = 1; if (ok && !wild_match_file(mask, fdbe->filename)) ok = 0; if (ok && (fdbe->stat & FILE_HIDDEN) && !(showall)) ok = 0; if (ok) { /* Display it! */ if (cnt == 0) { dprintf(idx, FILES_LSHEAD1); dprintf(idx, FILES_LSHEAD2); } filelist_add(flist, fdbe->filename); if (fdbe->stat & FILE_DIR) { char *s2 = NULL, *s3 = NULL; /* Too long? */ if (strlen(fdbe->filename) > 45) { /* Display the filename on its own line. */ s2 = nmalloc(strlen(fdbe->filename) + 3); sprintf(s2, "%s/\n", fdbe->filename); filelist_addout(flist, s2); my_free(s2); } else { s2 = nmalloc(strlen(fdbe->filename) + 2); sprintf(s2, "%s/", fdbe->filename); } /* Note: You have to keep the sprintf and the nmalloc statements * in sync, i.e. always check that you allocate enough * memory. */ if ((fdbe->flags_req) && (user.global &(USER_MASTER | USER_JANITOR))) { s3 = nmalloc(42 + strlen(s2 ? s2 : "") + 6 + strlen(FILES_REQUIRES) + strlen(fdbe->flags_req) + 1 + strlen(fdbe->chan ? fdbe->chan : "") + 1); sprintf(s3, "%-30s <DIR%s> (%s %s%s%s)\n", s2, fdbe->stat & FILE_SHARE ? " SHARE" : "", FILES_REQUIRES, fdbe->flags_req, fdbe->chan ? " " : "", fdbe->chan ? fdbe->chan : ""); } else { s3 = nmalloc(38 + strlen(s2 ? s2 : "")); sprintf(s3, "%-30s <DIR>\n", s2 ? s2 : ""); } if (s2) my_free(s2); filelist_addout(flist, s3); my_free(s3); } else { char s2[41], t[50], *s3 = NULL, *s4; s2[0] = 0; if (showall) { if (fdbe->stat & FILE_SHARE) strcat(s2, " (shr)"); if (fdbe->stat & FILE_HIDDEN) strcat(s2, " (hid)"); } egg_strftime(t, 10, "%d%b%Y", localtime(&fdbe->uploaded)); if (fdbe->size < 1024) sprintf(s1, "%5d", fdbe->size); else sprintf(s1, "%4dk", (int) (fdbe->size / 1024)); if (fdbe->sharelink) strcpy(s1, " "); /* Too long? */ if (strlen(fdbe->filename) > 30) { s3 = nmalloc(strlen(fdbe->filename) + 2); sprintf(s3, "%s\n", fdbe->filename); filelist_addout(flist, s3); my_free(s3); /* Causes filename to be displayed on its own line */ } else malloc_strcpy(s3, fdbe->filename); s4 = nmalloc(69 + strlen(s3 ? s3 : "") + strlen(s1) + strlen(fdbe->uploader) + strlen(t) + strlen(s2)); sprintf(s4, "%-30s %s %-9s (%s) %6d%s\n", s3 ? s3 : "", s1, fdbe->uploader, t, fdbe->gots, s2); if (s3) my_free(s3); filelist_addout(flist, s4); my_free(s4); if (fdbe->sharelink) { s4 = nmalloc(9 + strlen(fdbe->sharelink)); sprintf(s4, " --> %s\n", fdbe->sharelink); filelist_addout(flist, s4); my_free(s4); } } if (fdbe->desc) { p = strchr(fdbe->desc, '\n'); while (p != NULL) { *p = 0; if ((fdbe->desc)[0]) { char *sd; sd = nmalloc(strlen(fdbe->desc) + 5); sprintf(sd, " %s\n", fdbe->desc); filelist_addout(flist, sd); my_free(sd); } strcpy(fdbe->desc, p + 1); p = strchr(fdbe->desc, '\n'); } if ((fdbe->desc)[0]) { char *sd; sd = nmalloc(strlen(fdbe->desc) + 5); sprintf(sd, " %s\n", fdbe->desc); filelist_addout(flist, sd); my_free(sd); } } cnt++; } free_fdbe(&fdbe); fdbe = filedb_getfile(fdb, ftell(fdb), GET_FULL); } if (is == 0) dprintf(idx, FILES_NOFILES); else if (cnt == 0) dprintf(idx, FILES_NOMATCH); else { filelist_sort(flist); filelist_idxshow(flist, idx); dprintf(idx, "--- %d file%s.\n", cnt, cnt != 1 ? "s" : ""); } filelist_free(flist); }
/* Dependant on revenge_mode, punish the offender. */ static void punish_badguy(struct chanset_t *chan, char *whobad, struct userrec *u, char *badnick, char *victim, int mevictim, int type) { char reason[1024], ct[81], *kick_msg; memberlist *m; struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 }; m = ismember(chan, badnick); if (!m) return; get_user_flagrec(u, &fr, chan->dname); /* Get current time into a string */ egg_strftime(ct, 7, "%d %b", localtime(&now)); /* Put together log and kick messages */ reason[0] = 0; switch (type) { case REVENGE_KICK: kick_msg = IRC_KICK_PROTECT; simple_sprintf(reason, "kicked %s off %s", victim, chan->dname); break; case REVENGE_DEOP: simple_sprintf(reason, "deopped %s on %s", victim, chan->dname); kick_msg = IRC_DEOP_PROTECT; break; default: kick_msg = "revenge!"; } putlog(LOG_MISC, chan->dname, "Punishing %s (%s)", badnick, reason); /* Set the offender +d */ if ((chan->revenge_mode > 0) && !(chan_deop(fr) || glob_deop(fr))) { char s[UHOSTLEN], s1[UHOSTLEN]; memberlist *mx = NULL; /* Removing op */ if (chan_op(fr) || (glob_op(fr) && !chan_deop(fr))) { fr.match = FR_CHAN; if (chan_op(fr)) fr.chan &= ~USER_OP; else fr.chan |= USER_DEOP; set_user_flagrec(u, &fr, chan->dname); putlog(LOG_MISC, "*", "No longer opping %s[%s] (%s)", u->handle, whobad, reason); } /* ... or just setting to deop */ else if (u) { /* In the user list already, cool :) */ fr.match = FR_CHAN; fr.chan |= USER_DEOP; set_user_flagrec(u, &fr, chan->dname); simple_sprintf(s, "(%s) %s", ct, reason); putlog(LOG_MISC, "*", "Now deopping %s[%s] (%s)", u->handle, whobad, s); } /* ... or creating new user and setting that to deop */ else { strcpy(s1, whobad); maskaddr(s1, s, chan->ban_type); strcpy(s1, badnick); /* If that handle exists use "badX" (where X is an increasing number) * instead. */ while (get_user_by_handle(userlist, s1)) { if (!strncmp(s1, "bad", 3)) { int i; i = atoi(s1 + 3); simple_sprintf(s1 + 3, "%d", i + 1); } else strcpy(s1, "bad1"); /* Start with '1' */ } userlist = adduser(userlist, s1, s, "-", 0); fr.match = FR_CHAN; fr.chan = USER_DEOP; fr.udef_chan = 0; u = get_user_by_handle(userlist, s1); if ((mx = ismember(chan, badnick))) mx->user = u; set_user_flagrec(u, &fr, chan->dname); simple_sprintf(s, "(%s) %s (%s)", ct, reason, whobad); set_user(&USERENTRY_COMMENT, u, (void *) s); putlog(LOG_MISC, "*", "Now deopping %s (%s)", whobad, reason); } } /* Always try to deop the offender */ if (!mevictim) add_mode(chan, '-', 'o', badnick); /* Ban. Should be done before kicking. */ if (chan->revenge_mode > 2) { char s[UHOSTLEN], s1[UHOSTLEN]; splitnick(&whobad); maskaddr(whobad, s1, chan->ban_type); simple_sprintf(s, "(%s) %s", ct, reason); u_addban(chan, s1, botnetnick, s, now + (60 * chan->ban_time), 0); if (!mevictim && HALFOP_CANDOMODE('b')) { add_mode(chan, '+', 'b', s1); flush_mode(chan, QUICK); } } /* Kick the offender */ if (!mevictim && (chan->revenge_mode > 1) && (!channel_dontkickops(chan) || (!chan_op(fr) && (!glob_op(fr) || chan_deop(fr)))) && !chan_sentkick(m) && (me_op(chan) || (me_halfop(chan) && !chan_hasop(m) && (strchr(NOHALFOPS_MODES, 'b') == NULL)))) { dprintf(DP_MODE, "KICK %s %s :%s\n", chan->name, badnick, kick_msg); m->flags |= SENTKICK; } }
void putlog(int type, const char *chname, const char *format, ...) { char va_out[LOGLINEMAX + 1] = ""; va_list va; va_start(va, format); egg_vsnprintf(va_out, sizeof(va_out), format, va); va_end(va); if (!va_out[0]) { putlog(LOG_ERRORS, "*", "Empty putlog() detected"); return; } if (!log_repeated) { if (type == last_type && !egg_strncasecmp(chname, last_chname, sizeof(last_chname)) && !egg_strncasecmp(va_out, last_log, sizeof(last_log))) { ++log_repeats; return; } if (log_repeats) { log_repeated = 1; putlog(type, last_chname, "Last message repeated %d times.\n", log_repeats); log_repeats = 0; } strlcpy(last_log, va_out, sizeof(last_log)); last_type = type; strlcpy(last_chname, chname, sizeof(last_chname)); } else log_repeated = 0; char *p = NULL; if ((p = strchr(va_out, '\n'))) /* make sure no trailing newline */ *p = 0; int idx = 0; char out[LOGLINEMAX + 1] = ""; if (conf.bot && conf.bot->hub) { char stamp[34] = ""; struct tm *t = gmtime(&now); egg_strftime(stamp, sizeof(stamp), LOG_TS, t); /* Place the timestamp in the string to be printed */ strlcpy(out, stamp, sizeof(out)); strlcat(out, " ", sizeof(out)); strlcat(out, va_out, sizeof(out)); } else strlcpy(out, va_out, sizeof(out)); /* strcat(out, "\n"); */ #ifdef no /* FIXME: WRITE LOG HERE */ int logfile_masks = LOG_CMDS|LOG_ERRORS|LOG_WARN|LOG_BOTS|LOG_MISC; if (logfile_masks && (logfile_masks & type)) logfile(type, out); #endif /* broadcast to hubs */ if (chname[0] == '*' && conf.bot && conf.bot->nick) botnet_send_log(-1, conf.bot->nick, type, out); for (idx = 0; idx < dcc_total; idx++) { if (dcc[idx].type && (dcc[idx].type == &DCC_CHAT && dcc[idx].simul == -1) && (dcc[idx].u.chat->con_flags & type)) { if ((chname[0] == '@') || (chname[0] == '*') || (dcc[idx].u.chat->con_chan[0] == '*') || (!rfc_casecmp(chname, dcc[idx].u.chat->con_chan))) dprintf(idx, "%s\n", out); } } if ((!backgrd) && (!term_z)) { dprintf(DP_STDOUT, "%s\n", out); } else if ((type & LOG_ERRORS || type & LOG_MISC) && use_stderr) { dprintf(DP_STDERR, "%s\n", va_out); } }