4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * PPPoE Server-mode daemon log file support.
25 * Copyright (c) 2000-2001 by Sun Microsystems, Inc.
26 * All rights reserved.
29 #pragma ident "%Z%%M% %I% %E% SMI"
40 #include <sys/types.h>
45 /* Not all functions are used by all applications. Let lint know this. */
48 const char *prog_name
= "none"; /* Subsystem name for syslog */
49 int log_level
; /* Higher number for more detail. */
51 static int curlogfd
= -1; /* Current log file */
52 static const char *curfname
; /* Name of current log file */
53 static const char *stderr_name
= "stderr";
55 #define SMALLSTR 254 /* Don't allocate for most strings. */
58 * Returns -1 on error (with errno set), 0 on blocked write (file
59 * system full), or N (buffer length) on success.
62 dowrite(int fd
, const void *buf
, int len
)
65 const uint8_t *bp
= (uint8_t *)buf
;
68 retv
= write(fd
, bp
, len
);
81 return (bp
- (uint8_t *)buf
);
85 /* A close that avoids closing stderr */
93 if ((curlogfd
!= STDERR_FILENO
) || (curfname
!= stderr_name
))
94 retval
= close(curlogfd
);
100 * Log levels are 0 for no messages, 1 for errors, 2 for warnings, 3
101 * for informational messages, and 4 for debugging messages.
104 vlogat(int loglev
, const char *fmt
, va_list args
)
107 char regbuf
[SMALLSTR
+2];
116 static int xlate_loglev
[] = {
117 LOG_ERR
, LOG_WARNING
, LOG_INFO
, LOG_DEBUG
120 if (loglev
>= log_level
)
126 time_t now
= time(NULL
);
129 * Form a time/date string for file (non-syslog) logging.
130 * Caution: string broken in two so that SCCS doesn't mangle
131 * the %-T-% sequence.
133 timlen
= strftime(timbuf
, sizeof (timbuf
), "%Y/%m/%d %T"
134 "%Z: ", localtime(&now
));
137 /* Try formatting once into the small buffer. */
138 va_copy(args2
, args
);
139 slen
= vsnprintf(regbuf
, SMALLSTR
, fmt
, args
);
140 if (slen
< SMALLSTR
) {
144 * Length returned by vsnprintf doesn't include null,
145 * and may also be missing a terminating \n.
147 ostr
= alloca(slen
+ 2);
148 slen
= vsnprintf(ostr
, slen
+ 1, fmt
, args2
);
151 /* Don't bother logging empty lines. */
155 /* Tack on a \n if needed. */
156 if (ostr
[slen
- 1] != '\n') {
161 /* Translate our log levels into syslog standard values */
162 assert(loglev
>= 0 && loglev
< Dim(xlate_loglev
));
163 sloglev
= xlate_loglev
[loglev
];
165 /* Log each line separately */
166 for (; *ostr
!= '\0'; ostr
= nstr
+ 1) {
167 nstr
= strchr(ostr
, '\n');
169 /* Ignore zero-length lines. */
173 slen
= nstr
- ostr
+ 1;
176 * If we're supposed to be logging to a file, then try
177 * that first. Ditch the file and revert to syslog if
181 if ((retv
= dowrite(curlogfd
, timbuf
, timlen
)) > 0)
182 retv
= dowrite(curlogfd
, ostr
, slen
);
185 * If we've successfully logged this line,
186 * then go do the next one.
191 /* Save errno (if any) and close log file */
199 * Recursion is safe here because we cleared
200 * out curlogfd above.
203 logerr("write log %s: %s", curfname
,
206 logerr("cannot write %s", curfname
);
208 logdbg("closed log %s", curfname
);
210 logerr("closing log %s: %s", curfname
,
213 syslog(sloglev
, "%.*s", slen
, ostr
);
217 /* Log at debug level */
219 logdbg(const char *fmt
, ...)
224 vlogat(LOGLVL_DBG
, fmt
, args
);
228 /* Log informational messages */
230 loginfo(const char *fmt
, ...)
235 vlogat(LOGLVL_INFO
, fmt
, args
);
239 /* Log warning messages */
241 logwarn(const char *fmt
, ...)
246 vlogat(LOGLVL_WARN
, fmt
, args
);
250 /* Log error messages */
252 logerr(const char *fmt
, ...)
257 vlogat(LOGLVL_ERR
, fmt
, args
);
261 /* Log a strerror message */
263 logstrerror(const char *emsg
)
265 logerr("%s: %s\n", emsg
, mystrerror(errno
));
269 log_to_stderr(int dbglvl
)
274 curlogfd
= STDERR_FILENO
;
275 curfname
= stderr_name
;
279 * Set indicated log file and debug level.
282 log_for_service(const char *fname
, int dbglvl
)
289 (*fname
== '\0' || strcasecmp(fname
, "syslog") == 0))
291 if (fname
== NULL
&& curfname
== NULL
)
296 if (fname
== curfname
||
297 (fname
!= NULL
&& strcmp(fname
, curfname
) == 0)) {
306 curlogfd
= open(fname
, O_WRONLY
|O_APPEND
|O_CREAT
, 0600);
312 logdbg("closed log %s", curfname
);
314 logerr("closing log %s: %s", curfname
,
319 logdbg("opened log %s", fname
);
321 logerr("opening log %s: %s", fname
, mystrerror(err2
));
327 * Close any open log file. This is used for SIGHUP (to support log
328 * file rotation) and when execing.
331 close_log_files(void)
339 logdbg("closed log %s", curfname
);
341 logerr("closing log %s: %s", curfname
,
347 * Reopen syslog connection; in case it was closed.
352 openlog(prog_name
, LOG_PID
| LOG_NDELAY
| LOG_NOWAIT
, LOG_DAEMON
);
353 /* I control the log level */
354 (void) setlogmask(LOG_UPTO(LOG_DEBUG
));