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