2  * Copyright (c) 2004-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 <sys/types.h> 
  26 #include <sys/socket.h> 
  41 #define _PATH_WALL "/usr/bin/wall" 
  42 #define _PATH_ASL_CONF "/etc/asl.conf" 
  43 #define MY_ID "asl_action" 
  46 #define ACTION_IGNORE    1 
  47 #define ACTION_NOTIFY    2 
  48 #define ACTION_BROADCAST 3 
  49 #define ACTION_ACCESS    4 
  50 #define ACTION_STORE     5 
  51 #define ACTION_STORE_DIR 6 
  52 #define ACTION_FORWARD   7 
  54 #define forever for(;;) 
  56 #define ACT_STORE_FLAG_STAY_OPEN 0x00000001 
  57 #define ACT_STORE_FLAG_CONTINUE  0x00000002 
  59 static asl_msg_t 
*query 
= NULL
; 
  60 static int reset 
= RESET_NONE
; 
  61 static pthread_mutex_t reset_lock 
= PTHREAD_MUTEX_INITIALIZER
; 
  63 typedef struct action_rule_s
 
  69         struct action_rule_s 
*next
; 
  88 static action_rule_t 
*asl_action_rule 
= NULL
; 
  89 static action_rule_t 
*asl_datastore_rule 
= NULL
; 
  90 static int filter_token 
= -1; 
  92 int asl_action_close(); 
  93 static int _parse_config_file(const char *); 
  94 extern void db_save_message(aslmsg m
); 
  99         char *a
, *p
, *e
, *out
; 
 102         if (s 
== NULL
) return NULL
; 
 103         if (*s 
== NULL
) return NULL
; 
 131                         if (quote 
== 0) quote 
= 1; 
 135                 if (((*p 
== ' ') || (*p 
== '\t')) && (quote 
== 0)) 
 148         if (len 
== 0) return NULL
; 
 150         out 
= malloc(len 
+ 1); 
 151         if (out 
== NULL
) return NULL
; 
 161         pthread_mutex_lock(&reset_lock
); 
 163         if (reset 
== RESET_CONFIG
) 
 166                 _parse_config_file(_PATH_ASL_CONF
); 
 171         pthread_mutex_unlock(&reset_lock
); 
 175  * Config File format: 
 176  * Set parameter rule - initializes a parameter. 
 178  * Query rule - if a message matches the query, then the action is invoked. 
 179  * The rule may be identified by either "?" or "Q". 
 180  *              ? [k v] [k v] ... action args...    
 181  *              Q [k v] [k v] ... action args...    
 182  * Universal match rule - the action is invoked for all messages 
 186 /* Skip over query */ 
 188 _find_action(char *s
) 
 193         if (p 
== NULL
) return NULL
; 
 194         if ((*p 
!= 'Q') && (*p 
!= '?') && (*p 
!= '*')) return NULL
; 
 201                 while ((*p 
== ' ') || (*p 
== '\t')) p
++; 
 203                 if (*p 
== '\0') return NULL
; 
 204                 if (*p 
!= '[') return p
; 
 206                 /* skip to closing ] */ 
 224 _parse_query_action(char *s
) 
 227         action_rule_t 
*out
, *rule
; 
 229         act 
= _find_action(s
); 
 230         if (act 
== NULL
) return -1; 
 232         out 
= (action_rule_t 
*)calloc(1, sizeof(action_rule_t
)); 
 233         if (out 
== NULL
) return -1; 
 235         p 
