/**************************************************************************
* Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, *
* Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. *
* *
* Merc Diku Mud improvements copyright (C) 1992, 1993 by Michael *
* Chastain, Michael Quan, and Mitchell Tse. *
* *
* In order to use any part of this Merc Diku Mud, you must comply with *
* both the original Diku license in 'license.doc' as well the Merc *
* license in 'license.txt'. In particular, you may not remove either of *
* these copyright notices. *
* *
* Much time and thought has gone into this software and you are *
* benefiting. We hope that you share your changes too. What goes *
* around, comes around. *
***************************************************************************
* ROM 2.4 is copyright 1993-1998 Russ Taylor *
* ROM has been brought to you by the ROM consortium *
* Russ Taylor (rtaylor@hypercube.org) *
* Gabrielle Taylor (gtaylor@hypercube.org) *
* Brian Moore (zump@rom.org) *
* By using this code, you have agreed to follow the terms of the *
* ROM license, in the file Rom24/doc/rom.license *
***************************************************************************
* The Dawn of Time v1.69q (c)1997-2002 Michael Garratt *
* >> A number of people have contributed to the Dawn codebase, with the *
* majority of code written by Michael Garratt - www.dawnoftime.org *
* >> To use this source code, you must fully comply with the dawn license *
* in licenses.txt... In particular, you may not remove this copyright *
* notice. *
***************************************************************************
* 1stMud ROM Derivative (c) 2001-2004 by Markanth *
* http://www.firstmud.com/ <markanth@firstmud.com> *
* By using this code you have agreed to follow the term of *
* the 1stMud license in ../doc/1stMud/LICENSE *
***************************************************************************/
#include "merc.h"
#define LOG_TIME_MAGIC_NUM 666
#define LOG_TIME_FMT "%b %e %H:%M:%S"
time_t last_current_time;
time_t cycle_log_after;
bool log_hold_log_string_core_stdout_restore_value;
bool log_string_core_stdout_enabled = true;
char initial_startup_log_buffer[7 * MSL + 1];
bool initial_startup_log_buffer_full = false;
FILE *current_logfile_descriptor = NULL;
char current_logfile_name[MSL];
time_t get_tomorrow_start(void)
{
struct tm now;
time_t tommorrow_start;
now = *localtime(¤t_time);
now.tm_sec = 0;
now.tm_min = 0;
now.tm_hour = 0;
now.tm_mday++;
tommorrow_start = mktime(&now);
return tommorrow_start;
}
FILE *get_new_logfile(int portprefix, char *logfilename)
{
sprintf(logfilename, "%s%d-%s.log", LOG_DIR, portprefix,
str_time(-1, -1, "%m-%d"));
return fopen(logfilename, "w");
}
static void log_str_fmt(FILE * file, const char *str)
{
if (!file)
return;
if (last_current_time == LOG_TIME_MAGIC_NUM)
fprintf(file, "%s\n", str);
else if (!NullStr(str))
{
if (last_current_time == current_time)
fprintf(file, "%15s :: %s\n", " ", str);
else
fprintf(file, "%15s :: %s\n", str_time(-1, -1, LOG_TIME_FMT),
str);
}
}
static void log_string_core_stdout(const char *str)
{
if (log_string_core_stdout_enabled)
{
log_str_fmt(stdout, str);
}
}
void log_hold_till_commandline_options_parsed(void)
{
log_hold_log_string_core_stdout_restore_value =
log_string_core_stdout_enabled;
log_string_core_stdout_enabled = false;
}
void log_release_held_logs(void)
{
log_string_core_stdout_enabled =
log_hold_log_string_core_stdout_restore_value;
if (!NullStr(initial_startup_log_buffer))
log_string_core_stdout(initial_startup_log_buffer);
}
void write_log_index(char *str)
{
append_file(LOG_INDEX_FILE,
FORMATF("[%d] %s :: %s", getpid(),
str_time(-1, -1, LOG_TIME_FMT), str), true);
}
void log_string_flush()
{
fflush(stdout);
if (current_logfile_descriptor)
{
fflush(current_logfile_descriptor);
}
}
void log_string_core(const char *str)
{
if (!mainport)
{
int pos;
log_string_core_stdout(str);
if (!initial_startup_log_buffer_full
&& (pos =
strlen(initial_startup_log_buffer)) + strlen(str) <
sizeof(initial_startup_log_buffer) - 100)
{
sprintf(&initial_startup_log_buffer[pos], "%15s :: %s\n",
"startup buffer", str);
}
else
{
initial_startup_log_buffer_full = true;
logf
("initial_startup_log_buffer exceeded, some logging information will be lost.");
}
return;
}
if (IsSet(mud_info.cmdline_options, CMDLINE_NO_LOGFILE))
{
log_string_core_stdout(str);
return;
}
if (current_logfile_descriptor && cycle_log_after < current_time)
{
char new_logfile_name[MSL];
FILE *new_logfile_descriptor;
cycle_log_after = get_tomorrow_start();
new_logfile_descriptor = get_new_logfile(mainport, new_logfile_name);
logf("transfering logging from %s to %s", current_logfile_name,
new_logfile_name);
log_string_flush();
fclose(current_logfile_descriptor);
current_logfile_descriptor = new_logfile_descriptor;
new_logfile_descriptor = NULL;
logf("logging continuation of %s", current_logfile_name);
strcpy(current_logfile_name, new_logfile_name);
new_logfile_name[0] = '\0';
}
if (!current_logfile_descriptor)
{
int portprefix = mainport;
mainport = 0;
current_logfile_descriptor =
get_new_logfile(portprefix, current_logfile_name);
cycle_log_after = get_tomorrow_start();
mainport = portprefix;
if (current_logfile_descriptor)
{
log_string_core(initial_startup_log_buffer);
initial_startup_log_buffer[0] = '\0';
if (initial_startup_log_buffer_full)
{
logf
("initial_startup_log_buffer exceeded, some logging information will be lost.");
initial_startup_log_buffer_full = false;
}
logf("Logging to %s", current_logfile_name);
write_log_index("============================================");
write_log_index(FORMATF
("%s logging to %s", EXE_FILE,
current_logfile_name));
#ifdef HAVE_WORKING_FORK
if (IsSet
(mud_info.cmdline_options, CMDLINE_NO_BACKGROUND_PROCESS))
{
logf("Mud remaining in foreground, process id = %d.",
getpid());
}
else
{
pid_t fork_result;
logf("switching to daemon mode (background running process)");
fork_result = fork();
if (fork_result < 0)
{
bugf
("switching to background daemon failed! errno=%d (%s)",
errno, strerror(errno));
}
else if (fork_result)
{
sleep_seconds(1);
exit(1);
}
if (setsid() < 0)
{
bugf("failed to set new session id.");
}
logf
("The mud is now running in the background, process id = %d.",
getpid());
}
#endif
if (!IsSet(mud_info.cmdline_options, CMDLINE_LOG_CONSOLE))
{
log_string_core_stdout_enabled = false;
}
}
}
log_string_core_stdout(str);
if (current_logfile_descriptor)
{
log_str_fmt(current_logfile_descriptor, str);
}
}
void log_string(const char *str)
{
if (IsSet(run_level, RUNLEVEL_INIT))
{
return;
}
log_string_core(str);
last_current_time = current_time;
log_string_flush();
return;
}
void fulltime_log_string(const char *str)
{
if (IsSet(run_level, RUNLEVEL_INIT))
{
return;
}
last_current_time = 0;
log_string_core(str);
log_string_flush();
return;
}
void log_bar(void)
{
last_current_time = LOG_TIME_MAGIC_NUM;
log_string(draw_line(NULL, "*", 0));
}
void log_note(const char *text)
{
const char *msg;
log_bar();
msg = str_dup(text);
msg = format_string(msg);
msg = string_replace_all(msg, "{}", "\n");
log_string(msg);
free_string(msg);
log_bar();
}
void log_notef(const char *fmt, ...)
{
char buf[MPL];
va_list args;
va_start(args, fmt);
vsnprintf(buf, sizeof(buf) - 100, fmt, args);
va_end(args);
log_note(buf);
}
void log_error(const char *str)
{
#ifdef HAVE_STRERROR
log_str_fmt(stderr, FORMATF("%s - %s", strerror(errno), str));
logf("%s - %s", strerror(errno), str);
#else
perror(str);
log_string(str);
#endif
last_current_time = current_time;
return;
}
void logf_error(const char *fmt, ...)
{
char buf[MPL];
if (!NullStr(fmt))
{
va_list args;
va_start(args, fmt);
vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
}
else
buf[0] = NUL;
log_error(buf);
}