Skip to content

Commit fc10d0b

Browse files
committed
pacctformat: a new plugin to handle Process Accounting files
This plugin makes it possible to read/follow process accounting files on Linux.
1 parent c9dbb50 commit fc10d0b

9 files changed

+217
-2
lines changed

configure.in

+1
Original file line numberDiff line numberDiff line change
@@ -819,6 +819,7 @@ AC_OUTPUT(dist.conf
819819
src/csvparser/Makefile
820820
src/confgen/Makefile
821821
src/syslogformat/Makefile
822+
src/pacctformat/Makefile
822823
scripts/Makefile
823824
scripts/update-patterndb
824825
doc/Makefile

scl/Makefile.am

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
SCL_SUBDIRS = system
1+
SCL_SUBDIRS = system pacct
22
SCL_CONFIGS = scl.conf modules.conf syslog-ng.conf
33
EXTRA_DIST = ./scl.conf $(SCL_SUBDIRS)
44

scl/pacct/plugin.conf

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#############################################################################
2+
# Copyright (c) 2010 BalaBit IT Ltd, Budapest, Hungary
3+
#
4+
# This program is free software; you can redistribute it and/or modify it
5+
# under the terms of the GNU General Public License version 2 as published
6+
# by the Free Software Foundation.
7+
#
8+
# Note that this permission is granted for only version 2 of the GPL.
9+
#
10+
# As an additional exemption you are allowed to compile & link against the
11+
# OpenSSL libraries as published by the OpenSSL project. See the file
12+
# COPYING for details.
13+
#
14+
# This program is distributed in the hope that it will be useful,
15+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
# GNU General Public License for more details.
18+
#
19+
# You should have received a copy of the GNU General Public License
20+
# along with this program; if not, write to the Free Software
21+
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22+
#
23+
#############################################################################
24+
25+
@module pacctformat
26+
27+
block source pacct(file("/var/log/account/pacct") follow-freq(1)) {
28+
file("`file`" follow-freq(`follow-freq`) format("pacct"));
29+
};

scl/scl.conf

+1
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,4 @@
3232

3333
@include 'modules.conf'
3434
@include 'scl/system/plugin.conf'
35+
@include 'scl/pacct/plugin.conf'

src/Makefile.am

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
SUBDIRS = . afsocket afsql afstreams affile afprog afuser dbparser csvparser confgen syslogformat dummy
1+
SUBDIRS = . afsocket afsql afstreams affile afprog afuser dbparser csvparser confgen syslogformat pacctformat dummy
22
YFLAGS=@YFLAGS@
33

44
export top_srcdir

src/pacctformat/Makefile.am

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
plugindir = @plugindir@
2+
AM_CPPFLAGS = -I$(top_srcdir)/src -I..
3+
export top_srcdir
4+
5+
plugin_LTLIBRARIES := libpacctformat.la
6+
libpacctformat_la_SOURCES = \
7+
pacct-format.c pacct-format.h pacct-format-plugin.c
8+
9+
libpacctformat_la_CPPFLAGS = $(AM_CPPFLAGS)
10+
11+
include $(top_srcdir)/build/lex-rules.am

src/pacctformat/pacct-format-plugin.c

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
2+
#include "pacct-format.h"
3+
#include "messages.h"
4+
#include "plugin.h"
5+
6+
static MsgFormatHandler *
7+
pacct_format_construct(Plugin *self, GlobalConfig *cfg, gint plugin_type, const gchar *plugin_name)
8+
{
9+
return &pacct_handler;
10+
}
11+
12+
static Plugin pacct_format_plugin =
13+
{
14+
.type = LL_CONTEXT_FORMAT,
15+
.name = "pacct",
16+
.construct = &pacct_format_construct,
17+
};
18+
19+
gboolean
20+
syslogng_module_init(GlobalConfig *cfg, CfgArgs *args)
21+
{
22+
plugin_register(cfg, &pacct_format_plugin, 1);
23+
return TRUE;
24+
}

src/pacctformat/pacct-format.c

+141
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
#include "pacct-format.h"
2+
#include "logmsg.h"
3+
4+
/* we're using the Linux header as the glibc one is incomplete */
5+
#include <linux/acct.h>
6+
7+
typedef struct acct_v3 acct_t;
8+
9+
#define PACCT_PREFIX ".pacct."
10+
11+
static gboolean handles_registered = FALSE;
12+
static NVHandle handle_ac_flag;
13+
static NVHandle handle_ac_tty;
14+
static NVHandle handle_ac_exitcode;
15+
static NVHandle handle_ac_uid;
16+
static NVHandle handle_ac_gid;
17+
static NVHandle handle_ac_pid;
18+
static NVHandle handle_ac_ppid;
19+
static NVHandle handle_ac_btime;
20+
static NVHandle handle_ac_etime;
21+
static NVHandle handle_ac_utime;
22+
static NVHandle handle_ac_stime;
23+
static NVHandle handle_ac_mem;
24+
static NVHandle handle_ac_io;
25+
static NVHandle handle_ac_rw;
26+
static NVHandle handle_ac_minflt;
27+
static NVHandle handle_ac_majflt;
28+
static NVHandle handle_ac_swaps;
29+
static NVHandle handle_ac_comm;
30+
31+
#define PACCT_REGISTER(field) \
32+
do { \
33+
handle_##field = log_msg_get_value_handle(PACCT_PREFIX # field); \
34+
} while(0)
35+
36+
#define PACCT_CONVERT_NOP(x) (x)
37+
38+
#define PACCT_CONVERT_COMP_TO_ULONG(x) ((ulong) ((x & 0x1fff) << (((x >> 13) & 0x7) * 3)))
39+
40+
#define PACCT_FORMAT_CONVERT(msg, rec, field, format, convert) \
41+
do { \
42+
gchar __buf[64]; \
43+
gsize __len; \
44+
\
45+
__len = g_snprintf(__buf, sizeof(__buf), format, convert(rec->field)); \
46+
log_msg_set_value(msg, handle_##field, __buf, __len); \
47+
} while (0)
48+
49+
#define PACCT_FORMAT(msg, rec, field, format) \
50+
PACCT_FORMAT_CONVERT(msg, rec, field, format, PACCT_CONVERT_NOP)
51+
52+
void
53+
pacct_register_handles(void)
54+
{
55+
PACCT_REGISTER(ac_flag);
56+
PACCT_REGISTER(ac_tty);
57+
PACCT_REGISTER(ac_exitcode);
58+
PACCT_REGISTER(ac_uid);
59+
PACCT_REGISTER(ac_gid);
60+
PACCT_REGISTER(ac_pid);
61+
PACCT_REGISTER(ac_ppid);
62+
PACCT_REGISTER(ac_btime);
63+
PACCT_REGISTER(ac_etime);
64+
PACCT_REGISTER(ac_utime);
65+
PACCT_REGISTER(ac_stime);
66+
PACCT_REGISTER(ac_mem);
67+
PACCT_REGISTER(ac_io);
68+
PACCT_REGISTER(ac_rw);
69+
PACCT_REGISTER(ac_minflt);
70+
PACCT_REGISTER(ac_majflt);
71+
PACCT_REGISTER(ac_swaps);
72+
PACCT_REGISTER(ac_comm);
73+
}
74+
75+
void
76+
pacct_format_handler(MsgFormatOptions *options, const guchar *data, gsize length, LogMessage *msg)
77+
{
78+
acct_t *rec;
79+
gsize len;
80+
81+
if (length < sizeof(*rec))
82+
{
83+
gchar *buf;
84+
85+
buf = g_strdup_printf("Error parsing process accounting record, record too small; rec_size='%d', expected_size='%d'",
86+
(gint) length, (gint) sizeof(*rec));
87+
log_msg_set_value(msg, LM_V_MESSAGE, buf, -1);
88+
g_free(buf);
89+
return;
90+
}
91+
rec = (acct_t *) data;
92+
if (rec->ac_version != 3)
93+
{
94+
gchar *buf;
95+
96+
buf = g_strdup_printf("Error parsing process accounting record, only the v3 format is supported; version='%d'",
97+
rec->ac_version);
98+
log_msg_set_value(msg, LM_V_MESSAGE, buf, -1);
99+
g_free(buf);
100+
return;
101+
}
102+
if (G_UNLIKELY(!handles_registered))
103+
{
104+
pacct_register_handles();
105+
handles_registered = TRUE;
106+
}
107+
PACCT_FORMAT(msg, rec, ac_flag, "%02x");
108+
PACCT_FORMAT(msg, rec, ac_tty, "%u");
109+
PACCT_FORMAT(msg, rec, ac_exitcode, "%u");
110+
PACCT_FORMAT(msg, rec, ac_uid, "%u");
111+
PACCT_FORMAT(msg, rec, ac_gid, "%u");
112+
PACCT_FORMAT(msg, rec, ac_pid, "%u");
113+
PACCT_FORMAT(msg, rec, ac_ppid, "%u");
114+
PACCT_FORMAT_CONVERT(msg, rec, ac_btime, "%lu.00", PACCT_CONVERT_COMP_TO_ULONG);
115+
PACCT_FORMAT(msg, rec, ac_etime, "%9.2f");
116+
PACCT_FORMAT_CONVERT(msg, rec, ac_utime, "%lu.00", PACCT_CONVERT_COMP_TO_ULONG);
117+
PACCT_FORMAT_CONVERT(msg, rec, ac_stime, "%lu.00", PACCT_CONVERT_COMP_TO_ULONG);
118+
PACCT_FORMAT_CONVERT(msg, rec, ac_mem, "%lu", PACCT_CONVERT_COMP_TO_ULONG);
119+
PACCT_FORMAT_CONVERT(msg, rec, ac_io, "%lu", PACCT_CONVERT_COMP_TO_ULONG);
120+
PACCT_FORMAT_CONVERT(msg, rec, ac_rw, "%lu", PACCT_CONVERT_COMP_TO_ULONG);
121+
PACCT_FORMAT_CONVERT(msg, rec, ac_minflt, "%lu", PACCT_CONVERT_COMP_TO_ULONG);
122+
PACCT_FORMAT_CONVERT(msg, rec, ac_majflt, "%lu", PACCT_CONVERT_COMP_TO_ULONG);
123+
PACCT_FORMAT_CONVERT(msg, rec, ac_swaps, "%lu", PACCT_CONVERT_COMP_TO_ULONG);
124+
if (rec->ac_comm[ACCT_COMM - 1] == 0)
125+
len = strlen(rec->ac_comm);
126+
else
127+
len = ACCT_COMM;
128+
log_msg_set_value(msg, handle_ac_comm, rec->ac_comm, len);
129+
}
130+
131+
LogProto *
132+
pacct_construct_proto(MsgFormatOptions *options, LogTransport *transport, guint flags)
133+
{
134+
return log_proto_record_server_new(transport, sizeof(acct_t), flags | LPRS_BINARY);
135+
}
136+
137+
MsgFormatHandler pacct_handler =
138+
{
139+
.construct_proto = pacct_construct_proto,
140+
.parse = &pacct_format_handler
141+
};

src/pacctformat/pacct-format.h

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#ifndef PACCT_FORMAT_H_INCLUDED
2+
#define PACCT_FORMAT_H_INCLUDED
3+
4+
#include "msg-format.h"
5+
6+
extern MsgFormatHandler pacct_handler;
7+
8+
#endif

0 commit comments

Comments
 (0)