= strchr(act
, ' '); 
 236         if (p 
!= NULL
) *p 
= '\0'; 
 238         if (!strcasecmp(act
, "ignore"))               out
->action 
= ACTION_IGNORE
; 
 239         else if (!strcasecmp(act
, "notify"))          out
->action 
= ACTION_NOTIFY
; 
 240         else if (!strcasecmp(act
, "broadcast"))       out
->action 
= ACTION_BROADCAST
; 
 241         else if (!strcasecmp(act
, "access"))          out
->action 
= ACTION_ACCESS
; 
 242         else if (!strcasecmp(act
, "store"))           out
->action 
= ACTION_STORE
; 
 243         else if (!strcasecmp(act
, "save"))            out
->action 
= ACTION_STORE
; 
 244         else if (!strcasecmp(act
, "store_directory")) out
->action 
= ACTION_STORE_DIR
; 
 245         else if (!strcasecmp(act
, "store_dir"))       out
->action 
= ACTION_STORE_DIR
; 
 246         else if (!strcasecmp(act
, "forward"))         out
->action 
= ACTION_FORWARD
; 
 250                 out
->options 
= strdup(p
+1); 
 252                 if (out
->options 
== NULL
) 
 263         if (s
[0] == '*') out
->query 
= asl_msg_new(ASL_TYPE_QUERY
); 
 267                 out
->query 
= asl_msg_from_string(s
); 
 270         if (out
->query 
== NULL
) 
 272                 asldebug("out->query is NULL (ERROR)\n"); 
 278         if ((out
->action 
== ACTION_STORE
) && (out
->options 
== NULL
)) 
 280                 asldebug("action = ACTION_STORE options = NULL\n"); 
 281                 if (asl_datastore_rule 
== NULL
) asl_datastore_rule 
= out
; 
 284                         for (rule 
= asl_datastore_rule
; rule
->next 
!= NULL
; rule 
= rule
->next
); 
 290                 asldebug("action = %d options = %s\n", out
->action
, out
->options
); 
 291                 if (asl_action_rule 
== NULL
) asl_action_rule 
= out
; 
 294                         for (rule 
= asl_action_rule
; rule
->next 
!= NULL
; rule 
= rule
->next
); 
 303  * Used to sed config parameters. 
 304  * Line format "= name value" 
 307 _parse_set_param(char *s
) 
 310         uint32_t intval
, count
, v32a
, v32b
, v32c
; 
 312         if (s 
== NULL
) return -1; 
 313         if (s
[0] == '\0') return 0; 
 315         /* skip '=' and whitespace */ 
 317         while ((*s 
== ' ') || (*s 
== '\t')) s
++; 
 319         l 
= explode(s
, " \t"); 
 320         if (l 
== NULL
) return -1; 
 322         for (count 
= 0; l
[count
] != NULL
; count
++); 
 324         /* name is required */ 
 331         /* value is required */ 
 338         if (!strcasecmp(l
[0], "debug")) 
 340                 /* = debug {0|1} [file] */ 
 342                 config_debug(intval
, l
[2]); 
 344         else if (!strcasecmp(l
[0], "cutoff")) 
 348                 if (intval 
> ASL_LEVEL_DEBUG
) intval 
= ASL_LEVEL_DEBUG
; 
 349                 global
.asl_log_filter 
= ASL_FILTER_MASK_UPTO(intval
); 
 351         else if (!strcasecmp(l
[0], "mark_time")) 
 353                 /* = mark_time seconds */ 
 354                 OSSpinLockLock(&global
.lock
); 
 355                 global
.mark_time 
= atoll(l
[1]); 
 356                 OSSpinLockUnlock(&global
.lock
); 
 358         else if (!strcasecmp(l
[0], "dup_delay")) 
 360                 /* = bsd_max_dup_time seconds */ 
 361                 OSSpinLockLock(&global
.lock
); 
 362                 global
.bsd_max_dup_time 
= atoll(l
[1]); 
 363                 OSSpinLockUnlock(&global
.lock
); 
 365         else if (!strcasecmp(l
[0], "asl_store_ping_time")) 
 367                 /* NB this is private / unpublished */ 
 368                 /* = asl_store_ping_time seconds */ 
 369                 OSSpinLockLock(&global
.lock
); 
 370                 global
