[pcsc-lite] Converted initscript to systemd service file (#617330)

Kalev Lember kalev at fedoraproject.org
Fri Jul 15 08:21:58 UTC 2011


commit 305f583cd4ae4072750b1cbd81d8c05e048c8d43
Author: Kalev Lember <kalevlember at gmail.com>
Date:   Fri Jul 15 10:55:47 2011 +0300

    Converted initscript to systemd service file (#617330)
    
    Thanks to Jóhann B. Guðmundsson for initial work.

 0001-Support-systemd-socket-activation.patch | 1016 ++++++++++++++++++++++++++
 0002-Add-disable-autostart-option.patch      |   94 +++
 0003-Install-systemd-service-files.patch     |  144 ++++
 pcsc-lite-1.6.7-noautostart.patch            |  100 ---
 pcsc-lite.spec                               |   73 ++-
 pcscd.init                                   |   84 ---
 6 files changed, 1308 insertions(+), 203 deletions(-)
---
diff --git a/0001-Support-systemd-socket-activation.patch b/0001-Support-systemd-socket-activation.patch
new file mode 100644
index 0000000..c23bb7e
--- /dev/null
+++ b/0001-Support-systemd-socket-activation.patch
@@ -0,0 +1,1016 @@
+From ed83954ce404d0e58a04dfe7bfd379203f7830b5 Mon Sep 17 00:00:00 2001
+From: Kalev Lember <kalev at smartlink.ee>
+Date: Thu, 23 Jun 2011 21:58:56 +0300
+Subject: [PATCH 1/3] Support systemd socket activation
+
+Add systemd socket-based activation support to pcscd as an alternative
+to the existing autostart code which used forking from the user space
+library. Systemd socket activation makes it possible to start pcscd on
+demand by systemd when a request is sent on the IPC socket.
+
+The implementation uses the $LISTEN_FDS/$LISTEN_PID env var parsing code
+from systemd's sd-daemon.[ch] copy library.
+---
+ PCSC/src/Makefile.am        |    6 +
+ 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
+
+diff --git a/PCSC/src/Makefile.am b/PCSC/src/Makefile.am
+index 2bd2f11..1b70466 100644
+--- a/PCSC/src/Makefile.am
++++ b/PCSC/src/Makefile.am
+@@ -67,6 +67,8 @@ pcscd_SOURCES = \
+ 	prothandler.h \
+ 	readerfactory.c \
+ 	readerfactory.h \
++	sd-daemon.c \
++	sd-daemon.h \
+ 	simclist.c \
+ 	simclist.h \
+ 	strlcat.c \
+@@ -95,6 +97,10 @@ fix-rights: install-sbinPROGRAMS
+ 	chgrp pcscd $(DESTDIR)$(sbindir)/pcscd
+ 	chmod g+s $(DESTDIR)$(sbindir)/pcscd
+ 
++update-systemd:
++	curl http://cgit.freedesktop.org/systemd/plain/src/sd-daemon.c > sd-daemon.c
++	curl http://cgit.freedesktop.org/systemd/plain/src/sd-daemon.h > sd-daemon.h
++
+ testpcsc_SOURCES = testpcsc.c
+ testpcsc_LDADD = libpcsclite.la
+ 
+diff --git a/PCSC/src/pcscdaemon.c b/PCSC/src/pcscdaemon.c
+index 6abc328..609f981 100644
+--- a/PCSC/src/pcscdaemon.c
++++ b/PCSC/src/pcscdaemon.c
+@@ -37,6 +37,7 @@
+ #include "pcsclite.h"
+ #include "pcscd.h"
+ #include "debuglog.h"
++#include "sd-daemon.h"
+ #include "winscard_msg.h"
+ #include "winscard_svc.h"
+ #include "sys_generic.h"
+@@ -54,6 +55,7 @@
+ char AraKiri = FALSE;
+ static char Init = TRUE;
+ char AutoExit = FALSE;
++char SocketActivated = FALSE;
+ static int ExitValue = EXIT_FAILURE;
+ int HPForceReaderPolling = 0;
+ static int pipefd[] = {-1, -1};
+@@ -316,6 +318,20 @@ int main(int argc, char **argv)
+ 	}
+ 
+ 	/*
++	 * Check if systemd passed us any file descriptors
++	 */
++	rv = sd_listen_fds(0);
++	if (rv > 1)
++	{
++		Log1(PCSC_LOG_CRITICAL, "Too many file descriptors received");
++		return EXIT_FAILURE;
++	}
++	else if (rv == 1)
++		SocketActivated = TRUE;
++	else
++		SocketActivated = FALSE;
++
++	/*
+ 	 * test the presence of /var/run/pcscd/pcscd.comm
+ 	 */
+ 
+@@ -366,16 +382,19 @@ int main(int argc, char **argv)
+ 				return EXIT_FAILURE;
+ 			}
+ 
+-			Log1(PCSC_LOG_CRITICAL,
+-				"file " PCSCLITE_CSOCK_NAME " already exists.");
+-			Log1(PCSC_LOG_CRITICAL,
+-				"Maybe another pcscd is running?");
+-			Log1(PCSC_LOG_CRITICAL,
+-				"I can't read process pid from " PCSCLITE_RUN_PID);
+-			Log1(PCSC_LOG_CRITICAL, "Remove " PCSCLITE_CSOCK_NAME);
+-			Log1(PCSC_LOG_CRITICAL,
+-				"if pcscd is not running to clear this message.");
+-			return EXIT_FAILURE;
++			if (!SocketActivated)
++			{
++				Log1(PCSC_LOG_CRITICAL,
++					"file " PCSCLITE_CSOCK_NAME " already exists.");
++				Log1(PCSC_LOG_CRITICAL,
++					"Maybe another pcscd is running?");
++				Log1(PCSC_LOG_CRITICAL,
++					"I can't read process pid from " PCSCLITE_RUN_PID);
++				Log1(PCSC_LOG_CRITICAL, "Remove " PCSCLITE_CSOCK_NAME);
++				Log1(PCSC_LOG_CRITICAL,
++					"if pcscd is not running to clear this message.");
++				return EXIT_FAILURE;
++			}
+ 		}
+ 	}
+ 	else
+@@ -568,7 +587,11 @@ int main(int argc, char **argv)
+ 	/*
+ 	 * Initialize the comm structure
+ 	 */
+-	rv = InitializeSocket();
++	if (SocketActivated)
++		rv = ListenExistingSocket(SD_LISTEN_FDS_START + 0);
++	else
++		rv = InitializeSocket();
++
+ 	if (rv)
+ 	{
+ 		Log1(PCSC_LOG_CRITICAL, "Error initializing pcscd.");
+@@ -652,10 +675,13 @@ static void clean_temp_files(void)
+ {
+ 	int rv;
+ 
+-	rv = remove(PCSCLITE_CSOCK_NAME);
+-	if (rv != 0)
+-		Log2(PCSC_LOG_ERROR, "Cannot remove " PCSCLITE_CSOCK_NAME ": %s",
+-			strerror(errno));
++	if (!SocketActivated)
++	{
++		rv = remove(PCSCLITE_CSOCK_NAME);
++		if (rv != 0)
++			Log2(PCSC_LOG_ERROR, "Cannot remove " PCSCLITE_CSOCK_NAME ": %s",
++				strerror(errno));
++	}
+ 
+ 	rv = remove(PCSCLITE_RUN_PID);
+ 	if (rv != 0)
+diff --git a/PCSC/src/sd-daemon.c b/PCSC/src/sd-daemon.c
+new file mode 100644
+index 0000000..a2ec74c
+--- /dev/null
++++ b/PCSC/src/sd-daemon.c
+@@ -0,0 +1,520 @@
++/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
++
++/***
++  Copyright 2010 Lennart Poettering
++
++  Permission is hereby granted, free of charge, to any person
++  obtaining a copy of this software and associated documentation files
++  (the "Software"), to deal in the Software without restriction,
++  including without limitation the rights to use, copy, modify, merge,
++  publish, distribute, sublicense, and/or sell copies of the Software,
++  and to permit persons to whom the Software is furnished to do so,
++  subject to the following conditions:
++
++  The above copyright notice and this permission notice shall be
++  included in all copies or substantial portions of the Software.
++
++  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++  SOFTWARE.
++***/
++
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE
++#endif
++
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <sys/socket.h>
++#include <sys/un.h>
++#include <sys/fcntl.h>
++#include <netinet/in.h>
++#include <stdlib.h>
++#include <errno.h>
++#include <unistd.h>
++#include <string.h>
++#include <stdarg.h>
++#include <stdio.h>
++#include <stddef.h>
++#include <limits.h>
++
++#if defined(__linux__)
++#include <mqueue.h>
++#endif
++
++#include "sd-daemon.h"
++
++#if (__GNUC__ >= 4) && !defined(SD_EXPORT_SYMBOLS)
++#define _sd_hidden_ __attribute__ ((visibility("hidden")))
++#else
++#define _sd_hidden_
++#endif
++
++_sd_hidden_ int sd_listen_fds(int unset_environment) {
++
++#if defined(DISABLE_SYSTEMD) || !defined(__linux__)
++        return 0;
++#else
++        int r, fd;
++        const char *e;
++        char *p = NULL;
++        unsigned long l;
++
++        if (!(e = getenv("LISTEN_PID"))) {
++                r = 0;
++                goto finish;
++        }
++
++        errno = 0;
++        l = strtoul(e, &p, 10);
++
++        if (errno != 0) {
++                r = -errno;
++                goto finish;
++        }
++
++        if (!p || *p || l <= 0) {
++                r = -EINVAL;
++                goto finish;
++        }
++
++        /* Is this for us? */
++        if (getpid() != (pid_t) l) {
++                r = 0;
++                goto finish;
++        }
++
++        if (!(e = getenv("LISTEN_FDS"))) {
++                r = 0;
++                goto finish;
++        }
++
++        errno = 0;
++        l = strtoul(e, &p, 10);
++
++        if (errno != 0) {
++                r = -errno;
++                goto finish;
++        }
++
++        if (!p || *p) {
++                r = -EINVAL;
++                goto finish;
++        }
++
++        for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + (int) l; fd ++) {
++                int flags;
++
++                if ((flags = fcntl(fd, F_GETFD)) < 0) {
++                        r = -errno;
++                        goto finish;
++                }
++
++                if (flags & FD_CLOEXEC)
++                        continue;
++
++                if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0) {
++                        r = -errno;
++                        goto finish;
++                }
++        }
++
++        r = (int) l;
++
++finish:
++        if (unset_environment) {
++                unsetenv("LISTEN_PID");
++                unsetenv("LISTEN_FDS");
++        }
++
++        return r;
++#endif
++}
++
++_sd_hidden_ int sd_is_fifo(int fd, const char *path) {
++        struct stat st_fd;
++
++        if (fd < 0)
++                return -EINVAL;
++
++        memset(&st_fd, 0, sizeof(st_fd));
++        if (fstat(fd, &st_fd) < 0)
++                return -errno;
++
++        if (!S_ISFIFO(st_fd.st_mode))
++                return 0;
++
++        if (path) {
++                struct stat st_path;
++
++                memset(&st_path, 0, sizeof(st_path));
++                if (stat(path, &st_path) < 0) {
++
++                        if (errno == ENOENT || errno == ENOTDIR)
++                                return 0;
++
++                        return -errno;
++                }
++
++                return
++                        st_path.st_dev == st_fd.st_dev &&
++                        st_path.st_ino == st_fd.st_ino;
++        }
++
++        return 1;
++}
++
++_sd_hidden_ int sd_is_special(int fd, const char *path) {
++        struct stat st_fd;
++
++        if (fd < 0)
++                return -EINVAL;
++
++        if (fstat(fd, &st_fd) < 0)
++                return -errno;
++
++        if (!S_ISREG(st_fd.st_mode) && !S_ISCHR(st_fd.st_mode))
++                return 0;
++
++        if (path) {
++                struct stat st_path;
++
++                if (stat(path, &st_path) < 0) {
++
++                        if (errno == ENOENT || errno == ENOTDIR)
++                                return 0;
++
++                        return -errno;
++                }
++
++                if (S_ISREG(st_fd.st_mode) && S_ISREG(st_path.st_mode))
++                        return
++                                st_path.st_dev == st_fd.st_dev &&
++                                st_path.st_ino == st_fd.st_ino;
++                else if (S_ISCHR(st_fd.st_mode) && S_ISCHR(st_path.st_mode))
++                        return st_path.st_rdev == st_fd.st_rdev;
++                else
++                        return 0;
++        }
++
++        return 1;
++}
++
++static int sd_is_socket_internal(int fd, int type, int listening) {
++        struct stat st_fd;
++
++        if (fd < 0 || type < 0)
++                return -EINVAL;
++
++        if (fstat(fd, &st_fd) < 0)
++                return -errno;
++
++        if (!S_ISSOCK(st_fd.st_mode))
++                return 0;
++
++        if (type != 0) {
++                int other_type = 0;
++                socklen_t l = sizeof(other_type);
++
++                if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &other_type, &l) < 0)
++                        return -errno;
++
++                if (l != sizeof(other_type))
++                        return -EINVAL;
++
++                if (other_type != type)
++                        return 0;
++        }
++
++        if (listening >= 0) {
++                int accepting = 0;
++                socklen_t l = sizeof(accepting);
++
++                if (getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &accepting, &l) < 0)
++                        return -errno;
++
++                if (l != sizeof(accepting))
++                        return -EINVAL;
++
++                if (!accepting != !listening)
++                        return 0;
++        }
++
++        return 1;
++}
++
++union sockaddr_union {
++        struct sockaddr sa;
++        struct sockaddr_in in4;
++        struct sockaddr_in6 in6;
++        struct sockaddr_un un;
++        struct sockaddr_storage storage;
++};
++
++_sd_hidden_ int sd_is_socket(int fd, int family, int type, int listening) {
++        int r;
++
++        if (family < 0)
++                return -EINVAL;
++
++        if ((r = sd_is_socket_internal(fd, type, listening)) <= 0)
++                return r;
++
++        if (family > 0) {
++                union sockaddr_union sockaddr;
++                socklen_t l;
++
++                memset(&sockaddr, 0, sizeof(sockaddr));
++                l = sizeof(sockaddr);
++
++                if (getsockname(fd, &sockaddr.sa, &l) < 0)
++                        return -errno;
++
++                if (l < sizeof(sa_family_t))
++                        return -EINVAL;
++
++                return sockaddr.sa.sa_family == family;
++        }
++
++        return 1;
++}
++
++_sd_hidden_ int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port) {
++        union sockaddr_union sockaddr;
++        socklen_t l;
++        int r;
++
++        if (family != 0 && family != AF_INET && family != AF_INET6)
++                return -EINVAL;
++
++        if ((r = sd_is_socket_internal(fd, type, listening)) <= 0)
++                return r;
++
++        memset(&sockaddr, 0, sizeof(sockaddr));
++        l = sizeof(sockaddr);
++
++        if (getsockname(fd, &sockaddr.sa, &l) < 0)
++                return -errno;
++
++        if (l < sizeof(sa_family_t))
++                return -EINVAL;
++
++        if (sockaddr.sa.sa_family != AF_INET &&
++            sockaddr.sa.sa_family != AF_INET6)
++                return 0;
++
++        if (family > 0)
++                if (sockaddr.sa.sa_family != family)
++                        return 0;
++
++        if (port > 0) {
++                if (sockaddr.sa.sa_family == AF_INET) {
++                        if (l < sizeof(struct sockaddr_in))
++                                return -EINVAL;
++
++                        return htons(port) == sockaddr.in4.sin_port;
++                } else {
++                        if (l < sizeof(struct sockaddr_in6))
++                                return -EINVAL;
++
++                        return htons(port) == sockaddr.in6.sin6_port;
++                }
++        }
++
++        return 1;
++}
++
++_sd_hidden_ int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length) {
++        union sockaddr_union sockaddr;
++        socklen_t l;
++        int r;
++
++        if ((r = sd_is_socket_internal(fd, type, listening)) <= 0)
++                return r;
++
++        memset(&sockaddr, 0, sizeof(sockaddr));
++        l = sizeof(sockaddr);
++
++        if (getsockname(fd, &sockaddr.sa, &l) < 0)
++                return -errno;
++
++        if (l < sizeof(sa_family_t))
++                return -EINVAL;
++
++        if (sockaddr.sa.sa_family != AF_UNIX)
++                return 0;
++
++        if (path) {
++                if (length <= 0)
++                        length = strlen(path);
++
++                if (length <= 0)
++                        /* Unnamed socket */
++                        return l == offsetof(struct sockaddr_un, sun_path);
++
++                if (path[0])
++                        /* Normal path socket */
++                        return
++                                (l >= offsetof(struct sockaddr_un, sun_path) + length + 1) &&
++                                memcmp(path, sockaddr.un.sun_path, length+1) == 0;
++                else
++                        /* Abstract namespace socket */
++                        return
++                                (l == offsetof(struct sockaddr_un, sun_path) + length) &&
++                                memcmp(path, sockaddr.un.sun_path, length) == 0;
++        }
++
++        return 1;
++}
++
++_sd_hidden_ int sd_is_mq(int fd, const char *path) {
++#if !defined(__linux__)
++        return 0;
++#else
++        struct mq_attr attr;
++
++        if (fd < 0)
++                return -EINVAL;
++
++        if (mq_getattr(fd, &attr) < 0)
++                return -errno;
++
++        if (path) {
++                char fpath[PATH_MAX];
++                struct stat a, b;
++
++                if (path[0] != '/')
++                        return -EINVAL;
++
++                if (fstat(fd, &a) < 0)
++                        return -errno;
++
++                strncpy(stpcpy(fpath, "/dev/mqueue"), path, sizeof(fpath) - 12);
++                fpath[sizeof(fpath)-1] = 0;
++
++                if (stat(fpath, &b) < 0)
++                        return -errno;
++
++                if (a.st_dev != b.st_dev ||
++                    a.st_ino != b.st_ino)
++                        return 0;
++        }
++
++        return 1;
++#endif
++}
++
++_sd_hidden_ int sd_notify(int unset_environment, const char *state) {
++#if defined(DISABLE_SYSTEMD) || !defined(__linux__) || !defined(SOCK_CLOEXEC)
++        return 0;
++#else
++        int fd = -1, r;
++        struct msghdr msghdr;
++        struct iovec iovec;
++        union sockaddr_union sockaddr;
++        const char *e;
++
++        if (!state) {
++                r = -EINVAL;
++                goto finish;
++        }
++
++        if (!(e = getenv("NOTIFY_SOCKET")))
++                return 0;
++
++        /* Must be an abstract socket, or an absolute path */
++        if ((e[0] != '@' && e[0] != '/') || e[1] == 0) {
++                r = -EINVAL;
++                goto finish;
++        }
++
++        if ((fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0)) < 0) {
++                r = -errno;
++                goto finish;
++        }
++
++        memset(&sockaddr, 0, sizeof(sockaddr));
++        sockaddr.sa.sa_family = AF_UNIX;
++        strncpy(sockaddr.un.sun_path, e, sizeof(sockaddr.un.sun_path));
++
++        if (sockaddr.un.sun_path[0] == '@')
++                sockaddr.un.sun_path[0] = 0;
++
++        memset(&iovec, 0, sizeof(iovec));
++        iovec.iov_base = (char*) state;
++        iovec.iov_len = strlen(state);
++
++        memset(&msghdr, 0, sizeof(msghdr));
++        msghdr.msg_name = &sockaddr;
++        msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + strlen(e);
++
++        if (msghdr.msg_namelen > sizeof(struct sockaddr_un))
++                msghdr.msg_namelen = sizeof(struct sockaddr_un);
++
++        msghdr.msg_iov = &iovec;
++        msghdr.msg_iovlen = 1;
++
++        if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
++                r = -errno;
++                goto finish;
++        }
++
++        r = 1;
++
++finish:
++        if (unset_environment)
++                unsetenv("NOTIFY_SOCKET");
++
++        if (fd >= 0)
++                close(fd);
++
++        return r;
++#endif
++}
++
++_sd_hidden_ int sd_notifyf(int unset_environment, const char *format, ...) {
++#if defined(DISABLE_SYSTEMD) || !defined(__linux__)
++        return 0;
++#else
++        va_list ap;
++        char *p = NULL;
++        int r;
++
++        va_start(ap, format);
++        r = vasprintf(&p, format, ap);
++        va_end(ap);
++
++        if (r < 0 || !p)
++                return -ENOMEM;
++
++        r = sd_notify(unset_environment, p);
++        free(p);
++
++        return r;
++#endif
++}
++
++_sd_hidden_ int sd_booted(void) {
++#if defined(DISABLE_SYSTEMD) || !defined(__linux__)
++        return 0;
++#else
++
++        struct stat a, b;
++
++        /* We simply test whether the systemd cgroup hierarchy is
++         * mounted */
++
++        if (lstat("/sys/fs/cgroup", &a) < 0)
++                return 0;
++
++        if (lstat("/sys/fs/cgroup/systemd", &b) < 0)
++                return 0;
++
++        return a.st_dev != b.st_dev;
++#endif
++}
+diff --git a/PCSC/src/sd-daemon.h b/PCSC/src/sd-daemon.h
+new file mode 100644
+index 0000000..46dc7fd
+--- /dev/null
++++ b/PCSC/src/sd-daemon.h
+@@ -0,0 +1,277 @@
++/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
++
++#ifndef foosddaemonhfoo
++#define foosddaemonhfoo
++
++/***
++  Copyright 2010 Lennart Poettering
++
++  Permission is hereby granted, free of charge, to any person
++  obtaining a copy of this software and associated documentation files
++  (the "Software"), to deal in the Software without restriction,
++  including without limitation the rights to use, copy, modify, merge,
++  publish, distribute, sublicense, and/or sell copies of the Software,
++  and to permit persons to whom the Software is furnished to do so,
++  subject to the following conditions:
++
++  The above copyright notice and this permission notice shall be
++  included in all copies or substantial portions of the Software.
++
++  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++  SOFTWARE.
++***/
++
++#include <sys/types.h>
++#include <inttypes.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/*
++  Reference implementation of a few systemd related interfaces for
++  writing daemons. These interfaces are trivial to implement. To
++  simplify porting we provide this reference implementation.
++  Applications are welcome to reimplement the algorithms described
++  here if they do not want to include these two source files.
++
++  The following functionality is provided:
++
++  - Support for logging with log levels on stderr
++  - File descriptor passing for socket-based activation
++  - Daemon startup and status notification
++  - Detection of systemd boots
++
++  You may compile this with -DDISABLE_SYSTEMD to disable systemd
++  support. This makes all those calls NOPs that are directly related to
++  systemd (i.e. only sd_is_xxx() will stay useful).
++
++  Since this is drop-in code we don't want any of our symbols to be
++  exported in any case. Hence we declare hidden visibility for all of
++  them.
++
++  You may find an up-to-date version of these source files online:
++
++  http://cgit.freedesktop.org/systemd/plain/src/sd-daemon.h
++  http://cgit.freedesktop.org/systemd/plain/src/sd-daemon.c
++
++  This should compile on non-Linux systems, too, but with the
++  exception of the sd_is_xxx() calls all functions will become NOPs.
++
++  See sd-daemon(7) for more information.
++*/
++
++#ifndef _sd_printf_attr_
++#if __GNUC__ >= 4
++#define _sd_printf_attr_(a,b) __attribute__ ((format (printf, a, b)))
++#else
++#define _sd_printf_attr_(a,b)
++#endif
++#endif
++
++/*
++  Log levels for usage on stderr:
++
++          fprintf(stderr, SD_NOTICE "Hello World!\n");
++
++  This is similar to printk() usage in the kernel.
++*/
++#define SD_EMERG   "<0>"  /* system is unusable */
++#define SD_ALERT   "<1>"  /* action must be taken immediately */
++#define SD_CRIT    "<2>"  /* critical conditions */
++#define SD_ERR     "<3>"  /* error conditions */
++#define SD_WARNING "<4>"  /* warning conditions */
++#define SD_NOTICE  "<5>"  /* normal but significant condition */
++#define SD_INFO    "<6>"  /* informational */
++#define SD_DEBUG   "<7>"  /* debug-level messages */
++
++/* The first passed file descriptor is fd 3 */
++#define SD_LISTEN_FDS_START 3
++
++/*
++  Returns how many file descriptors have been passed, or a negative
++  errno code on failure. Optionally, removes the $LISTEN_FDS and
++  $LISTEN_PID file descriptors from the environment (recommended, but
++  problematic in threaded environments). If r is the return value of
++  this function you'll find the file descriptors passed as fds
++  SD_LISTEN_FDS_START to SD_LISTEN_FDS_START+r-1. Returns a negative
++  errno style error code on failure. This function call ensures that
++  the FD_CLOEXEC flag is set for the passed file descriptors, to make
++  sure they are not passed on to child processes. If FD_CLOEXEC shall
++  not be set, the caller needs to unset it after this call for all file
++  descriptors that are used.
++
++  See sd_listen_fds(3) for more information.
++*/
++int sd_listen_fds(int unset_environment);
++
++/*
++  Helper call for identifying a passed file descriptor. Returns 1 if
++  the file descriptor is a FIFO in the file system stored under the
++  specified path, 0 otherwise. If path is NULL a path name check will
++  not be done and the call only verifies if the file descriptor
++  refers to a FIFO. Returns a negative errno style error code on
++  failure.
++
++  See sd_is_fifo(3) for more information.
++*/
++int sd_is_fifo(int fd, const char *path);
++
++/*
++  Helper call for identifying a passed file descriptor. Returns 1 if
++  the file descriptor is a special character device on the file
++  system stored under the specified path, 0 otherwise.
++  If path is NULL a path name check will not be done and the call
++  only verifies if the file descriptor refers to a special character.
++  Returns a negative errno style error code on failure.
++
++  See sd_is_special(3) for more information.
++*/
++int sd_is_special(int fd, const char *path);
++
++/*
++  Helper call for identifying a passed file descriptor. Returns 1 if
++  the file descriptor is a socket of the specified family (AF_INET,
++  ...) and type (SOCK_DGRAM, SOCK_STREAM, ...), 0 otherwise. If
++  family is 0 a socket family check will not be done. If type is 0 a
++  socket type check will not be done and the call only verifies if
++  the file descriptor refers to a socket. If listening is > 0 it is
++  verified that the socket is in listening mode. (i.e. listen() has
++  been called) If listening is == 0 it is verified that the socket is
++  not in listening mode. If listening is < 0 no listening mode check
++  is done. Returns a negative errno style error code on failure.
++
++  See sd_is_socket(3) for more information.
++*/
++int sd_is_socket(int fd, int family, int type, int listening);
++
++/*
++  Helper call for identifying a passed file descriptor. Returns 1 if
++  the file descriptor is an Internet socket, of the specified family
++  (either AF_INET or AF_INET6) and the specified type (SOCK_DGRAM,
++  SOCK_STREAM, ...), 0 otherwise. If version is 0 a protocol version
++  check is not done. If type is 0 a socket type check will not be
++  done. If port is 0 a socket port check will not be done. The
++  listening flag is used the same way as in sd_is_socket(). Returns a
++  negative errno style error code on failure.
++
++  See sd_is_socket_inet(3) for more information.
++*/
++int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port);
++
++/*
++  Helper call for identifying a passed file descriptor. Returns 1 if
++  the file descriptor is an AF_UNIX socket of the specified type
++  (SOCK_DGRAM, SOCK_STREAM, ...) and path, 0 otherwise. If type is 0
++  a socket type check will not be done. If path is NULL a socket path
++  check will not be done. For normal AF_UNIX sockets set length to
++  0. For abstract namespace sockets set length to the length of the
++  socket name (including the initial 0 byte), and pass the full
++  socket path in path (including the initial 0 byte). The listening
++  flag is used the same way as in sd_is_socket(). Returns a negative
++  errno style error code on failure.
++
++  See sd_is_socket_unix(3) for more information.
++*/
++int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length);
++
++/*
++  Helper call for identifying a passed file descriptor. Returns 1 if
++  the file descriptor is a POSIX Message Queue of the specified name,
++  0 otherwise. If path is NULL a message queue name check is not
++  done. Returns a negative errno style error code on failure.
++*/
++int sd_is_mq(int fd, const char *path);
++
++/*
++  Informs systemd about changed daemon state. This takes a number of
++  newline separated environment-style variable assignments in a
++  string. The following variables are known:
++
++     READY=1      Tells systemd that daemon startup is finished (only
++                  relevant for services of Type=notify). The passed
++                  argument is a boolean "1" or "0". Since there is
++                  little value in signaling non-readiness the only
++                  value daemons should send is "READY=1".
++
++     STATUS=...   Passes a single-line status string back to systemd
++                  that describes the daemon state. This is free-from
++                  and can be used for various purposes: general state
++                  feedback, fsck-like programs could pass completion
++                  percentages and failing programs could pass a human
++                  readable error message. Example: "STATUS=Completed
++                  66% of file system check..."
++
++     ERRNO=...    If a daemon fails, the errno-style error code,
++                  formatted as string. Example: "ERRNO=2" for ENOENT.
++
++     BUSERROR=... If a daemon fails, the D-Bus error-style error
++                  code. Example: "BUSERROR=org.freedesktop.DBus.Error.TimedOut"
++
++     MAINPID=...  The main pid of a daemon, in case systemd did not
++                  fork off the process itself. Example: "MAINPID=4711"
++
++  Daemons can choose to send additional variables. However, it is
++  recommended to prefix variable names not listed above with X_.
++
++  Returns a negative errno-style error code on failure. Returns > 0
++  if systemd could be notified, 0 if it couldn't possibly because
++  systemd is not running.
++
++  Example: When a daemon finished starting up, it could issue this
++  call to notify systemd about it:
++
++     sd_notify(0, "READY=1");
++
++  See sd_notifyf() for more complete examples.
++
++  See sd_notify(3) for more information.
++*/
++int sd_notify(int unset_environment, const char *state);
++
++/*
++  Similar to sd_notify() but takes a format string.
++
++  Example 1: A daemon could send the following after initialization:
++
++     sd_notifyf(0, "READY=1\n"
++                   "STATUS=Processing requests...\n"
++                   "MAINPID=%lu",
++                   (unsigned long) getpid());
++
++  Example 2: A daemon could send the following shortly before
++  exiting, on failure:
++
++     sd_notifyf(0, "STATUS=Failed to start up: %s\n"
++                   "ERRNO=%i",
++                   strerror(errno),
++                   errno);
++
++  See sd_notifyf(3) for more information.
++*/
++int sd_notifyf(int unset_environment, const char *format, ...) _sd_printf_attr_(2,3);
++
++/*
++  Returns > 0 if the system was booted with systemd. Returns < 0 on
++  error. Returns 0 if the system was not booted with systemd. Note
++  that all of the functions above handle non-systemd boots just
++  fine. You should NOT protect them with a call to this function. Also
++  note that this function checks whether the system, not the user
++  session is controlled by systemd. However the functions above work
++  for both user and system services.
++
++  See sd_booted(3) for more information.
++*/
++int sd_booted(void);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif
+diff --git a/PCSC/src/winscard_msg.h b/PCSC/src/winscard_msg.h
+index b2b6f90..b8c490c 100644
+--- a/PCSC/src/winscard_msg.h
++++ b/PCSC/src/winscard_msg.h
+@@ -252,6 +252,7 @@
+ 
+ #ifdef PCSCD
+ 	int32_t InitializeSocket(void);
++	int32_t ListenExistingSocket(int fd);
+ 	int32_t ProcessEventsServer(/*@out@*/ uint32_t *);
+ #else
+ 	char *getSocketName(void);
+diff --git a/PCSC/src/winscard_msg_srv.c b/PCSC/src/winscard_msg_srv.c
+index 19ea363..4bb5bdc 100644
+--- a/PCSC/src/winscard_msg_srv.c
++++ b/PCSC/src/winscard_msg_srv.c
+@@ -39,6 +39,7 @@
+ 
+ #include "misc.h"
+ #include "pcscd.h"
++#include "sd-daemon.h"
+ #include "winscard.h"
+ #include "debuglog.h"
+ #include "winscard_msg.h"
+@@ -138,6 +139,30 @@ INTERNAL int32_t InitializeSocket(void)
+ }
+ 
+ /**
++ * @brief Acquires a socket passed in from systemd.
++ *
++ * This is called by the server to start listening on an existing socket for
++ * local IPC with the clients.
++ *
++ * @param fd The file descriptor to start listening on.
++ *
++ * @return Error code.
++ * @retval 0 Success
++ * @retval -1 Passed FD is not an UNIX socket.
++ */
++INTERNAL int32_t ListenExistingSocket(int fd)
++{
++	if (!sd_is_socket(fd, AF_UNIX, SOCK_STREAM, -1))
++	{
++		Log1(PCSC_LOG_CRITICAL, "Passed FD is not an UNIX socket");
++		return -1;
++	}
++
++	commonSocket = fd;
++	return 0;
++}
++
++/**
+  * @brief Looks for messages sent by clients.
+  *
+  * This is called by the Server's function \c SVCServiceRunLoop().
+-- 
+1.7.5.4
+
diff --git a/0002-Add-disable-autostart-option.patch b/0002-Add-disable-autostart-option.patch
new file mode 100644
index 0000000..a46a041
--- /dev/null
+++ b/0002-Add-disable-autostart-option.patch
@@ -0,0 +1,94 @@
+From c7f825b2c4a5c7d4ac8abe5690737c2c8fffbfcc Mon Sep 17 00:00:00 2001
+From: Kalev Lember <kalev at smartlink.ee>
+Date: Fri, 24 Jun 2011 00:46:13 +0300
+Subject: [PATCH 2/3] Add --disable-autostart option
+
+This option disables pcscd autostarting code in the libpcsclite library.
+
+With systemd socket activation in place, pcscd can be started
+automatically by systemd when a request arrives on the IPC socket. That
+makes starting the service as a fork from user library unnecessary.
+---
+ PCSC/configure.in        |   11 +++++++++++
+ PCSC/src/winscard_clnt.c |    6 ++++++
+ 2 files changed, 17 insertions(+), 0 deletions(-)
+
+diff --git a/PCSC/configure.in b/PCSC/configure.in
+index 831ee88..97e3360 100644
+--- a/PCSC/configure.in
++++ b/PCSC/configure.in
+@@ -274,6 +274,16 @@ if test x$use_libusb = xyes; then
+   PCSCLITE_FEATURES="${PCSCLITE_FEATURES} libusb"
+ fi
+ 
++# --disable-autostart
++AC_ARG_ENABLE(autostart,
++  AC_HELP_STRING([--disable-autostart], [disable pcscd automatic startup]),
++  [ use_autostart="${enableval}" ], [ use_autostart="yes" ] )
++
++if test x$use_autostart != xno; then
++  AC_DEFINE(ENABLE_AUTOSTART, 1, [Enable pcscd automatic startup])
++  PCSCLITE_FEATURES="${PCSCLITE_FEATURES} autostart"
++fi
++
+ # --enable-embedded
+ AC_ARG_ENABLE(embedded,
+   AC_HELP_STRING([--enable-embedded], [limit RAM and CPU ressources by disabling features (log)]),
+@@ -381,6 +391,7 @@ ATR parsing messages: ${debugatr}
+ ipcdir:               ${ipcdir}
+ use serial:           ${use_serial}
+ use usb:              ${use_usb}
++use autostart:        ${use_autostart}
+ 
+ PCSCLITE_FEATURES:    ${PCSCLITE_FEATURES}
+ 
+diff --git a/PCSC/src/winscard_clnt.c b/PCSC/src/winscard_clnt.c
+index 92c8481..982be01 100644
+--- a/PCSC/src/winscard_clnt.c
++++ b/PCSC/src/winscard_clnt.c
+@@ -444,8 +444,10 @@ LONG SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1,
+ 	LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
+ {
+ 	LONG rv;
++#ifdef ENABLE_AUTOSTART
+ 	int daemon_launched = FALSE;
+ 	int retries = 0;
++#endif
+ 
+ 	API_TRACE_IN("%ld, %p, %p", dwScope, pvReserved1, pvReserved2)
+ 	PROFILE_START
+@@ -457,6 +459,7 @@ again:
+ 		/* we reconnected to a daemon or we got called from a forked child */
+ 		rv = SCardCheckDaemonAvailability();
+ 
++#ifdef ENABLE_AUTOSTART
+ 	if (SCARD_E_NO_SERVICE == rv)
+ 	{
+ launch:
+@@ -517,6 +520,7 @@ launch:
+ 			goto again;
+ 		}
+ 	}
++#endif
+ 
+ 	if (rv != SCARD_S_SUCCESS)
+ 		goto end;
+@@ -526,6 +530,7 @@ launch:
+ 		pvReserved2, phContext);
+ 	(void)SCardUnlockThread();
+ 
++#ifdef ENABLE_AUTOSTART
+ 	/* SCardEstablishContextTH may fail if the previous pcscd crashed
+ 	 * without cleaning /var/run/pcscd/pcscd.comm */
+ 	if (SCARD_E_NO_SERVICE == rv)
+@@ -534,6 +539,7 @@ launch:
+ 		if (retries <= 1)
+ 			goto launch;
+ 	}
++#endif
+ 
+ end:
+ 	PROFILE_END(rv)
+-- 
+1.7.5.4
+
diff --git a/0003-Install-systemd-service-files.patch b/0003-Install-systemd-service-files.patch
new file mode 100644
index 0000000..c96509a
--- /dev/null
+++ b/0003-Install-systemd-service-files.patch
@@ -0,0 +1,144 @@
+From 0f85375fd8949e529a6f46c07cdabda74040fd8a Mon Sep 17 00:00:00 2001
+From: Kalev Lember <kalev at smartlink.ee>
+Date: Fri, 24 Jun 2011 22:32:33 +0300
+Subject: [PATCH 3/3] Install systemd service files
+
+---
+ PCSC/Makefile.am          |    5 ++++-
+ PCSC/configure.in         |   32 ++++++++++++++++++++++----------
+ PCSC/etc/Makefile.am      |    9 +++++++++
+ PCSC/etc/pcscd.service.in |   13 +++++++++++++
+ PCSC/etc/pcscd.socket.in  |    8 ++++++++
+ 5 files changed, 56 insertions(+), 11 deletions(-)
+ create mode 100644 PCSC/etc/Makefile.am
+ create mode 100644 PCSC/etc/pcscd.service.in
+ create mode 100644 PCSC/etc/pcscd.socket.in
+
+diff --git a/PCSC/Makefile.am b/PCSC/Makefile.am
+index 079b58a..c515128 100644
+--- a/PCSC/Makefile.am
++++ b/PCSC/Makefile.am
+@@ -1,10 +1,13 @@
+-SUBDIRS = m4 src doc
++SUBDIRS = m4 src etc doc
+ 
+ fix-rights:
+ 	$(MAKE) -C src $@
+ 
+ ACLOCAL_AMFLAGS = -I m4
+ 
++DISTCHECK_CONFIGURE_FLAGS = \
++	--with-systemdsystemunitdir=$$dc_install_base/$(systemdsystemunitdir)
++
+ EXTRA_DIST = DRIVERS SECURITY bootstrap HELP ChangeLog.svn
+ 
+ DISTCLEANFILES = ChangeLog.svn
+diff --git a/PCSC/configure.in b/PCSC/configure.in
+index 97e3360..cc6fe5f 100644
+--- a/PCSC/configure.in
++++ b/PCSC/configure.in
+@@ -274,6 +274,14 @@ if test x$use_libusb = xyes; then
+   PCSCLITE_FEATURES="${PCSCLITE_FEATURES} libusb"
+ fi
+ 
++AC_ARG_WITH([systemdsystemunitdir],
++  AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files]),
++  [], [with_systemdsystemunitdir=$($PKG_CONFIG --variable=systemdsystemunitdir systemd)])
++if test "x$with_systemdsystemunitdir" != xno; then
++  AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir])
++fi
++AM_CONDITIONAL(HAVE_SYSTEMD, [test -n "$with_systemdsystemunitdir" -a "x$with_systemdsystemunitdir" != xno ])
++
+ # --disable-autostart
+ AC_ARG_ENABLE(autostart,
+   AC_HELP_STRING([--disable-autostart], [disable pcscd automatic startup]),
+@@ -383,17 +391,18 @@ PTHREAD_CFLAGS:      ${PTHREAD_CFLAGS}
+ PTHREAD_LIBS:        ${PTHREAD_LIBS}
+ PCSC_ARCH:           ${PCSC_ARCH}
+ 
+-pcscd binary          ${PCSCD_BINARY}
+-libudev support:      ${use_libudev}
+-libusb support:       ${use_libusb}
+-USB drop directory:   ${usbdropdir}
+-ATR parsing messages: ${debugatr}
+-ipcdir:               ${ipcdir}
+-use serial:           ${use_serial}
+-use usb:              ${use_usb}
+-use autostart:        ${use_autostart}
++pcscd binary            ${PCSCD_BINARY}
++libudev support:        ${use_libudev}
++libusb support:         ${use_libusb}
++USB drop directory:     ${usbdropdir}
++ATR parsing messages:   ${debugatr}
++ipcdir:                 ${ipcdir}
++use serial:             ${use_serial}
++use usb:                ${use_usb}
++use autostart:          ${use_autostart}
++systemd unit directory: ${with_systemdsystemunitdir}
+ 
+-PCSCLITE_FEATURES:    ${PCSCLITE_FEATURES}
++PCSCLITE_FEATURES:      ${PCSCLITE_FEATURES}
+ 
+ EOF
+ 
+@@ -406,6 +415,9 @@ doc/doxygen.conf
+ doc/pcscd.8
+ doc/reader.conf.5
+ doc/example/Makefile
++etc/Makefile
++etc/pcscd.service
++etc/pcscd.socket
+ src/Makefile
+ src/libpcsclite.pc
+ src/pcscd.h
+diff --git a/PCSC/etc/Makefile.am b/PCSC/etc/Makefile.am
+new file mode 100644
+index 0000000..6ab04fc
+--- /dev/null
++++ b/PCSC/etc/Makefile.am
+@@ -0,0 +1,9 @@
++if HAVE_SYSTEMD
++SCRIPT_IN_FILES = \
++	pcscd.service.in \
++	pcscd.socket.in
++
++systemdsystemunit_DATA = \
++	pcscd.service \
++	pcscd.socket
++endif
+diff --git a/PCSC/etc/pcscd.service.in b/PCSC/etc/pcscd.service.in
+new file mode 100644
+index 0000000..4800d32
+--- /dev/null
++++ b/PCSC/etc/pcscd.service.in
+@@ -0,0 +1,13 @@
++[Unit]
++Description=PC/SC Smart Card Daemon
++Requires=pcscd.socket
++After=syslog.target
++
++[Service]
++ExecStart=@sbindir_exp@/pcscd -f
++ExecReload=@sbindir_exp@/pcscd -H
++StandardOutput=syslog
++
++[Install]
++WantedBy=multi-user.target
++Also=pcscd.socket
+diff --git a/PCSC/etc/pcscd.socket.in b/PCSC/etc/pcscd.socket.in
+new file mode 100644
+index 0000000..6fc93da
+--- /dev/null
++++ b/PCSC/etc/pcscd.socket.in
+@@ -0,0 +1,8 @@
++[Unit]
++Description=PC/SC Smart Card Daemon Activation Socket
++
++[Socket]
++ListenStream=@ipcdir@/pcscd.comm
++
++[Install]
++WantedBy=sockets.target
+-- 
+1.7.5.4
+
diff --git a/pcsc-lite.spec b/pcsc-lite.spec
index ed868b4..ff5b1cc 100644
--- a/pcsc-lite.spec
+++ b/pcsc-lite.spec
@@ -2,25 +2,29 @@
 
 Name:           pcsc-lite
 Version:        1.7.4
-Release:        1%{?dist}
+Release:        2%{?dist}
 Summary:        PC/SC Lite smart card framework and applications
 
 Group:          System Environment/Daemons
 License:        BSD
 URL:            http://pcsclite.alioth.debian.org/
 Source0:        http://alioth.debian.org/download.php/%{upstream_build}/%{name}-%{version}.tar.bz2
-Source1:        pcscd.init
-# Disable pcscd on-demand startup (#653903)
-Patch2:         %{name}-1.6.7-noautostart.patch
+# Patches for systemd support
+# http://archives.neohapsis.com/archives/dev/muscle/2011-q2/0138.html
+Patch0:         0001-Support-systemd-socket-activation.patch
+Patch1:         0002-Add-disable-autostart-option.patch
+Patch2:         0003-Install-systemd-service-files.patch
 
+BuildRequires:  automake libtool
 BuildRequires:  libudev-devel
 BuildRequires:  doxygen
 BuildRequires:  graphviz
-Requires(post): initscripts
-Requires(post): /sbin/chkconfig
-Requires(preun): /sbin/chkconfig
-Requires(preun): initscripts
-Requires(postun): initscripts
+BuildRequires:  systemd-units
+
+Requires(post): systemd-sysv
+Requires(post): systemd-units
+Requires(preun): systemd-units
+Requires(postun): systemd-units
 Requires:       pcsc-ifd-handler
 Requires:       %{name}-libs = %{version}-%{release}
 
@@ -60,7 +64,11 @@ Requires:       %{name}-libs = %{version}-%{release}
 
 %prep
 %setup -q
-%patch2 -p1 -b .noautostart
+%patch0 -p2 -b .socket_activation
+%patch1 -p2 -b .noautostart
+%patch2 -p2 -b .service_files
+
+autoreconf -f
 
 # Convert to utf-8
 for file in ChangeLog; do
@@ -73,6 +81,7 @@ done
 %build
 %configure \
   --disable-static \
+  --disable-autostart \
   --enable-ipcdir=%{_localstatedir}/run \
   --enable-usbdropdir=%{_libdir}/pcsc/drivers
 make %{?_smp_mflags}
@@ -82,8 +91,6 @@ doxygen doc/doxygen.conf ; rm -f doc/api/*.{map,md5}
 %install
 make install DESTDIR=$RPM_BUILD_ROOT
 
-install -Dpm 755 %{SOURCE1} $RPM_BUILD_ROOT%{_initrddir}/pcscd
-
 # Create empty directories
 mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/reader.conf.d
 mkdir -p $RPM_BUILD_ROOT%{_libdir}/pcsc/drivers
@@ -95,17 +102,41 @@ rm $RPM_BUILD_ROOT%{_docdir}/pcsc-lite/README.DAEMON
 
 
 %post
-/sbin/chkconfig --add pcscd
+if [ $1 -eq 1 ] ; then
+    # Initial installation
+    /bin/systemctl enable pcscd.socket >/dev/null 2>&1
+fi
 
 %preun
-if [ $1 = 0 ] ; then
-  /sbin/service pcscd stop >/dev/null 2>&1 || :
-  /sbin/chkconfig --del pcscd
+if [ $1 -eq 0 ] ; then
+    # Package removal, not upgrade
+    /bin/systemctl --no-reload disable pcscd.service pcscd.socket >/dev/null 2>&1 || :
+    /bin/systemctl stop pcscd.service pcscd.socket >/dev/null 2>&1 || :
 fi
 
 %postun
-if [ "$1" -ge "1" ]; then
-  /sbin/service pcscd condrestart >/dev/null 2>&1 || :
+/bin/systemctl daemon-reload >/dev/null 2>&1 || :
+if [ $1 -ge 1 ] ; then
+    # Package upgrade, not uninstall
+    /bin/systemctl try-restart pcscd.service >/dev/null 2>&1 || :
+fi
+
+%triggerun -- pcsc-lite < 1.7.4-2
+# Save the current service runlevel info
+# User must manually run systemd-sysv-convert --apply pcscd
+# to migrate them to systemd targets
+%{_bindir}/systemd-sysv-convert --save pcscd >/dev/null 2>&1 ||:
+
+# Enable pcscd socket activation
+/bin/systemctl enable pcscd.socket >/dev/null 2>&1
+
+# Run these because the SysV package being removed won't do them
+/sbin/chkconfig --del pcscd >/dev/null 2>&1 || :
+
+# Restart the service if it's already running
+if /bin/systemctl is-active pcscd.service >/dev/null 2>&1 ; then
+    /bin/systemctl stop pcscd.service >/dev/null 2>&1 ||:
+    /bin/systemctl start pcscd.socket pcscd.service >/dev/null 2>&1 ||:
 fi
 
 %post libs -p /sbin/ldconfig
@@ -116,7 +147,8 @@ fi
 %files
 %doc AUTHORS ChangeLog* DRIVERS HELP README SECURITY TODO
 %dir %{_sysconfdir}/reader.conf.d/
-%{_initrddir}/pcscd
+%{_unitdir}/pcscd.service
+%{_unitdir}/pcscd.socket
 %{_sbindir}/pcscd
 %dir %{_libdir}/pcsc/
 %dir %{_libdir}/pcsc/drivers/
@@ -137,6 +169,9 @@ fi
 
 
 %changelog
+* Fri Jul 15 2011 Kalev Lember <kalevlember at gmail.com> - 1.7.4-2
+- Converted initscript to systemd service file (#617330)
+
 * Fri Jun 24 2011 Kalev Lember <kalev at smartlink.ee> - 1.7.4-1
 - Update to 1.7.4
 


More information about the scm-commits mailing list