1 |
Add systemd socket-based activation support to pcscd as an alternative |
From ed83954ce404d0e58a04dfe7bfd379203f7830b5 Mon Sep 17 00:00:00 2001 |
2 |
to the existing autostart code which used forking from the user space |
From: Kalev Lember <kalev@smartlink.ee> |
3 |
library. Systemd socket activation makes it possible to start pcscd on |
Date: Thu, 23 Jun 2011 21:58:56 +0300 |
4 |
demand by systemd when a request is sent on the IPC socket. |
Subject: [PATCH 1/3] Support systemd socket activation |
5 |
|
|
6 |
The implementation uses the $LISTEN_FDS/$LISTEN_PID env var parsing code |
Add systemd socket-based activation support to pcscd as an alternative |
7 |
from systemd's sd-daemon.[ch] copy library. |
to the existing autostart code which used forking from the user space |
8 |
--- |
library. Systemd socket activation makes it possible to start pcscd on |
9 |
PCSC/src/Makefile.am | 6 + |
demand by systemd when a request is sent on the IPC socket. |
|
PCSC/src/pcscdaemon.c | 56 ++++-- |
|
|
PCSC/src/sd-daemon.c | 520 +++++++++++++++++++++++++++++++++++++++++++ |
|
|
PCSC/src/sd-daemon.h | 277 +++++++++++++++++++++++ |
|
|
PCSC/src/winscard_msg.h | 1 + |
|
|
PCSC/src/winscard_msg_srv.c | 25 ++ |
|
|
6 files changed, 870 insertions(+), 15 deletions(-) |
|
|
create mode 100644 PCSC/src/sd-daemon.c |
|
|
create mode 100644 PCSC/src/sd-daemon.h |
|
10 |
|
|
11 |
diff --git a/PCSC/src/Makefile.am b/PCSC/src/Makefile.am |
The implementation uses the $LISTEN_FDS/$LISTEN_PID env var parsing code |
12 |
index 2bd2f11..1b70466 100644 |
from systemd's sd-daemon.[ch] copy library. |
13 |
--- a/PCSC/src/Makefile.am |
--- |
14 |
+++ b/PCSC/src/Makefile.am |
PCSC/src/Makefile.am | 6 + |
15 |
@@ -67,6 +67,8 @@ pcscd_SOURCES = \ |
PCSC/src/pcscdaemon.c | 56 ++++-- |
16 |
prothandler.h \ |
PCSC/src/sd-daemon.c | 520 +++++++++++++++++++++++++++++++++++++++++++ |
17 |
readerfactory.c \ |
PCSC/src/sd-daemon.h | 277 +++++++++++++++++++++++ |
18 |
readerfactory.h \ |
PCSC/src/winscard_msg.h | 1 + |
19 |
+ sd-daemon.c \ |
PCSC/src/winscard_msg_srv.c | 25 ++ |
20 |
+ sd-daemon.h \ |
6 files changed, 870 insertions(+), 15 deletions(-) |
21 |
simclist.c \ |
create mode 100644 PCSC/src/sd-daemon.c |
22 |
simclist.h \ |
create mode 100644 PCSC/src/sd-daemon.h |
23 |
strlcat.c \ |
|
24 |
@@ -95,6 +97,10 @@ fix-rights: install-sbinPROGRAMS |
diff --git a/PCSC/src/Makefile.am b/PCSC/src/Makefile.am |
25 |
chgrp pcscd $(DESTDIR)$(sbindir)/pcscd |
index 2bd2f11..1b70466 100644 |
26 |
chmod g+s $(DESTDIR)$(sbindir)/pcscd |
--- a/PCSC/src/Makefile.am |
27 |
|
+++ b/PCSC/src/Makefile.am |
28 |
+update-systemd: |
@@ -67,6 +67,8 @@ pcscd_SOURCES = \ |
29 |
+ curl http://cgit.freedesktop.org/systemd/plain/src/sd-daemon.c > sd-daemon.c |
prothandler.h \ |
30 |
+ curl http://cgit.freedesktop.org/systemd/plain/src/sd-daemon.h > sd-daemon.h |
readerfactory.c \ |
31 |
+ |
readerfactory.h \ |
32 |
testpcsc_SOURCES = testpcsc.c |
+ sd-daemon.c \ |
33 |
testpcsc_LDADD = libpcsclite.la |
+ sd-daemon.h \ |
34 |
|
simclist.c \ |
35 |
diff --git a/PCSC/src/pcscdaemon.c b/PCSC/src/pcscdaemon.c |
simclist.h \ |
36 |
index 6abc328..609f981 100644 |
strlcat.c \ |
37 |
--- a/PCSC/src/pcscdaemon.c |
@@ -95,6 +97,10 @@ fix-rights: install-sbinPROGRAMS |
38 |
+++ b/PCSC/src/pcscdaemon.c |
chgrp pcscd $(DESTDIR)$(sbindir)/pcscd |
39 |
@@ -37,6 +37,7 @@ |
chmod g+s $(DESTDIR)$(sbindir)/pcscd |
40 |
#include "pcsclite.h" |
|
41 |
#include "pcscd.h" |
+update-systemd: |
42 |
#include "debuglog.h" |
+ curl http://cgit.freedesktop.org/systemd/plain/src/sd-daemon.c > sd-daemon.c |
43 |
+#include "sd-daemon.h" |
+ curl http://cgit.freedesktop.org/systemd/plain/src/sd-daemon.h > sd-daemon.h |
44 |
#include "winscard_msg.h" |
+ |
45 |
#include "winscard_svc.h" |
testpcsc_SOURCES = testpcsc.c |
46 |
#include "sys_generic.h" |
testpcsc_LDADD = libpcsclite.la |
47 |
@@ -54,6 +55,7 @@ |
|
48 |
char AraKiri = FALSE; |
diff --git a/PCSC/src/pcscdaemon.c b/PCSC/src/pcscdaemon.c |
49 |
static char Init = TRUE; |
index 6abc328..609f981 100644 |
50 |
char AutoExit = FALSE; |
--- a/PCSC/src/pcscdaemon.c |
51 |
+char SocketActivated = FALSE; |
+++ b/PCSC/src/pcscdaemon.c |
52 |
static int ExitValue = EXIT_FAILURE; |
@@ -37,6 +37,7 @@ |
53 |
int HPForceReaderPolling = 0; |
#include "pcsclite.h" |
54 |
static int pipefd[] = {-1, -1}; |
#include "pcscd.h" |
55 |
@@ -316,6 +318,20 @@ int main(int argc, char **argv) |
#include "debuglog.h" |
56 |
} |
+#include "sd-daemon.h" |
57 |
|
#include "winscard_msg.h" |
58 |
/* |
#include "winscard_svc.h" |
59 |
+ * Check if systemd passed us any file descriptors |
#include "sys_generic.h" |
60 |
+ */ |
@@ -54,6 +55,7 @@ |
61 |
+ rv = sd_listen_fds(0); |
char AraKiri = FALSE; |
62 |
+ if (rv > 1) |
static char Init = TRUE; |
63 |
+ { |
char AutoExit = FALSE; |
64 |
+ Log1(PCSC_LOG_CRITICAL, "Too many file descriptors received"); |
+char SocketActivated = FALSE; |
65 |
+ return EXIT_FAILURE; |
static int ExitValue = EXIT_FAILURE; |
66 |
+ } |
int HPForceReaderPolling = 0; |
67 |
+ else if (rv == 1) |
static int pipefd[] = {-1, -1}; |
68 |
+ SocketActivated = TRUE; |
@@ -316,6 +318,20 @@ int main(int argc, char **argv) |
69 |
+ else |
} |
70 |
+ SocketActivated = FALSE; |
|
71 |
+ |
/* |
72 |
+ /* |
+ * Check if systemd passed us any file descriptors |
73 |
* test the presence of /var/run/pcscd/pcscd.comm |
+ */ |
74 |
*/ |
+ rv = sd_listen_fds(0); |
75 |
|
+ if (rv > 1) |
76 |
@@ -366,16 +382,19 @@ int main(int argc, char **argv) |
+ { |
77 |
return EXIT_FAILURE; |
+ Log1(PCSC_LOG_CRITICAL, "Too many file descriptors received"); |
78 |
} |
+ return EXIT_FAILURE; |
79 |
|
+ } |
80 |
- Log1(PCSC_LOG_CRITICAL, |
+ else if (rv == 1) |
81 |
- "file " PCSCLITE_CSOCK_NAME " already exists."); |
+ SocketActivated = TRUE; |
82 |
- Log1(PCSC_LOG_CRITICAL, |
+ else |
83 |
- "Maybe another pcscd is running?"); |
+ SocketActivated = FALSE; |
84 |
- Log1(PCSC_LOG_CRITICAL, |
+ |
85 |
- "I can't read process pid from " PCSCLITE_RUN_PID); |
+ /* |
86 |
- Log1(PCSC_LOG_CRITICAL, "Remove " PCSCLITE_CSOCK_NAME); |
* test the presence of /var/run/pcscd/pcscd.comm |
87 |
- Log1(PCSC_LOG_CRITICAL, |
*/ |
88 |
- "if pcscd is not running to clear this message."); |
|
89 |
- return EXIT_FAILURE; |
@@ -366,16 +382,19 @@ int main(int argc, char **argv) |
90 |
+ if (!SocketActivated) |
return EXIT_FAILURE; |
91 |
+ { |
} |
92 |
+ Log1(PCSC_LOG_CRITICAL, |
|
93 |
+ "file " PCSCLITE_CSOCK_NAME " already exists."); |
- Log1(PCSC_LOG_CRITICAL, |
94 |
+ Log1(PCSC_LOG_CRITICAL, |
- "file " PCSCLITE_CSOCK_NAME " already exists."); |
95 |
+ "Maybe another pcscd is running?"); |
- Log1(PCSC_LOG_CRITICAL, |
96 |
+ Log1(PCSC_LOG_CRITICAL, |
- "Maybe another pcscd is running?"); |
97 |
+ "I can't read process pid from " PCSCLITE_RUN_PID); |
- Log1(PCSC_LOG_CRITICAL, |
98 |
+ Log1(PCSC_LOG_CRITICAL, "Remove " PCSCLITE_CSOCK_NAME); |
- "I can't read process pid from " PCSCLITE_RUN_PID); |
99 |
+ Log1(PCSC_LOG_CRITICAL, |
- Log1(PCSC_LOG_CRITICAL, "Remove " PCSCLITE_CSOCK_NAME); |
100 |
+ "if pcscd is not running to clear this message."); |
- Log1(PCSC_LOG_CRITICAL, |
101 |
+ return EXIT_FAILURE; |
- "if pcscd is not running to clear this message."); |
102 |
+ } |
- return EXIT_FAILURE; |
103 |
} |
+ if (!SocketActivated) |
104 |
} |
+ { |
105 |
else |
+ Log1(PCSC_LOG_CRITICAL, |
106 |
@@ -568,7 +587,11 @@ int main(int argc, char **argv) |
+ "file " PCSCLITE_CSOCK_NAME " already exists."); |
107 |
/* |
+ Log1(PCSC_LOG_CRITICAL, |
108 |
* Initialize the comm structure |
+ "Maybe another pcscd is running?"); |
109 |
*/ |
+ Log1(PCSC_LOG_CRITICAL, |
110 |
- rv = InitializeSocket(); |
+ "I can't read process pid from " PCSCLITE_RUN_PID); |
111 |
+ if (SocketActivated) |
+ Log1(PCSC_LOG_CRITICAL, "Remove " PCSCLITE_CSOCK_NAME); |
112 |
+ rv = ListenExistingSocket(SD_LISTEN_FDS_START + 0); |
+ Log1(PCSC_LOG_CRITICAL, |
113 |
+ else |
+ "if pcscd is not running to clear this message."); |
114 |
+ rv = InitializeSocket(); |
+ return EXIT_FAILURE; |
115 |
+ |
+ } |
116 |
if (rv) |
} |
117 |
{ |
} |
118 |
Log1(PCSC_LOG_CRITICAL, "Error initializing pcscd."); |
else |
119 |
@@ -652,10 +675,13 @@ static void clean_temp_files(void) |
@@ -568,7 +587,11 @@ int main(int argc, char **argv) |
120 |
{ |
/* |
121 |
int rv; |
* Initialize the comm structure |
122 |
|
*/ |
123 |
- rv = remove(PCSCLITE_CSOCK_NAME); |
- rv = InitializeSocket(); |
124 |
- if (rv != 0) |
+ if (SocketActivated) |
125 |
- Log2(PCSC_LOG_ERROR, "Cannot remove " PCSCLITE_CSOCK_NAME ": %s", |
+ rv = ListenExistingSocket(SD_LISTEN_FDS_START + 0); |
126 |
- strerror(errno)); |
+ else |
127 |
+ if (!SocketActivated) |
+ rv = InitializeSocket(); |
128 |
+ { |
+ |
129 |
+ rv = remove(PCSCLITE_CSOCK_NAME); |
if (rv) |
130 |
+ if (rv != 0) |
{ |
131 |
+ Log2(PCSC_LOG_ERROR, "Cannot remove " PCSCLITE_CSOCK_NAME ": %s", |
Log1(PCSC_LOG_CRITICAL, "Error initializing pcscd."); |
132 |
+ strerror(errno)); |
@@ -652,10 +675,13 @@ static void clean_temp_files(void) |
133 |
+ } |
{ |
134 |
|
int rv; |
135 |
rv = remove(PCSCLITE_RUN_PID); |
|
136 |
if (rv != 0) |
- rv = remove(PCSCLITE_CSOCK_NAME); |
137 |
diff --git a/PCSC/src/sd-daemon.c b/PCSC/src/sd-daemon.c |
- if (rv != 0) |
138 |
new file mode 100644 |
- Log2(PCSC_LOG_ERROR, "Cannot remove " PCSCLITE_CSOCK_NAME ": %s", |
139 |
index 0000000..a2ec74c |
- strerror(errno)); |
140 |
--- /dev/null |
+ if (!SocketActivated) |
141 |
+++ b/PCSC/src/sd-daemon.c |
+ { |
142 |
@@ -0,0 +1,520 @@ |
+ rv = remove(PCSCLITE_CSOCK_NAME); |
143 |
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ |
+ if (rv != 0) |
144 |
+ |
+ Log2(PCSC_LOG_ERROR, "Cannot remove " PCSCLITE_CSOCK_NAME ": %s", |
145 |
+/*** |
+ strerror(errno)); |
146 |
+ Copyright 2010 Lennart Poettering |
+ } |
147 |
+ |
|
148 |
+ Permission is hereby granted, free of charge, to any person |
rv = remove(PCSCLITE_RUN_PID); |
149 |
+ obtaining a copy of this software and associated documentation files |
if (rv != 0) |
150 |
+ (the "Software"), to deal in the Software without restriction, |
diff --git a/PCSC/src/sd-daemon.c b/PCSC/src/sd-daemon.c |
151 |
+ including without limitation the rights to use, copy, modify, merge, |
new file mode 100644 |
152 |
+ publish, distribute, sublicense, and/or sell copies of the Software, |
index 0000000..a2ec74c |
153 |
+ and to permit persons to whom the Software is furnished to do so, |
--- /dev/null |
154 |
+ subject to the following conditions: |
+++ b/PCSC/src/sd-daemon.c |
155 |
+ |
@@ -0,0 +1,520 @@ |
156 |
+ The above copyright notice and this permission notice shall be |
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ |
157 |
+ included in all copies or substantial portions of the Software. |
+ |
158 |
+ |
+/*** |
159 |
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
+ Copyright 2010 Lennart Poettering |
160 |
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
+ |
161 |
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
+ Permission is hereby granted, free of charge, to any person |
162 |
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS |
+ obtaining a copy of this software and associated documentation files |
163 |
+ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
+ (the "Software"), to deal in the Software without restriction, |
164 |
+ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
+ including without limitation the rights to use, copy, modify, merge, |
165 |
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
+ publish, distribute, sublicense, and/or sell copies of the Software, |
166 |
+ SOFTWARE. |
+ and to permit persons to whom the Software is furnished to do so, |
167 |
+***/ |
+ subject to the following conditions: |
168 |
+ |
+ |
169 |
+#ifndef _GNU_SOURCE |
+ The above copyright notice and this permission notice shall be |
170 |
+#define _GNU_SOURCE |
+ included in all copies or substantial portions of the Software. |
171 |
+#endif |
+ |
172 |
+ |
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
173 |
+#include <sys/types.h> |
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
174 |
+#include <sys/stat.h> |
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
175 |
+#include <sys/socket.h> |
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS |
176 |
+#include <sys/un.h> |
+ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
177 |
+#include <sys/fcntl.h> |
+ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
178 |
+#include <netinet/in.h> |
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
179 |
+#include <stdlib.h> |
+ SOFTWARE. |
180 |
+#include <errno.h> |
+***/ |
181 |
+#include <unistd.h> |
+ |
182 |
+#include <string.h> |
+#ifndef _GNU_SOURCE |
183 |
+#include <stdarg.h> |
+#define _GNU_SOURCE |
184 |
+#include <stdio.h> |
+#endif |
185 |
+#include <stddef.h> |
+ |
186 |
+#include <limits.h> |
+#include <sys/types.h> |
187 |
+ |
+#include <sys/stat.h> |
188 |
+#if defined(__linux__) |
+#include <sys/socket.h> |
189 |
+#include <mqueue.h> |
+#include <sys/un.h> |
190 |
+#endif |
+#include <sys/fcntl.h> |
191 |
+ |
+#include <netinet/in.h> |
192 |
+#include "sd-daemon.h" |
+#include <stdlib.h> |
193 |
+ |
+#include <errno.h> |
194 |
+#if (__GNUC__ >= 4) && !defined(SD_EXPORT_SYMBOLS) |
+#include <unistd.h> |
195 |
+#define _sd_hidden_ __attribute__ ((visibility("hidden"))) |
+#include <string.h> |
196 |
+#else |
+#include <stdarg.h> |
197 |
+#define _sd_hidden_ |
+#include <stdio.h> |
198 |
+#endif |
+#include <stddef.h> |
199 |
+ |
+#include <limits.h> |
200 |
+_sd_hidden_ int sd_listen_fds(int unset_environment) { |
+ |
201 |
+ |
+#if defined(__linux__) |
202 |
+#if defined(DISABLE_SYSTEMD) || !defined(__linux__) |
+#include <mqueue.h> |
203 |
+ return 0; |
+#endif |
204 |
+#else |
+ |
205 |
+ int r, fd; |
+#include "sd-daemon.h" |
206 |
+ const char *e; |
+ |
207 |
+ char *p = NULL; |
+#if (__GNUC__ >= 4) && !defined(SD_EXPORT_SYMBOLS) |
208 |
+ unsigned long l; |
+#define _sd_hidden_ __attribute__ ((visibility("hidden"))) |
209 |
+ |
+#else |
210 |
+ if (!(e = getenv("LISTEN_PID"))) { |
+#define _sd_hidden_ |
211 |
+ r = 0; |
+#endif |
212 |
+ goto finish; |
+ |
213 |
+ } |
+_sd_hidden_ int sd_listen_fds(int unset_environment) { |
214 |
+ |
+ |
215 |
+ errno = 0; |
+#if defined(DISABLE_SYSTEMD) || !defined(__linux__) |
216 |
+ l = strtoul(e, &p, 10); |
+ return 0; |
217 |
+ |
+#else |
218 |
+ if (errno != 0) { |
+ int r, fd; |
219 |
+ r = -errno; |
+ const char *e; |
220 |
+ goto finish; |
+ char *p = NULL; |
221 |
+ } |
+ unsigned long l; |
222 |
+ |
+ |
223 |
+ if (!p || *p || l <= 0) { |
+ if (!(e = getenv("LISTEN_PID"))) { |
224 |
+ r = -EINVAL; |
+ r = 0; |
225 |
+ goto finish; |
+ goto finish; |
226 |
+ } |
+ } |
227 |
+ |
+ |
228 |
+ /* Is this for us? */ |
+ errno = 0; |
229 |
+ if (getpid() != (pid_t) l) { |
+ l = strtoul(e, &p, 10); |
230 |
+ r = 0; |
+ |
231 |
+ goto finish; |
+ if (errno != 0) { |
232 |
+ } |
+ r = -errno; |
233 |
+ |
+ goto finish; |
234 |
+ if (!(e = getenv("LISTEN_FDS"))) { |
+ } |
235 |
+ r = 0; |
+ |
236 |
+ goto finish; |
+ if (!p || *p || l <= 0) { |
237 |
+ } |
+ r = -EINVAL; |
238 |
+ |
+ goto finish; |
239 |
+ errno = 0; |
+ } |
240 |
+ l = strtoul(e, &p, 10); |
+ |
241 |
+ |
+ /* Is this for us? */ |
242 |
+ if (errno != 0) { |
+ if (getpid() != (pid_t) l) { |
243 |
+ r = -errno; |
+ r = 0; |
244 |
+ goto finish; |
+ goto finish; |
245 |
+ } |
+ } |
246 |
+ |
+ |
247 |
+ if (!p || *p) { |
+ if (!(e = getenv("LISTEN_FDS"))) { |
248 |
+ r = -EINVAL; |
+ r = 0; |
249 |
+ goto finish; |
+ goto finish; |
250 |
+ } |
+ } |
251 |
+ |
+ |
252 |
+ for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + (int) l; fd ++) { |
+ errno = 0; |
253 |
+ int flags; |
+ l = strtoul(e, &p, 10); |
254 |
+ |
+ |
255 |
+ if ((flags = fcntl(fd, F_GETFD)) < 0) { |
+ if (errno != 0) { |
256 |
+ r = -errno; |
+ r = -errno; |
257 |
+ goto finish; |
+ goto finish; |
258 |
+ } |
+ } |
259 |
+ |
+ |
260 |
+ if (flags & FD_CLOEXEC) |
+ if (!p || *p) { |
261 |
+ continue; |
+ r = -EINVAL; |
262 |
+ |
+ goto finish; |
263 |
+ if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0) { |
+ } |
264 |
+ r = -errno; |
+ |
265 |
+ goto finish; |
+ for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + (int) l; fd ++) { |
266 |
+ } |
+ int flags; |
267 |
+ } |
+ |
268 |
+ |
+ if ((flags = fcntl(fd, F_GETFD)) < 0) { |
269 |
+ r = (int) l; |
+ r = -errno; |
270 |
+ |
+ goto finish; |
271 |
+finish: |
+ } |
272 |
+ if (unset_environment) { |
+ |
273 |
+ unsetenv("LISTEN_PID"); |
+ if (flags & FD_CLOEXEC) |
274 |
+ unsetenv("LISTEN_FDS"); |
+ continue; |
275 |
+ } |
+ |
276 |
+ |
+ if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0) { |
277 |
+ return r; |
+ r = -errno; |
278 |
+#endif |
+ goto finish; |
279 |
+} |
+ } |
280 |
+ |
+ } |
281 |
+_sd_hidden_ int sd_is_fifo(int fd, const char *path) { |
+ |
282 |
+ struct stat st_fd; |
+ r = (int) l; |
283 |
+ |
+ |
284 |
+ if (fd < 0) |
+finish: |
285 |
+ return -EINVAL; |
+ if (unset_environment) { |
286 |
+ |
+ unsetenv("LISTEN_PID"); |
287 |
+ memset(&st_fd, 0, sizeof(st_fd)); |
+ unsetenv("LISTEN_FDS"); |
288 |
+ if (fstat(fd, &st_fd) < 0) |
+ } |
289 |
+ return -errno; |
+ |
290 |
+ |
+ return r; |
291 |
+ if (!S_ISFIFO(st_fd.st_mode)) |
+#endif |
292 |
+ return 0; |
+} |
293 |
+ |
+ |
294 |
+ if (path) { |
+_sd_hidden_ int sd_is_fifo(int fd, const char *path) { |
295 |
+ struct stat st_path; |
+ struct stat st_fd; |
296 |
+ |
+ |
297 |
+ memset(&st_path, 0, sizeof(st_path)); |
+ if (fd < 0) |
298 |
+ if (stat(path, &st_path) < 0) { |
+ return -EINVAL; |
299 |
+ |
+ |
300 |
+ if (errno == ENOENT || errno == ENOTDIR) |
+ memset(&st_fd, 0, sizeof(st_fd)); |
301 |
+ return 0; |
+ if (fstat(fd, &st_fd) < 0) |
302 |
+ |
+ return -errno; |
303 |
+ return -errno; |
+ |
304 |
+ } |
+ if (!S_ISFIFO(st_fd.st_mode)) |
305 |
+ |
+ return 0; |
306 |
+ return |
+ |
307 |
+ st_path.st_dev == st_fd.st_dev && |
+ if (path) { |
308 |
+ st_path.st_ino == st_fd.st_ino; |
+ struct stat st_path; |
309 |
+ } |
+ |
310 |
+ |
+ memset(&st_path, 0, sizeof(st_path)); |
311 |
+ return 1; |
+ if (stat(path, &st_path) < 0) { |
312 |
+} |
+ |
313 |
+ |
+ if (errno == ENOENT || errno == ENOTDIR) |
314 |
+_sd_hidden_ int sd_is_special(int fd, const char *path) { |
+ return 0; |
315 |
+ struct stat st_fd; |
+ |
316 |
+ |
+ return -errno; |
317 |
+ if (fd < 0) |
+ } |
318 |
+ return -EINVAL; |
+ |
319 |
+ |
+ return |
320 |
+ if (fstat(fd, &st_fd) < 0) |
+ st_path.st_dev == st_fd.st_dev && |
321 |
+ return -errno; |
+ st_path.st_ino == st_fd.st_ino; |
322 |
+ |
+ } |
323 |
+ if (!S_ISREG(st_fd.st_mode) && !S_ISCHR(st_fd.st_mode)) |
+ |
324 |
+ return 0; |
+ return 1; |
325 |
+ |
+} |
326 |
+ if (path) { |
+ |
327 |
+ struct stat st_path; |
+_sd_hidden_ int sd_is_special(int fd, const char *path) { |
328 |
+ |
+ struct stat st_fd; |
329 |
+ if (stat(path, &st_path) < 0) { |
+ |
330 |
+ |
+ if (fd < 0) |
331 |
+ if (errno == ENOENT || errno == ENOTDIR) |
+ return -EINVAL; |
332 |
+ return 0; |
+ |
333 |
+ |
+ if (fstat(fd, &st_fd) < 0) |
334 |
+ return -errno; |
+ return -errno; |
335 |
+ } |
+ |
336 |
+ |
+ if (!S_ISREG(st_fd.st_mode) && !S_ISCHR(st_fd.st_mode)) |
337 |
+ if (S_ISREG(st_fd.st_mode) && S_ISREG(st_path.st_mode)) |
+ return 0; |
338 |
+ return |
+ |
339 |
+ st_path.st_dev == st_fd.st_dev && |
+ if (path) { |
340 |
+ st_path.st_ino == st_fd.st_ino; |
+ struct stat st_path; |
341 |
+ else if (S_ISCHR(st_fd.st_mode) && S_ISCHR(st_path.st_mode)) |
+ |
342 |
+ return st_path.st_rdev == st_fd.st_rdev; |
+ if (stat(path, &st_path) < 0) { |
343 |
+ else |
+ |
344 |
+ return 0; |
+ if (errno == ENOENT || errno == ENOTDIR) |
345 |
+ } |
+ return 0; |
346 |
+ |
+ |
347 |
+ return 1; |
+ return -errno; |
348 |
+} |
+ } |
349 |
+ |
+ |
350 |
+static int sd_is_socket_internal(int fd, int type, int listening) { |
+ if (S_ISREG(st_fd.st_mode) && S_ISREG(st_path.st_mode)) |
351 |
+ struct stat st_fd; |
+ return |
352 |
+ |
+ st_path.st_dev == st_fd.st_dev && |
353 |
+ if (fd < 0 || type < 0) |
+ st_path.st_ino == st_fd.st_ino; |
354 |
+ return -EINVAL; |
+ else if (S_ISCHR(st_fd.st_mode) && S_ISCHR(st_path.st_mode)) |
355 |
+ |
+ return st_path.st_rdev == st_fd.st_rdev; |
356 |
+ if (fstat(fd, &st_fd) < 0) |
+ else |
357 |
+ return -errno; |
+ return 0; |
358 |
+ |
+ } |
359 |
+ if (!S_ISSOCK(st_fd.st_mode)) |
+ |
360 |
+ return 0; |
+ return 1; |
361 |
+ |
+} |
362 |
+ if (type != 0) { |
+ |
363 |
+ int other_type = 0; |
+static int sd_is_socket_internal(int fd, int type, int listening) { |
364 |
+ socklen_t l = sizeof(other_type); |
+ struct stat st_fd; |
365 |
+ |
+ |
366 |
+ if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &other_type, &l) < 0) |
+ if (fd < 0 || type < 0) |
367 |
+ return -errno; |
+ return -EINVAL; |
368 |
+ |
+ |
369 |
+ if (l != sizeof(other_type)) |
+ if (fstat(fd, &st_fd) < 0) |
370 |
+ return -EINVAL; |
+ return -errno; |
371 |
+ |
+ |
372 |
+ if (other_type != type) |
+ if (!S_ISSOCK(st_fd.st_mode)) |
373 |
+ return 0; |
+ return 0; |
374 |
+ } |
+ |
375 |
+ |
+ if (type != 0) { |
376 |
+ if (listening >= 0) { |
+ int other_type = 0; |
377 |
+ int accepting = 0; |
+ socklen_t l = sizeof(other_type); |
378 |
+ socklen_t l = sizeof(accepting); |
+ |
379 |
+ |
+ if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &other_type, &l) < 0) |
380 |
+ if (getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &accepting, &l) < 0) |
+ return -errno; |
381 |
+ return -errno; |
+ |
382 |
+ |
+ if (l != sizeof(other_type)) |
383 |
+ if (l != sizeof(accepting)) |
+ return -EINVAL; |
384 |
+ return -EINVAL; |
+ |
385 |
+ |
+ if (other_type != type) |
386 |
+ if (!accepting != !listening) |
+ return 0; |
387 |
+ return 0; |
+ } |
388 |
+ } |
+ |
389 |
+ |
+ if (listening >= 0) { |
390 |
+ return 1; |
+ int accepting = 0; |
391 |
+} |
+ socklen_t l = sizeof(accepting); |
392 |
+ |
+ |
393 |
+union sockaddr_union { |
+ if (getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &accepting, &l) < 0) |
394 |
+ struct sockaddr sa; |
+ return -errno; |
395 |
+ struct sockaddr_in in4; |
+ |
396 |
+ struct sockaddr_in6 in6; |
+ if (l != sizeof(accepting)) |
397 |
+ struct sockaddr_un un; |
+ return -EINVAL; |
398 |
+ struct sockaddr_storage storage; |
+ |
399 |
+}; |
+ if (!accepting != !listening) |
400 |
+ |
+ return 0; |
401 |
+_sd_hidden_ int sd_is_socket(int fd, int family, int type, int listening) { |
+ } |
402 |
+ int r; |
+ |
403 |
+ |
+ return 1; |
404 |
+ if (family < 0) |
+} |
405 |
+ return -EINVAL; |
+ |
406 |
+ |
+union sockaddr_union { |
407 |
+ if ((r = sd_is_socket_internal(fd, type, listening)) <= 0) |
+ struct sockaddr sa; |
408 |
+ return r; |
+ struct sockaddr_in in4; |
409 |
+ |
+ struct sockaddr_in6 in6; |
410 |
+ if (family > 0) { |
+ struct sockaddr_un un; |
411 |
+ union sockaddr_union sockaddr; |
+ struct sockaddr_storage storage; |
412 |
+ socklen_t l; |
+}; |
413 |
+ |
+ |
414 |
+ memset(&sockaddr, 0, sizeof(sockaddr)); |
+_sd_hidden_ int sd_is_socket(int fd, int family, int type, int listening) { |
415 |
+ l = sizeof(sockaddr); |
+ int r; |
416 |
+ |
+ |
417 |
+ if (getsockname(fd, &sockaddr.sa, &l) < 0) |
+ if (family < 0) |
418 |
+ return -errno; |
+ return -EINVAL; |
419 |
+ |
+ |
420 |
+ if (l < sizeof(sa_family_t)) |
+ if ((r = sd_is_socket_internal(fd, type, listening)) <= 0) |
421 |
+ return -EINVAL; |
+ return r; |
422 |
+ |
+ |
423 |
+ return sockaddr.sa.sa_family == family; |
+ if (family > 0) { |
424 |
+ } |
+ union sockaddr_union sockaddr; |
425 |
+ |
+ socklen_t l; |
426 |
+ return 1; |
+ |
427 |
+} |
+ memset(&sockaddr, 0, sizeof(sockaddr)); |
428 |
+ |
+ l = sizeof(sockaddr); |
429 |
+_sd_hidden_ int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port) { |
+ |
430 |
+ union sockaddr_union sockaddr; |
+ if (getsockname(fd, &sockaddr.sa, &l) < 0) |
431 |
+ socklen_t l; |
+ return -errno; |
432 |
+ int r; |
+ |
433 |
+ |
+ if (l < sizeof(sa_family_t)) |
434 |
+ if (family != 0 && family != AF_INET && family != AF_INET6) |
+ return -EINVAL; |
435 |
+ return -EINVAL; |
+ |
436 |
+ |
+ return sockaddr.sa.sa_family == family; |
437 |
+ if ((r = sd_is_socket_internal(fd, type, listening)) <= 0) |
+ } |
438 |
+ return r; |
+ |
439 |
+ |
+ return 1; |
440 |
+ memset(&sockaddr, 0, sizeof(sockaddr)); |
+} |
441 |
+ l = sizeof(sockaddr); |
+ |
442 |
+ |
+_sd_hidden_ int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port) { |
443 |
+ if (getsockname(fd, &sockaddr.sa, &l) < 0) |
+ union sockaddr_union sockaddr; |
444 |
+ return -errno; |
+ socklen_t l; |
445 |
+ |
+ int r; |
446 |
+ if (l < sizeof(sa_family_t)) |
+ |
447 |
+ return -EINVAL; |
+ if (family != 0 && family != AF_INET && family != AF_INET6) |
448 |
+ |
+ return -EINVAL; |
449 |
+ if (sockaddr.sa.sa_family != AF_INET && |
+ |
450 |
+ sockaddr.sa.sa_family != AF_INET6) |
+ if ((r = sd_is_socket_internal(fd, type, listening)) <= 0) |
451 |
+ return 0; |
+ return r; |
452 |
+ |
+ |
453 |
+ if (family > 0) |
+ memset(&sockaddr, 0, sizeof(sockaddr)); |
454 |
+ if (sockaddr.sa.sa_family != family) |
+ l = sizeof(sockaddr); |
455 |
+ return 0; |
+ |
456 |
+ |
+ if (getsockname(fd, &sockaddr.sa, &l) < 0) |
457 |
+ if (port > 0) { |
+ return -errno; |
458 |
+ if (sockaddr.sa.sa_family == AF_INET) { |
+ |
459 |
+ if (l < sizeof(struct sockaddr_in)) |
+ if (l < sizeof(sa_family_t)) |
460 |
+ return -EINVAL; |
+ return -EINVAL; |
461 |
+ |
+ |
462 |
+ return htons(port) == sockaddr.in4.sin_port; |
+ if (sockaddr.sa.sa_family != AF_INET && |
463 |
+ } else { |
+ sockaddr.sa.sa_family != AF_INET6) |
464 |
+ if (l < sizeof(struct sockaddr_in6)) |
+ return 0; |
465 |
+ return -EINVAL; |
+ |
466 |
+ |
+ if (family > 0) |
467 |
+ return htons(port) == sockaddr.in6.sin6_port; |
+ if (sockaddr.sa.sa_family != family) |
468 |
+ } |
+ return 0; |
469 |
+ } |
+ |
470 |
+ |
+ if (port > 0) { |
471 |
+ return 1; |
+ if (sockaddr.sa.sa_family == AF_INET) { |
472 |
+} |
+ if (l < sizeof(struct sockaddr_in)) |
473 |
+ |
+ return -EINVAL; |
474 |
+_sd_hidden_ int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length) { |
+ |
475 |
+ union sockaddr_union sockaddr; |
+ return htons(port) == sockaddr.in4.sin_port; |
476 |
+ socklen_t l; |
+ } else { |
477 |
+ int r; |
+ if (l < sizeof(struct sockaddr_in6)) |
478 |
+ |
+ return -EINVAL; |
479 |
+ if ((r = sd_is_socket_internal(fd, type, listening)) <= 0) |
+ |
480 |
+ return r; |
+ return htons(port) == sockaddr.in6.sin6_port; |
481 |
+ |
+ } |
482 |
+ memset(&sockaddr, 0, sizeof(sockaddr)); |
+ } |
483 |
+ l = sizeof(sockaddr); |
+ |
484 |
+ |
+ return 1; |
485 |
+ if (getsockname(fd, &sockaddr.sa, &l) < 0) |
+} |
486 |
+ return -errno; |
+ |
487 |
+ |
+_sd_hidden_ int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length) { |
488 |
+ if (l < sizeof(sa_family_t)) |
+ union sockaddr_union sockaddr; |
489 |
+ return -EINVAL; |
+ socklen_t l; |
490 |
+ |
+ int r; |
491 |
+ if (sockaddr.sa.sa_family != AF_UNIX) |
+ |
492 |
+ return 0; |
+ if ((r = sd_is_socket_internal(fd, type, listening)) <= 0) |
493 |
+ |
+ return r; |
494 |
+ if (path) { |
+ |
495 |
+ if (length <= 0) |
+ memset(&sockaddr, 0, sizeof(sockaddr)); |
496 |
+ length = strlen(path); |
+ l = sizeof(sockaddr); |
497 |
+ |
+ |
498 |
+ if (length <= 0) |
+ if (getsockname(fd, &sockaddr.sa, &l) < 0) |
499 |
+ /* Unnamed socket */ |
+ return -errno; |
500 |
+ return l == offsetof(struct sockaddr_un, sun_path); |
+ |
501 |
+ |
+ if (l < sizeof(sa_family_t)) |
502 |
+ if (path[0]) |
+ return -EINVAL; |
503 |
+ /* Normal path socket */ |
+ |
504 |
+ return |
+ if (sockaddr.sa.sa_family != AF_UNIX) |
505 |
+ (l >= offsetof(struct sockaddr_un, sun_path) + length + 1) && |
+ return 0; |
506 |
+ memcmp(path, sockaddr.un.sun_path, length+1) == 0; |
+ |
507 |
+ else |
+ if (path) { |
508 |
+ /* Abstract namespace socket */ |
+ if (length <= 0) |
509 |
+ return |
+ length = strlen(path); |
510 |
+ (l == offsetof(struct sockaddr_un, sun_path) + length) && |
+ |
511 |
+ memcmp(path, sockaddr.un.sun_path, length) == 0; |
+ if (length <= 0) |
512 |
+ } |
+ /* Unnamed socket */ |
513 |
+ |
+ return l == offsetof(struct sockaddr_un, sun_path); |
514 |
+ return 1; |
+ |
515 |
+} |
+ if (path[0]) |
516 |
+ |
+ /* Normal path socket */ |
517 |
+_sd_hidden_ int sd_is_mq(int fd, const char *path) { |
+ return |
518 |
+#if !defined(__linux__) |
+ (l >= offsetof(struct sockaddr_un, sun_path) + length + 1) && |
519 |
+ return 0; |
+ memcmp(path, sockaddr.un.sun_path, length+1) == 0; |
520 |
+#else |
+ else |
521 |
+ struct mq_attr attr; |
+ /* Abstract namespace socket */ |
522 |
+ |
+ return |
523 |
+ if (fd < 0) |
+ (l == offsetof(struct sockaddr_un, sun_path) + length) && |
524 |
+ return -EINVAL; |
+ memcmp(path, sockaddr.un.sun_path, length) == 0; |
525 |
+ |
+ } |
526 |
+ if (mq_getattr(fd, &attr) < 0) |
+ |
527 |
+ return -errno; |
+ return 1; |
528 |
+ |
+} |
529 |
+ if (path) { |
+ |
530 |
+ char fpath[PATH_MAX]; |
+_sd_hidden_ int sd_is_mq(int fd, const char *path) { |
531 |
+ struct stat a, b; |
+#if !defined(__linux__) |
532 |
+ |
+ return 0; |
533 |
+ if (path[0] != '/') |
+#else |
534 |
+ return -EINVAL; |
+ struct mq_attr attr; |
535 |
+ |
+ |
536 |
+ if (fstat(fd, &a) < 0) |
+ if (fd < 0) |
537 |
+ return -errno; |
+ return -EINVAL; |
538 |
+ |
+ |
539 |
+ strncpy(stpcpy(fpath, "/dev/mqueue"), path, sizeof(fpath) - 12); |
+ if (mq_getattr(fd, &attr) < 0) |
540 |
+ fpath[sizeof(fpath)-1] = 0; |
+ return -errno; |
541 |
+ |
+ |
542 |
+ if (stat(fpath, &b) < 0) |
+ if (path) { |
543 |
+ return -errno; |
+ char fpath[PATH_MAX]; |
544 |
+ |
+ struct stat a, b; |
545 |
+ if (a.st_dev != b.st_dev || |
+ |
546 |
+ a.st_ino != b.st_ino) |
+ if (path[0] != '/') |
547 |
+ return 0; |
+ return -EINVAL; |
548 |
+ } |
+ |
549 |
+ |
+ if (fstat(fd, &a) < 0) |
550 |
+ return 1; |
+ return -errno; |
551 |
+#endif |
+ |
552 |
+} |
+ strncpy(stpcpy(fpath, "/dev/mqueue"), path, sizeof(fpath) - 12); |
553 |
+ |
+ fpath[sizeof(fpath)-1] = 0; |
554 |
+_sd_hidden_ int sd_notify(int unset_environment, const char *state) { |
+ |
555 |
+#if defined(DISABLE_SYSTEMD) || !defined(__linux__) || !defined(SOCK_CLOEXEC) |
+ if (stat(fpath, &b) < 0) |
556 |
+ return 0; |
+ return -errno; |
557 |
+#else |
+ |
558 |
+ int fd = -1, r; |
+ if (a.st_dev != b.st_dev || |
559 |
+ struct msghdr msghdr; |
+ a.st_ino != b.st_ino) |
560 |
+ struct iovec iovec; |
+ return 0; |
561 |
+ union sockaddr_union sockaddr; |
+ } |
562 |
+ const char *e; |
+ |
563 |
+ |
+ return 1; |
564 |
+ if (!state) { |
+#endif |
565 |
+ r = -EINVAL; |
+} |
566 |
+ goto finish; |
+ |
567 |
+ } |
+_sd_hidden_ int sd_notify(int unset_environment, const char *state) { |
568 |
+ |
+#if defined(DISABLE_SYSTEMD) || !defined(__linux__) || !defined(SOCK_CLOEXEC) |
569 |
+ if (!(e = getenv("NOTIFY_SOCKET"))) |
+ return 0; |
570 |
+ return 0; |
+#else |
571 |
+ |
+ int fd = -1, r; |
572 |
+ /* Must be an abstract socket, or an absolute path */ |
+ struct msghdr msghdr; |
573 |
+ if ((e[0] != '@' && e[0] != '/') || e[1] == 0) { |
+ struct iovec iovec; |
574 |
+ r = -EINVAL; |
+ union sockaddr_union sockaddr; |
575 |
+ goto finish; |
+ const char *e; |
576 |
+ } |
+ |
577 |
+ |
+ if (!state) { |
578 |
+ if ((fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0)) < 0) { |
+ r = -EINVAL; |
579 |
+ r = -errno; |
+ goto finish; |
580 |
+ goto finish; |
+ } |
581 |
+ } |
+ |
582 |
+ |
+ if (!(e = getenv("NOTIFY_SOCKET"))) |
583 |
+ memset(&sockaddr, 0, sizeof(sockaddr)); |
+ return 0; |
584 |
+ sockaddr.sa.sa_family = AF_UNIX; |
+ |
585 |
+ strncpy(sockaddr.un.sun_path, e, sizeof(sockaddr.un.sun_path)); |
+ /* Must be an abstract socket, or an absolute path */ |
586 |
+ |
+ if ((e[0] != '@' && e[0] != '/') || e[1] == 0) { |
587 |
+ if (sockaddr.un.sun_path[0] == '@') |
+ r = -EINVAL; |
588 |
+ sockaddr.un.sun_path[0] = 0; |
+ goto finish; |
589 |
+ |
+ } |
590 |
+ memset(&iovec, 0, sizeof(iovec)); |
+ |
591 |
+ iovec.iov_base = (char*) state; |
+ if ((fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0)) < 0) { |
592 |
+ iovec.iov_len = strlen(state); |
+ r = -errno; |
593 |
+ |
+ goto finish; |
594 |
+ memset(&msghdr, 0, sizeof(msghdr)); |
+ } |
595 |
+ msghdr.msg_name = &sockaddr; |
+ |
596 |
+ msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + strlen(e); |
+ memset(&sockaddr, 0, sizeof(sockaddr)); |
597 |
+ |
+ sockaddr.sa.sa_family = AF_UNIX; |
598 |
+ if (msghdr.msg_namelen > sizeof(struct sockaddr_un)) |
+ strncpy(sockaddr.un.sun_path, e, sizeof(sockaddr.un.sun_path)); |
599 |
+ msghdr.msg_namelen = sizeof(struct sockaddr_un); |
+ |
600 |
+ |
+ if (sockaddr.un.sun_path[0] == '@') |
601 |
+ msghdr.msg_iov = &iovec; |
+ sockaddr.un.sun_path[0] = 0; |
602 |
+ msghdr.msg_iovlen = 1; |
+ |
603 |
+ |
+ memset(&iovec, 0, sizeof(iovec)); |
604 |
+ if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) { |
+ iovec.iov_base = (char*) state; |
605 |
+ r = -errno; |
+ iovec.iov_len = strlen(state); |
606 |
+ goto finish; |
+ |
607 |
+ } |
+ memset(&msghdr, 0, sizeof(msghdr)); |
608 |
+ |
+ msghdr.msg_name = &sockaddr; |
609 |
+ r = 1; |
+ msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + strlen(e); |
610 |
+ |
+ |
611 |
+finish: |
+ if (msghdr.msg_namelen > sizeof(struct sockaddr_un)) |
612 |
+ if (unset_environment) |
+ msghdr.msg_namelen = sizeof(struct sockaddr_un); |
613 |
+ unsetenv("NOTIFY_SOCKET"); |
+ |
614 |
+ |
+ msghdr.msg_iov = &iovec; |
615 |
+ if (fd >= 0) |
+ msghdr.msg_iovlen = 1; |
616 |
+ close(fd); |
+ |
617 |
+ |
+ if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) { |
618 |
+ return r; |
+ r = -errno; |
619 |
+#endif |
+ goto finish; |
620 |
+} |
+ } |
621 |
+ |
+ |
622 |
+_sd_hidden_ int sd_notifyf(int unset_environment, const char *format, ...) { |
+ r = 1; |
623 |
+#if defined(DISABLE_SYSTEMD) || !defined(__linux__) |
+ |
624 |
+ return 0; |
+finish: |
625 |
+#else |
+ if (unset_environment) |
626 |
+ va_list ap; |
+ unsetenv("NOTIFY_SOCKET"); |
627 |
+ char *p = NULL; |
+ |
628 |
+ int r; |
+ if (fd >= 0) |
629 |
+ |
+ close(fd); |
630 |
+ va_start(ap, format); |
+ |
631 |
+ r = vasprintf(&p, format, ap); |
+ return r; |
632 |
+ va_end(ap); |
+#endif |
633 |
+ |
+} |
634 |
+ if (r < 0 || !p) |
+ |
635 |
+ return -ENOMEM; |
+_sd_hidden_ int sd_notifyf(int unset_environment, const char *format, ...) { |
636 |
+ |
+#if defined(DISABLE_SYSTEMD) || !defined(__linux__) |
637 |
+ r = sd_notify(unset_environment, p); |
+ return 0; |
638 |
+ free(p); |
+#else |
639 |
+ |
+ va_list ap; |
640 |
+ return r; |
+ char *p = NULL; |
641 |
+#endif |
+ int r; |
642 |
+} |
+ |
643 |
+ |
+ va_start(ap, format); |
644 |
+_sd_hidden_ int sd_booted(void) { |
+ r = vasprintf(&p, format, ap); |
645 |
+#if defined(DISABLE_SYSTEMD) || !defined(__linux__) |
+ va_end(ap); |
646 |
+ return 0; |
+ |
647 |
+#else |
+ if (r < 0 || !p) |
648 |
+ |
+ return -ENOMEM; |
649 |
+ struct stat a, b; |
+ |
650 |
+ |
+ r = sd_notify(unset_environment, p); |
651 |
+ /* We simply test whether the systemd cgroup hierarchy is |
+ free(p); |
652 |
+ * mounted */ |
+ |
653 |
+ |
+ return r; |
654 |
+ if (lstat("/sys/fs/cgroup", &a) < 0) |
+#endif |
655 |
+ return 0; |
+} |
656 |
+ |
+ |
657 |
+ if (lstat("/sys/fs/cgroup/systemd", &b) < 0) |
+_sd_hidden_ int sd_booted(void) { |
658 |
+ return 0; |
+#if defined(DISABLE_SYSTEMD) || !defined(__linux__) |
659 |
+ |
+ return 0; |
660 |
+ return a.st_dev != b.st_dev; |
+#else |
661 |
+#endif |
+ |
662 |
+} |
+ struct stat a, b; |
663 |
diff --git a/PCSC/src/sd-daemon.h b/PCSC/src/sd-daemon.h |
+ |
664 |
new file mode 100644 |
+ /* We simply test whether the systemd cgroup hierarchy is |
665 |
index 0000000..46dc7fd |
+ * mounted */ |
666 |
--- /dev/null |
+ |
667 |
+++ b/PCSC/src/sd-daemon.h |
+ if (lstat("/sys/fs/cgroup", &a) < 0) |
668 |
@@ -0,0 +1,277 @@ |
+ return 0; |
669 |
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ |
+ |
670 |
+ |
+ if (lstat("/sys/fs/cgroup/systemd", &b) < 0) |
671 |
+#ifndef foosddaemonhfoo |
+ return 0; |
672 |
+#define foosddaemonhfoo |
+ |
673 |
+ |
+ return a.st_dev != b.st_dev; |
674 |
+/*** |
+#endif |
675 |
+ Copyright 2010 Lennart Poettering |
+} |
676 |
+ |
diff --git a/PCSC/src/sd-daemon.h b/PCSC/src/sd-daemon.h |
677 |
+ Permission is hereby granted, free of charge, to any person |
new file mode 100644 |
678 |
+ obtaining a copy of this software and associated documentation files |
index 0000000..46dc7fd |
679 |
+ (the "Software"), to deal in the Software without restriction, |
--- /dev/null |
680 |
+ including without limitation the rights to use, copy, modify, merge, |
+++ b/PCSC/src/sd-daemon.h |
681 |
+ publish, distribute, sublicense, and/or sell copies of the Software, |
@@ -0,0 +1,277 @@ |
682 |
+ and to permit persons to whom the Software is furnished to do so, |
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ |
683 |
+ subject to the following conditions: |
+ |
684 |
+ |
+#ifndef foosddaemonhfoo |
685 |
+ The above copyright notice and this permission notice shall be |
+#define foosddaemonhfoo |
686 |
+ included in all copies or substantial portions of the Software. |
+ |
687 |
+ |
+/*** |
688 |
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
+ Copyright 2010 Lennart Poettering |
689 |
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
+ |
690 |
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
+ Permission is hereby granted, free of charge, to any person |
691 |
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS |
+ obtaining a copy of this software and associated documentation files |
692 |
+ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
+ (the "Software"), to deal in the Software without restriction, |
693 |
+ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
+ including without limitation the rights to use, copy, modify, merge, |
694 |
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
+ publish, distribute, sublicense, and/or sell copies of the Software, |
695 |
+ SOFTWARE. |
+ and to permit persons to whom the Software is furnished to do so, |
696 |
+***/ |
+ subject to the following conditions: |
697 |
+ |
+ |
698 |
+#include <sys/types.h> |
+ The above copyright notice and this permission notice shall be |
699 |
+#include <inttypes.h> |
+ included in all copies or substantial portions of the Software. |
700 |
+ |
+ |
701 |
+#ifdef __cplusplus |
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
702 |
+extern "C" { |
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
703 |
+#endif |
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
704 |
+ |
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS |
705 |
+/* |
+ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
706 |
+ Reference implementation of a few systemd related interfaces for |
+ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
707 |
+ writing daemons. These interfaces are trivial to implement. To |
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
708 |
+ simplify porting we provide this reference implementation. |
+ SOFTWARE. |
709 |
+ Applications are welcome to reimplement the algorithms described |
+***/ |
710 |
+ here if they do not want to include these two source files. |
+ |
711 |
+ |
+#include <sys/types.h> |
712 |
+ The following functionality is provided: |
+#include <inttypes.h> |
713 |
+ |
+ |
714 |
+ - Support for logging with log levels on stderr |
+#ifdef __cplusplus |
715 |
+ - File descriptor passing for socket-based activation |
+extern "C" { |
716 |
+ - Daemon startup and status notification |
+#endif |
717 |
+ - Detection of systemd boots |
+ |
718 |
+ |
+/* |
719 |
+ You may compile this with -DDISABLE_SYSTEMD to disable systemd |
+ Reference implementation of a few systemd related interfaces for |
720 |
+ support. This makes all those calls NOPs that are directly related to |
+ writing daemons. These interfaces are trivial to implement. To |
721 |
+ systemd (i.e. only sd_is_xxx() will stay useful). |
+ simplify porting we provide this reference implementation. |
722 |
+ |
+ Applications are welcome to reimplement the algorithms described |
723 |
+ Since this is drop-in code we don't want any of our symbols to be |
+ here if they do not want to include these two source files. |
724 |
+ exported in any case. Hence we declare hidden visibility for all of |
+ |
725 |
+ them. |
+ The following functionality is provided: |
726 |
+ |
+ |
727 |
+ You may find an up-to-date version of these source files online: |
+ - Support for logging with log levels on stderr |
728 |
+ |
+ - File descriptor passing for socket-based activation |
729 |
|
+ - Daemon startup and status notification |
730 |
|
+ - Detection of systemd boots |
731 |
|
+ |
732 |
|
+ You may compile this with -DDISABLE_SYSTEMD to disable systemd |
733 |
|
+ support. This makes all those calls NOPs that are directly related to |
734 |
|
+ systemd (i.e. only sd_is_xxx() will stay useful). |
735 |
|
+ |
736 |
|
+ Since this is drop-in code we don't want any of our symbols to be |
737 |
|
+ exported in any case. Hence we declare hidden visibility for all of |
738 |
|
+ them. |
739 |
|
+ |
740 |
|
+ You may find an up-to-date version of these source files online: |
741 |
|
+ |
742 |
+ http://cgit.freedesktop.org/systemd/plain/src/sd-daemon.h |
+ http://cgit.freedesktop.org/systemd/plain/src/sd-daemon.h |
743 |
+ http://cgit.freedesktop.org/systemd/plain/src/sd-daemon.c |
+ http://cgit.freedesktop.org/systemd/plain/src/sd-daemon.c |
744 |
+ |
+ |
745 |
+ This should compile on non-Linux systems, too, but with the |
+ This should compile on non-Linux systems, too, but with the |
746 |
+ exception of the sd_is_xxx() calls all functions will become NOPs. |
+ exception of the sd_is_xxx() calls all functions will become NOPs. |
747 |
+ |
+ |
748 |
+ See sd-daemon(7) for more information. |
+ See sd-daemon(7) for more information. |
749 |
+*/ |
+*/ |
750 |
+ |
+ |
751 |
+#ifndef _sd_printf_attr_ |
+#ifndef _sd_printf_attr_ |
752 |
+#if __GNUC__ >= 4 |
+#if __GNUC__ >= 4 |
753 |
+#define _sd_printf_attr_(a,b) __attribute__ ((format (printf, a, b))) |
+#define _sd_printf_attr_(a,b) __attribute__ ((format (printf, a, b))) |
754 |
+#else |
+#else |
755 |
+#define _sd_printf_attr_(a,b) |
+#define _sd_printf_attr_(a,b) |
756 |
+#endif |
+#endif |
757 |
+#endif |
+#endif |
758 |
+ |
+ |
759 |
+/* |
+/* |
760 |
+ Log levels for usage on stderr: |
+ Log levels for usage on stderr: |
761 |
+ |
+ |
762 |
+ fprintf(stderr, SD_NOTICE "Hello World!\n"); |
+ fprintf(stderr, SD_NOTICE "Hello World!\n"); |
763 |
+ |
+ |
764 |
+ This is similar to printk() usage in the kernel. |
+ This is similar to printk() usage in the kernel. |
765 |
+*/ |
+*/ |
766 |
+#define SD_EMERG "<0>" /* system is unusable */ |
+#define SD_EMERG "<0>" /* system is unusable */ |
767 |
+#define SD_ALERT "<1>" /* action must be taken immediately */ |
+#define SD_ALERT "<1>" /* action must be taken immediately */ |
768 |
+#define SD_CRIT "<2>" /* critical conditions */ |
+#define SD_CRIT "<2>" /* critical conditions */ |
769 |
+#define SD_ERR "<3>" /* error conditions */ |
+#define SD_ERR "<3>" /* error conditions */ |
770 |
+#define SD_WARNING "<4>" /* warning conditions */ |
+#define SD_WARNING "<4>" /* warning conditions */ |
771 |
+#define SD_NOTICE "<5>" /* normal but significant condition */ |
+#define SD_NOTICE "<5>" /* normal but significant condition */ |
772 |
+#define SD_INFO "<6>" /* informational */ |
+#define SD_INFO "<6>" /* informational */ |
773 |
+#define SD_DEBUG "<7>" /* debug-level messages */ |
+#define SD_DEBUG "<7>" /* debug-level messages */ |
774 |
+ |
+ |
775 |
+/* The first passed file descriptor is fd 3 */ |
+/* The first passed file descriptor is fd 3 */ |
776 |
+#define SD_LISTEN_FDS_START 3 |
+#define SD_LISTEN_FDS_START 3 |
777 |
+ |
+ |
778 |
+/* |
+/* |
779 |
+ Returns how many file descriptors have been passed, or a negative |
+ Returns how many file descriptors have been passed, or a negative |
780 |
+ errno code on failure. Optionally, removes the $LISTEN_FDS and |
+ errno code on failure. Optionally, removes the $LISTEN_FDS and |
781 |
+ $LISTEN_PID file descriptors from the environment (recommended, but |
+ $LISTEN_PID file descriptors from the environment (recommended, but |
782 |
+ problematic in threaded environments). If r is the return value of |
+ problematic in threaded environments). If r is the return value of |
783 |
+ this function you'll find the file descriptors passed as fds |
+ this function you'll find the file descriptors passed as fds |
784 |
+ SD_LISTEN_FDS_START to SD_LISTEN_FDS_START+r-1. Returns a negative |
+ SD_LISTEN_FDS_START to SD_LISTEN_FDS_START+r-1. Returns a negative |
785 |
+ errno style error code on failure. This function call ensures that |
+ errno style error code on failure. This function call ensures that |
786 |
+ the FD_CLOEXEC flag is set for the passed file descriptors, to make |
+ the FD_CLOEXEC flag is set for the passed file descriptors, to make |
787 |
+ sure they are not passed on to child processes. If FD_CLOEXEC shall |
+ sure they are not passed on to child processes. If FD_CLOEXEC shall |
788 |
+ not be set, the caller needs to unset it after this call for all file |
+ not be set, the caller needs to unset it after this call for all file |
789 |
+ descriptors that are used. |
+ descriptors that are used. |
790 |
+ |
+ |
791 |
+ See sd_listen_fds(3) for more information. |
+ See sd_listen_fds(3) for more information. |
792 |
+*/ |
+*/ |
793 |
+int sd_listen_fds(int unset_environment); |
+int sd_listen_fds(int unset_environment); |
794 |
+ |
+ |
795 |
+/* |
+/* |
796 |
+ Helper call for identifying a passed file descriptor. Returns 1 if |
+ Helper call for identifying a passed file descriptor. Returns 1 if |
797 |
+ the file descriptor is a FIFO in the file system stored under the |
+ the file descriptor is a FIFO in the file system stored under the |
798 |
+ specified path, 0 otherwise. If path is NULL a path name check will |
+ specified path, 0 otherwise. If path is NULL a path name check will |
799 |
+ not be done and the call only verifies if the file descriptor |
+ not be done and the call only verifies if the file descriptor |
800 |
+ refers to a FIFO. Returns a negative errno style error code on |
+ refers to a FIFO. Returns a negative errno style error code on |
801 |
+ failure. |
+ failure. |
802 |
+ |
+ |
803 |
+ See sd_is_fifo(3) for more information. |
+ See sd_is_fifo(3) for more information. |
804 |
+*/ |
+*/ |
805 |
+int sd_is_fifo(int fd, const char *path); |
+int sd_is_fifo(int fd, const char *path); |
806 |
+ |
+ |
807 |
+/* |
+/* |
808 |
+ Helper call for identifying a passed file descriptor. Returns 1 if |
+ Helper call for identifying a passed file descriptor. Returns 1 if |
809 |
+ the file descriptor is a special character device on the file |
+ the file descriptor is a special character device on the file |
810 |
+ system stored under the specified path, 0 otherwise. |
+ system stored under the specified path, 0 otherwise. |
811 |
+ If path is NULL a path name check will not be done and the call |
+ If path is NULL a path name check will not be done and the call |
812 |
+ only verifies if the file descriptor refers to a special character. |
+ only verifies if the file descriptor refers to a special character. |
813 |
+ Returns a negative errno style error code on failure. |
+ Returns a negative errno style error code on failure. |
814 |
+ |
+ |
815 |
+ See sd_is_special(3) for more information. |
+ See sd_is_special(3) for more information. |
816 |
+*/ |
+*/ |
817 |
+int sd_is_special(int fd, const char *path); |
+int sd_is_special(int fd, const char *path); |
818 |
+ |
+ |
819 |
+/* |
+/* |
820 |
+ Helper call for identifying a passed file descriptor. Returns 1 if |
+ Helper call for identifying a passed file descriptor. Returns 1 if |
821 |
+ the file descriptor is a socket of the specified family (AF_INET, |
+ the file descriptor is a socket of the specified family (AF_INET, |
822 |
+ ...) and type (SOCK_DGRAM, SOCK_STREAM, ...), 0 otherwise. If |
+ ...) and type (SOCK_DGRAM, SOCK_STREAM, ...), 0 otherwise. If |
823 |
+ family is 0 a socket family check will not be done. If type is 0 a |
+ family is 0 a socket family check will not be done. If type is 0 a |
824 |
+ socket type check will not be done and the call only verifies if |
+ socket type check will not be done and the call only verifies if |
825 |
+ the file descriptor refers to a socket. If listening is > 0 it is |
+ the file descriptor refers to a socket. If listening is > 0 it is |
826 |
+ verified that the socket is in listening mode. (i.e. listen() has |
+ verified that the socket is in listening mode. (i.e. listen() has |
827 |
+ been called) If listening is == 0 it is verified that the socket is |
+ been called) If listening is == 0 it is verified that the socket is |
828 |
+ not in listening mode. If listening is < 0 no listening mode check |
+ not in listening mode. If listening is < 0 no listening mode check |
829 |
+ is done. Returns a negative errno style error code on failure. |
+ is done. Returns a negative errno style error code on failure. |
830 |
+ |
+ |
831 |
+ See sd_is_socket(3) for more information. |
+ See sd_is_socket(3) for more information. |
832 |
+*/ |
+*/ |
833 |
+int sd_is_socket(int fd, int family, int type, int listening); |
+int sd_is_socket(int fd, int family, int type, int listening); |
834 |
+ |
+ |
835 |
+/* |
+/* |
836 |
+ Helper call for identifying a passed file descriptor. Returns 1 if |
+ Helper call for identifying a passed file descriptor. Returns 1 if |
837 |
+ the file descriptor is an Internet socket, of the specified family |
+ the file descriptor is an Internet socket, of the specified family |
838 |
+ (either AF_INET or AF_INET6) and the specified type (SOCK_DGRAM, |
+ (either AF_INET or AF_INET6) and the specified type (SOCK_DGRAM, |
839 |
+ SOCK_STREAM, ...), 0 otherwise. If version is 0 a protocol version |
+ SOCK_STREAM, ...), 0 otherwise. If version is 0 a protocol version |
840 |
+ check is not done. If type is 0 a socket type check will not be |
+ check is not done. If type is 0 a socket type check will not be |
841 |
+ done. If port is 0 a socket port check will not be done. The |
+ done. If port is 0 a socket port check will not be done. The |
842 |
+ listening flag is used the same way as in sd_is_socket(). Returns a |
+ listening flag is used the same way as in sd_is_socket(). Returns a |
843 |
+ negative errno style error code on failure. |
+ negative errno style error code on failure. |
844 |
+ |
+ |
845 |
+ See sd_is_socket_inet(3) for more information. |
+ See sd_is_socket_inet(3) for more information. |
846 |
+*/ |
+*/ |
847 |
+int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port); |
+int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port); |
848 |
+ |
+ |
849 |
+/* |
+/* |
850 |
+ Helper call for identifying a passed file descriptor. Returns 1 if |
+ Helper call for identifying a passed file descriptor. Returns 1 if |
851 |
+ the file descriptor is an AF_UNIX socket of the specified type |
+ the file descriptor is an AF_UNIX socket of the specified type |
852 |
+ (SOCK_DGRAM, SOCK_STREAM, ...) and path, 0 otherwise. If type is 0 |
+ (SOCK_DGRAM, SOCK_STREAM, ...) and path, 0 otherwise. If type is 0 |
853 |
+ a socket type check will not be done. If path is NULL a socket path |
+ a socket type check will not be done. If path is NULL a socket path |
854 |
+ check will not be done. For normal AF_UNIX sockets set length to |
+ check will not be done. For normal AF_UNIX sockets set length to |
855 |
+ 0. For abstract namespace sockets set length to the length of the |
+ 0. For abstract namespace sockets set length to the length of the |
856 |
+ socket name (including the initial 0 byte), and pass the full |
+ socket name (including the initial 0 byte), and pass the full |
857 |
+ socket path in path (including the initial 0 byte). The listening |
+ socket path in path (including the initial 0 byte). The listening |
858 |
+ flag is used the same way as in sd_is_socket(). Returns a negative |
+ flag is used the same way as in sd_is_socket(). Returns a negative |
859 |
+ errno style error code on failure. |
+ errno style error code on failure. |
860 |
+ |
+ |
861 |
+ See sd_is_socket_unix(3) for more information. |
+ See sd_is_socket_unix(3) for more information. |
862 |
+*/ |
+*/ |
863 |
+int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length); |
+int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length); |
864 |
+ |
+ |
865 |
+/* |
+/* |
866 |
+ Helper call for identifying a passed file descriptor. Returns 1 if |
+ Helper call for identifying a passed file descriptor. Returns 1 if |
867 |
+ the file descriptor is a POSIX Message Queue of the specified name, |
+ the file descriptor is a POSIX Message Queue of the specified name, |
868 |
+ 0 otherwise. If path is NULL a message queue name check is not |
+ 0 otherwise. If path is NULL a message queue name check is not |
869 |
+ done. Returns a negative errno style error code on failure. |
+ done. Returns a negative errno style error code on failure. |
870 |
+*/ |
+*/ |
871 |
+int sd_is_mq(int fd, const char *path); |
+int sd_is_mq(int fd, const char *path); |
872 |
+ |
+ |
873 |
+/* |
+/* |
874 |
+ Informs systemd about changed daemon state. This takes a number of |
+ Informs systemd about changed daemon state. This takes a number of |
875 |
+ newline separated environment-style variable assignments in a |
+ newline separated environment-style variable assignments in a |
876 |
+ string. The following variables are known: |
+ string. The following variables are known: |
877 |
+ |
+ |
878 |
+ READY=1 Tells systemd that daemon startup is finished (only |
+ READY=1 Tells systemd that daemon startup is finished (only |
879 |
+ relevant for services of Type=notify). The passed |
+ relevant for services of Type=notify). The passed |
880 |
+ argument is a boolean "1" or "0". Since there is |
+ argument is a boolean "1" or "0". Since there is |
881 |
+ little value in signaling non-readiness the only |
+ little value in signaling non-readiness the only |
882 |
+ value daemons should send is "READY=1". |
+ value daemons should send is "READY=1". |
883 |
+ |
+ |
884 |
+ STATUS=... Passes a single-line status string back to systemd |
+ STATUS=... Passes a single-line status string back to systemd |
885 |
+ that describes the daemon state. This is free-from |
+ that describes the daemon state. This is free-from |
886 |
+ and can be used for various purposes: general state |
+ and can be used for various purposes: general state |
887 |
+ feedback, fsck-like programs could pass completion |
+ feedback, fsck-like programs could pass completion |
888 |
+ percentages and failing programs could pass a human |
+ percentages and failing programs could pass a human |
889 |
+ readable error message. Example: "STATUS=Completed |
+ readable error message. Example: "STATUS=Completed |
890 |
+ 66% of file system check..." |
+ 66% of file system check..." |
891 |
+ |
+ |
892 |
+ ERRNO=... If a daemon fails, the errno-style error code, |
+ ERRNO=... If a daemon fails, the errno-style error code, |
893 |
+ formatted as string. Example: "ERRNO=2" for ENOENT. |
+ formatted as string. Example: "ERRNO=2" for ENOENT. |
894 |
+ |
+ |
895 |
+ BUSERROR=... If a daemon fails, the D-Bus error-style error |
+ BUSERROR=... If a daemon fails, the D-Bus error-style error |
896 |
+ code. Example: "BUSERROR=org.freedesktop.DBus.Error.TimedOut" |
+ code. Example: "BUSERROR=org.freedesktop.DBus.Error.TimedOut" |
897 |
+ |
+ |
898 |
+ MAINPID=... The main pid of a daemon, in case systemd did not |
+ MAINPID=... The main pid of a daemon, in case systemd did not |
899 |
+ fork off the process itself. Example: "MAINPID=4711" |
+ fork off the process itself. Example: "MAINPID=4711" |
900 |
+ |
+ |
901 |
+ Daemons can choose to send additional variables. However, it is |
+ Daemons can choose to send additional variables. However, it is |
902 |
+ recommended to prefix variable names not listed above with X_. |
+ recommended to prefix variable names not listed above with X_. |
903 |
+ |
+ |
904 |
+ Returns a negative errno-style error code on failure. Returns > 0 |
+ Returns a negative errno-style error code on failure. Returns > 0 |
905 |
+ if systemd could be notified, 0 if it couldn't possibly because |
+ if systemd could be notified, 0 if it couldn't possibly because |
906 |
+ systemd is not running. |
+ systemd is not running. |
907 |
+ |
+ |
908 |
+ Example: When a daemon finished starting up, it could issue this |
+ Example: When a daemon finished starting up, it could issue this |
909 |
+ call to notify systemd about it: |
+ call to notify systemd about it: |
910 |
+ |
+ |
911 |
+ sd_notify(0, "READY=1"); |
+ sd_notify(0, "READY=1"); |
912 |
+ |
+ |
913 |
+ See sd_notifyf() for more complete examples. |
+ See sd_notifyf() for more complete examples. |
914 |
+ |
+ |
915 |
+ See sd_notify(3) for more information. |
+ See sd_notify(3) for more information. |
916 |
+*/ |
+*/ |
917 |
+int sd_notify(int unset_environment, const char *state); |
+int sd_notify(int unset_environment, const char *state); |
918 |
+ |
+ |
919 |
+/* |
+/* |
920 |
+ Similar to sd_notify() but takes a format string. |
+ Similar to sd_notify() but takes a format string. |
921 |
+ |
+ |
922 |
+ Example 1: A daemon could send the following after initialization: |
+ Example 1: A daemon could send the following after initialization: |
923 |
+ |
+ |
924 |
+ sd_notifyf(0, "READY=1\n" |
+ sd_notifyf(0, "READY=1\n" |
925 |
+ "STATUS=Processing requests...\n" |
+ "STATUS=Processing requests...\n" |
926 |
+ "MAINPID=%lu", |
+ "MAINPID=%lu", |
927 |
+ (unsigned long) getpid()); |
+ (unsigned long) getpid()); |
928 |
+ |
+ |
929 |
+ Example 2: A daemon could send the following shortly before |
+ Example 2: A daemon could send the following shortly before |
930 |
+ exiting, on failure: |
+ exiting, on failure: |
931 |
+ |
+ |
932 |
+ sd_notifyf(0, "STATUS=Failed to start up: %s\n" |
+ sd_notifyf(0, "STATUS=Failed to start up: %s\n" |
933 |
+ "ERRNO=%i", |
+ "ERRNO=%i", |
934 |
+ strerror(errno), |
+ strerror(errno), |
935 |
+ errno); |
+ errno); |
936 |
+ |
+ |
937 |
+ See sd_notifyf(3) for more information. |
+ See sd_notifyf(3) for more information. |
938 |
+*/ |
+*/ |
939 |
+int sd_notifyf(int unset_environment, const char *format, ...) _sd_printf_attr_(2,3); |
+int sd_notifyf(int unset_environment, const char *format, ...) _sd_printf_attr_(2,3); |
940 |
+ |
+ |
941 |
+/* |
+/* |
942 |
+ Returns > 0 if the system was booted with systemd. Returns < 0 on |
+ Returns > 0 if the system was booted with systemd. Returns < 0 on |
943 |
+ error. Returns 0 if the system was not booted with systemd. Note |
+ error. Returns 0 if the system was not booted with systemd. Note |
944 |
+ that all of the functions above handle non-systemd boots just |
+ that all of the functions above handle non-systemd boots just |
945 |
+ fine. You should NOT protect them with a call to this function. Also |
+ fine. You should NOT protect them with a call to this function. Also |
946 |
+ note that this function checks whether the system, not the user |
+ note that this function checks whether the system, not the user |
947 |
+ session is controlled by systemd. However the functions above work |
+ session is controlled by systemd. However the functions above work |
948 |
+ for both user and system services. |
+ for both user and system services. |
949 |
+ |
+ |
950 |
+ See sd_booted(3) for more information. |
+ See sd_booted(3) for more information. |
951 |
+*/ |
+*/ |
952 |
+int sd_booted(void); |
+int sd_booted(void); |
953 |
+ |
+ |
954 |
+#ifdef __cplusplus |
+#ifdef __cplusplus |
955 |
+} |
+} |
956 |
+#endif |
+#endif |
957 |
+ |
+ |
958 |
+#endif |
+#endif |
959 |
diff --git a/PCSC/src/winscard_msg.h b/PCSC/src/winscard_msg.h |
diff --git a/PCSC/src/winscard_msg.h b/PCSC/src/winscard_msg.h |
960 |
index b2b6f90..b8c490c 100644 |
index b2b6f90..b8c490c 100644 |
961 |
--- a/PCSC/src/winscard_msg.h |
--- a/PCSC/src/winscard_msg.h |
962 |
+++ b/PCSC/src/winscard_msg.h |
+++ b/PCSC/src/winscard_msg.h |
963 |
@@ -252,6 +252,7 @@ |
@@ -252,6 +252,7 @@ |
964 |
|
|
965 |
#ifdef PCSCD |
#ifdef PCSCD |
966 |
int32_t InitializeSocket(void); |
int32_t InitializeSocket(void); |
967 |
+ int32_t ListenExistingSocket(int fd); |
+ int32_t ListenExistingSocket(int fd); |
968 |
int32_t ProcessEventsServer(/*@out@*/ uint32_t *); |
int32_t ProcessEventsServer(/*@out@*/ uint32_t *); |
969 |
#else |
#else |
970 |
char *getSocketName(void); |
char *getSocketName(void); |
971 |
diff --git a/PCSC/src/winscard_msg_srv.c b/PCSC/src/winscard_msg_srv.c |
diff --git a/PCSC/src/winscard_msg_srv.c b/PCSC/src/winscard_msg_srv.c |
972 |
index 19ea363..4bb5bdc 100644 |
index 19ea363..4bb5bdc 100644 |
973 |
--- a/PCSC/src/winscard_msg_srv.c |
--- a/PCSC/src/winscard_msg_srv.c |
974 |
+++ b/PCSC/src/winscard_msg_srv.c |
+++ b/PCSC/src/winscard_msg_srv.c |
975 |
@@ -39,6 +39,7 @@ |
@@ -39,6 +39,7 @@ |
976 |
|
|
977 |
#include "misc.h" |
#include "misc.h" |
978 |
#include "pcscd.h" |
#include "pcscd.h" |
979 |
+#include "sd-daemon.h" |
+#include "sd-daemon.h" |
980 |
#include "winscard.h" |
#include "winscard.h" |
981 |
#include "debuglog.h" |
#include "debuglog.h" |
982 |
#include "winscard_msg.h" |
#include "winscard_msg.h" |
983 |
@@ -138,6 +139,30 @@ INTERNAL int32_t InitializeSocket(void) |
@@ -138,6 +139,30 @@ INTERNAL int32_t InitializeSocket(void) |
984 |
} |
} |
985 |
|
|
986 |
/** |
/** |
987 |
+ * @brief Acquires a socket passed in from systemd. |
+ * @brief Acquires a socket passed in from systemd. |
988 |
+ * |
+ * |
989 |
+ * This is called by the server to start listening on an existing socket for |
+ * This is called by the server to start listening on an existing socket for |
990 |
+ * local IPC with the clients. |
+ * local IPC with the clients. |
991 |
+ * |
+ * |
992 |
+ * @param fd The file descriptor to start listening on. |
+ * @param fd The file descriptor to start listening on. |
993 |
+ * |
+ * |
994 |
+ * @return Error code. |
+ * @return Error code. |
995 |
+ * @retval 0 Success |
+ * @retval 0 Success |
996 |
+ * @retval -1 Passed FD is not an UNIX socket. |
+ * @retval -1 Passed FD is not an UNIX socket. |
997 |
+ */ |
+ */ |
998 |
+INTERNAL int32_t ListenExistingSocket(int fd) |
+INTERNAL int32_t ListenExistingSocket(int fd) |
999 |
+{ |
+{ |
1000 |
+ if (!sd_is_socket(fd, AF_UNIX, SOCK_STREAM, -1)) |
+ if (!sd_is_socket(fd, AF_UNIX, SOCK_STREAM, -1)) |
1001 |
+ { |
+ { |
1002 |
+ Log1(PCSC_LOG_CRITICAL, "Passed FD is not an UNIX socket"); |
+ Log1(PCSC_LOG_CRITICAL, "Passed FD is not an UNIX socket"); |
1003 |
+ return -1; |
+ return -1; |
1004 |
+ } |
+ } |
1005 |
+ |
+ |
1006 |
+ commonSocket = fd; |
+ commonSocket = fd; |
1007 |
+ return 0; |
+ return 0; |
1008 |
+} |
+} |
1009 |
+ |
+ |
1010 |
+/** |
+/** |
1011 |
* @brief Looks for messages sent by clients. |
* @brief Looks for messages sent by clients. |
1012 |
* |
* |
1013 |
* This is called by the Server's function \c SVCServiceRunLoop(). |
* This is called by the Server's function \c SVCServiceRunLoop(). |
1014 |
-- |
-- |
1015 |
1.7.5.4 |
1.7.5.4 |
1016 |
|
|