26static char *errcopy = NULL;
28static size_t moutcopy;
29static size_t merrcopy;
31static int noutcopy = 0;
32static int nerrcopy = 0;
36static char *errfiledouble = NULL;
39static int copying = 0;
42static PHYSFS_File *logout_file = NULL;
43static PHYSFS_File *logerr_file = NULL;
48static int slogprintf( FILE *stream,
int newline,
const char *str,
size_t n );
49static int vlogprintf( FILE *stream,
int newline,
const char *fmt, va_list ap );
51static void log_append(
const FILE *stream,
const char *str );
53 const char *filedouble );
59static int slogprintf( FILE *stream,
int newline,
const char *str,
size_t n )
65 if ( stream == stdout && logout_file != NULL ) {
66 PHYSFS_writeBytes( logout_file, str, newline ? n + 1 : n );
68 PHYSFS_flush( logout_file );
71 if ( stream == stderr && logerr_file != NULL ) {
72 PHYSFS_writeBytes( logerr_file, str, newline ? n + 1 : n );
74 PHYSFS_flush( logerr_file );
78 n = fprintf( stream,
"%s", str );
87static int vlogprintf( FILE *stream,
int newline,
const char *fmt, va_list ap )
95 n = vsnprintf( NULL, 0, fmt, aq );
97 buf = malloc( n + 2 );
98 n = vsnprintf( buf, n + 1, fmt, ap );
116int logprintf( FILE *stream,
int newline,
const char *fmt, ... )
136 if ( !conf.redirect_file )
140 ts = localtime( &cur );
141 strftime( timestr,
sizeof( timestr ),
"%Y-%m-%d_%H-%M-%S", ts );
143 PHYSFS_mkdir(
"logs" );
144 logout_file = PHYSFS_openWrite(
"logs/stdout.txt" );
145 if ( logout_file == NULL )
146 WARN( _(
"Unable to redirect stdout to file" ) );
148 logerr_file = PHYSFS_openWrite(
"logs/stderr.txt" );
149 if ( logerr_file == NULL )
150 WARN( _(
"Unable to redirect stderr to file" ) );
152 SDL_asprintf( &
outfiledouble,
"logs/%s_stdout.txt", timestr );
153 SDL_asprintf( &errfiledouble,
"logs/%s_stderr.txt", timestr );
182 if ( copying == enable )
190 outcopy = calloc( moutcopy, BUFSIZ );
194 errcopy = calloc( merrcopy, BUFSIZ );
199 if ( noutcopy && logout_file != NULL )
202 if ( nerrcopy && logerr_file != NULL )
203 PHYSFS_writeBytes( logerr_file, errcopy, strlen( errcopy ) );
238 const char *filedouble )
245 PHYSFS_close( *file );
248 if ( PHYSFS_stat( fname, &stat ) == 0 )
251 if ( stat.filesize == 0 )
252 PHYSFS_delete( fname );
265 int len = strlen( str );
266 if ( stream == stdout ) {
267 while ( ( len + noutcopy ) >= (
int)moutcopy ) {
274 strncpy( &
outcopy[noutcopy], str, len + 1 );
276 }
else if ( stream == stderr ) {
277 while ( ( len + nerrcopy ) >= (
int)merrcopy ) {
279 errcopy = realloc( errcopy, merrcopy );
280 if ( errcopy == NULL )
284 strncpy( &errcopy[nerrcopy], str, len + 1 );
292 WARN( _(
"An error occurred while buffering %s!" ),
293 stream == stdout ?
"stdout" :
"stderr" );
299int log_warn(
const char *file,
size_t line,
const char *func,
const char *fmt,
302 static char *warn_last_msg = NULL;
303 static int warn_last_num;
310 n = vsnprintf( NULL, 0, fmt, ap );
312 buf = malloc( n + 2 );
314 n = vsnprintf( buf, n + 1, fmt, ap );
320 if ( ( warn_last_msg != NULL ) && strcmp( warn_last_msg, buf ) == 0 ) {
322 if ( warn_last_num == 10 )
324 _(
"LAST WARNING PRINTED %d TIMES, SKIPPING FROM NOW ON" ),
326 if ( warn_last_num >= 10 ) {
333 debug_logBacktrace();
336 logprintf( stderr, 0, _(
"WARNING %s:%lu [%s]: " ), file,
337 (
unsigned long)line, func );
341 free( warn_last_msg );
void log_clean(void)
Deletes useless (empty) log files from the current session.
int logprintf(FILE *stream, int newline, const char *fmt,...)
Like fprintf, but automatically teed to log files (and line-terminated if newline is true).
static void log_append(const FILE *stream, const char *str)
Appends a message to a stream's in-memory buffer.
void log_init(void)
Sets up the logging subsystem. (Calling this ensures logging output is preserved until we have a plac...
static void log_copy(int enable)
Sets up or terminates copying of standard streams into memory.
static int vlogprintf(FILE *stream, int newline, const char *fmt, va_list ap)
va_list version of logprintf and backend.
void log_redirect(void)
Sets up redirection of stdout and stderr to files. PhysicsFS must be initialized for this to work.
static void log_cleanStream(PHYSFS_File **file, const char *fname, const char *filedouble)
int log_warn(const char *file, size_t line, const char *func, const char *fmt,...)
Prints warnings, but skips if they are repeated too much.
static int slogprintf(FILE *stream, int newline, const char *str, size_t n)
va_list version of logprintf and backend.
static void log_purge(void)
Deletes copied output without printing the contents.
static char * outfiledouble
Header file with generic functions and naev-specifics.
int ndata_copyIfExists(const char *file1, const char *file2)
Copy a file, if it exists.