log.c

Go to the documentation of this file.
00001 /* Logging routines.
00002  *
00003  * (C) 2003-2008 Anope Team
00004  * Contact us at info@anope.org
00005  *
00006  * Please read COPYING and README for further details.
00007  *
00008  * Based on the original code of Epona by Lara.
00009  * Based on the original code of Services by Andy Church. 
00010  * 
00011  * $Id: log.c 1345 2008-01-13 12:54:14Z geniusdex $ 
00012  *
00013  */
00014 
00015 #include "services.h"
00016 #include "pseudo.h"
00017 
00018 static FILE *logfile;
00019 
00020 static int curday = 0;
00021 
00022 /*************************************************************************/
00023 
00024 static int get_logname(char *name, int count, struct tm *tm)
00025 {
00026     char timestamp[32];
00027     time_t t;
00028 
00029 
00030     if (!tm) {
00031         time(&t);
00032         tm = localtime(&t);
00033     }
00034 
00035     /* fix bug 577 */
00036     strftime(timestamp, sizeof(timestamp), "%Y%m%d", tm);
00037     snprintf(name, count, "logs/%s.%s", log_filename, timestamp);
00038     curday = tm->tm_yday;
00039 
00040     return 1;
00041 }
00042 
00043 /*************************************************************************/
00044 
00045 static void remove_log(void)
00046 {
00047     time_t t;
00048     struct tm tm;
00049 
00050     char name[PATH_MAX];
00051 
00052     if (!KeepLogs)
00053         return;
00054 
00055     time(&t);
00056     t -= (60 * 60 * 24 * KeepLogs);
00057     tm = *localtime(&t);
00058 
00059     /* removed if from here cause get_logchan is always 1 */
00060     get_logname(name, sizeof(name), &tm);
00061 #ifndef _WIN32
00062     unlink(name);
00063 #else
00064     DeleteFile(name);
00065 #endif
00066 }
00067 
00068 /*************************************************************************/
00069 
00070 static void checkday(void)
00071 {
00072     time_t t;
00073     struct tm tm;
00074 
00075     time(&t);
00076     tm = *localtime(&t);
00077 
00078     if (curday != tm.tm_yday) {
00079         close_log();
00080         remove_log();
00081         open_log();
00082     }
00083 }
00084 
00085 /*************************************************************************/
00086 
00087 /* Open the log file.  Return -1 if the log file could not be opened, else
00088  * return 0. */
00089 
00090 int open_log(void)
00091 {
00092     char name[PATH_MAX];
00093 
00094     if (logfile)
00095         return 0;
00096 
00097     /* if removed again.. get_logname is always 1 */
00098     get_logname(name, sizeof(name), NULL);
00099     logfile = fopen(name, "a");
00100 
00101     if (logfile)
00102         setbuf(logfile, NULL);
00103     return logfile != NULL ? 0 : -1;
00104 }
00105 
00106 /*************************************************************************/
00107 
00108 /* Close the log file. */
00109 
00110 void close_log(void)
00111 {
00112     if (!logfile)
00113         return;
00114     fclose(logfile);
00115     logfile = NULL;
00116 }
00117 
00118 /*************************************************************************/
00119 
00120 /* added cause this is used over and over in the code */
00121 char *log_gettimestamp(void)
00122 {
00123     time_t t;
00124     struct tm tm;
00125     static char tbuf[256];
00126 
00127     time(&t);
00128     tm = *localtime(&t);
00129 #if HAVE_GETTIMEOFDAY
00130     if (debug) {
00131         char *s;
00132         struct timeval tv;
00133         gettimeofday(&tv, NULL);
00134         strftime(tbuf, sizeof(tbuf) - 1, "[%b %d %H:%M:%S", &tm);
00135         s = tbuf + strlen(tbuf);
00136         s += snprintf(s, sizeof(tbuf) - (s - tbuf), ".%06d",
00137                       (int) tv.tv_usec);
00138         strftime(s, sizeof(tbuf) - (s - tbuf) - 1, " %Y]", &tm);
00139     } else {
00140 #endif
00141         strftime(tbuf, sizeof(tbuf) - 1, "[%b %d %H:%M:%S %Y]", &tm);
00142 #if HAVE_GETTIMEOFDAY
00143     }
00144 #endif
00145     return tbuf;
00146 }
00147 
00148 /*************************************************************************/
00149 
00150 /* Log stuff to the log file with a datestamp.  Note that errno is
00151  * preserved by this routine and log_perror().
00152  */
00153 
00154 void alog(const char *fmt, ...)
00155 {
00156     va_list args;
00157     char *buf;
00158     int errno_save = errno;
00159     char str[BUFSIZE];
00160 
00161     checkday();
00162 
00163     if (!fmt) {
00164         return;
00165     }
00166 
00167     va_start(args, fmt);
00168     vsnprintf(str, sizeof(str), fmt, args);
00169     va_end(args);
00170 
00171     buf = log_gettimestamp();
00172 
00173     if (logfile) {
00174         fprintf(logfile, "%s %s\n", buf, str);
00175     }
00176     if (nofork) {
00177         fprintf(stderr, "%s %s\n", buf, str);
00178     }
00179     if (LogChannel && logchan && !debug && findchan(LogChannel)) {
00180         privmsg(s_GlobalNoticer, LogChannel, "%s", str);
00181     }
00182     errno = errno_save;
00183 }
00184 
00185 /*************************************************************************/
00186 
00187 /* Like alog(), but tack a ": " and a system error message (as returned by
00188  * strerror()) onto the end.
00189  */
00190 
00191 void log_perror(const char *fmt, ...)
00192 {
00193     va_list args;
00194     char *buf;
00195     int errno_save = errno;
00196     char str[BUFSIZE];
00197 
00198     checkday();
00199 
00200     if (!fmt) {
00201         return;
00202     }
00203 
00204     va_start(args, fmt);
00205     vsnprintf(str, sizeof(str), fmt, args);
00206     va_end(args);
00207 
00208     buf = log_gettimestamp();
00209 
00210     if (logfile) {
00211         fprintf(logfile, "%s %s : %s\n", buf, str, strerror(errno_save));
00212     }
00213     if (nofork) {
00214         fprintf(stderr, "%s %s : %s\n", buf, str, strerror(errno_save));
00215     }
00216     errno = errno_save;
00217 }
00218 
00219 /*************************************************************************/
00220 
00221 /* We've hit something we can't recover from.  Let people know what
00222  * happened, then go down.
00223  */
00224 
00225 void fatal(const char *fmt, ...)
00226 {
00227     va_list args;
00228     char *buf;
00229     char buf2[4096];
00230 
00231     checkday();
00232 
00233     if (!fmt) {
00234         return;
00235     }
00236 
00237     va_start(args, fmt);
00238     vsnprintf(buf2, sizeof(buf2), fmt, args);
00239     va_end(args);
00240 
00241     buf = log_gettimestamp();
00242 
00243     if (logfile)
00244         fprintf(logfile, "%s FATAL: %s\n", buf, buf2);
00245     if (nofork)
00246         fprintf(stderr, "%s FATAL: %s\n", buf, buf2);
00247     if (servsock >= 0)
00248         anope_cmd_global(NULL, "FATAL ERROR!  %s", buf2);
00249 
00250     /* one of the many places this needs to be called from */
00251     ModuleRunTimeDirCleanUp();
00252 
00253     exit(1);
00254 }
00255 
00256 /*************************************************************************/
00257 
00258 /* Same thing, but do it like perror(). */
00259 
00260 void fatal_perror(const char *fmt, ...)
00261 {
00262     va_list args;
00263     char *buf;
00264     char buf2[4096];
00265     int errno_save = errno;
00266 
00267     checkday();
00268 
00269     if (!fmt) {
00270         return;
00271     }
00272 
00273     va_start(args, fmt);
00274     vsnprintf(buf2, sizeof(buf2), fmt, args);
00275     va_end(args);
00276 
00277     buf = log_gettimestamp();
00278 
00279     if (logfile)
00280         fprintf(logfile, "%s FATAL: %s: %s\n", buf, buf2,
00281                 strerror(errno_save));
00282     if (nofork)
00283         fprintf(stderr, "%s FATAL: %s: %s\n", buf, buf2,
00284                 strerror(errno_save));
00285     if (servsock >= 0)
00286         anope_cmd_global(NULL, "FATAL ERROR!  %s: %s", buf2,
00287                          strerror(errno_save));
00288 
00289     /* one of the many places this needs to be called from */
00290     ModuleRunTimeDirCleanUp();
00291 
00292     exit(1);
00293 }
00294 
00295 /*************************************************************************/
00296 
00297 /* Same thing, but do it like perror(). 
00298  * This is for socket errors. On *nix, it works just like fatal_perror,
00299  * on Win32, it uses the socket error code and formatting functions.
00300  */
00301 
00302 void fatal_sockerror(const char *fmt, ...)
00303 {
00304     va_list args;
00305     char *buf;
00306     char buf2[4096];
00307     int errno_save = ano_sockgeterr();
00308 
00309     if (!fmt) {
00310         return;
00311     }
00312 
00313     checkday();
00314 
00315     /* this will fix 581 */
00316     va_start(args, fmt);
00317     vsnprintf(buf2, sizeof(buf2), fmt, args);
00318     va_end(args);
00319 
00320     buf = log_gettimestamp();
00321 
00322     if (logfile)
00323         fprintf(logfile, "%s FATAL: %s: %s\n", buf, buf2,
00324                 ano_sockstrerror(errno_save));
00325     if (stderr)
00326         fprintf(stderr, "%s FATAL: %s: %s\n", buf, buf2,
00327                 ano_sockstrerror(errno_save));
00328     if (servsock >= 0)
00329         anope_cmd_global(NULL, "FATAL ERROR!  %s: %s", buf2,
00330                          strerror(errno_save));
00331 
00332     /* one of the many places this needs to be called from */
00333     ModuleRunTimeDirCleanUp();
00334 
00335     exit(1);
00336 }

Generated on Sun Oct 5 09:06:56 2008 for Anope by  doxygen 1.5.7.1