summaryrefslogtreecommitdiff
path: root/comm/error.cc
diff options
context:
space:
mode:
authorchatty1993-07-27 13:51:56 +0000
committerchatty1993-07-27 13:51:56 +0000
commit77ebaecf895b8b863e3e80382bd6ec0e18305dcd (patch)
tree4728edfef3b9b039ce3b90239a78de9eeff8b989 /comm/error.cc
parentf94a933e3eecbe4fde14183117fbc056418eeb23 (diff)
downloadivy-league-77ebaecf895b8b863e3e80382bd6ec0e18305dcd.zip
ivy-league-77ebaecf895b8b863e3e80382bd6ec0e18305dcd.tar.gz
ivy-league-77ebaecf895b8b863e3e80382bd6ec0e18305dcd.tar.bz2
ivy-league-77ebaecf895b8b863e3e80382bd6ec0e18305dcd.tar.xz
Incorporated changes from mbl@prl and mbl@europarc
Diffstat (limited to 'comm/error.cc')
-rw-r--r--comm/error.cc118
1 files changed, 108 insertions, 10 deletions
diff --git a/comm/error.cc b/comm/error.cc
index fc02eb9..aed7c0b 100644
--- a/comm/error.cc
+++ b/comm/error.cc
@@ -17,7 +17,12 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#ifdef sun
+extern "C" int rename (const char*, const char*);
+#endif
#include <stdio.h>
+#include <sys/file.h>
+#include "ccu/Time.h"
/*?class UchERROR
The set of global functions described here are designed to handle errors.
@@ -60,8 +65,13 @@ char* ErrorTable [] = {
"Subclass should implement virtual member", // ErrShouldImplement
};
-static char ProgName [128], LogFile [128];
+static char ProgName [256], LogFile [256];
static bool LogOn =FALSE;
+static int LogFd = -1;
+static off_t LogSize = 0;
+static off_t LogHalf = 0;
+
+#define LOG_HALF 25000
static errtype
DefaultHandler (errtype how, const char* /*who*/, const char* /*what*/, const char* msg)
@@ -82,7 +92,7 @@ HandleError (errtype how, const char* who, const char* what)
char *msg = MakeErrorString (how, who, what);
- if (how >= ErrLog && LogOn) {
+ if (how >= ErrLog) {
LogMessage (msg);
if (how == ErrLog)
return TRUE;
@@ -133,20 +143,77 @@ ProgramName (const char* name)
/*?
Set the log file name.
All messages are appended to the logfile.
-If \var{reset} is TRUE, the file is cleared.
-NOTE : logging is not currently implemented.
+If \var{reset} is TRUE, the file is renamed to \var{file\~}.
+If this fails, the file is simply cleared.
+If the \com{LOGDIR} environment variable is defined, and if \var{file}
+does not start with \com{/} or \com{./}, the value of \com{LOGDIR} is
+prepended to \var{file}, followed by a slash if necessary.
+Otherwise, the directory \com{$HOME/.log} is used.
?*/
void
LogfileName (const char* file, bool reset)
{
if (file) {
- strncpy (LogFile, file, sizeof (LogFile) -1);
+ if (LogOn && LogFd >= 0)
+ close (LogFd);
+ if (*file == '/' || strncmp (file, "./", 2) == 0) {
+ LogFile [0] = '\0';
+ } else {
+ // try $LOGDIR
+ char* dir = getenv ("LOGDIR");
+ if (dir) {
+ strcpy (LogFile, dir);
+ } else {
+ // try $HOME/.log
+ char* home = getenv ("HOME");
+ if (home) {
+ strcpy (LogFile, home);
+ strcat (LogFile, "/.log");
+ if (access (LogFile, F_OK) != 0) {
+ // try to create the directory
+ if (mkdir (LogFile, 0755) != 0) {
+ Error (ErrWarn, "LogFileName", "logging to /tmp directory");
+ strcpy (LogFile, "/tmp");
+ }
+ }
+ }
+ }
+ if (LogFile [strlen (LogFile) - 1] != '/')
+ strcat (LogFile, "/");
+ }
+
+ strcat (LogFile, file);
LogOn = TRUE;
+ int flags = O_RDWR | O_CREAT;
if (reset) {
- // to do: clear logfile
+ flags |= O_TRUNC;
+ // try to save previous version in LogFile~
+ if (access (LogFile, F_OK) == 0) {
+ char old [256];
+ strcpy (old, LogFile);
+ strcat (old, "~");
+ rename (LogFile, old);
+ }
+ }
+ LogFd = open (LogFile, flags, 0644);
+ if (LogFd < 0) {
+ SysError (ErrWarn, "LogfileName");
+ LogOn = FALSE;
+ } else {
+ LogHalf = 0;
+ if (reset)
+ LogSize = 0;
+ else {
+ LogSize = lseek (LogFd, 0L, 2 /*SEEK_END*/);
+ LogSize += write (LogFd, "\n", 1);
+ }
+ LogMessage ("-------- logging started --------\n");
}
- } else
+ } else {
+ if (LogOn && LogFd >= 0)
+ close (LogFd);
LogOn = FALSE;
+ }
}
/*?nodoc?*/
@@ -158,12 +225,43 @@ CleanUp (CleanUpProc)
/*?
Append a message to the logfile, if one has been specified.
-NOTE : logging is not currently implemented.
?*/
void
-LogMessage (const char*)
+LogMessage (const char* msg)
{
- // to be done
+ if (! LogOn || LogFd < 0)
+ return;
+
+ CcuTimeStamp now;
+ // format of time: Sun Sep 16 01:03:52 1973\n\0
+ // 123456789012345678901234
+ LogSize += write (LogFd, now.AsString (), 20); // strip year
+ LogSize += write (LogFd, msg, strlen (msg));
+
+ // limit the size of the log file
+ if (LogSize > LOG_HALF && LogHalf == 0)
+ LogHalf = LogSize;
+
+ if (LogSize < 2 * LOG_HALF)
+ return;
+
+ // copy bytes from LogHalf to LogSize to beginning of file
+ off_t src, dst;
+ int n;
+ char buf [4096];
+ lseek (LogFd, 0L, 0 /*SEEK_SET*/);
+ write (LogFd, "...\n", 4);
+ for (src = LogHalf, dst = 4; src < LogSize; src += n, dst += n) {
+ lseek (LogFd, src, 0 /*SEEK_SET*/);
+ n = read (LogFd, buf, sizeof (buf));
+ if (n <= 0)
+ break;
+ lseek (LogFd, dst, 0 /*SEEK_SET*/);
+ write (LogFd, buf, n);
+ }
+ lseek (LogFd, dst, 0 /*SEEK_SET*/);
+////// ftruncate (LogFd, dst); /////// this seems not to be a POSIX call
+ LogHalf = LogSize = dst;
}
/*?