1 /*
2  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  */
5 
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <sys/types.h>
9 #include <sys/stat.h>
10 #include <nl_types.h>
11 #include <limits.h>
12 #include <stdarg.h>
13 #include <string.h>
14 
15 #include <syslog.h>
16 #include <portable.h>
17 /* #include <lthread.h> */
18 #include <pthread.h>
19 #include <thread.h>
20 
21 #include "log.h"
22 
23 #define	LDAP_DEBUG_ANY	0xffff
24 
25 static pthread_mutex_t	log_mutex;
26 static char		logfile[PATH_MAX] =
27 					"/var/opt/SUNWconn/ldap/log/slapd.log";
28 static int		logsize = 512000;
29 static int		logtime = 1;
30 static FILE		*logfd = NULL;
31 static int		syslogopen = 0;
32 pthread_mutex_t		systime_mutex;
33 nl_catd			sundscat;
34 static int		log_debug = LDAP_DEBUG_STATS;
35 
36 typedef struct _logctx {
37 	char		*logfile;
38 	int		syslogopen;
39 	int		logsize;
40 	pthread_mutex_t	log_mutex;
41 	int		log_debug;
42 	int		log_syslog;
43 
44 } LogCtx;
45 
46 void
ldaplogconfig(char * logf,int size)47 ldaplogconfig(char *logf, int size)
48 {
49 	strcpy(logfile, logf);
50 	logsize = size * 1024;
51 }
52 
53 void
ldaplogconfigf(FILE * fd)54 ldaplogconfigf(FILE *fd)
55 {
56 	logfd = fd;
57 	logsize = 0;
58 }
59 
60 void
ldaploginit(char * name,int facility)61 ldaploginit(char *name, int facility)
62 {
63 	openlog(name, OPENLOG_OPTIONS, facility);
64 	syslogopen = 1;
65 	pthread_mutex_init(&log_mutex, NULL);
66 }
67 
68 void
ldaploginitlevel(char * name,int facility,int level)69 ldaploginitlevel(char *name, int facility, int level)
70 {
71 	ldaploginit(name, facility);
72 	log_debug = level;
73 }
74 
75 LogCtx *
sundsloginit(char * name,int facility,int debug_level,int syslog_level)76 sundsloginit(char *name, int facility, int debug_level, int syslog_level)
77 {
78 	LogCtx *returnCtx = NULL;
79 
80 	if ((returnCtx = (LogCtx *)malloc(sizeof (LogCtx))) == NULL)
81 		return (NULL);
82 	if ((returnCtx->logfile = strdup(name)) == NULL) {
83 		free(returnCtx);
84 		return (NULL);
85 	}
86 	openlog(returnCtx->logfile, OPENLOG_OPTIONS, facility);
87 	returnCtx->syslogopen = 1;
88 	pthread_mutex_init(&(returnCtx->log_mutex), NULL);
89 	returnCtx->log_debug = debug_level;
90 	returnCtx->log_syslog = syslog_level;
91 	return (returnCtx);
92 }
93 
94 static char timestr[128];
95 static time_t timelast = 0;
96 
97 /*VARARGS*/
98 void
ldaplog(int level,char * fmt,...)99 ldaplog(int level, char *fmt, ...)
100 {
101 	va_list ap;
102 	struct stat statbuf = {0};
103 	char newlog1[PATH_MAX];
104 	char newlog2[PATH_MAX];
105 	time_t now;
106 	int i;
107 
108 	if (!(log_debug & level))
109 		return;
110 
111 	va_start(ap, fmt);
112 
113 	if (level == LDAP_DEBUG_ANY) {
114 		/*
115 		 * this message is probably an error message, send it to syslog
116 		 */
117 		if (syslogopen) {
118 			vsyslog(LOG_ERR, fmt, ap);
119 		} /* end if */
120 		/* and sent it also on stderr */
121 		vfprintf(stderr, fmt, ap);
122 	} /* end if */
123 
124 	/*
125 	 * check that the log file is not already too big
126 	 */
127 	pthread_mutex_lock(&log_mutex);
128 	if ((logsize > 0) && (stat(logfile, &statbuf) == 0 &&
129 					statbuf.st_size > logsize)) {
130 		for (i = 9; i > 1; i--) {
131 			(void) sprintf(newlog1, "%s.%d", logfile, i-1);
132 			(void) sprintf(newlog2, "%s.%d", logfile, i);
133 			(void) rename(newlog1, newlog2);
134 		} /* end for */
135 		if (logfd) {
136 			fclose(logfd);
137 			logfd = NULL;
138 		} /* end if */
139 		(void) rename(logfile, newlog1);
140 	} /* end if */
141 	/*
142 	 * send the message into a regular log file
143 	 */
144 	if (!logfd) {
145 		logfd = fopen(logfile, "aF");
146 	} /* end if */
147 	/*
148 	 * finally write the message into the log file
149 	 */
150 	if (logfd) {
151 		if (logtime) {
152 			time(&now);
153 			if (now-timelast > 60) {
154 				pthread_mutex_lock(&systime_mutex);
155 				timelast = now;
156 				ctime_r(&now, timestr, 128);
157 				pthread_mutex_unlock(&systime_mutex);
158 			} /* end if */
159 			fprintf(logfd, "%.16s : ", timestr);
160 		} /* end if */
161 		vfprintf(logfd, fmt, ap);
162 		fflush(logfd);
163 	} /* end if */
164 	pthread_mutex_unlock(&log_mutex);
165 	va_end(ap);
166 }
167