Magellan Linux

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1573 - (hide annotations) (download)
Thu Nov 24 20:58:47 2011 UTC (12 years, 6 months ago) by niro
File size: 32205 byte(s)
systemd patches
1 niro 1573 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