1 /*
2  * Copyright (c) 1997-2012 Motonori Nakamura <motonori@wide.ad.jp>
3  * Copyright (c) 1997-2012 WIDE Project
4  * Copyright (c) 1997-2003 Kyoto University
5  * Copyright (c) 2012 National Institute of Informatics
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  *    must display the following acknowledgement:
19  *      This product includes software developed by WIDE Project and
20  *      its contributors.
21  * 4. Neither the name of the Project, the University nor the names of
22  *    its contributors may be used to endorse or promote products derived
23  *    from this software without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  */
37 
38 #ifndef lint
39 static char *_id_ = "$Id: log.c,v 1.14 2012/06/07 07:51:35 motonori Exp $";
40 #endif
41 
42 # include "common.h"
43 # include "extern.h"
44 
45 #define	SYSLOG_FD
46 #ifdef	SYSLOG_FD
47 static int syslog_fd = -1;
48 #endif
49 
50 void
init_logg()51 init_logg()
52 {
53 #ifdef	SYSLOG_FD
54 	int fd_before, fd_after;
55 #endif
56 
57 	if (cnf.log_facility < 0)
58 		return;
59 
60 #ifdef	SYSLOG_FD
61 	/* a hack to get the file descriptor for /dev/log */
62 	fd_before = open ("/dev/null", O_WRONLY, 0);
63 	if (fd_before >= 0)
64 		close(fd_before);
65 #endif
66 
67 	openlog("smtpfeed", LOG_NDELAY|LOG_PID, cnf.log_facility);
68 
69 #ifdef	SYSLOG_FD
70 	fd_after = open ("/dev/null", O_WRONLY, 0);
71 	if (fd_after >= 0)
72 		close(fd_after);
73 	if (fd_before >= 0 && fd_before != fd_after)
74 	{
75 		syslog_fd = fd_before;
76 		if (cnf.debug & DEBUG_TRANS)
77 		logg(LOG_DEBUG, "file descriptor for syslog: %d", syslog_fd);
78 	}
79 #endif
80 }
81 
82 #ifdef	SYSLOG_FD
83 #define	SLEEPTIME	100000	/* micro second */
84 #define	SYSLOG_RETRY	1000
85 #endif
86 
87 void
88 # ifdef __STDC__
logg(int level,const char * fmt,...)89 logg(int level, const char *fmt, ...)
90 # else
91 logg(level, fmt, va_alist)
92 int level;
93 char *fmt;
94 va_dcl
95 # endif
96 {
97 	char buf[MAXLINE];
98 	int len, save_errno;
99 	VA_LOCAL_DECL
100 
101 	if (cnf.log_facility == LOG_NONE)
102 		return;
103 	buf[0] = '\0';
104 	save_errno = errno;
105 	if (env.queueid != NULL)
106 		strncpy(buf, env.queueid, MAXLINE);
107 	else if (env.envid != NULL)
108 		strncpy(buf, env.envid, MAXLINE);
109 	else
110 		strcpy(buf, "NOID");
111 	len = strlen(buf);
112 	if (len >= MAXLINE-2)
113 		len = 0;
114 	else {
115 		strcat(buf, ": ");
116 		len += 2;
117 	}
118 
119 	VA_START(fmt);
120 	vsnprintf(buf+len, sizeof(buf)-len, fmt, ap);
121 	VA_END;
122 
123 	if (cnf.log_facility == LOG_STDERR) {
124 		fprintf(stderr, "%s\n", buf);
125 	} else {
126 #ifdef	SYSLOG_FD
127 		int retry = SYSLOG_RETRY;
128 
129 		errno = 0;
130 #endif
131 		syslog(level, "%s", buf);
132 #ifdef	SYSLOG_FD
133 		while (errno == ENOBUFS && syslog_fd >= 0)
134 		{
135 			/* retry to write out into syslog */
136 			struct timeval timeout;
137 			static fd_set slmask;
138 			int r;
139 
140 			timeout.tv_sec = 0;
141 			timeout.tv_usec = SLEEPTIME;
142 			FD_ZERO(&slmask);
143 			FD_SET(syslog_fd, &slmask);
144 			r = select(syslog_fd + 1, (fd_set *)NULL, &slmask,
145 				   (fd_set *)NULL, &timeout);
146 			if (r > 0)
147 			{
148 				/* ready to write */
149 				errno = 0;
150 				syslog(level, "%s", buf);
151 			}
152 			if (r < 0 || --retry <= 0)
153 				break;
154 		}
155 #endif
156 	}
157 	errno = save_errno;
158 }
159