Diff for /freem/src/log.c between versions 1.2 and 1.14

version 1.2, 2025/03/08 06:11:05 version 1.14, 2025/05/14 12:22:04
Line 1 Line 1
 /*  /*
  *                            *   *   $Id$
  *                           * *   *    freem error logging
  *                          *   *  
  *                     ***************  
  *                      * *       * *  
  *                       *  MUMPS  *  
  *                      * *       * *  
  *                     ***************  
  *                          *   *  
  *                           * *  
  *                            *  
  *  
  *   log.c  
  *        freem error logging  
  *   *
  *     *  
  *   Author: Serena Willis <jpw@coherent-logic.com>   *   Author: Serena Willis <snw@coherent-logic.com>
  *    Copyright (C) 1998 MUG Deutschland   *    Copyright (C) 1998 MUG Deutschland
  *    Copyright (C) 2020 Coherent Logic Development LLC   *    Copyright (C) 2020, 2025 Coherent Logic Development LLC
  *   *
  *   *
  *   This file is part of FreeM.   *   This file is part of FreeM.
Line 35 Line 23
  *   You should have received a copy of the GNU Affero Public License   *   You should have received a copy of the GNU Affero Public License
  *   along with FreeM.  If not, see <https://www.gnu.org/licenses/>.   *   along with FreeM.  If not, see <https://www.gnu.org/licenses/>.
  *   *
    *   $Log$
    *   Revision 1.14  2025/05/14 12:22:04  snw
    *   Further work on shared memory
    *
    *   Revision 1.13  2025/04/16 17:36:12  snw
    *   Add FreeBSD shm cleanup script
    *
    *   Revision 1.12  2025/04/15 16:49:36  snw
    *   Make use of logprintf throughout codebase
    *
    *   Revision 1.11  2025/04/15 14:56:20  snw
    *   Fix broken build due to missing declarations
    *
    *   Revision 1.10  2025/04/15 14:39:06  snw
    *   Further improvements to logging
    *
    *   Revision 1.9  2025/04/15 02:24:43  snw
    *   Improve FreeM logging capabilities
    *
    *   Revision 1.8  2025/04/04 02:12:25  snw
    *   Bump to 0.63.0-rc5 and make sure m_log function is never empty
    *
    *   Revision 1.7  2025/04/04 01:18:21  snw
    *   Remove vestigial logging code and bump to 0.63.0-rc4
    *
    *   Revision 1.6  2025/04/01 23:21:45  snw
    *   fmadm commands for stopping, starting, and restarting environments now functional
    *
    *   Revision 1.5  2025/04/01 20:11:46  snw
    *   Further work on fmadm
    *
    *   Revision 1.4  2025/03/09 19:50:47  snw
    *   Second phase of REUSE compliance and header reformat
    *
    *
    * SPDX-FileCopyrightText:  (C) 2025 Coherent Logic Development LLC
    * SPDX-License-Identifier: AGPL-3.0-or-later
  **/   **/
   
 #include <stdio.h>  #include <stdio.h>
