2 * Copyright (c) 2007-2011 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 #include <TargetConditionals.h>
34 #include <sys/socket.h>
35 #include <sys/sysctl.h>
36 #include <netinet/in.h>
37 #include <arpa/inet.h>
38 #include <mach/mach.h>
39 #include <servers/bootstrap.h>
40 #include <bootstrap_priv.h>
45 #include <asl_private.h>
48 #include <asl_store.h>
50 #include "asl_common.h"
52 #define MOD_CASE_FOLD 'C'
54 #define MOD_SUBSTRING 'S'
55 #define MOD_PREFIX 'A'
56 #define MOD_SUFFIX 'Z'
57 #define MOD_NUMERIC 'N'
66 #define ASL_QUERY_OP_NOT 0x1000
68 #define QUERY_FLAG_SEARCH_REVERSE 0x00000001
70 #define FACILITY_CONSOLE "com.apple.console"
72 /* Shared with Libc */
73 #define NOTIFY_RC "com.apple.asl.remote"
75 /* XXX add to asl_private.h */
76 #define ASL_OPT_CONTROL "control"
80 #define SEARCH_MATCH 1
82 #define PROC_NOT_FOUND -1
83 #define PROC_NOT_UNIQUE -2
88 #define forever for(;;)
90 #define SEND_FORMAT_LEGACY 0
91 #define SEND_FORMAT_ASL 1
93 #define FORMAT_RAW 0x00000100
94 #define FORMAT_LEGACY 0x00000200
95 #define FORMAT_STD 0x00000400
96 #define FORMAT_XML 0x00000800
97 #define COMPRESS_DUPS 0x00010000
99 #define EXPORT 0x00000100
101 #define ASL_FILTER_MASK_PACEWNID 0xff
102 #define ASL_FILTER_MASK_PACEWNI 0x7f
103 #define ASL_FILTER_MASK_PACEWN 0x3f
104 #define ASL_FILTER_MASK_PACEW 0x1f
105 #define ASL_FILTER_MASK_PACE 0x0f
106 #define ASL_FILTER_MASK_PAC 0x07
108 #define FETCH_BATCH 1024
109 #define MAX_RANDOM 8192
111 #define DB_SELECT_ASL 0
112 #define DB_SELECT_STORE 1
113 #define DB_SELECT_FILES 2
114 #define DB_SELECT_SYSLOGD 3
115 #define DB_SELECT_LEGACY 4
117 /* STD and BSD format messages start with 'DAY MMM DD HH:MM:SS ' timestamp */
118 #define STD_BSD_DATE_LEN 20
120 /* Max message size for direct watch */
121 #define MAX_DIRECT_SIZE 16384
123 /* Buffer for direct watch data */
124 #define DIRECT_BUF_SIZE 1024
126 static asl_file_list_t
*db_files
= NULL
;
127 static asl_store_t
*store
= NULL
;
128 static asl_file_t
*legacy
= NULL
;
129 static asl_file_t
*export
= NULL
;
130 static const char *sort_key
= NULL
;
131 static const char *sort_key_2
= NULL
;
132 static int sort_numeric
= 0;
133 static char *last_printmsg_str
= NULL
;
134 static int last_printmsg_count
= 0;
135 static const char *tfmt
= NULL
;
137 #if TARGET_OS_EMBEDDED
138 static uint32_t dbselect
= DB_SELECT_SYSLOGD
;
140 static uint32_t dbselect
= DB_SELECT_ASL
;
144 uint32_t notify_register_plain(const char *name
, int *out_token
);
146 extern asl_msg_t
*asl_msg_from_string(const char *buf
);
147 extern char *asl_list_to_string(asl_search_result_t
*list
, uint32_t *outlen
);
148 extern asl_search_result_t
*asl_list_from_string(const char *buf
);
149 extern int asl_msg_cmp(asl_msg_t
*a
, asl_msg_t
*b
);
150 extern time_t asl_parse_time(const char *in
);
151 /* END PRIVATE API */
153 static mach_port_t asl_server_port
= MACH_PORT_NULL
;
155 static const char *myname
= "syslog";
158 asl_search_result_t
*syslogd_query(asl_search_result_t
*q
, uint64_t start
, int count
, int dir
, uint64_t *last
);
159 static void printmsg(FILE *f
, aslmsg msg
, char *fmt
, int pflags
);
164 fprintf(stderr
, "usage:\n");
165 fprintf(stderr
, "%s -s [-r host] [-l level] message...\n", myname
);
166 fprintf(stderr
, " send a message\n");
167 fprintf(stderr
, "\n");
168 fprintf(stderr
, "%s -s [-r host] -k key val [key val]...\n", myname
);
169 fprintf(stderr
, " send a message with the given keys and values\n");
170 fprintf(stderr
, "\n");
171 fprintf(stderr
, "%s -c process [filter]\n", myname
);
172 fprintf(stderr
, " get (set if filter is specified) syslog filter for process (pid or name)\n");
173 fprintf(stderr
, " level may be any combination of the characters \"p a c e w n i d\"\n");
174 fprintf(stderr
, " p = Emergency (\"Panic\")\n");
175 fprintf(stderr
, " a = Alert\n");
176 fprintf(stderr
, " c = Critical\n");
177 fprintf(stderr
, " e = Error\n");
178 fprintf(stderr
, " w = Warning\n");
179 fprintf(stderr
, " n = Notice\n");
180 fprintf(stderr
, " i = Info\n");
181 fprintf(stderr
, " d = Debug\n");
182 fprintf(stderr
, " a minus sign preceding a single letter means \"up to\" that level\n");
183 fprintf(stderr
, "\n");
184 fprintf(stderr
, "%s -config [params...]\n", myname
);
185 fprintf(stderr
, " without params, fetch and print syslogd parameters and statistics\n");
186 fprintf(stderr
, " otherwise, set or reset syslogd configuration parameters\n");
187 fprintf(stderr
, "\n");
188 fprintf(stderr
, "%s -module [name [action]]\n", myname
);
189 fprintf(stderr
, " with no name, prints configuration for all ASL output modules\n");
190 fprintf(stderr
, " with name and no action, prints configuration for named ASL output module\n");
191 fprintf(stderr
, " supported actions - module name required, use '*' (with single quotes) for all modules:\n");
192 fprintf(stderr
, " enable [01] enables (or disables with 0) named module\n");
193 fprintf(stderr
, " does not apply to com.apple.asl when '*' is used\n");
194 fprintf(stderr
, " checkpoint [file] checkpoints all files or specified file for named module\n");
195 fprintf(stderr
, "\n");
196 fprintf(stderr
, "%s [-f file...] [-d path...] [-x file] [-w [N]] [-F format] [-nocompress] [-u] [-sort key1 [key2]] [-nsort key1 [key2]] [-k key [[op] val]]... [-o -k key [[op] val]] ...]...\n", myname
);
197 fprintf(stderr
, " -f read named file[s], rather than standard log message store.\n");
198 fprintf(stderr
, " -d read all file in named directory path, rather than standard log message store.\n");
199 fprintf(stderr
, " -x export to named ASL format file, rather than printing\n");
200 fprintf(stderr
, " -w watch data store (^C to quit)\n");
201 fprintf(stderr
, " prints the last N matching lines (default 10) before waiting\n");
202 fprintf(stderr
, " \"-w all\" prints all matching lines before waiting\n");
203 fprintf(stderr
, " \"-w boot\" prints all matching lines since last system boot before waiting\n");
204 fprintf(stderr
, " -F output format may be \"std\", \"raw\", \"bsd\", or \"xml\"\n");
205 fprintf(stderr
, " format may also be a string containing variables of the form\n");
206 fprintf(stderr
, " $Key or $(Key) - use the latter for non-whitespace delimited variables\n");
207 fprintf(stderr
, " -T timestamp format may be \"sec\" (seconds), \"utc\" (UTC), or \"local\" (local timezone)\n");
208 fprintf(stderr
, " -E text encoding may be \"vis\", \"safe\", or \"none\"\n");
209 fprintf(stderr
, " -nodc no duplicate message compression\n");
210 fprintf(stderr
, " -u print timestamps using UTC (equivalent to \"-T utc\")\n");
211 fprintf(stderr
, " -sort sort messages using value for specified key1 (secondary sort by key2 if provided)\n");
212 fprintf(stderr
, " -nsort numeric sort messages using value for specified key1 (secondary sort by key2 if provided)\n");
213 fprintf(stderr
, " -k key/value match\n");
214 fprintf(stderr
, " if no operator or value is given, checks for the existence of the key\n");
215 fprintf(stderr
, " if no operator is given, default is \"%s\"\n", OP_EQ
);
216 fprintf(stderr
, " -B only process log messages since last system boot\n");
217 fprintf(stderr
, " -C alias for \"-k Facility com.apple.console\"\n");
218 fprintf(stderr
, " -o begins a new query\n");
219 fprintf(stderr
, " queries are \'OR\'ed together\n");
220 fprintf(stderr
, "operators are zero or more modifiers followed by a comparison\n");
221 fprintf(stderr
, " %s equal\n", OP_EQ
);
222 fprintf(stderr
, " %s not equal\n", OP_NE
);
223 fprintf(stderr
, " %s greater than\n", OP_GT
);
224 fprintf(stderr
, " %s greater or equal\n", OP_GE
);
225 fprintf(stderr
, " %s less than\n", OP_LT
);
226 fprintf(stderr
, " %s less or equal\n", OP_LE
);
227 fprintf(stderr
, "optional modifiers for operators\n");
228 fprintf(stderr
, " %c case-fold\n", MOD_CASE_FOLD
);
229 fprintf(stderr
, " %c regular expression\n", MOD_REGEX
);
230 fprintf(stderr
, " %c substring\n", MOD_SUBSTRING
);
231 fprintf(stderr
, " %c prefix\n", MOD_PREFIX
);
232 fprintf(stderr
, " %c suffix\n", MOD_SUFFIX
);
233 fprintf(stderr
, " %c numeric comparison\n", MOD_NUMERIC
);
237 notify_status_string(int status
)
239 if (status
== NOTIFY_STATUS_OK
) return "OK";
240 if (status
== NOTIFY_STATUS_INVALID_NAME
) return "Process not registered";
241 if (status
== NOTIFY_STATUS_NOT_AUTHORIZED
) return "Not authorized";
242 return "Operation failed";
246 asl_level_string(int level
)
248 if (level
== ASL_LEVEL_EMERG
) return ASL_STRING_EMERG
;
249 if (level
== ASL_LEVEL_ALERT
) return ASL_STRING_ALERT
;
250 if (level
== ASL_LEVEL_CRIT
) return ASL_STRING_CRIT
;
251 if (level
== ASL_LEVEL_ERR
) return ASL_STRING_ERR
;
252 if (level
== ASL_LEVEL_WARNING
) return ASL_STRING_WARNING
;
253 if (level
== ASL_LEVEL_NOTICE
) return ASL_STRING_NOTICE
;
254 if (level
== ASL_LEVEL_INFO
) return ASL_STRING_INFO
;
255 if (level
== ASL_LEVEL_DEBUG
) return ASL_STRING_DEBUG
;
260 module_control(int argc
, char *argv
[])
262 const char *val
= NULL
;
263 asl_search_result_t
*q
;
268 ctl
= (asl_msg_t
*)_asl_server_control_query();
271 fprintf(stderr
, "can't get status information from syslogd\n");
283 asl_out_module_t
*m
= asl_out_module_init();
284 asl_out_module_t
*x
= m
;
288 if ((argc
== 0) || (!strcmp(argv
[0], x
->name
)))
290 asl_msg_lookup(ctl
, x
->name
, &val
, NULL
);
292 if (first
== 0) printf("\n");
295 if (x
->name
== NULL
) printf("ASL out module has no name\n");
296 else printf("ASL out module: %s %s[current status: %s]\n", x
->name
, (x
->flags
& MODULE_FLAG_LOCAL
) ? "local " : "", (val
== NULL
) ? "unknown" : val
);
298 asl_out_module_print(stdout
, x
);
304 asl_msg_release(ctl
);
305 asl_out_module_free(m
);
309 /* name enable [val] */
310 /* name disable [val] */
311 if ((!strcmp(argv
[1], "enable")) || (!strcmp(argv
[1], "disable")))
318 if (!strcmp(argv
[1], "enable"))
320 if (argc
< 3) want
= 1;
321 else if (!strcmp(argv
[2], "1")) want
= 1;
322 else if (!strcmp(argv
[2], "0")) want
= 0;
325 printf("invalid value %s for %s %s - expecting 0 or 1\n", argv
[2], argv
[0], argv
[1]);
331 if (argc
< 3) want
= 0;
332 else if (!strcmp(argv
[2], "1")) want
= 0;
333 else if (!strcmp(argv
[2], "0")) want
= 1;
336 printf("invalid value %s for %s %s - expecting 0 or 1\n", argv
[2], argv
[0], argv
[1]);
341 asl_msg_lookup(ctl
, argv
[0], &val
, NULL
);
344 if (!strcmp(val
, "enabled")) status
= 1;
348 asl_msg_release(ctl
);
352 printf("internal error: want = -1\n");
358 printf("module %s is already %s\n", argv
[0], val
);
362 cm
= asl_new(ASL_TYPE_MSG
);
363 asprintf(&str
, "@ %s enable %d", argv
[0], want
);
365 if ((cm
== NULL
) || (str
== NULL
))
367 fprintf(stderr
, "can't allocate memory - exiting\n");
371 ac
= asl_open(NULL
, NULL
, 0);
372 asl_set_filter(ac
, ASL_FILTER_MASK_UPTO(ASL_LEVEL_DEBUG
));
373 asl_set(cm
, ASL_KEY_LEVEL
, "7");
374 asl_set(cm
, ASL_KEY_OPTION
, "control");
375 asl_set(cm
, ASL_KEY_MSG
, str
);
381 asl_msg_release(ctl
);
385 asl_msg_release(ctl
);
387 /* name checkpoint [file] */
388 if (!strcmp(argv
[1], "checkpoint"))
390 q
= (asl_search_result_t
*)calloc(1, sizeof(q
));
391 qm
= asl_msg_new(ASL_TYPE_QUERY
);
393 if ((q
== NULL
) || (qm
== NULL
))
395 fprintf(stderr
, "can't allocate memory - exiting\n");
399 q
->msg
= (asl_msg_t
**)calloc(1, sizeof(asl_msg_t
*));
402 fprintf(stderr
, "can't allocate memory - exiting\n");
409 asl_msg_set_key_val_op(qm
, ASL_KEY_OPTION
, "control", ASL_QUERY_OP_EQUAL
);
410 asprintf(&str
, "%s checkpoint%s%s", argv
[0], (argc
> 2) ? " " : "", (argc
> 2) ? argv
[2] : "");
411 asl_msg_set_key_val_op(qm
, "action", str
, ASL_QUERY_OP_EQUAL
);
413 asl_search_result_t
*res
= syslogd_query(q
, 0, 0, 1, &last
);
416 aslresponse_free((aslresponse
)res
);
420 printf("unknown module control: %s\n", argv
[1]);
425 procinfo(char *pname
, int *pid
, int *uid
)
428 int i
, status
, nprocs
;
430 struct kinfo_proc
*procs
, *newprocs
;
437 mib
[2] = KERN_PROC_ALL
;
441 status
= sysctl(mib
, miblen
, NULL
, &size
, NULL
, 0);
445 newprocs
= reallocf(procs
, size
);
446 if (newprocs
== NULL
)
448 if (procs
!= NULL
) free(procs
);
449 return PROC_NOT_FOUND
;
453 status
= sysctl(mib
, miblen
, procs
, &size
, NULL
, 0);
454 } while ((status
== -1) && (errno
== ENOMEM
));
458 if (procs
!= NULL
) free(procs
);
459 return PROC_NOT_FOUND
;
462 if (size
% sizeof(struct kinfo_proc
) != 0)
464 if (procs
!= NULL
) free(procs
);
465 return PROC_NOT_FOUND
;
468 if (procs
== NULL
) return PROC_NOT_FOUND
;
470 nprocs
= size
/ sizeof(struct kinfo_proc
);
474 /* Search for a pid */
475 for (i
= 0; i
< nprocs
; i
++)
477 if (*pid
== procs
[i
].kp_proc
.p_pid
)
479 *uid
= procs
[i
].kp_eproc
.e_ucred
.cr_uid
;
484 return PROC_NOT_FOUND
;
487 *pid
= PROC_NOT_FOUND
;
489 for (i
= 0; i
< nprocs
; i
++)
491 if (!strcmp(procs
[i
].kp_proc
.p_comm
, pname
))
493 if (*pid
!= PROC_NOT_FOUND
)
496 return PROC_NOT_UNIQUE
;
499 *pid
= procs
[i
].kp_proc
.p_pid
;
500 *uid
= procs
[i
].kp_eproc
.e_ucred
.cr_uid
;
505 if (*pid
== PROC_NOT_FOUND
) return PROC_NOT_FOUND
;
511 rcontrol_get_string(const char *name
, int *val
)
516 status
= notify_register_plain(name
, &t
);
517 if (status
!= NOTIFY_STATUS_OK
) return status
;
520 status
= notify_get_state(t
, &x
);
529 rcontrol_set_string(const char *name
, int filter
)
534 status
= notify_register_plain(name
, &t
);
535 if (status
!= NOTIFY_STATUS_OK
) return status
;
538 status
= notify_set_state(t
, x
);
539 notify_post(NOTIFY_RC
);
545 asl_string_to_filter(char *s
)
549 if (s
== NULL
) return 0;
550 if (s
[0] == '\0') return 0;
552 if ((s
[0] >= '0') && (s
[0] <= '9')) return ASL_FILTER_MASK(atoi(s
));
556 if ((s
[1] == 'P') || (s
[1] == 'p')) i
= ASL_LEVEL_EMERG
;
557 else if ((s
[1] == 'A') || (s
[1] == 'a')) i
= ASL_LEVEL_ALERT
;
558 else if ((s
[1] == 'C') || (s
[1] == 'c')) i
= ASL_LEVEL_CRIT
;
559 else if ((s
[1] == 'E') || (s
[1] == 'e')) i
= ASL_LEVEL_ERR
;
560 else if ((s
[1] == 'X') || (s
[1] == 'x')) i
= ASL_LEVEL_ERR
;
561 else if ((s
[1] == 'W') || (s
[1] == 'w')) i
= ASL_LEVEL_WARNING
;
562 else if ((s
[1] == 'N') || (s
[1] == 'n')) i
= ASL_LEVEL_NOTICE
;
563 else if ((s
[1] == 'I') || (s
[1] == 'i')) i
= ASL_LEVEL_INFO
;
564 else if ((s
[1] == 'D') || (s
[1] == 'd')) i
= ASL_LEVEL_DEBUG
;
565 else i
= atoi(s
+ 1);
566 f
= ASL_FILTER_MASK_UPTO(i
);
571 for (i
= 0; s
[i
] != '\0'; i
++)
573 if ((s
[i
] == 'P') || (s
[i
] == 'p')) f
|= ASL_FILTER_MASK_EMERG
;
574 else if ((s
[i
] == 'A') || (s
[i
] == 'a')) f
|= ASL_FILTER_MASK_ALERT
;
575 else if ((s
[i
] == 'C') || (s
[i
] == 'c')) f
|= ASL_FILTER_MASK_CRIT
;
576 else if ((s
[i
] == 'E') || (s
[i
] == 'e')) f
|= ASL_FILTER_MASK_ERR
;
577 else if ((s
[i
] == 'X') || (s
[i
] == 'x')) f
|= ASL_FILTER_MASK_ERR
;
578 else if ((s
[i
] == 'W') || (s
[i
] == 'w')) f
|= ASL_FILTER_MASK_WARNING
;
579 else if ((s
[i
] == 'N') || (s
[i
] == 'n')) f
|= ASL_FILTER_MASK_NOTICE
;
580 else if ((s
[i
] == 'I') || (s
[i
] == 'i')) f
|= ASL_FILTER_MASK_INFO
;
581 else if ((s
[i
] == 'D') || (s
[i
] == 'd')) f
|= ASL_FILTER_MASK_DEBUG
;
588 asl_filter_string(int f
)
590 static char str
[1024];
593 memset(str
, 0, sizeof(str
));
596 if ((f
== ASL_FILTER_MASK_PACEWNID
) != 0)
598 strcat(str
, "Emergency - Debug");
602 if ((f
== ASL_FILTER_MASK_PACEWNI
) != 0)
604 strcat(str
, "Emergency - Info");
608 if ((f
== ASL_FILTER_MASK_PACEWN
) != 0)
610 strcat(str
, "Emergency - Notice");
614 if ((f
== ASL_FILTER_MASK_PACEW
) != 0)
616 strcat(str
, "Emergency - Warning");
620 if ((f
== ASL_FILTER_MASK_PACE
) != 0)
622 strcat(str
, "Emergency - Error");
626 if ((f
== ASL_FILTER_MASK_PAC
) != 0)
628 strcat(str
, "Emergency - Critical");
632 if ((f
& ASL_FILTER_MASK_EMERG
) != 0)
634 strcat(str
, "Emergency");
638 if ((f
& ASL_FILTER_MASK_ALERT
) != 0)
640 if (i
> 0) strcat(str
, ", ");
641 strcat(str
, "Alert");
645 if ((f
& ASL_FILTER_MASK_CRIT
) != 0)
647 if (i
> 0) strcat(str
, ", ");
648 strcat(str
, "Critical");
652 if ((f
& ASL_FILTER_MASK_ERR
) != 0)
654 if (i
> 0) strcat(str
, ", ");
655 strcat(str
, "Error");
659 if ((f
& ASL_FILTER_MASK_WARNING
) != 0)
661 if (i
> 0) strcat(str
, ", ");
662 strcat(str
, "Warning");
666 if ((f
& ASL_FILTER_MASK_NOTICE
) != 0)
668 if (i
> 0) strcat(str
, ", ");
669 strcat(str
, "Notice");
673 if ((f
& ASL_FILTER_MASK_INFO
) != 0)
675 if (i
> 0) strcat(str
, ", ");
680 if ((f
& ASL_FILTER_MASK_DEBUG
) != 0)
682 if (i
> 0) strcat(str
, ", ");
683 strcat(str
, "Debug");
687 if (i
== 0) sprintf(str
, "Off");
693 rcontrol_name(pid_t pid
, uid_t uid
)
695 static char str
[1024];
697 if (pid
== RC_MASTER
) return NOTIFY_SYSTEM_MASTER
;
699 memset(str
, 0, sizeof(str
));
700 if (uid
== 0) snprintf(str
, sizeof(str
) - 1, "%s.%d", NOTIFY_PREFIX_SYSTEM
, pid
);
701 else snprintf(str
, sizeof(str
) - 1, "user.uid.%d.syslog.%d", uid
, pid
);
706 rcontrol_get(pid_t pid
, uid_t uid
)
714 status
= rcontrol_get_string(rcontrol_name(pid
, uid
), &filter
);
715 if (status
== NOTIFY_STATUS_OK
)
717 printf("Master filter mask: %s\n", asl_filter_string(filter
));
721 printf("Unable to determine master filter mask\n");
725 status
= rcontrol_get_string(rcontrol_name(pid
, uid
), &filter
);
726 if (status
== NOTIFY_STATUS_OK
)
728 printf("Process %d syslog filter mask: %s\n", pid
, asl_filter_string(filter
));
732 printf("Unable to determine syslog filter mask for pid %d\n", pid
);
737 rcontrol_set(pid_t pid
, uid_t uid
, int filter
)
742 rcname
= rcontrol_name(pid
, uid
);
746 status
= rcontrol_set_string(rcname
, filter
);
748 if (status
== NOTIFY_STATUS_OK
)
750 if (pid
== RC_MASTER
) status
= notify_post(NOTIFY_SYSTEM_MASTER
);
754 printf("Unable to set master syslog filter mask: %s\n", notify_status_string(status
));
758 status
= rcontrol_set_string(rcname
, filter
);
759 if (status
== NOTIFY_STATUS_OK
)
761 status
= notify_post(rcname
);
765 printf("Unable to set syslog filter mask for pid %d: %s\n", pid
, notify_status_string(status
));
770 rsend(aslmsg msg
, char *rhost
)
778 struct sockaddr_in dst
;
780 char myname
[MAXHOSTNAMELEN
+ 1];
782 if (msg
== NULL
) return 0;
784 h
= gethostbyname(rhost
);
785 if (h
== NULL
) return -1;
787 s
= socket(AF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
788 if (s
<= 0) return -1;
790 memset(&dst
, 0, sizeof(struct sockaddr_in
));
791 memcpy(&(dst
.sin_addr
.s_addr
), h
->h_addr_list
[0], 4);
792 dst
.sin_family
= AF_INET
;
794 dst
.sin_len
= sizeof(struct sockaddr_in
);
796 level
= ASL_LEVEL_DEBUG
;
798 val
= asl_get(msg
, ASL_KEY_LEVEL
);
799 if (val
!= NULL
) level
= atoi(val
);
804 asprintf(×tr
, "%lu", tick
);
807 asl_set(msg
, ASL_KEY_TIME
, timestr
);
811 if (gethostname(myname
, MAXHOSTNAMELEN
) == 0) asl_set(msg
, ASL_KEY_HOST
, myname
);
814 str
= asl_msg_to_string((asl_msg_t
*)msg
, &len
);
815 if (str
== NULL
) return -1;
817 asprintf(&out
, "%10u %s\n", len
+1, str
);
819 if (out
== NULL
) return -1;
821 sendto(s
, out
, len
+12, 0, (const struct sockaddr
*)&dst
, sizeof(struct sockaddr_in
));
829 rlegacy(char *msg
, int level
, char *rhost
)
836 struct sockaddr_in dst
;
838 char myname
[MAXHOSTNAMELEN
+ 1];
840 if (msg
== NULL
) return 0;
842 h
= gethostbyname(rhost
);
843 if (h
== NULL
) return -1;
845 s
= socket(AF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
846 if (s
<= 0) return -1;
848 memset(&dst
, 0, sizeof(struct sockaddr_in
));
849 memcpy(&(dst
.sin_addr
.s_addr
), h
->h_addr_list
[0], 4);
850 dst
.sin_family
= AF_INET
;
852 dst
.sin_len
= sizeof(struct sockaddr_in
);
855 ltime
= ctime(&tick
);
858 gethostname(myname
, MAXHOSTNAMELEN
);
860 asprintf(&out
, "<%d>%s %s syslog[%d]: %s", level
, ltime
+4, myname
, getpid(), msg
);
862 sendto(s
, out
, len
, 0, (const struct sockaddr
*)&dst
, sizeof(struct sockaddr_in
));
874 if (s
== NULL
) return 0;
877 if ((s
[0] == '-') || (s
[0] == '+')) i
= 1;
879 if (s
[i
] == '\0') return 0;
881 for (; s
[i
] != '\0'; i
++)
883 if (!isdigit(s
[i
])) return 0;
890 asl_string_to_level(const char *s
)
892 if (s
== NULL
) return -1;
894 if ((s
[0] >= '0') && (s
[0] <= '7') && (s
[1] == '\0')) return atoi(s
);
896 if (!strncasecmp(s
, "em", 2)) return ASL_LEVEL_EMERG
;
897 else if (!strncasecmp(s
, "p", 1)) return ASL_LEVEL_EMERG
;
898 else if (!strncasecmp(s
, "a", 1)) return ASL_LEVEL_ALERT
;
899 else if (!strncasecmp(s
, "c", 1)) return ASL_LEVEL_CRIT
;
900 else if (!strncasecmp(s
, "er", 2)) return ASL_LEVEL_ERR
;
901 else if (!strncasecmp(s
, "x", 1)) return ASL_LEVEL_ERR
;
902 else if (!strncasecmp(s
, "w", 1)) return ASL_LEVEL_WARNING
;
903 else if (!strncasecmp(s
, "n", 1)) return ASL_LEVEL_NOTICE
;
904 else if (!strncasecmp(s
, "i", 1)) return ASL_LEVEL_INFO
;
905 else if (!strncasecmp(s
, "d", 1)) return ASL_LEVEL_DEBUG
;
911 asl_string_to_char_level(const char *s
)
913 if (s
== NULL
) return NULL
;
915 if ((s
[0] >= '0') && (s
[0] <= '7') && (s
[1] == '\0')) return s
;
917 if (!strncasecmp(s
, "em", 2)) return "0";
918 else if (!strncasecmp(s
, "p", 1)) return "0";
919 else if (!strncasecmp(s
, "a", 1)) return "1";
920 else if (!strncasecmp(s
, "c", 1)) return "2";
921 else if (!strncasecmp(s
, "er", 2)) return "3";
922 else if (!strncasecmp(s
, "x", 1)) return "3";
923 else if (!strncasecmp(s
, "w", 1)) return "4";
924 else if (!strncasecmp(s
, "n", 1)) return "5";
925 else if (!strncasecmp(s
, "i", 1)) return "6";
926 else if (!strncasecmp(s
, "d", 1)) return "7";
932 syslog_remote_control(int argc
, char *argv
[])
934 int pid
, uid
, status
, mask
;
936 if ((argc
< 3) || (argc
> 4))
938 fprintf(stderr
, "usage:\n");
939 fprintf(stderr
, "%s -c process [mask]\n", myname
);
940 fprintf(stderr
, " get (set if mask is specified) syslog filter mask for process (pid or name)\n");
941 fprintf(stderr
, " process may be pid or process name\n");
942 fprintf(stderr
, " use \"-c 0\" to get master syslog filter mask\n");
943 fprintf(stderr
, " use \"-c 0 off\" to disable master syslog filter mask\n");
944 fprintf(stderr
, "\n");
951 status
= PROC_NOT_FOUND
;
953 if ((!strcmp(argv
[2], "syslogd")) || (!strcmp(argv
[2], "syslog")))
955 fprintf(stderr
, "%s: does not have a filter mask\n", argv
[2]);
958 else if (_isanumber(argv
[2]) != 0)
961 status
= procinfo(NULL
, &pid
, &uid
);
965 status
= procinfo(argv
[2], &pid
, &uid
);
968 if (status
== PROC_NOT_FOUND
)
970 fprintf(stderr
, "%s: process not found\n", argv
[2]);
974 if (status
== PROC_NOT_UNIQUE
)
976 fprintf(stderr
, "%s: multiple processes found\n", argv
[2]);
977 fprintf(stderr
, "use pid to identify a process uniquely\n");
981 if (pid
== 0) pid
= RC_MASTER
;
985 if ((pid
== RC_MASTER
) && (!strcasecmp(argv
[3], "off"))) mask
= 0;
988 mask
= asl_string_to_filter(argv
[3]);
991 printf("unknown syslog mask: %s\n", argv
[3]);
996 rcontrol_set(pid
, uid
, mask
);
1000 rcontrol_get(pid
, uid
);
1007 syslog_send(int argc
, char *argv
[])
1009 int i
, start
, kv
, len
, rfmt
, rlevel
;
1012 char tmp
[64], *str
, *rhost
;
1016 rfmt
= SEND_FORMAT_LEGACY
;
1020 for (i
= 1; i
< argc
; i
++)
1022 if (!strcmp(argv
[i
], "-s")) start
= i
+1;
1023 else if (!strcmp(argv
[i
], "-k"))
1026 rfmt
= SEND_FORMAT_ASL
;
1028 else if (!strcmp(argv
[i
], "-r"))
1033 else if (!strcmp(argv
[i
], "-l"))
1035 rlevel
= asl_string_to_level(argv
[++i
]);
1038 fprintf(stderr
, "Unknown level: %s\n", argv
[i
]);
1045 asl
= asl_open(myname
, "syslog", 0);
1046 asl_set_filter(asl
, ASL_FILTER_MASK_UPTO(ASL_LEVEL_DEBUG
));
1048 m
= asl_new(ASL_TYPE_MSG
);
1049 asl_set(m
, ASL_KEY_SENDER
, myname
);
1051 sprintf(tmp
, "%d", rlevel
);
1052 asl_set(m
, ASL_KEY_LEVEL
, tmp
);
1059 for (i
= start
; i
< argc
; i
++) len
+= (strlen(argv
[i
]) + 1);
1060 str
= calloc(len
+ 1, 1);
1061 if (str
== NULL
) return -1;
1063 for (i
= start
; i
< argc
; i
++)
1065 strcat(str
, argv
[i
]);
1066 if ((i
+1) < argc
) strcat(str
, " ");
1068 asl_set(m
, ASL_KEY_MSG
, str
);
1072 for (i
= start
+ 1; i
< argc
; i
+= 2)
1074 if (!strcmp(argv
[i
], "-k")) i
++;
1075 asl_set(m
, argv
[i
], argv
[i
+ 1]);
1076 if (!strcmp(argv
[i
], ASL_KEY_LEVEL
)) rlevel
= atoi(argv
[i
+ 1]);
1084 else if (rfmt
== SEND_FORMAT_ASL
)
1088 else if ((rfmt
== SEND_FORMAT_LEGACY
) && (str
!= NULL
))
1090 rlegacy(str
, rlevel
, rhost
);
1095 if (str
!= NULL
) free(str
);
1103 syslog_config(int argc
, char *argv
[])
1111 const char *key
, *val
;
1115 asl_msg_t
*ctl
= (asl_msg_t
*)_asl_server_control_query();
1119 fprintf(stderr
, "can't get status information from syslogd\n");
1123 for (x
= asl_msg_fetch(ctl
, 0, &key
, &val
, NULL
); x
!= IndexNull
; x
= asl_msg_fetch(ctl
, x
, &key
, &val
, NULL
))
1125 printf("%s %s\n", key
, val
);
1128 asl_msg_release(ctl
);
1135 fprintf(stderr
, "syslogd parameters may only be set by the superuser\n");
1139 str
= asl_string_new(0);
1140 asl_string_append(str
, "= ");
1142 for (i
= 2; i
< argc
; i
++)
1144 asl_string_append(str
, argv
[i
]);
1145 if ((i
+ 1) < argc
) asl_string_append(str
, " ");
1148 asl
= asl_open(myname
, "syslog", 0);
1150 m
= asl_new(ASL_TYPE_MSG
);
1151 asl_set(m
, ASL_KEY_LEVEL
, ASL_STRING_NOTICE
);
1152 asl_set(m
, ASL_KEY_OPTION
, ASL_OPT_CONTROL
);
1153 asl_set(m
, ASL_KEY_SENDER
, myname
);
1154 asl_set(m
, ASL_KEY_MSG
, asl_string_bytes(str
));
1158 asl_string_free(str
);
1166 syslog_control(int argc
, char *argv
[])
1177 fprintf(stderr
, "syslog control limited to use by superuser\n");
1181 str
= asl_string_new(0);
1182 asl_string_append(str
, "@ ");
1184 for (i
= 2; i
< argc
; i
++)
1186 asl_string_append(str
, argv
[i
]);
1187 if ((i
+ 1) < argc
) asl_string_append(str
, " ");
1190 asl
= asl_open(myname
, "syslog", 0);
1192 m
= asl_new(ASL_TYPE_MSG
);
1193 asl_set(m
, ASL_KEY_LEVEL
, ASL_STRING_NOTICE
);
1194 asl_set(m
, ASL_KEY_OPTION
, ASL_OPT_CONTROL
);
1195 asl_set(m
, ASL_KEY_SENDER
, myname
);
1196 asl_set(m
, ASL_KEY_MSG
, asl_string_bytes(str
));
1200 asl_string_free(str
);
1208 print_xml_header(FILE *f
)
1210 if (f
== NULL
) return;
1212 fprintf(f
, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
1213 fprintf(f
, "<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n");
1214 fprintf(f
, "<plist version=\"1.0\">\n");
1215 fprintf(f
, "<array>\n");
1219 print_xml_trailer(FILE *f
)
1221 if (f
== NULL
) return;
1223 fprintf(f
, "</array>\n");
1224 fprintf(f
, "</plist>\n");
1228 printmsg(FILE *f
, aslmsg msg
, char *fmt
, int pflags
)
1232 uint32_t encode
, len
, status
;
1240 status
= asl_file_save(export
, msg
, &xid
);
1241 if (status
!= ASL_STATUS_OK
)
1243 fprintf(stderr
, "export file write failed: %s\n", asl_core_error(status
));
1244 asl_file_close(export
);
1252 encode
= pflags
& 0x0000000f;
1254 mf
= ASL_MSG_FMT_RAW
;
1255 if (fmt
!= NULL
) mf
= (const char *)fmt
;
1256 else if (pflags
& FORMAT_STD
) mf
= ASL_MSG_FMT_STD
;
1257 else if (pflags
& FORMAT_LEGACY
) mf
= ASL_MSG_FMT_BSD
;
1258 else if (pflags
& FORMAT_XML
) mf
= ASL_MSG_FMT_XML
;
1261 str
= asl_format_message((asl_msg_t
*)msg
, mf
, tfmt
, encode
, &len
);
1262 if (str
== NULL
) return;
1264 if (pflags
& COMPRESS_DUPS
)
1266 if (last_printmsg_str
!= NULL
)
1268 if (!strcmp(str
+ STD_BSD_DATE_LEN
, last_printmsg_str
+ STD_BSD_DATE_LEN
))
1270 last_printmsg_count
++;
1275 if (last_printmsg_count
> 0)
1277 fprintf(f
, "--- last message repeated %d time%s ---\n", last_printmsg_count
, (last_printmsg_count
== 1) ? "" : "s");
1280 free(last_printmsg_str
);
1281 last_printmsg_str
= str
;
1282 last_printmsg_count
= 0;
1284 fprintf(f
, "%s", str
);
1289 last_printmsg_str
= str
;
1290 last_printmsg_count
= 0;
1292 fprintf(f
, "%s", str
);
1297 fprintf(f
, "%s", str
);
1302 asl_search_result_t
*
1303 store_query(asl_search_result_t
*q
, uint64_t start
, int count
, int dir
, uint64_t *last
)
1306 asl_search_result_t
*res
;
1310 status
= asl_store_open_read(NULL
, &store
);
1311 if (status
!= 0) return NULL
;
1315 status
= asl_store_match(store
, q
, &res
, last
, start
, count
, dir
);
1316 if (status
!= 0) return NULL
;
1321 asl_search_result_t
*
1322 file_query(asl_search_result_t
*q
, uint64_t start
, int count
, int dir
, uint64_t *last
)
1325 asl_search_result_t
*res
;
1328 status
= asl_file_list_match(db_files
, q
, &res
, last
, start
, count
, dir
);
1329 if (status
!= 0) return NULL
;
1334 asl_search_result_t
*
1335 legacy_query(asl_search_result_t
*q
, uint64_t start
, int count
, int dir
, uint64_t *last
)
1338 asl_search_result_t
*res
;
1341 status
= asl_file_match(legacy
, q
, &res
, last
, start
, count
, dir
);
1342 if (status
!= 0) return NULL
;
1347 asl_search_result_t
*
1348 syslogd_query(asl_search_result_t
*q
, uint64_t start
, int count
, int dir
, uint64_t *last
)
1352 uint32_t len
, reslen
, status
;
1354 kern_return_t kstatus
;
1355 asl_search_result_t
*l
;
1357 if (asl_server_port
== MACH_PORT_NULL
)
1359 kstatus
= bootstrap_look_up2(bootstrap_port
, ASL_SERVICE_NAME
, &asl_server_port
, 0, BOOTSTRAP_PRIVILEGED_SERVER
);
1360 if (kstatus
!= KERN_SUCCESS
)
1362 fprintf(stderr
, "query failed: can't contact syslogd\n");
1368 str
= asl_list_to_string(q
, &len
);
1370 kstatus
= vm_allocate(mach_task_self(), (vm_address_t
*)&vmstr
, len
, TRUE
);
1371 if (kstatus
!= KERN_SUCCESS
)
1377 memmove(vmstr
, str
, len
);
1384 if (dir
< 0) flags
= QUERY_FLAG_SEARCH_REVERSE
;
1386 kstatus
= _asl_server_query_2(asl_server_port
, (caddr_t
)vmstr
, len
, start
, count
, flags
, (caddr_t
*)&res
, &reslen
, last
, (int *)&status
);
1388 if (res
== NULL
) return NULL
;
1389 l
= asl_list_from_string(res
);
1390 vm_deallocate(mach_task_self(), (vm_address_t
)res
, reslen
);
1395 filter_and_print(aslmsg msg
, asl_search_result_t
*ql
, FILE *f
, char *pfmt
, int pflags
)
1397 int i
, do_match
, did_match
;
1399 if (msg
== NULL
) return;
1402 if (ql
== NULL
) do_match
= 0;
1403 else if (ql
->count
== 0) do_match
= 0;
1411 for (i
= 0; (i
< ql
->count
) && (did_match
== 0); i
++)
1413 did_match
= asl_msg_cmp(ql
->msg
[i
], (asl_msg_t
*)msg
);
1417 if (did_match
!= 0) printmsg(f
, msg
, pfmt
, pflags
);
1420 #if TARGET_OS_EMBEDDED
1422 syslogd_direct_watch(FILE *f
, char *pfmt
, int pflags
, asl_search_result_t
*ql
)
1424 struct sockaddr_in address
;
1425 int i
, bytes
, sock
, stream
, status
;
1428 socklen_t addresslength
;
1429 char *str
, buf
[DIRECT_BUF_SIZE
];
1432 if (asl_server_port
== MACH_PORT_NULL
)
1434 status
= bootstrap_look_up(bootstrap_port
, ASL_SERVICE_NAME
, &asl_server_port
);
1435 if (status
!= KERN_SUCCESS
)
1437 fprintf(stderr
, "query failed: can't contact syslogd\n");
1442 addresslength
= sizeof(address
);
1443 sock
= socket(AF_INET
, SOCK_STREAM
, 0);
1444 port
= (arc4random() % (IPPORT_HILASTAUTO
- IPPORT_HIFIRSTAUTO
)) + IPPORT_HIFIRSTAUTO
;
1446 memset(&address
, 0, addresslength
);
1447 address
.sin_addr
.s_addr
= htonl(INADDR_LOOPBACK
);
1448 address
.sin_family
= AF_INET
;
1449 address
.sin_port
= htons(port
);
1451 status
= bind(sock
, (struct sockaddr
*)&address
, sizeof(address
));
1453 for (i
= 0; (i
< MAX_RANDOM
) && (status
< 0); i
++)
1455 port
= (arc4random() % (IPPORT_HILASTAUTO
- IPPORT_HIFIRSTAUTO
)) + IPPORT_HIFIRSTAUTO
;
1456 address
.sin_port
= htons(port
);
1458 status
= bind(sock
, (struct sockaddr
*)&address
, sizeof(address
));
1463 fprintf(stderr
, "query failed: can't find a port to connect to syslogd\n");
1469 if (listen(sock
, 1) == -1)
1476 _asl_server_register_direct_watch(asl_server_port
, i
);
1478 stream
= accept(sock
, (struct sockaddr
*)&address
, &addresslength
);
1489 bytes
= recvfrom(stream
, &n
, sizeof(n
), 0, NULL
, NULL
);
1492 fprintf(stderr
, "\nrecvfrom (message length) returned %d (errno %d) - exiting\n", bytes
, errno
);
1495 else inlen
= ntohl(n
);
1497 if (inlen
== 0) continue;
1500 if (inlen
<= DIRECT_BUF_SIZE
)
1506 str
= calloc(1, inlen
+ 1);
1509 fprintf(stderr
, "\ncan't allocate memory - exiting\n");
1520 bytes
= recvfrom(stream
, str
+ n
, inlen
- n
, 0, NULL
, NULL
);
1523 fprintf(stderr
, "\nrecvfrom (message body) returned %d (errno %d) at length %d of %d - exiting\n", bytes
, errno
, n
, inlen
);
1531 fprintf(stderr
, "\ntruncated message: expected %d bytes received %d bytes\n", inlen
, n
);
1537 msg
= (aslmsg
)asl_msg_from_string(str
);
1538 if (str
!= buf
) free(str
);
1539 filter_and_print(msg
, ql
, f
, pfmt
, pflags
);
1546 address
.sin_addr
.s_addr
= 0;
1551 sort_compare_key(const void *a
, const void *b
, const char *key
)
1554 const char *va
, *vb
;
1557 if (key
== NULL
) return 0;
1562 va
= asl_get(*ma
, key
);
1563 vb
= asl_get(*mb
, key
);
1565 if (va
== NULL
) return -1;
1566 if (vb
== NULL
) return 1;
1568 if (sort_numeric
== 1)
1572 if (na
< nb
) return -1;
1573 if (na
> nb
) return 1;
1577 return strcmp(va
, vb
);
1581 sort_compare(const void *a
, const void *b
)
1585 if (sort_key
== NULL
) return 0;
1587 cmp
= sort_compare_key(a
, b
, sort_key
);
1588 if ((cmp
== 0) && (sort_key_2
!= NULL
)) cmp
= sort_compare_key(a
, b
, sort_key_2
);
1594 search_once(FILE *f
, char *pfmt
, int pflags
, asl_search_result_t
*ql
, uint64_t qmin
, uint64_t *cmax
, uint32_t count
, uint32_t batch
, int dir
, uint32_t tail
)
1596 asl_search_result_t
*res
;
1599 if (pflags
& FORMAT_XML
) print_xml_header(f
);
1607 if (batch
== 0) more
= 0;
1609 if ((dbselect
== DB_SELECT_ASL
) || (dbselect
== DB_SELECT_STORE
)) res
= store_query(ql
, qmin
, batch
, dir
, cmax
);
1610 else if (dbselect
== DB_SELECT_FILES
) res
= file_query(ql
, qmin
, batch
, dir
, cmax
);
1611 else if (dbselect
== DB_SELECT_SYSLOGD
) res
= syslogd_query(ql
, qmin
, batch
, dir
, cmax
);
1612 else if (dbselect
== DB_SELECT_LEGACY
) res
= legacy_query(ql
, qmin
, batch
, dir
, cmax
);
1614 if ((dir
>= 0) && (*cmax
> qmin
)) qmin
= *cmax
+ 1;
1615 else if ((dir
< 0) && (*cmax
< qmin
)) qmin
= *cmax
- 1;
1623 if ((batch
> 0) && (res
->count
< batch
)) more
= 0;
1624 total
+= res
->count
;
1625 if ((count
> 0) && (total
>= count
)) more
= 0;
1630 i
= res
->count
- tail
;
1635 if (sort_key
!= NULL
)
1637 qsort(res
->msg
, res
->count
, sizeof(asl_msg_t
*), sort_compare
);
1640 if ((f
!= NULL
) || (export
!= NULL
))
1642 for (; i
< res
->count
; i
++) printmsg(f
, (aslmsg
)(res
->msg
[i
]), pfmt
, pflags
);
1645 aslresponse_free((aslresponse
)res
);
1649 if ((pflags
& COMPRESS_DUPS
) && (last_printmsg_count
> 0))
1651 fprintf(f
, "--- last message repeated %d time%s ---\n", last_printmsg_count
, (last_printmsg_count
== 1) ? "" : "s");
1652 free(last_printmsg_str
);
1653 last_printmsg_str
= NULL
;
1654 last_printmsg_count
= 0;
1657 if (pflags
& FORMAT_XML
) print_xml_trailer(f
);
1665 op
= ASL_QUERY_OP_NULL
;
1667 if (o
== NULL
) return op
;
1669 for (i
= 0; o
[i
] != '\0'; i
++)
1671 if (o
[i
] == MOD_CASE_FOLD
) op
|= ASL_QUERY_OP_CASEFOLD
;
1672 else if (o
[i
] == MOD_REGEX
) op
|= ASL_QUERY_OP_REGEX
;
1673 else if (o
[i
] == MOD_NUMERIC
) op
|= ASL_QUERY_OP_NUMERIC
;
1674 else if (o
[i
] == MOD_SUBSTRING
) op
|= ASL_QUERY_OP_SUBSTRING
;
1675 else if (o
[i
] == MOD_PREFIX
) op
|= ASL_QUERY_OP_PREFIX
;
1676 else if (o
[i
] == MOD_SUFFIX
) op
|= ASL_QUERY_OP_SUFFIX
;
1678 else if (!strncasecmp(o
+i
, OP_EQ
, sizeof(OP_EQ
)))
1680 op
|= ASL_QUERY_OP_EQUAL
;
1681 i
+= (sizeof(OP_EQ
) - 2);
1683 else if (!strncasecmp(o
+i
, OP_NE
, sizeof(OP_NE
)))
1685 op
|= ASL_QUERY_OP_NOT_EQUAL
;
1686 i
+= (sizeof(OP_NE
) - 2);
1688 else if (!strncasecmp(o
+i
, OP_GT
, sizeof(OP_GT
)))
1690 op
|= ASL_QUERY_OP_GREATER
;
1691 i
+= (sizeof(OP_GT
) - 2);
1693 else if (!strncasecmp(o
+i
, OP_GE
, sizeof(OP_GE
)))
1695 op
|= ASL_QUERY_OP_GREATER_EQUAL
;
1696 i
+= (sizeof(OP_GE
) - 2);
1698 else if (!strncasecmp(o
+i
, OP_LT
, sizeof(OP_LT
)))
1700 op
|= ASL_QUERY_OP_LESS
;
1701 i
+= (sizeof(OP_LT
) - 2);
1703 else if (!strncasecmp(o
+i
, OP_LE
, sizeof(OP_LE
)))
1705 op
|= ASL_QUERY_OP_LESS_EQUAL
;
1706 i
+= (sizeof(OP_LE
) - 2);
1710 fprintf(stderr
, "invalid option: %s\n", o
);
1716 if (op
& ASL_QUERY_OP_NUMERIC
)
1718 if (op
& ASL_QUERY_OP_CASEFOLD
)
1720 fprintf(stderr
, "warning: case fold modifier has no effect with numeric comparisons\n");
1721 op
&= ~ASL_QUERY_OP_CASEFOLD
;
1724 if (op
& ASL_QUERY_OP_REGEX
)
1726 fprintf(stderr
, "warning: regex modifier has no effect with numeric comparisons\n");
1727 op
&= ~ASL_QUERY_OP_REGEX
;
1730 if (op
& ASL_QUERY_OP_SUBSTRING
)
1732 fprintf(stderr
, "warning: substring modifier has no effect with numeric comparisons\n");
1733 op
&= ~ASL_QUERY_OP_SUBSTRING
;
1736 if (op
& ASL_QUERY_OP_PREFIX
)
1738 fprintf(stderr
, "warning: prefix modifier has no effect with numeric comparisons\n");
1739 op
&= ~ASL_QUERY_OP_PREFIX
;
1742 if (op
& ASL_QUERY_OP_SUFFIX
)
1744 fprintf(stderr
, "warning: suffix modifier has no effect with numeric comparisons\n");
1745 op
&= ~ASL_QUERY_OP_SUFFIX
;
1749 if (op
& ASL_QUERY_OP_REGEX
)
1751 if (op
& ASL_QUERY_OP_SUBSTRING
)
1753 fprintf(stderr
, "warning: substring modifier has no effect with regular expression comparisons\n");
1754 op
&= ~ASL_QUERY_OP_SUBSTRING
;
1757 if (op
& ASL_QUERY_OP_PREFIX
)
1759 fprintf(stderr
, "warning: prefix modifier has no effect with regular expression comparisons\n");
1760 op
&= ~ASL_QUERY_OP_PREFIX
;
1763 if (op
& ASL_QUERY_OP_SUFFIX
)
1765 fprintf(stderr
, "warning: suffix modifier has no effect with regular expression comparisons\n");
1766 op
&= ~ASL_QUERY_OP_SUFFIX
;
1774 add_op(asl_msg_t
*q
, char *key
, char *op
, char *val
, uint32_t flags
)
1779 if (key
== NULL
) return -1;
1780 if (q
== NULL
) return -1;
1783 if (strcmp(key
, ASL_KEY_TIME
) == 0)
1785 qval
= (const char *)val
;
1787 else if ((strcmp(key
, ASL_KEY_LEVEL
) == 0) && (_isanumber(val
) == 0))
1789 /* Convert level strings to numeric values */
1790 qval
= asl_string_to_char_level(val
);
1793 fprintf(stderr
, "invalid value for \"Level\"key: %s\n", val
);
1798 o
= ASL_QUERY_OP_NULL
;
1799 if (val
== NULL
) o
= ASL_QUERY_OP_TRUE
;
1804 if (o
== ASL_QUERY_OP_NULL
) return -1;
1807 fprintf(stderr
, "no value supplied for operator %s %s\n", key
, op
);
1811 if ((qval
== NULL
) && (o
& ASL_QUERY_OP_NUMERIC
) && (_isanumber(val
) == 0))
1813 fprintf(stderr
, "non-numeric value supplied for numeric operator %s %s %s\n", key
, op
, val
);
1819 if (qval
!= NULL
) asl_msg_set_key_val_op(q
, key
, qval
, o
);
1820 else asl_msg_set_key_val_op(q
, key
, val
, o
);
1826 add_db_file(const char *name
)
1831 if (dbselect
== DB_SELECT_LEGACY
)
1833 fprintf(stderr
, "syslog can only read one legacy format database\n");
1834 fprintf(stderr
, "can't combine legacy and non-legacy databases in a single search\n");
1838 /* shouldn't happen */
1839 if (name
== NULL
) return DB_SELECT_ASL
;
1842 status
= asl_file_open_read(name
, &s
);
1843 if (status
!= ASL_STATUS_OK
)
1845 fprintf(stderr
, "data store file %s open failed: %s \n", name
, asl_core_error(status
));
1851 fprintf(stderr
, "data store file %s open failed\n", name
);
1855 if (s
->flags
& ASL_FILE_FLAG_LEGACY_STORE
)
1857 if (db_files
!= NULL
)
1859 fprintf(stderr
, "syslog can only read a single legacy format database\n");
1860 fprintf(stderr
, "can't combine legacy and non-legacy databases in a single search\n");
1865 return DB_SELECT_LEGACY
;
1868 db_files
= asl_file_list_add(db_files
, s
);
1869 return DB_SELECT_FILES
;
1873 add_db_dir(const char *name
)
1876 struct dirent
*dent
;
1882 * Try opening as a data store
1884 status
= asl_store_open_read(name
, &store
);
1887 if (name
== NULL
) return DB_SELECT_ASL
;
1888 if (!strcmp(name
, PATH_ASL_STORE
)) return DB_SELECT_ASL
;
1889 return DB_SELECT_STORE
;
1893 * Open all readable files
1898 fprintf(stderr
, "%s: %s\n", name
, strerror(errno
));
1902 while ((dent
= readdir(dp
)) != NULL
)
1904 if (dent
->d_name
[0] == '.') continue;
1907 asprintf(&path
, "%s/%s", name
, dent
->d_name
);
1910 * asl_file_open_read will fail if path is NULL,
1911 * if the file is not an ASL store file,
1912 * or if it isn't readable.
1915 status
= asl_file_open_read(path
, &s
);
1916 if (path
!= NULL
) free(path
);
1917 if ((status
!= ASL_STATUS_OK
) || (s
== NULL
)) continue;
1919 db_files
= asl_file_list_add(db_files
, s
);
1924 return DB_SELECT_FILES
;
1928 main(int argc
, char *argv
[])
1931 int i
, j
, n
, watch
, status
, pflags
, iamroot
, user_tflag
, export_preserve_id
, saw_dash_d
, since_boot
;
1932 int notify_file
, notify_token
;
1933 asl_search_result_t
*qlist
;
1936 const char *exportname
;
1937 uint32_t flags
, tail_count
, batch
, encode
;
1938 uint64_t qmin
, cmax
;
1946 batch
= FETCH_BATCH
;
1947 pflags
= FORMAT_STD
| COMPRESS_DUPS
;
1948 encode
= ASL_ENCODE_SAFE
;
1951 export_preserve_id
= 0;
1955 i
= asl_store_location();
1956 if (i
== ASL_STORE_LOCATION_MEMORY
) dbselect
= DB_SELECT_SYSLOGD
;
1958 if (getuid() == 0) iamroot
= 1;
1960 for (i
= 1; i
< argc
; i
++)
1962 if ((!strcmp(argv
[i
], "-help")) || (!strcmp(argv
[i
], "--help")))
1968 if ((!strcmp(argv
[i
], "-time")) || (!strcmp(argv
[i
], "--time")))
1971 printf("%llu\n", qmin
);
1975 if ((!strcmp(argv
[i
], "-config")) || (!strcmp(argv
[i
], "--config")))
1977 syslog_config(argc
, argv
);
1981 if ((!strcmp(argv
[i
], "-control")) || (!strcmp(argv
[i
], "--control")))
1983 syslog_control(argc
, argv
);
1987 if ((!strcmp(argv
[i
], "-module")) || (!strcmp(argv
[i
], "--module")))
1989 module_control(argc
, argv
);
1993 if (!strcmp(argv
[i
], "-s"))
1995 syslog_send(argc
, argv
);
1999 if (!strcmp(argv
[i
], "-c"))
2001 syslog_remote_control(argc
, argv
);
2006 qlist
= (asl_search_result_t
*)calloc(1, sizeof(asl_search_result_t
));
2007 if (qlist
== NULL
) exit(1);
2009 for (i
= 1; i
< argc
; i
++)
2011 if (!strcmp(argv
[i
], "-f"))
2015 for (j
= i
+ 1; j
< argc
; j
++)
2017 if (!strcmp(argv
[j
], "-"))
2019 dbselect
= DB_SELECT_SYSLOGD
;
2023 else if (argv
[j
][0] == '-')
2029 dbselect
= add_db_file(argv
[j
]);
2035 else if (!strcmp(argv
[i
], "-d"))
2039 if (saw_dash_d
< argc
)
2041 for (j
= saw_dash_d
; j
< argc
; j
++)
2043 if (!strcmp(argv
[j
], "store"))
2045 dbselect
= add_db_dir(PATH_ASL_STORE
);
2048 else if (!strcmp(argv
[j
], "archive"))
2050 dbselect
= add_db_dir(PATH_ASL_ARCHIVE
);
2053 else if (argv
[j
][0] == '-')
2059 dbselect
= add_db_dir(argv
[j
]);
2066 fprintf(stderr
, "missing directory name following -d flag\n");
2070 else if (!strcmp(argv
[i
], "-b"))
2072 batch
= atoi(argv
[++i
]);
2074 else if (!strcmp(argv
[i
], "-B"))
2078 else if (!strcmp(argv
[i
], "-w"))
2082 if (((i
+ 1) < argc
) && (argv
[i
+ 1][0] != '-'))
2085 if (!strcmp(argv
[i
], "all"))
2087 tail_count
= (uint32_t)-1;
2089 else if (!strcmp(argv
[i
], "boot"))
2095 tail_count
= atoi(argv
[i
]);
2099 else if (!strcmp(argv
[i
], "-sort"))
2101 if (((i
+ 1) < argc
) && (argv
[i
+ 1][0] != '-'))
2106 if (((i
+ 1) < argc
) && (argv
[i
+ 1][0] != '-'))
2109 sort_key_2
= argv
[i
];
2114 sort_key
= ASL_KEY_MSG_ID
;
2119 else if (!strcmp(argv
[i
], "-nsort"))
2121 if (((i
+ 1) < argc
) && (argv
[i
+ 1][0] != '-'))
2126 if (((i
+ 1) < argc
) && (argv
[i
+ 1][0] != '-'))
2129 sort_key_2
= argv
[i
];
2134 sort_key
= ASL_KEY_MSG_ID
;
2140 else if (!strcmp(argv
[i
], "-u"))
2145 else if ((!strcmp(argv
[i
], "-x")) || (!strcmp(argv
[i
], "-X")))
2147 if ((i
+ 1) >= argc
)
2149 aslresponse_free(qlist
);
2154 if (!strcmp(argv
[i
], "-x")) export_preserve_id
= 1;
2156 exportname
= argv
[++i
];
2158 else if (!strcmp(argv
[i
], "-E"))
2160 if ((i
+ 1) >= argc
)
2162 aslresponse_free(qlist
);
2169 if (!strcmp(argv
[i
], "vis")) encode
= ASL_ENCODE_ASL
;
2170 else if (!strcmp(argv
[i
], "safe")) encode
= ASL_ENCODE_SAFE
;
2171 else if (!strcmp(argv
[i
], "xml")) encode
= ASL_ENCODE_XML
;
2172 else if (!strcmp(argv
[i
], "none")) encode
= ASL_ENCODE_NONE
;
2173 else if ((argv
[i
][0] >= '0') && (argv
[i
][0] <= '9') && (argv
[i
][1] == '\0')) encode
= atoi(argv
[i
]);
2175 else if (!strcmp(argv
[i
], "-F"))
2177 if ((i
+ 1) >= argc
)
2179 aslresponse_free(qlist
);
2186 if (!strcmp(argv
[i
], "raw"))
2188 pflags
= FORMAT_RAW
;
2189 if (user_tflag
== 0) tfmt
= "sec";
2191 else if (!strcmp(argv
[i
], "std"))
2193 pflags
= FORMAT_STD
| COMPRESS_DUPS
;
2195 else if (!strcmp(argv
[i
], "bsd"))
2197 pflags
= FORMAT_LEGACY
| COMPRESS_DUPS
;
2199 else if (!strcmp(argv
[i
], "xml"))
2201 pflags
= FORMAT_XML
;
2202 encode
= ASL_ENCODE_XML
;
2210 else if (!strcmp(argv
[i
], "-T"))
2212 if ((i
+ 1) >= argc
)
2214 aslresponse_free(qlist
);
2223 else if (!strcmp(argv
[i
], "-nodc"))
2225 pflags
= pflags
& ~COMPRESS_DUPS
;
2227 else if (!strcmp(argv
[i
], "-o"))
2231 if (qlist
->count
== 0)
2233 qlist
->msg
= (asl_msg_t
**)calloc(1, sizeof(asl_msg_t
*));
2237 qlist
->msg
= (asl_msg_t
**)reallocf(qlist
->msg
, (qlist
->count
+ 1) * sizeof(asl_msg_t
*));
2240 if (qlist
->msg
== NULL
) exit(1);
2242 cq
= asl_msg_new(ASL_TYPE_QUERY
);
2243 qlist
->msg
[qlist
->count
] = cq
;
2246 else if (!strcmp(argv
[i
], "-n"))
2248 flags
= ASL_QUERY_OP_NOT
;
2250 else if (!strcmp(argv
[i
], "-C"))
2252 if (qlist
->count
== 0)
2254 qlist
->msg
= (asl_msg_t
**)calloc(1, sizeof(asl_msg_t
*));
2255 if (qlist
->msg
== NULL
) exit(1);
2257 cq
= asl_msg_new(ASL_TYPE_QUERY
);
2258 qlist
->msg
[qlist
->count
] = cq
;
2262 status
= add_op(cq
, ASL_KEY_FACILITY
, OP_EQ
, FACILITY_CONSOLE
, flags
);
2267 aslresponse_free(qlist
);
2271 else if (!strcmp(argv
[i
], "-k"))
2274 for (n
= i
; n
< argc
; n
++)
2276 if (!strcmp(argv
[n
], "-o")) break;
2277 if (!strcmp(argv
[n
], "-n")) break;
2278 if (!strcmp(argv
[n
], "-k")) break;
2281 fprintf(stderr
, "invalid sequence: -k");
2282 for (j
= i
; j
<= n
; j
++) fprintf(stderr
, " %s", argv
[j
]);
2283 fprintf(stderr
, "\n");
2296 if (qlist
->count
== 0)
2298 qlist
->msg
= (asl_msg_t
**)calloc(1, sizeof(asl_msg_t
*));
2299 if (qlist
->msg
== NULL
) exit(1);
2301 cq
= asl_msg_new(ASL_TYPE_QUERY
);
2302 qlist
->msg
[qlist
->count
] = cq
;
2307 if (n
== 1) status
= add_op(cq
, argv
[i
], NULL
, NULL
, flags
);
2308 else if (n
== 2) status
= add_op(cq
, argv
[i
], OP_EQ
, argv
[i
+1], flags
);
2309 else status
= add_op(cq
, argv
[i
], argv
[i
+1], argv
[i
+2], flags
);
2314 aslresponse_free(qlist
);
2322 fprintf(stderr
, "syslog: unknown option \"%s\"\n", argv
[i
]);
2323 fprintf(stderr
, "run \"syslog -help\" for usage\n");
2333 * Catch and report some cases where watch (-w) doesn't work
2337 if (sort_key
!= NULL
)
2339 fprintf(stderr
, "Warning: -w flag has no effect with -sort flag\n");
2343 if (dbselect
== DB_SELECT_FILES
)
2345 if (saw_dash_d
== 0)
2347 fprintf(stderr
, "Warning: -w flag not supported for a set of one or more files\n");
2351 fprintf(stderr
, "Warning: directory \"%s\" is not an ASL data store\n", argv
[saw_dash_d
]);
2352 fprintf(stderr
, " -w flag not supported for a set of one or more files\n");
2359 if (exportname
!= NULL
)
2363 fprintf(stderr
, "Warning: -w flag has no effect with -x export flag\n");
2367 status
= asl_file_open_write(exportname
, 0644, -1, -1, &export
);
2368 if (status
!= ASL_STATUS_OK
)
2370 aslresponse_free(qlist
);
2371 fprintf(stderr
, "export file open failed: %s\n", asl_core_error(status
));
2376 * allow the string cache to be unlimited to maximize string dup compression
2377 * preserve message IDs
2379 export
->flags
= ASL_FILE_FLAG_UNLIMITED_CACHE
;
2380 if (export_preserve_id
!= 0) export
->flags
|= ASL_FILE_FLAG_PRESERVE_MSG_ID
;
2391 /* set starting point */
2392 if (since_boot
== 1)
2394 /* search back for last "BOOT_TIME (ut_type == 2) record */
2395 asl_search_result_t
*bt
;
2398 bt
= (asl_search_result_t
*)calloc(1, sizeof(asl_search_result_t
));
2401 fprintf(stderr
, "\ncan't allocate memory - exiting\n");
2405 bt
->msg
= (asl_msg_t
**)calloc(1, sizeof(asl_msg_t
*));
2406 if (bt
->msg
== NULL
)
2408 fprintf(stderr
, "\ncan't allocate memory - exiting\n");
2412 bq
= asl_new(ASL_TYPE_QUERY
);
2415 fprintf(stderr
, "\ncan't allocate memory - exiting\n");
2419 asl_set_query(bq
, "ut_type", "2", ASL_QUERY_OP_EQUAL
);
2421 bt
->msg
[0] = (asl_msg_t
*)bq
;
2424 search_once(NULL
, NULL
, 0, bt
, -1, &qmin
, 1, 1, -1, 0);
2429 if (qmin
> 0) qmin
--;
2432 else if (watch
== 1)
2434 /* go back tail_count records from last record */
2436 search_once(NULL
, NULL
, 0, qlist
, qmin
, &cmax
, 1, 1, -1, 0);
2438 if (cmax
>= tail_count
) qmin
= cmax
- tail_count
;
2444 if ((watch
== 1) && (dbselect
== DB_SELECT_ASL
))
2446 status
= notify_register_file_descriptor("com.apple.system.logger.message", ¬ify_file
, 0, ¬ify_token
);
2447 if (status
!= NOTIFY_STATUS_OK
) notify_token
= -1;
2450 /* output should be line buffered */
2451 if (outfile
!= NULL
) setlinebuf(outfile
);
2453 search_once(outfile
, pfmt
, pflags
, qlist
, qmin
+ 1, &cmax
, 0, 0, 1, tail_count
);
2457 if (dbselect
== DB_SELECT_SYSLOGD
)
2459 #if TARGET_OS_EMBEDDED
2460 syslogd_direct_watch(outfile
, pfmt
, pflags
, qlist
);
2462 fprintf(stderr
, "Warning: -w flag cannot be used when querying syslogd directly\n");
2466 else if (notify_token
== -1)
2471 if (cmax
> qmin
) qmin
= cmax
;
2472 search_once(outfile
, pfmt
, pflags
, qlist
, qmin
+ 1, &cmax
, 0, batch
, 1, 0);
2477 while (read(notify_file
, &i
, 4) == 4)
2479 if (cmax
> qmin
) qmin
= cmax
;
2480 search_once(outfile
, pfmt
, pflags
, qlist
, qmin
+ 1, &cmax
, 0, batch
, 1, 0);
2485 if (db_files
!= NULL
) asl_file_list_close(db_files
);
2486 if (store
!= NULL
) asl_store_close(store
);
2487 if (export
!= NULL
) asl_file_close(export
);
2489 aslresponse_free(qlist
);