home *** CD-ROM | disk | FTP | other *** search
- /*
- *
- * Title : Logger process.
- * System : Any */
- #define Version "3.0"
- /* Copyright : (c) John H. Winters
- * Date : 28th September, 1992
- * Author : John H. Winters
- *
- * Function : Logs messages to the console and several log files.
- *
- *
- * Modification history.
- *
- * Version : 2.0
- * Date : 28th September, 1992
- * Author : John H. Winters
- * Changes : Re-written to cater for prioritised messages.
- *
- * Version : 2.1
- * Date : 18th October, 1992
- * Author : John H. Winters
- * Changes : Added OS/2 PM version.
- *
- * Version : 2.2
- * Date : 13th November, 1992
- * Author : John H. Winters
- * Changes : Added the ability to handle a DROP_DEAD message on
- * logger's own queue.
- *
- * Version : 3.0
- * Date : 24th May, 1993
- * Author : John H. Winters
- * Changes : Updated for Risc OS 3.1
- *
- * Version :
- * Date :
- * Author :
- * Changes :
- *
- */
-
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <time.h>
-
- #if defined (OS2)
- #include <process.h>
- #define INCL_DOSERRORS
- #define INCL_DOSPROCESS
- #define INCL_DOSQUEUES
- #define INCL_VIO
- #include <os2.h>
- #endif
-
- #include "global.h"
-
- #if defined (ARTHUR)
- #include "winapp.h"
- #endif
-
- #include "sdf.h"
- #include "logging.h"
- #include "fe.h"
- #include "internal.h"
-
- /*
- *============================================================================
- *
- * Hash defines.
- *
- *============================================================================
- */
-
- #define MAX_FILES 5
- #define MAX_LINE 256
-
- /*
- *============================================================================
- *
- * Type definitions.
- *
- *============================================================================
- */
-
- #if defined (OS2)
- typedef union {
- t_old_msg old_msg ;
- t_NL_Header message ;
- } t_item ;
- #endif
-
- /*
- *============================================================================
- *
- * Local data.
- *
- *============================================================================
- */
-
- static u8 *FileNames [MAX_FILES] = {
- NULL,
- NULL,
- NULL,
- NULL,
- NULL
- } ;
- static uint FilesReady = FALSE ;
- #if defined (OS2)
- static HQUEUE LogQHandle = 0 ;
- #endif
- #if defined (ARTHUR)
- static uint MessageAction ;
- #endif
- static uint NumFiles = 0 ;
-
- /*
- *============================================================================
- *
- * Forward declarations.
- *
- *============================================================================
- */
-
- #if defined (OS2)
- static uint CreateQueue (void) ;
-
- static void Format (
- const U8 *taskname,
- t_LOG_Severity severity,
- const U8 *message,
- uint messagelen,
- const U8 *timestamp) ;
- #endif
-
- static void InitialiseFiles (
- #if defined (OS2)
- uint argc,
- u8 *argv []
- #else
- void
- #endif
- ) ;
-
- #if defined (ARTHUR)
- static uint IpmHandler (
- t_poll_block *poll_block,
- void *reference) ;
- #endif
-
- #if defined (OS2)
- static void LogText (
- const u8 *text,
- uint length) ;
- #endif
-
- static uint
- #if defined (OS2)
- _loadds
- #endif
- MessageHandler (
- t_LOG_Severity severity,
- const U8 *message,
- const U8 *timestamp) ;
-
- #if defined (OS2)
- static void TidyUp (void) ;
- #endif
-
- /*
- *============================================================================
- *
- * Externally visible routines.
- *
- *============================================================================
- */
-
- #if defined (OS2)
- sint main (
- uint argc,
- u8 *argv [])
-
- /*
- * Function :
- * Main routine of the logger process.
- *
- * Parameters :
- * The usual for main. Any command line parameter is
- * taken as the name of a file to log to.
- *
- * Returns :
- * EXIT_SUCCESS.
- *
- */
-
- {
- static t_item *item ;
- static USHORT itemlength ;
- t_LOG_HandlerMask mask = {{TRUE, TRUE, TRUE, TRUE, TRUE}} ;
- u8 priority ;
- QUEUERESULT queuestatus ;
- USHORT result ;
-
- atexit (TidyUp) ;
- LOG_AddHandler (mask, MessageHandler) ;
- if (argc > 1)
- {
- InitialiseFiles (argc, argv) ;
- }
- #if defined (PM)
- if ((FE_LoadResources ()) &&
- (FE_BeginProcessing ()))
- {
- #endif
- LOG_Info ("Logger version " Version " compiled on " __DATE__ " at " __TIME__ "\n") ;
- if (CreateQueue ())
- {
- LOG_Info ("Logger ready to receive log messages.\n") ;
- /*
- * Now just wait for incoming messages and log them as they
- * occur.
- */
- for (;;)
- {
- result = DosReadQueue (LogQHandle,
- &queuestatus,
- &itemlength,
- &item,
- 0,
- DCWW_WAIT,
- &priority,
- 0) ;
- if (result == 0)
- {
- /*
- * Read something. Elementary security check.
- */
- if (item == MAKEP (queuestatus.usEventCode, 0))
- {
- if (item->old_msg.header.ident == OLD_LOG_IDENT)
- {
- /*
- * This should be a message.
- */
- if (sizeof (t_old_msg_header) + item->old_msg.header.size ==
- itemlength)
- {
- LogText (item->old_msg.body,
- item->old_msg.header.size) ;
- }
- else
- {
- LOG_Warning ("Log message received with wrong length.\n") ;
- }
- }
- else if (item->message.ident == LOG_IDENT)
- {
- /*
- * New format log message.
- */
- if (item->message.format_version == FORMAT_VERSION)
- {
- if ((itemlength >= sizeof (t_NL_Header)) &&
- ((sizeof (t_NL_Header) +
- SDF_Getu16 (item->message.text_length)) ==
- itemlength))
- {
- Format (item->message.task_name,
- item->message.severity,
- (u8 *) ((&item->message) + 1),
- SDF_Getu16 (item->message.text_length),
- item->message.timestamp) ;
- }
- else
- {
- LOG_Warning ("Badly structured log message received.\n") ;
- }
- }
- else
- {
- LOG_Warning ("Log message received with unknown format version (%d).\n",
- item->message.format_version) ;
- }
- }
- else if (item->old_msg.header.ident == DROP_DEAD)
- {
- exit (EXIT_SUCCESS) ;
- }
- else
- {
- LOG_Warning ("Unknown message type - %d - received.\n",
- item->message.ident) ;
- }
- /*
- * Must deallocate the segment.
- */
- DosFreeSeg (queuestatus.usEventCode) ;
- }
- else
- {
- LOG_Warning ("Badly formatted message received.\n") ;
- }
- }
- }
- }
- #if defined (PM)
- }
- #endif
- return (EXIT_SUCCESS) ;
- }
- #endif
-
- #if defined (ARTHUR)
- uint WA_BeginProcessing (void)
-
- /*
- * Function :
- * Begin processing under Risc-OS
- *
- * Parameters :
- * None.
- *
- * Returns :
- * TRUE for success, FALSE for failure.
- *
- */
-
- {
- u8 *string ;
-
- if (FE_BeginProcessing ())
- {
- InitialiseFiles () ;
- LOG_Info ("Logger version " Version " compiled on " __DATE__ " at " __TIME__ "\n") ;
- /*
- * Now need to register for the appropriate type of incoming messages.
- */
- string = getenv ("Logger$MessNo") ;
- if (string == NULL)
- {
- LOG_Error ("Logger$MessNo is not defined. Messages cannot be received.\n") ;
- return (TRUE) ;
- }
- else
- {
- MessageAction = atoi (string) ;
- if ((MessageAction & 0x80000) == 0)
- {
- LOG_Warning ("Logger$MessNo is set to 0x%lx.\n",
- MessageAction) ;
- LOG_Warning ("This is not a suitable number for application software.\n") ;
- }
- LOG_Info ("Logger ready to receive log messages.\n") ;
- return (WA_ClaimMessage (MessageAction,
- IpmHandler,
- NULL)) ;
- }
- }
- else
- {
- return (FALSE) ;
- }
- }
-
-
- uint WA_LoadResources (void)
-
- /*
- * Function :
- * Load our resources as required.
- *
- * Parameters :
- * As received by main ().
- *
- * Returns :
- * TRUE for success, FALSE for failure.
- *
- */
-
- {
- t_LOG_HandlerMask mask = {{TRUE, TRUE, TRUE, TRUE, TRUE}} ;
-
- return ((LOG_AddHandler (mask, MessageHandler)) &&
- (FE_LoadResources ())) ;
- }
-
- #endif
-
- /*
- *============================================================================
- *
- * Forward declarations.
- *
- *============================================================================
- */
-
- #if defined (OS2)
- static uint CreateQueue (void)
-
- /*
- * Function :
- * Create a queue for other processes to write to.
- *
- * Parameters :
- * None.
- *
- * Returns :
- * TRUE if it is successfully created, FALSE otherwise.
- *
- */
-
- {
- if (DosCreateQueue (&LogQHandle,
- QUE_FIFO,
- QUEUE_NAME) == 0)
- {
- return (TRUE) ;
- }
- else
- {
- LogQHandle = 0 ;
- LOG_Error ("Failed to create a queue.\n") ;
- return (FALSE) ;
- }
- }
- #endif
-
-
- static void Format (
- const U8 *taskname,
- t_LOG_Severity severity,
- const U8 *message,
- uint messagelen,
- const U8 *timestamp)
-
- /*
- * Function :
- * Format a chunk of text and send it to the console and all
- * active log files. Note that this routine can be called
- * recursively, although not simultaneously from multiple
- * threads. (The LOGGING module guarantees only one call,
- * but it is possible that we will be called due to an
- * incoming IPM, and then call LOG_Xxxxxx, causing a second
- * call on this routine. Three calls are impossible).
- *
- * Parameters :
- * taskname Name of the task generating the message.
- * severity Severity of the message.
- * message Text of the message.
- * messagelen Length of message text.
- * timestamp Textual timestamp.
- *
- * Returns :
- * None.
- *
- */
-
- {
- u8 buffer [MAX_LINE + 2] ;
- FILE *handle ;
- uint index ;
- u8 *name ;
- static u8 severities [] = "DIWESU" ;
-
- if (LOG_MAX_TASKNAME + LOG_TIMESTAMP_LEN + 8 + messagelen > MAX_LINE)
- {
- messagelen = MAX_LINE - (LOG_MAX_TASKNAME + LOG_TIMESTAMP_LEN + 8) ;
- }
- while ((messagelen > 0) &&
- (message [messagelen - 1] == '\n'))
- {
- messagelen-- ;
- }
- if ((severity < 0) ||
- (severity > 5))
- {
- severity = 5 ;
- }
- sprintf (buffer,
- "%*.*s :%c: %*.*s : %*.*s\n",
- LOG_MAX_TASKNAME,
- LOG_MAX_TASKNAME,
- taskname,
- severities [severity],
- LOG_TIMESTAMP_LEN,
- LOG_TIMESTAMP_LEN,
- timestamp,
- messagelen,
- messagelen,
- message) ;
- #if defined (OS2)
- #if defined (PM)
- FE_PutText (buffer) ;
- #else
- /*
- * Send it to the screen.
- */
- fwrite (buffer, strlen (buffer), 1, stdout) ;
- #endif
- #endif
- #if defined (ARTHUR)
- FE_PutText (buffer) ;
- #endif
- if (FilesReady)
- {
- /*
- * Send it to the files.
- */
- for (index = 0; index < NumFiles; index++)
- {
- if (FileNames [index] != NULL)
- {
- handle = fopen (FileNames [index], "a") ;
- if (handle == NULL)
- {
- /*
- * File has failed. Recurse.
- */
- name = FileNames [index] ;
- FileNames [index] = NULL ;
- LOG_Warning ("Can't open log file \"%s\".\n",
- name) ;
- }
- else
- {
- fwrite (buffer, strlen (buffer), 1, handle) ;
- fclose (handle) ;
- }
- }
- }
- }
- }
-
-
- static void InitialiseFiles (
- #if defined (OS2)
- uint argc,
- u8 *argv []
- #else
- void
- #endif
- )
-
- /*
- * Function :
- * See which files we can open and write a date
- * stamp to each. Record the active files.
- *
- * Parameters :
- * argc \ As received by main ().
- * argv /
- *
- * Returns :
- * None, but updates the file records.
- *
- */
-
- {
- FILE *handle ;
- uint index ;
- u8 *name ;
- time_t tp ;
- #if !defined (OS2)
- u8 *temp ;
- u8 var_name [] = "Logger$FileN" ;
- #endif
-
- #if defined (OS2)
- for (index = 1; index < argc; index++)
- {
- name = malloc (strlen (argv [index]) + 1) ;
- if (name == NULL)
- {
- LOG_Error ("Can't allocate space to record log file - \"%s\".\n",
- argv [index]) ;
- }
- else
- {
- strcpy (name, argv [index]) ;
- if (NumFiles < MAX_FILES)
- {
- FileNames [NumFiles] = name ;
- NumFiles++ ;
- }
- else
- {
- LOG_Error ("Cannot log to \"%s\". Maximum log files (%d) reached.\n",
- name,
- MAX_FILES) ;
- free (name) ;
- }
- }
- }
- #else
- for (index = 0; index < MAX_FILES; index++)
- {
- var_name [strlen (var_name) - 1] = (u8) ('0' + index) ;
- name = getenv (var_name) ;
- if (name != NULL)
- {
- temp = malloc (strlen (name) + 1) ;
- if (temp == NULL)
- {
- LOG_Error ("Can't allocate space to record log file - \"%s\".\n",
- name) ;
- }
- else
- {
- strcpy (temp, name) ;
- if (NumFiles < MAX_FILES)
- {
- FileNames [NumFiles] = temp ;
- NumFiles++ ;
- }
- else
- {
- LOG_Error ("Cannot log to \"%s\". Maximum log files (%d) reached.\n",
- temp,
- MAX_FILES) ;
- free (temp) ;
- }
- }
- }
- }
- #endif
- /*
- * Now start each of the files.
- */
- for (index = 0; index < NumFiles; index++)
- {
- /*
- * Try to write a date stamp to it.
- */
- LOG_Info ("Opening log file - \"%s\".\n",
- FileNames [index]) ;
- handle = fopen (FileNames [index], "a") ;
- if (handle == NULL)
- {
- LOG_Warning ("Can't open log file - \"%s\".\n",
- FileNames [index]) ;
- free (FileNames [index]) ;
- FileNames [index] = NULL ;
- }
- else
- {
- tp = time (NULL) ;
- fprintf (handle,
- "++++++++ Log process started - %s",
- ctime (&tp)) ;
- fclose (handle) ;
- }
- }
- FilesReady = TRUE ;
- }
-
-
- #if defined (ARTHUR)
- static uint IpmHandler (
- t_poll_block *poll_block,
- void *reference)
-
- /*
- * Function :
- * Handle incoming log messages in Risc-OS.
- *
- * Parameters :
- * poll_block Poll block containing message.
- * reference Ignored.
- *
- * Returns :
- * TRUE if the message was for us, FALSE otherwise.
- *
- */
-
- {
- uint calc_size ;
- t_NL_Header *item ;
-
- reference = reference ;
- /*
- * Looks like one for us.
- */
- item = (t_NL_Header *) (poll_block->data.mb.data.bytes) ;
- calc_size = 20 + sizeof (t_NL_Header) + SDF_Getu16 (item->text_length) ;
- calc_size = (((calc_size + 3) / 4) * 4) ;
- if (poll_block->data.mb.size == calc_size)
- {
- Format (item->task_name,
- item->severity,
- (u8 *) (item + 1),
- SDF_Getu16 (item->text_length),
- item->timestamp) ;
- }
- else
- {
- LOG_Warning ("Badly formatted log message received.\n") ;
- }
- return (TRUE) ;
- }
- #endif
-
-
- #if defined (OS2)
- static void LogText (
- const u8 *text,
- uint length)
-
- /*
- * Function :
- * Send a chunk of text to the console and all
- * active log files.
- *
- * Parameters :
- * text The text to log.
- * length Length of the text.
- *
- * Returns :
- * None.
- *
- */
-
- {
- struct tm *broken_date ;
- u8 buffer [18] ;
- time_t time_now ;
-
- time_now = time (NULL) ;
- broken_date = localtime (&time_now) ;
- sprintf (buffer,
- "%02.2d/%02.2d/%02.2d %02.2d:%02.2d:%02.2d",
- broken_date->tm_mday,
- broken_date->tm_mon + 1,
- broken_date->tm_year % 100,
- broken_date->tm_hour,
- broken_date->tm_min,
- broken_date->tm_sec) ;
- Format (text,
- 5,
- text + 10,
- length - 10,
- buffer) ;
- }
- #endif
-
- #if defined (OS2)
- #include "stackoff.h"
- #endif
-
- static uint
- #if defined (OS2)
- _loadds
- #endif
- MessageHandler (
- t_LOG_Severity severity,
- const U8 *message,
- const U8 *timestamp)
-
- /*
- * Function :
- * Handle a locally generated log message.
- *
- * Parameters :
- * severity Severity of the message.
- * message Text of the message.
- * timestamp Textual timestamp for the message.
- *
- * Returns :
- * TRUE
- *
- */
-
- {
- Format ("LOGGER ",
- severity,
- message,
- strlen (message),
- timestamp) ;
- return (TRUE) ;
- }
- #if defined (OS2)
- #include "stackon.h"
- #endif
-
-
- #if defined (OS2)
- static void TidyUp (void)
-
- /*
- * Function :
- * Tidy up before process exit.
- *
- * Parameters :
- * None.
- *
- * Returns :
- * None.
- *
- */
-
- {
- if (LogQHandle != 0)
- {
- DosCloseQueue (LogQHandle) ;
- LogQHandle = 0 ;
- }
- #if defined (PM)
- FE_WindDown () ;
- #endif
- }
- #endif
-