[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