2 * Copyright 2006-08,2012-14 Red Hat Inc., Durham, North Carolina.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 * Steve Grubb <sgrubb@redhat.com>
24 #include "expression.h"
27 #include "interpret.h"
32 #include <stdio_ext.h>
36 /* like strchr except string is delimited by length, not null byte */
37 static char *strnchr(const char *s, int c, size_t n)
40 const char *p_end = s + n;
42 for (p_char = (char *)s; p_char < p_end && *p_char != c; p_char++);
43 if (p_char == p_end) return NULL;
47 static int setup_log_file_array(auparse_state_t *au)
49 struct daemon_conf config;
50 char *filename, **tmp;
51 int len, num = 0, i = 0;
53 /* Load config so we know where logs are */
54 set_aumessage_mode(MSG_STDERR, DBG_NO);
55 load_config(&config, TEST_SEARCH);
58 len = strlen(config.log_file) + 16;
59 filename = malloc(len);
61 fprintf(stderr, "No memory\n");
65 /* Find oldest log file */
66 snprintf(filename, len, "%s", config.log_file);
68 if (access(filename, R_OK) != 0)
71 snprintf(filename, len, "%s.%d", config.log_file, num);
75 fprintf(stderr, "No log file\n");
81 tmp = malloc((num+2)*sizeof(char *));
83 /* Got it, now process logs from last to first */
85 snprintf(filename, len, "%s.%d", config.log_file, num);
87 snprintf(filename, len, "%s", config.log_file);
89 tmp[i++] = strdup(filename);
91 /* Get next log file */
94 snprintf(filename, len, "%s.%d", config.log_file, num);
96 snprintf(filename, len, "%s", config.log_file);
100 free_config(&config);
103 // Terminate the list
105 au->source_list = tmp;
109 /* General functions that affect operation of the library */
110 auparse_state_t *auparse_init(ausource_t source, const void *b)
112 char **tmp, **bb = (char **)b, *buf = (char *)b;
116 auparse_state_t *au = malloc(sizeof(auparse_state_t));
123 au->source_list = NULL;
124 databuf_init(&au->databuf, 0, 0);
126 au->callback_user_data = NULL;
127 au->callback_user_data_destroy = NULL;
135 setup_log_file_array(au);
140 tmp = malloc(2*sizeof(char *));
143 au->source_list = tmp;
145 case AUSOURCE_FILE_ARRAY:
148 if (access(bb[n], R_OK))
152 tmp = malloc((n+1)*sizeof(char *));
154 tmp[i] = strdup(bb[i]);
156 au->source_list = tmp;
158 case AUSOURCE_BUFFER:
161 if (databuf_init(&au->databuf, len,
162 DATABUF_FLAG_PRESERVE_HEAD) < 0)
164 if (databuf_append(&au->databuf, buf, len) < 0)
167 case AUSOURCE_BUFFER_ARRAY:
169 for (n = 0; (buf = bb[n]); n++) {
171 if (bb[n][len-1] != '\n') {
177 if (databuf_init(&au->databuf, size,
178 DATABUF_FLAG_PRESERVE_HEAD) < 0)
180 for (n = 0; (buf = bb[n]); n++) {
182 if (databuf_append(&au->databuf, buf, len) < 0)
186 case AUSOURCE_DESCRIPTOR:
188 au->in = fdopen(n, "rm");
190 case AUSOURCE_FILE_POINTER:
194 if (databuf_init(&au->databuf, 0, 0) < 0) goto bad_exit;
208 aup_list_create(&au->le);
209 au->parse_state = EVENT_EMPTY;
211 au->find_field = NULL;
212 au->search_where = AUSEARCH_STOP_EVENT;
216 databuf_free(&au->databuf);
222 void auparse_add_callback(auparse_state_t *au, auparse_callback_ptr callback,
223 void *user_data, user_destroy user_destroy_func)
230 if (au->callback_user_data_destroy) {
231 (*au->callback_user_data_destroy)(au->callback_user_data);
232 au->callback_user_data = NULL;
235 au->callback = callback;
236 au->callback_user_data = user_data;
237 au->callback_user_data_destroy = user_destroy_func;
240 static void consume_feed(auparse_state_t *au, int flush)
242 while (auparse_next_event(au) > 0) {
244 (*au->callback)(au, AUPARSE_CB_EVENT_READY,
245 au->callback_user_data);
249 // FIXME: might need a call here to force auparse_next_event()
250 // to consume any partial data not fully consumed.
251 if (au->parse_state == EVENT_ACCUMULATING) {
252 // Emit the event, set event cursors to initial position
253 aup_list_first(&au->le);
254 aup_list_first_field(&au->le);
255 au->parse_state = EVENT_EMITTED;
257 (*au->callback)(au, AUPARSE_CB_EVENT_READY,
258 au->callback_user_data);
264 int auparse_feed(auparse_state_t *au, const char *data, size_t data_len)
266 if (databuf_append(&au->databuf, data, data_len) < 0)
272 int auparse_flush_feed(auparse_state_t *au)
278 // If there is data in the state machine, return 1
279 // Otherwise return 0 to indicate its empty
280 int auparse_feed_has_data(const auparse_state_t *au)
282 if (au->parse_state == EVENT_ACCUMULATING)
287 int auparse_reset(auparse_state_t *au)
294 aup_list_clear(&au->le);
295 au->parse_state = EVENT_EMPTY;
300 case AUSOURCE_FILE_ARRAY:
306 case AUSOURCE_DESCRIPTOR:
307 case AUSOURCE_FILE_POINTER:
311 case AUSOURCE_BUFFER:
312 case AUSOURCE_BUFFER_ARRAY:
316 databuf_reset(&au->databuf);
325 /* Add EXPR to AU, using HOW to select the combining operator.
326 On success, return 0.
327 On error, free EXPR set errno and return -1.
328 NOTE: EXPR is freed on error! */
329 static int add_expr(auparse_state_t *au, struct expr *expr, ausearch_rule_t how)
331 if (au->expr == NULL)
333 else if (how == AUSEARCH_RULE_CLEAR) {
339 e = expr_create_binary(how == AUSEARCH_RULE_OR ? EO_OR : EO_AND,
354 static int ausearch_add_item_internal(auparse_state_t *au, const char *field,
355 const char *op, const char *value, ausearch_rule_t how, unsigned op_eq,
360 // Make sure there's a field
364 // Make sure how is within range
365 if (how < AUSEARCH_RULE_CLEAR || how > AUSEARCH_RULE_AND)
368 // All pre-checks are done, build a rule
369 if (strcmp(op, "exists") == 0)
370 expr = expr_create_field_exists(field);
374 if (strcmp(op, "=") == 0)
376 else if (strcmp(op, "!=") == 0)
382 expr = expr_create_comparison(field, t_op, value);
386 if (add_expr(au, expr, how) != 0)
387 return -1; /* expr is freed by add_expr() */
395 int ausearch_add_item(auparse_state_t *au, const char *field, const char *op,
396 const char *value, ausearch_rule_t how)
398 return ausearch_add_item_internal(au, field, op, value, how, EO_RAW_EQ,
402 int ausearch_add_interpreted_item(auparse_state_t *au, const char *field,
403 const char *op, const char *value, ausearch_rule_t how)
405 return ausearch_add_item_internal(au, field, op, value, how,
406 EO_INTERPRETED_EQ, EO_INTERPRETED_NE);
409 int ausearch_add_timestamp_item_ex(auparse_state_t *au, const char *op,
410 time_t sec, unsigned milli, unsigned serial, ausearch_rule_t how)
412 static const struct {
427 for (i = 0; i < sizeof(ts_tab) / sizeof(*ts_tab); i++) {
428 if (strcmp(ts_tab[i].name, op) == 0)
433 t_op = ts_tab[i].value;
438 // Make sure how is within range
439 if (how < AUSEARCH_RULE_CLEAR || how > AUSEARCH_RULE_AND)
442 // All pre-checks are done, build a rule
443 expr = expr_create_timestamp_comparison_ex(t_op, sec, milli, serial);
446 if (add_expr(au, expr, how) != 0)
447 return -1; /* expr is freed by add_expr() */
455 int ausearch_add_timestamp_item(auparse_state_t *au, const char *op, time_t sec,
456 unsigned milli, ausearch_rule_t how)
458 return ausearch_add_timestamp_item_ex(au, op, sec, milli, 0, how);
461 int ausearch_add_expression(auparse_state_t *au, const char *expression,
462 char **error, ausearch_rule_t how)
466 if (how < AUSEARCH_RULE_CLEAR || how > AUSEARCH_RULE_AND)
469 expr = expr_parse(expression, error);
475 if (add_expr(au, expr, how) != 0)
476 goto err; /* expr is freed by add_expr() */
486 int ausearch_add_regex(auparse_state_t *au, const char *regexp)
490 // Make sure there's an expression
494 expr = expr_create_regexp_expression(regexp);
497 if (add_expr(au, expr, AUSEARCH_RULE_AND) != 0)
498 return -1; /* expr is freed by add_expr() */
506 int ausearch_set_stop(auparse_state_t *au, austop_t where)
508 if (where < AUSEARCH_STOP_EVENT || where > AUSEARCH_STOP_FIELD) {
513 au->search_where = where;
517 void ausearch_clear(auparse_state_t *au)
519 if (au->expr != NULL) {
523 au->search_where = AUSEARCH_STOP_EVENT;
526 void auparse_destroy(auparse_state_t *au)
528 aulookup_destroy_uid_list();
529 aulookup_destroy_gid_list();
533 if (au->source_list) {
535 while (au->source_list[n])
536 free(au->source_list[n++]);
537 free(au->source_list);
538 au->source_list = NULL;
544 aup_list_clear(&au->le);
545 au->parse_state = EVENT_EMPTY;
546 free(au->find_field);
547 au->find_field = NULL;
549 databuf_free(&au->databuf);
550 if (au->callback_user_data_destroy) {
551 (*au->callback_user_data_destroy)(au->callback_user_data);
552 au->callback_user_data = NULL;
561 /* alloc a new buffer, cur_buf which contains a null terminated line
562 * without a newline (note, this implies the line may be empty (strlen == 0)) if
563 * successfully read a blank line (e.g. containing only a single newline).
564 * cur_buf will have been newly allocated with malloc.
566 * Note: cur_buf will be freed the next time this routine is called if
567 * cur_buf is not NULL, callers who retain a reference to the cur_buf
568 * pointer will need to set cur_buf to NULL to cause the previous cur_buf
569 * allocation to persist.
572 * 1 if successful (errno == 0)
573 * 0 if non-blocking input unavailable (errno == 0)
574 * -1 if error (errno contains non-zero error code)
575 * -2 if EOF (errno == 0)
578 static int readline_file(auparse_state_t *au)
584 if (au->cur_buf != NULL) {
588 if (au->in == NULL) {
592 if ((rc = getline(&au->cur_buf, &n, au->in)) <= 0) {
593 // Note: getline always malloc's if lineptr==NULL or n==0,
594 // on failure malloc'ed memory is left uninitialized,
595 // caller must free it.
599 // Note: feof() does not set errno
601 // return EOF condition
605 // return error condition, error code in errno
608 p_last_char = au->cur_buf + (rc-1);
609 if (*p_last_char == '\n') { /* nuke newline */
618 /* malloc & copy a line into cur_buf from the internal buffer,
619 * next_buf. cur_buf will contain a null terminated line without a
620 * newline (note, this implies the line may be empty (strlen == 0)) if
621 * successfully read a blank line (e.g. containing only a single
624 * Note: cur_buf will be freed the next time this routine is called if
625 * cur_buf is not NULL, callers who retain a reference to the cur_buf
626 * pointer will need to set cur_buf to NULL to cause the previous cur_buf
627 * allocation to persist.
630 * 1 if successful (errno == 0)
631 * 0 if non-blocking input unavailable (errno == 0)
632 * -1 if error (errno contains non-zero error code)
633 * -2 if EOF (errno == 0)
636 static int readline_buf(auparse_state_t *au)
638 char *p_newline=NULL;
641 if (au->cur_buf != NULL) {
646 //if (debug) databuf_print(&au->databuf, 1, "readline_buf");
647 if (au->databuf.len == 0) {
648 // return EOF condition
653 if ((p_newline = strnchr(databuf_beg(&au->databuf), '\n',
654 au->databuf.len)) != NULL) {
655 line_len = p_newline - databuf_beg(&au->databuf);
658 au->cur_buf = malloc(line_len+1); // +1 for null terminator
659 if (au->cur_buf == NULL)
660 return -1; // return error condition, errno set
661 strncpy(au->cur_buf, databuf_beg(&au->databuf), line_len);
662 au->cur_buf[line_len] = 0;
664 if (databuf_advance(&au->databuf, line_len+1) < 0)
671 // return no data available
677 static int str2event(char *s, au_event_t *e)
682 ptr = strchr(s+10, ':');
684 e->serial = strtoul(ptr+1, NULL, 10);
690 ptr = strchr(s, '.');
692 e->milli = strtoul(ptr+1, NULL, 10);
698 e->sec = strtoul(s, NULL, 10);
704 /* Returns 0 on success and 1 on error */
705 static int extract_timestamp(const char *b, au_event_t *e)
712 tmp = strndupa(b, 340);
714 tmp = strndupa(b, 80);
715 ptr = audit_strsplit(tmp);
717 // Optionally grab the node - may or may not be included
719 e->host = strdup(ptr+5);
720 (void)audit_strsplit(NULL); // Bump along to the next one
722 // at this point we have type=
723 ptr = audit_strsplit(NULL);
728 ptr = strchr(ptr, '(');
730 // now we should be pointed at the timestamp
733 eptr = strchr(ptr, ')');
737 if (str2event(ptr, e) == 0)
740 // audit_msg(LOG_ERROR,
741 // "Error extracting time stamp (%s)\n",
745 // else we have a bad line
747 // else we have a bad line
749 // else we have a bad line
753 static int inline events_are_equal(au_event_t *e1, au_event_t *e2)
755 // Check time & serial first since its most likely way
756 // to spot 2 different events
757 if (!(e1->serial == e2->serial && e1->milli == e2->milli &&
760 // Hmm...same so far, check if both have a host, only a string
761 // compare can tell if they are the same. Otherwise, if only one
762 // of them have a host, they are definitely not the same. Its
763 // a boundary on daemon config.
764 if (e1->host && e2->host) {
765 if (strcmp(e1->host, e2->host))
767 } else if (e1->host || e2->host)
772 /* This function will figure out how to get the next line of input.
773 * storing it cur_buf. cur_buf will be NULL terminated but will not
774 * contain a trailing newline. This implies a successful read
775 * (result == 1) may result in a zero length cur_buf if a blank line
778 * cur_buf will have been allocated with malloc. The next time this
779 * routine is called if cur_buf is non-NULL cur_buf will be freed,
780 * thus if the caller wishes to retain a reference to malloc'ed
781 * cur_buf data it should copy the cur_buf pointer and set cur_buf to
785 * 1 if successful (errno == 0)
786 * 0 if non-blocking input unavailable (errno == 0)
787 * -1 if error (errno contains non-zero error code)
788 * -2 if EOF (errno == 0)
791 static int retrieve_next_line(auparse_state_t *au)
795 // If line was pushed back for re-reading return that
796 if (au->line_pushed) {
797 // Starting new event, clear previous event data,
798 // previous line is returned again for new parsing
806 case AUSOURCE_DESCRIPTOR:
807 case AUSOURCE_FILE_POINTER:
808 rc = readline_file(au);
809 if (rc > 0) au->line_number++;
813 case AUSOURCE_FILE_ARRAY:
814 // if the first time through, open file
815 if (au->list_idx == 0 && au->in == NULL &&
816 au->source_list != NULL) {
817 if (au->source_list[au->list_idx] == NULL) {
822 au->in = fopen(au->source_list[au->list_idx],
826 __fsetlocking(au->in, FSETLOCKING_BYCALLER);
829 // loop reading lines from a file
831 if ((rc = readline_file(au)) == -2) {
832 // end of file, open next file,
833 // try readline again
838 if (au->source_list[au->list_idx]) {
840 au->source_list[au->list_idx],
844 __fsetlocking(au->in,
845 FSETLOCKING_BYCALLER);
853 return -2; // return EOF
854 case AUSOURCE_BUFFER:
855 case AUSOURCE_BUFFER_ARRAY:
856 rc = readline_buf(au);
861 rc = readline_buf(au);
862 // No such thing as EOF for feed, translate EOF
863 // to data not available
873 return -1; /* should never reach here */
876 static void push_line(auparse_state_t *au)
883 * Functions that traverse events.
885 static int ausearch_reposition_cursors(auparse_state_t *au)
889 switch (au->search_where)
891 case AUSEARCH_STOP_EVENT:
892 aup_list_first(&au->le);
893 aup_list_first_field(&au->le);
895 case AUSEARCH_STOP_RECORD:
896 aup_list_first_field(&au->le);
898 case AUSEARCH_STOP_FIELD:
899 // do nothing - this is the normal stopping point
908 /* This is called during search once per each record. It walks the list
909 * of nvpairs and decides if a field matches. */
910 static int ausearch_compare(auparse_state_t *au)
914 r = aup_list_get_cur(&au->le);
916 return expr_eval(au, r, au->expr);
921 // Returns < 0 on error, 0 no data, > 0 success
922 int ausearch_next_event(auparse_state_t *au)
926 if (au->expr == NULL) {
930 if ((rc = auparse_first_record(au)) <= 0)
934 if ((rc = ausearch_compare(au)) > 0) {
935 ausearch_reposition_cursors(au);
939 } while ((rc = auparse_next_record(au)) > 0);
942 } while ((rc = auparse_next_event(au)) > 0);
949 // Brute force go to next event. Returns < 0 on error, 0 no data, > 0 success
950 int auparse_next_event(auparse_state_t *au)
955 if (au->parse_state == EVENT_EMITTED) {
956 // If the last call resulted in emitting event data then
957 // clear previous event data in preparation to accumulate
959 aup_list_clear(&au->le);
960 au->parse_state = EVENT_EMPTY;
963 // accumulate new event data
965 rc = retrieve_next_line(au);
966 if (debug) printf("next_line(%d) '%s'\n", rc, au->cur_buf);
967 if (rc == 0) return 0; // No data now
969 // We're at EOF, did we read any data previously?
970 // If so return data available, else return no data
972 if (au->parse_state == EVENT_ACCUMULATING) {
973 if (debug) printf("EOF, EVENT_EMITTED\n");
974 au->parse_state = EVENT_EMITTED;
975 return 1; // data is available
979 if (rc > 0) { // Input available
981 if (extract_timestamp(au->cur_buf, &event)) {
983 printf("Malformed line:%s\n",
987 if (au->parse_state == EVENT_EMPTY) {
988 // First record in new event, initialize event
991 "First record in new event, initialize event\n");
992 aup_list_set_event(&au->le, &event);
993 aup_list_append(&au->le, au->cur_buf,
994 au->list_idx, au->line_number);
995 au->parse_state = EVENT_ACCUMULATING;
997 } else if (events_are_equal(&au->le.e, &event)) {
998 // Accumulate data into existing event
1001 "Accumulate data into existing event\n");
1002 aup_list_append(&au->le, au->cur_buf,
1003 au->list_idx, au->line_number);
1004 au->parse_state = EVENT_ACCUMULATING;
1007 // New event, save input for next invocation
1010 "New event, save current input for next invocation, EVENT_EMITTED\n");
1012 // Emit the event, set event cursors to
1014 aup_list_first(&au->le);
1015 aup_list_first_field(&au->le);
1016 au->parse_state = EVENT_EMITTED;
1017 free((char *)event.host);
1018 return 1; // data is available
1020 free((char *)event.host);
1021 // Check to see if the event can be emitted due to EOE
1022 // or something we know is a single record event. At
1023 // this point, new record should be pointed at 'cur'
1024 if ((r = aup_list_get_cur(&au->le)) == NULL)
1026 if ( r->type == AUDIT_EOE ||
1027 r->type < AUDIT_FIRST_EVENT ||
1028 r->type >= AUDIT_FIRST_ANOM_MSG) {
1029 // Emit the event, set event cursors to
1031 aup_list_first(&au->le);
1032 aup_list_first_field(&au->le);
1033 au->parse_state = EVENT_EMITTED;
1034 return 1; // data is available
1036 } else { // Read error
1042 /* Accessors to event data */
1043 const au_event_t *auparse_get_timestamp(auparse_state_t *au)
1045 if (au && au->le.e.sec != 0)
1052 time_t auparse_get_time(auparse_state_t *au)
1055 return au->le.e.sec;
1061 unsigned int auparse_get_milli(auparse_state_t *au)
1064 return au->le.e.milli;
1070 unsigned long auparse_get_serial(auparse_state_t *au)
1073 return au->le.e.serial;
1079 // Gets the machine node name
1080 const char *auparse_get_node(auparse_state_t *au)
1082 if (au && au->le.e.host != NULL)
1083 return strdup(au->le.e.host);
1089 int auparse_node_compare(au_event_t *e1, au_event_t *e2)
1091 // If both have a host, only a string compare can tell if they
1092 // are the same. Otherwise, if only one of them have a host, they
1093 // are definitely not the same. Its a boundary on daemon config.
1094 if (e1->host && e2->host)
1095 return strcmp(e1->host, e2->host);
1105 int auparse_timestamp_compare(au_event_t *e1, au_event_t *e2)
1107 if (e1->sec > e2->sec)
1109 if (e1->sec < e2->sec)
1112 if (e1->milli > e2->milli)
1114 if (e1->milli < e2->milli)
1117 if (e1->serial > e2->serial)
1119 if (e1->serial < e2->serial)
1125 unsigned int auparse_get_num_records(auparse_state_t *au)
1127 return aup_list_get_cnt(&au->le);
1131 /* Functions that traverse records in the same event */
1132 int auparse_first_record(auparse_state_t *au)
1136 if (aup_list_get_cnt(&au->le) == 0) {
1137 rc = auparse_next_event(au);
1141 aup_list_first(&au->le);
1142 aup_list_first_field(&au->le);
1148 int auparse_next_record(auparse_state_t *au)
1150 if (aup_list_get_cnt(&au->le) == 0) {
1151 int rc = auparse_first_record(au);
1155 if (aup_list_next(&au->le))
1162 int auparse_goto_record_num(auparse_state_t *au, unsigned int num)
1164 /* Check if a request is out of range */
1165 if (num >= aup_list_get_cnt(&au->le))
1168 if (aup_list_goto_rec(&au->le, num) != NULL)
1175 /* Accessors to record data */
1176 int auparse_get_type(auparse_state_t *au)
1178 rnode *r = aup_list_get_cur(&au->le);
1186 const char *auparse_get_type_name(auparse_state_t *au)
1188 rnode *r = aup_list_get_cur(&au->le);
1190 return audit_msg_type_to_name(r->type);
1196 unsigned int auparse_get_line_number(auparse_state_t *au)
1198 rnode *r = aup_list_get_cur(&au->le);
1200 return r->line_number;
1206 const char *auparse_get_filename(auparse_state_t *au)
1211 case AUSOURCE_FILE_ARRAY:
1217 rnode *r = aup_list_get_cur(&au->le);
1219 if (r->list_idx < 0) return NULL;
1220 return au->source_list[r->list_idx];
1227 int auparse_first_field(auparse_state_t *au)
1229 return aup_list_first_field(&au->le);
1233 int auparse_next_field(auparse_state_t *au)
1235 rnode *r = aup_list_get_cur(&au->le);
1237 if (nvlist_next(&r->nv))
1246 unsigned int auparse_get_num_fields(auparse_state_t *au)
1248 rnode *r = aup_list_get_cur(&au->le);
1250 return nvlist_get_cnt(&r->nv);
1255 const char *auparse_get_record_text(auparse_state_t *au)
1257 rnode *r = aup_list_get_cur(&au->le);
1265 /* scan from current location to end of event */
1266 const char *auparse_find_field(auparse_state_t *au, const char *name)
1268 free(au->find_field);
1269 au->find_field = strdup(name);
1272 const char *cur_name;
1275 // look at current record before moving
1276 r = aup_list_get_cur(&au->le);
1279 cur_name = nvlist_get_cur_name(&r->nv);
1280 if (cur_name && strcmp(cur_name, name) == 0)
1281 return nvlist_get_cur_val(&r->nv);
1283 return auparse_find_field_next(au);
1288 /* Increment 1 location and then scan for next field */
1289 const char *auparse_find_field_next(auparse_state_t *au)
1291 if (au->find_field == NULL) {
1298 rnode *r = aup_list_get_cur(&au->le);
1299 while (r) { // For each record in the event...
1301 nvlist_next(&r->nv);
1304 if (nvlist_find_name(&r->nv, au->find_field))
1305 return nvlist_get_cur_val(&r->nv);
1306 r = aup_list_next(&au->le);
1308 aup_list_first_field(&au->le);
1315 /* Accessors to field data */
1316 const char *auparse_get_field_name(auparse_state_t *au)
1319 rnode *r = aup_list_get_cur(&au->le);
1321 return nvlist_get_cur_name(&r->nv);
1327 const char *auparse_get_field_str(auparse_state_t *au)
1330 rnode *r = aup_list_get_cur(&au->le);
1332 return nvlist_get_cur_val(&r->nv);
1337 int auparse_get_field_type(auparse_state_t *au)
1340 rnode *r = aup_list_get_cur(&au->le);
1342 return nvlist_get_cur_type(r);
1344 return AUPARSE_TYPE_UNCLASSIFIED;
1347 int auparse_get_field_int(auparse_state_t *au)
1349 const char *v = auparse_get_field_str(au);
1354 val = strtol(v, NULL, 10);
1363 const char *auparse_interpret_field(auparse_state_t *au)
1366 rnode *r = aup_list_get_cur(&au->le);
1368 return nvlist_interp_cur_val(r);