]>
git.proxmox.com Git - mirror_frr.git/blob - lib/systemd.c
2 * Copyright (C) 2016 Cumulus Networks, Inc.
5 * This file is part of Quagga.
7 * Quagga is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
12 * Quagga is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27 #include "lib_errors.h"
29 /* these are cleared from env so they don't "leak" into things we fork(),
30 * particularly for watchfrr starting individual daemons
32 * watchdog_pid is currently not used since watchfrr starts forking.
33 * (TODO: handle that better, somehow?)
35 static pid_t watchdog_pid
= -1;
36 static intmax_t watchdog_msec
;
38 /* not used yet, but can trigger auto-switch to journald logging */
39 bool sd_stdout_is_journal
;
40 bool sd_stderr_is_journal
;
42 static char *notify_socket
;
44 /* talk to whatever entity claims to be systemd ;)
46 * refer to sd_notify docs for messages systemd accepts over this socket.
47 * This function should be functionally equivalent to sd_notify().
49 static void systemd_send_information(const char *info
)
52 struct sockaddr_un sun
;
57 sock
= socket(AF_UNIX
, SOCK_DGRAM
, 0);
61 sun
.sun_family
= AF_UNIX
;
62 strlcpy(sun
.sun_path
, notify_socket
, sizeof(sun
.sun_path
));
64 /* linux abstract unix socket namespace */
65 if (sun
.sun_path
[0] == '@')
66 sun
.sun_path
[0] = '\0';
68 /* nothing we can do if this errors out... */
69 (void)sendto(sock
, info
, strlen(info
), 0, (struct sockaddr
*)&sun
,
75 void systemd_send_stopping(void)
77 systemd_send_information("STATUS=");
78 systemd_send_information("STOPPING=1");
81 static struct thread_master
*systemd_master
= NULL
;
83 static void systemd_send_watchdog(struct thread
*t
)
85 systemd_send_information("WATCHDOG=1");
87 assert(watchdog_msec
> 0);
88 thread_add_timer_msec(systemd_master
, systemd_send_watchdog
, NULL
,
92 void systemd_send_started(struct thread_master
*m
)
98 systemd_send_information("READY=1");
99 if (watchdog_msec
> 0)
100 systemd_send_watchdog(NULL
);
103 void systemd_send_status(const char *status
)
107 snprintf(buffer
, sizeof(buffer
), "STATUS=%s", status
);
108 systemd_send_information(buffer
);
111 static intmax_t getenv_int(const char *varname
, intmax_t dflt
)
116 val
= getenv(varname
);
120 intval
= strtoimax(val
, &err
, 0);
126 void systemd_init_env(void)
133 notify_socket
= getenv("NOTIFY_SOCKET");
135 /* no point in setting up watchdog w/o notify socket */
137 intmax_t watchdog_usec
;
139 watchdog_pid
= getenv_int("WATCHDOG_PID", -1);
140 if (watchdog_pid
<= 0)
143 /* note this is the deadline, hence the divide by 3 */
144 watchdog_usec
= getenv_int("WATCHDOG_USEC", 0);
145 if (watchdog_usec
>= 3000)
146 watchdog_msec
= watchdog_usec
/ 3000;
148 if (watchdog_usec
!= 0)
151 "systemd expects a %jd microsecond watchdog timer, but FRR only supports millisecond resolution!",
157 tmp
= getenv("JOURNAL_STREAM");
158 if (tmp
&& sscanf(tmp
, "%ju:%ju%n", &dev
, &ino
, &len
) == 2
159 && (size_t)len
== strlen(tmp
)) {
160 if (fstat(1, &st
) == 0 && st
.st_dev
== (dev_t
)dev
161 && st
.st_ino
== (ino_t
)ino
)
162 sd_stdout_is_journal
= true;
163 if (fstat(2, &st
) == 0 && st
.st_dev
== (dev_t
)dev
164 && st
.st_ino
== (ino_t
)ino
)
165 sd_stderr_is_journal
= true;
168 /* these should *not* be passed to any other process we start */
169 unsetenv("WATCHDOG_PID");
170 unsetenv("WATCHDOG_USEC");