2 * Copyright (c) 2004-2007 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * "Portions Copyright (c) 2004 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@
35 #include <crt_externs.h>
37 #include <asl_private.h>
40 #include <mach/mach.h>
41 #include <mach/std_types.h>
43 #include <mach/mach_types.h>
44 #include <sys/types.h>
45 #include <servers/bootstrap.h>
49 #define ASL_SERVICE_NAME "com.apple.system.logger"
51 #define streq(A, B) (strcmp(A, B) == 0)
52 #define strcaseeq(A, B) (strcasecmp(A, B) == 0)
54 #define forever for(;;)
78 #define XML_TAG_STRING 1
79 #define XML_TAG_DATA 2
81 #define FETCH_BATCH 256
84 time_t asl_parse_time(const char *);
85 const char *asl_syslog_faciliy_num_to_name(int n
);
86 __private_extern__ asl_client_t
*_asl_open_default();
89 uint32_t notify_register_plain(const char *name
, int *out_token
);
92 int _asl_server_socket(int *sock
, struct sockaddr_un
*server
);
93 int asl_is_utf8(const char *str
);
94 uint8_t *asl_b64_encode(const uint8_t *buf
, size_t len
);
96 /* character encoding lengths */
97 static const uint8_t char_encode_len
[128] =
99 2, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
100 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
101 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1,
102 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3
105 static const char *cvis_7_13
= "abtnvfr";
113 pthread_mutex_t lock
;
117 #ifndef BUILDING_VARIANT
118 __private_extern__ _asl_global_t _asl_global
= {0, -1, -1, NULL
, PTHREAD_MUTEX_INITIALIZER
, NULL
};
120 static mach_port_t asl_server_port
= MACH_PORT_NULL
;
123 _asl_connect(asl_client_t
*asl
)
125 if (asl
->sock
>= 0) return 0;
127 return _asl_server_socket(&asl
->sock
, &asl
->server
);
131 _asl_notify_open(int do_lock
)
137 if (do_lock
!= 0) pthread_mutex_lock(&_asl_global
.lock
);
139 _asl_global
.notify_count
++;
141 if (_asl_global
.notify_token
!= -1)
143 if (do_lock
!= 0) pthread_mutex_unlock(&_asl_global
.lock
);
149 prefix
= NOTIFY_PREFIX_USER
;
150 if (getuid() == 0) prefix
= NOTIFY_PREFIX_SYSTEM
;
152 if (_asl_global
.master_token
== -1)
154 status
= notify_register_plain(NOTIFY_SYSTEM_MASTER
, &_asl_global
.master_token
);
155 if (status
!= NOTIFY_STATUS_OK
) _asl_global
.master_token
= -1;
158 asprintf(¬ify_name
, "%s.%d", prefix
, getpid());
160 if (notify_name
!= NULL
)
162 status
= notify_register_plain(notify_name
, &_asl_global
.notify_token
);
164 if (status
!= NOTIFY_STATUS_OK
) _asl_global
.notify_token
= -1;
167 if (do_lock
!= 0) pthread_mutex_unlock(&_asl_global
.lock
);
169 if (_asl_global
.notify_token
== -1) return -1;
176 pthread_mutex_lock(&_asl_global
.lock
);
178 if (_asl_global
.notify_count
> 0) _asl_global
.notify_count
--;
180 if (_asl_global
.notify_count
> 0)
182 pthread_mutex_unlock(&_asl_global
.lock
);
186 if (_asl_global
.master_token
> 0) notify_cancel(_asl_global
.master_token
);
187 _asl_global
.master_token
= -1;
189 if (_asl_global
.notify_token
> 0) notify_cancel(_asl_global
.notify_token
);
190 _asl_global
.notify_token
= -1;
192 pthread_mutex_unlock(&_asl_global
.lock
);
196 asl_open(const char *ident
, const char *facility
, uint32_t opts
)
201 asl
= (asl_client_t
*)calloc(1, sizeof(asl_client_t
));
212 if (asl
->options
& ASL_OPT_NO_DELAY
)
214 if (_asl_connect(asl
) < 0)
225 asl
->filter
= ASL_FILTER_MASK_UPTO(ASL_LEVEL_NOTICE
);
229 asl
->name
= strdup(ident
);
230 if (asl
->name
== NULL
)
239 name
= *(*_NSGetArgv());
242 x
= strrchr(name
, '/');
245 asl
->name
= strdup(x
);
246 if (asl
->name
== NULL
)
255 asl
->facility
= NULL
;
256 if (facility
!= NULL
) asl
->facility
= strdup(facility
);
257 else asl
->facility
= strdup(asl_syslog_faciliy_num_to_name(LOG_USER
));
258 if (asl
->facility
== NULL
)
265 if (!(asl
->options
& ASL_OPT_NO_REMOTE
)) _asl_notify_open(1);
267 if (asl
->options
& ASL_OPT_STDERR
) asl_add_output((aslclient
)asl
, fileno(stderr
), ASL_MSG_FMT_STD
, ASL_TIME_FMT_LCL
);
269 return (aslclient
)asl
;
273 asl_close(aslclient ac
)
278 asl
= (asl_client_t
*)ac
;
279 if (asl
== NULL
) return;
281 if (asl
->sock
>= 0) close(asl
->sock
);
282 if (asl
->name
!= NULL
) free(asl
->name
);
283 if (asl
->facility
!= NULL
) free(asl
->facility
);
284 if (!(asl
->options
& ASL_OPT_NO_REMOTE
)) _asl_notify_close();
285 if (asl
->fd_list
!= NULL
) free(asl
->fd_list
);
287 if (asl
->fd_mfmt
!= NULL
)
289 for (i
= 0; i
< asl
->fd_count
; i
++) if (asl
->fd_mfmt
[i
] != NULL
) free(asl
->fd_mfmt
[i
]);
293 if (asl
->fd_tfmt
!= NULL
)
295 for (i
= 0; i
< asl
->fd_count
; i
++) if (asl
->fd_tfmt
[i
] != NULL
) free(asl
->fd_tfmt
[i
]);
299 memset(asl
, 0, sizeof(asl_client_t
));
303 __private_extern__ asl_client_t
*
306 pthread_mutex_lock(&_asl_global
.lock
);
307 if (_asl_global
.asl
!= NULL
)
309 pthread_mutex_unlock(&_asl_global
.lock
);
310 return _asl_global
.asl
;
314 * Do a sleight-of-hand with ASL_OPT_NO_REMOTE to avoid a deadlock
315 * since asl_open(xxx, yyy, 0) calls _asl_notify_open(1)
316 * which locks _asl_global.lock.
318 _asl_global
.asl
= asl_open(NULL
, NULL
, ASL_OPT_NO_REMOTE
);
320 /* Reset options to clear ASL_OPT_NO_REMOTE bit */
321 if (_asl_global
.asl
!= NULL
) _asl_global
.asl
->options
= 0;
323 /* Now call _asl_notify_open(0) to finish the work */
326 pthread_mutex_unlock(&_asl_global
.lock
);
328 return _asl_global
.asl
;
332 _asl_msg_index(asl_msg_t
*msg
, const char *k
)
336 if (msg
== NULL
) return (uint32_t)-1;
337 if (k
== NULL
) return (uint32_t)-1;
339 for (i
= 0; i
< msg
->count
; i
++)
341 if (msg
->key
[i
] == NULL
) continue;
342 if (streq(msg
->key
[i
], k
)) return i
;
349 _asl_encode_char(char **m
, uint32_t *x
, uint32_t c
, uint32_t encode
, uint32_t encode_space
)
358 /* NUL is not allowed */
361 /* Meta chars get \M prefix */
364 /* except meta-space, which is \240 */
384 /* space is either ' ' or \s */
387 if (encode_space
== 0)
403 if ((meta
== 0) && (c
== 92))
412 /* [ and ] ane escaped in ASL encoding */
413 if ((encode
== ENCODE_ASL
) && (meta
== 0) && ((c
== 91) || (c
== 93)))
438 /* 33-126 are printable (add a '-' prefix for meta) */
439 if ((c
>= 33) && (c
<= 126))
453 /* non-meta BEL, BS, HT, NL, VT, NP, CR (7-13) are \a, \b, \t, \n, \v, \f, and \r */
454 if ((meta
== 0) && (c
>= 7) && (c
<= 13))
457 *p
++ = cvis_7_13
[c
- 7];
463 /* 0 - 31 are ^@ - ^_ (non-meta get a leading \) */
464 if ((c
>= 0) && (c
<= 31))
483 _asl_append_string(char **m
, uint32_t *x
, const char *s
, uint32_t encode
, uint32_t escspace
)
485 uint32_t i
, n
, spextra
;
488 if (m
== NULL
) return;
489 if (x
== NULL
) return;
490 if (s
== NULL
) return;
492 if (encode
== ENCODE_NONE
)
504 *m
= reallocf(*m
, n
+ (*x
));
507 if (*m
== NULL
) return;
509 memcpy((*m
) + (*x
) - 1, s
, n
+ 1);
517 if (escspace
!= 0) spextra
= 1;
520 for (i
= 0; s
[i
] != '\0'; i
++)
528 else if ((c
== 91) || (c
== 93))
530 if (encode
== ENCODE_ASL
) n
+= 2;
535 n
+= char_encode_len
[c
];
536 if (c
== 32) n
+= spextra
;
549 *m
= reallocf(*m
, n
+ (*x
));
552 if (*m
== NULL
) return;
554 for (i
= 0; s
[i
] != '\0'; i
++)
557 _asl_encode_char(m
, x
, c
, encode
, escspace
);
564 _asl_append_xml_string(char **m
, uint32_t *x
, char *s
)
570 if (m
== NULL
) return;
571 if (x
== NULL
) return;
572 if (s
== NULL
) return;
575 for (i
= 0; s
[i
] != '\0'; i
++)
580 * XML wants & < > " and '
581 * We use &#xnn; for control chars.
582 * Everything else just gets printed "as is" (we know the input is UTF8)
584 if (c
== '&') n
+= 5;
585 else if (c
== '<') n
+= 4;
586 else if (c
== '>') n
+= 4;
587 else if (c
== '"') n
+= 6;
588 else if (c
== '\'') n
+= 6;
589 else if (iscntrl(c
)) n
+= 6;
602 *m
= reallocf(*m
, n
+ (*x
));
605 if (*m
== NULL
) return;
607 for (i
= 0; s
[i
] != '\0'; i
++)
614 memcpy(p
, "&", 5);
622 memcpy(p
, "<", 4);
630 memcpy(p
, ">", 4);
638 memcpy(p
, """, 6);
646 memcpy(p
, "'", 6);
653 snprintf(tmp
, sizeof(tmp
), "&#x%02hhu;", c
);
673 _asl_append_xml_tag(char **m
, uint32_t *x
, int tag
, char *s
)
677 if (m
== NULL
) return;
678 if (x
== NULL
) return;
680 if (tag
== XML_TAG_KEY
)
682 _asl_append_string(m
, x
, "\t\t<key>", ENCODE_NONE
, 0);
683 _asl_append_xml_string(m
, x
, s
);
684 _asl_append_string(m
, x
, "</key>\n", ENCODE_NONE
, 0);
688 if (tag
== XML_TAG_STRING
)
690 _asl_append_string(m
, x
, "\t\t<string>", ENCODE_NONE
, 0);
691 _asl_append_xml_string(m
, x
, s
);
692 _asl_append_string(m
, x
, "</string>\n", ENCODE_NONE
, 0);
696 if (tag
== XML_TAG_DATA
)
698 _asl_append_string(m
, x
, "\t\t<data>", ENCODE_NONE
, 0);
699 b64
= (char *)asl_b64_encode((uint8_t *)s
, strlen(s
));
702 _asl_append_string(m
, x
, b64
, ENCODE_NONE
, 0);
705 _asl_append_string(m
, x
, "</data>\n", ENCODE_NONE
, 0);
711 _asl_append_op(char **m
, uint32_t *x
, uint32_t op
)
716 if (m
== NULL
) return;
717 if (x
== NULL
) return;
719 if (op
== ASL_QUERY_OP_NULL
) return _asl_append_string(m
, x
, ".", ENCODE_NONE
, 0);
722 if (op
& ASL_QUERY_OP_CASEFOLD
) opstr
[i
++] = 'C';
724 if (op
& ASL_QUERY_OP_REGEX
) opstr
[i
++] = 'R';
726 if (op
& ASL_QUERY_OP_NUMERIC
) opstr
[i
++] = 'N';
728 if (op
& ASL_QUERY_OP_PREFIX
)
730 if (op
& ASL_QUERY_OP_SUFFIX
) opstr
[i
++] = 'S';
731 else opstr
[i
++] = 'A';
733 if (op
& ASL_QUERY_OP_SUFFIX
) opstr
[i
++] = 'Z';
735 switch (op
& ASL_QUERY_OP_TRUE
)
737 case ASL_QUERY_OP_EQUAL
:
740 case ASL_QUERY_OP_GREATER
:
743 case ASL_QUERY_OP_GREATER_EQUAL
:
747 case ASL_QUERY_OP_LESS
:
750 case ASL_QUERY_OP_LESS_EQUAL
:
754 case ASL_QUERY_OP_NOT_EQUAL
:
757 case ASL_QUERY_OP_TRUE
:
764 if (i
== 0) return _asl_append_string(m
, x
, ".", ENCODE_NONE
, 0);
767 return _asl_append_string(m
, x
, opstr
, ENCODE_NONE
, 0);
771 _asl_time_string(int fmt
, const char *str
)
781 if (str
!= NULL
) tick
= asl_parse_time(str
);
785 asprintf(&out
, "%lu", tick
);
792 asprintf(&out
, "%d.%02d.%02d %02d:%02d:%02d UTC", stm
->tm_year
+ 1900, stm
->tm_mon
+ 1, stm
->tm_mday
, stm
->tm_hour
, stm
->tm_min
, stm
->tm_sec
);
798 ltime
= ctime_r(&tick
, ltbuf
);
799 if (ltime
== NULL
) return NULL
;
801 asprintf(&out
, "%s", ltime
);
809 _asl_msg_to_string_time_fmt(asl_msg_t
*msg
, uint32_t *len
, int tf
)
816 if (msg
== NULL
) return NULL
;
824 if (out
== NULL
) return NULL
;
829 for (i
= 0; i
< msg
->count
; i
++)
831 if (msg
->key
[i
] == NULL
) continue;
832 if (i
> 0) _asl_append_string(&out
, &outlen
, " [", ENCODE_NONE
, 0);
833 else _asl_append_string(&out
, &outlen
, "[", ENCODE_NONE
, 0);
835 _asl_append_string(&out
, &outlen
, msg
->key
[i
], ENCODE_ASL
, 1);
837 if ((tf
!= TFMT_SEC
) && (!strcmp(msg
->key
[i
], ASL_KEY_TIME
)))
839 s
= _asl_time_string(tf
, msg
->val
[i
]);
842 _asl_append_string(&out
, &outlen
, " ", ENCODE_NONE
, 0);
843 _asl_append_string(&out
, &outlen
, s
, ENCODE_ASL
, 0);
846 else if (msg
->val
[i
] != NULL
)
848 _asl_append_string(&out
, &outlen
, " ", ENCODE_NONE
, 0);
849 _asl_append_string(&out
, &outlen
, msg
->val
[i
], ENCODE_ASL
, 0);
852 _asl_append_string(&out
, &outlen
, "]", ENCODE_NONE
, 0);
855 _asl_append_string(&out
, &outlen
, "\n", ENCODE_NONE
, 0);
862 asl_msg_to_string(asl_msg_t
*msg
, uint32_t *len
)
869 if (msg
== NULL
) return NULL
;
875 if (msg
->type
== ASL_TYPE_QUERY
)
877 _asl_append_string(&out
, &outlen
, "Q ", ENCODE_NONE
, 0);
878 if (out
== NULL
) return NULL
;
883 if (out
== NULL
) return NULL
;
888 for (i
= 0; i
< msg
->count
; i
++)
890 if (msg
->key
[i
] == NULL
) continue;
892 if (i
> 0) _asl_append_string(&out
, &outlen
, " [", ENCODE_NONE
, 0);
893 else _asl_append_string(&out
, &outlen
, "[", ENCODE_NONE
, 0);
895 if (msg
->type
== ASL_TYPE_QUERY
)
897 _asl_append_op(&out
, &outlen
, msg
->op
[i
]);
898 _asl_append_string(&out
, &outlen
, " ", ENCODE_NONE
, 0);
901 _asl_append_string(&out
, &outlen
, msg
->key
[i
], ENCODE_ASL
, 1);
903 if (msg
->val
[i
] != NULL
)
905 _asl_append_string(&out
, &outlen
, " ", ENCODE_NONE
, 0);
906 _asl_append_string(&out
, &outlen
, msg
->val
[i
], ENCODE_ASL
, 0);
909 _asl_append_string(&out
, &outlen
, "]", ENCODE_NONE
, 0);
917 _asl_msg_op_from_string(char *o
)
921 op
= ASL_QUERY_OP_NULL
;
923 if (o
== NULL
) return op
;
925 for (i
= 0; o
[i
] != '\0'; i
++)
927 if (o
[i
] == '.') return ASL_QUERY_OP_NULL
;
928 if (o
[i
] == 'C') op
|= ASL_QUERY_OP_CASEFOLD
;
929 if (o
[i
] == 'R') op
|= ASL_QUERY_OP_REGEX
;
930 if (o
[i
] == 'N') op
|= ASL_QUERY_OP_NUMERIC
;
931 if (o
[i
] == 'S') op
|= ASL_QUERY_OP_SUBSTRING
;
932 if (o
[i
] == 'A') op
|= ASL_QUERY_OP_PREFIX
;
933 if (o
[i
] == 'Z') op
|= ASL_QUERY_OP_SUFFIX
;
934 if (o
[i
] == '<') op
|= ASL_QUERY_OP_LESS
;
935 if (o
[i
] == '>') op
|= ASL_QUERY_OP_GREATER
;
936 if (o
[i
] == '=') op
|= ASL_QUERY_OP_EQUAL
;
937 if (o
[i
] == '!') op
|= ASL_QUERY_OP_NOT_EQUAL
;
938 if (o
[i
] == 'T') op
|= ASL_QUERY_OP_TRUE
;
945 _asl_msg_get_next_word(char **p
, uint32_t *tt
, uint32_t spacedel
)
947 char *str
, *out
, c
, oval
;
948 uint32_t i
, len
, n
, outlen
;
952 if (p
== NULL
) return NULL
;
953 if (*p
== NULL
) return NULL
;
954 if (**p
== '\0') return NULL
;
956 /* skip one space if it's there (word separator) */
957 if (**p
== ' ') (*p
)++;
959 /* skip leading white space */
962 while ((**p
== ' ') || (**p
== '\t')) (*p
)++;
965 if (**p
== '\0') return NULL
;
966 if (**p
== '\n') return NULL
;
977 if (out
== NULL
) return NULL
;
984 /* scan for token and calulate it's length (input and decoded output len) */
992 /* stop scanning when we hit a delimiter */
993 if (((spacedel
!= 0) && (c
== ' ')) || (c
== ']') || (c
== '\0')) break;
999 if ((c
== 'a') || (c
== 'b') || (c
== 't') || (c
== 'n') || (c
== 'v') || (c
== 'f') || (c
== 'r') || (c
== 's') || (c
== '[') || (c
== '\\') || (c
== ']'))
1004 if (str
[++len
] == '\0') return NULL
;
1008 if (str
[++len
] == '\0') return NULL
;
1009 if (str
[++len
] == '\0') return NULL
;
1011 else if ((c
>= '0') && (c
<= '3'))
1013 if (str
[++len
] == '\0') return NULL
;
1014 if (str
[++len
] == '\0') return NULL
;
1028 if ((len
== 0) && (**p
== ']'))
1033 if (out
== NULL
) return NULL
;
1042 out
= malloc(outlen
+ 1);
1043 if (out
== NULL
) return NULL
;
1046 for (i
= 0; i
< len
; i
++)
1103 if (str
[i
] == '?') out
[n
++] = 127;
1104 else out
[n
++] = str
[i
] - 64;
1113 if (str
[i
] == '?') out
[n
++] = 255;
1114 else out
[n
++] = str
[i
] + 64;
1119 out
[n
++] = str
[i
] + 128;
1129 else if ((c
>= '0') && (c
<= '3'))
1131 oval
= (c
- '0') * 64;
1135 if ((c
< '0') || (c
> '7'))
1142 oval
+= ((c
- '0') * 8);
1146 if ((c
< '0') || (c
> '7'))
1167 if ((c
< '0') || (c
> '9')) *tt
= TOKEN_WORD
;
1178 asl_msg_from_string(const char *buf
)
1180 uint32_t tt
, type
, op
;
1181 char *k
, *v
, *o
, *p
;
1184 if (buf
== NULL
) return NULL
;
1186 type
= ASL_TYPE_MSG
;
1189 k
= _asl_msg_get_next_word(&p
, &tt
, 1);
1190 if (k
== NULL
) return NULL
;
1194 type
= ASL_TYPE_QUERY
;
1197 k
= _asl_msg_get_next_word(&p
, &tt
, 1);
1199 else if (tt
== TOKEN_INT
)
1201 /* Leading integer is a string length - skip it */
1203 k
= _asl_msg_get_next_word(&p
, &tt
, 1);
1204 if (k
== NULL
) return NULL
;
1207 msg
= calloc(1, sizeof(asl_msg_t
));
1208 if (msg
== NULL
) return NULL
;
1212 /* OPEN WORD [WORD [WORD]] CLOSE */
1215 op
= ASL_QUERY_OP_NULL
;
1217 if (tt
!= TOKEN_OPEN
)
1225 /* get op for query type */
1226 if (type
== ASL_TYPE_QUERY
)
1228 o
= _asl_msg_get_next_word(&p
, &tt
, 1);
1229 if ((o
== NULL
) || (tt
!= TOKEN_WORD
))
1231 if (o
!= NULL
) free(o
);
1236 op
= _asl_msg_op_from_string(o
);
1240 k
= _asl_msg_get_next_word(&p
, &tt
, 1);
1241 if (tt
== TOKEN_INT
) tt
= TOKEN_WORD
;
1242 if ((k
== NULL
) || (tt
!= TOKEN_WORD
))
1244 if (k
!= NULL
) free(k
);
1249 v
= _asl_msg_get_next_word(&p
, &tt
, 0);
1250 if (tt
== TOKEN_INT
) tt
= TOKEN_WORD
;
1253 asl_set_query(msg
, k
, NULL
, op
);
1257 if (tt
== TOKEN_CLOSE
)
1259 asl_set_query(msg
, k
, NULL
, op
);
1261 else if (tt
== TOKEN_WORD
)
1263 asl_set_query(msg
, k
, v
, op
);
1267 if (k
!= NULL
) free(k
);
1268 if (v
!= NULL
) free(v
);
1273 if (k
!= NULL
) free(k
);
1274 if (v
!= NULL
) free(v
);
1276 if (tt
!= TOKEN_CLOSE
)
1278 k
= _asl_msg_get_next_word(&p
, &tt
, 1);
1279 if (k
== NULL
) break;
1281 if (tt
!= TOKEN_CLOSE
)
1290 k
= _asl_msg_get_next_word(&p
, &tt
, 1);
1291 if (k
== NULL
) break;
1298 asl_list_to_string(asl_search_result_t
*list
, uint32_t *outlen
)
1300 uint32_t i
, len
, newlen
;
1303 if (list
== NULL
) return NULL
;
1304 if (list
->count
== 0) return NULL
;
1305 if (list
->msg
== NULL
) return NULL
;
1308 asprintf(&out
, "%u\n", list
->count
);
1309 if (out
== NULL
) return NULL
;
1310 *outlen
= strlen(out
) + 1;
1312 for (i
= 0; i
< list
->count
; i
++)
1315 msgbuf
= asl_msg_to_string(list
->msg
[i
], &len
);
1323 newlen
= *outlen
+ len
;
1324 out
= reallocf(out
, newlen
);
1331 memmove((out
+ *outlen
- 1), msgbuf
, len
);
1332 out
[newlen
- 2] = '\n';
1333 out
[newlen
- 1] = '\0';
1342 asl_search_result_t
*
1343 asl_list_from_string(const char *buf
)
1347 asl_search_result_t
*out
;
1350 if (buf
== NULL
) return NULL
;
1354 if (n
== 0) return NULL
;
1356 out
= (asl_search_result_t
*)calloc(1, sizeof(asl_search_result_t
));
1357 if (out
== NULL
) return NULL
;
1359 out
->msg
= (asl_msg_t
**)calloc(n
, sizeof(asl_msg_t
*));
1360 if (out
->msg
== NULL
)
1366 for (i
= 0; i
< n
; i
++)
1368 p
= strchr(p
, '\n');
1371 aslresponse_free((aslresponse
)out
);
1377 m
= asl_msg_from_string(p
);
1380 aslresponse_free((aslresponse
)out
);
1392 _asl_msg_equal(asl_msg_t
*a
, asl_msg_t
*b
)
1396 if (a
->count
!= b
->count
) return 0;
1398 for (i
= 0; i
< a
->count
; i
++)
1400 j
= _asl_msg_index(b
, a
->key
[i
]);
1401 if (j
== (uint32_t)-1) return 0;
1403 if (a
->val
[i
] == NULL
)
1405 if (b
->val
[j
] != NULL
) return 0;
1409 if (b
->val
[j
] == NULL
) return 0;
1410 if (strcmp(a
->val
[i
], b
->val
[j
])) return 0;
1413 if (a
->type
== ASL_TYPE_QUERY
)
1415 if (a
->op
[i
] != b
->op
[j
]) return 0;
1423 _asl_isanumber(char *s
)
1427 if (s
== NULL
) return 0;
1430 if ((s
[0] == '-') || (s
[0] == '+')) i
= 1;
1432 if (s
[i
] == '\0') return 0;
1434 for (; s
[i
] != '\0'; i
++)
1436 if (!isdigit(s
[i
])) return 0;
1443 _asl_msg_op_test(uint32_t op
, char *q
, char *m
, uint32_t n
)
1450 t
= op
& ASL_QUERY_OP_TRUE
;
1452 if (op
& ASL_QUERY_OP_REGEX
)
1454 memset(&rex
, 0, sizeof(regex_t
));
1456 rflags
= REG_EXTENDED
| REG_NOSUB
;
1457 if (op
& ASL_QUERY_OP_CASEFOLD
) rflags
|= REG_ICASE
;
1459 if (regcomp(&rex
, q
, rflags
) != 0) return 0;
1460 cmp
= regexec(&rex
, m
, 0, NULL
, 0);
1465 if (op
& ASL_QUERY_OP_NUMERIC
)
1467 /* We assume the query contains a numeric string */
1468 if (_asl_isanumber(m
) == 0) return 0;
1475 case ASL_QUERY_OP_EQUAL
: return (nm
== nq
);
1476 case ASL_QUERY_OP_GREATER
: return (nm
> nq
);
1477 case ASL_QUERY_OP_GREATER_EQUAL
: return (nm
>= nq
);
1478 case ASL_QUERY_OP_LESS
: return (nm
< nq
);
1479 case ASL_QUERY_OP_LESS_EQUAL
: return (nm
<= nq
);
1480 case ASL_QUERY_OP_NOT_EQUAL
: return (nm
!= nq
);
1486 if (op
& ASL_QUERY_OP_CASEFOLD
)
1488 if (n
== 0) cmp
= strcasecmp(m
, q
);
1489 else cmp
= strncasecmp(m
, q
, n
);
1493 if (n
== 0) cmp
= strcmp(m
, q
);
1494 else cmp
= strncmp(m
, q
, n
);
1499 case ASL_QUERY_OP_EQUAL
: return (cmp
== 0);
1500 case ASL_QUERY_OP_GREATER
: return (cmp
> 0);
1501 case ASL_QUERY_OP_GREATER_EQUAL
: return (cmp
>= 0);
1502 case ASL_QUERY_OP_LESS
: return (cmp
< 0);
1503 case ASL_QUERY_OP_LESS_EQUAL
: return (cmp
<= 0);
1504 case ASL_QUERY_OP_NOT_EQUAL
: return (cmp
!= 0);
1512 _asl_msg_test_op_substr(uint32_t op
, char *q
, char *m
)
1514 uint32_t i
, d
, lm
, lq
;
1519 if (lq
> lm
) return 0;
1522 for (i
= 0; i
<= d
; i
++)
1524 if (_asl_msg_op_test(op
, q
, m
+ i
, lq
) != 0) return 1;
1531 _asl_msg_test_op_prefix(uint32_t op
, char *q
, char *m
)
1538 if (lq
> lm
) return 0;
1540 return _asl_msg_op_test(op
, q
, m
, lq
);
1544 _asl_msg_test_op_suffix(uint32_t op
, char *q
, char *m
)
1551 if (lq
> lm
) return 0;
1554 return _asl_msg_op_test(op
, q
, m
+ d
, lq
);
1558 _asl_msg_test_op(uint32_t op
, char *q
, char *m
)
1562 t
= op
& ASL_QUERY_OP_TRUE
;
1563 if (t
== ASL_QUERY_OP_TRUE
) return 1;
1565 if (op
& ASL_QUERY_OP_PREFIX
)
1567 if (op
& ASL_QUERY_OP_SUFFIX
) return _asl_msg_test_op_substr(op
, q
, m
);
1568 return _asl_msg_test_op_prefix(op
, q
, m
);
1570 if (op
& ASL_QUERY_OP_SUFFIX
) return _asl_msg_test_op_suffix(op
, q
, m
);
1572 return _asl_msg_op_test(op
, q
, m
, 0);
1576 _asl_msg_test_time_op(uint32_t op
, char *q
, char *m
)
1581 uint32_t t
, do_numeric
;
1586 if ((op
& ASL_QUERY_OP_PREFIX
) || (op
& ASL_QUERY_OP_SUFFIX
) || (op
& ASL_QUERY_OP_REGEX
) || (op
& ASL_QUERY_OP_CASEFOLD
)) do_numeric
= 0;
1588 tq
= asl_parse_time(q
);
1589 if (tq
< 0) return _asl_msg_test_op(op
, q
, m
);
1591 tm
= asl_parse_time(m
);
1592 if (tm
< 0) return _asl_msg_test_op(op
, q
, m
);
1594 if (do_numeric
== 1)
1596 t
= op
& ASL_QUERY_OP_TRUE
;
1599 case ASL_QUERY_OP_EQUAL
:
1600 if (tm
== tq
) return 1;
1602 case ASL_QUERY_OP_GREATER
:
1603 if (tm
> tq
) return 1;
1605 case ASL_QUERY_OP_GREATER_EQUAL
:
1606 if (tm
>= tq
) return 1;
1608 case ASL_QUERY_OP_LESS
:
1609 if (tm
< tq
) return 1;
1611 case ASL_QUERY_OP_LESS_EQUAL
:
1612 if (tm
<= tq
) return 1;
1614 case ASL_QUERY_OP_NOT_EQUAL
:
1615 if (tm
!= tq
) return 1;
1624 memset(>ime
, 0, sizeof(struct tm
));
1625 gmtime_r(&tq
, >ime
);
1627 /* Canonical form: YYYY.MM.DD hh:mm:ss UTC */
1629 asprintf(&vq
, "%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
);
1630 if (vq
== NULL
) return 0;
1632 memset(>ime
, 0, sizeof(struct tm
));
1633 gmtime_r(&tm
, >ime
);
1635 /* Canonical form: YYYY.MM.DD hh:mm:ss UTC */
1637 asprintf(&vm
, "%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
);
1638 if (vm
== NULL
) return 0;
1640 cmp
= _asl_msg_test_op(op
, q
, m
);
1649 _asl_msg_test(asl_msg_t
*q
, asl_msg_t
*m
)
1655 for (i
= 0; i
< q
->count
; i
++)
1657 j
= _asl_msg_index(m
, q
->key
[i
]);
1658 if (j
== (uint32_t)-1) return 0;
1660 if (q
->val
[i
] == NULL
) continue;
1661 if (q
->op
== NULL
) continue;
1663 if ((q
->op
[i
] & ASL_QUERY_OP_TRUE
) == ASL_QUERY_OP_TRUE
) continue;
1665 if (m
->val
[j
] == NULL
) return 0;
1670 if (streq(q
->key
[i
], ASL_KEY_TIME
))
1672 cmp
= _asl_msg_test_time_op(q
->op
[i
], q
->val
[i
], m
->val
[j
]);
1676 cmp
= _asl_msg_test_op(q
->op
[i
], val
, m
->val
[j
]);
1679 if (cmp
== 0) return 0;
1686 asl_msg_cmp(asl_msg_t
*a
, asl_msg_t
*b
)
1688 if (a
== NULL
) return 0;
1689 if (b
== NULL
) return 0;
1691 if (a
->type
== b
->type
) return _asl_msg_equal(a
, b
);
1692 if (a
->type
== ASL_TYPE_QUERY
) return _asl_msg_test(a
, b
);
1693 return _asl_msg_test(b
, a
);
1697 * asl_add_file: write log messages to the given file descriptor
1698 * Log messages will be written to this file as well as to the server.
1701 asl_add_output(aslclient ac
, int fd
, const char *mfmt
, const char *tfmt
)
1704 int use_global_lock
;
1707 use_global_lock
= 0;
1708 asl
= (asl_client_t
*)ac
;
1711 asl
= _asl_open_default();
1712 if (asl
== NULL
) return -1;
1713 pthread_mutex_lock(&_asl_global
.lock
);
1714 use_global_lock
= 1;
1717 for (i
= 0; i
< asl
->fd_count
; i
++)
1719 if (asl
->fd_list
[i
] == fd
)
1721 /* update message format and time format */
1722 if (asl
->fd_mfmt
[i
] != NULL
) free(asl
->fd_mfmt
[i
]);
1723 asl
->fd_mfmt
[i
] = NULL
;
1724 if (mfmt
!= NULL
) asl
->fd_mfmt
[i
] = strdup(mfmt
);
1726 if (asl
->fd_tfmt
[i
] != NULL
) free(asl
->fd_tfmt
[i
]);
1727 asl
->fd_tfmt
[i
] = NULL
;
1728 if (tfmt
!= NULL
) asl
->fd_tfmt
[i
] = strdup(tfmt
);
1730 if (use_global_lock
!= 0) pthread_mutex_unlock(&_asl_global
.lock
);
1735 if (asl
->fd_count
== 0)
1737 asl
->fd_list
= (int *)calloc(1, sizeof(int));
1738 asl
->fd_mfmt
= (char **)calloc(1, sizeof(char *));
1739 asl
->fd_tfmt
= (char **)calloc(1, sizeof(char *));
1743 asl
->fd_list
= (int *)reallocf(asl
->fd_list
, (1 + asl
->fd_count
) * sizeof(int));
1744 asl
->fd_mfmt
= (char **)reallocf(asl
->fd_mfmt
, (1 + asl
->fd_count
) * sizeof(char *));
1745 asl
->fd_tfmt
= (char **)reallocf(asl
->fd_tfmt
, (1 + asl
->fd_count
) * sizeof(char *));
1748 if ((asl
->fd_list
== NULL
) || (asl
->fd_mfmt
== NULL
) || (asl
->fd_tfmt
== NULL
))
1750 if (asl
->fd_list
!= NULL
) free(asl
->fd_list
);
1751 if (asl
->fd_mfmt
!= NULL
) free(asl
->fd_mfmt
);
1752 if (asl
->fd_tfmt
!= NULL
) free(asl
->fd_tfmt
);
1754 if (use_global_lock
!= 0) pthread_mutex_unlock(&_asl_global
.lock
);
1758 asl
->fd_list
[asl
->fd_count
] = fd
;
1759 if (mfmt
!= NULL
) asl
->fd_mfmt
[asl
->fd_count
] = strdup(mfmt
);
1760 if (tfmt
!= NULL
) asl
->fd_tfmt
[asl
->fd_count
] = strdup(tfmt
);
1764 if (use_global_lock
!= 0) pthread_mutex_unlock(&_asl_global
.lock
);
1769 asl_add_log_file(aslclient ac
, int fd
)
1771 return asl_add_output(ac
, fd
, ASL_MSG_FMT_STD
, ASL_TIME_FMT_LCL
);
1775 * asl_remove_output: stop writing log messages to the given file descriptor
1778 asl_remove_output(aslclient ac
, int fd
)
1781 int x
, use_global_lock
;
1784 use_global_lock
= 0;
1785 asl
= (asl_client_t
*)ac
;
1788 asl
= _asl_open_default();
1789 if (asl
== NULL
) return -1;
1790 pthread_mutex_lock(&_asl_global
.lock
);
1791 use_global_lock
= 1;
1794 if (asl
->fd_count
== 0)
1796 if (use_global_lock
!= 0) pthread_mutex_unlock(&_asl_global
.lock
);
1801 for (i
= 0; i
< asl
->fd_count
; i
++)
1803 if (asl
->fd_list
[i
] == fd
)
1812 if (use_global_lock
!= 0) pthread_mutex_unlock(&_asl_global
.lock
);
1816 if (asl
->fd_mfmt
[x
] != NULL
) free(asl
->fd_mfmt
[x
]);
1817 if (asl
->fd_tfmt
[x
] != NULL
) free(asl
->fd_tfmt
[x
]);
1819 for (i
= x
+ 1; i
< asl
->fd_count
; i
++, x
++)
1821 asl
->fd_list
[x
] = asl
->fd_list
[i
];
1822 asl
->fd_mfmt
[x
] = asl
->fd_mfmt
[i
];
1823 asl
->fd_tfmt
[x
] = asl
->fd_tfmt
[i
];
1828 if (asl
->fd_count
== 0)
1831 asl
->fd_list
= NULL
;
1832 asl
->fd_mfmt
= NULL
;
1833 asl
->fd_tfmt
= NULL
;
1837 asl
->fd_list
= (int *)reallocf(asl
->fd_list
, asl
->fd_count
* sizeof(int));
1838 asl
->fd_mfmt
= (char **)reallocf(asl
->fd_mfmt
, asl
->fd_count
* sizeof(char *));
1839 asl
->fd_tfmt
= (char **)reallocf(asl
->fd_tfmt
, asl
->fd_count
* sizeof(char *));
1841 if ((asl
->fd_list
== NULL
) || (asl
->fd_mfmt
== NULL
) || (asl
->fd_tfmt
== NULL
))
1843 if (asl
->fd_list
!= NULL
)
1846 asl
->fd_list
= NULL
;
1849 if (asl
->fd_mfmt
!= NULL
)
1851 for (i
= 0; i
< asl
->fd_count
; i
++) if (asl
->fd_mfmt
[i
] != NULL
) free(asl
->fd_mfmt
[i
]);
1853 asl
->fd_mfmt
= NULL
;
1856 if (asl
->fd_tfmt
!= NULL
)
1858 for (i
= 0; i
< asl
->fd_count
; i
++) if (asl
->fd_tfmt
[i
] != NULL
) free(asl
->fd_tfmt
[i
]);
1860 asl
->fd_tfmt
= NULL
;
1864 if (use_global_lock
!= 0) pthread_mutex_unlock(&_asl_global
.lock
);
1869 if (use_global_lock
!= 0) pthread_mutex_unlock(&_asl_global
.lock
);
1874 asl_remove_log_file(aslclient ac
, int fd
)
1876 return asl_remove_output(ac
, fd
);
1880 asl_set_filter(aslclient ac
, int f
)
1882 int last
, use_global_lock
;
1885 use_global_lock
= 0;
1886 asl
= (asl_client_t
*)ac
;
1889 asl
= _asl_open_default();
1890 if (asl
== NULL
) return -1;
1891 pthread_mutex_lock(&_asl_global
.lock
);
1892 use_global_lock
= 1;
1898 if (use_global_lock
!= 0) pthread_mutex_unlock(&_asl_global
.lock
);
1903 * asl_key: examine attribute keys
1904 * returns the key of the nth attribute in a message (beginning at zero)
1905 * returns NULL if the message has fewer attributes
1908 asl_key(aslmsg a
, uint32_t n
)
1912 msg
= (asl_msg_t
*)a
;
1913 if (msg
== NULL
) return NULL
;
1915 if (n
>= msg
->count
) return NULL
;
1920 * asl_new: create a new log message.
1923 asl_new(uint32_t type
)
1928 msg
= calloc(1, sizeof(asl_msg_t
));
1929 if (msg
== NULL
) return NULL
;
1932 if (type
== ASL_TYPE_QUERY
) return (aslmsg
)msg
;
1935 * Defaut attributes are:
1947 msg
->key
= calloc(msg
->count
, sizeof(char *));
1948 if (msg
->key
== NULL
)
1954 msg
->val
= calloc(msg
->count
, sizeof(char *));
1955 if (msg
->val
== NULL
)
1963 msg
->key
[i
] = strdup(ASL_KEY_TIME
);
1964 if (msg
->key
[i
] == NULL
)
1971 msg
->key
[i
] = strdup(ASL_KEY_HOST
);
1972 if (msg
->key
[i
] == NULL
)
1979 msg
->key
[i
] = strdup(ASL_KEY_SENDER
);
1980 if (msg
->key
[i
] == NULL
)
1987 msg
->key
[i
] = strdup(ASL_KEY_PID
);
1988 if (msg
->key
[i
] == NULL
)
1995 msg
->key
[i
] = strdup(ASL_KEY_UID
);
1996 if (msg
->key
[i
] == NULL
)
2003 msg
->key
[i
] = strdup(ASL_KEY_GID
);
2004 if (msg
->key
[i
] == NULL
)
2011 msg
->key
[i
] = strdup(ASL_KEY_LEVEL
);
2012 if (msg
->key
[i
] == NULL
)
2019 msg
->key
[i
] = strdup(ASL_KEY_MSG
);
2020 if (msg
->key
[i
] == NULL
)
2030 * asl_get: get attribute values from a message
2032 * key: attribute key
2033 * returns the attribute value
2034 * returns NULL if the message does not contain the key
2037 asl_get(aslmsg a
, const char *key
)
2042 msg
= (asl_msg_t
*)a
;
2044 if (msg
== NULL
) return NULL
;
2046 i
= _asl_msg_index(msg
, key
);
2047 if (i
== (uint32_t)-1) return NULL
;
2051 #endif /* BUILDING_VARIANT */
2054 * asl_vlog: Similar to asl_log, but taking a va_list instead of a list of
2057 * level: the log level of the associated message
2058 * format: A formating string followed by a list of arguments, like vprintf()
2059 * returns 0 for success, non-zero for failure
2062 asl_vlog(aslclient ac
, aslmsg a
, int level
, const char *format
, va_list ap
)
2064 int status
, saved_errno
;
2066 char *str
, *fmt
, *estr
;
2067 uint32_t i
, len
, elen
, expand
, my_msg
;
2070 asl
= (asl_client_t
*)ac
;
2074 * Initialize _asl_global so that asl_new will have global data.
2075 * Not strictly necessary, but helps performance.
2077 asl
= _asl_open_default();
2078 if (asl
== NULL
) return -1;
2081 saved_errno
= errno
;
2083 if (format
== NULL
) return -1;
2085 msg
= (asl_msg_t
*)a
;
2091 msg
= asl_new(ASL_TYPE_MSG
);
2092 if (msg
== NULL
) return -1;
2095 if (msg
->type
!= ASL_TYPE_MSG
) return -1;
2097 if (level
< ASL_LEVEL_EMERG
) level
= ASL_LEVEL_EMERG
;
2098 if (level
> ASL_LEVEL_DEBUG
) level
= ASL_LEVEL_DEBUG
;
2101 asprintf(&str
, "%d", level
);
2104 if ((msg
!= NULL
) && (my_msg
!= 0)) asl_free(msg
);
2108 asl_set(msg
, ASL_KEY_LEVEL
, str
);
2111 /* insert strerror for %m */
2114 estr
= strdup(strerror(saved_errno
));
2117 if ((msg
!= NULL
) && (my_msg
!= 0)) asl_free(msg
);
2125 elen
= strlen(estr
);
2127 for (i
= 0; format
[i
] != '\0'; i
++)
2129 if (format
[i
] == '%')
2131 if (format
[i
+1] == '\0') len
++;
2132 else if (format
[i
+1] == 'm')
2148 fmt
= (char *)format
;
2152 fmt
= malloc(len
+ 1);
2155 if (estr
!= NULL
) free(estr
);
2161 for (i
= 0; format
[i
] != '\0'; i
++)
2163 if (format
[i
] == '%')
2165 if (format
[i
+1] == '\0')
2168 else if (format
[i
+1] == 'm')
2170 memcpy(fmt
+len
, estr
, elen
);
2176 fmt
[len
++] = format
[i
++];
2177 fmt
[len
++] = format
[i
];
2180 else fmt
[len
++] = format
[i
];
2186 if (estr
!= NULL
) free(estr
);
2188 vasprintf(&str
, fmt
, ap
);
2189 if (expand
!= 0) free(fmt
);
2193 if ((msg
!= NULL
) && (my_msg
!= 0)) asl_free(msg
);
2197 asl_set(msg
, ASL_KEY_MSG
, str
);
2200 status
= asl_send(ac
, (aslmsg
)msg
);
2202 if ((msg
!= NULL
) && (my_msg
!= 0)) asl_free(msg
);
2207 * asl_log: log a message with a particular log level
2209 * level: the log level
2210 * format: A formating string followed by a list of arguments, like printf()
2211 * returns 0 for success, non-zero for failure
2214 asl_log(aslclient ac
, aslmsg a
, int level
, const char *format
, ...)
2219 if (format
== NULL
) return -1;
2221 va_start(ap
, format
);
2222 status
= asl_vlog(ac
, a
, level
, format
, ap
);
2228 #ifndef BUILDING_VARIANT
2231 _asl_level_string(int level
)
2233 if (level
== ASL_LEVEL_EMERG
) return ASL_STRING_EMERG
;
2234 if (level
== ASL_LEVEL_ALERT
) return ASL_STRING_ALERT
;
2235 if (level
== ASL_LEVEL_CRIT
) return ASL_STRING_CRIT
;
2236 if (level
== ASL_LEVEL_ERR
) return ASL_STRING_ERR
;
2237 if (level
== ASL_LEVEL_WARNING
) return ASL_STRING_WARNING
;
2238 if (level
== ASL_LEVEL_NOTICE
) return ASL_STRING_NOTICE
;
2239 if (level
== ASL_LEVEL_INFO
) return ASL_STRING_INFO
;
2240 if (level
== ASL_LEVEL_DEBUG
) return ASL_STRING_DEBUG
;
2245 * format a message for printing
2246 * out parameter len returns string length including trailing NUL
2249 asl_format_message(aslmsg msg
, const char *mfmt
, const char *tfmt
, uint32_t *len
)
2251 char *out
, *tstr
, *k
, c
[2];
2252 const char *hstr
, *sstr
, *pstr
, *mstr
, *lstr
, *rprc
, *rpid
, *v
;
2253 int i
, j
, l
, mf
, tf
, paren
, oval
, level
;
2258 if (msg
== NULL
) return NULL
;
2263 if (mfmt
== NULL
) mf
= MFMT_RAW
;
2264 else if (!strcmp(mfmt
, ASL_MSG_FMT_RAW
)) mf
= MFMT_RAW
;
2265 else if (!strcmp(mfmt
, ASL_MSG_FMT_STD
)) mf
= MFMT_STD
;
2266 else if (!strcmp(mfmt
, ASL_MSG_FMT_BSD
)) mf
= MFMT_BSD
;
2267 else if (!strcmp(mfmt
, ASL_MSG_FMT_XML
)) mf
= MFMT_XML
;
2268 else if (!strcmp(mfmt
, ASL_MSG_FMT_MSG
)) mf
= MFMT_MSG
;
2271 if (tfmt
== NULL
) tf
= TFMT_SEC
;
2272 else if (!strcmp(tfmt
, ASL_TIME_FMT_SEC
)) tf
= TFMT_SEC
;
2273 else if (!strcmp(tfmt
, ASL_TIME_FMT_UTC
)) tf
= TFMT_UTC
;
2274 else if (!strcmp(tfmt
, ASL_TIME_FMT_LCL
)) tf
= TFMT_LCL
;
2278 out
= _asl_msg_to_string_time_fmt((asl_msg_t
*)msg
, len
, tf
);
2284 mstr
= asl_get(msg
, ASL_KEY_MSG
);
2285 if (mstr
== NULL
) return NULL
;
2287 _asl_append_string(&out
, len
, mstr
, ENCODE_VIS
, 0);
2288 _asl_append_string(&out
, len
, "\n", ENCODE_NONE
, 0);
2293 if ((mf
== MFMT_STD
) || (mf
== MFMT_BSD
))
2295 /* BSD: Mth dd hh:mm:ss host sender[pid]: message */
2296 /* BSD: Mth dd hh:mm:ss host sender[pid] (refproc[refpid]): message */
2297 /* STD: Mth dd hh:mm:ss host sender[pid] <Level>: message */
2298 /* STD: Mth dd hh:mm:ss host sender[pid] (refproc[refpid]) <Level>: message */
2300 v
= asl_get(msg
, ASL_KEY_TIME
);
2301 tstr
= _asl_time_string(tf
, v
);
2303 hstr
= asl_get(msg
, ASL_KEY_HOST
);
2304 sstr
= asl_get(msg
, ASL_KEY_SENDER
);
2305 pstr
= asl_get(msg
, ASL_KEY_PID
);
2306 mstr
= asl_get(msg
, ASL_KEY_MSG
);
2308 rprc
= asl_get(msg
, ASL_KEY_REF_PROC
);
2309 rpid
= asl_get(msg
, ASL_KEY_REF_PID
);
2315 lstr
= asl_get(msg
, ASL_KEY_LEVEL
);
2316 if (lstr
!= NULL
) level
= atoi(lstr
);
2321 _asl_append_string(&out
, len
, "0", ENCODE_NONE
, 0);
2325 _asl_append_string(&out
, len
, tstr
, ENCODE_NONE
, 0);
2329 _asl_append_string(&out
, len
, " ", ENCODE_NONE
, 0);
2331 if (hstr
== NULL
) _asl_append_string(&out
, len
, "unknown", ENCODE_NONE
, 0);
2332 else _asl_append_string(&out
, len
, hstr
, ENCODE_VIS
, 0);
2334 _asl_append_string(&out
, len
, " ", ENCODE_NONE
, 0);
2336 if (sstr
== NULL
) _asl_append_string(&out
, len
, "unknown", ENCODE_NONE
, 0);
2337 else _asl_append_string(&out
, len
, sstr
, ENCODE_VIS
, 0);
2339 if ((pstr
!= NULL
) && (strcmp(pstr
, "-1")))
2341 _asl_append_string(&out
, len
, "[", ENCODE_NONE
, 0);
2342 _asl_append_string(&out
, len
, pstr
, ENCODE_NONE
, 0);
2343 _asl_append_string(&out
, len
, "]", ENCODE_NONE
, 0);
2346 if ((rprc
!= NULL
) || (rpid
!= NULL
)) _asl_append_string(&out
, len
, " (", ENCODE_NONE
, 0);
2348 if (rprc
!= NULL
) _asl_append_string(&out
, len
, rprc
, ENCODE_VIS
, 0);
2351 _asl_append_string(&out
, len
, "[", ENCODE_NONE
, 0);
2352 _asl_append_string(&out
, len
, rpid
, ENCODE_NONE
, 0);
2353 _asl_append_string(&out
, len
, "]", ENCODE_NONE
, 0);
2356 if ((rprc
!= NULL
) || (rpid
!= NULL
)) _asl_append_string(&out
, len
, ")", ENCODE_NONE
, 0);
2360 _asl_append_string(&out
, len
, " <", ENCODE_NONE
, 0);
2361 _asl_append_string(&out
, len
, _asl_level_string(level
), ENCODE_NONE
, 0);
2362 _asl_append_string(&out
, len
, ">", ENCODE_NONE
, 0);
2365 _asl_append_string(&out
, len
, ": ", ENCODE_NONE
, 0);
2367 if (mstr
!= NULL
) _asl_append_string(&out
, len
, mstr
, ENCODE_VIS
, 0);
2369 _asl_append_string(&out
, len
, "\n", ENCODE_NONE
, 0);
2375 _asl_append_string(&out
, len
, "\t<dict>\n", ENCODE_NONE
, 0);
2377 for (i
= 0; i
< msg
->count
; i
++)
2379 if (asl_is_utf8(msg
->key
[i
]) == 1)
2381 _asl_append_xml_tag(&out
, len
, XML_TAG_KEY
, msg
->key
[i
]);
2382 if (!strcmp(msg
->key
[i
], ASL_KEY_TIME
))
2384 tstr
= _asl_time_string(tf
, msg
->val
[i
]);
2385 _asl_append_xml_tag(&out
, len
, XML_TAG_STRING
, tstr
);
2386 if (tstr
!= NULL
) free(tstr
);
2390 if (asl_is_utf8(msg
->val
[i
]) == 1) _asl_append_xml_tag(&out
, len
, XML_TAG_STRING
, msg
->val
[i
]);
2391 else _asl_append_xml_tag(&out
, len
, XML_TAG_DATA
, msg
->val
[i
]);
2396 _asl_append_string(&out
, len
, "\t</dict>\n", ENCODE_NONE
, 0);
2403 for (i
= 0; mfmt
[i
] != '\0'; i
++)
2419 if (out
!= NULL
) free(out
);
2425 for (j
= i
; mfmt
[j
] != '\0'; j
++)
2428 if (mfmt
[j
] == '\\') c
[0] = mfmt
[++j
];
2429 else if ((paren
== 1) && (mfmt
[j
] ==')')) break;
2430 else if (mfmt
[j
] != ' ') c
[0] = mfmt
[j
];
2432 if (c
[0] == '\0') break;
2434 k
= reallocf(k
, l
+ 1);
2437 if (out
!= NULL
) free(out
);
2446 if (paren
== 1) j
++;
2450 v
= asl_get(msg
, k
);
2453 if (!strcmp(k
, ASL_KEY_TIME
))
2455 tstr
= _asl_time_string(tf
, v
);
2456 _asl_append_string(&out
, len
, tstr
, ENCODE_NONE
, 0);
2457 if (tstr
!= NULL
) free(tstr
);
2461 _asl_append_string(&out
, len
, (char *)v
, ENCODE_NONE
, 0);
2468 if (mfmt
[i
] == '\\')
2471 if (mfmt
[i
] == '$') _asl_append_string(&out
, len
, "$", ENCODE_NONE
, 0);
2472 else if (mfmt
[i
] == 'e') _asl_append_string(&out
, len
, "\e", ENCODE_NONE
, 0);
2473 else if (mfmt
[i
] == 's') _asl_append_string(&out
, len
, " ", ENCODE_NONE
, 0);
2474 else if (mfmt
[i
] == 'a') _asl_append_string(&out
, len
, "\a", ENCODE_NONE
, 0);
2475 else if (mfmt
[i
] == 'b') _asl_append_string(&out
, len
, "\b", ENCODE_NONE
, 0);
2476 else if (mfmt
[i
] == 'f') _asl_append_string(&out
, len
, "\f", ENCODE_NONE
, 0);
2477 else if (mfmt
[i
] == 'n') _asl_append_string(&out
, len
, "\n", ENCODE_NONE
, 0);
2478 else if (mfmt
[i
] == 'r') _asl_append_string(&out
, len
, "\r", ENCODE_NONE
, 0);
2479 else if (mfmt
[i
] == 't') _asl_append_string(&out
, len
, "\t", ENCODE_NONE
, 0);
2480 else if (mfmt
[i
] == 'v') _asl_append_string(&out
, len
, "\v", ENCODE_NONE
, 0);
2481 else if (mfmt
[i
] == '\'') _asl_append_string(&out
, len
, "\'", ENCODE_NONE
, 0);
2482 else if (mfmt
[i
] == '\\') _asl_append_string(&out
, len
, "\\", ENCODE_NONE
, 0);
2483 else if (isdigit(mfmt
[i
]))
2485 oval
= mfmt
[i
] - '0';
2486 if (isdigit(mfmt
[i
+1]))
2489 oval
= (oval
* 8) + (mfmt
[i
] - '0');
2490 if (isdigit(mfmt
[i
+1]))
2493 oval
= (oval
* 8) + (mfmt
[i
] - '0');
2497 _asl_append_string(&out
, len
, c
, ENCODE_NONE
, 0);
2502 if (mfmt
[i
] == '\0') break;
2504 _asl_append_string(&out
, len
, c
, ENCODE_NONE
, 0);
2507 _asl_append_string(&out
, len
, "\n", ENCODE_NONE
, 0);
2513 * asl_send: send a message
2514 * This routine may be used instead of asl_log() or asl_vlog() if asl_set()
2515 * has been used to set all of a message's attributes.
2517 * returns 0 for success, non-zero for failure
2520 asl_send(aslclient ac
, aslmsg msg
)
2522 char *str
, *out_raw
, *out
;
2523 uint32_t i
, len
, level
, lmask
, outstatus
, filter
, senderx
, facilityx
;
2528 int status
, rc_filter
;
2530 int use_global_lock
;
2532 char hname
[_POSIX_HOST_NAME_MAX
];
2534 use_global_lock
= 0;
2535 asl
= (asl_client_t
*)ac
;
2538 asl
= _asl_open_default();
2539 if (asl
== NULL
) return -1;
2540 use_global_lock
= 1;
2543 if (msg
== NULL
) return 0;
2545 level
= ASL_LEVEL_DEBUG
;
2547 val
= asl_get(msg
, ASL_KEY_LEVEL
);
2548 if (val
!= NULL
) level
= atoi(val
);
2550 lmask
= ASL_FILTER_MASK(level
);
2552 filter
= asl
->filter
;
2555 if (!(asl
->options
& ASL_OPT_NO_REMOTE
))
2557 pthread_mutex_lock(&_asl_global
.lock
);
2559 if (_asl_global
.notify_token
>= 0)
2563 status
= notify_get_state(_asl_global
.notify_token
, &v64
);
2564 if ((status
== NOTIFY_STATUS_OK
) && (v64
!= 0))
2571 if ((rc_filter
== 0) && (_asl_global
.master_token
>= 0))
2575 status
= notify_get_state(_asl_global
.master_token
, &v64
);
2576 if ((status
== NOTIFY_STATUS_OK
) && (v64
!= 0))
2582 pthread_mutex_unlock(&_asl_global
.lock
);
2586 * Time, Host, PID, UID, and GID values get set here
2590 asprintf(&str
, "%lu", tick
);
2593 asl_set(msg
, ASL_KEY_TIME
, str
);
2597 memset(&hname
, 0, _POSIX_HOST_NAME_MAX
);
2598 if (gethostname(hname
, _POSIX_HOST_NAME_MAX
) == 0)
2600 asl_set(msg
, ASL_KEY_HOST
, hname
);
2604 asprintf(&str
, "%u", getpid());
2607 asl_set(msg
, ASL_KEY_PID
, str
);
2612 asprintf(&str
, "%d", getuid());
2615 asl_set(msg
, ASL_KEY_UID
, str
);
2620 asprintf(&str
, "%u", getgid());
2623 asl_set(msg
, ASL_KEY_GID
, str
);
2627 senderx
= (uint32_t)-1;
2628 facilityx
= (uint32_t)-1;
2629 mt
= (asl_msg_t
*)msg
;
2631 for (i
= 0; (i
< mt
->count
) && ((senderx
== (uint32_t)-1) || (facilityx
== (uint32_t)-1)); i
++)
2633 if (mt
->key
[i
] == NULL
) continue;
2634 if (streq(mt
->key
[i
], ASL_KEY_SENDER
)) senderx
= i
;
2635 else if (streq(mt
->key
[i
], ASL_KEY_FACILITY
)) facilityx
= i
;
2639 * Set Sender if needed
2641 if ((senderx
== (uint32_t)-1) || (mt
->val
[senderx
] == NULL
))
2643 if ((ac
!= NULL
) && (ac
->name
!= NULL
))
2645 /* Use the Sender name from the client handle */
2646 asl_set(msg
, ASL_KEY_SENDER
, ac
->name
);
2650 /* Get the value for ASL_KEY_SENDER from cache */
2651 if (_asl_global
.sender
== NULL
)
2653 name
= *(*_NSGetArgv());
2656 x
= strrchr(name
, '/');
2660 pthread_mutex_lock(&_asl_global
.lock
);
2662 if (_asl_global
.sender
== NULL
) _asl_global
.sender
= strdup(x
);
2663 pthread_mutex_unlock(&_asl_global
.lock
);
2667 if (_asl_global
.sender
!= NULL
) asl_set(msg
, ASL_KEY_SENDER
, _asl_global
.sender
);
2668 else asl_set(msg
, ASL_KEY_SENDER
, "Unknown");
2675 if ((facilityx
== (uint32_t)-1) || (mt
->val
[facilityx
] == NULL
))
2677 if ((ac
!= NULL
) && (ac
->facility
!= NULL
))
2679 /* Use the Facility name from the client handle */
2680 asl_set(msg
, ASL_KEY_FACILITY
, ac
->facility
);
2686 if (use_global_lock
!= 0) pthread_mutex_lock(&_asl_global
.lock
);
2688 if ((filter
!= 0) && ((filter
& lmask
) != 0))
2691 out_raw
= asl_msg_to_string((asl_msg_t
*)msg
, &len
);
2693 if ((out_raw
!= NULL
) && (len
!= 0))
2695 asprintf(&out
, "%10u %s\n", len
+ 1, out_raw
);
2698 if (asl
->sock
== -1) _asl_connect(asl
);
2702 status
= write(asl
->sock
, out
, len
+ 12);
2705 /* Write failed - try resetting */
2709 if (asl
->sock
>= 0) status
= write(asl
->sock
, out
, len
+ 12);
2710 if (status
< 0) outstatus
= -1;
2713 else outstatus
= -1;
2722 for (i
= 0; i
< asl
->fd_count
; i
++)
2724 if (asl
->fd_list
[i
] < 0) continue;
2727 out
= asl_format_message(msg
, asl
->fd_mfmt
[i
], asl
->fd_tfmt
[i
], &len
);
2728 if (out
== NULL
) continue;
2730 status
= write(asl
->fd_list
[i
], out
, len
- 1);
2733 asl
->fd_list
[i
] = -1;
2740 if (use_global_lock
!= 0) pthread_mutex_unlock(&_asl_global
.lock
);
2746 asl_msg_string(aslmsg a
)
2750 return asl_msg_to_string((asl_msg_t
*)a
, &len
);
2754 * asl_free: free a message
2755 * msg: an aslmsg to free
2763 msg
= (asl_msg_t
*)a
;
2765 if (msg
== NULL
) return;
2767 for (i
= 0; i
< msg
->count
; i
++)
2769 if (msg
->key
[i
] != NULL
) free(msg
->key
[i
]);
2770 if (msg
->val
[i
] != NULL
) free(msg
->val
[i
]);
2775 if (msg
->key
!= NULL
) free(msg
->key
);
2776 if (msg
->val
!= NULL
) free(msg
->val
);
2777 if (msg
->op
!= NULL
) free(msg
->op
);
2784 * Called if there's a malloc error while manipulating a message in asl_set_query.
2785 * Cleans up the key, kap, and op fields, sets count to zero.
2788 _asl_clear_msg(asl_msg_t
*msg
)
2792 if (msg
== NULL
) return;
2794 for (i
= 0; i
< msg
->count
; i
++)
2796 if (msg
->key
!= NULL
&& msg
->key
[i
] != NULL
) free(msg
->key
[i
]);
2797 if (msg
->val
!= NULL
&& msg
->val
[i
] != NULL
) free(msg
->val
[i
]);
2800 if (msg
->key
!= NULL
) free(msg
->key
);
2801 if (msg
->val
!= NULL
) free(msg
->val
);
2802 if (msg
->op
!= NULL
) free(msg
->op
);
2812 * asl_set_query: set arbitrary parameters of a query
2813 * Similar to als_set, but allows richer query operations.
2814 * See ASL_QUERY_OP_* above.
2816 * key: attribute key
2817 * value: attribute value
2818 * op: an operation from the set above.
2819 * returns 0 for success, non-zero for failure
2822 asl_set_query(aslmsg a
, const char *key
, const char *val
, uint32_t op
)
2828 msg
= (asl_msg_t
*)a
;
2830 if (msg
== NULL
) return 0;
2832 if (key
== NULL
) return -1;
2836 if (streq(key
, ASL_KEY_LEVEL
))
2838 if (val
== NULL
) return -1;
2839 if (val
[0] == '\0') return -1;
2840 if ((val
[0] >= '0') && (val
[0] <= '9'))
2843 asprintf(&dv
, "%d", i
);
2844 if (dv
== NULL
) return -1;
2846 else if (!strcasecmp(val
, ASL_STRING_EMERG
))
2849 if (dv
== NULL
) return -1;
2851 else if (!strcasecmp(val
, ASL_STRING_ALERT
))
2854 if (dv
== NULL
) return -1;
2856 else if (!strcasecmp(val
, ASL_STRING_CRIT
))
2859 if (dv
== NULL
) return -1;
2861 else if (!strcasecmp(val
, ASL_STRING_ERR
))
2864 if (dv
== NULL
) return -1;
2866 else if (!strcasecmp(val
, ASL_STRING_WARNING
))
2869 if (dv
== NULL
) return -1;
2871 else if (!strcasecmp(val
, ASL_STRING_NOTICE
))
2874 if (dv
== NULL
) return -1;
2876 else if (!strcasecmp(val
, ASL_STRING_INFO
))
2879 if (dv
== NULL
) return -1;
2881 else if (!strcasecmp(val
, ASL_STRING_DEBUG
))
2884 if (dv
== NULL
) return -1;
2889 if ((dv
== NULL
) && (val
!= NULL
))
2892 if (dv
== NULL
) return -1;
2895 for (i
= 0; i
< msg
->count
; i
++)
2897 if (msg
->key
[i
] == NULL
) continue;
2899 if ((msg
->type
!= ASL_TYPE_QUERY
) && (streq(msg
->key
[i
], key
)))
2901 if (msg
->val
[i
] != NULL
) free(msg
->val
[i
]);
2903 if (val
!= NULL
) msg
->val
[i
] = dv
;
2904 if (msg
->op
!= NULL
) msg
->op
[i
] = op
;
2909 if (msg
->count
== 0)
2911 msg
->key
= (char **)calloc(1, sizeof(char *));
2912 if (msg
->key
== NULL
)
2914 _asl_clear_msg(msg
);
2918 msg
->val
= (char **)calloc(1, sizeof(char *));
2919 if (msg
->val
== NULL
)
2921 _asl_clear_msg(msg
);
2925 if (msg
->type
== ASL_TYPE_QUERY
)
2927 msg
->op
= (uint32_t *)calloc(1, sizeof(uint32_t));
2928 if (msg
->op
== NULL
)
2930 _asl_clear_msg(msg
);
2937 msg
->key
= (char **)reallocf(msg
->key
, (msg
->count
+ 1) * sizeof(char *));
2938 if (msg
->key
== NULL
)
2940 _asl_clear_msg(msg
);
2944 msg
->val
= (char **)reallocf(msg
->val
, (msg
->count
+ 1) * sizeof(char *));
2945 if (msg
->val
== NULL
)
2947 _asl_clear_msg(msg
);
2951 if (msg
->type
== ASL_TYPE_QUERY
)
2953 msg
->op
= (uint32_t *)reallocf(msg
->op
, (msg
->count
+ 1) * sizeof(uint32_t));
2954 if (msg
->op
== NULL
)
2956 _asl_clear_msg(msg
);
2963 if (dk
== NULL
) return -1;
2965 msg
->key
[msg
->count
] = dk
;
2966 msg
->val
[msg
->count
] = dv
;
2967 if (msg
->op
!= NULL
) msg
->op
[msg
->count
] = op
;
2974 * asl_set: set attributes of a message
2976 * key: attribute key
2977 * value: attribute value
2978 * returns 0 for success, non-zero for failure
2981 asl_set(aslmsg msg
, const char *key
, const char *val
)
2983 return asl_set_query(msg
, key
, val
, 0);
2987 * asl_unset: remove attributes of a message
2989 * key: attribute key
2990 * returns 0 for success, non-zero for failure
2993 asl_unset(aslmsg a
, const char *key
)
2998 msg
= (asl_msg_t
*)a
;
3000 if (msg
== NULL
) return 0;
3001 if (key
== NULL
) return 0;
3003 for (i
= 0; i
< msg
->count
; i
++)
3005 if (msg
->key
[i
] == NULL
) continue;
3007 if (streq(msg
->key
[i
], key
))
3010 if (msg
->val
[i
] != NULL
) free(msg
->val
[i
]);
3012 for (j
= i
+ 1; j
< msg
->count
; j
++, i
++)
3014 msg
->key
[i
] = msg
->key
[j
];
3015 msg
->val
[i
] = msg
->val
[j
];
3016 if (msg
->op
!= NULL
) msg
->op
[i
] = msg
->op
[j
];
3021 if (msg
->count
== 0)
3029 if (msg
->op
!= NULL
) free(msg
->op
);
3034 msg
->key
= (char **)reallocf(msg
->key
, msg
->count
* sizeof(char *));
3035 if (msg
->key
== NULL
) return -1;
3037 msg
->val
= (char **)reallocf(msg
->val
, msg
->count
* sizeof(char *));
3038 if (msg
->val
== NULL
) return -1;
3040 if (msg
->op
!= NULL
)
3042 msg
->op
= (uint32_t *)reallocf(msg
->op
, msg
->count
* sizeof(uint32_t));
3043 if (msg
->op
== NULL
) return -1;
3055 * asl_search: Search for messages matching the criteria described
3056 * by the aslmsg. The caller should set the attributes to match using
3057 * asl_set_query() or asl_set(). The operatoin ASL_QUERY_OP_EQUAL is
3058 * used for attributes set with asl_set().
3060 * returns: a set of messages that can be iterated over using aslresp_next(),
3061 * and the values can be retrieved using aslresp_get.
3064 asl_search(aslclient ac
, aslmsg a
)
3066 asl_search_result_t
*batch
, *out
;
3067 char *qstr
, *str
, *res
;
3068 uint32_t i
, j
, len
, reslen
, status
;
3069 uint64_t cmax
, qmin
;
3070 kern_return_t kstatus
;
3071 security_token_t sec
;
3074 if (a
== NULL
) return 0;
3077 qstr
= asl_msg_to_string((asl_msg_t
*)a
, &len
);
3082 asprintf(&str
, "0\n");
3087 asprintf(&str
, "1\n%s\n", qstr
);
3092 if (str
== NULL
) return NULL
;
3094 if (asl_server_port
== MACH_PORT_NULL
)
3096 kstatus
= bootstrap_look_up(bootstrap_port
, ASL_SERVICE_NAME
, &asl_server_port
);
3097 if (kstatus
!= KERN_SUCCESS
) return NULL
;
3101 * Fetch a batch of results each time through the loop.
3102 * Fetching many small batches rebuces the load on syslogd.
3116 kstatus
= vm_allocate(mach_task_self(), (vm_address_t
*)&vmstr
, len
, TRUE
);
3117 if (kstatus
!= KERN_SUCCESS
) return NULL
;
3119 memmove(vmstr
, str
, len
);
3121 kstatus
= _asl_server_query(asl_server_port
, vmstr
, len
, qmin
, FETCH_BATCH
, 0, (caddr_t
*)&res
, &reslen
, &cmax
, (int *)&status
, &sec
);
3122 if (kstatus
!= KERN_SUCCESS
) break;
3123 if (res
== NULL
) break;
3125 batch
= asl_list_from_string(res
);
3126 vm_deallocate(mach_task_self(), (vm_address_t
)res
, reslen
);
3128 if (batch
== NULL
) break;
3129 if (batch
->count
== 0)
3131 aslresponse_free(batch
);
3135 if (out
== NULL
) out
= (asl_search_result_t
*)calloc(1, sizeof(asl_search_result_t
));
3138 aslresponse_free(batch
);
3142 if (out
->count
== 0) out
->msg
= (asl_msg_t
**)calloc(batch
->count
, sizeof(asl_msg_t
*));
3143 else out
->msg
= (asl_msg_t
**)reallocf(out
->msg
, (out
->count
+ batch
->count
) * sizeof(asl_msg_t
*));
3144 if (out
->msg
== NULL
)
3146 aslresponse_free(batch
);
3152 for (i
= 0, j
= out
->count
; i
< batch
->count
; i
++, j
++) out
->msg
[j
] = batch
->msg
[i
];
3154 out
->count
+= batch
->count
;
3158 if (i
< FETCH_BATCH
) break;
3160 if (cmax
> qmin
) qmin
= cmax
;
3168 * aslresponse_next: Iterate over responses returned from asl_search()
3169 * a: a response returned from asl_search();
3170 * returns: The next log message (an aslmsg) or NULL on failure
3173 aslresponse_next(aslresponse r
)
3175 asl_search_result_t
*res
;
3178 res
= (asl_search_result_t
*)r
;
3179 if (res
== NULL
) return NULL
;
3181 if (res
->curr
>= res
->count
) return NULL
;
3182 m
= res
->msg
[res
->curr
];
3189 * aslresponse_free: Free a response returned from asl_search()
3190 * a: a response returned from asl_search()
3193 aslresponse_free(aslresponse r
)
3195 asl_search_result_t
*res
;
3198 res
= (asl_search_result_t
*)r
;
3199 if (res
== NULL
) return;
3201 for (i
= 0; i
< res
->count
; i
++) asl_free(res
->msg
[i
]);
3207 asl_syslog_faciliy_name_to_num(const char *name
)
3209 if (name
== NULL
) return -1;
3211 if (strcaseeq(name
, "auth")) return LOG_AUTH
;
3212 if (strcaseeq(name
, "authpriv")) return LOG_AUTHPRIV
;
3213 if (strcaseeq(name
, "cron")) return LOG_CRON
;
3214 if (strcaseeq(name
, "daemon")) return LOG_DAEMON
;
3215 if (strcaseeq(name
, "ftp")) return LOG_FTP
;
3216 if (strcaseeq(name
, "install")) return LOG_INSTALL
;
3217 if (strcaseeq(name
, "kern")) return LOG_KERN
;
3218 if (strcaseeq(name
, "lpr")) return LOG_LPR
;
3219 if (strcaseeq(name
, "mail")) return LOG_MAIL
;
3220 if (strcaseeq(name
, "netinfo")) return LOG_NETINFO
;
3221 if (strcaseeq(name
, "remoteauth")) return LOG_REMOTEAUTH
;
3222 if (strcaseeq(name
, "news")) return LOG_NEWS
;
3223 if (strcaseeq(name
, "security")) return LOG_AUTH
;
3224 if (strcaseeq(name
, "syslog")) return LOG_SYSLOG
;
3225 if (strcaseeq(name
, "user")) return LOG_USER
;
3226 if (strcaseeq(name
, "uucp")) return LOG_UUCP
;
3227 if (strcaseeq(name
, "local0")) return LOG_LOCAL0
;
3228 if (strcaseeq(name
, "local1")) return LOG_LOCAL1
;
3229 if (strcaseeq(name
, "local2")) return LOG_LOCAL2
;
3230 if (strcaseeq(name
, "local3")) return LOG_LOCAL3
;
3231 if (strcaseeq(name
, "local4")) return LOG_LOCAL4
;
3232 if (strcaseeq(name
, "local5")) return LOG_LOCAL5
;
3233 if (strcaseeq(name
, "local6")) return LOG_LOCAL6
;
3234 if (strcaseeq(name
, "local7")) return LOG_LOCAL7
;
3235 if (strcaseeq(name
, "launchd")) return LOG_LAUNCHD
;
3241 asl_syslog_faciliy_num_to_name(int n
)
3243 if (n
< 0) return NULL
;
3245 if (n
== LOG_AUTH
) return "auth";
3246 if (n
== LOG_AUTHPRIV
) return "authpriv";
3247 if (n
== LOG_CRON
) return "cron";
3248 if (n
== LOG_DAEMON
) return "daemon";
3249 if (n
== LOG_FTP
) return "ftp";
3250 if (n
== LOG_INSTALL
) return "install";
3251 if (n
== LOG_KERN
) return "kern";
3252 if (n
== LOG_LPR
) return "lpr";
3253 if (n
== LOG_MAIL
) return "mail";
3254 if (n
== LOG_NETINFO
) return "netinfo";
3255 if (n
== LOG_REMOTEAUTH
) return "remoteauth";
3256 if (n
== LOG_NEWS
) return "news";
3257 if (n
== LOG_AUTH
) return "security";
3258 if (n
== LOG_SYSLOG
) return "syslog";
3259 if (n
== LOG_USER
) return "user";
3260 if (n
== LOG_UUCP
) return "uucp";
3261 if (n
== LOG_LOCAL0
) return "local0";
3262 if (n
== LOG_LOCAL1
) return "local1";
3263 if (n
== LOG_LOCAL2
) return "local2";
3264 if (n
== LOG_LOCAL3
) return "local3";
3265 if (n
== LOG_LOCAL4
) return "local4";
3266 if (n
== LOG_LOCAL5
) return "local5";
3267 if (n
== LOG_LOCAL6
) return "local6";
3268 if (n
== LOG_LOCAL7
) return "local7";
3269 if (n
== LOG_LAUNCHD
) return "launchd";
3275 * utility for converting a time string into a time_t
3276 * we only deal with the following formats:
3277 * Canonical form YYYY.MM.DD hh:mm:ss UTC
3278 * ctime() form Mth dd hh:mm:ss (e.g. Aug 25 09:54:37)
3279 * absolute form - # seconds since the epoch (e.g. 1095789191)
3280 * relative time - seconds before or after now (e.g. -300, +43200)
3281 * relative time - days/hours/minutes/seconds before or after now (e.g. -1d, +6h, +30m, -10s)
3284 #define CANONICAL_TIME_REX "^[0-9][0-9][0-9][0-9].[01]?[0-9].[0-3]?[0-9][ ]+[0-2]?[0-9]:[0-5][0-9]:[0-5][0-9][ ]+UTC$"
3285 #define CTIME_REX "^[adfjmnos][aceopu][bcglnprtvy][ ]+[0-3]?[0-9][ ]+[0-2]?[0-9]:[0-5][0-9]:[0-5][0-9]$"
3286 #define ABSOLUTE_TIME_REX "^[0-9]+[s]?$"
3287 #define RELATIVE_TIME_REX "^[\\+-\\][0-9]+[smhdw]?$"
3289 #define SECONDS_PER_MINUTE 60
3290 #define SECONDS_PER_HOUR 3600
3291 #define SECONDS_PER_DAY 86400
3292 #define SECONDS_PER_WEEK 604800
3295 * We use the last letter in the month name to determine
3296 * the month number (0-11). There are two collisions:
3297 * Jan and Jun both end in n
3298 * Mar and Apr both end in r
3299 * In these cases we check the second letter.
3301 * The MTH_LAST array maps the last letter to a number.
3303 static const int8_t MTH_LAST
[] = {-1, 1, 11, -1, -1, -1, 7, -1, -1, -1, -1, 6, -1, 5, -1, 8, -1, 3, -1, 9, -1, 10, -1, -1, 4, -1};
3312 if (s
[2] > 90) v8
= s
[2] - 'a';
3313 else v8
= s
[2] - 'A';
3315 if ((v8
< 0) || (v8
> 25)) return -1;
3318 if (v8
< 0) return -1;
3321 if ((i
== 5) && ((s
[1] == 'a') || (s
[1] == 'A'))) return 0;
3322 if ((i
== 3) && ((s
[1] == 'a') || (s
[1] == 'A'))) return 2;
3327 asl_parse_time(const char *in
)
3329 int len
, y
, status
, rflags
;
3331 time_t tick
, delta
, factor
;
3333 static regex_t rex_canon
, rex_ctime
, rex_abs
, rex_rel
;
3334 static int init_canon
= 0;
3335 static int init_ctime
= 0;
3336 static int init_abs
= 0;
3337 static int init_rel
= 0;
3339 if (in
== NULL
) return -1;
3341 rflags
= REG_EXTENDED
| REG_NOSUB
| REG_ICASE
;
3343 if (init_canon
== 0)
3345 memset(&rex_canon
, 0, sizeof(regex_t
));
3346 status
= regcomp(&rex_canon
, CANONICAL_TIME_REX
, rflags
);
3347 if (status
!= 0) return -1;
3351 if (init_ctime
== 0)
3353 memset(&rex_ctime
, 0, sizeof(regex_t
));
3354 status
= regcomp(&rex_ctime
, CTIME_REX
, rflags
);
3355 if (status
!= 0) return -1;
3361 memset(&rex_abs
, 0, sizeof(regex_t
));
3362 status
= regcomp(&rex_abs
, ABSOLUTE_TIME_REX
, rflags
);
3363 if (status
!= 0) return -1;
3369 memset(&rex_rel
, 0, sizeof(regex_t
));
3370 status
= regcomp(&rex_rel
, RELATIVE_TIME_REX
, rflags
);
3371 if (status
!= 0) return -1;
3375 len
= strlen(in
) + 1;
3377 if (regexec(&rex_abs
, in
, 0, NULL
, 0) == 0)
3380 * Absolute time (number of seconds since the epoch)
3383 if (str
== NULL
) return -1;
3385 if ((str
[len
-2] == 's') || (str
[len
-2] == 'S')) str
[len
-2] = '\0';
3392 else if (regexec(&rex_rel
, in
, 0, NULL
, 0) == 0)
3395 * Reletive time (number of seconds before or after right now)
3398 if (str
== NULL
) return -1;
3402 if ((str
[len
-2] == 's') || (str
[len
-2] == 'S'))
3406 else if ((str
[len
-2] == 'm') || (str
[len
-2] == 'M'))
3409 factor
= SECONDS_PER_MINUTE
;
3411 else if ((str
[len
-2] == 'h') || (str
[len
-2] == 'H'))
3414 factor
= SECONDS_PER_HOUR
;
3416 else if ((str
[len
-2] == 'd') || (str
[len
-2] == 'D'))
3419 factor
= SECONDS_PER_DAY
;
3421 else if ((str
[len
-2] == 'w') || (str
[len
-2] == 'W'))
3424 factor
= SECONDS_PER_WEEK
;
3428 delta
= factor
* atol(str
);
3435 else if (regexec(&rex_canon
, in
, 0, NULL
, 0) == 0)
3437 memset(&t
, 0, sizeof(struct tm
));
3439 if (str
== NULL
) return -1;
3445 t
.tm_year
= atoi(x
) - 1900;
3451 t
.tm_mon
= atoi(x
) - 1;
3457 t
.tm_mday
= atoi(x
);
3460 for (x
= p
+ 1; *x
== ' '; x
++);
3463 t
.tm_hour
= atoi(x
);
3480 else if (regexec(&rex_ctime
, in
, 0, NULL
, 0) == 0)
3482 /* We assume it's in the current year */
3483 memset(&t
, 0, sizeof(struct tm
));
3485 gmtime_r(&tick
, &t
);
3488 memset(&t
, 0, sizeof(struct tm
));
3490 if (str
== NULL
) return -1;
3493 t
.tm_mon
= _month_num(str
);
3494 if (t
.tm_mon
< 0) return -1;
3496 for (x
= strchr(str
, ' '); *x
== ' '; x
++);
3499 t
.tm_mday
= atoi(x
);
3502 for (x
= p
+ 1; *x
== ' '; x
++);
3505 t
.tm_hour
= atoi(x
);
3526 #ifdef ASL_SYSLOG_COMPAT
3528 __private_extern__
void
3529 asl_syslog_syslog(int pri
, const char *fmt
, ...)
3534 if (fmt
== NULL
) return;
3536 m
= asl_new(ASL_TYPE_MSG
);
3539 asl_vlog(NULL
, m
, pri
, fmt
, ap
);
3545 __private_extern__
void
3546 asl_syslog_vsyslog(int pri
, const char *fmt
, va_list ap
)
3550 m
= asl_new(ASL_TYPE_MSG
);
3551 asl_vlog(NULL
, m
, pri
, fmt
, ap
);
3555 __private_extern__
void
3556 asl_syslog_openlog(const char *ident
, int flags
, int facility
)
3563 if (flags
& LOG_NDELAY
) opts
|= ASL_OPT_NO_DELAY
;
3564 if (flags
& LOG_PERROR
) opts
|= ASL_OPT_STDERR
;
3566 fname
= asl_syslog_faciliy_num_to_name(facility
);
3567 if (fname
== NULL
) fname
= "user";
3569 asl_global_client
= asl_open(ident
, fname
, opts
);
3572 __private_extern__
void
3573 asl_syslog_closelog()
3578 __private_extern__
int
3579 asl_syslog_setlogmask(int p
)
3581 return asl_set_filter(p
);
3584 #endif ASL_SYSLOG_COMPAT
3586 #endif /* BUILDING_VARIANT */