.asl_store_ping_time 
= atoll(l
[1]); 
 371                 OSSpinLockUnlock(&global
.lock
); 
 373         else if (!strcasecmp(l
[0], "utmp_ttl")) 
 375                 /* = utmp_ttl seconds */ 
 376                 OSSpinLockLock(&global
.lock
); 
 377                 global
.utmp_ttl 
= (time_t)atoll(l
[1]); 
 378                 OSSpinLockUnlock(&global
.lock
); 
 380         else if (!strcasecmp(l
[0], "fs_ttl")) 
 382                 /* = fs_ttl seconds */ 
 383                 OSSpinLockLock(&global
.lock
); 
 384                 global
.fs_ttl 
= (time_t)atoll(l
[1]); 
 385                 OSSpinLockUnlock(&global
.lock
); 
 387         else if (!strcasecmp(l
[0], "mps_limit")) 
 389                 /* = mps_limit number */ 
 390                 OSSpinLockLock(&global
.lock
); 
 391                 global
.mps_limit 
= (uint32_t)atol(l
[1]); 
 392                 OSSpinLockUnlock(&global
.lock
); 
 394         else if (!strcasecmp(l
[0], "max_file_size")) 
 396                 /* = max_file_size bytes */ 
 397                 pthread_mutex_lock(global
.db_lock
); 
 399                 if (global
.dbtype 
& DB_TYPE_FILE
) 
 401                         asl_store_close(global
.file_db
); 
 402                         global
.file_db 
= NULL
; 
 403                         global
.db_file_max 
= atoi(l
[1]); 
 406                 pthread_mutex_unlock(global
.db_lock
); 
 408         else if ((!strcasecmp(l
[0], "db")) || (!strcasecmp(l
[0], "database")) || (!strcasecmp(l
[0], "datastore"))) 
 410                 /* NB this is private / unpublished */ 
 411                 /* = db type [max]... */ 
 417                 if ((l
[1][0] >= '0') && (l
[1][0] <= '9')) 
 420                         if ((count 
>= 3) && (strcmp(l
[2], "-"))) v32a 
= atoi(l
[2]); 
 421                         if ((count 
>= 4) && (strcmp(l
[3], "-"))) v32b 
= atoi(l
[3]); 
 422                         if ((count 
>= 5) && (strcmp(l
[4], "-"))) v32c 
= atoi(l
[4]); 
 424                 else if (!strcasecmp(l
[1], "file")) 
 426                         intval 
= DB_TYPE_FILE
; 
 427                         if ((count 
>= 3) && (strcmp(l
[2], "-"))) v32a 
= atoi(l
[2]); 
 429                 else if (!strncasecmp(l
[1], "mem", 3)) 
 431                         intval 
= DB_TYPE_MEMORY
; 
 432                         if ((count 
>= 3) && (strcmp(l
[2], "-"))) v32b 
= atoi(l
[2]); 
 434                 else if (!strncasecmp(l
[1], "min", 3)) 
 436                         intval 
= DB_TYPE_MINI
; 
 437                         if ((count 
>= 3) && (strcmp(l
[2], "-"))) v32c 
= atoi(l
[2]); 
 445                 if (v32a 
== 0) v32a 
= global
.db_file_max
; 
 446                 if (v32b 
== 0) v32b 
= global
.db_memory_max
; 
 447                 if (v32c 
== 0) v32c 
= global
.db_mini_max
; 
 449                 config_data_store(intval
, v32a
, v32b
, v32c
); 
 462         if (s 
== NULL
) return -1; 
 463         while ((*s 
== ' ') || (*s 
== '\t')) s
++; 
 465         /* First non-whitespace char is the rule type */ 
 471                         /* Blank Line or Comment */ 
 478                         /* Query-match action */ 
 479                         status 
= _parse_query_action(s
); 
 485                         status 
