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 1574 - (hide 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 niro 1574 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 niro 1573
6 niro 1574 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 niro 1573
11 niro 1574 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 niro 1573 + http://cgit.freedesktop.org/systemd/plain/src/sd-daemon.h
743     + http://cgit.freedesktop.org/systemd/plain/src/sd-daemon.c
744 niro 1574 +
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 niro 1573 --
1015     1.7.5.4
1016 niro 1574