static int journal_seek_cursor (lua_State *L) { sd_journal *j = check_journal(L, 1); const char *cursor = luaL_checkstring(L, 2); int err = sd_journal_seek_cursor(j, cursor); if (err != 0) return handle_error(L, -err); lua_pushboolean(L, 1); return 1; }
int open_journal_for_upload(Uploader *u, sd_journal *j, const char *cursor, bool after_cursor, bool follow) { int fd, r, events; u->journal = j; sd_journal_set_data_threshold(j, 0); if (follow) { fd = sd_journal_get_fd(j); if (fd < 0) return log_error_errno(fd, "sd_journal_get_fd failed: %m"); events = sd_journal_get_events(j); r = sd_journal_reliable_fd(j); assert(r >= 0); if (r > 0) u->timeout = -1; else u->timeout = JOURNAL_UPLOAD_POLL_TIMEOUT; r = sd_event_add_io(u->events, &u->input_event, fd, events, dispatch_journal_input, u); if (r < 0) return log_error_errno(r, "Failed to register input event: %m"); log_debug("Listening for journal events on fd:%d, timeout %d", fd, u->timeout == (uint64_t) -1 ? -1 : (int) u->timeout); } else log_debug("Not listening for journal events."); if (cursor) { r = sd_journal_seek_cursor(j, cursor); if (r < 0) { return log_error_errno(r, "Failed to seek to cursor %s: %m", cursor); } } return process_journal_input(u, 1 + !!after_cursor); }
int systemd_journal_decoder(int eventarray, void *buffer, size_t size, struct timeval *timestamp, void *data) { int sts; pmAtomValue atom; enum journald_field_encoding jfe = * (enum journald_field_encoding *) data; sts = pmdaEventAddRecord(eventarray, timestamp, PM_EVENT_FLAG_POINT); if (sts < 0) return sts; /* Go to the cursor point enqueued for this client. The buffer is already \0-terminated. */ sts = sd_journal_seek_cursor(journald_context_seeky, (char*) buffer); if (sts < 0) { /* But see RHBZ #876654. */ return /* sts */ 0; } sts = sd_journal_next(journald_context_seeky); if (sts < 0) return sts; if (sts == 0) return -ENODATA; /* event got lost between cursor-recording and now */ /* Add the _CURSOR implicit journal field. */ atom.cp = buffer; sts = pmdaEventAddParam(eventarray, METRICTAB_JOURNAL_CURSOR_PMID, PM_TYPE_STRING, &atom); /* Add all the explicit journal fields. */ while (1) { const void *data; size_t data_len; if (sts < 0) break; sts = sd_journal_enumerate_data(journald_context_seeky, &data, &data_len); if (sts <= 0) break; /* Infer string upon absence of embedded \0's. */ if (jfe == JFE_STRING_BLOB_AUTO && (memchr (data, '\0', data_len) == NULL)) { /* Unfortunately, data may not be \0-terminated, so we can't simply pass it to atom.cp. We need to copy the bad boy first. */ atom.cp = strndup(data, data_len); if (atom.cp == NULL) sts = -ENOMEM; else { sts = pmdaEventAddParam(eventarray, METRICTAB_JOURNAL_STRING_PMID, PM_TYPE_STRING, &atom); free (atom.cp); } /* NB: we assume libpcp_pmda will not free() the field. */ } else { pmValueBlock *aggr = (pmValueBlock *)malloc(PM_VAL_HDR_SIZE + data_len); if (aggr == NULL) sts = -ENOMEM; else { aggr->vtype = PM_TYPE_AGGREGATE; if (PM_VAL_HDR_SIZE + data_len >= 1<<24) aggr->vlen = (1U<<24) - 1; /* vlen is a :24 bit field */ else aggr->vlen = PM_VAL_HDR_SIZE + data_len; memcpy (aggr->vbuf, data, data_len); atom.vbp = aggr; sts = pmdaEventAddParam(eventarray, METRICTAB_JOURNAL_BLOB_PMID, PM_TYPE_AGGREGATE, &atom); /* NB: we assume libpcp_pmda will free() aggr. */ } } } return sts < 0 ? sts : 1; /* added one event array */ }
int systemd_journal_event_filter (void *rp, void *data, size_t size) { int rc; struct uid_gid_tuple* ugt = rp; assert (ugt == & ctxtab[pmdaGetContext()]); if (pmDebug & DBG_TRACE_APPL0) __pmNotifyErr(LOG_DEBUG, "filter (%d) uid=%d gid=%d data=%p bytes=%u\n", pmdaGetContext(), ugt->uid, ugt->gid, data, (unsigned)size); /* The data/size pair gives the object in the event queue, i.e., the systemd journal cursor string. It has not yet been turned into a PM_TYPE_EVENT tuple yet, and if we have our way, it won't be (for non-participating clients). */ /* The general filtering idea is to only feed journal records to clients if their uid matches the _UID=NNN field -or- gid matches _GID=MMM -or- the client is highly authenticated (wildcard_p) -or- per-uid filtering was turned off at the pmda level. */ /* Reminder: function rc == 0 passes the filter. */ /* Unfiltered? Everyone gets egg soup! */ if (! uid_gid_filter_p) return 0; if (pmDebug & DBG_TRACE_APPL0) __pmNotifyErr(LOG_DEBUG, "filter (%d) uid%s%d gid%s%d wildcard=%d\n", pmdaGetContext(), ugt->uid_p?"=":"?", ugt->uid, ugt->gid_p?"=":"?", ugt->gid, ugt->wildcard_p); /* Superuser? May we offer some goulash? */ if (ugt->wildcard_p) return 0; /* Unauthenticated context? No soup for you! */ if (! ugt->uid_p && ! ugt->gid_p) return 1; /* OK, we need to take a look at the journal record in question. */ if (pmDebug & DBG_TRACE_APPL0) __pmNotifyErr(LOG_DEBUG, "filter cursor=%s\n", (const char*) data); (void) size; /* already known \0-terminated */ rc = sd_journal_seek_cursor(journald_context_seeky, (char*) data); if (rc < 0) { __pmNotifyErr(LOG_ERR, "filter cannot seek to cursor=%s\n", (const char*) data); return 1; /* No point trying again in systemd_journal_decoder. */ } rc = sd_journal_next(journald_context_seeky); if (rc < 0) { __pmNotifyErr(LOG_ERR, "filter cannot advance to next\n"); return 1; /* No point trying again in systemd_journal_decoder. */ } if (ugt->uid_p) { char *uid_str = my_sd_journal_get_data(journald_context_seeky, "_UID"); if (uid_str) { int uid = atoi (& uid_str[5]); /* skip over _UID= */ free (uid_str); if (uid == ugt->uid) return 0; /* You're a somebody. Here's a bowl of stew. */ } } if (ugt->gid_p) { char *gid_str = my_sd_journal_get_data(journald_context_seeky, "_GID"); if (gid_str) { int gid = atoi (& gid_str[5]); /* skip over _GID= */ free (gid_str); if (gid == ugt->gid) return 0; /* You're with pals. Here's a bowl of miso. */ } } /* No soup for you! */ return 1; }