Magellan Linux

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.1573  
changed lines
  Added in v.1574