static void real_plog(int lvl, char *fmt, va_list vargs) { char msg[1024]; char efmt[1024]; char *ptr = msg; static char last_msg[1024]; static int last_count = 0, last_lvl = 0; if (!(xlog_level & lvl)) return; #ifdef DEBUG_MEM checkup_mem(); #endif /* DEBUG_MEM */ expand_error(fmt, efmt, 1024); #ifdef HAVE_VSNPRINTF vsnprintf(ptr, 1024, efmt, vargs); #else /* not HAVE_VSNPRINTF */ /* * XXX: ptr is 1024 bytes long. It is possible to write into it * more than 1024 bytes, if efmt is already large, and vargs expand * as well. This is not as safe as using vsnprintf(). */ vsprintf(ptr, efmt, vargs); msg[1023] = '\0'; /* null terminate, to be sure */ #endif /* not HAVE_VSNPRINTF */ ptr += strlen(ptr); if (ptr[-1] == '\n') *--ptr = '\0'; #ifdef HAVE_SYSLOG if (syslogging) { switch (lvl) { /* from mike <*****@*****.**> */ case XLOG_FATAL: lvl = LOG_CRIT; break; case XLOG_ERROR: lvl = LOG_ERR; break; case XLOG_USER: lvl = LOG_WARNING; break; case XLOG_WARNING: lvl = LOG_WARNING; break; case XLOG_INFO: lvl = LOG_INFO; break; case XLOG_DEBUG: lvl = LOG_DEBUG; break; case XLOG_MAP: lvl = LOG_DEBUG; break; case XLOG_STATS: lvl = LOG_INFO; break; default: lvl = LOG_ERR; break; } syslog(lvl, "%s", msg); return; } #endif /* HAVE_SYSLOG */ *ptr++ = '\n'; *ptr = '\0'; /* * mimic syslog behavior: only write repeated strings if they differ */ switch (last_count) { case 0: /* never printed at all */ last_count = 1; strncpy(last_msg, msg, 1024); last_lvl = lvl; show_time_host_and_name(lvl); /* mimic syslog header */ fwrite(msg, ptr - msg, 1, logfp); fflush(logfp); break; case 1: /* item printed once, if same, don't repeat */ if (STREQ(last_msg, msg)) { last_count++; } else { /* last msg printed once, new one differs */ /* last_count remains at 1 */ strncpy(last_msg, msg, 1024); last_lvl = lvl; show_time_host_and_name(lvl); /* mimic syslog header */ fwrite(msg, ptr - msg, 1, logfp); fflush(logfp); } break; case 100: /* * Don't allow repetitions longer than 100, so you can see when something * cycles like crazy. */ show_time_host_and_name(last_lvl); sprintf(last_msg, "last message repeated %d times\n", last_count); fwrite(last_msg, strlen(last_msg), 1, logfp); fflush(logfp); last_count = 0; /* start from scratch */ break; default: /* item repeated multiple times */ if (STREQ(last_msg, msg)) { last_count++; } else { /* last msg repeated+skipped, new one differs */ show_time_host_and_name(last_lvl); sprintf(last_msg, "last message repeated %d times\n", last_count); fwrite(last_msg, strlen(last_msg), 1, logfp); strncpy(last_msg, msg, 1024); last_count = 1; last_lvl = lvl; show_time_host_and_name(lvl); /* mimic syslog header */ fwrite(msg, ptr - msg, 1, logfp); fflush(logfp); } break; } }
static void real_plog(int lvl, const char *fmt, va_list vargs) { char msg[1024]; char efmt[1024]; char *ptr = msg; static char last_msg[1024]; static int last_count = 0, last_lvl = 0; if (!(xlog_level & lvl)) return; #ifdef DEBUG_MEM # if defined(HAVE_MALLINFO) && defined(HAVE_MALLOC_VERIFY) checkup_mem(); # endif /* not defined(HAVE_MALLINFO) && defined(HAVE_MALLOC_VERIFY) */ #endif /* DEBUG_MEM */ /* * Note: xvsnprintf() may call plog() if a truncation happened, but the * latter has some code to break out of an infinite loop. See comment in * xsnprintf() below. */ xvsnprintf(ptr, 1023, expand_error(fmt, efmt, 1024), vargs); ptr += strlen(ptr); if (*(ptr-1) == '\n') *--ptr = '\0'; #ifdef HAVE_SYSLOG if (syslogging) { switch (lvl) { /* from mike <*****@*****.**> */ case XLOG_FATAL: lvl = LOG_CRIT; break; case XLOG_ERROR: lvl = LOG_ERR; break; case XLOG_USER: lvl = LOG_WARNING; break; case XLOG_WARNING: lvl = LOG_WARNING; break; case XLOG_INFO: lvl = LOG_INFO; break; case XLOG_DEBUG: lvl = LOG_DEBUG; break; case XLOG_MAP: lvl = LOG_DEBUG; break; case XLOG_STATS: lvl = LOG_INFO; break; default: lvl = LOG_ERR; break; } syslog(lvl, "%s", msg); return; } #endif /* HAVE_SYSLOG */ *ptr++ = '\n'; *ptr = '\0'; /* * mimic syslog behavior: only write repeated strings if they differ */ switch (last_count) { case 0: /* never printed at all */ last_count = 1; if (strlcpy(last_msg, msg, sizeof(last_msg)) >= sizeof(last_msg)) /* don't use xstrlcpy here (recursive!) */ fprintf(stderr, "real_plog: string \"%s\" truncated to \"%s\"\n", last_msg, msg); last_lvl = lvl; show_time_host_and_name(lvl); /* mimic syslog header */ __IGNORE(fwrite(msg, ptr - msg, 1, logfp)); fflush(logfp); break; case 1: /* item printed once, if same, don't repeat */ if (STREQ(last_msg, msg)) { last_count++; } else { /* last msg printed once, new one differs */ /* last_count remains at 1 */ if (strlcpy(last_msg, msg, sizeof(last_msg)) >= sizeof(last_msg)) /* don't use xstrlcpy here (recursive!) */ fprintf(stderr, "real_plog: string \"%s\" truncated to \"%s\"\n", last_msg, msg); last_lvl = lvl; show_time_host_and_name(lvl); /* mimic syslog header */ __IGNORE(fwrite(msg, ptr - msg, 1, logfp)); fflush(logfp); } break; case 100: /* * Don't allow repetitions longer than 100, so you can see when something * cycles like crazy. */ show_time_host_and_name(last_lvl); xsnprintf(last_msg, sizeof(last_msg), "last message repeated %d times\n", last_count); __IGNORE(fwrite(last_msg, strlen(last_msg), 1, logfp)); fflush(logfp); last_count = 0; /* start from scratch */ break; default: /* item repeated multiple times */ if (STREQ(last_msg, msg)) { last_count++; } else { /* last msg repeated+skipped, new one differs */ show_time_host_and_name(last_lvl); xsnprintf(last_msg, sizeof(last_msg), "last message repeated %d times\n", last_count); __IGNORE(fwrite(last_msg, strlen(last_msg), 1, logfp)); if (strlcpy(last_msg, msg, 1024) >= 1024) /* don't use xstrlcpy here (recursive!) */ fprintf(stderr, "real_plog: string \"%s\" truncated to \"%s\"\n", last_msg, msg); last_count = 1; last_lvl = lvl; show_time_host_and_name(lvl); /* mimic syslog header */ __IGNORE(fwrite(msg, ptr - msg, 1, logfp)); fflush(logfp); } break; } }