2 * Copyright (c) 1999-2008 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.0 (the 'License'). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
22 * @APPLE_LICENSE_HEADER_END@
26 * The Regents of the University of California. All rights reserved.
28 * Redistribution and use in source and binary forms, with or without
29 * modification, are permitted provided that the following conditions
31 * 1. Redistributions of source code must retain the above copyright
32 * notice, this list of conditions and the following disclaimer.
33 * 2. Redistributions in binary form must reproduce the above copyright
34 * notice, this list of conditions and the following disclaimer in the
35 * documentation and/or other materials provided with the distribution.
36 * 3. All advertising materials mentioning features or use of this software
37 * must display the following acknowledgement:
38 * This product includes software developed by the University of
39 * California, Berkeley and its contributors.
40 * 4. Neither the name of the University nor the names of its contributors
41 * may be used to endorse or promote products derived from this software
42 * without specific prior written permission.
44 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
45 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
47 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
48 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
49 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
50 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
51 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
52 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
53 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
57 #include <sys/types.h>
58 #include <sys/param.h>
59 #include <sys/socket.h>
60 #include <sys/syslog.h>
64 #include <mach/mach.h>
65 #include <servers/bootstrap.h>
78 #include <asl_private.h>
87 #include <crt_externs.h>
89 #define LOG_NO_NOTIFY 0x1000
90 #define INTERNALLOG LOG_ERR|LOG_CONS|LOG_PERROR|LOG_PID
92 #ifdef BUILDING_VARIANT
93 __private_extern__
int _sl_LogStat
; /* status bits, set by openlog() */
94 __private_extern__
const char *_sl_LogTag
; /* string to tag the entry with */
95 __private_extern__
int _sl_LogFacility
; /* default facility code */
96 __private_extern__
int _sl_LogMask
; /* local mask of priorities to be logged */
97 __private_extern__
int _sl_MasterLogMask
; /* master (remote control) mask of priorities to be logged */
98 __private_extern__
int _sl_ProcLogMask
; /* process-specific (remote control) mask of priorities to be logged */
99 __private_extern__
int _sl_RCToken
; /* for remote control change notification */
100 __private_extern__
int _sl_NotifyToken
; /* for remote control of priority filter */
101 __private_extern__
int _sl_NotifyMaster
; /* for remote control of priority filter */
102 __private_extern__
int _sl_pid
; /* pid */
103 #else /* !BUILDING_VARIANT */
104 __private_extern__
int _sl_LogStat
= 0; /* status bits, set by openlog() */
105 __private_extern__
const char *_sl_LogTag
= NULL
; /* string to tag the entry with */
106 __private_extern__
int _sl_LogFacility
= LOG_USER
; /* default facility code */
107 __private_extern__
int _sl_LogMask
= 0xff; /* mask of priorities to be logged */
108 __private_extern__
int _sl_MasterLogMask
= 0; /* master mask of priorities to be logged */
109 __private_extern__
int _sl_ProcLogMask
= 0; /* process-specific mask of priorities to be logged */
110 __private_extern__
int _sl_RCToken
= -1; /* for remote control change notification */
111 __private_extern__
int _sl_NotifyToken
= -1; /* for remote control of max logged priority */
112 __private_extern__
int _sl_NotifyMaster
= -1; /* for remote control of max logged priority */
113 __private_extern__
int _sl_pid
= -1; /* pid */
114 #endif /* BUILDING_VARIANT */
116 __private_extern__
void _sl_init_notify();
118 #define ASL_SERVICE_NAME "com.apple.system.logger"
119 static mach_port_t asl_server_port
= MACH_PORT_NULL
;
121 #define NOTIFY_SYSTEM_MASTER "com.apple.system.syslog.master"
122 #define NOTIFY_PREFIX_SYSTEM "com.apple.system.syslog"
123 #define NOTIFY_PREFIX_USER "user.syslog"
124 #define NOTIFY_STATE_OFFSET 1000
127 uint32_t notify_register_plain(const char *name
, int *out_token
);
128 const char *asl_syslog_faciliy_num_to_name(int);
132 * print message on log file; output is intended for syslogd(8).
136 syslog(int pri
, const char *fmt
, ...)
138 syslog(pri
, fmt
, va_alist
)
151 vsyslog(pri
, fmt
, ap
);
156 vsyslog(int pri
, const char *fmt
, va_list ap
)
158 int status
, i
, saved_errno
, filter
, check
, rc_filter
;
161 uint32_t elen
, count
, outlen
;
162 char *p
, *str
, *expanded
, *err_str
, hname
[MAXHOSTNAMELEN
+1];
165 int fd
, mask
, level
, facility
;
167 kern_return_t kstatus
;
172 if (_sl_pid
== -1) _sl_pid
= getpid();
174 /* Check for invalid bits. */
175 if (pri
& ~(LOG_PRIMASK
| LOG_FACMASK
))
177 syslog(INTERNALLOG
, "syslog: unknown facility/priority: %x", pri
);
178 pri
&= (LOG_PRIMASK
| LOG_FACMASK
);
181 level
= LOG_PRI(pri
);
182 facility
= pri
& LOG_FACMASK
;
184 if (facility
== 0) facility
= _sl_LogFacility
;
188 /* initialize or re-check process-specific and master filters */
189 if (_sl_RCToken
>= 0)
192 status
= notify_check(_sl_RCToken
, &check
);
193 if ((status
== NOTIFY_STATUS_OK
) && (check
!= 0))
195 if (_sl_NotifyMaster
>= 0)
198 if (notify_get_state(_sl_NotifyMaster
, &cval
) == NOTIFY_STATUS_OK
) _sl_MasterLogMask
= cval
;
201 if (_sl_NotifyToken
>= 0)
204 if (notify_get_state(_sl_NotifyToken
, &cval
) == NOTIFY_STATUS_OK
) _sl_ProcLogMask
= cval
;
209 filter
= _sl_LogMask
;
212 /* master filter overrides local filter */
213 if (_sl_MasterLogMask
!= 0)
215 filter
= _sl_MasterLogMask
;
219 /* process-specific filter overrides local and master */
220 if (_sl_ProcLogMask
!= 0)
222 filter
= _sl_ProcLogMask
;
226 mask
= LOG_MASK(level
);
227 if ((mask
& filter
) == 0) return;
229 /* Build the message. */
230 msg
= asl_new(ASL_TYPE_MSG
);
232 if (_sl_LogTag
== NULL
) _sl_LogTag
= *(*_NSGetArgv());
233 if (_sl_LogTag
!= NULL
)
235 asl_set(msg
, ASL_KEY_SENDER
, _sl_LogTag
);
238 str
= (char *)asl_syslog_faciliy_num_to_name(facility
);
239 if (str
!= NULL
) asl_set(msg
, ASL_KEY_FACILITY
, str
);
242 memset(&tval
, 0, sizeof(struct timeval
));
244 status
= gettimeofday(&tval
, NULL
);
248 asprintf(&str
, "%lu", tval
.tv_sec
);
251 asl_set(msg
, ASL_KEY_TIME
, str
);
256 asprintf(&str
, "%lu", tval
.tv_usec
* 1000);
259 asl_set(msg
, ASL_KEY_TIME_NSEC
, str
);
267 asprintf(&str
, "%lu", tick
);
270 asl_set(msg
, ASL_KEY_TIME
, str
);
276 asprintf(&str
, "%u", _sl_pid
);
279 asl_set(msg
, ASL_KEY_PID
, str
);
284 asprintf(&str
, "%d", getuid());
287 asl_set(msg
, ASL_KEY_UID
, str
);
292 asprintf(&str
, "%u", getgid());
295 asl_set(msg
, ASL_KEY_GID
, str
);
300 asprintf(&str
, "%u", level
);
303 asl_set(msg
, ASL_KEY_LEVEL
, str
);
307 status
= gethostname(hname
, MAXHOSTNAMELEN
);
308 if (status
< 0) asl_set(msg
, ASL_KEY_HOST
, "localhost");
309 else asl_set(msg
, ASL_KEY_HOST
, hname
);
313 for (i
= 0; fmt
[i
] != '\0'; i
++)
315 if ((fmt
[i
] == '%') && (fmt
[i
+1] == 'm')) count
++;
322 /* deal with malloc failures gracefully */
325 err_str
= strdup(strerror(saved_errno
));
326 if (err_str
== NULL
) count
= 0;
329 elen
= strlen(err_str
);
330 expanded
= malloc(i
+ (count
* elen
));
331 if (expanded
== NULL
) count
= 0;
335 if (expanded
== NULL
) expanded
= (char *)fmt
;
340 for (i
= 0; fmt
[i
] != '\0'; i
++)
342 if ((fmt
[i
] == '%') && (fmt
[i
+1] == 'm'))
344 memcpy(p
, err_str
, elen
);
357 if (err_str
!= NULL
) free(err_str
);
359 vasprintf(&str
, expanded
, ap
);
360 if (count
> 0) free(expanded
);
364 asl_set(msg
, ASL_KEY_MSG
, str
);
366 /* Output to stderr if requested. */
367 if (_sl_LogStat
& LOG_PERROR
)
370 if (_sl_LogStat
& LOG_PID
) asprintf(&p
, "%s[%u]: %s", (_sl_LogTag
== NULL
) ? "???" : _sl_LogTag
, _sl_pid
, str
);
371 else asprintf(&p
, "%s: %s", (_sl_LogTag
== NULL
) ? "???" : _sl_LogTag
, str
);
378 iov
[0].iov_len
= strlen(p
);
379 iov
[1].iov_base
= "\n";
381 writev(STDERR_FILENO
, iov
, 2);
389 /* Set "ASLOption store" if remote control is active */
392 val
= asl_get(msg
, ASL_KEY_OPTION
);
395 asl_set(msg
, ASL_KEY_OPTION
, ASL_OPT_STORE
);
400 asprintf(&str
, "%s %s", ASL_OPT_STORE
, val
);
403 asl_set(msg
, ASL_KEY_OPTION
, str
);
410 /* send a mach message to syslogd */
411 str
= asl_format_message(msg
, ASL_MSG_FMT_RAW
, ASL_TIME_FMT_SEC
, ASL_ENCODE_ASL
, &count
);
415 kstatus
= vm_allocate(mach_task_self(), (vm_address_t
*)&out
, outlen
+ 1, TRUE
);
416 if (kstatus
== KERN_SUCCESS
)
418 memset(out
, 0, outlen
+ 1);
419 snprintf((char *)out
, outlen
, "%10u %s", count
, str
);
422 if (asl_server_port
== MACH_PORT_NULL
) kstatus
= bootstrap_look_up(bootstrap_port
, ASL_SERVICE_NAME
, &asl_server_port
);
424 if (kstatus
== KERN_SUCCESS
) kstatus
= _asl_server_message(asl_server_port
, (caddr_t
)out
, outlen
+ 1);
425 else vm_deallocate(mach_task_self(), (vm_address_t
)out
, outlen
+ 1);
427 if (kstatus
== KERN_SUCCESS
)
439 * Output the message to the console.
441 if (_sl_LogStat
& LOG_CONS
&& (fd
= open(_PATH_CONSOLE
, O_WRONLY
| O_NOCTTY
| O_NONBLOCK
)) >= 0)
445 p
= asl_format_message(msg
, ASL_MSG_FMT_STD
, ASL_TIME_FMT_LCL
, ASL_ENCODE_SAFE
, &count
);
450 /* count includes trailing nul */
451 iov
.iov_len
= count
- 1;
464 #ifndef BUILDING_VARIANT
466 __private_extern__
void
470 _sl_NotifyToken
= -1;
471 _sl_NotifyMaster
= -1;
473 asl_server_port
= MACH_PORT_NULL
;
478 __private_extern__
void
485 if (_sl_LogStat
& LOG_NO_NOTIFY
)
488 _sl_NotifyMaster
= -2;
489 _sl_NotifyToken
= -2;
493 if (_sl_RCToken
== -1)
495 status
= notify_register_check(NOTIFY_RC
, &_sl_RCToken
);
496 if (status
!= NOTIFY_STATUS_OK
) _sl_RCToken
= -2;
499 if (_sl_NotifyMaster
== -1)
501 status
= notify_register_plain(NOTIFY_SYSTEM_MASTER
, &_sl_NotifyMaster
);
502 if (status
!= NOTIFY_STATUS_OK
) _sl_NotifyMaster
= -2;
505 if (_sl_NotifyToken
== -1)
507 _sl_NotifyToken
= -2;
511 if (euid
== 0) asprintf(¬ify_name
, "%s.%d", NOTIFY_PREFIX_SYSTEM
, getpid());
512 else asprintf(¬ify_name
, "user.uid.%d.syslog.%d", euid
, getpid());
514 if (notify_name
!= NULL
)
516 status
= notify_register_plain(notify_name
, &_sl_NotifyToken
);
518 if (status
!= NOTIFY_STATUS_OK
) _sl_NotifyToken
= -2;
524 openlog(const char *ident
, int logstat
, int logfac
)
526 kern_return_t kstatus
;
528 if (ident
!= NULL
) _sl_LogTag
= ident
;
530 _sl_LogStat
= logstat
;
532 if (logfac
!= 0 && (logfac
&~ LOG_FACMASK
) == 0) _sl_LogFacility
= logfac
;
534 if (asl_server_port
== MACH_PORT_NULL
)
536 kstatus
= bootstrap_look_up(bootstrap_port
, ASL_SERVICE_NAME
, &asl_server_port
);
546 if (asl_server_port
!= MACH_PORT_NULL
) mach_port_deallocate(mach_task_self(), asl_server_port
);
547 asl_server_port
= MACH_PORT_NULL
;
549 if (_sl_NotifyToken
!= -1) notify_cancel(_sl_NotifyToken
);
550 _sl_NotifyToken
= -1;
552 if (_sl_NotifyMaster
!= -1) notify_cancel(_sl_NotifyMaster
);
553 _sl_NotifyMaster
= -1;
556 /* setlogmask -- set the log mask level */
558 setlogmask(int pmask
)
563 if (pmask
!= 0) _sl_LogMask
= pmask
;
567 #endif /* !BUILDING_VARIANT */