= _parse_set_param(s
); 
 498                 asprintf(&str
, "[%s syslogd] [%s %u] [%s %u] [%s Ignoring unrecognized entry in %s: %s] [%s 0] [%s 0] [Facility syslog]", 
 500                                  ASL_KEY_LEVEL
, ASL_LEVEL_ERR
, 
 501                                  ASL_KEY_PID
, getpid(), 
 502                                  ASL_KEY_MSG
, _PATH_ASL_CONF
, s
, 
 503                                  ASL_KEY_UID
, ASL_KEY_GID
); 
 513 _act_notify(action_rule_t 
*r
) 
 515         if (r 
== NULL
) return; 
 516         if (r
->options 
== NULL
) return; 
 518         notify_post(r
->options
); 
 522 _act_broadcast(action_rule_t 
*r
, aslmsg msg
) 
 524 #ifndef CONFIG_IPHONE 
 528         if (r 
== NULL
) return; 
 529         if (msg 
== NULL
) return; 
 532         if (val 
== NULL
) val 
= asl_get(msg
, ASL_KEY_MSG
); 
 533         if (val 
== NULL
) return; 
 535         pw 
= popen(_PATH_WALL
, "w"); 
 538                 asldebug("%s: error sending wall message: %s\n", MY_ID
, strerror(errno
)); 
 542         fprintf(pw
, "%s", val
); 
 548 _act_access_control(action_rule_t 
*r
, aslmsg msg
) 
 553         ruid 
= atoi(r
->options
); 
 555         p 
= strchr(r
->options
, ' '); 
 556         if (p 
== NULL
) p 
= strchr(r
->options
, '\t'); 
 564         if (ruid 
!= -1) asl_set(msg
, ASL_KEY_READ_UID
, r
->options
); 
 567                 if (rgid 
!= -1) asl_set(msg
, ASL_KEY_READ_GID
, p
); 
 574 _act_store_file_setup(struct store_data 
*sd
) 
 578         if (sd 
== NULL
) return ASL_STATUS_INVALID_STORE
; 
 579         if (sd
->store 
== NULL
) return ASL_STATUS_INVALID_STORE
; 
 580         if (sd
->store
->store 
== NULL
) return ASL_STATUS_INVALID_STORE
; 
 582         status 
= asl_file_read_set_position(sd
->store
, ASL_FILE_POSITION_LAST
); 
 583         if (status 
!= ASL_STATUS_OK
) return status
; 
 585         sd
->next_id 
= sd
->store
->cursor_xid 
+ 1; 
 586         if (fseek(sd
->store
->store
, 0, SEEK_END
) != 0) return ASL_STATUS_ACCESS_DENIED
; 
 588         return ASL_STATUS_OK
; 
 592 _act_store_dir_setup(struct store_data 
*sd
, time_t tick
) 
 601         if (sd 
== NULL
) return ASL_STATUS_INVALID_STORE
; 
 602         if (sd
->dir 
== NULL
) return ASL_STATUS_INVALID_STORE
; 
 604         /* get / set message id from StoreData file */ 
 607         if (sd
->storedata 
== NULL
) 
 609                 memset(&sb
, 0, sizeof(struct stat
)); 
 610                 status 
= stat(sd
->dir
, &sb
); 
 613                         /* must be a directory */ 
 614                         if (!S_ISDIR(sb
.st_mode
)) return ASL_STATUS_INVALID_STORE
; 
 616                 else if (errno 
== ENOENT
) 
 618                         /* doesn't exist - create it */ 
 620                         status 
= mkdir(sd
->dir
, sd
->mode
); 
 623                         if (status 
!= 0) return ASL_STATUS_WRITE_FAILED
; 
 625                         if ((sd
->uid 
!= 0) || (sd
->gid 
!= 0)) 
 627                                 if (chown(sd
->dir
, sd
->uid
, sd
->gid
) != 0) return ASL_STATUS_WRITE_FAILED
; 
 632                         /* Unexpected stat error */ 
 633                         return ASL_STATUS_FAILED
