File: systemd_notify.c

package info (click to toggle)
dtrace 2.0.5-1
  • links: PTS
  • area: main
  • in suites: sid
  • size: 24,408 kB
  • sloc: ansic: 61,247; sh: 17,997; asm: 1,717; lex: 947; awk: 754; yacc: 695; perl: 37; sed: 17; makefile: 15
file content (70 lines) | stat: -rw-r--r-- 1,648 bytes parent folder | download
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
/* SPDX-License-Identifier: MIT-0 */
/* Lightly modified from the sd_notify manpage.  */

#include <sys/socket.h>
#include <sys/un.h>
#include <errno.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <unistd.h>

int
systemd_notify(const char *message)
{
	union sockaddr_union {
		struct sockaddr sa;
		struct sockaddr_un sun;
	} socket_addr = {
		.sun.sun_family = AF_UNIX,
	};

	size_t path_length, message_length;
	int fd = -1;
	const char *socket_path;

	/* Verify the argument first */
	if (!message)
		return -EINVAL;

	message_length = strlen(message);
	if (message_length == 0)
		return -EINVAL;

	/* If the variable is not set, the protocol is a noop */
	socket_path = getenv("NOTIFY_SOCKET");
	if (!socket_path)
		return 0; /* Not set? Nothing to do */

	/* Only AF_UNIX is supported, with path or abstract sockets */
	if (socket_path[0] != '/' && socket_path[0] != '@')
		return -EAFNOSUPPORT;

	path_length = strlen(socket_path);
	/* Ensure there is room for NUL byte */
	if (path_length >= sizeof(socket_addr.sun.sun_path))
		return -E2BIG;

	memcpy(socket_addr.sun.sun_path, socket_path, path_length);

	/* Support for abstract socket */
	if (socket_addr.sun.sun_path[0] == '@')
		socket_addr.sun.sun_path[0] = 0;

	fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
	if (fd < 0)
		return -errno;

	if (connect(fd, &socket_addr.sa, offsetof(struct sockaddr_un, sun_path) + path_length) != 0) {
		close(fd);
		return -errno;
	}

	ssize_t written = write(fd, message, message_length);
	if (written != (ssize_t) message_length) {
		close(fd);
		return written < 0 ? -errno : -EPROTO;
	}

	return 1; /* Notified! */
}