mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-11-10 03:16:17 +01:00
gio-launch-desktop: Redirect stdout, stderr to systemd Journal
This prevents a launched process's output from being mixed up with the output of the parent process, which can lead to the wrong program being blamed for warning messages. Signed-off-by: Simon McVittie <smcv@collabora.com>
This commit is contained in:
parent
ae15c800ce
commit
763643ceaa
@ -1,6 +1,10 @@
|
|||||||
/* GIO - GLib Input, Output and Streaming Library
|
/* GIO - GLib Input, Output and Streaming Library
|
||||||
*
|
*
|
||||||
|
* Copyright 2004 Ximian Inc.
|
||||||
|
* Copyright 2011-2022 systemd contributors
|
||||||
* Copyright (C) 2018 Endless Mobile, Inc.
|
* Copyright (C) 2018 Endless Mobile, Inc.
|
||||||
|
* Copyright 2022 Collabora Ltd.
|
||||||
|
*
|
||||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
@ -33,6 +37,193 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#if defined(__linux__) && !defined(__BIONIC__)
|
||||||
|
#include <alloca.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <syslog.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* write_all:
|
||||||
|
* @fd: a file descriptor
|
||||||
|
* @vbuf: a buffer
|
||||||
|
* @to_write: length of @vbuf
|
||||||
|
*
|
||||||
|
* Write all bytes from @vbuf to @fd, blocking if necessary.
|
||||||
|
*
|
||||||
|
* Returns: 0 on success, -1 with errno set on failure
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
write_all (int fd, const void *vbuf, size_t to_write)
|
||||||
|
{
|
||||||
|
const char *buf = vbuf;
|
||||||
|
|
||||||
|
while (to_write > 0)
|
||||||
|
{
|
||||||
|
ssize_t count = write (fd, buf, to_write);
|
||||||
|
if (count < 0)
|
||||||
|
{
|
||||||
|
if (errno != EINTR)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
to_write -= count;
|
||||||
|
buf += count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* journal_stream_fd:
|
||||||
|
* @identifier: identifier (syslog tag) for logged messages
|
||||||
|
* @priority: a priority between `LOG_EMERG` and `LOG_DEBUG` inclusive
|
||||||
|
* @level_prefix: if nonzero, journald will interpret prefixes like <0>
|
||||||
|
* as specifying the priority for a line
|
||||||
|
*
|
||||||
|
* Reimplementation of sd_journal_stream_fd(), to avoid having to link
|
||||||
|
* gio-launch-desktop to libsystemd.
|
||||||
|
*
|
||||||
|
* Note that unlike the libsystemd version, this reports errors by returning
|
||||||
|
* -1 with errno set.
|
||||||
|
*
|
||||||
|
* Returns: a non-negative fd number, or -1 with errno set on error
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
journal_stream_fd (const char *identifier,
|
||||||
|
int priority,
|
||||||
|
int level_prefix)
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct sockaddr sa;
|
||||||
|
struct sockaddr_un un;
|
||||||
|
} sa =
|
||||||
|
{
|
||||||
|
.un.sun_family = AF_UNIX,
|
||||||
|
.un.sun_path = "/run/systemd/journal/stdout",
|
||||||
|
};
|
||||||
|
socklen_t salen;
|
||||||
|
char *header;
|
||||||
|
int fd;
|
||||||
|
size_t l;
|
||||||
|
int saved_errno;
|
||||||
|
/* Arbitrary large size for the sending buffer, from systemd */
|
||||||
|
int large_buffer_size = 8 * 1024 * 1024;
|
||||||
|
|
||||||
|
static_assert (LOG_EMERG == 0, "Linux ABI defines LOG_EMERG");
|
||||||
|
static_assert (LOG_DEBUG == 7, "Linux ABI defines LOG_DEBUG");
|
||||||
|
|
||||||
|
fd = socket (AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
|
||||||
|
|
||||||
|
if (fd < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
salen = offsetof (struct sockaddr_un, sun_path) + strlen (sa.un.sun_path) + 1;
|
||||||
|
|
||||||
|
if (connect (fd, &sa.sa, salen) < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (shutdown (fd, SHUT_RD) < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
(void) setsockopt (fd, SOL_SOCKET, SO_SNDBUF, &large_buffer_size,
|
||||||
|
(socklen_t) sizeof (large_buffer_size));
|
||||||
|
|
||||||
|
if (identifier == NULL)
|
||||||
|
identifier = "";
|
||||||
|
|
||||||
|
if (priority < 0)
|
||||||
|
priority = 0;
|
||||||
|
|
||||||
|
if (priority > 7)
|
||||||
|
priority = 7;
|
||||||
|
|
||||||
|
l = strlen (identifier);
|
||||||
|
header = alloca (l + 1 /* identifier, newline */
|
||||||
|
+ 1 /* empty unit ID, newline */
|
||||||
|
+ 2 /* priority, newline */
|
||||||
|
+ 2 /* level prefix, newline */
|
||||||
|
+ 2 /* don't forward to syslog */
|
||||||
|
+ 2 /* don't forward to kmsg */
|
||||||
|
+ 2 /* don't forward to console */);
|
||||||
|
memcpy (header, identifier, l);
|
||||||
|
header[l++] = '\n';
|
||||||
|
header[l++] = '\n'; /* empty unit ID */
|
||||||
|
header[l++] = '0' + priority;
|
||||||
|
header[l++] = '\n';
|
||||||
|
header[l++] = '0' + !!level_prefix;
|
||||||
|
header[l++] = '\n';
|
||||||
|
header[l++] = '0'; /* don't forward to syslog */
|
||||||
|
header[l++] = '\n';
|
||||||
|
header[l++] = '0'; /* don't forward to kmsg */
|
||||||
|
header[l++] = '\n';
|
||||||
|
header[l++] = '0'; /* don't forward to console */
|
||||||
|
header[l++] = '\n';
|
||||||
|
|
||||||
|
if (write_all (fd, header, l) < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
return fd;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
saved_errno = errno;
|
||||||
|
|
||||||
|
if (fd >= 0)
|
||||||
|
close (fd);
|
||||||
|
|
||||||
|
errno = saved_errno;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_up_journal (const char *argv1)
|
||||||
|
{
|
||||||
|
const char *identifier;
|
||||||
|
const char *slash;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
identifier = getenv ("GIO_LAUNCHED_DESKTOP_FILE");
|
||||||
|
|
||||||
|
if (identifier == NULL)
|
||||||
|
identifier = argv1;
|
||||||
|
|
||||||
|
slash = strrchr (identifier, '/');
|
||||||
|
|
||||||
|
if (slash != NULL && slash[1] != '\0')
|
||||||
|
identifier = slash + 1;
|
||||||
|
|
||||||
|
fd = journal_stream_fd (identifier, LOG_INFO, 0);
|
||||||
|
|
||||||
|
/* Silently ignore failure to open the Journal */
|
||||||
|
if (fd < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (dup2 (fd, STDOUT_FILENO) != STDOUT_FILENO)
|
||||||
|
fprintf (stderr,
|
||||||
|
"gio-launch-desktop[%d]: Unable to redirect \"%s\" to Journal: %s",
|
||||||
|
getpid (),
|
||||||
|
identifier,
|
||||||
|
strerror (errno));
|
||||||
|
|
||||||
|
if (dup2 (fd, STDERR_FILENO) != STDERR_FILENO)
|
||||||
|
fprintf (stderr,
|
||||||
|
"gio-launch-desktop[%d]: Unable to redirect \"%s\" to Journal: %s",
|
||||||
|
getpid (),
|
||||||
|
identifier,
|
||||||
|
strerror (errno));
|
||||||
|
|
||||||
|
close (fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc, char *argv[])
|
main (int argc, char *argv[])
|
||||||
{
|
{
|
||||||
@ -49,5 +240,9 @@ main (int argc, char *argv[])
|
|||||||
|
|
||||||
putenv (buf);
|
putenv (buf);
|
||||||
|
|
||||||
|
#if defined(__linux__) && !defined(__BIONIC__)
|
||||||
|
set_up_journal (argv[1]);
|
||||||
|
#endif
|
||||||
|
|
||||||
return execvp (argv[1], argv + 1);
|
return execvp (argv[1], argv + 1);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user