2 * Copyright (c) 2004-2012 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 <TargetConditionals.h>
26 #include <sys/types.h>
27 #include <sys/socket.h>
29 #include <sys/ucred.h>
34 #include <netinet/in.h>
35 #include <arpa/inet.h>
38 #include <sys/fslog.h>
41 #include <vproc_priv.h>
42 #include <mach/mach.h>
44 #include <libkern/OSAtomic.h>
46 #include <uuid/uuid.h>
49 #define LIST_SIZE_DELTA 256
51 #define streq(A,B) (strcmp(A,B)==0)
52 #define forever for(;;)
54 #define ASL_MSG_TYPE_MASK 0x0000000f
55 #define ASL_TYPE_ERROR 2
57 #define ASL_KEY_FACILITY "Facility"
59 #define FACILITY_USER "user"
60 #define FACILITY_CONSOLE "com.apple.console"
61 #define SYSTEM_RESERVED "com.apple.system"
62 #define SYSTEM_RESERVED_LEN 16
64 #define VERIFY_STATUS_OK 0
65 #define VERIFY_STATUS_INVALID_MESSAGE 1
66 #define VERIFY_STATUS_EXCEEDED_QUOTA 2
68 extern void disaster_message(aslmsg m
);
69 extern int asl_action_reset(void);
70 extern int asl_action_control_set_param(const char *s
);
72 static char myname
[MAXHOSTNAMELEN
+ 1] = {0};
73 static int name_change_token
= -1;
75 static OSSpinLock count_lock
= 0;
77 #if !TARGET_OS_EMBEDDED
78 static vproc_transaction_t vproc_trans
= {0};
81 #define QUOTA_KERN_EXCEEDED_MESSAGE "*** kernel exceeded %d log message per second limit - remaining messages this second discarded ***"
83 #define DEFAULT_DB_FILE_MAX 25600000
84 #define DEFAULT_DB_MEMORY_MAX 8192
85 #define DEFAULT_DB_MINI_MAX 256
86 #define DEFAULT_MPS_LIMIT 500
87 #define DEFAULT_REMOTE_DELAY 5000
88 #define DEFAULT_BSD_MAX_DUP_SEC 30
89 #define DEFAULT_MARK_SEC 0
90 #define DEFAULT_UTMP_TTL_SEC 31622400
92 static time_t quota_time
= 0;
93 static int32_t kern_quota
;
94 static int32_t kern_level
;
96 static const char *kern_notify_key
[] =
98 "com.apple.system.log.kernel.emergency",
99 "com.apple.system.log.kernel.alert",
100 "com.apple.system.log.kernel.critical",
101 "com.apple.system.log.kernel.error",
102 "com.apple.system.log.kernel.warning",
103 "com.apple.system.log.kernel.notice",
104 "com.apple.system.log.kernel.info",
105 "com.apple.system.log.kernel.debug"
108 static int kern_notify_token
[8] = {-1, -1, -1, -1, -1, -1, -1, -1 };
111 kern_quota_check(time_t now
, aslmsg msg
, uint32_t level
)
115 if (msg
== NULL
) return VERIFY_STATUS_INVALID_MESSAGE
;
116 if (global
.mps_limit
== 0) return VERIFY_STATUS_OK
;
118 if (quota_time
!= now
)
120 kern_quota
= global
.mps_limit
;
125 if (level
< kern_level
) kern_level
= level
;
126 if (kern_quota
> 0) kern_quota
--;
128 if (kern_quota
> 0) return VERIFY_STATUS_OK
;
129 if (kern_quota
< 0) return VERIFY_STATUS_EXCEEDED_QUOTA
;
134 asprintf(&str
, QUOTA_KERN_EXCEEDED_MESSAGE
, global
.mps_limit
);
137 asl_set(msg
, ASL_KEY_MSG
, str
);
139 lstr
[0] = kern_level
+ '0';
141 asl_set(msg
, ASL_KEY_LEVEL
, lstr
);
144 return VERIFY_STATUS_OK
;
150 static dispatch_once_t once
;
153 dispatch_once(&once
, ^{
154 snprintf(myname
, sizeof(myname
), "%s", "localhost");
155 notify_register_check(kNotifySCHostNameChange
, &name_change_token
);
161 if (name_change_token
>= 0) status
= notify_check(name_change_token
, &check
);
163 if ((status
== 0) && (check
== 0)) return (const char *)myname
;
165 if (gethostname(myname
, MAXHOSTNAMELEN
) < 0)
167 snprintf(myname
, sizeof(myname
), "%s", "localhost");
172 dot
= strchr(myname
, '.');
173 if (dot
!= NULL
) *dot
= '\0';
176 return (const char *)myname
;
180 asl_client_count_increment()
182 OSSpinLockLock(&count_lock
);
184 #if !TARGET_OS_EMBEDDED
185 if (global
.client_count
== 0) vproc_trans
= vproc_transaction_begin(NULL
);
187 global
.client_count
++;
189 OSSpinLockUnlock(&count_lock
);
193 asl_client_count_decrement()
195 OSSpinLockLock(&count_lock
);
197 if (global
.client_count
> 0) global
.client_count
--;
198 #if !TARGET_OS_EMBEDDED
199 if (global
.client_count
== 0) vproc_transaction_end(NULL
, vproc_trans
);
202 OSSpinLockUnlock(&count_lock
);
206 * Checks message content and sets attributes as required
208 * SOURCE_INTERNAL log messages sent by syslogd itself
209 * SOURCE_ASL_SOCKET legacy asl(3) TCP socket
210 * SOURCE_BSD_SOCKET legacy syslog(3) UDP socket
211 * SOURCE_UDP_SOCKET from the network
212 * SOURCE_KERN from the kernel
213 * SOURCE_ASL_MESSAGE mach messages sent from Libc by asl(3) and syslog(3)
214 * SOURCE_LAUNCHD forwarded from launchd
218 aslmsg_verify(aslmsg msg
, uint32_t source
, int32_t *kern_post_level
, uid_t
*uid_out
)
220 const char *val
, *fac
, *ruval
, *rgval
;
225 uint32_t status
, level
, fnum
;
228 struct proc_uniqidentifierinfo pinfo
;
230 if (msg
== NULL
) return VERIFY_STATUS_INVALID_MESSAGE
;
235 if (kern_post_level
!= NULL
) *kern_post_level
= -1;
236 if (uid_out
!= NULL
) *uid_out
= -2;
241 val
= asl_get(msg
, ASL_KEY_PID
);
242 if (val
== NULL
) asl_set(msg
, ASL_KEY_PID
, "0");
243 else pid
= (pid_t
)atoi(val
);
245 /* if PID is 1 (launchd), use the refpid if provided */
248 val
= asl_get(msg
, ASL_KEY_REF_PID
);
249 if (val
!= NULL
) pid
= (pid_t
)atoi(val
);
253 val
= asl_get(msg
, ASL_KEY_LEVEL
);
254 level
= ASL_LEVEL_DEBUG
;
255 if ((val
!= NULL
) && (val
[1] == '\0') && (val
[0] >= '0') && (val
[0] <= '7')) level
= val
[0] - '0';
256 snprintf(buf
, sizeof(buf
), "%d", level
);
257 asl_set(msg
, ASL_KEY_LEVEL
, buf
);
259 /* check kernel quota if enabled and no processes are watching */
260 if ((pid
== 0) && (global
.mps_limit
> 0) && (global
.watchers_active
== 0))
262 status
= kern_quota_check(now
, msg
, level
);
263 if (status
!= VERIFY_STATUS_OK
) return status
;
268 /* set Sender_Mach_UUID */
269 uuid_clear(pinfo
.p_uuid
);
270 if (proc_pidinfo(pid
, PROC_PIDUNIQIDENTIFIERINFO
, 1, &pinfo
, sizeof(pinfo
)) == sizeof(pinfo
))
272 uuid_unparse(pinfo
.p_uuid
, ustr
);
273 asl_set(msg
, ASL_KEY_SENDER_MACH_UUID
, ustr
);
278 val
= asl_get(msg
, ASL_KEY_TIME
);
279 if (val
!= NULL
) tick
= asl_parse_time(val
);
281 /* Set time to now if it is unset or from the future (not allowed!) */
282 if ((tick
== 0) || (tick
> now
)) tick
= now
;
284 /* Canonical form: seconds since the epoch */
285 snprintf(buf
, sizeof(buf
) - 1, "%lu", tick
);
286 asl_set(msg
, ASL_KEY_TIME
, buf
);
289 val
= asl_get(msg
, ASL_KEY_HOST
);
290 if (val
== NULL
) asl_set(msg
, ASL_KEY_HOST
, whatsmyhostname());
293 val
= asl_get(msg
, ASL_KEY_UID
);
297 if ((uid
== 0) && strcmp(val
, "0")) uid
= -2;
298 if (uid_out
!= NULL
) *uid_out
= uid
;
302 val
= asl_get(msg
, ASL_KEY_GID
);
306 if ((gid
== 0) && strcmp(val
, "0")) gid
= -2;
313 case SOURCE_INTERNAL
:
315 asl_set(msg
, ASL_KEY_UID
, "0");
316 asl_set(msg
, ASL_KEY_GID
, "0");
319 case SOURCE_ASL_SOCKET
:
320 case SOURCE_ASL_MESSAGE
:
323 /* we trust the UID & GID in the message */
328 /* we do not trust the UID 0 or GID 0 or 80 in the message */
329 if (uid
== 0) asl_set(msg
, ASL_KEY_UID
, "-2");
330 if ((gid
== 0) || (gid
== 80)) asl_set(msg
, ASL_KEY_GID
, "-2");
335 val
= asl_get(msg
, ASL_KEY_SENDER
);
342 asl_set(msg
, ASL_KEY_SENDER
, "kernel");
345 case SOURCE_INTERNAL
:
347 asl_set(msg
, ASL_KEY_SENDER
, "syslogd");
352 asl_set(msg
, ASL_KEY_SENDER
, "Unknown");
356 else if ((source
!= SOURCE_KERN
) && (uid
!= 0) && (!strcmp(val
, "kernel")))
358 /* allow UID 0 to send messages with "Sender kernel", but nobody else */
359 asl_set(msg
, ASL_KEY_SENDER
, "Unknown");
363 fac
= asl_get(msg
, ASL_KEY_FACILITY
);
366 if (source
== SOURCE_KERN
) fac
= "kern";
368 asl_set(msg
, ASL_KEY_FACILITY
, fac
);
370 else if (fac
[0] == '#')
373 if ((fac
[1] >= '0') && (fac
[1] <= '9'))
375 fnum
= atoi(fac
+ 1) << 3;
376 if ((fnum
== 0) && (strcmp(fac
+ 1, "0"))) fnum
= LOG_USER
;
379 fac
= asl_syslog_faciliy_num_to_name(fnum
);
380 asl_set(msg
, ASL_KEY_FACILITY
, fac
);
382 else if (!strncmp(fac
, SYSTEM_RESERVED
, SYSTEM_RESERVED_LEN
))
384 /* only UID 0 may use "com.apple.system" */
385 if (uid
!= 0) asl_set(msg
, ASL_KEY_FACILITY
, FACILITY_USER
);
389 * kernel messages are only readable by root and admin group.
390 * all other messages are admin-only readable unless they already
391 * have specific read access controls set.
393 if (source
== SOURCE_KERN
)
395 asl_set(msg
, ASL_KEY_READ_UID
, "0");
396 asl_set(msg
, ASL_KEY_READ_GID
, "80");
400 ruval
= asl_get(msg
, ASL_KEY_READ_UID
);
401 rgval
= asl_get(msg
, ASL_KEY_READ_GID
);
403 if ((ruval
== NULL
) && (rgval
== NULL
))
405 asl_set(msg
, ASL_KEY_READ_GID
, "80");
409 /* Set DB Expire Time for com.apple.system.utmpx and lastlog */
410 if ((!strcmp(fac
, "com.apple.system.utmpx")) || (!strcmp(fac
, "com.apple.system.lastlog")))
412 snprintf(buf
, sizeof(buf
), "%lu", tick
+ global
.utmp_ttl
);
413 asl_set(msg
, ASL_KEY_EXPIRE_TIME
, buf
);
416 /* Set DB Expire Time for Filesystem errors */
417 if (!strcmp(fac
, FSLOG_VAL_FACILITY
))
419 snprintf(buf
, sizeof(buf
), "%lu", tick
+ FS_TTL_SEC
);
420 asl_set(msg
, ASL_KEY_EXPIRE_TIME
, buf
);
424 * special case handling of kernel disaster messages
426 if ((source
== SOURCE_KERN
) && (level
<= KERN_DISASTER_LEVEL
))
428 if (kern_post_level
!= NULL
) *kern_post_level
= level
;
429 disaster_message(msg
);
432 return VERIFY_STATUS_OK
;
436 list_append_msg(asl_search_result_t
*list
, aslmsg msg
)
438 if (list
== NULL
) return;
439 if (msg
== NULL
) return;
442 * NB: curr is the list size
443 * grow list if necessary
445 if (list
->count
== list
->curr
)
449 list
->msg
= (asl_msg_t
**)calloc(LIST_SIZE_DELTA
, sizeof(asl_msg_t
*));
453 list
->msg
= (asl_msg_t
**)reallocf(list
->msg
, (list
->curr
+ LIST_SIZE_DELTA
) * sizeof(asl_msg_t
*));
456 if (list
->msg
== NULL
)
463 list
->curr
+= LIST_SIZE_DELTA
;
466 list
->msg
[list
->count
] = (asl_msg_t
*)msg
;
475 OSSpinLockLock(&global
.lock
);
477 global
.pid
= getpid();
479 free(global
.debug_file
);
480 global
.debug_file
= NULL
;
481 global
.launchd_enabled
= 1;
483 #if TARGET_OS_EMBEDDED
484 global
.dbtype
= DB_TYPE_MINI
;
486 global
.dbtype
= DB_TYPE_FILE
;
488 global
.db_file_max
= DEFAULT_DB_FILE_MAX
;
489 global
.db_memory_max
= DEFAULT_DB_MEMORY_MAX
;
490 global
.db_mini_max
= DEFAULT_DB_MINI_MAX
;
491 global
.mps_limit
= DEFAULT_MPS_LIMIT
;
492 global
.remote_delay_time
= DEFAULT_REMOTE_DELAY
;
493 global
.bsd_max_dup_time
= DEFAULT_BSD_MAX_DUP_SEC
;
494 global
.mark_time
= DEFAULT_MARK_SEC
;
495 global
.utmp_ttl
= DEFAULT_UTMP_TTL_SEC
;
497 global
.asl_out_module
= asl_out_module_init();
498 OSSpinLockUnlock(&global
.lock
);
500 if (global
.asl_out_module
!= NULL
)
502 for (r
= global
.asl_out_module
->ruleset
; r
!= NULL
; r
= r
->next
)
504 if ((r
->action
== ACTION_SET_PARAM
) && (r
->query
== NULL
) && (!strncmp(r
->options
, "debug", 5))) control_set_param(r
->options
, true);
510 * Used to set config parameters.
511 * Line format "= name value"
514 control_set_param(const char *s
, bool eval
)
517 uint32_t intval
, count
, v32a
, v32b
, v32c
;
519 if (s
== NULL
) return -1;
520 if (s
[0] == '\0') return 0;
522 /* skip '=' and whitespace */
524 while ((*s
== ' ') || (*s
== '\t')) s
++;
526 l
= explode(s
, " \t");
527 if (l
== NULL
) return -1;
529 for (count
= 0; l
[count
] != NULL
; count
++);
531 /* name is required */
538 /* Check variables that allow 0 or 1 / boolean */
539 if (!strcasecmp(l
[0], "debug"))
541 /* = debug [0|1] [file] */
544 intval
= (eval
) ? 1 : 0;
545 config_debug(intval
, NULL
);
547 else if (!strcmp(l
[1], "0"))
549 config_debug(0, l
[2]);
551 else if (!strcmp(l
[1], "1"))
553 config_debug(1, l
[2]);
557 intval
= (eval
) ? 1 : 0;
558 config_debug(intval
, l
[1]);
565 /* value is required */
572 if (!strcasecmp(l
[0], "mark_time"))
574 /* = mark_time seconds */
575 OSSpinLockLock(&global
.lock
);
576 if (eval
) global
.mark_time
= atoll(l
[1]);
577 else global
.mark_time
= 0;
578 OSSpinLockUnlock(&global
.lock
);
580 else if (!strcasecmp(l
[0], "dup_delay"))
582 /* = bsd_max_dup_time seconds */
583 OSSpinLockLock(&global
.lock
);
584 if (eval
) global
.bsd_max_dup_time
= atoll(l
[1]);
585 else global
.bsd_max_dup_time
= DEFAULT_BSD_MAX_DUP_SEC
;
586 OSSpinLockUnlock(&global
.lock
);
588 else if (!strcasecmp(l
[0], "remote_delay"))
590 /* = remote_delay microseconds */
591 OSSpinLockLock(&global
.lock
);
592 if (eval
) global
.remote_delay_time
= atol(l
[1]);
593 else global
.remote_delay_time
= DEFAULT_REMOTE_DELAY
;
594 OSSpinLockUnlock(&global
.lock
);
596 else if (!strcasecmp(l
[0], "utmp_ttl"))
598 /* = utmp_ttl seconds */
599 OSSpinLockLock(&global
.lock
);
600 if (eval
) global
.utmp_ttl
= (time_t)atoll(l
[1]);
601 else global
.utmp_ttl
= DEFAULT_UTMP_TTL_SEC
;
602 OSSpinLockUnlock(&global
.lock
);
604 else if (!strcasecmp(l
[0], "mps_limit"))
606 /* = mps_limit number */
607 OSSpinLockLock(&global
.lock
);
608 if (eval
) global
.mps_limit
= (uint32_t)atol(l
[1]);
609 else global
.mps_limit
= DEFAULT_MPS_LIMIT
;
610 OSSpinLockUnlock(&global
.lock
);
612 else if (!strcasecmp(l
[0], "max_file_size"))
614 /* = max_file_size bytes */
615 pthread_mutex_lock(global
.db_lock
);
617 if (global
.dbtype
& DB_TYPE_FILE
)
619 asl_store_close(global
.file_db
);
620 global
.file_db
= NULL
;
621 if (eval
) global
.db_file_max
= atoi(l
[1]);
622 else global
.db_file_max
= DEFAULT_DB_FILE_MAX
;
625 pthread_mutex_unlock(global
.db_lock
);
627 else if ((!strcasecmp(l
[0], "db")) || (!strcasecmp(l
[0], "database")) || (!strcasecmp(l
[0], "datastore")))
629 /* NB this is private / unpublished */
630 /* = db type [max]... */
637 if ((l
[1][0] >= '0') && (l
[1][0] <= '9'))
640 if ((count
>= 3) && (strcmp(l
[2], "-"))) v32a
= atoi(l
[2]);
641 if ((count
>= 4) && (strcmp(l
[3], "-"))) v32b
= atoi(l
[3]);
642 if ((count
>= 5) && (strcmp(l
[4], "-"))) v32c
= atoi(l
[4]);
644 else if (!strcasecmp(l
[1], "file"))
646 intval
= DB_TYPE_FILE
;
647 if ((count
>= 3) && (strcmp(l
[2], "-"))) v32a
= atoi(l
[2]);
649 else if (!strncasecmp(l
[1], "mem", 3))
651 intval
= DB_TYPE_MEMORY
;
652 if ((count
>= 3) && (strcmp(l
[2], "-"))) v32b
= atoi(l
[2]);
654 else if (!strncasecmp(l
[1], "min", 3))
656 intval
= DB_TYPE_MINI
;
657 if ((count
>= 3) && (strcmp(l
[2], "-"))) v32c
= atoi(l
[2]);
665 if (v32a
== 0) v32a
= global
.db_file_max
;
666 if (v32b
== 0) v32b
= global
.db_memory_max
;
667 if (v32c
== 0) v32c
= global
.db_mini_max
;
669 config_data_store(intval
, v32a
, v32b
, v32c
);
673 #if TARGET_OS_EMBEDDED
674 intval
= DB_TYPE_MINI
;
676 intval
= DB_TYPE_FILE
;
678 config_data_store(intval
, DEFAULT_DB_FILE_MAX
, DEFAULT_DB_MEMORY_MAX
, DEFAULT_DB_MINI_MAX
);
687 control_message(aslmsg msg
)
689 const char *str
= asl_get(msg
, ASL_KEY_MSG
);
691 if (str
== NULL
) return 0;
693 if (!strncmp(str
, "= reset", 7))
696 return asl_action_reset();
698 else if (!strncmp(str
, "= crash", 7))
702 else if (!strncmp(str
, "@ ", 2))
704 return asl_action_control_set_param(str
);
706 else if (!strncmp(str
, "= ", 2))
708 return control_set_param(str
, true);
715 process_message(aslmsg msg
, uint32_t source
)
717 if (msg
== NULL
) return;
719 OSAtomicIncrement32(&global
.work_queue_count
);
720 dispatch_async(global
.work_queue
, ^{
728 status
= aslmsg_verify(msg
, source
, &kplevel
, &uid
);
729 if (status
== VERIFY_STATUS_OK
)
731 if ((source
== SOURCE_KERN
) && (kplevel
>= 0))
733 if (kplevel
> 7) kplevel
= 7;
734 if (kern_notify_token
[kplevel
] < 0)
736 status
= notify_register_plain(kern_notify_key
[kplevel
], &(kern_notify_token
[kplevel
]));
737 if (status
!= 0) asldebug("notify_register_plain(%s) failed status %u\n", status
);
740 notify_post(kern_notify_key
[kplevel
]);
743 if ((uid
== 0) && asl_check_option(msg
, ASL_OPT_CONTROL
)) control_message(msg
);
745 /* send message to output modules */
746 asl_out_message(msg
);
747 #if !TARGET_IPHONE_SIMULATOR
748 if (global
.bsd_out_enabled
) bsd_out_message(msg
);
753 OSAtomicDecrement32(&global
.work_queue_count
);
758 internal_log_message(const char *str
)
762 if (str
== NULL
) return 1;
764 msg
= (aslmsg
)asl_msg_from_string(str
);
765 if (msg
== NULL
) return 1;
767 process_message(msg
, SOURCE_INTERNAL
);
773 asldebug(const char *str
, ...)
778 if (global
.debug
== 0) return 0;
780 if (global
.debug_file
== NULL
) dfp
= fopen(_PATH_SYSLOGD_LOG
, "a");
781 else dfp
= fopen(global
.debug_file
, "a");
782 if (dfp
== NULL
) return 0;
785 vfprintf(dfp
, str
, v
);
798 asprintf(&str
, "[Sender syslogd] [Level 6] [PID %u] [Message -- MARK --] [UID 0] [UID 0] [Facility syslog]", global
.pid
);
799 internal_log_message(str
);
804 asl_syslog_input_convert(const char *in
, int len
, char *rhost
, uint32_t source
)
806 int pf
, pri
, index
, n
;
807 char *p
, *colon
, *brace
, *space
, *tmp
, *tval
, *hval
, *sval
, *pval
, *mval
;
814 if (in
== NULL
) return NULL
;
815 if (len
<= 0) return NULL
;
828 /* skip leading whitespace */
829 while ((index
< len
) && ((*p
== ' ') || (*p
== '\t')))
835 if (index
>= len
) return NULL
;
837 /* parse "<NN>" priority (level and facility) */
843 n
= sscanf(p
, "%d", &pf
);
847 if (pf
> 0x7) fval
= asl_syslog_faciliy_num_to_name(pf
& LOG_FACMASK
);
850 while ((index
< len
) && (*p
!= '>'))
863 snprintf(prival
, sizeof(prival
), "%d", pri
);
865 /* check if a timestamp is included */
866 if (((len
- index
) > 15) && (p
[9] == ':') && (p
[12] == ':') && (p
[15] == ' '))
869 if (tmp
== NULL
) return NULL
;
874 tick
= asl_parse_time(tmp
);
875 if (tick
== (time_t)-1)
882 gmtime_r(&tick
, &time
);
883 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
);
890 /* stop here for kernel messages */
891 if (source
== SOURCE_KERN
)
893 msg
= asl_new(ASL_TYPE_MSG
);
894 if (msg
== NULL
) return NULL
;
896 asl_set(msg
, ASL_KEY_MSG
, p
);
897 asl_set(msg
, ASL_KEY_LEVEL
, prival
);
898 asl_set(msg
, ASL_KEY_PID
, "0");
903 /* if message is from a network socket, hostname follows */
904 if (source
== SOURCE_UDP_SOCKET
)
906 space
= strchr(p
, ' ');
910 hval
= malloc(n
+ 1);
911 if (hval
== NULL
) return NULL
;
921 colon
= strchr(p
, ':');
922 brace
= strchr(p
, '[');
924 /* check for "sender:" or sender[pid]:" */
927 if ((brace
!= NULL
) && (brace
< colon
))
930 sval
= malloc(n
+ 1);
931 if (sval
== NULL
) return NULL
;
936 n
= colon
- (brace
+ 1) - 1;
937 pval
= malloc(n
+ 1);
938 if (pval
== NULL
) return NULL
;
940 memcpy(pval
, (brace
+ 1), n
);
946 sval
= malloc(n
+ 1);
947 if (sval
== NULL
) return NULL
;
967 mval
= malloc(n
+ 1);
968 if (mval
== NULL
) return NULL
;
974 if (fval
== NULL
) fval
= asl_syslog_faciliy_num_to_name(LOG_USER
);
976 msg
= asl_new(ASL_TYPE_MSG
);
977 if (msg
== NULL
) return NULL
;
981 asl_set(msg
, ASL_KEY_TIME
, tval
);
985 if (fval
!= NULL
) asl_set(msg
, "Facility", fval
);
986 else asl_set(msg
, "Facility", "user");
990 asl_set(msg
, ASL_KEY_SENDER
, sval
);
996 asl_set(msg
, ASL_KEY_PID
, pval
);
1001 asl_set(msg
, ASL_KEY_PID
, "-1");
1006 asl_set(msg
, ASL_KEY_MSG
, mval
);
1010 asl_set(msg
, ASL_KEY_LEVEL
, prival
);
1011 asl_set(msg
, ASL_KEY_UID
, "-2");
1012 asl_set(msg
, ASL_KEY_GID
, "-2");
1016 asl_set(msg
, ASL_KEY_HOST
, hval
);
1019 else if (rhost
!= NULL
)
1021 asl_set(msg
, ASL_KEY_HOST
, rhost
);
1028 asl_input_parse(const char *in
, int len
, char *rhost
, uint32_t source
)
1031 int status
, x
, legacy
, off
;
1033 asldebug("asl_input_parse: %s\n", (in
== NULL
) ? "NULL" : in
);
1035 if (in
== NULL
) return NULL
;
1040 /* calculate length if not provided */
1041 if (len
== 0) len
= strlen(in
);
1044 * Determine if the input is "old" syslog format or new ASL format.
1045 * Old format lines should start with "<", but they can just be straight text.
1046 * ASL input may start with a length (10 bytes) followed by a space and a '['.
1047 * The length is optional, so ASL messages may also just start with '['.
1049 if ((in
[0] != '<') && (len
> 11))
1051 status
= sscanf(in
, "%d ", &x
);
1052 if ((status
== 1) && (in
[10] == ' ') && (in
[11] == '[')) legacy
= 0;
1055 if (legacy
== 1) return asl_syslog_input_convert(in
, len
, rhost
, source
);
1058 if (in
[0] == '[') off
= 0;
1060 msg
= (aslmsg
)asl_msg_from_string(in
+ off
);
1061 if (msg
== NULL
) return NULL
;
1063 if (rhost
!= NULL
) asl_set(msg
, ASL_KEY_HOST
, rhost
);
1068 #if !TARGET_IPHONE_SIMULATOR
1070 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
)
1076 if (global
.launchd_enabled
== 0) return;
1079 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",
1080 when->tv_sec, when->tv_usec, from_pid, about_pid, sender_uid, sender_gid, priority, from_name, about_name, session_name, msg);
1083 m
= asl_new(ASL_TYPE_MSG
);
1084 if (m
== NULL
) return;
1087 if (priority
< ASL_LEVEL_EMERG
) priority
= ASL_LEVEL_EMERG
;
1088 if (priority
> ASL_LEVEL_DEBUG
) priority
= ASL_LEVEL_DEBUG
;
1089 snprintf(str
, sizeof(str
), "%d", priority
);
1091 asl_set(m
, ASL_KEY_LEVEL
, str
);
1096 snprintf(str
, sizeof(str
), "%lu", when
->tv_sec
);
1097 asl_set(m
, ASL_KEY_TIME
, str
);
1099 snprintf(str
, sizeof(str
), "%lu", 1000 * (unsigned long int)when
->tv_usec
);
1100 asl_set(m
, ASL_KEY_TIME_NSEC
, str
);
1105 snprintf(str
, sizeof(str
), "%lu", now
);
1106 asl_set(m
, ASL_KEY_TIME
, str
);
1110 asl_set(m
, ASL_KEY_FACILITY
, FACILITY_CONSOLE
);
1113 snprintf(str
, sizeof(str
), "%u", (unsigned int)sender_uid
);
1114 asl_set(m
, ASL_KEY_UID
, str
);
1117 snprintf(str
, sizeof(str
), "%u", (unsigned int)sender_gid
);
1118 asl_set(m
, ASL_KEY_GID
, str
);
1123 snprintf(str
, sizeof(str
), "%u", (unsigned int)from_pid
);
1124 asl_set(m
, ASL_KEY_PID
, str
);
1128 if ((about_pid
> 0) && (about_pid
!= from_pid
))
1130 snprintf(str
, sizeof(str
), "%u", (unsigned int)about_pid
);
1131 asl_set(m
, ASL_KEY_REF_PID
, str
);
1135 if (from_name
!= NULL
)
1137 asl_set(m
, ASL_KEY_SENDER
, from_name
);
1141 if (sender_uid
!= 0)
1143 snprintf(str
, sizeof(str
), "%d", (int)sender_uid
);
1144 asl_set(m
, ASL_KEY_READ_UID
, str
);
1147 /* Reference Process */
1148 if (about_name
!= NULL
)
1150 if ((from_name
!= NULL
) && (strcmp(from_name
, about_name
) != 0))
1152 asl_set(m
, ASL_KEY_REF_PROC
, about_name
);
1157 if (session_name
!= NULL
)
1159 asl_set(m
, ASL_KEY_SESSION
, session_name
);
1165 asl_set(m
, ASL_KEY_MSG
, msg
);
1168 process_message(m
, SOURCE_LAUNCHD
);