Documentation

Generated on Thu Aug 31 00:02:29 2006

 

Log.cpp

Go to the documentation of this file.
00001 
00002 //  $Id: Log.cpp,v 1.32 2005/08/23 19:34:02 klas Exp $
00003 //
00004 //  Usage: Logging functions etc.
00005 //
00006 //  A part of babyftpd, licensed under the GNU GPL, see the file
00007 //    LICENSE for complete information.
00009 
00010 #define LOG_CPP
00011 #define BABY_IO
00012 #include "Log.h"
00013 
00014 class Log *logging;
00015 
00016 Log::Log(void)
00017 {
00018   sem_init(&this->to_log_lock, 0, 1);
00019   pthread_cond_init(&data_ready, NULL);
00020   pthread_mutex_init(&ready_mutex, NULL);
00021 
00022   openlog("BabyFTPd", LOG_PID, LOG_FTP);
00023 }
00024 
00025 Log::~Log(void)
00026 {
00027   closelog();
00028 
00029   sem_destroy(&this->to_log_lock);
00030   pthread_cond_destroy(&this->data_ready);
00031   pthread_mutex_destroy(&this->ready_mutex);
00032 }
00033 
00034 void Log::log_this(int log_level, enum log_types log_type, string log_message)
00035 {
00036   if(log_level > config->logger.log_level && log_type != TYPE_XFER)
00037     return; // no point in pushing data that wont be logged..
00038 
00039   struct log_data temp_data = {log_level, log_type, log_message};
00040 
00041   if(temp_data.type != TYPE_XFER && config->logger.thread_id)
00042     temp_data.message += " (" + util.itos(pthread_self()) + ")";
00043 
00044   sem_wait(&this->to_log_lock);
00045   this->to_log.push_back(temp_data);
00046   sem_post(&this->to_log_lock);
00047 
00048   // bump data_ready to tell main thread there is data
00049   pthread_mutex_lock(&this->ready_mutex);
00050   pthread_cond_signal(&this->data_ready);
00051   pthread_mutex_unlock(&this->ready_mutex);
00052 }
00053 
00054 
00055 void Log::log_main(void)
00056 {
00057   setuid(config->general.user);
00058   setgid(config->general.group);
00059 
00060   size_t time_string_len;
00061 
00062   {
00063     string temp;
00064     time_string_len = util.time_string(temp, config->logger.time_format, 500);
00065     time_string_len++;
00066   }
00067 
00068   while(true)
00069   {
00070     pthread_mutex_lock(&this->ready_mutex);
00071     while(this->to_log.empty())
00072       pthread_cond_wait(&this->data_ready, &this->ready_mutex);
00073     pthread_mutex_unlock(&this->ready_mutex);
00074 
00075     sem_wait(&this->to_log_lock);
00076     struct log_data temp_data = this->to_log.front();
00077     this->to_log.erase(this->to_log.begin());
00078     sem_post(&this->to_log_lock);
00079 
00080     switch(temp_data.level)
00081     {
00082       case 0:
00083         temp_data.level = LOG_CRIT;
00084         break;
00085 
00086       case 1:
00087         temp_data.level = LOG_ERR;
00088         break;
00089 
00090       case 2:
00091         temp_data.level = LOG_WARNING;
00092         break;
00093 
00094       case 3:
00095         temp_data.level = LOG_NOTICE;
00096         break;
00097 
00098       case 4:
00099         temp_data.level = LOG_INFO;
00100         break;
00101 
00102       case 5:
00103       default: // so we get everything else as well ;)
00104         temp_data.level = LOG_DEBUG;
00105         break;
00106     }
00107 
00108     if((temp_data.type == TYPE_AUTH && !config->logger.authlog.empty()) ||
00109         (temp_data.type == TYPE_INFO && !config->logger.infolog.empty()) ||
00110         (temp_data.type == TYPE_DEBUG && !config->logger.debuglog.empty()))
00111     {
00112       string timestr;
00113       util.time_string(timestr, config->logger.time_format, time_string_len);
00114       temp_data.message.insert(0, timestr);
00115     }
00116 
00117     switch(temp_data.type)
00118     {
00119       case TYPE_XFER:
00120         this->xferlog(temp_data);
00121         break;
00122 
00123       case TYPE_AUTH:
00124         this->authlog(temp_data);
00125         break;
00126 
00127       case TYPE_INFO:
00128         this->infolog(temp_data);
00129         break;
00130 
00131       case TYPE_DEBUG:
00132         this->debuglog(temp_data);
00133         break;
00134     }
00135   }
00136 }
00137 
00138 void Log::xferlog(struct log_data data_to_log)
00139 {
00140   ofstream xstream;
00141   xstream.open(config->logger.xferlog_file.c_str(),
00142       ofstream::out | ofstream::app);
00143   if(!xstream)
00144     log_this(2, TYPE_INFO, "Failed to open xferlog file \""
00145         + config->logger.xferlog_file  + "\" for writing, check permissions.");
00146   else
00147   {
00148     xstream << data_to_log.message << endl;
00149     xstream.close();
00150   }
00151 }
00152 
00153 void Log::authlog(struct log_data data_to_log)
00154 {
00155   if(config->logger.authlog.empty())
00156     syslog(LOG_AUTHPRIV | data_to_log.level, data_to_log.message.c_str());
00157   else
00158   {
00159     ofstream astream;
00160     astream.open(config->logger.authlog.c_str(),
00161         ofstream::out | ofstream::app);
00162     if(!astream)
00163       log_this(2, TYPE_INFO, "Failed to open authlog file \""
00164           + config->logger.authlog  + "\" for writing, check permissions.");
00165     else
00166     {
00167       astream << data_to_log.message << endl;
00168       astream.close();
00169     }
00170   }
00171 }
00172 
00173 void Log::infolog(struct log_data data_to_log)
00174 {
00175   if(config->logger.infolog.empty())
00176     syslog(LOG_FTP | data_to_log.level, data_to_log.message.c_str());
00177   else
00178   {
00179     ofstream istream;
00180     istream.open(config->logger.infolog.c_str(),
00181         ofstream::out | ofstream::app);
00182     if(!istream)
00183       log_this(2, TYPE_INFO, "Failed to open infolog file \""
00184           + config->logger.infolog  + "\" for writing, check permissions.");
00185     else
00186     {
00187       istream << data_to_log.message << endl;
00188       istream.close();
00189     }
00190   }
00191 }
00192 
00193 void Log::debuglog(struct log_data data_to_log)
00194 {
00195   if(config->logger.infolog.empty())
00196     syslog(LOG_FTP | data_to_log.level, data_to_log.message.c_str());
00197   else
00198   {
00199     ofstream dstream;
00200     dstream.open(config->logger.debuglog.c_str(),
00201         ofstream::out | ofstream::app);
00202     if(!dstream)
00203       log_this(2, TYPE_INFO, "Failed to open debuglog file \""
00204           + config->logger.debuglog  + "\" for writing, check permissions.");
00205     else
00206     {
00207       dstream << data_to_log.message << endl;
00208       dstream.close();
00209     }
00210   }
00211 }