Index: /trunk/psLib/src/sys/psLogMsg.c
===================================================================
--- /trunk/psLib/src/sys/psLogMsg.c	(revision 477)
+++ /trunk/psLib/src/sys/psLogMsg.c	(revision 477)
@@ -0,0 +1,302 @@
+/*****************************************************************************
+    A simple implementation of a logging facility for Pan-STARRS
+ *****************************************************************************/
+#include <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <time.h>
+#include <unistd.h>
+#include "psLib.h"
+
+#define MIN_LOG_LEVEL 0
+#define MAX_LOG_LEVEL 9
+static int logDest = PS_LOG_TO_STDERR; // where to log messages
+static int logLevel = PS_LOG_INFO; // log all messages at this or above
+/*****************************************************************************
+    psSetLogLevel(): Set the current log level and return old level.
+    Input:
+ level (int): the new log level.
+    Output:
+ none
+    Return:
+ The old log level.
+ *****************************************************************************/
+int psSetLogLevel(int level)
+{
+    int oldLevel = logLevel;
+
+    if ((level < MIN_LOG_LEVEL) ||
+            (level > MAX_LOG_LEVEL)) {
+        psLogMsg("logmsg", PS_LOG_WARN,
+                 "Attempt to set invalid logMsg level: %d", level);
+        level = (level < MIN_LOG_LEVEL) ? MIN_LOG_LEVEL : MAX_LOG_LEVEL;
+    }
+
+    logLevel = level;
+    return oldLevel;
+}
+
+
+/*****************************************************************************
+    psSetLogDestination(): sets the destination where log messages will be
+ sent to.
+    Input:
+ dest (int): the new log destination
+    Output:
+ None.
+    Return:
+ An integer specifying the old log destination.
+ *****************************************************************************/
+int psSetLogDestination(int dest)
+{
+    int old = logDest;
+
+    switch (dest) {
+    case PS_LOG_NONE:
+    case PS_LOG_TO_STDOUT:
+    case PS_LOG_TO_STDERR:
+        logDest = dest;
+        break;
+
+    default:
+        // GUS: Should you log this error properly?
+        fprintf(stderr,"Unknown logDestination: %d (ignored)\n", dest);
+        break;
+    }
+
+    return old;
+}
+
+
+static int log_time = 1;
+static int log_host = 1;
+static int log_level = 1;
+static int log_name = 1;
+static int log_msg = 1;
+/*****************************************************************************
+    psSetLogFormat(): Set the format of psLogMsg output.
+ 
+    More precisely, provide a string consisting of the letters
+ H (host)
+ L (level)
+ M (message)
+ N (name)
+ T (time).
+    The default is "HLMNT"
+    Input:
+ fmt: astring specifying the format.
+    Output:
+ none.
+    Return:
+ NULL.
+ *****************************************************************************/
+void psSetLogFormat(const char *fmt)
+{
+    int nlog_time = 0;
+    int nlog_host = 0;
+    int nlog_level = 0;
+    int nlog_name = 0;
+    int nlog_msg = 0;
+
+    for (const char *ptr = fmt; *ptr != '\0'; ptr++) {
+        switch (*ptr) {
+        case 'H':
+        case 'h':
+            nlog_host = 1;
+            break;
+        case 'L':
+        case 'l':
+            nlog_level = 1;
+            break;
+        case 'M':
+        case 'm':
+            nlog_msg = 1;
+            break;
+        case 'N':
+        case 'n':
+            nlog_name = 1;
+            break;
+        case 'T':
+        case 't':
+            nlog_time = 1;
+            break;
+        default:
+            psError(__func__, PS_ERR_UNKNOWN, 1,
+                    "Unknown logging keyword %c", *ptr);
+            break;
+        }
+    }
+
+    if (!nlog_msg) {
+        psTrace("utils.logMsg", 1,
+                "You must at least log error messages (You chose \"%s\")",
+                fmt);
+    }
+
+    log_host = nlog_host;
+    log_level = nlog_level;
+    log_msg = nlog_msg;
+    log_name = nlog_name;
+    log_time = nlog_time;
+}
+
+
+#if !defined(HOST_NAME_MAX)  // should be in limits.h
+#  define HOST_NAME_MAX 256
+#endif
+/*****************************************************************************
+    p_psVLogMsg(): This routine sends the message, which is a printf style
+ string specified in the "..." argument, to the current message log
+ destination with the severity specified by the "level" argument.
+    Input:
+ name
+ level
+ fmt
+ ap
+    Output:
+ none
+    Return:
+ NULL.
+ *****************************************************************************/
+void p_psVLogMsg(const char *name,
+                 int level,
+                 const char *fmt,
+                 va_list ap)
+{
+    static int first = 1;
+    static char hostname[HOST_NAME_MAX + 1];
+    char clevel;   // letter-name for level
+    char head[HOST_NAME_MAX + 40]; // yes, this is long enough
+    char *head_ptr = head;  // where we've got to in head
+    time_t clock = time(NULL);
+    struct tm *utc = gmtime(&clock);
+
+    if ((level > logLevel) ||
+            (logDest == PS_LOG_NONE)) {
+        return;
+    }
+
+    if (first) {
+        first = 0;
+        gethostname(hostname, HOST_NAME_MAX);
+    }
+
+    switch (level) {
+    case PS_LOG_ABORT:
+        clevel = 'A';
+        break;
+
+    case PS_LOG_ERROR:
+        clevel = 'E';
+        break;
+
+    case PS_LOG_WARN:
+        clevel = 'W';
+        break;
+
+    case PS_LOG_INFO:
+        clevel = 'I';
+        break;
+
+    case 4:
+    case 5:
+    case 6:
+    case 7:
+    case 8:
+    case 9:
+        clevel = level + '0';
+        break;
+
+    default:
+        psTrace("utils.logMsg", 2, "Invalid logMsg level: %d (%s)\n",
+                level, fmt);
+        level = (level < 0) ? 0 : 9;
+        break;
+    }
+
+
+    if (log_time) {
+        sprintf(head_ptr, "%4d:%02d:%02d %02d:%02d:%02dZ",
+                utc->tm_year + 1900, utc->tm_mon + 1, utc->tm_mday,
+                utc->tm_hour, utc->tm_min, utc->tm_sec);
+        head_ptr += strlen(head_ptr);
+    }
+    if (log_host) {
+        if (head_ptr > head) {
+            *head_ptr++ = '|';
+        }
+        sprintf(head_ptr, "%-20s", hostname);
+        head_ptr += strlen(head_ptr);
+    }
+    if (log_level) {
+        if (head_ptr > head) {
+            *head_ptr++ = '|';
+        }
+        sprintf(head_ptr, "%c", clevel);
+        head_ptr += strlen(head_ptr);
+    }
+    if (log_name) {
+        if (head_ptr > head) {
+            *head_ptr++ = '|';
+        }
+        sprintf(head_ptr, "%-15s", name);
+        head_ptr += strlen(head_ptr);
+    }
+    if (head_ptr > head) {
+        *head_ptr++ = '|';
+    }
+    *head_ptr = '\0';
+
+    switch (logDest) {
+    case PS_LOG_TO_STDOUT:
+        puts(head);
+        vprintf(fmt, ap);
+        if (fmt[strlen(fmt) - 1] != '\n') {
+            putc('\n', stdout);
+        }
+        break;
+
+    case PS_LOG_TO_STDERR:
+        fputs(head, stderr);
+        vfprintf(stderr, fmt, ap);
+        if (fmt[strlen(fmt) - 1] != '\n') {
+            putc('\n', stderr);
+        }
+        break;
+
+    default:
+        fprintf(stderr, "psLogMsg: You cannot get here (%s:%d)\n",
+                __FILE__, __LINE__);
+        abort();
+    }
+}
+
+
+/*****************************************************************************
+    psLogMsg(): This routine sends the message, which is a printf style
+ string specified in the "..." argument, to the current message log
+ destination with the severity specified by the "level" argument.
+    Input:
+ name: Indicates the source of this log message.
+ level: The severity of this log message.
+ fmt: The printf-stype formatted string, followed by the arguments
+  to that string.
+ ... The arguments to the above printf-style string.
+    Output:
+ none
+    Return:
+ NULL
+ *****************************************************************************/
+void psLogMsg(const char *name,
+              int level,
+              const char *fmt,
+              ...)
+{
+    va_list ap;
+
+    va_start(ap, fmt);
+    p_psVLogMsg(name, level, fmt, ap);
+    va_end(ap);
+}
Index: /trunk/psLib/src/sys/psLogMsg.h
===================================================================
--- /trunk/psLib/src/sys/psLogMsg.h	(revision 477)
+++ /trunk/psLib/src/sys/psLogMsg.h	(revision 477)
@@ -0,0 +1,44 @@
+#if !defined(PS_LOG_MSG_H)
+#define PS_LOG_MSG_H
+
+/** \file psLogMsg.h
+ *  \brief log messaging facilities
+ *  \ingroup SystemGroup
+ */
+
+#include <stdarg.h>
+
+/** Functions **************************************************************/
+/** \addtogroup SystemGroup System Utilities
+ *  \{
+ */
+
+/// Sets the log destination
+int psSetLogDestination(int dest);
+
+/// Sets the log level
+int psSetLogLevel(int level);
+
+/// sets the log format
+void psSetLogFormat(const char *fmt);
+
+/// Logs a message
+void psLogMsg(const char *name,  ///< name of the log source
+              int myLevel,   ///< severity level of this log message
+              const char *fmt, ...) ///< printf-style format command
+;
+
+/// Logs a message from varargs
+void p_psVLogMsg(const char *name, ///< name of the log source
+                 int myLevel,  ///< severity level of this log message
+                 const char *fmt,  ///< printf-style format command
+                 va_list ap)  ///< varargs argument list
+;
+
+/* \} */ // End of SystemGroup Functions
+
+enum { PS_LOG_ABORT = 0, PS_LOG_ERROR, PS_LOG_WARN, PS_LOG_INFO }; ///< Status codes for log messages
+
+enum { PS_LOG_NONE, PS_LOG_TO_STDERR, PS_LOG_TO_STDOUT }; ///< Destinations for log messages
+
+#endif
Index: /trunk/psLib/src/sysUtils/psLogMsg.c
===================================================================
--- /trunk/psLib/src/sysUtils/psLogMsg.c	(revision 477)
+++ /trunk/psLib/src/sysUtils/psLogMsg.c	(revision 477)
@@ -0,0 +1,302 @@
+/*****************************************************************************
+    A simple implementation of a logging facility for Pan-STARRS
+ *****************************************************************************/
+#include <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <time.h>
+#include <unistd.h>
+#include "psLib.h"
+
+#define MIN_LOG_LEVEL 0
+#define MAX_LOG_LEVEL 9
+static int logDest = PS_LOG_TO_STDERR; // where to log messages
+static int logLevel = PS_LOG_INFO; // log all messages at this or above
+/*****************************************************************************
+    psSetLogLevel(): Set the current log level and return old level.
+    Input:
+ level (int): the new log level.
+    Output:
+ none
+    Return:
+ The old log level.
+ *****************************************************************************/
+int psSetLogLevel(int level)
+{
+    int oldLevel = logLevel;
+
+    if ((level < MIN_LOG_LEVEL) ||
+            (level > MAX_LOG_LEVEL)) {
+        psLogMsg("logmsg", PS_LOG_WARN,
+                 "Attempt to set invalid logMsg level: %d", level);
+        level = (level < MIN_LOG_LEVEL) ? MIN_LOG_LEVEL : MAX_LOG_LEVEL;
+    }
+
+    logLevel = level;
+    return oldLevel;
+}
+
+
+/*****************************************************************************
+    psSetLogDestination(): sets the destination where log messages will be
+ sent to.
+    Input:
+ dest (int): the new log destination
+    Output:
+ None.
+    Return:
+ An integer specifying the old log destination.
+ *****************************************************************************/
+int psSetLogDestination(int dest)
+{
+    int old = logDest;
+
+    switch (dest) {
+    case PS_LOG_NONE:
+    case PS_LOG_TO_STDOUT:
+    case PS_LOG_TO_STDERR:
+        logDest = dest;
+        break;
+
+    default:
+        // GUS: Should you log this error properly?
+        fprintf(stderr,"Unknown logDestination: %d (ignored)\n", dest);
+        break;
+    }
+
+    return old;
+}
+
+
+static int log_time = 1;
+static int log_host = 1;
+static int log_level = 1;
+static int log_name = 1;
+static int log_msg = 1;
+/*****************************************************************************
+    psSetLogFormat(): Set the format of psLogMsg output.
+ 
+    More precisely, provide a string consisting of the letters
+ H (host)
+ L (level)
+ M (message)
+ N (name)
+ T (time).
+    The default is "HLMNT"
+    Input:
+ fmt: astring specifying the format.
+    Output:
+ none.
+    Return:
+ NULL.
+ *****************************************************************************/
+void psSetLogFormat(const char *fmt)
+{
+    int nlog_time = 0;
+    int nlog_host = 0;
+    int nlog_level = 0;
+    int nlog_name = 0;
+    int nlog_msg = 0;
+
+    for (const char *ptr = fmt; *ptr != '\0'; ptr++) {
+        switch (*ptr) {
+        case 'H':
+        case 'h':
+            nlog_host = 1;
+            break;
+        case 'L':
+        case 'l':
+            nlog_level = 1;
+            break;
+        case 'M':
+        case 'm':
+            nlog_msg = 1;
+            break;
+        case 'N':
+        case 'n':
+            nlog_name = 1;
+            break;
+        case 'T':
+        case 't':
+            nlog_time = 1;
+            break;
+        default:
+            psError(__func__, PS_ERR_UNKNOWN, 1,
+                    "Unknown logging keyword %c", *ptr);
+            break;
+        }
+    }
+
+    if (!nlog_msg) {
+        psTrace("utils.logMsg", 1,
+                "You must at least log error messages (You chose \"%s\")",
+                fmt);
+    }
+
+    log_host = nlog_host;
+    log_level = nlog_level;
+    log_msg = nlog_msg;
+    log_name = nlog_name;
+    log_time = nlog_time;
+}
+
+
+#if !defined(HOST_NAME_MAX)  // should be in limits.h
+#  define HOST_NAME_MAX 256
+#endif
+/*****************************************************************************
+    p_psVLogMsg(): This routine sends the message, which is a printf style
+ string specified in the "..." argument, to the current message log
+ destination with the severity specified by the "level" argument.
+    Input:
+ name
+ level
+ fmt
+ ap
+    Output:
+ none
+    Return:
+ NULL.
+ *****************************************************************************/
+void p_psVLogMsg(const char *name,
+                 int level,
+                 const char *fmt,
+                 va_list ap)
+{
+    static int first = 1;
+    static char hostname[HOST_NAME_MAX + 1];
+    char clevel;   // letter-name for level
+    char head[HOST_NAME_MAX + 40]; // yes, this is long enough
+    char *head_ptr = head;  // where we've got to in head
+    time_t clock = time(NULL);
+    struct tm *utc = gmtime(&clock);
+
+    if ((level > logLevel) ||
+            (logDest == PS_LOG_NONE)) {
+        return;
+    }
+
+    if (first) {
+        first = 0;
+        gethostname(hostname, HOST_NAME_MAX);
+    }
+
+    switch (level) {
+    case PS_LOG_ABORT:
+        clevel = 'A';
+        break;
+
+    case PS_LOG_ERROR:
+        clevel = 'E';
+        break;
+
+    case PS_LOG_WARN:
+        clevel = 'W';
+        break;
+
+    case PS_LOG_INFO:
+        clevel = 'I';
+        break;
+
+    case 4:
+    case 5:
+    case 6:
+    case 7:
+    case 8:
+    case 9:
+        clevel = level + '0';
+        break;
+
+    default:
+        psTrace("utils.logMsg", 2, "Invalid logMsg level: %d (%s)\n",
+                level, fmt);
+        level = (level < 0) ? 0 : 9;
+        break;
+    }
+
+
+    if (log_time) {
+        sprintf(head_ptr, "%4d:%02d:%02d %02d:%02d:%02dZ",
+                utc->tm_year + 1900, utc->tm_mon + 1, utc->tm_mday,
+                utc->tm_hour, utc->tm_min, utc->tm_sec);
+        head_ptr += strlen(head_ptr);
+    }
+    if (log_host) {
+        if (head_ptr > head) {
+            *head_ptr++ = '|';
+        }
+        sprintf(head_ptr, "%-20s", hostname);
+        head_ptr += strlen(head_ptr);
+    }
+    if (log_level) {
+        if (head_ptr > head) {
+            *head_ptr++ = '|';
+        }
+        sprintf(head_ptr, "%c", clevel);
+        head_ptr += strlen(head_ptr);
+    }
+    if (log_name) {
+        if (head_ptr > head) {
+            *head_ptr++ = '|';
+        }
+        sprintf(head_ptr, "%-15s", name);
+        head_ptr += strlen(head_ptr);
+    }
+    if (head_ptr > head) {
+        *head_ptr++ = '|';
+    }
+    *head_ptr = '\0';
+
+    switch (logDest) {
+    case PS_LOG_TO_STDOUT:
+        puts(head);
+        vprintf(fmt, ap);
+        if (fmt[strlen(fmt) - 1] != '\n') {
+            putc('\n', stdout);
+        }
+        break;
+
+    case PS_LOG_TO_STDERR:
+        fputs(head, stderr);
+        vfprintf(stderr, fmt, ap);
+        if (fmt[strlen(fmt) - 1] != '\n') {
+            putc('\n', stderr);
+        }
+        break;
+
+    default:
+        fprintf(stderr, "psLogMsg: You cannot get here (%s:%d)\n",
+                __FILE__, __LINE__);
+        abort();
+    }
+}
+
+
+/*****************************************************************************
+    psLogMsg(): This routine sends the message, which is a printf style
+ string specified in the "..." argument, to the current message log
+ destination with the severity specified by the "level" argument.
+    Input:
+ name: Indicates the source of this log message.
+ level: The severity of this log message.
+ fmt: The printf-stype formatted string, followed by the arguments
+  to that string.
+ ... The arguments to the above printf-style string.
+    Output:
+ none
+    Return:
+ NULL
+ *****************************************************************************/
+void psLogMsg(const char *name,
+              int level,
+              const char *fmt,
+              ...)
+{
+    va_list ap;
+
+    va_start(ap, fmt);
+    p_psVLogMsg(name, level, fmt, ap);
+    va_end(ap);
+}
Index: /trunk/psLib/src/sysUtils/psLogMsg.h
===================================================================
--- /trunk/psLib/src/sysUtils/psLogMsg.h	(revision 477)
+++ /trunk/psLib/src/sysUtils/psLogMsg.h	(revision 477)
@@ -0,0 +1,44 @@
+#if !defined(PS_LOG_MSG_H)
+#define PS_LOG_MSG_H
+
+/** \file psLogMsg.h
+ *  \brief log messaging facilities
+ *  \ingroup SystemGroup
+ */
+
+#include <stdarg.h>
+
+/** Functions **************************************************************/
+/** \addtogroup SystemGroup System Utilities
+ *  \{
+ */
+
+/// Sets the log destination
+int psSetLogDestination(int dest);
+
+/// Sets the log level
+int psSetLogLevel(int level);
+
+/// sets the log format
+void psSetLogFormat(const char *fmt);
+
+/// Logs a message
+void psLogMsg(const char *name,  ///< name of the log source
+              int myLevel,   ///< severity level of this log message
+              const char *fmt, ...) ///< printf-style format command
+;
+
+/// Logs a message from varargs
+void p_psVLogMsg(const char *name, ///< name of the log source
+                 int myLevel,  ///< severity level of this log message
+                 const char *fmt,  ///< printf-style format command
+                 va_list ap)  ///< varargs argument list
+;
+
+/* \} */ // End of SystemGroup Functions
+
+enum { PS_LOG_ABORT = 0, PS_LOG_ERROR, PS_LOG_WARN, PS_LOG_INFO }; ///< Status codes for log messages
+
+enum { PS_LOG_NONE, PS_LOG_TO_STDERR, PS_LOG_TO_STDOUT }; ///< Destinations for log messages
+
+#endif
