2 * Copyright (c) 2004 Apple Computer, 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@
34 #include <crt_externs.h>
36 #include <asl_private.h>
39 #include <mach/mach.h>
42 #define _PATH_ASL_IN "/var/run/asl_input"
44 #define streq(A, B) (strcmp(A, B) == 0)
45 #define strcaseeq(A, B) (strcasecmp(A, B) == 0)
47 #define forever for(;;)
56 time_t asl_parse_time(const char *);
57 const char *asl_syslog_faciliy_num_to_name(int n
);
58 __private_extern__ asl_client_t
*_asl_open_default();
61 uint32_t notify_get_state(int token
, int *state
);
62 uint32_t notify_register_plain(const char *name
, int *out_token
);
74 #ifndef BUILDING_VARIANT
75 __private_extern__ _asl_global_t _asl_global
= {0, -1, -1, NULL
, PTHREAD_MUTEX_INITIALIZER
, NULL
};
78 _asl_connect(asl_client_t
*asl
)
82 if (asl
->sock
>= 0) return 0;
84 asl
->sock
= socket(AF_UNIX
, SOCK_STREAM
, 0);
85 if (asl
->sock
< 0) return -1;
87 memset(&(asl
->server
), 0, sizeof(struct sockaddr_un
));
88 asl
->server
.sun_family
= AF_UNIX
;
90 strcpy(asl
->server
.sun_path
, _PATH_ASL_IN
);
91 len
= sizeof(asl
->server
.sun_len
) + sizeof(asl
->server
.sun_family
) + strlen(asl
->server
.sun_path
) + 1;
92 asl
->server
.sun_len
= strlen(_PATH_ASL_IN
) + 1;
94 status
= connect(asl
->sock
, (const struct sockaddr
*)&(asl
->server
), len
);
96 if (status
< 0) return -1;
101 _asl_notify_open(int do_lock
)
107 if (do_lock
!= 0) pthread_mutex_lock(&_asl_global
.lock
);
109 _asl_global
.notify_count
++;
111 if (_asl_global
.notify_token
!= -1)
113 if (do_lock
!= 0) pthread_mutex_unlock(&_asl_global
.lock
);
119 prefix
= NOTIFY_PREFIX_USER
;
120 if (getuid() == 0) prefix
= NOTIFY_PREFIX_SYSTEM
;
122 if (_asl_global
.master_token
== -1)
124 status
= notify_register_plain(NOTIFY_SYSTEM_MASTER
, &_asl_global
.master_token
);
125 if (status
!= NOTIFY_STATUS_OK
) _asl_global
.master_token
= -1;
128 asprintf(¬ify_name
, "%s.%d", prefix
, getpid());
130 if (notify_name
!= NULL
)
132 status
= notify_register_plain(notify_name
, &_asl_global
.notify_token
);
134 if (status
!= NOTIFY_STATUS_OK
) _asl_global
.notify_token
= -1;
137 if (do_lock
!= 0) pthread_mutex_unlock(&_asl_global
.lock
);
139 if (_asl_global
.notify_token
== -1) return -1;
146 pthread_mutex_lock(&_asl_global
.lock
);
148 if (_asl_global
.notify_count
> 0) _asl_global
.notify_count
--;
150 if (_asl_global
.notify_count
> 0)
152 pthread_mutex_unlock(&_asl_global
.lock
);
156 if (_asl_global
.master_token
> 0) notify_cancel(_asl_global
.master_token
);
157 _asl_global
.master_token
= -1;
159 if (_asl_global
.notify_token
> 0) notify_cancel(_asl_global
.notify_token
);
160 _asl_global
.notify_token
= -1;
162 pthread_mutex_unlock(&_asl_global
.lock
);
166 asl_open(const char *ident
, const char *facility
, uint32_t opts
)
171 asl
= (asl_client_t
*)calloc(1, sizeof(asl_client_t
));
182 if (asl
->options
& ASL_OPT_NO_DELAY
)
184 if (_asl_connect(asl
) < 0)
195 asl
->filter
= ASL_FILTER_MASK_UPTO(ASL_LEVEL_NOTICE
);
199 asl
->name
= strdup(ident
);
203 name
= *(*_NSGetArgv());
206 x
= strrchr(name
, '/');
209 asl
->name
= strdup(x
);
213 if (facility
!= NULL
) asl
->facility
= strdup(facility
);
214 else asl
->facility
= strdup(asl_syslog_faciliy_num_to_name(LOG_USER
));
216 if (!(asl
->options
& ASL_OPT_NO_REMOTE
)) _asl_notify_open(1);
218 return (aslclient
)asl
;
222 asl_close(aslclient ac
)
226 asl
= (asl_client_t
*)ac
;
227 if (asl
== NULL
) return;
229 if (asl
->sock
>= 0) close(asl
->sock
);
230 if (asl
->name
!= NULL
) free(asl
->name
);
231 if (asl
->facility
!= NULL
) free(asl
->facility
);
232 if (!(asl
->options
& ASL_OPT_NO_REMOTE
)) _asl_notify_close();
233 if (asl
->fd_list
!= NULL
) free(asl
->fd_list
);
235 memset(asl
, 0, sizeof(asl_client_t
));
239 __private_extern__ asl_client_t
*
242 pthread_mutex_lock(&_asl_global
.lock
);
243 if (_asl_global
.asl
!= NULL
)
245 pthread_mutex_unlock(&_asl_global
.lock
);
246 return _asl_global
.asl
;
250 * Do a sleight-of-hand with ASL_OPT_NO_REMOTE to avoid a deadlock
251 * since asl_open(xxx, yyy, 0) calls _asl_notify_open(1)
252 * which locks _asl_global.lock.
254 _asl_global
.asl
= asl_open(NULL
, NULL
, ASL_OPT_NO_REMOTE
);
256 /* Reset options to clear ASL_OPT_NO_REMOTE bit */
257 if (_asl_global
.asl
!= NULL
) _asl_global
.asl
->options
= 0;
259 /* Now call _asl_notify_open(0) to finish the work */
262 pthread_mutex_unlock(&_asl_global
.lock
);
264 return _asl_global
.asl
;
268 _asl_msg_index(asl_msg_t
*msg
, const char *k
)
272 if (msg
== NULL
) return (uint32_t)-1;
273 if (k
== NULL
) return (uint32_t)-1;
275 for (i
= 0; i
< msg
->count
; i
++)
277 if (msg
->key
[i
] == NULL
) continue;
278 if (streq(msg
->key
[i
], k
)) return i
;
285 _asl_append_string(char **m
, uint32_t *x
, char *s
, uint32_t encode
, uint32_t escspace
)
289 if (m
== NULL
) return;
290 if (x
== NULL
) return;
291 if (s
== NULL
) return;
294 if (encode
== 0) n
= strlen(s
);
297 for (i
= 0; s
[i
] != '\0'; i
++)
299 if (s
[i
] == '\\') n
++;
300 else if (s
[i
] == ']') n
++;
301 else if ((escspace
!= 0) && (s
[i
] == ' ')) n
++;
315 *m
= realloc(*m
, n
+ (*x
));
320 memcpy((*m
) + (*x
) - 1, s
, n
+ 1);
326 for (i
= 0; s
[i
] != '\0'; i
++)
328 if ((s
[i
] == '\\') || (s
[i
] == ']') || ((escspace
!= 0) && (s
[i
] == ' ')))
333 else if (s
[i
] == '\n') (*m
)[n
++] = ';';
334 else (*m
)[n
++] = s
[i
];
345 _asl_append_op(char **m
, uint32_t *x
, uint32_t op
)
350 if (m
== NULL
) return;
351 if (x
== NULL
) return;
353 if (op
== ASL_QUERY_OP_NULL
) return _asl_append_string(m
, x
, ".", 0, 0);
356 if (op
& ASL_QUERY_OP_CASEFOLD
) opstr
[i
++] = 'C';
358 if (op
& ASL_QUERY_OP_CASEFOLD
) opstr
[i
++] = 'R';
360 if (op
& ASL_QUERY_OP_NUMERIC
) opstr
[i
++] = 'N';
362 if (op
& ASL_QUERY_OP_PREFIX
)
364 if (op
& ASL_QUERY_OP_SUFFIX
) opstr
[i
++] = 'S';
365 else opstr
[i
++] = 'A';
367 if (op
& ASL_QUERY_OP_SUFFIX
) opstr
[i
++] = 'Z';
369 switch (op
& ASL_QUERY_OP_TRUE
)
371 case ASL_QUERY_OP_EQUAL
:
374 case ASL_QUERY_OP_GREATER
:
377 case ASL_QUERY_OP_GREATER_EQUAL
:
381 case ASL_QUERY_OP_LESS
:
384 case ASL_QUERY_OP_LESS_EQUAL
:
388 case ASL_QUERY_OP_NOT_EQUAL
:
391 case ASL_QUERY_OP_TRUE
:
398 if (i
== 0) return _asl_append_string(m
, x
, ".", 0, 0);
401 return _asl_append_string(m
, x
, opstr
, 0, 0);
405 asl_msg_to_string(asl_msg_t
*msg
, uint32_t *len
)
412 if (msg
== NULL
) return NULL
;
418 if (msg
->type
== ASL_TYPE_QUERY
)
420 _asl_append_string(&out
, &outlen
, "Q ", 0, 0);
421 if (out
== NULL
) return NULL
;
426 if (out
== NULL
) return NULL
;
431 for (i
= 0; i
< msg
->count
; i
++)
433 if (msg
->key
[i
] == NULL
) continue;
435 if (i
> 0) _asl_append_string(&out
, &outlen
, " [", 0, 0);
436 else _asl_append_string(&out
, &outlen
, "[", 0, 0);
438 if (msg
->type
== ASL_TYPE_QUERY
)
440 _asl_append_op(&out
, &outlen
, msg
->op
[i
]);
441 _asl_append_string(&out
, &outlen
, " ", 0, 0);
444 _asl_append_string(&out
, &outlen
, msg
->key
[i
], 1, 1);
446 if (msg
->val
[i
] != NULL
)
448 _asl_append_string(&out
, &outlen
, " ", 0, 0);
449 _asl_append_string(&out
, &outlen
, msg
->val
[i
], 1, 0);
452 _asl_append_string(&out
, &outlen
, "]", 0, 0);
460 _asl_msg_op_from_string(char *o
)
464 op
= ASL_QUERY_OP_NULL
;
466 if (o
== NULL
) return op
;
468 for (i
= 0; o
[i
] != '\0'; i
++)
470 if (o
[i
] == '.') return ASL_QUERY_OP_NULL
;
471 if (o
[i
] == 'C') op
|= ASL_QUERY_OP_CASEFOLD
;
472 if (o
[i
] == 'R') op
|= ASL_QUERY_OP_CASEFOLD
;
473 if (o
[i
] == 'N') op
|= ASL_QUERY_OP_NUMERIC
;
474 if (o
[i
] == 'S') op
|= ASL_QUERY_OP_SUBSTRING
;
475 if (o
[i
] == 'A') op
|= ASL_QUERY_OP_PREFIX
;
476 if (o
[i
] == 'Z') op
|= ASL_QUERY_OP_SUFFIX
;
477 if (o
[i
] == '<') op
|= ASL_QUERY_OP_LESS
;
478 if (o
[i
] == '>') op
|= ASL_QUERY_OP_GREATER
;
479 if (o
[i
] == '=') op
|= ASL_QUERY_OP_EQUAL
;
480 if (o
[i
] == '!') op
|= ASL_QUERY_OP_NOT_EQUAL
;
481 if (o
[i
] == 'T') op
|= ASL_QUERY_OP_TRUE
;
488 _asl_msg_get_next_word(char **p
, uint32_t *tt
, uint32_t spacedel
)
491 uint32_t i
, esc
, len
, n
;
495 if (p
== NULL
) return NULL
;
496 if (*p
== NULL
) return NULL
;
497 if (**p
== '\0') return NULL
;
499 /* skip one space if it's there (word separator) */
500 if (**p
== ' ') (*p
)++;
502 /* skip leading white space */
505 while ((**p
== ' ') || (**p
== '\t')) (*p
)++;
508 if (**p
== '\0') return NULL
;
509 if (**p
== '\n') return NULL
;
528 /* stop scanning when we hit a delimiter */
529 if (((spacedel
!= 0) && (**p
== ' ')) || (**p
== ']') || (**p
== '\0')) break;
532 if (**p
== '\\') esc
= 1;
535 /* skip over escaped chars so len is correct */
536 if ((esc
== 1) && ((**p
== ' ') || (**p
== ']') || (**p
== '\\'))) (*p
)++;
540 if ((len
== 0) && (**p
== ']'))
552 out
= malloc(len
+ 1);
554 for (n
= 0, i
= 0; n
< len
; i
++)
556 if ((start
[i
] == '\\') && ((start
[i
+1] == ' ') || (start
[i
+1] == ']') || (start
[i
+1] == '\\')))
562 if ((start
[i
] < '0') || (start
[i
] > '9')) *tt
= TOKEN_WORD
;
572 asl_msg_from_string(const char *buf
)
574 uint32_t tt
, type
, op
;
578 if (buf
== NULL
) return NULL
;
583 k
= _asl_msg_get_next_word(&p
, &tt
, 1);
584 if (k
== NULL
) return NULL
;
588 type
= ASL_TYPE_QUERY
;
591 k
= _asl_msg_get_next_word(&p
, &tt
, 1);
593 else if (tt
== TOKEN_INT
)
595 /* Leading integer is a string length - skip it */
597 k
= _asl_msg_get_next_word(&p
, &tt
, 1);
598 if (k
== NULL
) return NULL
;
601 msg
= calloc(1, sizeof(asl_msg_t
));
602 if (msg
== NULL
) return NULL
;
605 /* OPEN WORD [WORD [WORD]] CLOSE */
608 op
= ASL_QUERY_OP_NULL
;
610 if (tt
!= TOKEN_OPEN
)
618 /* get op for query type */
619 if (type
== ASL_TYPE_QUERY
)
621 o
= _asl_msg_get_next_word(&p
, &tt
, 1);
622 if ((o
== NULL
) || (tt
!= TOKEN_WORD
))
624 if (o
!= NULL
) free(o
);
629 op
= _asl_msg_op_from_string(o
);
633 k
= _asl_msg_get_next_word(&p
, &tt
, 1);
634 if (tt
== TOKEN_INT
) tt
= TOKEN_WORD
;
635 if ((k
== NULL
) || (tt
!= TOKEN_WORD
))
637 if (k
!= NULL
) free(k
);
642 v
= _asl_msg_get_next_word(&p
, &tt
, 0);
643 if (tt
== TOKEN_INT
) tt
= TOKEN_WORD
;
646 asl_set_query(msg
, k
, NULL
, op
);
650 if (tt
== TOKEN_CLOSE
)
652 asl_set_query(msg
, k
, NULL
, op
);
654 else if (tt
== TOKEN_WORD
)
656 asl_set_query(msg
, k
, v
, op
);
660 if (k
!= NULL
) free(k
);
661 if (v
!= NULL
) free(v
);
666 if (k
!= NULL
) free(k
);
667 if (v
!= NULL
) free(v
);
669 if (tt
!= TOKEN_CLOSE
)
671 k
= _asl_msg_get_next_word(&p
, &tt
, 1);
672 if (k
== NULL
) break;
674 if (tt
!= TOKEN_CLOSE
)
683 k
= _asl_msg_get_next_word(&p
, &tt
, 1);
684 if (k
== NULL
) break;
691 _asl_msg_equal(asl_msg_t
*a
, asl_msg_t
*b
)
695 if (a
->count
!= b
->count
) return 0;
697 for (i
= 0; i
< a
->count
; i
++)
699 j
= _asl_msg_index(b
, a
->key
[i
]);
700 if (j
== (uint32_t)-1) return 0;
702 if (a
->val
[i
] == NULL
)
704 if (b
->val
[j
] != NULL
) return 0;
708 if (b
->val
[j
] == NULL
) return 0;
709 if (strcmp(a
->val
[i
], b
->val
[j
])) return 0;
712 if (a
->type
== ASL_TYPE_QUERY
)
714 if (a
->op
[i
] != b
->op
[j
]) return 0;
722 _asl_isanumber(char *s
)
726 if (s
== NULL
) return 0;
729 if ((s
[0] == '-') || (s
[0] == '+')) i
= 1;
731 if (s
[i
] == '\0') return 0;
733 for (; s
[i
] != '\0'; i
++)
735 if (!isdigit(s
[i
])) return 0;
742 _asl_msg_op_test(uint32_t op
, char *q
, char *m
, uint32_t n
)
749 t
= op
& ASL_QUERY_OP_TRUE
;
751 if (op
& ASL_QUERY_OP_REGEX
)
753 memset(&rex
, 0, sizeof(regex_t
));
755 rflags
= REG_EXTENDED
| REG_NOSUB
;
756 if (op
& ASL_QUERY_OP_CASEFOLD
) rflags
|= REG_ICASE
;
758 if (regcomp(&rex
, q
, rflags
) != 0) return 0;
759 return (regexec(&rex
, m
, 0, NULL
, 0) == 0);
762 if (op
& ASL_QUERY_OP_NUMERIC
)
764 /* We assume the query contains a numeric string */
765 if (_asl_isanumber(m
) == 0) return 0;
772 case ASL_QUERY_OP_EQUAL
: return (nm
== nq
);
773 case ASL_QUERY_OP_GREATER
: return (nm
> nq
);
774 case ASL_QUERY_OP_GREATER_EQUAL
: return (nm
>= nq
);
775 case ASL_QUERY_OP_LESS
: return (nm
< nq
);
776 case ASL_QUERY_OP_LESS_EQUAL
: return (nm
<= nq
);
777 case ASL_QUERY_OP_NOT_EQUAL
: return (nm
!= nq
);
783 if (op
& ASL_QUERY_OP_CASEFOLD
)
785 if (n
== 0) cmp
= strcasecmp(m
, q
);
786 else cmp
= strncasecmp(m
, q
, n
);
790 if (n
== 0) cmp
= strcmp(m
, q
);
791 else cmp
= strncmp(m
, q
, n
);
796 case ASL_QUERY_OP_EQUAL
: return (cmp
== 0);
797 case ASL_QUERY_OP_GREATER
: return (cmp
> 0);
798 case ASL_QUERY_OP_GREATER_EQUAL
: return (cmp
>= 0);
799 case ASL_QUERY_OP_LESS
: return (cmp
< 0);
800 case ASL_QUERY_OP_LESS_EQUAL
: return (cmp
<= 0);
801 case ASL_QUERY_OP_NOT_EQUAL
: return (cmp
!= 0);
809 _asl_msg_test_op_substr(uint32_t op
, char *q
, char *m
)
811 uint32_t i
, d
, lm
, lq
;
816 if (lq
> lm
) return 0;
819 for (i
= 0; i
< d
; i
++)
821 if (_asl_msg_op_test(op
, q
, m
+ i
, lq
) != 0) return 1;
828 _asl_msg_test_op_prefix(uint32_t op
, char *q
, char *m
)
835 if (lq
> lm
) return 0;
837 return _asl_msg_op_test(op
, q
, m
, lq
);
841 _asl_msg_test_op_suffix(uint32_t op
, char *q
, char *m
)
848 if (lq
> lm
) return 0;
851 return _asl_msg_op_test(op
, q
, m
+ d
, lq
);
855 _asl_msg_test_op(uint32_t op
, char *q
, char *m
)
859 t
= op
& ASL_QUERY_OP_TRUE
;
860 if (t
== ASL_QUERY_OP_TRUE
) return 1;
862 if (op
& ASL_QUERY_OP_PREFIX
)
864 if (op
& ASL_QUERY_OP_SUFFIX
) return _asl_msg_test_op_substr(op
, q
, m
);
865 return _asl_msg_test_op_prefix(op
, q
, m
);
867 if (op
& ASL_QUERY_OP_SUFFIX
) return _asl_msg_test_op_suffix(op
, q
, m
);
869 return _asl_msg_op_test(op
, q
, m
, 0);
873 _asl_msg_test(asl_msg_t
*q
, asl_msg_t
*m
)
881 for (i
= 0; i
< q
->count
; i
++)
883 j
= _asl_msg_index(m
, q
->key
[i
]);
884 if (j
== (uint32_t)-1) return 0;
886 if (q
->val
[i
] == NULL
) continue;
887 if ((q
->op
[i
] & ASL_QUERY_OP_TRUE
) == ASL_QUERY_OP_TRUE
) continue;
889 if (m
->val
[j
] == NULL
) return 0;
894 if (streq(q
->key
[i
], ASL_KEY_TIME
))
896 tick
= asl_parse_time(val
);
899 memset(>ime
, 0, sizeof(struct tm
));
900 gmtime_r(&tick
, >ime
);
902 /* Canonical form: YYYY.MM.DD hh:mm:ss UTC */
904 asprintf(&val
, "%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
);
908 cmp
= _asl_msg_test_op(q
->op
[i
], val
, m
->val
[j
]);
909 if ((freeval
== 1) && (val
!= NULL
)) free(val
);
911 if (cmp
== 0) return 0;
918 asl_msg_cmp(asl_msg_t
*a
, asl_msg_t
*b
)
920 if (a
== NULL
) return 0;
921 if (b
== NULL
) return 0;
923 if (a
->type
== b
->type
) return _asl_msg_equal(a
, b
);
924 if (a
->type
== ASL_TYPE_QUERY
) return _asl_msg_test(a
, b
);
925 return _asl_msg_test(b
, a
);
929 _get_line_from_file(FILE *f
)
934 out
= fgetln(f
, &len
);
935 if (out
== NULL
) return NULL
;
936 if (len
== 0) return NULL
;
938 if (out
[len
] != '\n') len
++;
941 memcpy(s
, out
, len
- 1);
948 * asl_add_file: write log messages to the given file descriptor
949 * Log messages will be written to this file as well as to the server.
952 asl_add_log_file(aslclient ac
, int fd
)
959 asl
= (asl_client_t
*)ac
;
962 asl
= _asl_open_default();
963 if (asl
== NULL
) return -1;
964 pthread_mutex_lock(&_asl_global
.lock
);
968 for (i
= 0; i
< asl
->fd_count
; i
++)
970 if (asl
->fd_list
[i
] == fd
)
972 if (use_global_lock
!= 0) pthread_mutex_unlock(&_asl_global
.lock
);
977 if (asl
->fd_count
== 0)
979 asl
->fd_list
= (int *)calloc(1, sizeof(int));
983 asl
->fd_list
= (int *)realloc(asl
->fd_list
, (1 + asl
->fd_count
) * sizeof(int));
986 if (asl
->fd_list
== NULL
)
988 if (use_global_lock
!= 0) pthread_mutex_unlock(&_asl_global
.lock
);
992 asl
->fd_list
[asl
->fd_count
] = fd
;
995 if (use_global_lock
!= 0) pthread_mutex_unlock(&_asl_global
.lock
);
1000 * asl_remove_file: stop writing log messages to the given file descriptor
1003 asl_remove_log_file(aslclient ac
, int fd
)
1006 int x
, use_global_lock
;
1009 use_global_lock
= 0;
1010 asl
= (asl_client_t
*)ac
;
1013 asl
= _asl_open_default();
1014 if (asl
== NULL
) return -1;
1015 pthread_mutex_lock(&_asl_global
.lock
);
1016 use_global_lock
= 1;
1019 if (asl
->fd_count
== 0)
1021 if (use_global_lock
!= 0) pthread_mutex_unlock(&_asl_global
.lock
);
1026 for (i
= 0; i
< asl
->fd_count
; i
++)
1028 if (asl
->fd_list
[i
] == fd
)
1037 if (use_global_lock
!= 0) pthread_mutex_unlock(&_asl_global
.lock
);
1041 for (i
= x
+ 1; i
< asl
->fd_count
; i
++, x
++) asl
->fd_list
[x
] = asl
->fd_list
[i
];
1044 if (asl
->fd_count
== 0)
1047 asl
->fd_list
= NULL
;
1051 asl
->fd_list
= (int *)realloc(asl
->fd_list
, asl
->fd_count
* sizeof(int));
1052 if (asl
->fd_list
== NULL
)
1055 if (use_global_lock
!= 0) pthread_mutex_unlock(&_asl_global
.lock
);
1060 if (use_global_lock
!= 0) pthread_mutex_unlock(&_asl_global
.lock
);
1065 asl_set_filter(aslclient ac
, int f
)
1067 int last
, use_global_lock
;
1070 use_global_lock
= 0;
1071 asl
= (asl_client_t
*)ac
;
1074 asl
= _asl_open_default();
1075 if (asl
== NULL
) return -1;
1076 pthread_mutex_lock(&_asl_global
.lock
);
1077 use_global_lock
= 1;
1083 if (use_global_lock
!= 0) pthread_mutex_unlock(&_asl_global
.lock
);
1088 * asl_key: examine attribute keys
1089 * returns the key of the nth attribute in a message (beginning at zero)
1090 * returns NULL if the message has fewer attributes
1093 asl_key(aslmsg a
, uint32_t n
)
1097 msg
= (asl_msg_t
*)a
;
1098 if (msg
== NULL
) return NULL
;
1100 if (n
>= msg
->count
) return NULL
;
1105 * asl_new: create a new log message.
1108 asl_new(uint32_t type
)
1114 msg
= calloc(1, sizeof(asl_msg_t
));
1115 if (msg
== NULL
) return NULL
;
1118 if (type
== ASL_TYPE_QUERY
) return (aslmsg
)msg
;
1121 * Defaut attributes are:
1133 msg
->key
= calloc(msg
->count
, sizeof(char *));
1134 if (msg
->key
== NULL
)
1140 msg
->val
= calloc(msg
->count
, sizeof(char *));
1141 if (msg
->val
== NULL
)
1149 msg
->key
[i
] = strdup(ASL_KEY_TIME
);
1150 if (msg
->key
[i
] == NULL
)
1157 msg
->key
[i
] = strdup(ASL_KEY_HOST
);
1158 if (msg
->key
[i
] == NULL
)
1165 msg
->key
[i
] = strdup(ASL_KEY_SENDER
);
1166 if (msg
->key
[i
] == NULL
)
1172 /* Get the value for ASL_KEY_SENDER from cache */
1173 if (_asl_global
.sender
== NULL
)
1175 name
= *(*_NSGetArgv());
1178 x
= strrchr(name
, '/');
1182 pthread_mutex_lock(&_asl_global
.lock
);
1183 if (_asl_global
.sender
== NULL
) _asl_global
.sender
= strdup(x
);
1184 pthread_mutex_unlock(&_asl_global
.lock
);
1188 if (_asl_global
.sender
== NULL
)
1190 msg
->val
[i
] = strdup("Unknown");
1191 if (msg
->val
[i
] == NULL
)
1199 msg
->val
[i
] = strdup(_asl_global
.sender
);
1200 if (msg
->val
[i
] == NULL
)
1208 msg
->key
[i
] = strdup(ASL_KEY_PID
);
1209 if (msg
->key
[i
] == NULL
)
1216 msg
->key
[i
] = strdup(ASL_KEY_UID
);
1217 if (msg
->key
[i
] == NULL
)
1224 msg
->key
[i
] = strdup(ASL_KEY_GID
);
1225 if (msg
->key
[i
] == NULL
)
1232 msg
->key
[i
] = strdup(ASL_KEY_LEVEL
);
1233 if (msg
->key
[i
] == NULL
)
1240 msg
->key
[i
] = strdup(ASL_KEY_MSG
);
1241 if (msg
->key
[i
] == NULL
)
1251 * asl_get: get attribute values from a message
1253 * key: attribute key
1254 * returns the attribute value
1255 * returns NULL if the message does not contain the key
1258 asl_get(aslmsg a
, const char *key
)
1263 msg
= (asl_msg_t
*)a
;
1265 if (msg
== NULL
) return NULL
;
1267 i
= _asl_msg_index(msg
, key
);
1268 if (i
== (uint32_t)-1) return NULL
;
1272 #endif /* BUILDING_VARIANT */
1275 * asl_vlog: Similar to asl_log, but taking a va_list instead of a list of
1278 * level: the log level of the associated message
1279 * format: A formating string followed by a list of arguments, like vprintf()
1280 * returns 0 for success, non-zero for failure
1283 asl_vlog(aslclient ac
, aslmsg a
, int level
, const char *format
, va_list ap
)
1285 int status
, saved_errno
;
1287 char *str
, *fmt
, *estr
;
1288 uint32_t i
, len
, elen
, expand
, my_msg
;
1291 asl
= (asl_client_t
*)ac
;
1295 * Initialize _asl_global so that asl_new will have global data.
1296 * Not strictly necessary, but helps performance.
1298 asl
= _asl_open_default();
1299 if (asl
== NULL
) return -1;
1302 saved_errno
= errno
;
1304 if (format
== NULL
) return -1;
1306 msg
= (asl_msg_t
*)a
;
1312 msg
= asl_new(ASL_TYPE_MSG
);
1313 if (msg
== NULL
) return -1;
1316 if (msg
->type
!= ASL_TYPE_MSG
) return -1;
1318 if (level
< ASL_LEVEL_EMERG
) level
= ASL_LEVEL_EMERG
;
1319 if (level
> ASL_LEVEL_DEBUG
) level
= ASL_LEVEL_DEBUG
;
1322 asprintf(&str
, "%d", level
);
1325 if ((msg
!= NULL
) && (my_msg
!= 0)) asl_free(msg
);
1329 asl_set(msg
, ASL_KEY_LEVEL
, str
);
1332 /* insert strerror for %m */
1335 estr
= strdup(strerror(saved_errno
));
1340 elen
= strlen(estr
);
1342 for (i
= 0; format
[i
] != '\0'; i
++)
1344 if (format
[i
] == '%')
1346 if (format
[i
+1] == '\0') len
++;
1347 else if (format
[i
+1] == 'm')
1363 fmt
= (char *)format
;
1367 fmt
= malloc(len
+ 1);
1370 for (i
= 0; format
[i
] != '\0'; i
++)
1372 if (format
[i
] == '%')
1374 if (format
[i
+1] == '\0')
1377 else if (format
[i
+1] == 'm')
1379 memcpy(fmt
+len
, estr
, elen
);
1385 fmt
[len
++] = format
[i
++];
1386 fmt
[len
++] = format
[i
];
1389 else fmt
[len
++] = format
[i
];
1395 if (estr
!= NULL
) free(estr
);
1397 vasprintf(&str
, fmt
, ap
);
1398 if (expand
!= 0) free(fmt
);
1402 if ((msg
!= NULL
) && (my_msg
!= 0)) asl_free(msg
);
1406 asl_set(msg
, ASL_KEY_MSG
, str
);
1409 status
= asl_send(ac
, (aslmsg
)msg
);
1411 if ((msg
!= NULL
) && (my_msg
!= 0)) asl_free(msg
);
1416 * asl_log: log a message with a particular log level
1418 * level: the log level
1419 * format: A formating string followed by a list of arguments, like printf()
1420 * returns 0 for success, non-zero for failure
1423 asl_log(aslclient ac
, aslmsg a
, int level
, const char *format
, ...)
1428 if (format
== NULL
) return -1;
1430 va_start(ap
, format
);
1431 status
= asl_vlog(ac
, a
, level
, format
, ap
);
1437 #ifndef BUILDING_VARIANT
1440 * asl_send: send a message
1441 * This routine may be used instead of asl_log() or asl_vlog() if asl_set()
1442 * has been used to set all of a message's attributes.
1444 * returns 0 for success, non-zero for failure
1447 asl_send(aslclient ac
, aslmsg msg
)
1450 uint32_t i
, len
, level
, lmask
, outstatus
, filter
;
1453 int status
, rc_filter
;
1455 int use_global_lock
;
1457 use_global_lock
= 0;
1458 asl
= (asl_client_t
*)ac
;
1461 asl
= _asl_open_default();
1462 if (asl
== NULL
) return -1;
1463 use_global_lock
= 1;
1466 if (msg
== NULL
) return 0;
1468 level
= ASL_LEVEL_DEBUG
;
1470 val
= asl_get(msg
, ASL_KEY_LEVEL
);
1471 if (val
!= NULL
) level
= atoi(val
);
1473 lmask
= ASL_FILTER_MASK(level
);
1475 filter
= asl
->filter
;
1478 if (!(asl
->options
& ASL_OPT_NO_REMOTE
))
1480 pthread_mutex_lock(&_asl_global
.lock
);
1482 if (_asl_global
.notify_token
>= 0)
1484 status
= notify_get_state(_asl_global
.notify_token
, &i
);
1485 if ((status
== NOTIFY_STATUS_OK
) && (i
!= 0))
1492 if ((rc_filter
== 0) && (_asl_global
.master_token
>= 0))
1494 status
= notify_get_state(_asl_global
.master_token
, &i
);
1495 if ((status
== NOTIFY_STATUS_OK
) && (i
!= 0))
1501 pthread_mutex_unlock(&_asl_global
.lock
);
1505 * Time, PID, UID, and GID values get set here
1509 asprintf(&str
, "%u", tick
);
1512 asl_set(msg
, ASL_KEY_TIME
, str
);
1517 asprintf(&str
, "%u", getpid());
1520 asl_set(msg
, ASL_KEY_PID
, str
);
1525 asprintf(&str
, "%d", getuid());
1528 asl_set(msg
, ASL_KEY_UID
, str
);
1533 asprintf(&str
, "%u", getgid());
1536 asl_set(msg
, ASL_KEY_GID
, str
);
1541 str
= asl_msg_to_string((asl_msg_t
*)msg
, &len
);
1542 if (str
== NULL
) return -1;
1544 asprintf(&out
, "%10u %s\n", len
+1, str
);
1546 if (out
== NULL
) return -1;
1550 if (use_global_lock
!= 0) pthread_mutex_lock(&_asl_global
.lock
);
1552 if ((filter
!= 0) && ((filter
& lmask
) != 0))
1554 if (asl
->sock
== -1) _asl_connect(asl
);
1556 status
= write(asl
->sock
, out
, len
+ 12);
1559 /* Write failed - try resetting */
1562 status
= write(asl
->sock
, out
, len
+ 12);
1563 if (status
< 0) outstatus
= -1;
1567 if (asl
->options
& ASL_OPT_STDERR
) fprintf(stderr
, "%s", out
);
1569 for (i
= 0; i
< asl
->fd_count
; i
++)
1571 if (asl
->fd_list
[i
] < 0) continue;
1572 status
= write(asl
->fd_list
[i
], out
, len
+ 12);
1575 asl
->fd_list
[i
] = -1;
1580 if (use_global_lock
!= 0) pthread_mutex_unlock(&_asl_global
.lock
);
1588 asl_msg_string(aslmsg a
)
1592 return asl_msg_to_string((asl_msg_t
*)a
, &len
);
1596 * asl_free: free a message
1597 * msg: an aslmsg to free
1605 msg
= (asl_msg_t
*)a
;
1607 if (msg
== NULL
) return;
1609 for (i
= 0; i
< msg
->count
; i
++)
1611 if (msg
->key
[i
] != NULL
) free(msg
->key
[i
]);
1612 if (msg
->val
[i
] != NULL
) free(msg
->val
[i
]);
1617 if (msg
->key
!= NULL
) free(msg
->key
);
1618 if (msg
->val
!= NULL
) free(msg
->val
);
1619 if (msg
->op
!= NULL
) free(msg
->op
);
1626 * asl_set_query: set arbitrary parameters of a query
1627 * Similar to als_set, but allows richer query operations.
1628 * See ASL_QUERY_OP_* above.
1630 * key: attribute key
1631 * value: attribute value
1632 * op: an operation from the set above.
1633 * returns 0 for success, non-zero for failure
1635 int asl_set_query(aslmsg a
, const char *key
, const char *val
, uint32_t op
)
1641 msg
= (asl_msg_t
*)a
;
1643 if (msg
== NULL
) return 0;
1645 if (key
== NULL
) return -1;
1649 if (streq(key
, ASL_KEY_LEVEL
))
1651 if (val
== NULL
) return -1;
1652 if (val
[0] == '\0') return -1;
1653 if ((val
[0] >= '0') && (val
[0] <= '9'))
1656 asprintf(&dv
, "%d", i
);
1657 if (dv
== NULL
) return -1;
1659 else if (!strcasecmp(val
, ASL_STRING_EMERG
)) dv
= strdup("0");
1660 else if (!strcasecmp(val
, ASL_STRING_ALERT
)) dv
= strdup("1");
1661 else if (!strcasecmp(val
, ASL_STRING_CRIT
)) dv
= strdup("2");
1662 else if (!strcasecmp(val
, ASL_STRING_ERR
)) dv
= strdup("3");
1663 else if (!strcasecmp(val
, ASL_STRING_WARNING
)) dv
= strdup("4");
1664 else if (!strcasecmp(val
, ASL_STRING_NOTICE
)) dv
= strdup("5");
1665 else if (!strcasecmp(val
, ASL_STRING_INFO
)) dv
= strdup("6");
1666 else if (!strcasecmp(val
, ASL_STRING_DEBUG
)) dv
= strdup("7");
1670 if ((dv
== NULL
) && (val
!= NULL
))
1673 if (dv
== NULL
) return -1;
1676 for (i
= 0; i
< msg
->count
; i
++)
1678 if (msg
->key
[i
] == NULL
) continue;
1680 if ((msg
->type
!= ASL_TYPE_QUERY
) && (streq(msg
->key
[i
], key
)))
1682 if (msg
->val
[i
] != NULL
) free(msg
->val
[i
]);
1684 if (val
!= NULL
) msg
->val
[i
] = dv
;
1685 if (msg
->op
!= NULL
) msg
->op
[i
] = op
;
1690 if (msg
->count
== 0)
1692 msg
->key
= (char **)calloc(1, sizeof(char *));
1693 if (msg
->key
== NULL
)
1699 msg
->val
= (char **)calloc(1, sizeof(char *));
1700 if (msg
->val
== NULL
)
1706 if (msg
->type
== ASL_TYPE_QUERY
)
1708 msg
->op
= (uint32_t *)calloc(1, sizeof(uint32_t));
1709 if (msg
->op
== NULL
)
1718 msg
->key
= (char **)realloc(msg
->key
, (msg
->count
+ 1) * sizeof(char *));
1719 if (msg
->key
== NULL
)
1725 msg
->val
= (char **)realloc(msg
->val
, (msg
->count
+ 1) * sizeof(char *));
1726 if (msg
->val
== NULL
)
1732 if (msg
->type
== ASL_TYPE_QUERY
)
1734 msg
->op
= (uint32_t *)realloc(msg
->op
, (msg
->count
+ 1) * sizeof(uint32_t));
1735 if (msg
->op
== NULL
)
1744 if (dk
== NULL
) return -1;
1746 msg
->key
[msg
->count
] = dk
;
1747 msg
->val
[msg
->count
] = dv
;
1748 if (msg
->op
!= NULL
) msg
->op
[msg
->count
] = op
;
1755 * asl_set: set attributes of a message
1757 * key: attribute key
1758 * value: attribute value
1759 * returns 0 for success, non-zero for failure
1762 asl_set(aslmsg msg
, const char *key
, const char *val
)
1764 return asl_set_query(msg
, key
, val
, 0);
1768 * asl_unset: remove attributes of a message
1770 * key: attribute key
1771 * returns 0 for success, non-zero for failure
1774 asl_unset(aslmsg a
, const char *key
)
1779 msg
= (asl_msg_t
*)a
;
1781 if (msg
== NULL
) return 0;
1782 if (key
== NULL
) return 0;
1784 for (i
= 0; i
< msg
->count
; i
++)
1786 if (msg
->key
[i
] == NULL
) continue;
1788 if (streq(msg
->key
[i
], key
))
1791 if (msg
->val
[i
] != NULL
) free(msg
->val
[i
]);
1793 for (j
= i
+ 1; j
< msg
->count
; j
++, i
++)
1795 msg
->key
[i
] = msg
->key
[j
];
1796 msg
->val
[i
] = msg
->val
[j
];
1797 if (msg
->op
!= NULL
) msg
->op
[i
] = msg
->op
[j
];
1802 if (msg
->count
== 0)
1810 if (msg
->op
!= NULL
) free(msg
->op
);
1815 msg
->key
= (char **)realloc(msg
->key
, msg
->count
* sizeof(char *));
1816 if (msg
->key
== NULL
) return -1;
1818 msg
->val
= (char **)realloc(msg
->val
, msg
->count
* sizeof(char *));
1819 if (msg
->val
== NULL
) return -1;
1821 if (msg
->op
!= NULL
)
1823 msg
->op
= (uint32_t *)realloc(msg
->op
, msg
->count
* sizeof(uint32_t));
1824 if (msg
->op
== NULL
) return -1;
1836 * asl_search: Search for messages matching the criteria described
1837 * by the aslmsg . The caller should set the attributes to match using
1838 * asl_set_query() or asl_set(). The operatoin ASL_QUERY_OP_EQUAL is
1839 * used for attributes set with asl_set().
1841 * returns: a set of messages that can be iterated over using aslresp_next(),
1842 * and the values can be retrieved using aslresp_get.
1845 asl_search(aslclient ac
, aslmsg a
)
1849 asl_search_result_t
*res
;
1854 if (q
== NULL
) return 0;
1856 log
= fopen(_PATH_ASL_OUT
, "r");
1857 if (log
== NULL
) return NULL
;
1859 res
= (asl_search_result_t
*)calloc(1, sizeof(asl_search_result_t
));
1861 while (NULL
!= (str
= _get_line_from_file(log
)))
1863 m
= asl_msg_from_string(str
);
1864 if (m
== NULL
) continue;
1865 if (asl_msg_cmp(q
, m
) == 0)
1871 if (res
->count
== 0)
1873 res
->msg
= (asl_msg_t
**)calloc(1, sizeof(asl_msg_t
*));
1877 res
->msg
= (asl_msg_t
**)realloc(res
->msg
, (res
->count
+ 1) * sizeof(asl_msg_t
*));
1880 res
->msg
[res
->count
] = m
;
1889 * aslresponse_next: Iterate over responses returned from asl_search()
1890 * a: a response returned from asl_search();
1891 * returns: The next log message (an aslmsg) or NULL on failure
1894 aslresponse_next(aslresponse r
)
1896 asl_search_result_t
*res
;
1899 res
= (asl_search_result_t
*)r
;
1900 if (res
== NULL
) return NULL
;
1902 if (res
->curr
>= res
->count
) return NULL
;
1903 m
= res
->msg
[res
->curr
];
1910 * aslresponse_free: Free a response returned from asl_search()
1911 * a: a response returned from asl_search()
1914 aslresponse_free(aslresponse r
)
1916 asl_search_result_t
*res
;
1919 res
= (asl_search_result_t
*)r
;
1920 if (res
== NULL
) return;
1922 for (i
= 0; i
< res
->count
; i
++) free(res
->msg
[i
]);
1928 asl_syslog_faciliy_name_to_num(const char *name
)
1930 if (name
== NULL
) return -1;
1932 if (strcaseeq(name
, "auth")) return LOG_AUTH
;
1933 if (strcaseeq(name
, "authpriv")) return LOG_AUTHPRIV
;
1934 if (strcaseeq(name
, "cron")) return LOG_CRON
;
1935 if (strcaseeq(name
, "daemon")) return LOG_DAEMON
;
1936 if (strcaseeq(name
, "ftp")) return LOG_FTP
;
1937 if (strcaseeq(name
, "install")) return LOG_INSTALL
;
1938 if (strcaseeq(name
, "kern")) return LOG_KERN
;
1939 if (strcaseeq(name
, "lpr")) return LOG_LPR
;
1940 if (strcaseeq(name
, "mail")) return LOG_MAIL
;
1941 if (strcaseeq(name
, "netinfo")) return LOG_NETINFO
;
1942 if (strcaseeq(name
, "remoteauth")) return LOG_REMOTEAUTH
;
1943 if (strcaseeq(name
, "news")) return LOG_NEWS
;
1944 if (strcaseeq(name
, "security")) return LOG_AUTH
;
1945 if (strcaseeq(name
, "syslog")) return LOG_SYSLOG
;
1946 if (strcaseeq(name
, "user")) return LOG_USER
;
1947 if (strcaseeq(name
, "uucp")) return LOG_UUCP
;
1948 if (strcaseeq(name
, "local0")) return LOG_LOCAL0
;
1949 if (strcaseeq(name
, "local1")) return LOG_LOCAL1
;
1950 if (strcaseeq(name
, "local2")) return LOG_LOCAL2
;
1951 if (strcaseeq(name
, "local3")) return LOG_LOCAL3
;
1952 if (strcaseeq(name
, "local4")) return LOG_LOCAL4
;
1953 if (strcaseeq(name
, "local5")) return LOG_LOCAL5
;
1954 if (strcaseeq(name
, "local6")) return LOG_LOCAL6
;
1955 if (strcaseeq(name
, "local7")) return LOG_LOCAL7
;
1956 if (strcaseeq(name
, "launchd")) return LOG_LAUNCHD
;
1962 asl_syslog_faciliy_num_to_name(int n
)
1964 if (n
< 0) return NULL
;
1966 if (n
== LOG_AUTH
) return "auth";
1967 if (n
== LOG_AUTHPRIV
) return "authpriv";
1968 if (n
== LOG_CRON
) return "cron";
1969 if (n
== LOG_DAEMON
) return "daemon";
1970 if (n
== LOG_FTP
) return "ftp";
1971 if (n
== LOG_INSTALL
) return "install";
1972 if (n
== LOG_KERN
) return "kern";
1973 if (n
== LOG_LPR
) return "lpr";
1974 if (n
== LOG_MAIL
) return "mail";
1975 if (n
== LOG_NETINFO
) return "netinfo";
1976 if (n
== LOG_REMOTEAUTH
) return "remoteauth";
1977 if (n
== LOG_NEWS
) return "news";
1978 if (n
== LOG_AUTH
) return "security";
1979 if (n
== LOG_SYSLOG
) return "syslog";
1980 if (n
== LOG_USER
) return "user";
1981 if (n
== LOG_UUCP
) return "uucp";
1982 if (n
== LOG_LOCAL0
) return "local0";
1983 if (n
== LOG_LOCAL1
) return "local1";
1984 if (n
== LOG_LOCAL2
) return "local2";
1985 if (n
== LOG_LOCAL3
) return "local3";
1986 if (n
== LOG_LOCAL4
) return "local4";
1987 if (n
== LOG_LOCAL5
) return "local5";
1988 if (n
== LOG_LOCAL6
) return "local6";
1989 if (n
== LOG_LOCAL7
) return "local7";
1990 if (n
== LOG_LAUNCHD
) return "launchd";
1996 * utility for converting a time string into a time_t
1997 * we only deal with the following formats:
1998 * Canonical form YYYY.MM.DD hh:mm:ss UTC
1999 * ctime() form Mth dd hh:mm:ss (e.g. Aug 25 09:54:37)
2000 * absolute form - # seconds since the epoch (e.g. 1095789191)
2001 * relative time - seconds before or after now (e.g. -300, +43200)
2002 * relative time - days/hours/minutes/seconds before or after now (e.g. -1d, +6h, +30m, -10s)
2005 #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$"
2006 #define CTIME_REX "^[adfjmnos][aceopu][bcglnprtvy][ ]+[0-3]?[0-9][ ]+[0-2]?[0-9]:[0-5][0-9]:[0-5][0-9]$"
2007 #define ABSOLUTE_TIME_REX "^[0-9]+[s]?$"
2008 #define RELATIVE_TIME_REX "^[\\+-\\][0-9]+[smhdw]?$"
2010 #define SECONDS_PER_MINUTE 60
2011 #define SECONDS_PER_HOUR 3600
2012 #define SECONDS_PER_DAY 86400
2013 #define SECONDS_PER_WEEK 604800
2016 * We use the last letter in the month name to determine
2017 * the month number (0-11). There are two collisions:
2018 * Jan and Jun both end in n
2019 * Mar and Apr both end in r
2020 * In these cases we check the second letter.
2022 * The MTH_LAST array maps the last letter to a number.
2024 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};
2033 if (s
[2] > 90) v8
= s
[2] - 'a';
2034 else v8
= s
[2] - 'A';
2036 if ((v8
< 0) || (v8
> 25)) return -1;
2039 if (v8
< 0) return -1;
2042 if ((i
== 5) && ((s
[1] == 'a') || (s
[1] == 'A'))) return 0;
2043 if ((i
== 3) && ((s
[1] == 'a') || (s
[1] == 'A'))) return 2;
2048 asl_parse_time(const char *in
)
2050 int len
, y
, status
, rflags
, factor
;
2054 static regex_t rex_canon
, rex_ctime
, rex_abs
, rex_rel
;
2055 static int init_canon
= 0;
2056 static int init_ctime
= 0;
2057 static int init_abs
= 0;
2058 static int init_rel
= 0;
2060 if (in
== NULL
) return -1;
2062 rflags
= REG_EXTENDED
| REG_NOSUB
| REG_ICASE
;
2064 if (init_canon
== 0)
2066 memset(&rex_canon
, 0, sizeof(regex_t
));
2067 status
= regcomp(&rex_canon
, CANONICAL_TIME_REX
, rflags
);
2068 if (status
!= 0) return -1;
2072 if (init_ctime
== 0)
2074 memset(&rex_ctime
, 0, sizeof(regex_t
));
2075 status
= regcomp(&rex_ctime
, CTIME_REX
, rflags
);
2076 if (status
!= 0) return -1;
2082 memset(&rex_abs
, 0, sizeof(regex_t
));
2083 status
= regcomp(&rex_abs
, ABSOLUTE_TIME_REX
, rflags
);
2084 if (status
!= 0) return -1;
2090 memset(&rex_rel
, 0, sizeof(regex_t
));
2091 status
= regcomp(&rex_rel
, RELATIVE_TIME_REX
, rflags
);
2092 if (status
!= 0) return -1;
2096 len
= strlen(in
) + 1;
2098 if (regexec(&rex_abs
, in
, 0, NULL
, 0) == 0)
2101 * Absolute time (number of seconds since the epoch)
2104 if ((str
[len
-2] == 's') || (str
[len
-2] == 'S')) str
[len
-2] = '\0';
2111 else if (regexec(&rex_rel
, in
, 0, NULL
, 0) == 0)
2114 * Reletive time (number of seconds before or after right now)
2120 if ((str
[len
-2] == 's') || (str
[len
-2] == 'S'))
2124 else if ((str
[len
-2] == 'm') || (str
[len
-2] == 'M'))
2127 factor
= SECONDS_PER_MINUTE
;
2129 else if ((str
[len
-2] == 'h') || (str
[len
-2] == 'H'))
2132 factor
= SECONDS_PER_HOUR
;
2134 else if ((str
[len
-2] == 'd') || (str
[len
-2] == 'D'))
2137 factor
= SECONDS_PER_DAY
;
2139 else if ((str
[len
-2] == 'w') || (str
[len
-2] == 'W'))
2142 factor
= SECONDS_PER_WEEK
;
2146 delta
= factor
* atoi(str
);
2153 else if (regexec(&rex_canon
, in
, 0, NULL
, 0) == 0)
2155 memset(&t
, 0, sizeof(struct tm
));
2162 t
.tm_year
= atoi(x
) - 1900;
2168 t
.tm_mon
= atoi(x
) - 1;
2174 t
.tm_mday
= atoi(x
);
2177 for (x
= p
+ 1; *x
== ' '; x
++);
2180 t
.tm_hour
= atoi(x
);
2197 else if (regexec(&rex_ctime
, in
, 0, NULL
, 0) == 0)
2199 /* We assume it's in the current year */
2200 memset(&t
, 0, sizeof(struct tm
));
2202 gmtime_r(&tick
, &t
);
2205 memset(&t
, 0, sizeof(struct tm
));
2209 t
.tm_mon
= _month_num(str
);
2210 if (t
.tm_mon
< 0) return -1;
2212 for (x
= strchr(str
, ' '); *x
== ' '; x
++);
2215 t
.tm_mday
= atoi(x
);
2218 for (x
= p
+ 1; *x
== ' '; x
++);
2221 t
.tm_hour
= atoi(x
);
2242 #ifdef ASL_SYSLOG_COMPAT
2244 __private_extern__
void
2245 asl_syslog_syslog(int pri
, const char *fmt
, ...)
2250 if (fmt
== NULL
) return;
2252 m
= asl_new(ASL_TYPE_MSG
);
2255 asl_vlog(NULL
, m
, pri
, fmt
, ap
);
2261 __private_extern__
void
2262 asl_syslog_vsyslog(int pri
, const char *fmt
, va_list ap
)
2266 m
= asl_new(ASL_TYPE_MSG
);
2267 asl_vlog(NULL
, m
, pri
, fmt
, ap
);
2271 __private_extern__
void
2272 asl_syslog_openlog(const char *ident
, int flags
, int facility
)
2279 if (flags
& LOG_NDELAY
) opts
|= ASL_OPT_NO_DELAY
;
2280 if (flags
& LOG_PERROR
) opts
|= ASL_OPT_STDERR
;
2282 fname
= asl_syslog_faciliy_num_to_name(facility
);
2283 if (fname
== NULL
) fname
= "user";
2285 asl_global_client
= asl_open(ident
, fname
, opts
);
2288 __private_extern__
void
2289 asl_syslog_closelog()
2294 __private_extern__
int
2295 asl_syslog_setlogmask(int p
)
2297 return asl_set_filter(p
);
2300 #endif ASL_SYSLOG_COMPAT
2302 #endif /* BUILDING_VARIANT */