; 
 637                 asprintf(&path
, "%s/%s", sd
->dir
, FILE_ASL_STORE_DATA
); 
 638                 if (path 
== NULL
) return ASL_STATUS_NO_MEMORY
; 
 640                 memset(&sb
, 0, sizeof(struct stat
)); 
 641                 status 
= stat(path
, &sb
); 
 644                         /* StoreData exists: open and read last xid */ 
 645                         sd
->storedata 
= fopen(path
, "r+"); 
 646                         if (sd
->storedata 
== NULL
) 
 649                                 return ASL_STATUS_FAILED
; 
 652                         if (fread(&xid
, sizeof(uint64_t), 1, sd
->storedata
) != 1) 
 655                                 fclose(sd
->storedata
); 
 656                                 sd
->storedata 
= NULL
; 
 657                                 return ASL_STATUS_READ_FAILED
; 
 660                 else if (errno 
== ENOENT
) 
 662                         /* StoreData does not exist: create it */ 
 663                         sd
->storedata 
= fopen(path
, "w"); 
 664                         if (sd
->storedata 
== NULL
) 
 667                                 return ASL_STATUS_FAILED
; 
 670                         if ((sd
->uid 
!= 0) || (sd
->gid 
!= 0)) 
 672                                 if (chown(path
, sd
->uid
, sd
->gid
) != 0) 
 675                                         return ASL_STATUS_WRITE_FAILED
; 
 681                         /* Unexpected stat error */ 
 683                         return ASL_STATUS_FAILED
; 
 690                 rewind(sd
->storedata
); 
 691                 if (fread(&xid
, sizeof(uint64_t), 1, sd
->storedata
) != 1) 
 693                         fclose(sd
->storedata
); 
 694                         sd
->storedata 
= NULL
; 
 695                         return ASL_STATUS_READ_FAILED
; 
 699         xid 
= asl_core_ntohq(xid
); 
 703         xid 
= asl_core_htonq(xid
); 
 704         rewind(sd
->storedata
); 
 705         status 
= fwrite(&xid
, sizeof(uint64_t), 1, sd
->storedata
); 
 708                 fclose(sd
->storedata
); 
 709                 sd
->storedata 
= NULL
; 
 710                 return ASL_STATUS_WRITE_FAILED
; 
 713         if ((sd
->flags 
& ACT_STORE_FLAG_STAY_OPEN
) == 0) 
 715                 fclose(sd
->storedata
); 
 716                 sd
->storedata 
= NULL
; 
 719         memset(&ctm
, 0, sizeof(struct tm
)); 
 721         if (localtime_r((const time_t *)&tick
, &ctm
) == NULL
) return ASL_STATUS_FAILED
; 
 722         if ((sd
->p_year 
== ctm
.tm_year
) && (sd
->p_month 
== ctm
.tm_mon
) && (sd
->p_day 
== ctm
.tm_mday
) && (sd
->path 
!= NULL
)) return ASL_STATUS_OK
; 
 724         if (sd
->store 
!= NULL
) asl_file_close(sd
->store
); 
 733         asprintf(&(sd
->path
), "%s/%d.%02d.%02d.asl", sd
->dir
, ctm
.tm_year 
+ 1900, ctm
.tm_mon 
+ 1, ctm
.tm_mday
); 
 734         if (sd
->path 
== NULL
) return ASL_STATUS_NO_MEMORY
; 
 736         sd
->p_year 
= ctm
.tm_year
; 
 737         sd
->p_month 
= ctm
.tm_mon
; 
 738         sd
->p_day 
= ctm
.tm_mday
; 
 740         return ASL_STATUS_OK
; 
 744 _act_store(action_rule_t 
*r
, aslmsg msg
) 
 746         struct store_data 
*sd
; 
 751         mode_t tmp_mode
, mask
; 
 752         char *str
, *opts
, *p
; 
 758         /* _act_store is not used for the main ASL data store */ 
 759         if (r
->options 
== NULL
) return; 
 763                 /* set up store data */ 
 764                 sd 
