mirror of
https://github.com/matrix-construct/construct
synced 2024-08-31 05:45:16 +02:00
311 lines
7 KiB
C
311 lines
7 KiB
C
/*
|
|
* charybdis: an advanced Internet Relay Chat Daemon(ircd).
|
|
*
|
|
* Copyright (C) 2003 Lee H <lee@leeh.co.uk>
|
|
* Copyright (C) 2003-2005 ircd-ratbox development team
|
|
* Copyright (C) 2008 William Pitcock <nenolod@sacredspiral.co.uk>
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are
|
|
* met:
|
|
*
|
|
* 1.Redistributions of source code must retain the above copyright notice,
|
|
* this list of conditions and the following disclaimer.
|
|
*
|
|
* 2.Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* 3.The name of the author may not be used to endorse or promote products
|
|
* derived from this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
|
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#include "stdinc.h"
|
|
#include "ircd_defs.h"
|
|
#include "logger.h"
|
|
#include "s_conf.h"
|
|
#include "send.h"
|
|
#include "client.h"
|
|
#include "s_serv.h"
|
|
|
|
static FILE *log_main;
|
|
static FILE *log_user;
|
|
static FILE *log_fuser;
|
|
static FILE *log_oper;
|
|
static FILE *log_foper;
|
|
static FILE *log_server;
|
|
static FILE *log_kill;
|
|
static FILE *log_kline;
|
|
static FILE *log_operspy;
|
|
static FILE *log_ioerror;
|
|
|
|
struct log_struct
|
|
{
|
|
char **name;
|
|
FILE **logfile;
|
|
};
|
|
|
|
static struct log_struct log_table[LAST_LOGFILE] =
|
|
{
|
|
{ NULL, &log_main },
|
|
{ &ConfigFileEntry.fname_userlog, &log_user },
|
|
{ &ConfigFileEntry.fname_fuserlog, &log_fuser },
|
|
{ &ConfigFileEntry.fname_operlog, &log_oper },
|
|
{ &ConfigFileEntry.fname_foperlog, &log_foper },
|
|
{ &ConfigFileEntry.fname_serverlog, &log_server },
|
|
{ &ConfigFileEntry.fname_killlog, &log_kill },
|
|
{ &ConfigFileEntry.fname_klinelog, &log_kline },
|
|
{ &ConfigFileEntry.fname_operspylog, &log_operspy },
|
|
{ &ConfigFileEntry.fname_ioerrorlog, &log_ioerror }
|
|
};
|
|
|
|
static void
|
|
verify_logfile_access(const char *filename)
|
|
{
|
|
char *dirname, *d;
|
|
char buf[512];
|
|
d = rb_dirname(filename);
|
|
dirname = LOCAL_COPY(d);
|
|
rb_free(d);
|
|
|
|
if(access(dirname, F_OK) == -1)
|
|
{
|
|
snprintf(buf, sizeof(buf), "WARNING: Unable to access logfile %s - parent directory %s does not exist", filename, dirname);
|
|
if(testing_conf || server_state_foreground)
|
|
fprintf(stderr, "%s\n", buf);
|
|
sendto_realops_snomask(SNO_GENERAL, L_ALL, "%s", buf);
|
|
return;
|
|
}
|
|
|
|
if(access(filename, F_OK) == -1)
|
|
{
|
|
if(access(dirname, W_OK) == -1)
|
|
{
|
|
snprintf(buf, sizeof(buf), "WARNING: Unable to access logfile %s - access to parent directory %s failed: %s",
|
|
filename, dirname, strerror(errno));
|
|
if(testing_conf || server_state_foreground)
|
|
fprintf(stderr, "%s\n", buf);
|
|
sendto_realops_snomask(SNO_GENERAL, L_ALL, "%s", buf);
|
|
}
|
|
return;
|
|
}
|
|
|
|
if(access(filename, W_OK) == -1)
|
|
{
|
|
snprintf(buf, sizeof(buf), "WARNING: Access denied for logfile %s: %s", filename, strerror(errno));
|
|
if(testing_conf || server_state_foreground)
|
|
fprintf(stderr, "%s\n", buf);
|
|
sendto_realops_snomask(SNO_GENERAL, L_ALL, "%s", buf);
|
|
return;
|
|
}
|
|
return;
|
|
}
|
|
|
|
void
|
|
init_main_logfile(void)
|
|
{
|
|
verify_logfile_access(logFileName);
|
|
if(log_main == NULL)
|
|
{
|
|
log_main = fopen(logFileName, "a");
|
|
}
|
|
}
|
|
|
|
void
|
|
open_logfiles(void)
|
|
{
|
|
int i;
|
|
|
|
close_logfiles();
|
|
|
|
log_main = fopen(logFileName, "a");
|
|
|
|
/* log_main is handled above, so just do the rest */
|
|
for(i = 1; i < LAST_LOGFILE; i++)
|
|
{
|
|
/* reopen those with paths */
|
|
if(!EmptyString(*log_table[i].name))
|
|
{
|
|
verify_logfile_access(*log_table[i].name);
|
|
*log_table[i].logfile = fopen(*log_table[i].name, "a");
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
close_logfiles(void)
|
|
{
|
|
int i;
|
|
|
|
if(log_main != NULL)
|
|
fclose(log_main);
|
|
|
|
/* log_main is handled above, so just do the rest */
|
|
for(i = 1; i < LAST_LOGFILE; i++)
|
|
{
|
|
if(*log_table[i].logfile != NULL)
|
|
{
|
|
fclose(*log_table[i].logfile);
|
|
*log_table[i].logfile = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
ilog(ilogfile dest, const char *format, ...)
|
|
{
|
|
FILE *logfile = *log_table[dest].logfile;
|
|
char buf[BUFSIZE];
|
|
char buf2[BUFSIZE];
|
|
va_list args;
|
|
|
|
if(logfile == NULL)
|
|
return;
|
|
|
|
va_start(args, format);
|
|
vsnprintf(buf, sizeof(buf), format, args);
|
|
va_end(args);
|
|
|
|
snprintf(buf2, sizeof(buf2), "%s %s\n",
|
|
smalldate(rb_current_time()), buf);
|
|
|
|
if(fputs(buf2, logfile) < 0)
|
|
{
|
|
fclose(logfile);
|
|
*log_table[dest].logfile = NULL;
|
|
return;
|
|
}
|
|
|
|
fflush(logfile);
|
|
}
|
|
|
|
static void
|
|
_iprint(const char *domain, const char *buf)
|
|
{
|
|
if (domain == NULL || buf == NULL)
|
|
return;
|
|
|
|
fprintf(stderr, "%8s: %s\n", domain, buf);
|
|
}
|
|
|
|
void
|
|
idebug(const char *format, ...)
|
|
{
|
|
#ifndef NDEBUG
|
|
char buf[BUFSIZE];
|
|
va_list args;
|
|
|
|
va_start(args, format);
|
|
vsnprintf(buf, sizeof(buf), format, args);
|
|
va_end(args);
|
|
|
|
_iprint("debug", buf);
|
|
|
|
ilog(L_MAIN, "%s", buf);
|
|
#endif
|
|
}
|
|
|
|
void
|
|
inotice(const char *format, ...)
|
|
{
|
|
char buf[BUFSIZE];
|
|
va_list args;
|
|
|
|
va_start(args, format);
|
|
vsnprintf(buf, sizeof(buf), format, args);
|
|
va_end(args);
|
|
|
|
_iprint("notice", buf);
|
|
|
|
ilog(L_MAIN, "%s", buf);
|
|
}
|
|
|
|
void
|
|
iwarn(const char *format, ...)
|
|
{
|
|
char buf[BUFSIZE];
|
|
va_list args;
|
|
|
|
va_start(args, format);
|
|
vsnprintf(buf, sizeof(buf), format, args);
|
|
va_end(args);
|
|
|
|
_iprint("warning", buf);
|
|
|
|
ilog(L_MAIN, "%s", buf);
|
|
}
|
|
|
|
void
|
|
ierror(const char *format, ...)
|
|
{
|
|
char buf[BUFSIZE];
|
|
va_list args;
|
|
|
|
va_start(args, format);
|
|
vsnprintf(buf, sizeof(buf), format, args);
|
|
va_end(args);
|
|
|
|
_iprint("error", buf);
|
|
|
|
ilog(L_MAIN, "%s", buf);
|
|
}
|
|
|
|
void
|
|
report_operspy(struct Client *source_p, const char *token, const char *arg)
|
|
{
|
|
/* if its not my client its already propagated */
|
|
if(MyClient(source_p))
|
|
sendto_match_servs(source_p, "*", CAP_ENCAP, NOCAPS,
|
|
"ENCAP * OPERSPY %s %s",
|
|
token, arg ? arg : "");
|
|
|
|
sendto_realops_snomask(SNO_OPERSPY,
|
|
ConfigFileEntry.operspy_admin_only ? L_ADMIN : L_ALL,
|
|
"OPERSPY %s %s %s",
|
|
get_oper_name(source_p), token,
|
|
arg ? arg : "");
|
|
|
|
ilog(L_OPERSPY, "OPERSPY %s %s %s",
|
|
get_oper_name(source_p), token, arg ? arg : "");
|
|
}
|
|
|
|
const char *
|
|
smalldate(time_t ltime)
|
|
{
|
|
static char buf[MAX_DATE_STRING];
|
|
struct tm *lt;
|
|
|
|
lt = localtime(<ime);
|
|
|
|
snprintf(buf, sizeof(buf), "%d/%d/%d %02d.%02d",
|
|
lt->tm_year + 1900, lt->tm_mon + 1,
|
|
lt->tm_mday, lt->tm_hour, lt->tm_min);
|
|
|
|
return buf;
|
|
}
|
|
|
|
void
|
|
ilog_error(const char *error)
|
|
{
|
|
int e;
|
|
const char *errstr;
|
|
|
|
e = errno;
|
|
errstr = strerror(e);
|
|
|
|
ilog(L_IOERROR, "%s: %d (%s)", error, e, errstr);
|
|
sendto_realops_snomask(SNO_DEBUG, L_ALL, "%s: %d (%s)",
|
|
error, e, errstr);
|
|
}
|