int pr_trace_msg(const char *channel, int level, const char *fmt, ...) { int res; va_list msg; if (channel == NULL || fmt == NULL || level <= 0) { errno = EINVAL; return -1; } /* If no one's listening... */ if (pr_log_event_listening(PR_LOG_TYPE_TRACELOG) <= 0 && trace_logfd < 0) { return 0; } va_start(msg, fmt); res = pr_trace_vmsg(channel, level, fmt, msg); va_end(msg); return res; }
static void log_write(int priority, int f, char *s, int discard) { unsigned int max_priority = 0, *ptr = NULL; char serverinfo[PR_TUNABLE_BUFFER_SIZE] = {'\0'}; memset(serverinfo, '\0', sizeof(serverinfo)); if (main_server && main_server->ServerFQDN) { pr_netaddr_t *remote_addr = pr_netaddr_get_sess_remote_addr(); const char *remote_name = pr_netaddr_get_sess_remote_name(); snprintf(serverinfo, sizeof(serverinfo)-1, "%s", main_server->ServerFQDN); serverinfo[sizeof(serverinfo)-1] = '\0'; if (remote_addr && remote_name) { size_t serverinfo_len; serverinfo_len = strlen(serverinfo); snprintf(serverinfo + serverinfo_len, sizeof(serverinfo) - serverinfo_len, " (%s[%s])", remote_name, pr_netaddr_get_ipstr(remote_addr)); serverinfo[sizeof(serverinfo)-1] = '\0'; } } if (!discard && (logstderr || !main_server)) { char buf[LOGBUFFER_SIZE] = {'\0'}; size_t buflen, len; struct timeval now; struct tm *tm = NULL; unsigned long millis; gettimeofday(&now, NULL); tm = pr_localtime(NULL, (const time_t *) &(now.tv_sec)); if (tm == NULL) { return; } len = strftime(buf, sizeof(buf)-1, "%Y-%m-%d %H:%M:%S", tm); buflen = len; buf[sizeof(buf)-1] = '\0'; /* Convert microsecs to millisecs. */ millis = now.tv_usec / 1000; len = snprintf(buf + buflen, sizeof(buf) - len, ",%03lu ", millis); buflen += len; buf[sizeof(buf)-1] = '\0'; if (*serverinfo) { len = snprintf(buf + buflen, sizeof(buf) - buflen, "%s proftpd[%u] %s: %s\n", systemlog_host, (unsigned int) (session.pid ? session.pid : getpid()), serverinfo, s); } else { len = snprintf(buf + buflen, sizeof(buf) - buflen, "%s proftpd[%u]: %s\n", systemlog_host, (unsigned int) (session.pid ? session.pid : getpid()), s); } buflen += len; buf[sizeof(buf)-1] = '\0'; pr_log_event_generate(PR_LOG_TYPE_SYSTEMLOG, STDERR_FILENO, priority, buf, buflen); fprintf(stderr, "%s", buf); return; } if (syslog_discard) { /* Only return now if we don't have any log listeners. */ if (pr_log_event_listening(PR_LOG_TYPE_SYSLOG) <= 0 && pr_log_event_listening(PR_LOG_TYPE_SYSTEMLOG) <= 0) { return; } } ptr = get_param_ptr(main_server->conf, "SyslogLevel", FALSE); if (ptr != NULL) { max_priority = *ptr; } else { /* Default SyslogLevel */ max_priority = default_level; } if (priority > max_priority) { /* Only return now if we don't have any log listeners. */ if (pr_log_event_listening(PR_LOG_TYPE_SYSLOG) <= 0 && pr_log_event_listening(PR_LOG_TYPE_SYSTEMLOG) <= 0) { return; } } if (systemlog_fd != -1) { char buf[LOGBUFFER_SIZE] = {'\0'}; size_t buflen, len; struct timeval now; struct tm *tm; unsigned long millis; gettimeofday(&now, NULL); tm = pr_localtime(NULL, (const time_t *) &(now.tv_sec)); if (tm == NULL) { return; } len = strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", tm); buflen = len; buf[sizeof(buf) - 1] = '\0'; /* Convert microsecs to millisecs. */ millis = now.tv_usec / 1000; len = snprintf(buf + buflen, sizeof(buf) - len, ",%03lu ", millis); buflen += len; buf[sizeof(buf) - 1] = '\0'; if (*serverinfo) { len = snprintf(buf + buflen, sizeof(buf) - buflen, "%s proftpd[%u] %s: %s\n", systemlog_host, (unsigned int) (session.pid ? session.pid : getpid()), serverinfo, s); } else { len = snprintf(buf + buflen, sizeof(buf) - buflen, "%s proftpd[%u]: %s\n", systemlog_host, (unsigned int) (session.pid ? session.pid : getpid()), s); } buflen += len; buf[sizeof(buf)-1] = '\0'; pr_log_event_generate(PR_LOG_TYPE_SYSTEMLOG, systemlog_fd, priority, buf, buflen); /* Now we need to enforce the discard, syslog_discard and SyslogLevel * filtering. */ if (discard) { return; } if (syslog_discard) { return; } if (priority > max_priority) { return; } while (write(systemlog_fd, buf, buflen) < 0) { if (errno == EINTR) { pr_signals_handle(); continue; } return; } return; } pr_log_event_generate(PR_LOG_TYPE_SYSLOG, syslog_sockfd, priority, s, strlen(s)); if (set_facility != -1) f = set_facility; if (!syslog_open) { syslog_sockfd = pr_openlog("proftpd", LOG_NDELAY|LOG_PID, f); if (syslog_sockfd < 0) { (void) pr_trace_msg(trace_channel, 1, "error opening syslog fd: %s", strerror(errno)); return; } syslog_open = TRUE; } else if (f != facility) { /* If this message is to be sent to a different log facility than a * default one (or the facility configured via SyslogFacility), then * OR in the facility with the priority value, as per the syslog(3) * docs. */ priority |= f; } if (*serverinfo) { pr_syslog(syslog_sockfd, priority, "%s - %s\n", serverinfo, s); } else { pr_syslog(syslog_sockfd, priority, "%s\n", s); } }
int pr_trace_vmsg(const char *channel, int level, const char *fmt, va_list msg) { char buf[PR_TUNABLE_BUFFER_SIZE] = {'\0'}; size_t buflen; struct trace_levels *levels; int discard = FALSE; /* Writing a trace message at level zero is NOT helpful; this makes it * impossible to quell messages to that trace channel by setting the level * filter to zero. That being the case, treat level of zero as an invalid * level. */ if (channel == NULL || fmt == NULL || level <= 0) { errno = EINVAL; return -1; } if (trace_tab == NULL) { errno = EPERM; return -1; } levels = trace_get_levels(channel); if (levels == NULL) { discard = TRUE; if (pr_log_event_listening(PR_LOG_TYPE_TRACELOG) <= 0) { return -1; } } if (discard == FALSE && level < levels->min_level) { discard = TRUE; if (pr_log_event_listening(PR_LOG_TYPE_TRACELOG) <= 0) { return 0; } } if (discard == FALSE && level > levels->max_level) { discard = TRUE; if (pr_log_event_listening(PR_LOG_TYPE_TRACELOG) <= 0) { return 0; } } buflen = vsnprintf(buf, sizeof(buf), fmt, msg); /* Always make sure the buffer is NUL-terminated. */ buf[sizeof(buf)-1] = '\0'; /* Trim trailing newlines. */ while (buflen >= 1 && buf[buflen-1] == '\n') { pr_signals_handle(); buf[buflen-1] = '\0'; buflen--; } return trace_write(channel, level, buf, discard); }