4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1988 AT&T */
28 /* All Rights Reserved */
31 * University Copyright- Copyright (c) 1982, 1986, 1988
32 * The Regents of the University of California
35 * University Acknowledgment- Portions of this document are derived from
36 * software developed by the University of California, Berkeley, and its
42 * SYSLOG -- print message on log file
44 * This routine looks a lot like printf, except that it
45 * outputs to the log file instead of the standard output.
48 * prints the module name in front of the message,
49 * has some other formatting types (or will sometime),
50 * adds a newline on the end of the message.
52 * The output of this routine is intended to be read by /etc/syslogd.
55 #pragma weak _syslog = syslog
58 #include <sys/types.h>
59 #include <sys/types32.h>
61 #include <sys/stropts.h>
62 #include <sys/strlog.h>
63 #include <sys/log.h> /* for LOG_MAXPS */
85 #define MAXLINE 1024 /* max message size (but see below) */
87 #define PRIMASK(p) (1 << ((p) & LOG_PRIMASK))
88 #define PRIFAC(p) (((p) & LOG_FACMASK) >> 3)
89 #define IMPORTANT LOG_ERR
99 #define logname "/dev/conslog"
100 #define ctty "/dev/syscon"
101 #define sysmsg "/dev/sysmsg"
103 #define DOORFILE "/var/run/syslog_door"
105 static struct __syslog
{
115 char _ProcName
[PRFNSZ
+ 1];
118 0, /* status bits, set by openlog() */
119 "syslog", /* string to tag the entry with */
120 0xff, /* mask of priorities to be logged */
122 LOG_USER
, /* default facility code */
123 FALSE
, /* check for validity of fd for log */
124 0, /* openlog has not yet been called */
127 #define LogFile (__syslog._LogFile)
128 #define LogStat (__syslog._LogStat)
129 #define LogTag (__syslog._LogTag)
130 #define LogMask (__syslog._LogMask)
131 #define SyslogHost (__syslog._SyslogHost)
132 #define LogFacility (__syslog._LogFacility)
133 #define LogFileInvalid (__syslog._LogFileInvalid)
134 #define OpenLogCalled (__syslog._OpenLogCalled)
135 #define LogDev (__syslog._LogDev)
136 #define ProcName (__syslog._ProcName)
138 static int syslogd_ok(void);
141 * Regrettably, there are several instances inside libc where
142 * syslog() is called from the bottom of a deep call stack
143 * and a critical lock was acquired near the top of the stack.
145 * Because syslog() uses stdio (and it is called from within stdio)
146 * it runs the danger of deadlocking, perhaps with an interposed
147 * malloc() when fork() is occurring concurrently, perhaps with
148 * some other lock within libc.
150 * The only fix for this problem is to restructure libc not to do
151 * this thing and always to call syslog() with no locks held.
152 * This restructuring will require a substantial effort.
154 * Meanwhile, we just hope that on the rare occasion that syslog()
155 * is called from within libc (such occurrences should "never happen")
156 * that we don't get caught in a race condition deadlock.
159 syslog(int pri
, const char *fmt
, ...)
164 vsyslog(pri
, fmt
, ap
);
170 vsyslog(int pri
, const char *fmt
, va_list ap
)
175 char buf
[MAXLINE
+ 2];
176 char outline
[MAXLINE
+ 256]; /* pad to allow date, system name... */
182 char timestr
[26]; /* hardwired value 26 due to Posix */
184 int olderrno
= errno
;
185 struct stat statbuff
;
191 char *msgid_start
, *msgid_end
;
195 * Maximum tag length is 256 (the pad in outline) minus the size of the
196 * other things that can go in the pad.
200 /* see if we should just throw out this message */
201 if (pri
< 0 || PRIFAC(pri
) >= LOG_NFACILITIES
||
202 (PRIMASK(pri
) & LogMask
) == 0)
209 * if openlog() has not been called by the application,
210 * try to get the name of the application and set it
211 * as the ident string for messages. If unable to get
212 * it for any reason, fall back to using the default
213 * of syslog. If we succeed in getting the name, also
214 * turn on LOG_PID, to provide greater detail.
217 if (OpenLogCalled
== 0) {
218 (void) sprintf(procfile
, "/proc/%d/psinfo", (int)getpid());
219 if ((procfd
= open(procfile
, O_RDONLY
)) >= 0) {
220 if (read(procfd
, &p
, sizeof (psinfo_t
)) >= 0) {
221 (void) strncpy(ProcName
, p
.pr_fname
, PRFNSZ
);
222 LogTag
= (const char *) &ProcName
;
225 (void) close(procfd
);
229 openlog(LogTag
, LogStat
|LOG_NDELAY
|showpid
, 0);
231 if ((fstat(LogFile
, &statbuff
) != 0) ||
232 (!S_ISCHR(statbuff
.st_mode
)) || (statbuff
.st_rdev
!= LogDev
)) {
233 LogFileInvalid
= TRUE
;
237 /* set default facility if none specified */
238 if ((pri
& LOG_FACMASK
) == 0)
241 /* build the header */
243 hdr
.flags
= SL_CONSOLE
;
246 /* build the message */
248 * To avoid potential security problems, bounds checking is done
249 * on outline and buf.
250 * The following code presumes that the header information will
251 * fit in 250-odd bytes, as was accounted for in the buffer size
252 * allocation. This is dependent on the assumption that the LogTag
253 * and the string returned by sprintf() for getpid() will return
254 * be less than 230-odd characters combined.
258 (void) sprintf(o
, "%.15s ", ctime_r(&now
, timestr
) + 4);
262 taglen
= strlen(LogTag
) < MAX_TAG
? strlen(LogTag
) : MAX_TAG
;
263 (void) strncpy(o
, LogTag
, taglen
);
267 if (LogStat
& LOG_PID
) {
268 (void) sprintf(o
, "[%d]", (int)getpid());
272 (void) strcpy(o
, ": ");
276 STRLOG_MAKE_MSGID(fmt
, msgid
);
277 (void) sprintf(o
, "[ID %u FACILITY_AND_PRIORITY] ", msgid
);
282 while ((c
= *f
++) != '\0' && b
< &buf
[MAXLINE
]) {
288 if ((c
= *f
++) != 'm') {
293 if ((errmsg
= strerror(olderrno
)) == NULL
)
294 (void) snprintf(b
, &buf
[MAXLINE
] - b
, "error %d",
297 while (*errmsg
!= '\0' && b
< &buf
[MAXLINE
]) {
298 if (*errmsg
== '%') {
299 (void) strcpy(b
, "%%");
310 if (b
> buf
&& *(b
-1) != '\n') /* ensure at least one newline */
313 /* LINTED variable format specifier */
314 (void) vsnprintf(o
, &outline
[sizeof (outline
)] - o
, buf
, ap
);
315 clen
= (int)strlen(outline
) + 1; /* add one for NULL byte */
316 if (clen
> MAXLINE
) {
318 outline
[MAXLINE
-1] = '\0';
322 * 1136432 points out that the underlying log driver actually
323 * refuses to accept (ERANGE) messages longer than LOG_MAXPS
324 * bytes. So it really doesn't make much sense to putmsg a
327 if (clen
> LOG_MAXPS
) {
329 outline
[LOG_MAXPS
-1] = '\0';
332 /* set up the strbufs */
333 ctl
.maxlen
= sizeof (struct log_ctl
);
334 ctl
.len
= sizeof (struct log_ctl
);
335 ctl
.buf
= (caddr_t
)&hdr
;
336 dat
.maxlen
= sizeof (outline
);
340 /* output the message to the local logger */
341 if ((putmsg(LogFile
, &ctl
, &dat
, 0) >= 0) && syslogd_ok())
343 if (!(LogStat
& LOG_CONS
))
347 * Output the message to the console directly. To reduce visual
348 * clutter, we strip out the message ID.
350 if ((msgid_start
= strstr(outline
, "[ID ")) != NULL
&&
351 (msgid_end
= strstr(msgid_start
, "] ")) != NULL
)
352 (void) strcpy(msgid_start
, msgid_end
+ 2);
354 clen
= strlen(outline
) + 1;
356 nowait
= (LogStat
& LOG_NOWAIT
);
357 pid
= forkx(nowait
? 0 : (FORK_NOSIGCHLD
| FORK_WAITPID
));
365 (void) sigset(SIGALRM
, SIG_DFL
);
366 (void) sigemptyset(&sigs
);
367 (void) sigaddset(&sigs
, SIGALRM
);
368 (void) sigprocmask(SIG_UNBLOCK
, &sigs
, NULL
);
370 if (((fd
= open(sysmsg
, O_WRONLY
)) >= 0) ||
371 (fd
= open(ctty
, O_WRONLY
)) >= 0) {
373 outline
[clen
- 1] = '\r';
374 (void) write(fd
, outline
, clen
);
380 while (waitpid(pid
, NULL
, 0) == -1 && errno
== EINTR
)
385 * Use a door call to syslogd to see if it's alive.
395 if ((d
= open(DOORFILE
, O_RDONLY
)) < 0)
398 * see if our pid matches the pid of the door server.
399 * If so, syslogd has called syslog(), probably as
400 * a result of some name service library error, and
401 * we don't want to let syslog continue and possibly
405 if (__door_info(d
, &info
) < 0 || info
.di_target
== getpid()) {
409 darg
.data_ptr
= NULL
;
411 darg
.desc_ptr
= NULL
;
415 s
= __door_call(d
, &darg
);
418 return (0); /* failure - syslogd dead */
424 * OPENLOG -- open system log
428 openlog(const char *ident
, int logstat
, int logfac
)
430 struct stat statbuff
;
437 LogFacility
= logfac
& LOG_FACMASK
;
440 * if the fstat(2) fails or the st_rdev has changed
441 * then we must open the file
443 if ((fstat(LogFile
, &statbuff
) == 0) &&
444 (S_ISCHR(statbuff
.st_mode
)) && (statbuff
.st_rdev
== LogDev
))
447 if (LogStat
& LOG_NDELAY
) {
448 LogFile
= open(logname
, O_WRONLY
);
449 (void) fcntl(LogFile
, F_SETFD
, 1);
450 (void) fstat(LogFile
, &statbuff
);
451 LogDev
= statbuff
.st_rdev
;
456 * CLOSELOG -- close the system log
462 struct stat statbuff
;
466 /* if the LogFile is invalid it can not be closed */
471 * if the fstat(2) fails or the st_rdev has changed
472 * then we can not close the file
474 if ((fstat(LogFile
, &statbuff
) == 0) && (statbuff
.st_rdev
== LogDev
)) {
475 (void) close(LogFile
);
482 * SETLOGMASK -- set the log mask level
485 setlogmask(int pmask
)