-
Notifications
You must be signed in to change notification settings - Fork 10
/
journal_send.cc
executable file
·110 lines (82 loc) · 2.94 KB
/
journal_send.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
// Down below you will find the most intuitive code you probably ever saw on the
// Internet. It just copies an ordinary JavaScript string array into an iovec
// and then finally calls sd_journal_sendv. Rocket science included!
#include <nan.h>
// Instead of the locations being this file, let the user define their own
// CODE_FILE, CODE_LINE and CODE_FUNC, via stack trace (ex: npm callsite)
#define SD_JOURNAL_SUPPRESS_LOCATION 1
#include <systemd/sd-journal.h>
// Priority is a special case as it needs to be taken from the syslog.h
// preprocessor definitions, which aren't available from JavaScript.
#include <syslog.h>
// Macros for int to string conversion
#define TO_STR_H(x) "" #x
#define TO_STR(x) TO_STR_H(x)
// Create an array of all Syslog priority numbers
#define SYSLOG_PRIO_CNT 8
const char *const syslogPrio[] = {
TO_STR( LOG_EMERG ), // jsPrio: 0
TO_STR( LOG_ALERT ), // jsPrio: 1
TO_STR( LOG_CRIT ), // jsPrio: 2
TO_STR( LOG_ERR ), // jsPrio: 3
TO_STR( LOG_WARNING ), // jsPrio: 4
TO_STR( LOG_NOTICE ), // jsPrio: 5
TO_STR( LOG_INFO ), // jsPrio: 6
TO_STR( LOG_DEBUG ) // jsPrio: 7
};
#define PRIO_FIELD_NAME "PRIORITY="
#define PRIO_FIELD_NAME_LEN 9
void send( const Nan::FunctionCallbackInfo<v8::Value>& args ) {
int argc = args.Length();
struct iovec iov[ argc ];
// Make sure nobody forgot the arguments
if( argc < 2 ) {
Nan::ThrowTypeError( "Not enough arugments" );
return;
}
// Make sure first argument is a number
if( ! args[0]->IsNumber() ) {
Nan::ThrowTypeError( "First argument must be a number" );
return;
}
// Get the priority
int64_t jsPrio = ( args[0]->ToInteger() )->Value();
if( jsPrio < 0 || jsPrio >= SYSLOG_PRIO_CNT ) {
Nan::ThrowTypeError( "Unknown priority" );
return;
}
// Convert JavaScript priority to Syslog priority
size_t strLen = PRIO_FIELD_NAME_LEN + strlen( syslogPrio[jsPrio] );
iov[0].iov_len = strLen;
iov[0].iov_base = (char*) malloc( strLen + 1 );
snprintf( (char*) iov[0].iov_base, strLen + 1,
"%s%s", PRIO_FIELD_NAME, syslogPrio[jsPrio] );
// Copy all remaining arguments to the iovec
for( int i = 1; i < argc; i++ ) {
// First ensure that the argument is a string
if( ! args[i]->IsString() ) {
Nan::ThrowTypeError( "Arguments must be strings" );
return;
}
// Put string into the iovec
v8::Local<v8::String> arg = args[i]->ToString();
iov[i].iov_len = arg->Length();
iov[i].iov_base = (char*) malloc( arg->Length() + 1 );
arg->WriteUtf8( (char*) iov[i].iov_base, iov[i].iov_len );
}
// Send to journald
int ret = sd_journal_sendv( iov, argc );
// Free the memory again
for( int i = 0; i < argc; i++ ) {
free( iov[i].iov_base );
}
v8::Local<v8::Number> returnValue = Nan::New( ret );
args.GetReturnValue().Set( returnValue );
}
void init( v8::Local<v8::Object> exports ) {
exports->Set(
Nan::New("send").ToLocalChecked(),
Nan::New<v8::FunctionTemplate>( send )->GetFunction()
);
}
NODE_MODULE( journal_send, init )