]> git.saurik.com Git - apple/syslog.git/blob - util.tproj/syslog.c
syslog-13.1.tar.gz
[apple/syslog.git] / util.tproj / syslog.c
1 /*
2 * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include <ctype.h>
28 #include <time.h>
29 #include <string.h>
30 #include <errno.h>
31 #include <sys/socket.h>
32 #include <sys/sysctl.h>
33 #include <netinet/in.h>
34 #include <arpa/inet.h>
35 #include <netdb.h>
36 #include <notify.h>
37 #include <asl.h>
38 #include <asl_private.h>
39
40 #define MOD_CASE_FOLD 'C'
41 #define MOD_REGEX 'R'
42 #define MOD_SUBSTRING 'S'
43 #define MOD_PREFIX 'A'
44 #define MOD_SUFFIX 'Z'
45 #define MOD_NUMERIC 'N'
46
47 #define OP_EQ "eq"
48 #define OP_NE "ne"
49 #define OP_GT "gt"
50 #define OP_GE "ge"
51 #define OP_LT "lt"
52 #define OP_LE "le"
53
54 #define ASL_QUERY_OP_NOT 0x1000
55
56 #define SEARCH_EOF -1
57 #define SEARCH_NULL 0
58 #define SEARCH_MATCH 1
59
60 #define PROC_NOT_FOUND -1
61 #define PROC_NOT_UNIQUE -2
62
63 #define RC_MASTER -1
64 #define RC_SYSLOGD -2
65
66 #define CHUNK 64
67 #define forever for(;;)
68
69 #define SEND_FORMAT_LEGACY 0
70 #define SEND_FORMAT_ASL 1
71
72 #define PRINT_LOCALTIME 0x00000001
73 #define PRINT_LEGACY_FMT 0x00000002
74 #define PRINT_STD_FMT 0x00000004
75
76 #define ASL_FILTER_MASK_PACEWNID 0xff
77 #define ASL_FILTER_MASK_PACEWNI 0x7f
78 #define ASL_FILTER_MASK_PACEWN 0x3f
79 #define ASL_FILTER_MASK_PACEW 0x1f
80 #define ASL_FILTER_MASK_PACE 0x0f
81 #define ASL_FILTER_MASK_PAC 0x07
82
83
84 /* BEGIN PRIVATE API */
85 #define _PATH_ASL_PRUNE "/var/run/asl_prune"
86 #define _PATH_SYSLOGD_PID "/var/run/syslog.pid"
87
88 /* notify SPI */
89 uint32_t notify_get_state(int token, int *state);
90 uint32_t notify_set_state(int token, int state);
91 uint32_t notify_register_plain(const char *name, int *out_token);
92
93 extern char *asl_msg_to_string(aslmsg msg, uint32_t *len);
94 extern asl_msg_t *asl_msg_from_string(const char *buf);
95 extern int asl_msg_cmp(asl_msg_t *a, asl_msg_t *b);
96 extern time_t asl_parse_time(const char *in);
97 /* END PRIVATE API */
98
99 static const char *myname = "syslog";
100
101 void
102 usage()
103 {
104 fprintf(stderr, "usage:\n");
105 fprintf(stderr, "%s -s [-r host] [-l level] message...\n", myname);
106 fprintf(stderr, " send a message\n");
107 fprintf(stderr, "\n");
108 fprintf(stderr, "%s -s [-r host] -k key val [key val]...\n", myname);
109 fprintf(stderr, " send a message with the given keys and values\n");
110 fprintf(stderr, "\n");
111 fprintf(stderr, "%s -c process [filter]\n", myname);
112 fprintf(stderr, " get (set if filter is specified) syslog filter for process (pid or name)\n");
113 fprintf(stderr, " level may be any combination of the characters \"p a c e w n i d\"\n");
114 fprintf(stderr, " p = Emergency (\"Panic\")\n");
115 fprintf(stderr, " a = Alert\n");
116 fprintf(stderr, " c = Critical\n");
117 fprintf(stderr, " e = Error\n");
118 fprintf(stderr, " w = Warning\n");
119 fprintf(stderr, " n = Notice\n");
120 fprintf(stderr, " i = Info\n");
121 fprintf(stderr, " d = Debug\n");
122 fprintf(stderr, " a minus sign preceeding a single letter means \"up to\" that level\n");
123 fprintf(stderr, "\n");
124 fprintf(stderr, "%s -p [-k key [[op] val]]... [-o -k key [[op] val]] ...]...\n", myname);
125 fprintf(stderr, " -p prune datastore according to input expression (see below)\n");
126 fprintf(stderr, "\n");
127 fprintf(stderr, "%s [-w] [-F format] [-u] [-k key [[op] val]]... [-o -k key [[op] val]] ...]...\n", myname);
128 fprintf(stderr, " -w watch file (^C to quit)\n");
129 fprintf(stderr, " -F output format may be \"std\", \"raw\", or \"bsd\"\n");
130 fprintf(stderr, " format may also be a string containing variables of the form\n");
131 fprintf(stderr, " $Key or $(Key) - use the latter for non-whitespace delimited variables\n");
132 fprintf(stderr, " -u force printing of all timestamps using UTC\n");
133 fprintf(stderr, " -k key/value match\n");
134 fprintf(stderr, " if no operator or value is given, checks for the existance of the key\n");
135 fprintf(stderr, " if no operator is given, default is \"%s\"\n", OP_EQ);
136 fprintf(stderr, " -o begins a new query\n");
137 fprintf(stderr, " queries are \'OR\'ed together\n");
138 fprintf(stderr, "operators are zero or more modifiers followed by a comparison\n");
139 fprintf(stderr, " %s equal\n", OP_EQ);
140 fprintf(stderr, " %s not equal\n", OP_NE);
141 fprintf(stderr, " %s greater than\n", OP_GT);
142 fprintf(stderr, " %s greater or equal\n", OP_GE);
143 fprintf(stderr, " %s less than\n", OP_LT);
144 fprintf(stderr, " %s less or equal\n", OP_LE);
145 fprintf(stderr, "optional modifiers for operators\n");
146 fprintf(stderr, " %c case-fold\n", MOD_CASE_FOLD);
147 fprintf(stderr, " %c regular expression\n", MOD_REGEX);
148 fprintf(stderr, " %c substring\n", MOD_SUBSTRING);
149 fprintf(stderr, " %c prefix\n", MOD_PREFIX);
150 fprintf(stderr, " %c suffix\n", MOD_SUFFIX);
151 fprintf(stderr, " %c numeric comparison\n", MOD_NUMERIC);
152 }
153
154 const char *
155 notify_status_string(int status)
156 {
157 if (status == NOTIFY_STATUS_OK) return "OK";
158 if (status == NOTIFY_STATUS_INVALID_NAME) return "Process not registered";
159 if (status == NOTIFY_STATUS_NOT_AUTHORIZED) return "Not authorized";
160 return "Operation failed";
161 }
162
163 const char *
164 asl_level_string(int level)
165 {
166 if (level == ASL_LEVEL_EMERG) return ASL_STRING_EMERG;
167 if (level == ASL_LEVEL_ALERT) return ASL_STRING_ALERT;
168 if (level == ASL_LEVEL_CRIT) return ASL_STRING_CRIT;
169 if (level == ASL_LEVEL_ERR) return ASL_STRING_ERR;
170 if (level == ASL_LEVEL_WARNING) return ASL_STRING_WARNING;
171 if (level == ASL_LEVEL_NOTICE) return ASL_STRING_NOTICE;
172 if (level == ASL_LEVEL_INFO) return ASL_STRING_INFO;
173 if (level == ASL_LEVEL_DEBUG) return ASL_STRING_DEBUG;
174 return "Unknown";
175 }
176
177 int
178 procinfo(char *pname, int *pid, int *uid)
179 {
180 int mib[4];
181 int i, status, nprocs;
182 size_t miblen, size;
183 struct kinfo_proc *procs, *newprocs;
184
185 size = 0;
186 procs = NULL;
187
188 mib[0] = CTL_KERN;
189 mib[1] = KERN_PROC;
190 mib[2] = KERN_PROC_ALL;
191 mib[3] = 0;
192 miblen = 3;
193
194 status = sysctl(mib, miblen, NULL, &size, NULL, 0);
195 do
196 {
197 size += size / 10;
198 newprocs = realloc(procs, size);
199 if (newprocs == 0)
200 {
201 if (procs != NULL) free(procs);
202 return PROC_NOT_FOUND;
203 }
204
205 procs = newprocs;
206 status = sysctl(mib, miblen, procs, &size, NULL, 0);
207 } while ((status == -1) && (errno == ENOMEM));
208
209 if (status == -1)
210 {
211 if (procs != NULL) free(procs);
212 return PROC_NOT_FOUND;
213 }
214
215 if (size % sizeof(struct kinfo_proc) != 0)
216 {
217 if (procs != NULL) free(procs);
218 return PROC_NOT_FOUND;
219 }
220
221 if (procs == NULL) return PROC_NOT_FOUND;
222
223 nprocs = size / sizeof(struct kinfo_proc);
224
225 if (pname == NULL)
226 {
227 /* Search for a pid */
228 for (i = 0; i < nprocs; i++)
229 {
230 if (*pid == procs[i].kp_proc.p_pid)
231 {
232 *uid = procs[i].kp_eproc.e_ucred.cr_uid;
233 return 0;
234 }
235 }
236
237 return PROC_NOT_FOUND;
238 }
239
240 *pid = PROC_NOT_FOUND;
241
242 for (i = 0; i < nprocs; i++)
243 {
244 if (!strcmp(procs[i].kp_proc.p_comm, pname))
245 {
246 if (*pid != PROC_NOT_FOUND)
247 {
248 free(procs);
249 return PROC_NOT_UNIQUE;
250 }
251
252 *pid = procs[i].kp_proc.p_pid;
253 *uid = procs[i].kp_eproc.e_ucred.cr_uid;
254 }
255 }
256
257 free(procs);
258 if (*pid == PROC_NOT_FOUND) return PROC_NOT_FOUND;
259
260 return 0;
261 }
262
263 int
264 rcontrol_get_string(const char *prefix, int pid, int *val)
265 {
266 int t, x, status;
267 char *name;
268
269 status = NOTIFY_STATUS_OK;
270
271 if (pid == RC_SYSLOGD)
272 {
273 status = notify_register_plain(NOTIFY_SYSTEM_ASL_FILTER, &t);
274 }
275 else if (pid == RC_MASTER)
276 {
277 status = notify_register_plain(NOTIFY_SYSTEM_MASTER, &t);
278 }
279 else
280 {
281 name = NULL;
282 asprintf(&name, "%s.%d", prefix, pid);
283 if (name == NULL) return NOTIFY_STATUS_FAILED;
284
285 status = notify_register_plain(name, &t);
286 free(name);
287 }
288
289 if (status != NOTIFY_STATUS_OK) return status;
290
291 x = 0;
292 status = notify_get_state(t, &x);
293 notify_cancel(t);
294
295 *val = x;
296
297 return status;
298 }
299
300 int
301 rcontrol_set_string(const char *prefix, int pid, int filter)
302 {
303 int t, status;
304 char *name;
305
306 status = NOTIFY_STATUS_OK;
307
308 if (pid == RC_SYSLOGD)
309 {
310 status = notify_register_plain(NOTIFY_SYSTEM_ASL_FILTER, &t);
311 }
312 else if (pid == RC_MASTER)
313 {
314 status = notify_register_plain(NOTIFY_SYSTEM_MASTER, &t);
315 }
316 else
317 {
318 name = NULL;
319 asprintf(&name, "%s.%d", prefix, pid);
320 if (name == NULL) return NOTIFY_STATUS_FAILED;
321
322 status = notify_register_plain(name, &t);
323 free(name);
324 }
325
326 if (status != NOTIFY_STATUS_OK) return status;
327 status = notify_set_state(t, filter);
328 if ((pid == RC_SYSLOGD) && (status == NOTIFY_STATUS_OK)) status = notify_post(NOTIFY_SYSTEM_ASL_FILTER);
329 notify_cancel(t);
330 return status;
331 }
332
333 int
334 asl_string_to_filter(char *s)
335 {
336 int f, i;
337
338 if (s == NULL) return 0;
339 if (s[0] == '\0') return 0;
340
341 if ((s[0] >= '0') && (s[0] <= '9')) return ASL_FILTER_MASK(atoi(s));
342
343 if (s[0] == '-')
344 {
345 if ((s[1] == 'P') || (s[1] == 'p')) i = ASL_LEVEL_EMERG;
346 else if ((s[1] == 'A') || (s[1] == 'a')) i = ASL_LEVEL_ALERT;
347 else if ((s[1] == 'C') || (s[1] == 'c')) i = ASL_LEVEL_CRIT;
348 else if ((s[1] == 'E') || (s[1] == 'e')) i = ASL_LEVEL_ERR;
349 else if ((s[1] == 'X') || (s[1] == 'x')) i = ASL_LEVEL_ERR;
350 else if ((s[1] == 'W') || (s[1] == 'w')) i = ASL_LEVEL_WARNING;
351 else if ((s[1] == 'N') || (s[1] == 'n')) i = ASL_LEVEL_NOTICE;
352 else if ((s[1] == 'I') || (s[1] == 'i')) i = ASL_LEVEL_INFO;
353 else if ((s[1] == 'D') || (s[1] == 'd')) i = ASL_LEVEL_DEBUG;
354 else i = atoi(s + 1);
355 f = ASL_FILTER_MASK_UPTO(i);
356 return f;
357 }
358
359 f = 0;
360 for (i = 0; s[i] != '\0'; i++)
361 {
362 if ((s[i] == 'P') || (s[i] == 'p')) f |= ASL_FILTER_MASK_EMERG;
363 else if ((s[i] == 'A') || (s[i] == 'a')) f |= ASL_FILTER_MASK_ALERT;
364 else if ((s[i] == 'C') || (s[i] == 'c')) f |= ASL_FILTER_MASK_CRIT;
365 else if ((s[i] == 'E') || (s[i] == 'e')) f |= ASL_FILTER_MASK_ERR;
366 else if ((s[i] == 'X') || (s[i] == 'x')) f |= ASL_FILTER_MASK_ERR;
367 else if ((s[i] == 'W') || (s[i] == 'w')) f |= ASL_FILTER_MASK_WARNING;
368 else if ((s[i] == 'N') || (s[i] == 'n')) f |= ASL_FILTER_MASK_NOTICE;
369 else if ((s[i] == 'I') || (s[i] == 'i')) f |= ASL_FILTER_MASK_INFO;
370 else if ((s[i] == 'D') || (s[i] == 'd')) f |= ASL_FILTER_MASK_DEBUG;
371 }
372
373 return f;
374 }
375
376 char *
377 asl_filter_string(int f)
378 {
379 static char str[1024];
380 int i;
381
382 memset(str, 0, sizeof(str));
383 i = 0;
384
385 if ((f == ASL_FILTER_MASK_PACEWNID) != 0)
386 {
387 strcat(str, "Emergency - Debug");
388 return str;
389 }
390
391 if ((f == ASL_FILTER_MASK_PACEWNI) != 0)
392 {
393 strcat(str, "Emergency - Info");
394 return str;
395 }
396
397 if ((f == ASL_FILTER_MASK_PACEWN) != 0)
398 {
399 strcat(str, "Emergency - Notice");
400 return str;
401 }
402
403 if ((f == ASL_FILTER_MASK_PACEW) != 0)
404 {
405 strcat(str, "Emergency - Warning");
406 return str;
407 }
408
409 if ((f == ASL_FILTER_MASK_PACE) != 0)
410 {
411 strcat(str, "Emergency - Error");
412 return str;
413 }
414
415 if ((f == ASL_FILTER_MASK_PAC) != 0)
416 {
417 strcat(str, "Emergency - Critical");
418 return str;
419 }
420
421 if ((f & ASL_FILTER_MASK_EMERG) != 0)
422 {
423 strcat(str, "Emergency");
424 i++;
425 }
426
427 if ((f & ASL_FILTER_MASK_ALERT) != 0)
428 {
429 if (i > 0) strcat(str, ", ");
430 strcat(str, "Alert");
431 i++;
432 }
433
434 if ((f & ASL_FILTER_MASK_CRIT) != 0)
435 {
436 if (i > 0) strcat(str, ", ");
437 strcat(str, "Critical");
438 i++;
439 }
440
441 if ((f & ASL_FILTER_MASK_ERR) != 0)
442 {
443 if (i > 0) strcat(str, ", ");
444 strcat(str, "Error");
445 i++;
446 }
447
448 if ((f & ASL_FILTER_MASK_WARNING) != 0)
449 {
450 if (i > 0) strcat(str, ", ");
451 strcat(str, "Warning");
452 i++;
453 }
454
455 if ((f & ASL_FILTER_MASK_NOTICE) != 0)
456 {
457 if (i > 0) strcat(str, ", ");
458 strcat(str, "Notice");
459 i++;
460 }
461
462 if ((f & ASL_FILTER_MASK_INFO) != 0)
463 {
464 if (i > 0) strcat(str, ", ");
465 strcat(str, "Info");
466 i++;
467 }
468
469 if ((f & ASL_FILTER_MASK_DEBUG) != 0)
470 {
471 if (i > 0) strcat(str, ", ");
472 strcat(str, "Debug");
473 i++;
474 }
475
476 if (i == 0) sprintf(str, "Off");
477
478 return str;
479 }
480
481 int
482 rcontrol_get(const char *prefix, int pid)
483 {
484 int filter, status;
485 const char *name;
486
487 filter = 0;
488
489 if (pid < 0)
490 {
491 name = "Master";
492 if (pid == RC_SYSLOGD) name = "ASL Data Store";
493
494 status = rcontrol_get_string(NULL, pid, &filter);
495 if (status == NOTIFY_STATUS_OK)
496 {
497 printf("%s filter mask: %s\n", name, asl_filter_string(filter));
498 return 0;
499 }
500
501 printf("Unable to determine %s filter mask\n", name);
502 return -1;
503 }
504
505 status = rcontrol_get_string(prefix, pid, &filter);
506 if (status == NOTIFY_STATUS_OK)
507 {
508 printf("Process %d syslog filter mask: %s\n", pid, asl_filter_string(filter));
509 return 0;
510 }
511
512 printf("Unable to determine syslog filter mask for pid %d\n", pid);
513 return -1;
514 }
515
516 int
517 rcontrol_set(const char *prefix, int pid, int filter)
518 {
519 int status;
520 const char *name;
521
522 if (pid < 0)
523 {
524 name = "Master";
525 if (pid == RC_SYSLOGD) name = "ASL Data Store";
526 status = rcontrol_set_string(NULL, pid, filter);
527
528 if (status == NOTIFY_STATUS_OK)
529 {
530 printf("Set %s syslog filter mask: %s\n", name, asl_filter_string(filter));
531 return 0;
532 }
533
534 printf("Unable to set %s syslog filter mask: %s\n", name, notify_status_string(status));
535 return -1;
536 }
537
538 status = rcontrol_set_string(prefix, pid, filter);
539 if (status == NOTIFY_STATUS_OK)
540 {
541 printf("Set process %d syslog filter mask set: %s\n", pid, asl_filter_string(filter));
542 return 0;
543 }
544
545 printf("Unable to set syslog filter mask for pid %d: %s\n", pid, notify_status_string(status));
546 return -1;
547 }
548
549 int
550 rsend(aslmsg msg, char *rhost)
551 {
552 char *str, *out;
553 uint32_t len, level;
554 char *timestr;
555 const char *val;
556 time_t tick;
557 struct tm gtime;
558 int s;
559 struct sockaddr_in dst;
560 struct hostent *h;
561 char myname[MAXHOSTNAMELEN + 1];
562
563 if (msg == NULL) return 0;
564
565 h = gethostbyname(rhost);
566 if (h == NULL) return -1;
567
568 s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
569 if (s <= 0) return -1;
570
571 memset(&dst, 0, sizeof(struct sockaddr_in));
572 memcpy(&(dst.sin_addr.s_addr), h->h_addr_list[0], 4);
573 dst.sin_family = AF_INET;
574 dst.sin_port = 514;
575 dst.sin_len = sizeof(struct sockaddr_in);
576
577 level = ASL_LEVEL_DEBUG;
578
579 val = asl_get(msg, ASL_KEY_LEVEL);
580 if (val != NULL) level = atoi(val);
581
582 memset(&gtime, 0, sizeof(struct tm));
583 timestr = NULL;
584
585 tick = time(NULL);
586 gmtime_r(&tick, &gtime);
587
588 /* Canonical form: YYYY.MM.DD hh:mm:ss UTC */
589 asprintf(&timestr, "%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);
590
591 if (timestr != NULL)
592 {
593 asl_set(msg, ASL_KEY_TIME, timestr);
594 free(timestr);
595 }
596
597 if (gethostname(myname, MAXHOSTNAMELEN) == 0) asl_set(msg, ASL_KEY_HOST, myname);
598
599 len = 0;
600 str = asl_msg_to_string(msg, &len);
601 if (str == NULL) return -1;
602
603 asprintf(&out, "%10u %s\n", len+1, str);
604 free(str);
605 if (out == NULL) return -1;
606
607 sendto(s, out, len+12, 0, (const struct sockaddr *)&dst, sizeof(struct sockaddr_in));
608
609 free(out);
610 close(s);
611 return 0;
612 }
613
614 int
615 rlegacy(char *msg, int level, char *rhost)
616 {
617 char *out;
618 uint32_t len;
619 time_t tick;
620 char *ltime;
621 int s;
622 struct sockaddr_in dst;
623 struct hostent *h;
624 char myname[MAXHOSTNAMELEN + 1];
625
626 if (msg == NULL) return 0;
627
628 h = gethostbyname(rhost);
629 if (h == NULL) return -1;
630
631 s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
632 if (s <= 0) return -1;
633
634 memset(&dst, 0, sizeof(struct sockaddr_in));
635 memcpy(&(dst.sin_addr.s_addr), h->h_addr_list[0], 4);
636 dst.sin_family = AF_INET;
637 dst.sin_port = 514;
638 dst.sin_len = sizeof(struct sockaddr_in);
639
640 tick = time(NULL);
641 ltime = ctime(&tick);
642 ltime[19] = '\0';
643
644 gethostname(myname, MAXHOSTNAMELEN);
645
646 asprintf(&out, "<%d>%s %s syslog[%d]: %s", level, ltime+4, myname, getpid(), msg);
647 len = strlen(out);
648 sendto(s, out, len, 0, (const struct sockaddr *)&dst, sizeof(struct sockaddr_in));
649
650 free(out);
651 close(s);
652 return 0;
653 }
654
655 static int
656 _isanumber(char *s)
657 {
658 int i;
659
660 if (s == NULL) return 0;
661
662 i = 0;
663 if ((s[0] == '-') || (s[0] == '+')) i = 1;
664
665 if (s[i] == '\0') return 0;
666
667 for (; s[i] != '\0'; i++)
668 {
669 if (!isdigit(s[i])) return 0;
670 }
671
672 return 1;
673 }
674
675 int
676 asl_string_to_level(const char *s)
677 {
678 if (s == NULL) return -1;
679
680 if ((s[0] >= '0') && (s[0] <= '7') && (s[1] == '\0')) return atoi(s);
681
682 if (!strncasecmp(s, "em", 2)) return ASL_LEVEL_EMERG;
683 else if (!strncasecmp(s, "p", 1)) return ASL_LEVEL_EMERG;
684 else if (!strncasecmp(s, "a", 1)) return ASL_LEVEL_ALERT;
685 else if (!strncasecmp(s, "c", 1)) return ASL_LEVEL_CRIT;
686 else if (!strncasecmp(s, "er", 2)) return ASL_LEVEL_ERR;
687 else if (!strncasecmp(s, "x", 1)) return ASL_LEVEL_ERR;
688 else if (!strncasecmp(s, "w", 1)) return ASL_LEVEL_WARNING;
689 else if (!strncasecmp(s, "n", 1)) return ASL_LEVEL_NOTICE;
690 else if (!strncasecmp(s, "i", 1)) return ASL_LEVEL_INFO;
691 else if (!strncasecmp(s, "d", 1)) return ASL_LEVEL_DEBUG;
692
693 return -1;
694 }
695
696 int
697 syslog_remote_control(int argc, char *argv[])
698 {
699 int pid, uid, status, mask;
700 const char *prefix;
701
702 if ((argc < 3) || (argc > 4))
703 {
704 fprintf(stderr, "usage:\n");
705 fprintf(stderr, "%s -c process [mask]\n", myname);
706 fprintf(stderr, " get (set if mask is specified) syslog filter mask for process (pid or name)\n");
707 fprintf(stderr, " process may be pid or process name\n");
708 fprintf(stderr, " use \"-c 0\" to get master syslog filter mask\n");
709 fprintf(stderr, " use \"-c 0 off\" to disable master syslog filter mask\n");
710 fprintf(stderr, "\n");
711 return -1;
712 }
713
714 pid = RC_MASTER;
715 uid = -2;
716
717 status = PROC_NOT_FOUND;
718
719 if ((!strcmp(argv[2], "syslogd")) || (!strcmp(argv[2], "syslog")))
720 {
721 pid = RC_SYSLOGD;
722 uid = 0;
723 status = 0;
724 }
725 else if (_isanumber(argv[2]) != 0)
726 {
727 pid = atoi(argv[2]);
728 status = procinfo(NULL, &pid, &uid);
729 }
730 else
731 {
732 status = procinfo(argv[2], &pid, &uid);
733 }
734
735 if (status == PROC_NOT_FOUND)
736 {
737 fprintf(stderr, "%s: process not found\n", argv[2]);
738 return -1;
739 }
740
741 if (status == PROC_NOT_UNIQUE)
742 {
743 fprintf(stderr, "%s: multiple processes found\n", argv[2]);
744 fprintf(stderr, "use pid to identify a process uniquely\n");
745 return -1;
746 }
747
748 if (pid == 0) pid = RC_MASTER;
749
750 prefix = NOTIFY_PREFIX_USER;
751 if (uid == 0) prefix = NOTIFY_PREFIX_SYSTEM;
752
753 if (argc == 4)
754 {
755 if ((pid == RC_MASTER) && (!strcasecmp(argv[3], "off"))) mask = 0;
756 else if ((pid == RC_SYSLOGD) && (!strcasecmp(argv[3], "off"))) mask = 0;
757 else
758 {
759 mask = asl_string_to_filter(argv[3]);
760 if (mask < 0)
761 {
762 printf("unknown syslog mask: %s\n", argv[3]);
763 return -1;
764 }
765 }
766
767 rcontrol_set(prefix, pid, mask);
768 }
769 else
770 {
771 rcontrol_get(prefix, pid);
772 }
773
774 return 0;
775 }
776
777 int
778 syslog_send(int argc, char *argv[])
779 {
780 int i, start, kv, len, rfmt, rlevel;
781 aslclient asl;
782 aslmsg m;
783 char tmp[64], *str, *rhost;
784
785 kv = 0;
786 rhost = NULL;
787 rfmt = SEND_FORMAT_ASL;
788 start = 1;
789 rlevel = 7;
790
791 for (i = 1; i < argc; i++)
792 {
793 if (!strcmp(argv[i], "-s")) start = i+1;
794 else if (!strcmp(argv[i], "-k")) kv = 1;
795 else if (!strcmp(argv[i], "-r"))
796 {
797 rhost = argv[++i];
798 start = i+1;
799 rfmt = SEND_FORMAT_LEGACY;
800 }
801 else if (!strcmp(argv[i], "-R"))
802 {
803 rhost = argv[++i];
804 start = i+1;
805 }
806 else if (!strcmp(argv[i], "-l"))
807 {
808 rlevel = asl_string_to_level(argv[++i]);
809 if (rlevel < 0)
810 {
811 fprintf(stderr, "Unknown level: %s\n", argv[i]);
812 return(-1);
813 }
814 start = i+1;
815 }
816 }
817
818 asl = asl_open(myname, "syslog", 0);
819 asl_set_filter(asl, ASL_FILTER_MASK_UPTO(ASL_LEVEL_DEBUG));
820
821 m = asl_new(ASL_TYPE_MSG);
822 asl_set(m, ASL_KEY_SENDER, myname);
823
824 sprintf(tmp, "%d", rlevel);
825 asl_set(m, ASL_KEY_LEVEL, tmp);
826
827 str = NULL;
828
829 if (kv == 0)
830 {
831 len = 0;
832 for (i = start; i < argc; i++) len += (strlen(argv[i]) + 1);
833 str = calloc(len + 1, 1);
834 for (i = start; i < argc; i++)
835 {
836 strcat(str, argv[i]);
837 if ((i+1) < argc) strcat(str, " ");
838 }
839 asl_set(m, ASL_KEY_MSG, str);
840 }
841 else
842 {
843 for (i = start + 1; i < argc; i += 2) asl_set(m, argv[i], argv[i + 1]);
844 }
845
846 if (rhost == NULL)
847 {
848 asl_send(asl, m);
849 }
850 else if (rfmt == SEND_FORMAT_ASL)
851 {
852 rsend(m, rhost);
853 }
854 else if ((rfmt == SEND_FORMAT_LEGACY) && (str != NULL))
855 {
856 rlegacy(str, rlevel, rhost);
857 }
858
859 asl_free(m);
860
861 if (str != NULL) free(str);
862
863 asl_close(asl);
864
865 return 0;
866 }
867
868 static void
869 printmsg(FILE *f, asl_msg_t *msg, char *mstr, char *fmt, int pflags)
870 {
871 char *k, *t, c;
872 const char *v;
873 int i, j, l, paren, oval;
874 time_t tick;
875
876 if ((pflags & PRINT_STD_FMT) || (pflags & PRINT_LEGACY_FMT))
877 {
878 /* LEGACY: Mth dd hh:mm:ss host sender[pid]: message */
879 /* STD: Mth dd hh:mm:ss host sender[pid] <Level>: message */
880
881 /* Time */
882 v = asl_get(msg, ASL_KEY_TIME);
883 tick = 0;
884 if (v == NULL)
885 {
886 fprintf(f, "***Time unknown ");
887 }
888 else
889 {
890 tick = asl_parse_time(v);
891 t = ctime(&tick);
892 if (t == NULL) fprintf(f, "***Time unknown ");
893 else
894 {
895 t[19] = '\0';
896 fprintf(f, "%s ", t + 4);
897 }
898 }
899
900 /* Host */
901 v = asl_get(msg, ASL_KEY_HOST);
902 if (v != NULL) fprintf(f, "%s ", v);
903
904 /* Sender */
905 v = asl_get(msg, ASL_KEY_SENDER);
906 if (v != NULL) fprintf(f, "%s", v);
907
908 /* PID */
909 v = asl_get(msg, ASL_KEY_PID);
910 if ((v != NULL) && (v[0] != '-')) fprintf(f, "[%s]", v);
911
912 v = asl_get(msg, ASL_KEY_LEVEL);
913 i = -1;
914 if (_isanumber((char *)v)) i = atoi(v);
915 if (pflags & PRINT_STD_FMT) fprintf(f, " <%s>", asl_level_string(i));
916
917 fprintf(f, ": ");
918
919 /* Message */
920 v = asl_get(msg, ASL_KEY_MSG);
921 if (v != NULL) fprintf(f, "%s", v);
922
923 fprintf(f, "\n");
924 return;
925 }
926
927 if (fmt == NULL)
928 {
929 fprintf(f, "%s\n", mstr);
930 return;
931 }
932
933 for (i = 0; fmt[i] != '\0'; i++)
934 {
935 if (fmt[i] == '$')
936 {
937 i++;
938 paren = 0;
939
940 if (fmt[i] == '(')
941 {
942 paren = 1;
943 i++;
944 }
945
946 k = calloc(1, 1);
947 l = 0;
948
949 for (j = i; fmt[j] != '\0'; j++)
950 {
951 c = '\0';
952 if (fmt[j] == '\\') c = fmt[++j];
953 else if ((paren == 1) && (fmt[j] ==')')) break;
954 else if (fmt[j] != ' ') c = fmt[j];
955
956 if (c == '\0') break;
957
958 k = realloc(k, l + 1);
959 k[l] = c;
960 k[l + 1] = '\0';
961 l++;
962 }
963
964 if (paren == 1) j++;
965 i = j;
966 if (l > 0)
967 {
968 v = asl_get(msg, k);
969 if (v != NULL)
970 {
971 if ((pflags & PRINT_LOCALTIME) && (!strcmp(k, ASL_KEY_TIME)))
972 {
973 /* convert UTC time to localtime */
974 tick = asl_parse_time(v);
975 t = ctime(&tick);
976 if (t == NULL) fprintf(f, "%s", v);
977 else
978 {
979 t[19] = '\0';
980 fprintf(f, "%s", t + 4);
981 }
982 }
983 else
984 {
985 fprintf(f, "%s", v);
986 }
987 }
988 }
989 free(k);
990 }
991
992 if (fmt[i] == '\\')
993 {
994 i++;
995 if (fmt[i] == '$') fprintf(f, "$");
996 else if (fmt[i] == 'e') fprintf(f, "\e");
997 else if (fmt[i] == 'a') fprintf(f, "\a");
998 else if (fmt[i] == 'b') fprintf(f, "\b");
999 else if (fmt[i] == 'f') fprintf(f, "\f");
1000 else if (fmt[i] == 'n') fprintf(f, "\n");
1001 else if (fmt[i] == 'r') fprintf(f, "\r");
1002 else if (fmt[i] == 't') fprintf(f, "\t");
1003 else if (fmt[i] == 'v') fprintf(f, "\v");
1004 else if (fmt[i] == '\'') fprintf(f, "\'");
1005 else if (fmt[i] == '\\') fprintf(f, "\\");
1006 else if (isdigit(fmt[i]))
1007 {
1008 oval = fmt[i] - '0';
1009 if (isdigit(fmt[i+1]))
1010 {
1011 i++;
1012 oval = (oval * 8) + (fmt[i] - '0');
1013 if (isdigit(fmt[i+1]))
1014 {
1015 i++;
1016 oval = (oval * 8) + (fmt[i] - '0');
1017 }
1018 }
1019 c = oval;
1020 fputc(c, stdout);
1021 }
1022 continue;
1023 }
1024
1025 if (fmt[i] == '\0') break;
1026 fputc(fmt[i], stdout);
1027 }
1028
1029 fprintf(f, "\n");
1030 }
1031
1032 static char *
1033 getnextline(FILE *fp, int watch)
1034 {
1035 char *out, c;
1036 int len, count;
1037
1038 len = CHUNK;
1039 count = 0;
1040 out = calloc(len + 1, 1);
1041
1042 forever
1043 {
1044 c = getc(fp);
1045 if (c == EOF)
1046 {
1047 if (watch == 0)
1048 {
1049 if (count == 0)
1050 {
1051 free(out);
1052 return NULL;
1053 }
1054 return out;
1055 }
1056 clearerr(fp);
1057 usleep(250000);
1058 continue;
1059 }
1060
1061 if (c == '\n') return out;
1062 if (c == '\0') return out;
1063
1064 if (count == len)
1065 {
1066 len += CHUNK;
1067 out = realloc(out, len + 1);
1068 }
1069
1070 out[count++] = c;
1071 out[count] = '\0';
1072 }
1073
1074 return NULL;
1075 }
1076
1077 int
1078 search_next(asl_msg_t **q, int nq, FILE *log, int watch, aslmsg *outmsg, char **outstr)
1079 {
1080 char *str;
1081 aslmsg m;
1082 int i, match;
1083
1084 *outmsg = NULL;
1085 *outstr = NULL;
1086
1087 if (log == NULL) return SEARCH_EOF;
1088
1089 str = getnextline(log, watch);
1090 if (str == NULL) return SEARCH_EOF;
1091
1092 m = asl_msg_from_string(str);
1093 if (m == NULL)
1094 {
1095 free(str);
1096 return SEARCH_NULL;
1097 }
1098
1099 match = 0;
1100 if (q == NULL) match = 1;
1101 for (i = 0; (i < nq) && (match == 0); i++)
1102 {
1103 match = asl_msg_cmp(q[i], m);
1104 if ((q[i]->count > 0) && (q[i]->op[0] & ASL_QUERY_OP_NOT))
1105 {
1106 match = !match;
1107 }
1108 }
1109
1110 if (match == 0)
1111 {
1112 free(str);
1113 asl_free(m);
1114 return SEARCH_NULL;
1115 }
1116
1117 *outmsg = m;
1118 *outstr = str;
1119 return SEARCH_MATCH;
1120 }
1121
1122 uint32_t
1123 optype(char *o)
1124 {
1125 uint32_t op, i;
1126
1127 op = ASL_QUERY_OP_NULL;
1128
1129 if (o == NULL) return op;
1130
1131 for (i = 0; o[i] != '\0'; i++)
1132 {
1133 if (o[i] == MOD_CASE_FOLD) op |= ASL_QUERY_OP_CASEFOLD;
1134 else if (o[i] == MOD_REGEX) op |= ASL_QUERY_OP_REGEX;
1135 else if (o[i] == MOD_NUMERIC) op |= ASL_QUERY_OP_NUMERIC;
1136 else if (o[i] == MOD_SUBSTRING) op |= ASL_QUERY_OP_SUBSTRING;
1137 else if (o[i] == MOD_PREFIX) op |= ASL_QUERY_OP_PREFIX;
1138 else if (o[i] == MOD_SUFFIX) op |= ASL_QUERY_OP_SUFFIX;
1139
1140 else if (!strncasecmp(o+i, OP_EQ, sizeof(OP_EQ)))
1141 {
1142 op |= ASL_QUERY_OP_EQUAL;
1143 i += (sizeof(OP_EQ) - 2);
1144 }
1145 else if (!strncasecmp(o+i, OP_NE, sizeof(OP_NE)))
1146 {
1147 op |= ASL_QUERY_OP_NOT_EQUAL;
1148 i += (sizeof(OP_NE) - 2);
1149 }
1150 else if (!strncasecmp(o+i, OP_GT, sizeof(OP_GT)))
1151 {
1152 op |= ASL_QUERY_OP_GREATER;
1153 i += (sizeof(OP_GT) - 2);
1154 }
1155 else if (!strncasecmp(o+i, OP_GE, sizeof(OP_GE)))
1156 {
1157 op |= ASL_QUERY_OP_GREATER_EQUAL;
1158 i += (sizeof(OP_GE) - 2);
1159 }
1160 else if (!strncasecmp(o+i, OP_LT, sizeof(OP_LT)))
1161 {
1162 op |= ASL_QUERY_OP_LESS;
1163 i += (sizeof(OP_LT) - 2);
1164 }
1165 else if (!strncasecmp(o+i, OP_LE, sizeof(OP_LE)))
1166 {
1167 op |= ASL_QUERY_OP_LESS_EQUAL;
1168 i += (sizeof(OP_LE) - 2);
1169 }
1170 else
1171 {
1172 fprintf(stderr, "invalid option: %s\n", o);
1173 return 0;
1174 }
1175 }
1176
1177 /* sanity check */
1178 if (op & ASL_QUERY_OP_NUMERIC)
1179 {
1180 if (op & ASL_QUERY_OP_CASEFOLD)
1181 {
1182 fprintf(stderr, "warning: case fold modifier has no effect with numeric comparisons\n");
1183 op &= ~ASL_QUERY_OP_CASEFOLD;
1184 }
1185
1186 if (op & ASL_QUERY_OP_REGEX)
1187 {
1188 fprintf(stderr, "warning: regex modifier has no effect with numeric comparisons\n");
1189 op &= ~ASL_QUERY_OP_REGEX;
1190 }
1191
1192 if (op & ASL_QUERY_OP_SUBSTRING)
1193 {
1194 fprintf(stderr, "warning: substring modifier has no effect with numeric comparisons\n");
1195 op &= ~ASL_QUERY_OP_SUBSTRING;
1196 }
1197
1198 if (op & ASL_QUERY_OP_PREFIX)
1199 {
1200 fprintf(stderr, "warning: prefix modifier has no effect with numeric comparisons\n");
1201 op &= ~ASL_QUERY_OP_PREFIX;
1202 }
1203
1204 if (op & ASL_QUERY_OP_SUFFIX)
1205 {
1206 fprintf(stderr, "warning: suffix modifier has no effect with numeric comparisons\n");
1207 op &= ~ASL_QUERY_OP_SUFFIX;
1208 }
1209 }
1210
1211 if (op & ASL_QUERY_OP_REGEX)
1212 {
1213 if (op & ASL_QUERY_OP_SUBSTRING)
1214 {
1215 fprintf(stderr, "warning: substring modifier has no effect with regular expression comparisons\n");
1216 op &= ~ASL_QUERY_OP_SUBSTRING;
1217 }
1218
1219 if (op & ASL_QUERY_OP_PREFIX)
1220 {
1221 fprintf(stderr, "warning: prefix modifier has no effect with regular expression comparisons\n");
1222 op &= ~ASL_QUERY_OP_PREFIX;
1223 }
1224
1225 if (op & ASL_QUERY_OP_SUFFIX)
1226 {
1227 fprintf(stderr, "warning: suffix modifier has no effect with regular expression comparisons\n");
1228 op &= ~ASL_QUERY_OP_SUFFIX;
1229 }
1230 }
1231
1232 return op;
1233 }
1234
1235 int
1236 add_op(asl_msg_t *q, char *key, char *op, char *val, uint32_t flags)
1237 {
1238 uint32_t o;
1239
1240 if (key == NULL) return -1;
1241 if (q == NULL) return -1;
1242
1243 o = ASL_QUERY_OP_NULL;
1244 if (op != NULL)
1245 {
1246 o = optype(op);
1247 if (o == ASL_QUERY_OP_NULL) return -1;
1248 if (val == NULL)
1249 {
1250 fprintf(stderr, "no value supplied for operator %s %s\n", key, op);
1251 return -1;
1252 }
1253
1254 if ((o & ASL_QUERY_OP_NUMERIC) && (_isanumber(val) == 0))
1255 {
1256 fprintf(stderr, "non-numeric value supplied for numeric operator %s %s %s\n", key, op, val);
1257 return -1;
1258 }
1259
1260 }
1261
1262 o |= flags;
1263 asl_set_query(q, key, val, o);
1264
1265 return 0;
1266 }
1267
1268 int
1269 main(int argc, char *argv[])
1270 {
1271 FILE *log, *pf, *outfile;
1272 int i, j, n, qcount, qn, watch, prune, status, pflags, tflag;
1273 asl_msg_t **qlist, *outmsg;
1274 char *logname, *outname, *pfmt, *outstr;
1275 pid_t syslogd_pid;
1276 uint32_t flags;
1277
1278 qn = 0;
1279 watch = 0;
1280 prune = 0;
1281 logname = _PATH_ASL_OUT;
1282 qlist = NULL;
1283 qcount = 0;
1284 pfmt = NULL;
1285 flags = 0;
1286 pflags = PRINT_STD_FMT;
1287 tflag = PRINT_LOCALTIME;
1288
1289 for (i = 1; i < argc; i++)
1290 {
1291 if (!strcmp(argv[i], "-s"))
1292 {
1293 syslog_send(argc, argv);
1294 exit(0);
1295 }
1296
1297 if (!strcmp(argv[i], "-c"))
1298 {
1299 syslog_remote_control(argc, argv);
1300 exit(0);
1301 }
1302 }
1303
1304 for (i = 1; i < argc; i++)
1305 {
1306 if ((!strcmp(argv[i], "-help")) || (!strcmp(argv[i], "--help")))
1307 {
1308 usage();
1309 exit(0);
1310 }
1311 else if (!strcmp(argv[i], "-w"))
1312 {
1313 watch = 1;
1314 }
1315 else if (!strcmp(argv[i], "-u"))
1316 {
1317 tflag = 0;
1318 }
1319 else if (!strcmp(argv[i], "-p"))
1320 {
1321 prune = 1;
1322 }
1323 else if (!strcmp(argv[i], "-f"))
1324 {
1325 if ((i + 1) >= argc)
1326 {
1327 usage();
1328 exit(1);
1329 }
1330
1331 logname = argv[++i];
1332 }
1333 else if (!strcmp(argv[i], "-F"))
1334 {
1335 if ((i + 1) >= argc)
1336 {
1337 usage();
1338 exit(1);
1339 }
1340
1341 i++;
1342 if (!strcmp(argv[i], "raw"))
1343 {
1344 pflags = 0;
1345 tflag = 0;
1346 }
1347 else if (!strcmp(argv[i], "std"))
1348 {
1349 pflags = PRINT_STD_FMT;
1350 }
1351 else if (!strcmp(argv[i], "bsd"))
1352 {
1353 pflags = PRINT_LEGACY_FMT;
1354 }
1355 else
1356 {
1357 pflags = 0;
1358 pfmt = argv[i];
1359 }
1360 }
1361 else if (!strcmp(argv[i], "-o"))
1362 {
1363 flags = 0;
1364
1365 if (qlist == NULL)
1366 {
1367 qlist = (asl_msg_t **)calloc(1, sizeof(asl_msg_t *));
1368 }
1369 else
1370 {
1371 qlist = (asl_msg_t **)realloc(qlist, (qcount + 1) * sizeof(asl_msg_t *));
1372 }
1373
1374 qcount++;
1375 qn = qcount - 1;
1376 qlist[qn] = asl_new(ASL_TYPE_QUERY);
1377 }
1378 else if (!strcmp(argv[i], "-n"))
1379 {
1380 flags = ASL_QUERY_OP_NOT;
1381 }
1382 else if (!strcmp(argv[i], "-k"))
1383 {
1384 i++;
1385 for (n = i; n < argc; n++)
1386 {
1387 if (!strcmp(argv[n], "-o")) break;
1388 if (!strcmp(argv[n], "-n")) break;
1389 if (!strcmp(argv[n], "-k")) break;
1390 if ((n - i) > 2)
1391 {
1392 fprintf(stderr, "invalid sequence: -k");
1393 for (j = i; j <= n; j++) fprintf(stderr, " %s", argv[j]);
1394 fprintf(stderr, "\n");
1395 usage();
1396 exit(1);
1397 }
1398 }
1399
1400 n -= i;
1401 if (n == 0)
1402 {
1403 i--;
1404 continue;
1405 }
1406
1407 if (qlist == NULL)
1408 {
1409 qlist = (asl_msg_t **)calloc(1, sizeof(asl_msg_t *));
1410 qcount = 1;
1411 qn = 0;
1412 qlist[qn] = asl_new(ASL_TYPE_QUERY);
1413 }
1414
1415 status = 0;
1416 if (n == 1) status = add_op(qlist[qn], argv[i], NULL, NULL, flags);
1417 else if (n == 2) status = add_op(qlist[qn], argv[i], OP_EQ, argv[i+1], flags);
1418 else status = add_op(qlist[qn], argv[i], argv[i+1], argv[i+2], flags);
1419
1420 flags = 0;
1421 if (status != 0) exit(1);
1422 }
1423 }
1424
1425 pflags |= tflag;
1426
1427 if (prune == 1)
1428 {
1429 if (watch == 1)
1430 {
1431 fprintf(stderr, "-w flag has no effect when pruning log file\n");
1432 }
1433
1434 if (getuid() != 0)
1435 {
1436 fprintf(stderr, "you must be root to prune the log file\n");
1437 exit(1);
1438 }
1439
1440 if (qlist == NULL)
1441 {
1442 fprintf(stderr, "no queries for pruning\n");
1443 exit(0);
1444 }
1445
1446 pf = fopen(_PATH_SYSLOGD_PID, "r");
1447 if (pf == NULL)
1448 {
1449 perror(_PATH_SYSLOGD_PID);
1450 exit(1);
1451 }
1452
1453 status = fscanf(pf, "%d", &syslogd_pid);
1454 fclose(pf);
1455 if (status != 1)
1456 {
1457 fprintf(stderr, "can't read syslogd pid from %s\n", _PATH_SYSLOGD_PID);
1458 exit(1);
1459 }
1460
1461 unlink(_PATH_ASL_PRUNE);
1462 pf = fopen(_PATH_ASL_PRUNE, "w");
1463 if (pf == NULL)
1464 {
1465 perror(_PATH_ASL_PRUNE);
1466 exit(1);
1467 }
1468
1469 for (i = 0; i < qcount; i++)
1470 {
1471 outstr = asl_msg_to_string(qlist[i], &j);
1472 fprintf(pf, "%s\n", outstr);
1473 free(outstr);
1474 }
1475
1476 fclose(pf);
1477
1478 kill(syslogd_pid, SIGWINCH);
1479
1480 exit(0);
1481 }
1482
1483 log = NULL;
1484
1485 if (!strcmp(logname, "-")) log = stdin;
1486 else log = fopen(logname, "r");
1487
1488 if (log == NULL)
1489 {
1490 perror(logname);
1491 exit(1);
1492 }
1493
1494 if (watch == 1) fseek(log, 0, SEEK_END);
1495 outname = NULL;
1496 outfile = stdout;
1497
1498 do
1499 {
1500 outmsg = NULL;
1501 outstr = NULL;
1502 status = search_next(qlist, qcount, log, watch, &outmsg, &outstr);
1503
1504 if (status == SEARCH_MATCH)
1505 {
1506 printmsg(outfile, outmsg, outstr, pfmt, pflags);
1507 }
1508
1509 if (outstr != NULL) free(outstr);
1510 if (outmsg != NULL) asl_free(outmsg);
1511 }
1512 while (status != SEARCH_EOF);
1513
1514 fclose(log);
1515
1516 for (i = 0; i < qcount; i++) asl_free(qlist[i]);
1517 if (qlist != NULL) free(qlist);
1518
1519 exit(0);
1520 }