Hello community, here is the log from the commit of package pcsc-lite for openSUSE:Factory checked in at 2011-12-12 16:58:38 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/pcsc-lite (Old) and /work/SRC/openSUSE:Factory/.pcsc-lite.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Package is "pcsc-lite", Maintainer is "sbrabec@suse.com" Changes: -------- --- /work/SRC/openSUSE:Factory/pcsc-lite/pcsc-lite.changes 2011-11-22 17:49:27.000000000 +0100 +++ /work/SRC/openSUSE:Factory/.pcsc-lite.new/pcsc-lite.changes 2011-12-12 17:03:31.000000000 +0100 @@ -1,0 +2,11 @@ +Wed Dec 7 19:34:17 CET 2011 - sbrabec@suse.cz + +- Move libpcsclite.so file to the main package (bnc#732911). + +------------------------------------------------------------------- +Fri Nov 25 19:54:19 UTC 2011 - wr@rosenauer.org + +- Updated to version 1.8.1 + * added missing files in source archive + +------------------------------------------------------------------- Old: ---- pcsc-lite-1.8.0.tar.bz2 New: ---- pcsc-lite-1.8.1.tar.bz2 systemd-service.patch ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ pcsc-lite.spec ++++++ --- /var/tmp/diff_new_pack.aoPJRq/_old 2011-12-12 17:03:34.000000000 +0100 +++ /var/tmp/diff_new_pack.aoPJRq/_new 2011-12-12 17:03:34.000000000 +0100 @@ -33,7 +33,7 @@ BuildRequires: systemd %{?systemd_requires} %endif -Version: 1.8.0 +Version: 1.8.1 Release: 1 Requires(pre): pwdutils Group: Productivity/Security @@ -47,6 +47,7 @@ Source4: baselibs.conf Source5: pcsc-lite-init Source6: pcsc-lite-reader-conf +Patch0: systemd-service.patch Requires(post): %insserv_prereq %fillup_prereq %if %suse_version > 1130 PreReq: sysvinit(syslog) @@ -121,6 +122,7 @@ %prep %setup -q +%patch0 -p1 cp -a %{S:1} %{S:2} %{S:5} %{S:6} . %build @@ -168,24 +170,29 @@ %post %if %suse_version > 1140 %service_add_post pcscd.service pcscd.socket -%else +/bin/systemctl disable pcscd.service || : +/bin/systemctl enable pcscd.socket || : +/bin/systemctl try-restart pcscd.service || : +/bin/systemctl restart pcscd.socket || : +%endif %fillup_and_insserv -y -n pcscd pcscd %restart_on_update pcscd -%endif %preun %if %suse_version > 1140 %service_del_preun pcscd.service pcscd.socket -%else -%stop_on_removal pcscd %endif +%stop_on_removal pcscd %postun %if %suse_version > 1140 %service_del_postun pcscd.service pcscd.socket -%else -%insserv_cleanup +# make sure to reload systemd for possible downgrades +if [ "$1" = "1" ]; then + /bin/systemctl daemon-reload >/dev/null 2>&1 || : +fi %endif +%insserv_cleanup %post -n libpcsclite1 -p /sbin/ldconfig @@ -208,6 +215,8 @@ %endif %{_initrddir}/pcscd /var/adm/fillup-templates/sysconfig.pcscd +# libpcsclite.so should stay in the main package (#732911). Third party packages may need it for dlopen(). +%{_libdir}/libpcsclite.so %files -n libpcsclite1 %defattr(-,root,root) @@ -220,8 +229,10 @@ %files devel %defattr(-,root,root) %{_includedir}/* -%{_libdir}/*.so %{_libdir}/*.*a %{_libdir}/pkgconfig/*.pc +%{_libdir}/*.so +# libpcsclite.so should stay in the main package (#732911). Third party packages may need it for dlopen(). +%exclude %{_libdir}/libpcsclite.so %changelog ++++++ pcsc-lite-1.8.0.tar.bz2 -> pcsc-lite-1.8.1.tar.bz2 ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pcsc-lite-1.8.0/ChangeLog new/pcsc-lite-1.8.1/ChangeLog --- old/pcsc-lite-1.8.0/ChangeLog 2011-11-19 16:55:37.000000000 +0100 +++ new/pcsc-lite-1.8.1/ChangeLog 2011-11-25 15:05:43.000000000 +0100 @@ -1,3 +1,8 @@ +pcsc-lite-1.8.1: Ludovic Rousseau +25 November 2011 +- Distribute missing files from src/spy/ + + pcsc-lite-1.8.0: Ludovic Rousseau 19 November 2011 - PC/SC spy tool diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pcsc-lite-1.8.0/ChangeLog.svn new/pcsc-lite-1.8.1/ChangeLog.svn --- old/pcsc-lite-1.8.0/ChangeLog.svn 2011-11-19 16:57:42.000000000 +0100 +++ new/pcsc-lite-1.8.1/ChangeLog.svn 2011-11-25 15:10:39.000000000 +0100 @@ -1,3 +1,9 @@ +2011-11-25 Ludovic Rousseau + + * [r6118] ChangeLog, configure.in: Release 1.8.1 + * [r6117] src/spy/Makefile.am: Also distribute pcsc-spy.py + install_spy.sh uninstall_spy.sh README.txt + 2011-11-19 Ludovic Rousseau * [r6111] ChangeLog, configure.in: Release 1.8.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pcsc-lite-1.8.0/configure new/pcsc-lite-1.8.1/configure --- old/pcsc-lite-1.8.0/configure 2011-11-19 16:55:49.000000000 +0100 +++ new/pcsc-lite-1.8.1/configure 2011-11-25 15:09:01.000000000 +0100 @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.68 for pcsc-lite 1.8.0. +# Generated by GNU Autoconf 2.68 for pcsc-lite 1.8.1. # # # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, @@ -567,8 +567,8 @@ # Identity of this package. PACKAGE_NAME='pcsc-lite' PACKAGE_TARNAME='pcsc-lite' -PACKAGE_VERSION='1.8.0' -PACKAGE_STRING='pcsc-lite 1.8.0' +PACKAGE_VERSION='1.8.1' +PACKAGE_STRING='pcsc-lite 1.8.1' PACKAGE_BUGREPORT='' PACKAGE_URL='' @@ -1342,7 +1342,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures pcsc-lite 1.8.0 to adapt to many kinds of systems. +\`configure' configures pcsc-lite 1.8.1 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1412,7 +1412,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of pcsc-lite 1.8.0:";; + short | recursive ) echo "Configuration of pcsc-lite 1.8.1:";; esac cat <<\_ACEOF @@ -1544,7 +1544,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -pcsc-lite configure 1.8.0 +pcsc-lite configure 1.8.1 generated by GNU Autoconf 2.68 Copyright (C) 2010 Free Software Foundation, Inc. @@ -1963,7 +1963,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by pcsc-lite $as_me 1.8.0, which was +It was created by pcsc-lite $as_me 1.8.1, which was generated by GNU Autoconf 2.68. Invocation command line was $ $0 $@ @@ -2779,7 +2779,7 @@ # Define the identity of the package. PACKAGE='pcsc-lite' - VERSION='1.8.0' + VERSION='1.8.1' cat >>confdefs.h <<_ACEOF @@ -14627,7 +14627,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by pcsc-lite $as_me 1.8.0, which was +This file was extended by pcsc-lite $as_me 1.8.1, which was generated by GNU Autoconf 2.68. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -14693,7 +14693,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -pcsc-lite config.status 1.8.0 +pcsc-lite config.status 1.8.1 configured by $0, generated by GNU Autoconf 2.68, with options \\"\$ac_cs_config\\" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pcsc-lite-1.8.0/configure.in new/pcsc-lite-1.8.1/configure.in --- old/pcsc-lite-1.8.0/configure.in 2011-11-19 16:55:37.000000000 +0100 +++ new/pcsc-lite-1.8.1/configure.in 2011-11-25 15:03:21.000000000 +0100 @@ -3,7 +3,7 @@ AC_PREREQ(2.58) -AC_INIT(pcsc-lite, 1.8.0) +AC_INIT(pcsc-lite, 1.8.1) AC_CONFIG_SRCDIR(src/pcscdaemon.c) AM_INIT_AUTOMAKE(1.8 dist-bzip2 no-dist-gzip) AM_CONFIG_HEADER(config.h) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pcsc-lite-1.8.0/src/PCSC/pcsclite.h new/pcsc-lite-1.8.1/src/PCSC/pcsclite.h --- old/pcsc-lite-1.8.0/src/PCSC/pcsclite.h 2011-11-19 16:56:07.000000000 +0100 +++ new/pcsc-lite-1.8.1/src/PCSC/pcsclite.h 2011-11-25 15:09:15.000000000 +0100 @@ -190,7 +190,7 @@ #define INFINITE 0xFFFFFFFF /**< Infinite timeout */ #endif -#define PCSCLITE_VERSION_NUMBER "1.8.0" /**< Current version */ +#define PCSCLITE_VERSION_NUMBER "1.8.1" /**< Current version */ /** Maximum readers context (a slot is count as a reader) */ #define PCSCLITE_MAX_READERS_CONTEXTS 16 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pcsc-lite-1.8.0/src/pcscd.h new/pcsc-lite-1.8.1/src/pcscd.h --- old/pcsc-lite-1.8.0/src/pcscd.h 2011-11-19 16:56:07.000000000 +0100 +++ new/pcsc-lite-1.8.1/src/pcscd.h 2011-11-25 15:09:15.000000000 +0100 @@ -23,7 +23,7 @@ #define SCARD_INSERTED 0x0002 /**< Card was inserted */ #define SCARD_REMOVED 0x0004 /**< Card was removed */ -#define PCSCLITE_CONFIG_DIR "/usr/local/etc/reader.conf.d" +#define PCSCLITE_CONFIG_DIR "/etc/reader.conf.d" #define PCSCLITE_IPC_DIR USE_IPCDIR #define PCSCLITE_RUN_PID PCSCLITE_IPC_DIR "/pcscd.pid" @@ -32,7 +32,7 @@ #define PCSCLITE_SVC_IDENTITY 0x01030000 /**< Service ID */ -#define PCSCLITE_VERSION_NUMBER "1.8.0" /**< Current version */ +#define PCSCLITE_VERSION_NUMBER "1.8.1" /**< Current version */ #define PCSCLITE_STATUS_POLL_RATE 400000 /**< Status polling rate */ #define PCSCLITE_LOCK_POLL_RATE 100000 /**< Lock polling rate */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pcsc-lite-1.8.0/src/spy/Makefile.am new/pcsc-lite-1.8.1/src/spy/Makefile.am --- old/pcsc-lite-1.8.0/src/spy/Makefile.am 2011-10-04 20:45:30.000000000 +0200 +++ new/pcsc-lite-1.8.1/src/spy/Makefile.am 2011-11-25 15:02:52.000000000 +0100 @@ -6,3 +6,4 @@ pcsc-spy.c libpcscspy_la_LIBADD = -ldl +EXTRA_DIST = pcsc-spy.py install_spy.sh uninstall_spy.sh README.txt diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pcsc-lite-1.8.0/src/spy/Makefile.in new/pcsc-lite-1.8.1/src/spy/Makefile.in --- old/pcsc-lite-1.8.0/src/spy/Makefile.in 2011-11-19 16:55:50.000000000 +0100 +++ new/pcsc-lite-1.8.1/src/spy/Makefile.in 2011-11-25 15:09:02.000000000 +0100 @@ -258,6 +258,7 @@ pcsc-spy.c libpcscspy_la_LIBADD = -ldl +EXTRA_DIST = pcsc-spy.py install_spy.sh uninstall_spy.sh README.txt all: all-am .SUFFIXES: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pcsc-lite-1.8.0/src/spy/README.txt new/pcsc-lite-1.8.1/src/spy/README.txt --- old/pcsc-lite-1.8.0/src/spy/README.txt 1970-01-01 01:00:00.000000000 +0100 +++ new/pcsc-lite-1.8.1/src/spy/README.txt 2011-11-19 16:10:59.000000000 +0100 @@ -0,0 +1,57 @@ +============== +PCSC spy HOWTO +============== + +To be able to spy the PC/SC layer, the application flow must be modified +so that all PC/SC calls are redirected. Two options are available: +- the application is linked with libpcsclite.so.1 +- the application loads the libpcsclite.so.1 library using dlopen(3) + +Applications linked with libpcsclite.so.1 +========================================= + +We will use the standard LD_PRELOAD loader option to load our spying +library. + +Example: + +LD_PRELOAD=/usr/lib/libpcscspy.so opensc-tool -a + + +Application loading libpcsclite.so.1 +==================================== + +This is the case for the PC/SC wrappers like pyscard (for Python) and +pcsc-perl (for Perl). The LD_PRELOAD mechanism can't be used. Instead we +replace the libpcsclite.so.1 library by the spying one. + +Use install_spy.sh and uninstall_spy.sh to install and uninstall the +spying library. + +Using the spying library without pcsc-spy.py is not a problem but has +side effects: +- a line "libpcsclite_nospy.so.1: cannot open shared object file: No + such file or directory" will be displayed +- some CPU time will be lost because of the PC/SC calls redirection + + +Starting the spy tool +===================== + +pcsc-spy.py + + +If a command argument is passed we use it instead of the default +~/pcsc-spy FIFO file. It is then possible to record an execution log and +use pcsc-spy.py multiple times on the same log. + +To create the log file just do: + +mkfifo ~/pcsc-spy +cat ~/pcsc-spy > logfile + +and run your PC/SC application + + +Ludovic Rousseau +$Id: README.txt 6107 2011-11-18 09:29:14Z rousseau $ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pcsc-lite-1.8.0/src/spy/install_spy.sh new/pcsc-lite-1.8.1/src/spy/install_spy.sh --- old/pcsc-lite-1.8.0/src/spy/install_spy.sh 1970-01-01 01:00:00.000000000 +0100 +++ new/pcsc-lite-1.8.1/src/spy/install_spy.sh 2011-11-19 16:10:59.000000000 +0100 @@ -0,0 +1,20 @@ +#!/bin/sh + +# exit on the first error +set -e + +cd /usr/lib + +NOSPY=libpcsclite_nospy.so.1 + +if [ -f $NOSPY ] +then + echo "File $NOSPY already exists" +else + # backup the real library + cp libpcsclite.so.1 $NOSPY +fi + +# link to the spy library +ln -sf libpcscspy.so.0.0.0 libpcsclite.so.1.0.0 +ln -sf libpcsclite.so.1.0.0 libpcsclite.so.1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pcsc-lite-1.8.0/src/spy/pcsc-spy.py new/pcsc-lite-1.8.1/src/spy/pcsc-spy.py --- old/pcsc-lite-1.8.0/src/spy/pcsc-spy.py 1970-01-01 01:00:00.000000000 +0100 +++ new/pcsc-lite-1.8.1/src/spy/pcsc-spy.py 2011-11-19 16:10:59.000000000 +0100 @@ -0,0 +1,913 @@ +#! /usr/bin/env python + +""" +# Display PC/SC functions arguments +# Copyright (C) 2011 Ludovic Rousseau +""" +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see http://www.gnu.org/licenses/. + +# $Id: pcsc-spy.py 6108 2011-11-18 12:37:45Z rousseau $ + +import os +import signal +from Queue import Queue +from threading import Thread +from operator import attrgetter + + +def hexdump(data_buffer, width=16): + def quotechars(data_buffer): + return ''.join(['.', chr(c)][c > 31 and c < 127] + for c in data_buffer) + + result = [] + offset = 0 + while data_buffer: + line = data_buffer[:width] + data_buffer = data_buffer[width:] + hex_dump = " ".join("%02X" % c for c in line) + ascii_dump = quotechars(line) + if len(line) < width: + hex_dump += " " * (width - len(line)) + result.append("%04X %s %s" % (offset, hex_dump, ascii_dump)) + offset += width + return result + + +def _parse_rv(line): + """ parse the return value line """ + if line == "": + raise Exception("Empty line (application exited?)") + + (direction, sec, usec, function, code, rv) = line.split('|') + if direction != '<': + raise Exception("Wrong line:", line) + + sec = int(sec) + usec = int(usec) + + return (code, rv, sec, usec) + + +class StatRecord(object): + """ Record to store statistics """ + + def __init__(self, name): + self.name = name + self.executions = list() + self.total_time = 0 + self.occurences = 0 + + def __repr__(self): + return self.name + ": " + repr(self.executions) + + +class PCSCspy(object): + """ PC/SC spy """ + + color_red = "\x1b[01;31m" + color_green = "\x1b[32m" + color_blue = "\x1b[34m" + color_magenta = "\x1b[35m" + color_normal = "\x1b[0m" + + def _log_rv(self): + """ log the return value """ + line = self.queue.get() + (code, rv, sec, usec) = _parse_rv(line) + delta_sec = sec - self.sec + delta_usec = usec - self.usec + if delta_usec < 0: + delta_sec -= 1 + delta_usec += 1000000 + if self.diffable: + time = " [??.??]" + else: + time = " [%d.%09d]" % (delta_sec, delta_usec) + self.execution_time = delta_sec + delta_usec / 1000000. + + rvs = { + 0x00000000: "SCARD_S_SUCCESS", + 0x80100001: "SCARD_F_INTERNAL_ERROR", + 0x80100002: "SCARD_E_CANCELLED", + 0x80100003: "SCARD_E_INVALID_HANDLE", + 0x80100004: "SCARD_E_INVALID_PARAMETER", + 0x80100005: "SCARD_E_INVALID_TARGET", + 0x80100006: "SCARD_E_NO_MEMORY", + 0x80100007: "SCARD_F_WAITED_TOO_LONG", + 0x80100008: "SCARD_E_INSUFFICIENT_BUFFER", + 0x80100009: "SCARD_E_UNKNOWN_READER", + 0x8010000A: "SCARD_E_TIMEOUT", + 0x8010000B: "SCARD_E_SHARING_VIOLATION", + 0x8010000C: "SCARD_E_NO_SMARTCARD", + 0x8010000D: "SCARD_E_UNKNOWN_CARD", + 0x8010000E: "SCARD_E_CANT_DISPOSE", + 0x8010000F: "SCARD_E_PROTO_MISMATCH", + 0x80100010: "SCARD_E_NOT_READY", + 0x80100011: "SCARD_E_INVALID_VALUE", + 0x80100012: "SCARD_E_SYSTEM_CANCELLED", + 0x80100013: "SCARD_F_COMM_ERROR", + 0x80100014: "SCARD_F_UNKNOWN_ERROR", + 0x80100015: "SCARD_E_INVALID_ATR", + 0x80100016: "SCARD_E_NOT_TRANSACTED", + 0x80100017: "SCARD_E_READER_UNAVAILABLE", + 0x80100018: "SCARD_P_SHUTDOWN", + 0x80100019: "SCARD_E_PCI_TOO_SMALL", + 0x8010001A: "SCARD_E_READER_UNSUPPORTED", + 0x8010001B: "SCARD_E_DUPLICATE_READER", + 0x8010001C: "SCARD_E_CARD_UNSUPPORTED", + 0x8010001D: "SCARD_E_NO_SERVICE", + 0x8010001E: "SCARD_E_SERVICE_STOPPED", + 0x8010001F: "SCARD_E_UNSUPPORTED_FEATURE", + 0x80100020: "SCARD_E_ICC_INSTALLATION", + 0x80100021: "SCARD_E_ICC_CREATEORDER", + 0x80100023: "SCARD_E_DIR_NOT_FOUND", + 0x80100024: "SCARD_E_FILE_NOT_FOUND", + 0x80100025: "SCARD_E_NO_DIR", + 0x80100026: "SCARD_E_NO_FILE", + 0x80100027: "SCARD_E_NO_ACCESS", + 0x80100028: "SCARD_E_WRITE_TOO_MANY", + 0x80100029: "SCARD_E_BAD_SEEK", + 0x8010002A: "SCARD_E_INVALID_CHV", + 0x8010002B: "SCARD_E_UNKNOWN_RES_MNG", + 0x8010002C: "SCARD_E_NO_SUCH_CERTIFICATE", + 0x8010002D: "SCARD_E_CERTIFICATE_UNAVAILABLE", + 0x8010002E: "SCARD_E_NO_READERS_AVAILABLE", + 0x8010002F: "SCARD_E_COMM_DATA_LOST", + 0x80100030: "SCARD_E_NO_KEY_CONTAINER", + 0x80100031: "SCARD_E_SERVER_TOO_BUSY", + 0x80100065: "SCARD_W_UNSUPPORTED_CARD", + 0x80100066: "SCARD_W_UNRESPONSIVE_CARD", + 0x80100067: "SCARD_W_UNPOWERED_CARD", + 0x80100068: "SCARD_W_RESET_CARD", + 0x80100069: "SCARD_W_REMOVED_CARD", + 0x8010006A: "SCARD_W_SECURITY_VIOLATION", + 0x8010006B: "SCARD_W_WRONG_CHV", + 0x8010006C: "SCARD_W_CHV_BLOCKED", + 0x8010006D: "SCARD_W_EOF", + 0x8010006E: "SCARD_W_CANCELLED_BY_USER", + 0x8010006F: "SCARD_W_CARD_NOT_AUTHENTICATED", + } + rv_text = rvs[int(rv, 16)] + data = " => " + code + " (" + rv_text + " [" + rv + "]) " + if "0x00000000" != rv: + if self.color: + print self.indent + PCSCspy.color_red + data + PCSCspy.color_normal + time + else: + print self.indent + data + time + else: + print self.indent + data + time + + def log_in(self, line): + """ generic log for IN line """ + if self.color: + print self.indent + PCSCspy.color_green + " i " + line + PCSCspy.color_normal + else: + print self.indent + " i " + line + + def log_out(self, line): + """ generic log for OUT line """ + if self.color: + print self.indent + PCSCspy.color_magenta + " o " + line + PCSCspy.color_normal + else: + print self.indent + " o " + line + + def log_in_multi(self, lines, padding=""): + """ generic log for IN lines """ + for line in lines: + self.log_in(padding + line) + + def log_out_multi(self, lines, padding=""): + """ generic log for OUT lines """ + for line in lines: + self.log_out(padding + line) + + def log_in_hCard(self): + """ log hCard IN parameter """ + hCard = self.queue.get() + if self.diffable: + self.log_in("hCard: 0x????") + else: + self.log_in("hCard: %s" % hCard) + + def log_in_hContext(self): + """ log hContext IN parameter """ + hContext = self.queue.get() + if self.diffable: + self.log_in("hContext: 0x????") + else: + self.log_in("hContext: %s" % hContext) + + def log_in_disposition(self): + """ log dwDisposition IN parameter """ + dwDisposition = self.queue.get() + dispositions = {0: 'SCARD_LEAVE_CARD', + 1: 'SCARD_RESET_CARD', + 2: 'SCARD_UNPOWER_CARD', + 3: 'SCARD_EJECT_CARD'} + try: + disposition = dispositions[int(dwDisposition, 16)] + except KeyError: + disposition = "UNKNOWN" + self.log_in("dwDisposition: %s (%s)" % (disposition, + dwDisposition)) + + def log_in_attrid(self): + """ log dwAttrId IN parameter """ + dwAttrId = self.queue.get() + attrids = {0x00010100: 'SCARD_ATTR_VENDOR_NAME', + 0x00010102: 'SCARD_ATTR_VENDOR_IFD_VERSION', + 0x00010103: 'SCARD_ATTR_VENDOR_IFD_SERIAL_NO', + 0x0007A007: 'SCARD_ATTR_MAXINPUT', + 0x00090300: 'SCARD_ATTR_ICC_PRESENCE', + 0x00090301: 'SCARD_ATTR_ICC_INTERFACE_STATUS', + 0x00090303: 'SCARD_ATTR_ATR_STRING', + 0x7FFF0003: 'SCARD_ATTR_DEVICE_FRIENDLY_NAME'} + try: + attrid = attrids[int(dwAttrId, 16)] + except KeyError: + attrid = "UNKNOWN" + self.log_in("dwAttrId: %s (%s)" % (attrid, dwAttrId)) + + def log_in_dwShareMode(self): + """ log dwShareMode IN parameter """ + dwShareMode = self.queue.get() + sharemodes = {1: 'SCARD_SHARE_EXCLUSIVE', + 2: 'SCARD_SHARE_SHARED', + 3: 'SCARD_SHARE_DIRECT'} + try: + sharemode = sharemodes[int(dwShareMode, 16)] + except KeyError: + sharemode = "UNKNOWN" + self.log_in("dwShareMode: %s (%s)" % (sharemode, dwShareMode)) + + def log_in_dwPreferredProtocols(self): + """ log dwPreferredProtocols IN parameter """ + dwPreferredProtocols = self.queue.get() + PreferredProtocols = list() + protocol = int(dwPreferredProtocols, 16) + if protocol & 1: + PreferredProtocols.append("T=0") + if protocol & 2: + PreferredProtocols.append("T=1") + if protocol & 4: + PreferredProtocols.append("RAW") + if protocol & 8: + PreferredProtocols.append("T=15") + self.log_in("dwPreferredProtocols: %s (%s)" % (dwPreferredProtocols, + ", ".join(PreferredProtocols))) + + def log_out_dwActiveProtocol(self): + """ log dwActiveProtocol OUT parameter """ + dwActiveProtocol = self.queue.get() + protocol = int(dwActiveProtocol, 16) + if protocol & 1: + protocol = "T=0" + elif protocol & 2: + protocol = "T=1" + elif protocol & 4: + protocol = "RAW" + elif protocol & 8: + protocol = "T=15" + else: + protocol = "UNKNOWN" + self.log_out("dwActiveProtocol: %s (%s)" % (protocol, + dwActiveProtocol)) + + def log_out_hContext(self): + """ log hContext OUT parameter """ + hContext = self.queue.get() + if self.diffable: + self.log_out("hContext: 0x????") + else: + self.log_out("hContext: %s" % hContext) + + def _get_state(self, dwState): + """ parse dwCurrentState and dwEventState """ + SCardStates = {0: 'SCARD_STATE_UNAWARE', + 1: 'SCARD_STATE_IGNORE', + 2: 'SCARD_STATE_CHANGED', + 4: 'SCARD_STATE_UNKNOWN', + 8: 'SCARD_STATE_UNAVAILABLE', + 16: 'SCARD_STATE_EMPTY', + 32: 'SCARD_STATE_PRESENT', + 64: 'SCARD_STATE_ATRMATCH', + 128: 'SCARD_STATE_EXCLUSIVE', + 256: 'SCARD_STATE_INUSE', + 512: 'SCARD_STATE_MUTE', + 1024: 'SCARD_STATE_UNPOWERED'} + + state = list() + for bit in SCardStates.keys(): + if dwState & bit: + state.append(SCardStates[bit]) + return ", ".join(state) + + def log_dwCurrentState(self, log): + """ log dwCurrentState IN/OUT parameter """ + dwCurrentState = self.queue.get() + state = self._get_state(int(dwCurrentState, 16)) + log(" dwCurrentState: %s (%s)" % (state, dwCurrentState)) + + def log_dwEventState(self, log): + """ log dwEventState IN/OUT parameter """ + dwEventState = self.queue.get() + state = self._get_state(int(dwEventState, 16)) + log(" dwEventState: %s (%s)" % (state, dwEventState)) + + def log_dwControlCode(self): + """ log SCardControl() dwControlCode """ + dwControlCode = self.queue.get() + + try: + code = self.ControlCodes[int(dwControlCode, 16)] + except KeyError: + code = "UNKNOWN" + self.log_in("dwControlCode: %s (%s)" % (code, dwControlCode)) + + return int(dwControlCode, 16) + + def log_in2(self, header): + """ generic log IN parameter """ + data = self.queue.get() + if data.startswith("0x"): + decimal = int(data, 16) + self.log_in("%s %s (%d)" % (header, data, decimal)) + else: + self.log_in("%s %s" % (header, data)) + return data + + def log_out2(self, header): + """ generic log OUT parameter """ + data = self.queue.get() + if data == "EXIT": + raise Exception("Exit") + if data.startswith("0x"): + decimal = int(data, 16) + self.log_out("%s %s (%d)" % (header, data, decimal)) + else: + self.log_out("%s %s" % (header, data)) + return data + + def log_out_n_str(self, size_name, field_name): + """ log multi-lines entries """ + data = self.queue.get() + self.log_out("%s %s" % (size_name, data)) + size = int(data, 16) + data_read = 0 + if 0 == size: + data = self.queue.get() + self.log_out("%s %s" % (field_name, data)) + else: + while data_read < size: + data = self.queue.get() + self.log_out("%s %s" % (field_name, data)) + if data == 'NULL': + break + data_read += len(data) + 1 + + def log_name(self, name): + """ log function name """ + if self.color: + print self.indent + PCSCspy.color_blue + name + PCSCspy.color_normal + else: + print self.indent + name + + def _log_readers(self, readers, direction): + """ log SCARD_READERSTATE structure """ + log = self.log_in2 + raw_log = self.log_in + if (direction == "out"): + log = self.log_out2 + raw_log = self.log_out + for index in range(readers): + log("szReader:") + self.log_dwCurrentState(raw_log) + self.log_dwEventState(raw_log) + log(" Atr length:") + log(" Atr:") + + def log_buffer(self, field, direction): + log = self.log_in + log_multi = self.log_in_multi + if direction == "out": + log = self.log_out + log_multi = self.log_out_multi + + hex_buffer = self.queue.get() + log(field) + if hex_buffer == "NULL": + log(" NULL") + elif hex_buffer != "": + int_buffer = [int(x, 16) for x in hex_buffer.split(" ")] + formated_buffer = hexdump(int_buffer) + log_multi(formated_buffer, " ") + + return hex_buffer + + def _SCardEstablishContext(self): + """ SCardEstablishContext """ + self.log_name("SCardEstablishContext") + dwScope = self.queue.get() + scopes = {0: 'SCARD_SCOPE_USER', + 1: 'SCARD_SCOPE_TERMINAL', + 2: 'SCARD_SCOPE_SYSTEM'} + self.log_in("dwScope: %s (%s)" % (scopes[int(dwScope, 16)], dwScope)) + self.log_out_hContext() + self._log_rv() + + def _SCardIsValidContext(self): + """ SCardIsValidContext """ + self.log_name("SCardIsValidContext") + self.log_in_hContext() + self._log_rv() + + def _SCardReleaseContext(self): + """ SCardReleaseContext """ + self.log_name("SCardReleaseContext") + self.log_in_hContext() + self._log_rv() + + def _SCardListReaders(self): + """ SCardListReaders """ + self.log_name("SCardListReaders") + self.log_in_hContext() + self.log_in2("mszGroups:") + self.log_out_n_str("pcchReaders:", "mszReaders:") + self._log_rv() + + def _SCardListReaderGroups(self): + """ SCardListReaderGroups """ + self.log_name("SCardListReaderGroups") + self.log_in_hContext() + self.log_in2("pcchGroups:") + self.log_out_n_str("pcchGroups:", "mszGroups:") + self._log_rv() + + def _SCardGetStatusChange(self): + """ SCardGetStatusChange """ + self.log_name("SCardGetStatusChange") + self.log_in_hContext() + self.log_in2("dwTimeout:") + readers = int(self.queue.get(), 16) + self.log_in("cReaders: %d" % readers) + self._log_readers(readers, direction="in") + self._log_readers(readers, direction="out") + self._log_rv() + + def _SCardFreeMemory(self): + """ SCardFreeMemory """ + self.log_name("SCardFreeMemory") + self.log_in_hContext() + self.log_in2("pvMem:") + self._log_rv() + + def _SCardConnect(self): + """ SCardConnect """ + self.log_name("SCardConnect") + self.log_in_hContext() + self.log_in2("szReader") + self.log_in_dwShareMode() + self.log_in_dwPreferredProtocols() + self.log_in2("phCard") + self.log_in2("pdwActiveProtocol") + self.log_out2("phCard") + self.log_out_dwActiveProtocol() + self._log_rv() + + def _SCardTransmit(self): + """ SCardTransmit """ + self.log_name("SCardTransmit") + self.log_in_hCard() + self.log_in2("bSendLength") + self.log_buffer("bSendBuffer", "in") + self.log_out2("bRecvLength") + self.log_buffer("bRecvBuffer", "out") + self._log_rv() + + def _SCardControl(self): + """ SCardControl """ + self.log_name("SCarControl") + self.log_in_hCard() + dwControlCode = self.log_dwControlCode() + bSendLength = self.log_in2("bSendLength") + bSendBuffer = self.log_buffer("bSendBuffer", "in") + bRecvLength = self.log_out2("bRecvLength") + bRecvBuffer = self.log_buffer("bRecvBuffer", "out") + + def hex2int(data, lengh): + return [int(x, 16) for x in data.split(" ")] + + if dwControlCode == self.CM_IOCTL_GET_FEATURE_REQUEST: + print " parsing CM_IOCTL_GET_FEATURE_REQUEST results:" + bRecvLength = int(bRecvLength, 16) + + bRecvBuffer = hex2int(bRecvBuffer, bRecvLength) + + # parse GET_FEATURE_REQUEST results + while bRecvBuffer: + tag = bRecvBuffer[0] + length = bRecvBuffer[1] + value = bRecvBuffer[2:2 + length] + value_int = value[3] + 256 * (value[2] + 256 + * (value[1] + 256 * value[0])) + try: + self.ControlCodes[value_int] = self.features[tag] + self.__dict__[self.features[tag]] = value_int + except KeyError: + self.ControlCodes[value_int] = "UNKNOWN" + + print " Tag %s is 0x%X" % (self.ControlCodes[value_int], + value_int) + + bRecvBuffer = bRecvBuffer[2 + length:] + + elif dwControlCode == self.FEATURE_GET_TLV_PROPERTIES: + print " parsing FEATURE_GET_TLV_PROPERTIES results:" + bRecvLength = int(bRecvLength, 16) + + bRecvBuffer = hex2int(bRecvBuffer, bRecvLength) + + tlv_properties = { + 1: "PCSCv2_PART10_PROPERTY_wLcdLayout", + 2: "PCSCv2_PART10_PROPERTY_bEntryValidationCondition", + 3: "PCSCv2_PART10_PROPERTY_bTimeOut2", + 4: "PCSCv2_PART10_PROPERTY_wLcdMaxCharacters", + 5: "PCSCv2_PART10_PROPERTY_wLcdMaxLines", + 6: "PCSCv2_PART10_PROPERTY_bMinPINSize", + 7: "PCSCv2_PART10_PROPERTY_bMaxPINSize", + 8: "PCSCv2_PART10_PROPERTY_sFirmwareID", + 9: "PCSCv2_PART10_PROPERTY_bPPDUSupport"} + + # parse GET_TLV_PROPERTIES results + while bRecvBuffer: + tag = bRecvBuffer[0] + length = bRecvBuffer[1] + value = bRecvBuffer[2:2 + length] + + try: + tag_text = tlv_properties[tag] + except KeyError: + tag_text = "UNKNOWN" + + print " Tag:", tag_text + print " Length: ", length + print " Value:", value + + bRecvBuffer = bRecvBuffer[2 + length:] + + elif dwControlCode == self.FEATURE_IFD_PIN_PROPERTIES: + print " parsing FEATURE_IFD_PIN_PROPERTIES results:" + bRecvBuffer = hex2int(bRecvBuffer, int(bRecvLength, 16)) + + print " wLcdLayout:", bRecvBuffer[0], bRecvBuffer[1] + print " bEntryValidationCondition:", bRecvBuffer[2] + print " bTimeOut2:", bRecvBuffer[3] + + elif dwControlCode == self.FEATURE_VERIFY_PIN_DIRECT: + print " parsing FEATURE_VERIFY_PIN_DIRECT:" + bSendBuffer = hex2int(bSendBuffer, int(bSendLength, 16)) + + print " bTimerOut:", bSendBuffer[0] + print " bTimerOut2:", bSendBuffer[1] + print " bmFormatString:", bSendBuffer[2] + print " bmPINBlockString:", bSendBuffer[3] + print " bmPINLengthFormat:", bSendBuffer[4] + print " wPINMaxExtraDigit: 0x%02X%02X" % (bSendBuffer[6], + bSendBuffer[5]) + print " Min:", bSendBuffer[6] + print " Max:", bSendBuffer[5] + print " bEntryValidationCondition:", bSendBuffer[7] + print " bNumberMessage:", bSendBuffer[8] + print " wLangId: 0x%02X%02X" % (bSendBuffer[10], bSendBuffer[9]) + print " bMsgIndex:", bSendBuffer[11] + print " bTeoPrologue:", bSendBuffer[12], bSendBuffer[13], \ + bSendBuffer[14] + print " ulDataLength:", bSendBuffer[15] + \ + bSendBuffer[16] * 256 + bSendBuffer[17] * 2 ** 16 + \ + bSendBuffer[18] * 2 ** 24 + print " APDU:" + result = hexdump(bSendBuffer[19:]) + for line in result: + print " ", line + + self._log_rv() + + def _SCardGetAttrib(self): + """ SCardGetAttrib """ + self.log_name("SCardGetAttrib") + self.log_in_hCard() + self.log_in_attrid() + self.log_out2("bAttrLen") + self.log_buffer("bAttr", "out") + self._log_rv() + + def _SCardSetAttrib(self): + """ SCardSetAttrib """ + self.log_name("SCardSetAttrib") + self.log_in_hCard() + self.log_in_attrid() + self.log_in2("bAttrLen") + self.log_buffer("bAttr", "in") + self._log_rv() + + def _SCardStatus(self): + """ SCardStatus """ + self.log_name("SCardStatus") + self.log_in_hCard() + self.log_in2("pcchReaderLen") + self.log_in2("pcbAtrLen") + self.log_out2("cchReaderLen") + self.log_out2("mszReaderName") + self.log_out2("dwState") + self.log_out2("dwProtocol") + self.log_out2("bAtrLen") + self.log_out2("bAtr") + self._log_rv() + + def _SCardReconnect(self): + """ SCardReconnect """ + self.log_name("SCardReconnect") + self.log_in_hCard() + self.log_in_dwShareMode() + self.log_in_dwPreferredProtocols() + self.log_in2("dwInitialization") + self.log_out_dwActiveProtocol() + self._log_rv() + + def _SCardDisconnect(self): + """" SCardDisconnect """ + self.log_name("SCardDisconnect") + self.log_in_hCard() + self.log_in_disposition() + self._log_rv() + + def _SCardBeginTransaction(self): + """ SCardBeginTransaction """ + self.log_name("SCardBeginTransaction") + self.log_in_hCard() + self._log_rv() + + def _SCardEndTransaction(self): + """ SCardEndTransaction """ + self.log_name("SCardEndTransaction") + self.log_in_hCard() + self.log_in_disposition() + self._log_rv() + + def _SCardCancel(self): + """ SCardCancel """ + self.log_name("SCardCancel") + self.log_in_hCard() + self._log_rv() + + def __init__(self, queue, stats, indent=0, color=True, diffable=False): + """ constructor """ + + # communication queue + self.queue = queue + + self.color = color + self.diffable = diffable + self.stats = stats + self.indent = " " * indent + + self.features = {0x01: "FEATURE_VERIFY_PIN_START", + 0x02: "FEATURE_VERIFY_PIN_FINISH", + 0x03: "FEATURE_MODIFY_PIN_START", + 0x04: "FEATURE_MODIFY_PIN_FINISH", + 0x05: "FEATURE_GET_KEY_PRESSED", + 0x06: "FEATURE_VERIFY_PIN_DIRECT", + 0x07: "FEATURE_MODIFY_PIN_DIRECT", + 0x08: "FEATURE_MCT_READER_DIRECT", + 0x09: "FEATURE_MCT_UNIVERSAL", + 0x0A: "FEATURE_IFD_PIN_PROPERTIES", + 0x0B: "FEATURE_ABORT", + 0x0C: "FEATURE_SET_SPE_MESSAGE", + 0x0D: "FEATURE_VERIFY_PIN_DIRECT_APP_ID", + 0x0E: "FEATURE_MODIFY_PIN_DIRECT_APP_ID", + 0x0F: "FEATURE_WRITE_DISPLAY", + 0x10: "FEATURE_GET_KEY", + 0x11: "FEATURE_IFD_DISPLAY_PROPERTIES", + 0x12: "FEATURE_GET_TLV_PROPERTIES", + 0x13: "FEATURE_CCID_ESC_COMMAND"} + + def SCARD_CTL_CODE(code): + return 0x42000000 + code + + self.CM_IOCTL_GET_FEATURE_REQUEST = SCARD_CTL_CODE(3400) + self.ControlCodes = { + SCARD_CTL_CODE(1): "IOCTL_SMARTCARD_VENDOR_IFD_EXCHANGE", + SCARD_CTL_CODE(3400): "CM_IOCTL_GET_FEATURE_REQUEST" + } + # dwControlCode not yet known + for key in self.features.keys(): + self.__dict__[self.features[key]] = -1 + + def worker(self, *args): + line = self.queue.get() + while line != '': + # Enter function? + if line[0] != '>': + if line == 'EXIT': + return + else: + print "Garbage: ", line + else: + # dispatch + (direction, sec, usec, fct) = line.strip().split('|') + self.sec = int(sec) + self.usec = int(usec) + if fct == 'SCardEstablishContext': + self._SCardEstablishContext() + elif fct == 'SCardReleaseContext': + self._SCardReleaseContext() + elif fct == 'SCardIsValidContext': + self._SCardIsValidContext() + elif fct == 'SCardListReaderGroups': + self._SCardListReaderGroups() + elif fct == 'SCardFreeMemory': + self._SCardFreeMemory() + elif fct == 'SCardListReaders': + self._SCardListReaders() + elif fct == 'SCardGetStatusChange': + self._SCardGetStatusChange() + elif fct == 'SCardConnect': + self._SCardConnect() + elif fct == 'SCardTransmit': + self._SCardTransmit() + elif fct == 'SCardControl': + self._SCardControl() + elif fct == 'SCardGetAttrib': + self._SCardGetAttrib() + elif fct == 'SCardSetAttrib': + self._SCardSetAttrib() + elif fct == 'SCardStatus': + self._SCardStatus() + elif fct == 'SCardReconnect': + self._SCardReconnect() + elif fct == 'SCardDisconnect': + self._SCardDisconnect() + elif fct == 'SCardBeginTransaction': + self._SCardBeginTransaction() + elif fct == 'SCardEndTransaction': + self._SCardEndTransaction() + elif fct == 'SCardCancel': + self._SCardCancel() + else: + print "Unknown function:", fct + + try: + record = self.stats[fct] + except KeyError: + record = self.stats[fct] = StatRecord(fct) + record.executions.append(self.execution_time) + + line = self.queue.get() + + +class PCSCdemultiplexer(object): + def __init__(self, logfile=None, color=True, diffable=False): + """ constructor """ + + # use default fifo file? + if logfile == None: + logfile = os.path.expanduser('~/pcsc-spy') + + # create the FIFO file + try: + os.mkfifo(logfile) + except (OSError): + print "fifo %s already present. Reusing it." % logfile + + self.sec = self.usec = 0 + + self.fifo = logfile + self.filedesc2 = open(self.fifo, 'r') + + self.queues = dict() + self.color = color + self.diffable = diffable + + def __del__(self): + """ cleanup """ + from stat import S_ISFIFO + file_stat = os.stat(self.fifo) + + # remove the log fifo only if it is a FIFO and not a log file + if S_ISFIFO(file_stat.st_mode): + os.unlink(self.fifo) + + def loop(self): + """ loop reading logs """ + + # for statistics + stats = dict() + + threads = dict() + indent = 0 + + # dispatch + line = self.filedesc2.readline().strip() + + (thread, tail) = line.split('@') + (direction, sec, usec, fct) = tail.strip().split('|') + start_time = int(sec) + int(usec) / 1000000. + + while line != '': + (thread, tail) = line.split('@') + + try: + queue = self.queues[thread] + except KeyError: + queue = self.queues[thread] = Queue() + stats[thread] = dict() + # new worker + spy = PCSCspy(queue, stats[thread], indent=indent, + color=self.color, diffable=self.diffable) + threads[thread] = Thread(target=spy.worker) + threads[thread].start() + indent += 4 + + queue.put(tail) + + line = self.filedesc2.readline().strip() + + # tell the workers to exit + for thread in self.queues.keys(): + self.queues[thread].put('EXIT') + + # wait for all the workers to finish + for thread in threads: + threads[thread].join() + + (code, rv, sec, usec) = _parse_rv(tail) + end_time = sec + usec / 1000000. + total_time = end_time - start_time + + # compute some statistics + for thread in stats: + stat = stats[thread] + for fct in stat: + record = stat[fct] + record.occurences = len(record.executions) + record.total_time = sum(record.executions) + + records = [stat[fct] for fct in stat] + + # display statistics sorted by total_time + print + print "Results sorted by total execution time" + print "total time: %f sec" % total_time + for record in sorted(records, key=attrgetter('total_time'), + reverse=True): + print "%f sec (%3d calls) %5.2f%% %s" % (record.total_time, + record.occurences, record.total_time / total_time * 100., + record.name) + + +def main(logfile=None, color=True, diffable=False): + """ main """ + spy = PCSCdemultiplexer(logfile, color, diffable) + spy.loop() + +def signal_handler(sig, frame): + print 'Ctrl-C, exiting.' + os.kill(os.getpid(), signal.SIGQUIT) + +if __name__ == "__main__": + import sys + import getopt + + logfile = None + try: + opts, args = getopt.getopt(sys.argv[1:], "nd", ["nocolor", "diffable"]) + except getopt.GetoptError: + print "Usage: %s [-n|--nocolor] [-d|--diffable]" + sys.exit(1) + + color = True + diffable = False + for o, a in opts: + if o == "-n" or o == "--nocolor": + color = False + if o == "-d" or o == "--diffable": + diffable = True + + if len(args) > 0: + logfile = args[0] + + signal.signal(signal.SIGINT, signal_handler) + main(logfile, color=color, diffable=diffable) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pcsc-lite-1.8.0/src/spy/uninstall_spy.sh new/pcsc-lite-1.8.1/src/spy/uninstall_spy.sh --- old/pcsc-lite-1.8.0/src/spy/uninstall_spy.sh 1970-01-01 01:00:00.000000000 +0100 +++ new/pcsc-lite-1.8.1/src/spy/uninstall_spy.sh 2011-10-22 10:30:37.000000000 +0200 @@ -0,0 +1,9 @@ +#!/bin/sh + +# exit on the first error +set -e + +cd /usr/lib + +# Use the real library again +mv libpcsclite_nospy.so.1 libpcsclite.so.1.0.0 ++++++ systemd-service.patch ++++++ diff --git a/etc/pcscd.service.in b/etc/pcscd.service.in index 68dcfaa..8e632c8 100644 --- a/etc/pcscd.service.in +++ b/etc/pcscd.service.in @@ -3,7 +3,9 @@ Description=PC/SC Smart Card Daemon Requires=pcscd.socket [Service] -ExecStart=@sbindir_exp@/pcscd --foreground --auto-exit +Environment=PCSCD_OPTIONS="" +EnvironmentFile=-/etc/sysconfig/pcscd +ExecStart=@sbindir_exp@/pcscd --foreground --auto-exit $PCSCD_OPTIONS ExecReload=@sbindir_exp@/pcscd --hotplug StandardOutput=syslog -- To unsubscribe, e-mail: opensuse-commit+unsubscribe@opensuse.org For additional commands, e-mail: opensuse-commit+help@opensuse.org