= (struct store_data 
*)calloc(1, sizeof(struct store_data
)); 
 765                 if (sd 
== NULL
) return; 
 770                 if (r
->action 
== ACTION_STORE
) 
 772                         sd
->path 
= _next_word(&opts
); 
 773                         if ((sd
->path 
== NULL
) || (sd
->path
[0] != '/')) 
 776                                 asprintf(&str
, "[%s syslogd] [%s %u] [%s %u] [Facility syslog] [%s Invalid path for \"store\" action: %s]", 
 778                                                  ASL_KEY_LEVEL
, ASL_LEVEL_ERR
, 
 779                                                  ASL_KEY_PID
, getpid(), 
 780                                                  ASL_KEY_MSG
, (sd
->path 
== NULL
) ? "no path specified" : sd
->path
); 
 785                                 r
->action 
= ACTION_NONE
; 
 789                 else if (r
->action 
== ACTION_STORE_DIR
) 
 791                         sd
->dir 
= _next_word(&opts
); 
 792                         if ((sd
->dir 
== NULL
) || (sd
->dir
[0] != '/')) 
 795                                 asprintf(&str
, "[%s syslogd] [%s %u] [%s %u] [Facility syslog] [%s Invalid path for \"store_directory\" action: %s]", 
 797                                                  ASL_KEY_LEVEL
, ASL_LEVEL_ERR
, 
 798                                                  ASL_KEY_PID
, getpid(), 
 799                                                  ASL_KEY_MSG
, (sd
->dir 
== NULL
) ? "no path specified" : sd
->dir
); 
 804                                 r
->action 
= ACTION_NONE
; 
 815                 while (NULL 
!= (p 
= _next_word(&opts
))) 
 817                         if (!strcmp(p
, "stayopen")) 
 819                                 sd
->flags 
|= ACT_STORE_FLAG_STAY_OPEN
; 
 821                         else if (!strcmp(p
, "continue")) 
 823                                 sd
->flags 
|= ACT_STORE_FLAG_CONTINUE
; 
 825                         else if (!strncmp(p
, "mode=0", 6)) 
 829                                 if ((x 
< '0') || (x 
> '7')) 
 835                                         r
->action 
= ACTION_NONE
; 
 840                                 sd
->mode 
+= tmp_mode 
<< 6; 
 843                                 if ((x 
< '0') || (x 
> '7')) 
 849                                         r
->action 
= ACTION_NONE
; 
 854                                 sd
->mode 
+= tmp_mode 
<< 3; 
 857                                 if ((x 
< '0') || (x 
> '7')) 
 863                                         r
->action 
= ACTION_NONE
; 
 868                                 sd
->mode 
+= tmp_mode
; 
 870                         else if (!strncmp(p
, "mode=", 5)) sd
->mode 
= atoi(p
+4); 
 871                         else if (!strncmp(p
, "uid=", 4)) sd
->uid 
= atoi(p
+4); 
 872                         else if (!strncmp(p
, "gid=", 4)) sd
->gid 
= atoi(p
+4); 
 882                 sd 
= (struct store_data 
*)r
->data
; 
 885         if (r
->action 
== ACTION_STORE_DIR
) 
 887                 val 
= asl_get(msg
, ASL_KEY_TIME
); 
 888                 if (val 
== NULL
) return; 
 891                 status 
= _act_store_dir_setup(sd
, tick
); 
 892                 if (status 
!= ASL_STATUS_OK
) 
 894                         asldebug("_act_store_dir_setup %s failed: %s\n", sd
->path
, asl_core_error(status
)); 
 896                         /* disable further activity */ 
 897                         asl_file_close(sd
->store
); 
 899                         r
->action 
= ACTION_NONE
; 
 904         if (sd
->store 
== NULL
) 
 909                 status 
