2 * Copyright (c) 2004-2008 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 #include <sys/types.h>
25 #include <sys/socket.h>
27 #include <sys/ucred.h>
32 #include <sys/queue.h>
33 #include <netinet/in.h>
34 #include <arpa/inet.h>
37 #include <sys/fslog.h>
40 #include <vproc_priv.h>
41 #include <mach/mach.h>
44 #define streq(A,B) (strcmp(A,B)==0)
45 #define forever for(;;)
47 #define ASL_MSG_TYPE_MASK 0x0000000f
48 #define ASL_TYPE_ERROR 2
50 #define ASL_KEY_FACILITY "Facility"
52 #define FACILITY_USER "user"
53 #define FACILITY_CONSOLE "com.apple.console"
54 #define SYSTEM_RESERVED "com.apple.system"
55 #define SYSTEM_RESERVED_LEN 16
57 extern void disaster_message(asl_msg_t
*m
);
59 static char myname
[MAXHOSTNAMELEN
+ 1] = {0};
61 static pthread_mutex_t event_lock
= PTHREAD_MUTEX_INITIALIZER
;
63 static const char *kern_notify_key
[] =
65 "com.apple.system.log.kernel.emergency",
66 "com.apple.system.log.kernel.alert",
67 "com.apple.system.log.kernel.critical",
68 "com.apple.system.log.kernel.error",
69 "com.apple.system.log.kernel.warning",
70 "com.apple.system.log.kernel.notice",
71 "com.apple.system.log.kernel.info",
72 "com.apple.system.log.kernel.debug"
79 unsigned char write
:1;
80 unsigned char except
:1;
87 TAILQ_ENTRY(aslevent
) entries
;
94 TAILQ_ENTRY(asloutput
) entries
;
101 TAILQ_ENTRY(aslmatch
) entries
;
104 TAILQ_HEAD(ae
, aslevent
) Eventq
;
105 TAILQ_HEAD(ao
, asloutput
) Outq
;
106 TAILQ_HEAD(am
, aslmatch
) Matchq
;
108 static struct aslevent
*launchd_event
;
121 aslevent_log(asl_msg_t
*msg
, char *outid
)
126 for (i
= Outq
.tqh_first
; i
!= NULL
; i
= i
->entries
.tqe_next
)
128 if ((outid
!= NULL
) && (strcmp(i
->outid
, outid
) == 0))
130 status
= i
->sendmsg(msg
, outid
);
138 aslevent_addmatch(asl_msg_t
*query
, char *outid
)
140 struct aslmatch
*tmp
;
142 if (query
== NULL
) return -1;
143 if (outid
== NULL
) return -1;
145 tmp
= calloc(1, sizeof(struct aslmatch
));
146 if (tmp
== NULL
) return -1;
150 TAILQ_INSERT_TAIL(&Matchq
, tmp
, entries
);
156 aslevent_match(asl_msg_t
*msg
)
160 if (msg
== NULL
) return;
162 for (i
= Matchq
.tqh_first
; i
!= NULL
; i
= i
->entries
.tqe_next
)
164 if (asl_msg_cmp(i
->query
, msg
) != 0)
166 aslevent_log(msg
, i
->outid
);
172 aslevent_removefd(int fd
)
174 struct aslevent
*e
, *next
;
176 e
= Eventq
.tqh_first
;
180 next
= e
->entries
.tqe_next
;
198 if (gethostname(myname
, MAXHOSTNAMELEN
) < 0)
200 memset(myname
, 0, sizeof(myname
));
204 dot
= strchr(myname
, '.');
205 if (dot
!= NULL
) *dot
= '\0';
207 return (const char *)myname
;
211 aslevent_addfd(int fd
, uint32_t flags
, aslreadfn readfn
, aslwritefn writefn
, aslexceptfn exceptfn
)
214 int found
= 0, status
;
215 #ifdef LOCAL_PEERCRED
221 struct sockaddr_storage ss
;
222 char *sender
, str
[256];
228 memset(&ss
, 0, sizeof(struct sockaddr_storage
));
229 memset(str
, 0, sizeof(str
));
231 len
= sizeof(struct sockaddr_storage
);
233 if (flags
& ADDFD_FLAGS_LOCAL
)
235 snprintf(str
, sizeof(str
), "localhost");
238 #ifdef LOCAL_PEERCRED
241 status
= getsockopt(fd
, LOCAL_PEERCRED
, 1, &cr
, &len
);
251 status
= getpeername(fd
, (struct sockaddr
*)&ss
, &len
);
256 /* UNIX Domain socket */
257 snprintf(str
, sizeof(str
), "localhost");
262 if (inet_ntop(ss
.ss_family
, (struct sockaddr
*)&ss
, str
, 256) == NULL
) sender
= str
;
267 asldebug("fd %d flags 0x%08x UID %d GID %d Sender %s\n", fd
, flags
, u
, g
, (sender
== NULL
) ? "NULL" : sender
);
269 for (e
= Eventq
.tqh_first
; e
!= NULL
; e
= e
->entries
.tqe_next
)
274 e
->writefn
= writefn
;
275 e
->exceptfn
= exceptfn
;
276 if (e
->sender
!= NULL
) free(e
->sender
);
280 e
->sender
= strdup(sender
);
281 if (e
->sender
== NULL
) return -1;
292 e
= calloc(1, sizeof(struct aslevent
));
293 if (e
== NULL
) return -1;
297 e
->writefn
= writefn
;
298 e
->exceptfn
= exceptfn
;
302 e
->sender
= strdup(sender
);
303 if (e
->sender
== NULL
) return -1;
309 TAILQ_INSERT_TAIL(&Eventq
, e
, entries
);
315 aslmsg_verify(struct aslevent
*e
, asl_msg_t
*msg
, int32_t *kern_post_level
)
317 const char *val
, *fac
;
318 char buf
[32], *timestr
;
322 uint32_t level
, fnum
, kern
;
325 if (msg
== NULL
) return -1;
327 *kern_post_level
= -1;
330 if ((e
!= NULL
) && (e
->fd
== global
.kfd
)) kern
= 1;
336 val
= asl_get(msg
, ASL_KEY_TIME
);
337 if (val
!= NULL
) tick
= asl_parse_time(val
);
339 /* Set time to now if it is unset or from the future (not allowed!) */
340 if ((tick
== 0) || (tick
> now
)) tick
= now
;
342 memset(>ime
, 0, sizeof(struct tm
));
343 gmtime_r(&tick
, >ime
);
345 /* Canonical form: YYYY.MM.DD hh:mm:ss UTC */
346 asprintf(×tr
, "%d.%02d.%02d %02d:%02d:%02d UTC", gtime
.tm_year
+ 1900, gtime
.tm_mon
+ 1, gtime
.tm_mday
, gtime
.tm_hour
, gtime
.tm_min
, gtime
.tm_sec
);
349 asl_set(msg
, ASL_KEY_TIME
, timestr
);
354 if (e
== NULL
) asl_set(msg
, ASL_KEY_HOST
, whatsmyhostname());
355 else if (e
->sender
!= NULL
)
357 if (!strcmp(e
->sender
, "localhost")) asl_set(msg
, ASL_KEY_HOST
, whatsmyhostname());
358 else asl_set(msg
, ASL_KEY_HOST
, e
->sender
);
362 val
= asl_get(msg
, ASL_KEY_PID
);
363 if (val
== NULL
) asl_set(msg
, ASL_KEY_PID
, "0");
367 val
= asl_get(msg
, ASL_KEY_UID
);
371 asl_set(msg
, ASL_KEY_UID
, "0");
373 else if (val
== NULL
)
375 if (e
== NULL
) asl_set(msg
, ASL_KEY_UID
, "-2");
376 else if (e
->uid
== 99) asl_set(msg
, ASL_KEY_UID
, "-2");
380 snprintf(buf
, sizeof(buf
), "%d", e
->uid
);
381 asl_set(msg
, ASL_KEY_UID
, buf
);
384 else if ((e
!= NULL
) && (e
->uid
!= 99))
387 snprintf(buf
, sizeof(buf
), "%d", e
->uid
);
388 asl_set(msg
, ASL_KEY_UID
, buf
);
392 val
= asl_get(msg
, ASL_KEY_GID
);
395 asl_set(msg
, ASL_KEY_GID
, "0");
397 else if (val
== NULL
)
399 if (e
== NULL
) asl_set(msg
, ASL_KEY_GID
, "-2");
400 else if (e
->gid
== 99) asl_set(msg
, ASL_KEY_GID
, "-2");
403 snprintf(buf
, sizeof(buf
), "%d", e
->gid
);
404 asl_set(msg
, ASL_KEY_GID
, buf
);
407 else if ((e
!= NULL
) && (e
->gid
!= 99))
409 snprintf(buf
, sizeof(buf
), "%d", e
->gid
);
410 asl_set(msg
, ASL_KEY_GID
, buf
);
414 val
= asl_get(msg
, ASL_KEY_SENDER
);
417 if (kern
== 0) asl_set(msg
, ASL_KEY_SENDER
, "Unknown");
418 else asl_set(msg
, ASL_KEY_SENDER
, "kernel");
420 else if ((kern
== 0) && (uid
!= 0) && (!strcmp(val
, "kernel")))
422 asl_set(msg
, ASL_KEY_SENDER
, "Unknown");
426 val
= asl_get(msg
, ASL_KEY_LEVEL
);
427 level
= ASL_LEVEL_DEBUG
;
428 if ((val
!= NULL
) && (val
[1] == '\0') && (val
[0] >= '0') && (val
[0] <= '7')) level
= val
[0] - '0';
429 snprintf(buf
, sizeof(buf
), "%d", level
);
430 asl_set(msg
, ASL_KEY_LEVEL
, buf
);
433 fac
= asl_get(msg
, ASL_KEY_FACILITY
);
436 if (kern
== 1) fac
= "kern";
438 asl_set(msg
, ASL_KEY_FACILITY
, fac
);
440 else if (fac
[0] == '#')
443 if ((fac
[1] >= '0') && (fac
[1] <= '9'))
445 fnum
= atoi(fac
+ 1) << 3;
446 if ((fnum
== 0) && (strcmp(fac
+ 1, "0"))) fnum
= LOG_USER
;
449 fac
= asl_syslog_faciliy_num_to_name(fnum
);
450 asl_set(msg
, ASL_KEY_FACILITY
, fac
);
454 * Access Control: only UID 0 may use facility com.apple.system (or anything with that prefix).
455 * N.B. kernel can use any facility name.
458 /* Set DB Expire Time for com.apple.system.utmpx and lastlog */
459 if ((!strcmp(fac
, "com.apple.system.utmpx")) || (!strcmp(fac
, "com.apple.system.lastlog")))
461 snprintf(buf
, sizeof(buf
), "%lu", tick
+ global
.utmp_ttl
);
462 asl_set(msg
, ASL_KEY_EXPIRE_TIME
, buf
);
465 /* Set DB Expire Time for Filestsrem errors */
466 if (!strcmp(fac
, FSLOG_VAL_FACILITY
))
468 snprintf(buf
, sizeof(buf
), "%lu", tick
+ global
.fs_ttl
);
469 asl_set(msg
, ASL_KEY_EXPIRE_TIME
, buf
);
475 if (!strncmp(fac
, SYSTEM_RESERVED
, SYSTEM_RESERVED_LEN
))
477 if (uid
!= 0) asl_set(msg
, ASL_KEY_FACILITY
, FACILITY_USER
);
483 * special case handling of kernel disaster messages
485 if ((kern
== 1) && (level
<= KERN_DISASTER_LEVEL
))
487 *kern_post_level
= level
;
488 disaster_message(msg
);
495 aslevent_addoutput(aslsendmsgfn fn
, const char *outid
)
497 struct asloutput
*tmp
;
499 tmp
= calloc(1, sizeof(struct asloutput
));
500 if (tmp
== NULL
) return -1;
505 TAILQ_INSERT_TAIL(&Outq
, tmp
, entries
);
511 aslevent_fdsets(fd_set
*rd
, fd_set
*wr
, fd_set
*ex
)
516 // asldebug("--> aslevent_fdsets\n");
521 for (e
= Eventq
.tqh_first
; e
!= NULL
; e
= e
->entries
.tqe_next
)
523 if (e
->fd
< 0) continue;
525 // asldebug("adding fd %d\n", e->fd);
529 status
= MAX(e
->fd
, status
);
535 status
= MAX(e
->fd
, status
);
541 status
= MAX(e
->fd
, status
);
545 // asldebug("<--aslevent_fdsets\n");
552 struct aslevent
*e
, *next
;
554 e
= Eventq
.tqh_first
;
558 next
= e
->entries
.tqe_next
;
561 TAILQ_REMOVE(&Eventq
, e
, entries
);
562 if (e
->sender
!= NULL
) free(e
->sender
);
571 aslevent_handleevent(fd_set
*rd
, fd_set
*wr
, fd_set
*ex
)
576 int32_t kplevel
, cleanup
;
578 // asldebug("--> aslevent_handleevent\n");
582 for (e
= Eventq
.tqh_first
; e
!= NULL
; e
= e
->entries
.tqe_next
)
590 if (FD_ISSET(e
->fd
, rd
) && (e
->readfn
!= NULL
))
592 // asldebug("handling read event on %d\n", e->fd);
593 msg
= e
->readfn(e
->fd
);
594 if (msg
== NULL
) continue;
596 /* type field is overloaded to provide retain/release inside syslogd */
599 pthread_mutex_lock(&event_lock
);
602 if (aslmsg_verify(e
, msg
, &kplevel
) < 0)
604 asl_msg_release(msg
);
605 asldebug("recieved invalid message\n\n");
610 asl_msg_release(msg
);
611 if (kplevel
>= 0) notify_post(kern_notify_key
[kplevel
]);
614 pthread_mutex_unlock(&event_lock
);
617 if (FD_ISSET(e
->fd
, ex
) && e
->exceptfn
)
619 asldebug("handling except event on %d\n", e
->fd
);
620 out
= e
->exceptfn(e
->fd
);
621 if (out
== NULL
) asldebug("error writing message\n\n");
625 if (cleanup
!= 0) aslevent_cleanup();
627 // asldebug("<-- aslevent_handleevent\n");
631 asl_log_string(const char *str
)
636 if (str
== NULL
) return 1;
638 msg
= asl_msg_from_string(str
);
640 /* set retain count */
643 pthread_mutex_lock(&event_lock
);
646 if (aslmsg_verify(NULL
, msg
, &unused
) < 0)
648 pthread_mutex_unlock(&event_lock
);
649 asl_msg_release(msg
);
654 asl_msg_release(msg
);
656 pthread_mutex_unlock(&event_lock
);
662 asldebug(const char *str
, ...)
668 if (global
.debug
== 0) return 0;
671 if (global
.debug_file
!= NULL
) dfp
= fopen(global
.debug_file
, "a");
672 if (dfp
== NULL
) return 0;
675 status
= vfprintf(dfp
, str
, v
);
678 if (global
.debug_file
!= NULL
) fclose(dfp
);
688 asprintf(&str
, "[%s syslogd] [%s %u] [%s %u] [%s -- MARK --] [%s 0] [%s 0] [Facility syslog]",
690 ASL_KEY_LEVEL
, ASL_LEVEL_INFO
,
691 ASL_KEY_PID
, getpid(),
692 ASL_KEY_MSG
, ASL_KEY_UID
, ASL_KEY_GID
);
695 if (str
!= NULL
) free(str
);
699 asl_syslog_input_convert(const char *in
, int len
, char *rhost
, int kern
)
701 int pf
, pri
, index
, n
;
702 char *p
, *colon
, *brace
, *tmp
, *tval
, *sval
, *pval
, *mval
;
709 if (in
== NULL
) return NULL
;
710 if (len
<= 0) return NULL
;
722 while ((index
< len
) && ((*p
== ' ') || (*p
== '\t')))
728 if (index
>= len
) return NULL
;
735 n
= sscanf(p
, "%d", &pf
);
739 if (pf
> 0x7) fval
= asl_syslog_faciliy_num_to_name(pf
& LOG_FACMASK
);
742 while ((index
< len
) && (*p
!= '>'))
755 snprintf(prival
, sizeof(prival
), "%d", pri
);
757 if (((len
- index
) > 15) && (p
[9] == ':') && (p
[12] == ':') && (p
[15] == ' '))
760 if (tmp
== NULL
) return NULL
;
765 tick
= asl_parse_time(tmp
);
766 if (tick
== (time_t)-1)
773 gmtime_r(&tick
, &time
);
774 asprintf(&tval
, "%d.%02d.%02d %02d:%02d:%02d UTC", time
.tm_year
+ 1900, time
.tm_mon
+ 1, time
.tm_mday
, time
.tm_hour
, time
.tm_min
, time
.tm_sec
);
783 msg
= (asl_msg_t
*)calloc(1, sizeof(asl_msg_t
));
784 if (msg
== NULL
) return NULL
;
787 asl_set(msg
, ASL_KEY_MSG
, p
);
789 asl_set(msg
, ASL_KEY_LEVEL
, prival
);
791 asl_set(msg
, ASL_KEY_PID
, "0");
793 asl_set(msg
, ASL_KEY_HOST
, whatsmyhostname());
798 colon
= strchr(p
, ':');
799 brace
= strchr(p
, '[');
803 if ((brace
!= NULL
) && (brace
< colon
))
806 sval
= malloc(n
+ 1);
807 if (sval
== NULL
) return NULL
;
812 n
= colon
- (brace
+ 1) - 1;
813 pval
= malloc(n
+ 1);
814 if (pval
== NULL
) return NULL
;
816 memcpy(pval
, (brace
+ 1), n
);
822 sval
= malloc(n
+ 1);
823 if (sval
== NULL
) return NULL
;
843 mval
= malloc(n
+ 1);
844 if (mval
== NULL
) return NULL
;
850 if (fval
== NULL
) fval
= asl_syslog_faciliy_num_to_name(LOG_USER
);
852 msg
= (asl_msg_t
*)calloc(1, sizeof(asl_msg_t
));
853 if (msg
== NULL
) return NULL
;
857 asl_set(msg
, ASL_KEY_TIME
, tval
);
861 if (fval
!= NULL
) asl_set(msg
, "Facility", fval
);
862 else asl_set(msg
, "Facility", "user");
866 asl_set(msg
, ASL_KEY_SENDER
, sval
);
872 asl_set(msg
, ASL_KEY_PID
, pval
);
875 else asl_set(msg
, ASL_KEY_PID
, "-1");
879 asl_set(msg
, ASL_KEY_MSG
, mval
);
883 asl_set(msg
, ASL_KEY_LEVEL
, prival
);
884 asl_set(msg
, ASL_KEY_UID
, "-2");
885 asl_set(msg
, ASL_KEY_GID
, "-2");
887 if (rhost
== NULL
) asl_set(msg
, ASL_KEY_HOST
, whatsmyhostname());
888 else asl_set(msg
, ASL_KEY_HOST
, rhost
);
892 asl_msg_release(msg
);
900 asl_input_parse(const char *in
, int len
, char *rhost
, int kern
)
903 int status
, x
, legacy
;
905 asldebug("asl_input_parse: %s\n", (in
== NULL
) ? "NULL" : in
);
907 if (in
== NULL
) return NULL
;
912 /* calculate length if not provided */
913 if (len
== 0) len
= strlen(in
);
916 * Determine if the input is "old" syslog format or new ASL format.
917 * Old format lines should start with "<", but they can just be straight text.
918 * ASL input starts with a length (10 bytes) followed by a space and a '['.
920 if ((in
[0] != '<') && (len
> 11))
922 status
= sscanf(in
, "%d ", &x
);
923 if ((status
== 1) && (in
[10] == ' ') && (in
[11] == '[')) legacy
= 0;
926 if (legacy
== 1) return asl_syslog_input_convert(in
, len
, rhost
, kern
);
928 m
= asl_msg_from_string(in
+ 11);
929 if (m
== NULL
) return NULL
;
931 if (rhost
!= NULL
) asl_set(m
, ASL_KEY_HOST
, rhost
);
937 get_line_from_file(FILE *f
)
942 out
= fgetln(f
, &len
);
943 if (out
== NULL
) return NULL
;
944 if (len
== 0) return NULL
;
947 if (s
== NULL
) return NULL
;
956 asl_msg_type(asl_msg_t
*m
)
958 if (m
== NULL
) return ASL_TYPE_ERROR
;
959 return (m
->type
& ASL_MSG_TYPE_MASK
);
963 asl_msg_release(asl_msg_t
*m
)
967 if (m
== NULL
) return;
969 refcount
= m
->type
>> 4;
976 if (refcount
> 0) return;
981 asl_msg_retain(asl_msg_t
*m
)
983 if (m
== NULL
) return NULL
;
990 launchd_callback(struct timeval
*when
, pid_t from_pid
, pid_t about_pid
, uid_t sender_uid
, gid_t sender_gid
, int priority
, const char *from_name
, const char *about_name
, const char *session_name
, const char *msg
)
999 asldebug("launchd_callback Time %lu %lu PID %u RefPID %u UID %d GID %d PRI %d Sender %s Ref %s Session %s Message %s\n",
1000 when->tv_sec, when->tv_usec, from_pid, about_pid, sender_uid, sender_gid, priority, from_name, about_name, session_name, msg);
1003 if (launchd_event
!= NULL
)
1005 launchd_event
->uid
= sender_uid
;
1006 launchd_event
->gid
= sender_gid
;
1009 m
= asl_new(ASL_TYPE_MSG
);
1010 if (m
== NULL
) return;
1013 if (priority
< ASL_LEVEL_EMERG
) priority
= ASL_LEVEL_EMERG
;
1014 if (priority
> ASL_LEVEL_DEBUG
) priority
= ASL_LEVEL_DEBUG
;
1015 snprintf(str
, sizeof(str
), "%d", priority
);
1017 asl_set(m
, ASL_KEY_LEVEL
, str
);
1022 snprintf(str
, sizeof(str
), "%lu", when
->tv_sec
);
1023 asl_set(m
, ASL_KEY_TIME
, str
);
1025 snprintf(str
, sizeof(str
), "%lu", 1000 * (unsigned long int)when
->tv_usec
);
1026 asl_set(m
, ASL_KEY_TIME_NSEC
, str
);
1031 snprintf(str
, sizeof(str
), "%lu", now
);
1032 asl_set(m
, ASL_KEY_TIME
, str
);
1036 asl_set(m
, ASL_KEY_HOST
, whatsmyhostname());
1039 asl_set(m
, ASL_KEY_FACILITY
, FACILITY_CONSOLE
);
1044 snprintf(str
, sizeof(str
), "%u", (unsigned int)from_pid
);
1045 asl_set(m
, ASL_KEY_PID
, str
);
1049 if ((about_pid
> 0) && (about_pid
!= from_pid
))
1051 snprintf(str
, sizeof(str
), "%u", (unsigned int)about_pid
);
1052 asl_set(m
, ASL_KEY_REF_PID
, str
);
1056 if (from_name
!= NULL
)
1058 asl_set(m
, ASL_KEY_SENDER
, from_name
);
1062 if (sender_uid
!= 0)
1064 snprintf(str
, sizeof(str
), "%d", (int)sender_uid
);
1065 asl_set(m
, ASL_KEY_READ_UID
, str
);
1068 /* Reference Process */
1069 if (about_name
!= NULL
)
1071 if ((from_name
!= NULL
) && (strcmp(from_name
, about_name
) != 0))
1073 asl_set(m
, ASL_KEY_REF_PROC
, about_name
);
1078 if (session_name
!= NULL
)
1080 asl_set(m
, ASL_KEY_SESSION
, session_name
);
1086 asl_set(m
, ASL_KEY_MSG
, msg
);
1089 /* set retain count */
1092 /* verify and push to receivers */
1093 status
= aslmsg_verify(launchd_event
, m
, &unused
);
1094 if (status
>= 0) aslevent_match(m
);
1102 launchd_event
= (struct aslevent
*)calloc(1, sizeof(struct aslevent
));
1106 _vprocmgr_log_drain(NULL
, &event_lock
, launchd_callback
);