6
6
Copyright 2011 Lennart Poettering
8
8
systemd is free software; you can redistribute it and/or modify it
9
under the terms of the GNU General Public License as published by
10
the Free Software Foundation; either version 2 of the License, or
9
under the terms of the GNU Lesser General Public License as published by
10
the Free Software Foundation; either version 2.1 of the License, or
11
11
(at your option) any later version.
13
13
systemd is distributed in the hope that it will be useful, but
14
14
WITHOUT ANY WARRANTY; without even the implied warranty of
15
15
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
General Public License for more details.
16
Lesser General Public License for more details.
18
You should have received a copy of the GNU General Public License
18
You should have received a copy of the GNU Lesser General Public License
19
19
along with systemd; If not, see <http://www.gnu.org/licenses/>.
33
36
#define SNDBUF_SIZE (8*1024*1024)
38
#define ALLOCA_CODE_FUNC(f, func) \
41
const char *_func = (func); \
43
_fl = strlen(_func) + 1; \
44
*_f = alloca(_fl + 10); \
45
memcpy(*_f, "CODE_FUNC=", 10); \
46
memcpy(*_f + 10, _func, _fl); \
35
49
/* We open a single fd, and we'll share it with the current process,
36
50
* all its threads, and all its subprocesses. This means we need to
37
51
* initialize it atomically, and need to operate on it atomically
154
216
* be a tmpfs, and one that is available from early boot on
155
217
* and where unprivileged users can create files. */
156
218
char path[] = "/dev/shm/journal.XXXXXX";
161
w = alloca(sizeof(struct iovec) * n * 5);
219
bool have_syslog_identifier = false;
221
if (_unlikely_(!iov))
224
if (_unlikely_(n <= 0))
227
w = alloca(sizeof(struct iovec) * n * 5 + 3);
162
228
l = alloca(sizeof(uint64_t) * n);
164
230
for (i = 0; i < n; i++) {
167
if (!iov[i].iov_base ||
233
if (_unlikely_(!iov[i].iov_base || iov[i].iov_len <= 1))
171
236
c = memchr(iov[i].iov_base, '=', iov[i].iov_len);
172
if (!c || c == iov[i].iov_base)
237
if (_unlikely_(!c || c == iov[i].iov_base))
240
have_syslog_identifier = have_syslog_identifier ||
241
(c == (char *) iov[i].iov_base + 17 &&
242
memcmp(iov[i].iov_base, "SYSLOG_IDENTIFIER", 17) == 0);
175
244
nl = memchr(iov[i].iov_base, '\n', iov[i].iov_len);
246
if (_unlikely_(nl < c))
180
249
/* Already includes a newline? Bummer, then
205
274
IOVEC_SET_STRING(w[j++], "\n");
277
if (!have_syslog_identifier &&
278
string_is_safe(program_invocation_short_name)) {
280
/* Implicitly add program_invocation_short_name, if it
281
* is not set explicitly. We only do this for
282
* program_invocation_short_name, and nothing else
283
* since everything else is much nicer to retrieve
284
* from the outside. */
286
IOVEC_SET_STRING(w[j++], "SYSLOG_IDENTIFIER=");
287
IOVEC_SET_STRING(w[j++], program_invocation_short_name);
288
IOVEC_SET_STRING(w[j++], "\n");
208
291
fd = journal_fd();
292
if (_unlikely_(fd < 0))
355
static int fill_iovec_perror_and_send(const char *message, int skip, struct iovec iov[]) {
359
k = isempty(message) ? 0 : strlen(message) + 2;
367
j = strerror_r(_saved_errno_, buffer + 8 + k, n - 8 - k);
369
char error[6 + 10 + 1]; /* for a 32bit value */
371
if (j != buffer + 8 + k)
372
memmove(buffer + 8 + k, j, strlen(j)+1);
374
memcpy(buffer, "MESSAGE=", 8);
377
memcpy(buffer + 8, message, k - 2);
378
memcpy(buffer + 8 + k - 2, ": ", 2);
381
snprintf(error, sizeof(error), "ERRNO=%u", _saved_errno_);
384
IOVEC_SET_STRING(iov[skip+0], "PRIORITY=3");
385
IOVEC_SET_STRING(iov[skip+1], buffer);
386
IOVEC_SET_STRING(iov[skip+2], error);
388
return sd_journal_sendv(iov, skip + 3);
398
_public_ int sd_journal_perror(const char *message) {
399
struct iovec iovec[3];
401
return fill_iovec_perror_and_send(message, 0, iovec);
272
404
_public_ int sd_journal_stream_fd(const char *identifier, int priority, int level_prefix) {
273
405
union sockaddr_union sa;
469
_public_ int sd_journal_print_with_location(int priority, const char *file, const char *line, const char *func, const char *format, ...) {
473
va_start(ap, format);
474
r = sd_journal_printv_with_location(priority, file, line, func, format, ap);
480
_public_ int sd_journal_printv_with_location(int priority, const char *file, const char *line, const char *func, const char *format, va_list ap) {
481
char buffer[8 + LINE_MAX], p[11];
485
if (priority < 0 || priority > 7)
488
if (_unlikely_(!format))
491
snprintf(p, sizeof(p), "PRIORITY=%i", priority & LOG_PRIMASK);
494
memcpy(buffer, "MESSAGE=", 8);
495
vsnprintf(buffer+8, sizeof(buffer) - 8, format, ap);
496
char_array_0(buffer);
498
/* func is initialized from __func__ which is not a macro, but
499
* a static const char[], hence cannot easily be prefixed with
500
* CODE_FUNC=, hence let's do it manually here. */
501
ALLOCA_CODE_FUNC(f, func);
504
IOVEC_SET_STRING(iov[0], buffer);
505
IOVEC_SET_STRING(iov[1], p);
506
IOVEC_SET_STRING(iov[2], file);
507
IOVEC_SET_STRING(iov[3], line);
508
IOVEC_SET_STRING(iov[4], f);
510
return sd_journal_sendv(iov, ELEMENTSOF(iov));
513
_public_ int sd_journal_send_with_location(const char *file, const char *line, const char *func, const char *format, ...) {
516
struct iovec *iov = NULL;
519
va_start(ap, format);
520
i = fill_iovec_sprintf(format, ap, 3, &iov);
523
if (_unlikely_(i < 0)) {
528
ALLOCA_CODE_FUNC(f, func);
530
IOVEC_SET_STRING(iov[0], file);
531
IOVEC_SET_STRING(iov[1], line);
532
IOVEC_SET_STRING(iov[2], f);
534
r = sd_journal_sendv(iov, i);
537
for (j = 3; j < i; j++)
538
free(iov[j].iov_base);
545
_public_ int sd_journal_sendv_with_location(
546
const char *file, const char *line,
548
const struct iovec *iov, int n) {
553
if (_unlikely_(!iov))
556
if (_unlikely_(n <= 0))
559
niov = alloca(sizeof(struct iovec) * (n + 3));
560
memcpy(niov, iov, sizeof(struct iovec) * n);
562
ALLOCA_CODE_FUNC(f, func);
564
IOVEC_SET_STRING(niov[n++], file);
565
IOVEC_SET_STRING(niov[n++], line);
566
IOVEC_SET_STRING(niov[n++], f);
568
return sd_journal_sendv(niov, n);
571
_public_ int sd_journal_perror_with_location(
572
const char *file, const char *line,
574
const char *message) {
579
ALLOCA_CODE_FUNC(f, func);
581
IOVEC_SET_STRING(iov[0], file);
582
IOVEC_SET_STRING(iov[1], line);
583
IOVEC_SET_STRING(iov[2], f);
585
return fill_iovec_perror_and_send(message, 3, iov);