Magellan Linux

Contents of /trunk/pcsc-lite/patches/pcsc-lite-1.7.4-systemd-socket-activation.patch

Parent Directory Parent Directory | Revision Log Revision Log


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