/* * This file is part of rasdaman community. * * Rasdaman community is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Rasdaman community is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with rasdaman community. If not, see . * * Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / rasdaman GmbH. * * For more information please see * or contact Peter Baumann via . */ /*------------------------------------------------------------------------*/ /* logging.c - logging and error message handling. */ /*------------------------------------------------------------------------*/ #include "defs.h" #include "protos.h" #include "server.h" extern struct Logging *LogBase; rc_t OpenLog( struct Logging *Log, char *AccessLog, char *ServerLog, char *CommLog ) { /* removed this, we don't need this logs if( (Log->Mode & LF_STDERR) == LF_STDERR ) // Log to STDOUT/STDERR ? { Log->Access.Filename = NULL; Log->Access.FD = STDOUT_FILENO; Log->Access.State = FILE_OPEN; Log->Server.Filename = NULL; Log->Server.FD = STDERR_FILENO; Log->Server.State = FILE_OPEN; Log->Comm.Filename = NULL; Log->Comm.FD = STDOUT_FILENO; Log->Comm.State = FILE_OPEN; } else { Log->Access.Filename = AccessLog; if( AccessLog != NULL ) { Log->Access.FD = open( Log->Access.Filename, O_WRONLY | O_CREAT | O_APPEND, FILE_MODE ); if( Log->Server.FD < 0 ) ErrorMsg( E_SYS, FAIL, "FAIL: Open AccessLog failed." ); Log->Access.State = FILE_OPEN; } else { Log->Access.State = FILE_CLOSED; } Log->Server.Filename = ServerLog; if( ServerLog != NULL ) { Log->Server.FD = open( Log->Server.Filename, O_WRONLY | O_CREAT | O_APPEND, FILE_MODE ); if( Log->Server.FD < 0 ) ErrorMsg( E_SYS, FAIL, "FAIL: Open ServerLog failed." ); Log->Server.State = FILE_OPEN; } else { Log->Server.State = FILE_CLOSED; } } */ Log->Server.State = FILE_CLOSED; Log->Access.State = FILE_CLOSED; Log->Comm.State = FILE_CLOSED; return( OK ); } void CloseLog( struct Logging *Log ) { //close( Log->Server.FD ); Log->Server.State = FILE_CLOSED; //close( Log->Access.FD ); Log->Access.State = FILE_CLOSED; } void ErrorMsg( int errnoFlag, int ErrLevel, const char *ErrMsg, ... ) { int errno_save; char ErrMsgBuffer[ MAXLINELEN ]; size_t StringSize, BuffSize; va_list ArgPtr; errno_save = errno; va_start( ArgPtr, ErrMsg ); if( VSNPrintf( ErrMsgBuffer, MAXLINELEN, ErrMsg, ArgPtr ) < 0) ErrorMsg( E_PRIV, WARN, "WARN: Log message exceeded buffer size!" ); va_end( ArgPtr ); StringSize = strlen( ErrMsgBuffer ); BuffSize = MAXLINELEN - StringSize; if( errnoFlag ) { if( SNPrintf( ErrMsgBuffer + StringSize, &BuffSize, " Reason: %s", StrError( errno_save ) ) < 0) { ErrorMsg( E_PRIV, WARN, "WARN: Log message exceeded buffer size!" ); } } LogMsg( LG_SERVER, ErrLevel, ErrMsgBuffer ); switch( ErrLevel ) { case DUMP: { abort(); /* core dump erzeugen und beenden */ exit( DUMP ); /* sollte nicht soweit kommen... */ } break; case FAIL: { exit( FAIL ); /* Ausstieg mit Status "FAIL". */ } break; default: return; } } void LogMsg( int SubSys, int Level, const char *Msg, ... ) { return; /* char MsgBuffer[ MAXLINELEN ]; char *BufferPtr; size_t BuffSize = MAXLINELEN; size_t TimeBuffSize = DATE_BUFFSIZE; va_list ArgPtr; if( (Level == DEBUG) && ((LogBase->Mode & LF_VERB) == 0) ) // DEBUG Msgs wanted? return; bzero( MsgBuffer, MAXLINELEN ); BufferPtr = &MsgBuffer[0]; // ### HACK! access.log datestamp is already in msg string! if( SubSys != LG_ACCESS ) { LogDate( BufferPtr, TimeBuffSize ); strcat( BufferPtr, " " ); } if( SubSys == LG_SERVER ) { BufferPtr = &MsgBuffer[0] + strlen( MsgBuffer ); sprintf( BufferPtr, "<%d> ", getpid() ); } BufferPtr = &MsgBuffer[0] + strlen( MsgBuffer ); BuffSize = MAXLINELEN - strlen( MsgBuffer ) - 2; va_start( ArgPtr, Msg ); if( VSNPrintf( BufferPtr, BuffSize , Msg, ArgPtr ) < 0) ErrorMsg( E_PRIV, WARN, "WARN: Log message exceeded buffer size!" ); va_end( ArgPtr ); // Log-Meldungen sollten immer ein am Ende haben. // Also kontrollieren und nötigenfalls ergänzen. // Da MsgBuffer mit maximal MAXLINELEN - 2 Zeichen gefüllt sein // sollte, kann gefahrlos angehängt werden. if( MsgBuffer[ strlen( MsgBuffer ) - 1 ] != '\n' ) strcat( MsgBuffer, "\n" ); // Moeglichkeiten: // stdio offen, Server.Log nicht initialisiert // stdio offen, Server.Log initialisiert (Log auf stdio) // stdio geschlossen, Server.Log initialisiert (Log in File) switch( SubSys ) { case LG_SERVER: if( LogBase->Server.State == FILE_OPEN ) write( LogBase->Server.FD, MsgBuffer, strlen( MsgBuffer ) ); else write( STDERR_FILENO, MsgBuffer, strlen( MsgBuffer ) ); break; case LG_ACCESS: if( LogBase->Access.State == FILE_OPEN ) write( LogBase->Access.FD, MsgBuffer, strlen( MsgBuffer ) ); else write( STDOUT_FILENO, Msg, strlen( MsgBuffer ) ); break; case LG_COMM: if( LogBase->Comm.State == FILE_OPEN ) write( LogBase->Comm.FD, MsgBuffer, strlen( MsgBuffer ) ); else write( STDOUT_FILENO, Msg, strlen( MsgBuffer ) ); break; default: ErrorMsg( E_PRIV, WARN, "WARN: Unknown Logging sub-system!" ); } */ return; } rc_t LogDate( char *Buffer, int BuffSize ) { struct tm *ltime; int TZoffset; char sign; size_t strsize; size_t RestSize; ltime = Get_GMToffset( &TZoffset ); /* LOG Date Format: "[dd/mmm/yyyy:HH:MM:SS {-|+}XXXX]" */ /* XXXX = Timezone offset format: HHMM */ sign = ( TZoffset < 0 ? '-' : '+' ); if( TZoffset < 0 ) TZoffset = -TZoffset; strsize = strftime( Buffer, BuffSize, "[%d/%b/%Y:%H:%M:%S ", ltime ); if( strsize >= BuffSize-6 || strsize == 0 ) return( ERROR ); else { RestSize = BuffSize-strsize; SNPrintf( Buffer+strsize, &RestSize, "%c%.2d%.2d]", sign, TZoffset/60, TZoffset%60 ); return( OK ); } } /****** logging/Get_GMToffset ************************************************ * * NAME * Get_GMToffset -- Get numerical offset of localtime to gmtime. * * SYNOPSIS * * * FUNCTION * * * INPUTS * * * RESULT * * * NOTES * Source code taken from Apache 1.3.1 distribution. * * BUGS * * * SEE ALSO * * ****************************************************************************** * */ struct tm *Get_GMToffset( int *tz ) { time_t tt = time(NULL); struct tm gmt; struct tm *t; int days, hours, minutes; /* Assume we are never more than 24 hours away. */ gmt = *gmtime(&tt); /* remember gmtime/localtime return ptr to static */ t = localtime(&tt); /* buffer... so be careful */ days = t->tm_yday - gmt.tm_yday; hours = ((days < -1 ? 24 : 1 < days ? -24 : days * 24) + t->tm_hour - gmt.tm_hour); minutes = hours * 60 + t->tm_min - gmt.tm_min; *tz = minutes; return( t ); }