= asl_file_open_write(sd
->path
, (sd
->mode 
& 0666), sd
->uid
, sd
->gid
, &s
); 
 912                 if ((status 
!= ASL_STATUS_OK
) || (s 
== NULL
)) 
 914                         asldebug("asl_file_open_write %s failed: %s\n", sd
->path
, asl_core_error(status
)); 
 916                         /* disable further activity */ 
 917                         asl_file_close(sd
->store
); 
 919                         r
->action 
= ACTION_NONE
; 
 926         if (r
->action 
!= ACTION_STORE_DIR
) 
 928                 status 
= _act_store_file_setup(sd
); 
 929                 if (status 
!= ASL_STATUS_OK
) 
 931                         asldebug("_act_store_file_setup %s failed: %s\n", sd
->path
, asl_core_error(status
)); 
 933                         /* disable further activity */ 
 934                         asl_file_close(sd
->store
); 
 936                         r
->action 
= ACTION_NONE
; 
 943         status 
= asl_file_save(sd
->store
, msg
, &mid
); 
 944         if (status 
!= ASL_STATUS_OK
) 
 946                 asldebug("asl_file_save %s failed: %s\n", sd
->path
, asl_core_error(status
)); 
 948                 /* disable further activity on this file */ 
 949                 asl_file_close(sd
->store
); 
 951                 r
->action 
= ACTION_NONE
; 
 955         if ((sd
->flags 
& ACT_STORE_FLAG_STAY_OPEN
) == 0) 
 957                 asl_file_close(sd
->store
); 
 961         if ((sd
->flags 
& ACT_STORE_FLAG_CONTINUE
) == 0) 
 963                 opts 
= (char *)asl_get(msg
, ASL_KEY_OPTION
); 
 966                         asl_set(msg
, ASL_KEY_OPTION
, ASL_OPT_IGNORE
); 
 971                         asprintf(&str
, "%s %s", ASL_OPT_IGNORE
, opts
); 
 974                                 asl_set(msg
, ASL_KEY_OPTION
, str
); 
 982 _act_forward(action_rule_t 
*r
, aslmsg msg
) 
 984         /* To do: <rdar://problem/6130747> Add a "forward" action to asl.conf */ 
 988 send_to_asl_store(aslmsg msg
) 
 990         const char *vlevel
, *val
; 
 992         uint32_t status
, level
, lmask
; 
 996         if (filter_token 
== -1) 
 998                 /* set up com.apple.syslog.asl_filter */ 
 999                 status 
