--- freem/src/log.c 2025/03/09 19:50:47 1.4
+++ freem/src/log.c 2025/05/14 12:22:04 1.14
@@ -1,5 +1,5 @@
/*
- * $Id: log.c,v 1.4 2025/03/09 19:50:47 snw Exp $
+ * $Id: log.c,v 1.14 2025/05/14 12:22:04 snw Exp $
* freem error logging
*
*
@@ -24,6 +24,36 @@
* along with FreeM. If not, see .
*
* $Log: log.c,v $
+ * 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
*
@@ -38,14 +68,349 @@
# include
#endif
#include
+#include
+#include
+
+#if defined(USE_SYS_TIME_H) && !defined(MSDOS) && !defined(__osf__)
+# include
+#else
+# include
+#endif
#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 m_log (int level, const char *msg)
+
+}
+
+void log_level_to_text(int level, char *buf)
{
+ switch (level) {
+
+ 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__)
- syslog (level, "%s", msg);
+ if (level >= log_threshold_syslog) {
+ syslog (level, "%s", msg);
+ }
#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;
}