Line 43 Line 68
 # include <syslog.h>  # include <syslog.h>
 #endif  #endif
 #include <stdlib.h>  #include <stdlib.h>
   #include <stdarg.h>
   #include <unistd.h>
   
   #if defined(USE_SYS_TIME_H) && !defined(MSDOS) && !defined(__osf__)
   # include <sys/time.h>
   #else
   # include <time.h> 
   #endif
   
 #include "mpsdef.h"  #include "mpsdef.h"
   #include "log.h" /* for logging constants */
   #include "init.h" /* for cleanup() */
   #include "iniconf.h" /* for read_profile_string() */
   #include "shmmgr.h" /* for shm_exit() */
   
   short log_threshold_file;
   short log_threshold_syslog;
   short log_threshold_stderr;
   
   
   void init_log(void)
   {
       char buf[4096];
       char *env_value;
       
       if (read_profile_string (env_config_file, shm_env, "log_threshold_file", buf) == TRUE) {
           if (strcmp (buf, "debug") == 0) {
               log_threshold_file = FM_LOG_DEBUG;
           }
           else if (strcmp (buf, "info") == 0) {
               log_threshold_file = FM_LOG_INFO;
           }
           else if (strcmp (buf, "warning") == 0) {
               log_threshold_file = FM_LOG_WARNING;
           }
           else if (strcmp (buf, "error") == 0) {
               log_threshold_file = FM_LOG_ERROR;
           }
           else if (strcmp (buf, "fatal") == 0) {
               log_threshold_file = FM_LOG_FATAL;
           }
           else {
               log_threshold_file = FM_LOG_INFO;
           }
       }
       else {
           log_threshold_file = FM_LOG_INFO;
       }
   
       if (read_profile_string (env_config_file, shm_env, "log_threshold_syslog", buf) == TRUE) {
           if (strcmp (buf, "debug") == 0) {
               log_threshold_syslog = FM_LOG_DEBUG;
           }
           else if (strcmp (buf, "info") == 0) {
               log_threshold_syslog = FM_LOG_INFO;
           }
           else if (strcmp (buf, "warning") == 0) {
               log_threshold_syslog = FM_LOG_WARNING;
           }
           else if (strcmp (buf, "error") == 0) {
               log_threshold_syslog = FM_LOG_ERROR;
           }
           else if (strcmp (buf, "fatal") == 0) {
               log_threshold_syslog = FM_LOG_FATAL;
           }
           else {
               log_threshold_syslog = FM_LOG_INFO;
           }
       }
       else {
           log_threshold_syslog = FM_LOG_INFO;
       }
   
       if (read_profile_string (env_config_file, shm_env, "log_threshold_stderr", buf) == TRUE) {
           if (strcmp (buf, "debug") == 0) {
               log_threshold_stderr = FM_LOG_DEBUG;
           }
           else if (strcmp (buf, "info") == 0) {
               log_threshold_stderr = FM_LOG_INFO;
           }
           else if (strcmp (buf, "warning") == 0) {
               log_threshold_stderr = FM_LOG_WARNING;
           }
           else if (strcmp (buf, "error") == 0) {
               log_threshold_stderr = FM_LOG_ERROR;
           }
           else if (strcmp (buf, "fatal") == 0) {
               log_threshold_stderr = FM_LOG_FATAL;
           }
           else {
               log_threshold_stderr = FM_LOG_INFO;
           }
       }
       else {
           log_threshold_stderr = FM_LOG_WARNING;
       }
   
       if ((env_value = getenv ("FREEM_LOG_THRESHOLD_FILE")) != NULL) {
           if (strcmp (env_value, "debug") == 0) {
               log_threshold_file = FM_LOG_DEBUG;
           }
           else if (strcmp (env_value, "info") == 0) {
               log_threshold_file = FM_LOG_INFO;
           }
           else if (strcmp (env_value, "warning") == 0) {
               log_threshold_file = FM_LOG_WARNING;
           }
           else if (strcmp (env_value, "error") == 0) {
               log_threshold_file = FM_LOG_ERROR;
           }
           else if (strcmp (env_value, "fatal") == 0) {
               log_threshold_file = FM_LOG_FATAL;
           }
           else {
               log_threshold_file = FM_LOG_INFO;
           }
       }
   
       if ((env_value = getenv ("FREEM_LOG_THRESHOLD_SYSLOG")) != NULL) {
           if (strcmp (env_value, "debug") == 0) {
               log_threshold_syslog = FM_LOG_DEBUG;
           }
           else if (strcmp (env_value, "info") == 0) {
               log_threshold_syslog = FM_LOG_INFO;
           }
           else if (strcmp (env_value, "warning") == 0) {
               log_threshold_syslog = FM_LOG_WARNING;
           }
           else if (strcmp (env_value, "error") == 0) {
               log_threshold_syslog = FM_LOG_ERROR;
           }
           else if (strcmp (env_value, "fatal") == 0) {
               log_threshold_syslog = FM_LOG_FATAL;
           }
           else {
               log_threshold_syslog = FM_LOG_INFO;
           }
       }
   
       if ((env_value = getenv ("FREEM_LOG_THRESHOLD_STDERR")) != NULL) {
           if (strcmp (env_value, "debug") == 0) {
               log_threshold_stderr = FM_LOG_DEBUG;
           }
           else if (strcmp (env_value, "info") == 0) {
               log_threshold_stderr = FM_LOG_INFO;
           }
           else if (strcmp (env_value, "warning") == 0) {
               log_threshold_stderr = FM_LOG_WARNING;
           }
           else if (strcmp (env_value, "error") == 0) {
               log_threshold_stderr = FM_LOG_ERROR;
           }
           else if (strcmp (env_value, "fatal") == 0) {
               log_threshold_stderr = FM_LOG_FATAL;
           }
           else {
               log_threshold_stderr = FM_LOG_INFO;
           }
       }    
   
   
   
   }
   
   void log_level_to_text(int level, char *buf)
   {
       switch (level) {
   
 void m_log (int level, const char *msg)          case FM_LOG_DEBUG:
               sprintf (buf, "DEBUG");
               break;
   
           case FM_LOG_INFO:
               sprintf (buf, "INFO");
               break;
   
           case FM_LOG_WARNING:
               sprintf (buf, "WARNING");
               break;
   
           case FM_LOG_ERROR:
               sprintf (buf, "ERROR");
               break;
   
           case FM_LOG_FATAL:
               sprintf (buf, "FATAL");
               break;
   
           default:
               sprintf (buf, "LEVEL %d", level);
               break;
   
       }
   }
   
   void m_log(int level, const char *msg)
 {  {
   
       FILE *fp;
       time_t unix_epoch;
       char timeval[255];
       char filename[4096];    
       char lvl[20];
       struct tm *logtime;
   
       log_level_to_text (level, lvl);
       
       if (level >= log_threshold_file) {
           snprintf (filename, sizeof (filename) - 1, "/var/log/freem/%s.log", shm_env);
           
           if ((fp = fopen (filename, "a+")) != NULL) {
               unix_epoch = time (0L);
               logtime = localtime (&unix_epoch);
               strftime (timeval, sizeof (timeval) - 1, "%F %T", logtime);
               fprintf (fp, "%s [LEVEL %s PID %ld]:  %s\n", timeval, lvl, getpid (), msg);
               fclose (fp);
           }        
       }
       
 #if defined(__linux__) | defined(__FreeBSD__) | defined(__sun__)  #if defined(__linux__) | defined(__FreeBSD__) | defined(__sun__)
         syslog (level, "%s", msg);      if (level >= log_threshold_syslog) {
           syslog (level, "%s", msg);
       }
 #endif  #endif
   
       if (level >= log_threshold_stderr) fprintf (stderr, "%s [%s]\r\n", msg, lvl);
   
       if (level >= FM_LOG_FATAL) {
           cleanup ();
           exit (FM_LOG_FATAL);
       }
           
       return;    
   }
   
   void logprintf(int level, char *fmt, ...)
   {
       va_list ptr;
       va_start (ptr, fmt);
   
       char logmsg[BIGSTR];
       char tmps[BIGSTR];
       
       char ch;
       char typ;
       char subtyp;
   
       register int i;
   
       logmsg[0] = '\0';
       
       for (i = 0; fmt[i] != '\0'; i++) {
           ch = fmt[i];
   
           tmps[0] = '\0';
           
           switch (ch) {
               
               case '%':
                   typ = fmt[++i];
   
                   switch (typ) {
                       
                       case '%': /* literal percent sign */
                           strcat (logmsg, "%");
                           continue;
   
                       case 'c': /* char */
                           sprintf (tmps, "%c", va_arg (ptr, int));
                           strcat (logmsg, tmps);
                           continue;
   
                       case 's': /* C string */
                           strcat (logmsg, va_arg (ptr, char *));
                           continue;
   
                       case 'S': /* FreeM string */
                           stcpy (tmps, va_arg (ptr, char *));
                           stcnv_m2c (tmps);
                           strcat (logmsg, tmps);
                           continue;
   
                       case 'd': /* int */
                           sprintf (tmps, "%d", va_arg (ptr, int));
                           strcat (logmsg, tmps);
                           continue;
   
                       case 'p': /* pointer */
                           sprintf (tmps, "%p", va_arg (ptr, void *));
                           strcat (logmsg, tmps);
                           continue;
                           
                       case 'l': /* long... */
                           subtyp = fmt[++i];
                           switch (subtyp) {
                               
                               case 'd': /* long int */
                                   sprintf (tmps, "%ld", va_arg (ptr, long));
                                   strcat (logmsg, tmps);
                                   continue;
   
                               case 'f': /* float */
                                   sprintf (tmps, "%lf", va_arg (ptr, double));
                                   strcat (logmsg, tmps);
                                   continue;
                                   
                           }
                           continue;
                   }
                   
               case '\\':
                   typ = fmt[++i];
                   switch (typ) {
                       case 'n':
                           sprintf (tmps, "\n");
                           strcat (logmsg, tmps);
                           continue;
                           
                       case 'r':
                           sprintf (tmps, "\r");
                           strcat (logmsg, tmps);
                           continue;
   
                       case 't':
                           sprintf (tmps, "\t");
                           strcat (logmsg, tmps);
                           continue;
                           
                       case '\\':
                           sprintf (tmps, "\\");
                           strcat (logmsg, tmps);
                           continue;
                   }
                   
               default:
                   sprintf (tmps, "%c", ch);
                   strcat (logmsg, tmps);
                   break;
           }
       }
   
       m_log (level, logmsg);
           
       va_end (ptr);
       return;
 }  }

Removed from v.1.2  
changed lines
  Added in v.1.14


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>