= notify_register_check(NOTIFY_SYSTEM_ASL_FILTER
, &filter_token
); 
1000                 if (status 
!= NOTIFY_STATUS_OK
) 
1006                         status 
= notify_check(filter_token
, &x
); 
1007                         if (status 
== NOTIFY_STATUS_OK
) 
1009                                 v64 
= global
.asl_log_filter
; 
1010                                 status 
= notify_set_state(filter_token
, v64
); 
1012                         if (status 
!= NOTIFY_STATUS_OK
) 
1014                                 notify_cancel(filter_token
); 
1020         /* ASLOption "store" forces a message to be saved */ 
1021         log_me 
= asl_check_option(msg
, ASL_OPT_STORE
); 
1024                 db_save_message(msg
); 
1029         if (filter_token 
>= 0) 
1032                 status 
= notify_check(filter_token
, &x
); 
1033                 if ((status 
== NOTIFY_STATUS_OK
) && (x 
== 1)) 
1036                         status 
= notify_get_state(filter_token
, &v64
); 
1037                         if ((status 
== NOTIFY_STATUS_OK
) && (v64 
!= 0)) global
.asl_log_filter 
= v64
; 
1041         /* PID 0 (kernel) or PID 1 (launchd) messages are saved */ 
1042         val 
= asl_get(msg
, ASL_KEY_PID
); 
1043         if ((val 
!= NULL
) && (atoi(val
) <= 1)) log_me 
= 1; 
1046                 vlevel 
= asl_get(msg
, ASL_KEY_LEVEL
); 
1048                 if (vlevel 
!= NULL
) level 
= atoi(vlevel
); 
1049                 lmask 
= ASL_FILTER_MASK(level
); 
1050                 if ((lmask 
& global
.asl_log_filter
) != 0) log_me 
= 1; 
1053         if (log_me 
== 0) return; 
1055         /* if there are no rules, save the message */ 
1056         if (asl_datastore_rule 
== NULL
) 
1058                 db_save_message(msg
); 
1062         for (r 
= asl_datastore_rule
; r 
!= NULL
; r 
= r
->next
) 
1064                 if (asl_msg_cmp(r
->query
, (asl_msg_t 
*)msg
) == 1) 
1066                         /* if any rule matches, save the message (once!) */ 
1067                         db_save_message(msg
); 
1074 asl_action_sendmsg(aslmsg msg
, const char *outid
) 
1078         if (reset 
!= RESET_NONE
) _do_reset(); 
1080         if (msg 
== NULL
) return -1; 
1082         for (r 
= asl_action_rule
; r 
!= NULL
; r 
= r
->next
) 
1084                 if (asl_msg_cmp(r
->query
, (asl_msg_t 
*)msg
) == 1) 
1086                         if ((r
->action 
== ACTION_STORE
) || (r
->action 
== ACTION_STORE_DIR
)) 
1089                                 if (asl_check_option(msg
, ASL_OPT_IGNORE
) != 0) return -1; 
1092                         if (r
->action 
== ACTION_NONE
) continue; 
1093                         else if (r
->action 
== ACTION_IGNORE
) return -1; 
1094                         else if (r
->action 
== ACTION_ACCESS
) _act_access_control(r
, msg
); 
1095                         else if (r
->action 
== ACTION_NOTIFY
) _act_notify(r
); 
1096                         else if (r
->action 
== ACTION_BROADCAST
) _act_broadcast(r
, msg
); 
1097                         else if (r
->action 
== ACTION_FORWARD
) _act_forward(r
, msg
); 
1101         if (asl_check_option(msg
, ASL_OPT_IGNORE
) != 0) return -1; 
1103         send_to_asl_store(msg
); 
1109 _parse_config_file(const char *name
) 
1114         cf 
= fopen(name
, "r"); 
1115         if (cf 
== NULL
) return 1; 
1117         while (NULL 
!= (line 
= get_line_from_file(cf
))) 
1129 asl_action_init(void) 
1131         asldebug("%s: init\n", MY_ID
); 
1133         query 
= asl_msg_new(ASL_TYPE_QUERY
); 
1134         aslevent_addmatch(query
, MY_ID
); 
1135         aslevent_addoutput(asl_action_sendmsg
, MY_ID
); 
1137         _parse_config_file(_PATH_ASL_CONF
); 
1142 asl_action_reset(void) 
1144         reset 
= global
.reset
; 
1149 asl_action_close(void) 
1151         action_rule_t 
*r
, *n
; 
1152         struct store_data 
*sd
; 
1154         for (r 
= asl_action_rule
; r 
!= NULL
; r 
= n
) 
1158                 if (((r
->action 
== ACTION_STORE
) || (r
->action 
== ACTION_STORE_DIR
) || (r
->action 
== ACTION_NONE
)) && (r
->data 
!= NULL
)) 
1160                         sd 
= (struct store_data 
*)r
->data
; 
1161                         if (sd
->store 
!= NULL
) asl_file_close(sd
->store
); 
1162                         if (sd
->storedata 
!= NULL
) fclose(sd
->storedata
); 
1169                 if (r
->query 
!= NULL
) asl_msg_release(r
->query
); 
1175         asl_action_rule 
= NULL
; 
1178         for (r 
= asl_datastore_rule
; r 
!= NULL
; r 
= n
) 
1182                 if (r
->query 
!= NULL
) asl_msg_release(r
->query
); 
1188         asl_datastore_rule 
= NULL
;