#include <errno.h>
#include <limits.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <syslog.h>
#include <time.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <libgen.h>
#include <pthread.h>
#include <errno.h>
#include "ndmpd_log.h"
#include "ndmpd.h"
#include "ndmpd_common.h"
#define LOG_PATH "/var/log/ndmp"
#define LOG_FNAME "ndmplog.%d"
#define LOG_FILE_CNT 5
#define LOG_FILE_SIZE 4 * 1024 * 1024
#define LOG_SIZE_INT 256
char ndmp_log_info[256];
static boolean_t debug = B_FALSE;
static boolean_t log_to_stderr = B_FALSE;
static FILE *logfp;
static int ndmp_synclog = 1;
static mutex_t log_lock;
static char *priority_str[] = {
"EMERGENCY",
"ALERT",
"CRITICAL",
"ERROR",
"WARNING",
"NOTICE",
"INFO",
"DEBUG",
};
static char *
mk_pathname(char *fname, char *path, int idx)
{
static char buf[PATH_MAX];
static char name[NAME_MAX];
char *fmt;
int len;
len = strnlen(path, PATH_MAX);
fmt = (path[len - 1] == '/') ? "%s%s" : "%s/%s";
(void) snprintf(name, NAME_MAX, fname, idx);
(void) snprintf(buf, PATH_MAX, fmt, path, name);
return (buf);
}
static int
openlogfile(char *fname, char *mode)
{
assert(fname != NULL && *fname != '\0' &&
mode != NULL && *mode != '\0');
if ((logfp = fopen(fname, mode)) == NULL) {
perror("Error opening logfile");
return (-1);
}
(void) mutex_init(&log_lock, 0, NULL);
return (0);
}
static void
log_write_cur_time(void)
{
struct tm tm;
time_t secs;
secs = time(NULL);
(void) localtime_r(&secs, &tm);
(void) fprintf(logfp, "%2d/%02d %2d:%02d:%02d ",
tm.tm_mon + 1, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec);
}
static void
add_newline(char *fmt)
{
if (fmt[strlen(fmt) - 1] != '\n')
(void) fputc('\n', logfp);
}
static void
log_append(char *msg)
{
log_write_cur_time();
(void) fwrite(msg, 1, strlen(msg), logfp);
add_newline(msg);
if (ndmp_synclog)
(void) fflush(logfp);
}
int
ndmp_log_open_file(boolean_t to_stderr, boolean_t override_debug)
{
char *fname, *mode, *lpath;
char oldfname[PATH_MAX];
struct stat64 st;
int i;
log_to_stderr = to_stderr;
if (override_debug)
debug = B_TRUE;
else
debug = ndmpd_get_prop_yorn(NDMP_DEBUG_MODE) ? B_TRUE : B_FALSE;
lpath = ndmpd_get_prop(NDMP_DEBUG_PATH);
if ((lpath == NULL) || (*lpath == '\0'))
lpath = LOG_PATH;
if (stat64(lpath, &st) < 0) {
if (mkdirp(lpath, 0755) < 0) {
(void) fprintf(stderr,
"Could not create log path %s: %s\n",
lpath, strerror(errno));
lpath = "/var";
}
}
if (debug) {
i = LOG_FILE_CNT - 1;
while (i >= 0) {
fname = mk_pathname(LOG_FNAME, lpath, i);
(void) strncpy(oldfname, fname, PATH_MAX);
if (stat64(oldfname, &st) == -1) {
i--;
continue;
}
fname = mk_pathname(LOG_FNAME, lpath, i + 1);
if (rename(oldfname, fname))
(void) fprintf(stderr,
"Could not rename %s to %s: %s\n",
oldfname, fname, strerror(errno));
i--;
}
}
fname = mk_pathname(LOG_FNAME, lpath, 0);
if (debug)
mode = "w";
else
mode = "a";
return (openlogfile(fname, mode));
}
void
ndmp_log_close_file(void)
{
if (logfp != NULL) {
(void) fclose(logfp);
logfp = NULL;
}
(void) mutex_destroy(&log_lock);
}
void
ndmp_log(ulong_t priority, char *ndmp_log_info, char *fmt, ...)
{
int c;
va_list args;
char *f, *b;
char ndmp_log_buf[PATH_MAX+KILOBYTE];
char ndmp_syslog_buf[PATH_MAX+KILOBYTE];
char buf[PATH_MAX+KILOBYTE];
char *errstr;
if ((priority == LOG_DEBUG) && !debug)
return;
(void) mutex_lock(&log_lock);
if (priority > 7)
priority = LOG_ERR;
va_start(args, fmt);
b = buf;
f = fmt;
while (((c = *f++) != '\0') && (c != '\n') &&
(b < &buf[PATH_MAX+KILOBYTE])) {
if (c != '%') {
*b++ = c;
continue;
}
if ((c = *f++) != 'm') {
*b++ = '%';
*b++ = c;
continue;
}
if ((errstr = strerror(errno)) == NULL) {
(void) snprintf(b, &buf[PATH_MAX+KILOBYTE] - b,
"error %d", errno);
} else {
while ((*errstr != '\0') &&
(b < &buf[PATH_MAX+KILOBYTE])) {
if (*errstr == '%') {
(void) strncpy(b, "%%", 2);
b += 2;
} else {
*b++ = *errstr;
}
errstr++;
}
*b = '\0';
}
b += strlen(b);
}
*b = '\0';
(void) vsnprintf(ndmp_syslog_buf, sizeof (ndmp_syslog_buf), buf, args);
va_end(args);
if (priority != LOG_DEBUG)
syslog(priority, "%s", ndmp_syslog_buf);
(void) snprintf(ndmp_log_buf, sizeof (ndmp_log_buf), "%s: %s:%s",
priority_str[priority], ndmp_log_info, ndmp_syslog_buf);
if (logfp != NULL)
log_append(ndmp_log_buf);
if (log_to_stderr)
(void) fprintf(stderr, "%s\n", ndmp_log_buf);
(void) mutex_unlock(&log_lock);
}