| /* |
| * systemd socket activation support |
| * |
| * Copyright 2017 Red Hat, Inc. and/or its affiliates |
| * |
| * Authors: |
| * Richard W.M. Jones <rjones@redhat.com> |
| * |
| * This work is licensed under the terms of the GNU GPL, version 2 or later. |
| * See the COPYING file in the top-level directory. |
| */ |
| |
| #include "qemu/osdep.h" |
| #include "qemu/systemd.h" |
| #include "qemu/cutils.h" |
| #include "qemu/error-report.h" |
| |
| #ifndef _WIN32 |
| unsigned int check_socket_activation(void) |
| { |
| const char *s; |
| unsigned long pid; |
| unsigned long nr_fds; |
| unsigned int i; |
| int fd; |
| int f; |
| int err; |
| |
| s = getenv("LISTEN_PID"); |
| if (s == NULL) { |
| return 0; |
| } |
| err = qemu_strtoul(s, NULL, 10, &pid); |
| if (err) { |
| return 0; |
| } |
| if (pid != getpid()) { |
| return 0; |
| } |
| |
| s = getenv("LISTEN_FDS"); |
| if (s == NULL) { |
| return 0; |
| } |
| err = qemu_strtoul(s, NULL, 10, &nr_fds); |
| if (err) { |
| return 0; |
| } |
| assert(nr_fds <= UINT_MAX); |
| |
| /* So these are not passed to any child processes we might start. */ |
| unsetenv("LISTEN_FDS"); |
| unsetenv("LISTEN_PID"); |
| |
| /* So the file descriptors don't leak into child processes. */ |
| for (i = 0; i < nr_fds; ++i) { |
| fd = FIRST_SOCKET_ACTIVATION_FD + i; |
| f = fcntl(fd, F_GETFD); |
| if (f == -1 || fcntl(fd, F_SETFD, f | FD_CLOEXEC) == -1) { |
| /* If we cannot set FD_CLOEXEC then it probably means the file |
| * descriptor is invalid, so socket activation has gone wrong |
| * and we should exit. |
| */ |
| error_report("Socket activation failed: " |
| "invalid file descriptor fd = %d: %s", |
| fd, g_strerror(errno)); |
| exit(EXIT_FAILURE); |
| } |
| } |
| |
| return (unsigned int) nr_fds; |
| } |
| |
| #else /* !_WIN32 */ |
| unsigned int check_socket_activation(void) |
| { |
| return 0; |
| } |
| #endif |