New upstream version 1.8.22
This commit is contained in:
parent
8030f65243
commit
acc3243be1
|
@ -0,0 +1,9 @@
|
||||||
|
Main authors:
|
||||||
|
- David Corcoran <corcoran@musclecard.com>
|
||||||
|
- Ludovic Rousseau <ludovic.rousseau@free.fr>
|
||||||
|
- Damien Sauveron <sauveron@labri.fr>
|
||||||
|
|
||||||
|
Additional code by:
|
||||||
|
- Carlos Prados <cprados@yahoo.com>
|
||||||
|
- Antti Tapaninen <aet@cc.hut.fi>
|
||||||
|
- and some others
|
|
@ -0,0 +1,119 @@
|
||||||
|
Copyright (c) 1999-2003 David Corcoran <corcoran@musclecard.com>
|
||||||
|
Copyright (c) 2001-2011 Ludovic Rousseau <ludovic.rousseau@free.fr>
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. The name of the author may not be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
|
||||||
|
Some files are under GNU GPL v3 or any later version
|
||||||
|
- doc/example/pcsc_demo.c
|
||||||
|
- the files in src/spy/
|
||||||
|
- the files in UnitaryTests/
|
||||||
|
|
||||||
|
Copyright (C) 2003-2014 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/>.
|
||||||
|
|
||||||
|
|
||||||
|
Files src/auth.c and src/auth.h are:
|
||||||
|
* Copyright (C) 2013 Red Hat
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||||
|
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||||
|
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||||
|
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||||
|
* DAMAGE.
|
||||||
|
*
|
||||||
|
* Author: Nikos Mavrogiannopoulos <nmav@redhat.com>
|
||||||
|
|
||||||
|
|
||||||
|
Files src/sd-daemon.c and src/sd-daemon.h are:
|
||||||
|
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.
|
||||||
|
|
||||||
|
|
||||||
|
Files src/simclist.c and src/simclist.h are:
|
||||||
|
* Copyright (c) 2007,2008,2009,2010,2011 Mij <mij@bitchx.it>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,28 @@
|
||||||
|
DRIVERS
|
||||||
|
|
||||||
|
To install USB drivers, download the driver from
|
||||||
|
http://musclecard.com/software.html and copy it to a temporary location.
|
||||||
|
After you have unarchived the files copy the directory to
|
||||||
|
/usr/local/pcsc/drivers/. If the directory /usr/local/pcsc/drivers/
|
||||||
|
does not exist create it before copying the driver directory to it.
|
||||||
|
|
||||||
|
Example Mac OS X, Linux 2.4:
|
||||||
|
|
||||||
|
tar -xzvf driver.bundle-0.1.0.tar.gz
|
||||||
|
cp -r driver.bundle /usr/local/pcsc/drivers/
|
||||||
|
cd /usr/local/pcsc/drivers/driver.bundle
|
||||||
|
build or use Project Builder to build
|
||||||
|
|
||||||
|
The /usr/local/pcsc/drivers/ directory should contain bundle directories only.
|
||||||
|
You must restart pcscd to use the new driver.
|
||||||
|
|
||||||
|
|
||||||
|
All OS's:
|
||||||
|
|
||||||
|
For non-USB users, you must edit the /etc/reader.conf file.
|
||||||
|
You can do this easily by running the installifd program in the utils/
|
||||||
|
directory of pcsc-lite. Some newer drivers require you to specify 1 as the
|
||||||
|
port and then make a symlink from /dev/pcsc/1 to /dev/ttyS* so you can
|
||||||
|
enumerate your ports on any Unix without changing the driver.
|
||||||
|
|
||||||
|
Refer to the driver README for more information.
|
|
@ -0,0 +1,674 @@
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The GNU General Public License is a free, copyleft license for
|
||||||
|
software and other kinds of works.
|
||||||
|
|
||||||
|
The licenses for most software and other practical works are designed
|
||||||
|
to take away your freedom to share and change the works. By contrast,
|
||||||
|
the GNU General Public License is intended to guarantee your freedom to
|
||||||
|
share and change all versions of a program--to make sure it remains free
|
||||||
|
software for all its users. We, the Free Software Foundation, use the
|
||||||
|
GNU General Public License for most of our software; it applies also to
|
||||||
|
any other work released this way by its authors. You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
them if you wish), that you receive source code or can get it if you
|
||||||
|
want it, that you can change the software or use pieces of it in new
|
||||||
|
free programs, and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to prevent others from denying you
|
||||||
|
these rights or asking you to surrender the rights. Therefore, you have
|
||||||
|
certain responsibilities if you distribute copies of the software, or if
|
||||||
|
you modify it: responsibilities to respect the freedom of others.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must pass on to the recipients the same
|
||||||
|
freedoms that you received. You must make sure that they, too, receive
|
||||||
|
or can get the source code. And you must show them these terms so they
|
||||||
|
know their rights.
|
||||||
|
|
||||||
|
Developers that use the GNU GPL protect your rights with two steps:
|
||||||
|
(1) assert copyright on the software, and (2) offer you this License
|
||||||
|
giving you legal permission to copy, distribute and/or modify it.
|
||||||
|
|
||||||
|
For the developers' and authors' protection, the GPL clearly explains
|
||||||
|
that there is no warranty for this free software. For both users' and
|
||||||
|
authors' sake, the GPL requires that modified versions be marked as
|
||||||
|
changed, so that their problems will not be attributed erroneously to
|
||||||
|
authors of previous versions.
|
||||||
|
|
||||||
|
Some devices are designed to deny users access to install or run
|
||||||
|
modified versions of the software inside them, although the manufacturer
|
||||||
|
can do so. This is fundamentally incompatible with the aim of
|
||||||
|
protecting users' freedom to change the software. The systematic
|
||||||
|
pattern of such abuse occurs in the area of products for individuals to
|
||||||
|
use, which is precisely where it is most unacceptable. Therefore, we
|
||||||
|
have designed this version of the GPL to prohibit the practice for those
|
||||||
|
products. If such problems arise substantially in other domains, we
|
||||||
|
stand ready to extend this provision to those domains in future versions
|
||||||
|
of the GPL, as needed to protect the freedom of users.
|
||||||
|
|
||||||
|
Finally, every program is threatened constantly by software patents.
|
||||||
|
States should not allow patents to restrict development and use of
|
||||||
|
software on general-purpose computers, but in those that do, we wish to
|
||||||
|
avoid the special danger that patents applied to a free program could
|
||||||
|
make it effectively proprietary. To prevent this, the GPL assures that
|
||||||
|
patents cannot be used to render the program non-free.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
0. Definitions.
|
||||||
|
|
||||||
|
"This License" refers to version 3 of the GNU General Public License.
|
||||||
|
|
||||||
|
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||||
|
works, such as semiconductor masks.
|
||||||
|
|
||||||
|
"The Program" refers to any copyrightable work licensed under this
|
||||||
|
License. Each licensee is addressed as "you". "Licensees" and
|
||||||
|
"recipients" may be individuals or organizations.
|
||||||
|
|
||||||
|
To "modify" a work means to copy from or adapt all or part of the work
|
||||||
|
in a fashion requiring copyright permission, other than the making of an
|
||||||
|
exact copy. The resulting work is called a "modified version" of the
|
||||||
|
earlier work or a work "based on" the earlier work.
|
||||||
|
|
||||||
|
A "covered work" means either the unmodified Program or a work based
|
||||||
|
on the Program.
|
||||||
|
|
||||||
|
To "propagate" a work means to do anything with it that, without
|
||||||
|
permission, would make you directly or secondarily liable for
|
||||||
|
infringement under applicable copyright law, except executing it on a
|
||||||
|
computer or modifying a private copy. Propagation includes copying,
|
||||||
|
distribution (with or without modification), making available to the
|
||||||
|
public, and in some countries other activities as well.
|
||||||
|
|
||||||
|
To "convey" a work means any kind of propagation that enables other
|
||||||
|
parties to make or receive copies. Mere interaction with a user through
|
||||||
|
a computer network, with no transfer of a copy, is not conveying.
|
||||||
|
|
||||||
|
An interactive user interface displays "Appropriate Legal Notices"
|
||||||
|
to the extent that it includes a convenient and prominently visible
|
||||||
|
feature that (1) displays an appropriate copyright notice, and (2)
|
||||||
|
tells the user that there is no warranty for the work (except to the
|
||||||
|
extent that warranties are provided), that licensees may convey the
|
||||||
|
work under this License, and how to view a copy of this License. If
|
||||||
|
the interface presents a list of user commands or options, such as a
|
||||||
|
menu, a prominent item in the list meets this criterion.
|
||||||
|
|
||||||
|
1. Source Code.
|
||||||
|
|
||||||
|
The "source code" for a work means the preferred form of the work
|
||||||
|
for making modifications to it. "Object code" means any non-source
|
||||||
|
form of a work.
|
||||||
|
|
||||||
|
A "Standard Interface" means an interface that either is an official
|
||||||
|
standard defined by a recognized standards body, or, in the case of
|
||||||
|
interfaces specified for a particular programming language, one that
|
||||||
|
is widely used among developers working in that language.
|
||||||
|
|
||||||
|
The "System Libraries" of an executable work include anything, other
|
||||||
|
than the work as a whole, that (a) is included in the normal form of
|
||||||
|
packaging a Major Component, but which is not part of that Major
|
||||||
|
Component, and (b) serves only to enable use of the work with that
|
||||||
|
Major Component, or to implement a Standard Interface for which an
|
||||||
|
implementation is available to the public in source code form. A
|
||||||
|
"Major Component", in this context, means a major essential component
|
||||||
|
(kernel, window system, and so on) of the specific operating system
|
||||||
|
(if any) on which the executable work runs, or a compiler used to
|
||||||
|
produce the work, or an object code interpreter used to run it.
|
||||||
|
|
||||||
|
The "Corresponding Source" for a work in object code form means all
|
||||||
|
the source code needed to generate, install, and (for an executable
|
||||||
|
work) run the object code and to modify the work, including scripts to
|
||||||
|
control those activities. However, it does not include the work's
|
||||||
|
System Libraries, or general-purpose tools or generally available free
|
||||||
|
programs which are used unmodified in performing those activities but
|
||||||
|
which are not part of the work. For example, Corresponding Source
|
||||||
|
includes interface definition files associated with source files for
|
||||||
|
the work, and the source code for shared libraries and dynamically
|
||||||
|
linked subprograms that the work is specifically designed to require,
|
||||||
|
such as by intimate data communication or control flow between those
|
||||||
|
subprograms and other parts of the work.
|
||||||
|
|
||||||
|
The Corresponding Source need not include anything that users
|
||||||
|
can regenerate automatically from other parts of the Corresponding
|
||||||
|
Source.
|
||||||
|
|
||||||
|
The Corresponding Source for a work in source code form is that
|
||||||
|
same work.
|
||||||
|
|
||||||
|
2. Basic Permissions.
|
||||||
|
|
||||||
|
All rights granted under this License are granted for the term of
|
||||||
|
copyright on the Program, and are irrevocable provided the stated
|
||||||
|
conditions are met. This License explicitly affirms your unlimited
|
||||||
|
permission to run the unmodified Program. The output from running a
|
||||||
|
covered work is covered by this License only if the output, given its
|
||||||
|
content, constitutes a covered work. This License acknowledges your
|
||||||
|
rights of fair use or other equivalent, as provided by copyright law.
|
||||||
|
|
||||||
|
You may make, run and propagate covered works that you do not
|
||||||
|
convey, without conditions so long as your license otherwise remains
|
||||||
|
in force. You may convey covered works to others for the sole purpose
|
||||||
|
of having them make modifications exclusively for you, or provide you
|
||||||
|
with facilities for running those works, provided that you comply with
|
||||||
|
the terms of this License in conveying all material for which you do
|
||||||
|
not control copyright. Those thus making or running the covered works
|
||||||
|
for you must do so exclusively on your behalf, under your direction
|
||||||
|
and control, on terms that prohibit them from making any copies of
|
||||||
|
your copyrighted material outside their relationship with you.
|
||||||
|
|
||||||
|
Conveying under any other circumstances is permitted solely under
|
||||||
|
the conditions stated below. Sublicensing is not allowed; section 10
|
||||||
|
makes it unnecessary.
|
||||||
|
|
||||||
|
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||||
|
|
||||||
|
No covered work shall be deemed part of an effective technological
|
||||||
|
measure under any applicable law fulfilling obligations under article
|
||||||
|
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||||
|
similar laws prohibiting or restricting circumvention of such
|
||||||
|
measures.
|
||||||
|
|
||||||
|
When you convey a covered work, you waive any legal power to forbid
|
||||||
|
circumvention of technological measures to the extent such circumvention
|
||||||
|
is effected by exercising rights under this License with respect to
|
||||||
|
the covered work, and you disclaim any intention to limit operation or
|
||||||
|
modification of the work as a means of enforcing, against the work's
|
||||||
|
users, your or third parties' legal rights to forbid circumvention of
|
||||||
|
technological measures.
|
||||||
|
|
||||||
|
4. Conveying Verbatim Copies.
|
||||||
|
|
||||||
|
You may convey verbatim copies of the Program's source code as you
|
||||||
|
receive it, in any medium, provided that you conspicuously and
|
||||||
|
appropriately publish on each copy an appropriate copyright notice;
|
||||||
|
keep intact all notices stating that this License and any
|
||||||
|
non-permissive terms added in accord with section 7 apply to the code;
|
||||||
|
keep intact all notices of the absence of any warranty; and give all
|
||||||
|
recipients a copy of this License along with the Program.
|
||||||
|
|
||||||
|
You may charge any price or no price for each copy that you convey,
|
||||||
|
and you may offer support or warranty protection for a fee.
|
||||||
|
|
||||||
|
5. Conveying Modified Source Versions.
|
||||||
|
|
||||||
|
You may convey a work based on the Program, or the modifications to
|
||||||
|
produce it from the Program, in the form of source code under the
|
||||||
|
terms of section 4, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The work must carry prominent notices stating that you modified
|
||||||
|
it, and giving a relevant date.
|
||||||
|
|
||||||
|
b) The work must carry prominent notices stating that it is
|
||||||
|
released under this License and any conditions added under section
|
||||||
|
7. This requirement modifies the requirement in section 4 to
|
||||||
|
"keep intact all notices".
|
||||||
|
|
||||||
|
c) You must license the entire work, as a whole, under this
|
||||||
|
License to anyone who comes into possession of a copy. This
|
||||||
|
License will therefore apply, along with any applicable section 7
|
||||||
|
additional terms, to the whole of the work, and all its parts,
|
||||||
|
regardless of how they are packaged. This License gives no
|
||||||
|
permission to license the work in any other way, but it does not
|
||||||
|
invalidate such permission if you have separately received it.
|
||||||
|
|
||||||
|
d) If the work has interactive user interfaces, each must display
|
||||||
|
Appropriate Legal Notices; however, if the Program has interactive
|
||||||
|
interfaces that do not display Appropriate Legal Notices, your
|
||||||
|
work need not make them do so.
|
||||||
|
|
||||||
|
A compilation of a covered work with other separate and independent
|
||||||
|
works, which are not by their nature extensions of the covered work,
|
||||||
|
and which are not combined with it such as to form a larger program,
|
||||||
|
in or on a volume of a storage or distribution medium, is called an
|
||||||
|
"aggregate" if the compilation and its resulting copyright are not
|
||||||
|
used to limit the access or legal rights of the compilation's users
|
||||||
|
beyond what the individual works permit. Inclusion of a covered work
|
||||||
|
in an aggregate does not cause this License to apply to the other
|
||||||
|
parts of the aggregate.
|
||||||
|
|
||||||
|
6. Conveying Non-Source Forms.
|
||||||
|
|
||||||
|
You may convey a covered work in object code form under the terms
|
||||||
|
of sections 4 and 5, provided that you also convey the
|
||||||
|
machine-readable Corresponding Source under the terms of this License,
|
||||||
|
in one of these ways:
|
||||||
|
|
||||||
|
a) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by the
|
||||||
|
Corresponding Source fixed on a durable physical medium
|
||||||
|
customarily used for software interchange.
|
||||||
|
|
||||||
|
b) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by a
|
||||||
|
written offer, valid for at least three years and valid for as
|
||||||
|
long as you offer spare parts or customer support for that product
|
||||||
|
model, to give anyone who possesses the object code either (1) a
|
||||||
|
copy of the Corresponding Source for all the software in the
|
||||||
|
product that is covered by this License, on a durable physical
|
||||||
|
medium customarily used for software interchange, for a price no
|
||||||
|
more than your reasonable cost of physically performing this
|
||||||
|
conveying of source, or (2) access to copy the
|
||||||
|
Corresponding Source from a network server at no charge.
|
||||||
|
|
||||||
|
c) Convey individual copies of the object code with a copy of the
|
||||||
|
written offer to provide the Corresponding Source. This
|
||||||
|
alternative is allowed only occasionally and noncommercially, and
|
||||||
|
only if you received the object code with such an offer, in accord
|
||||||
|
with subsection 6b.
|
||||||
|
|
||||||
|
d) Convey the object code by offering access from a designated
|
||||||
|
place (gratis or for a charge), and offer equivalent access to the
|
||||||
|
Corresponding Source in the same way through the same place at no
|
||||||
|
further charge. You need not require recipients to copy the
|
||||||
|
Corresponding Source along with the object code. If the place to
|
||||||
|
copy the object code is a network server, the Corresponding Source
|
||||||
|
may be on a different server (operated by you or a third party)
|
||||||
|
that supports equivalent copying facilities, provided you maintain
|
||||||
|
clear directions next to the object code saying where to find the
|
||||||
|
Corresponding Source. Regardless of what server hosts the
|
||||||
|
Corresponding Source, you remain obligated to ensure that it is
|
||||||
|
available for as long as needed to satisfy these requirements.
|
||||||
|
|
||||||
|
e) Convey the object code using peer-to-peer transmission, provided
|
||||||
|
you inform other peers where the object code and Corresponding
|
||||||
|
Source of the work are being offered to the general public at no
|
||||||
|
charge under subsection 6d.
|
||||||
|
|
||||||
|
A separable portion of the object code, whose source code is excluded
|
||||||
|
from the Corresponding Source as a System Library, need not be
|
||||||
|
included in conveying the object code work.
|
||||||
|
|
||||||
|
A "User Product" is either (1) a "consumer product", which means any
|
||||||
|
tangible personal property which is normally used for personal, family,
|
||||||
|
or household purposes, or (2) anything designed or sold for incorporation
|
||||||
|
into a dwelling. In determining whether a product is a consumer product,
|
||||||
|
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||||
|
product received by a particular user, "normally used" refers to a
|
||||||
|
typical or common use of that class of product, regardless of the status
|
||||||
|
of the particular user or of the way in which the particular user
|
||||||
|
actually uses, or expects or is expected to use, the product. A product
|
||||||
|
is a consumer product regardless of whether the product has substantial
|
||||||
|
commercial, industrial or non-consumer uses, unless such uses represent
|
||||||
|
the only significant mode of use of the product.
|
||||||
|
|
||||||
|
"Installation Information" for a User Product means any methods,
|
||||||
|
procedures, authorization keys, or other information required to install
|
||||||
|
and execute modified versions of a covered work in that User Product from
|
||||||
|
a modified version of its Corresponding Source. The information must
|
||||||
|
suffice to ensure that the continued functioning of the modified object
|
||||||
|
code is in no case prevented or interfered with solely because
|
||||||
|
modification has been made.
|
||||||
|
|
||||||
|
If you convey an object code work under this section in, or with, or
|
||||||
|
specifically for use in, a User Product, and the conveying occurs as
|
||||||
|
part of a transaction in which the right of possession and use of the
|
||||||
|
User Product is transferred to the recipient in perpetuity or for a
|
||||||
|
fixed term (regardless of how the transaction is characterized), the
|
||||||
|
Corresponding Source conveyed under this section must be accompanied
|
||||||
|
by the Installation Information. But this requirement does not apply
|
||||||
|
if neither you nor any third party retains the ability to install
|
||||||
|
modified object code on the User Product (for example, the work has
|
||||||
|
been installed in ROM).
|
||||||
|
|
||||||
|
The requirement to provide Installation Information does not include a
|
||||||
|
requirement to continue to provide support service, warranty, or updates
|
||||||
|
for a work that has been modified or installed by the recipient, or for
|
||||||
|
the User Product in which it has been modified or installed. Access to a
|
||||||
|
network may be denied when the modification itself materially and
|
||||||
|
adversely affects the operation of the network or violates the rules and
|
||||||
|
protocols for communication across the network.
|
||||||
|
|
||||||
|
Corresponding Source conveyed, and Installation Information provided,
|
||||||
|
in accord with this section must be in a format that is publicly
|
||||||
|
documented (and with an implementation available to the public in
|
||||||
|
source code form), and must require no special password or key for
|
||||||
|
unpacking, reading or copying.
|
||||||
|
|
||||||
|
7. Additional Terms.
|
||||||
|
|
||||||
|
"Additional permissions" are terms that supplement the terms of this
|
||||||
|
License by making exceptions from one or more of its conditions.
|
||||||
|
Additional permissions that are applicable to the entire Program shall
|
||||||
|
be treated as though they were included in this License, to the extent
|
||||||
|
that they are valid under applicable law. If additional permissions
|
||||||
|
apply only to part of the Program, that part may be used separately
|
||||||
|
under those permissions, but the entire Program remains governed by
|
||||||
|
this License without regard to the additional permissions.
|
||||||
|
|
||||||
|
When you convey a copy of a covered work, you may at your option
|
||||||
|
remove any additional permissions from that copy, or from any part of
|
||||||
|
it. (Additional permissions may be written to require their own
|
||||||
|
removal in certain cases when you modify the work.) You may place
|
||||||
|
additional permissions on material, added by you to a covered work,
|
||||||
|
for which you have or can give appropriate copyright permission.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, for material you
|
||||||
|
add to a covered work, you may (if authorized by the copyright holders of
|
||||||
|
that material) supplement the terms of this License with terms:
|
||||||
|
|
||||||
|
a) Disclaiming warranty or limiting liability differently from the
|
||||||
|
terms of sections 15 and 16 of this License; or
|
||||||
|
|
||||||
|
b) Requiring preservation of specified reasonable legal notices or
|
||||||
|
author attributions in that material or in the Appropriate Legal
|
||||||
|
Notices displayed by works containing it; or
|
||||||
|
|
||||||
|
c) Prohibiting misrepresentation of the origin of that material, or
|
||||||
|
requiring that modified versions of such material be marked in
|
||||||
|
reasonable ways as different from the original version; or
|
||||||
|
|
||||||
|
d) Limiting the use for publicity purposes of names of licensors or
|
||||||
|
authors of the material; or
|
||||||
|
|
||||||
|
e) Declining to grant rights under trademark law for use of some
|
||||||
|
trade names, trademarks, or service marks; or
|
||||||
|
|
||||||
|
f) Requiring indemnification of licensors and authors of that
|
||||||
|
material by anyone who conveys the material (or modified versions of
|
||||||
|
it) with contractual assumptions of liability to the recipient, for
|
||||||
|
any liability that these contractual assumptions directly impose on
|
||||||
|
those licensors and authors.
|
||||||
|
|
||||||
|
All other non-permissive additional terms are considered "further
|
||||||
|
restrictions" within the meaning of section 10. If the Program as you
|
||||||
|
received it, or any part of it, contains a notice stating that it is
|
||||||
|
governed by this License along with a term that is a further
|
||||||
|
restriction, you may remove that term. If a license document contains
|
||||||
|
a further restriction but permits relicensing or conveying under this
|
||||||
|
License, you may add to a covered work material governed by the terms
|
||||||
|
of that license document, provided that the further restriction does
|
||||||
|
not survive such relicensing or conveying.
|
||||||
|
|
||||||
|
If you add terms to a covered work in accord with this section, you
|
||||||
|
must place, in the relevant source files, a statement of the
|
||||||
|
additional terms that apply to those files, or a notice indicating
|
||||||
|
where to find the applicable terms.
|
||||||
|
|
||||||
|
Additional terms, permissive or non-permissive, may be stated in the
|
||||||
|
form of a separately written license, or stated as exceptions;
|
||||||
|
the above requirements apply either way.
|
||||||
|
|
||||||
|
8. Termination.
|
||||||
|
|
||||||
|
You may not propagate or modify a covered work except as expressly
|
||||||
|
provided under this License. Any attempt otherwise to propagate or
|
||||||
|
modify it is void, and will automatically terminate your rights under
|
||||||
|
this License (including any patent licenses granted under the third
|
||||||
|
paragraph of section 11).
|
||||||
|
|
||||||
|
However, if you cease all violation of this License, then your
|
||||||
|
license from a particular copyright holder is reinstated (a)
|
||||||
|
provisionally, unless and until the copyright holder explicitly and
|
||||||
|
finally terminates your license, and (b) permanently, if the copyright
|
||||||
|
holder fails to notify you of the violation by some reasonable means
|
||||||
|
prior to 60 days after the cessation.
|
||||||
|
|
||||||
|
Moreover, your license from a particular copyright holder is
|
||||||
|
reinstated permanently if the copyright holder notifies you of the
|
||||||
|
violation by some reasonable means, this is the first time you have
|
||||||
|
received notice of violation of this License (for any work) from that
|
||||||
|
copyright holder, and you cure the violation prior to 30 days after
|
||||||
|
your receipt of the notice.
|
||||||
|
|
||||||
|
Termination of your rights under this section does not terminate the
|
||||||
|
licenses of parties who have received copies or rights from you under
|
||||||
|
this License. If your rights have been terminated and not permanently
|
||||||
|
reinstated, you do not qualify to receive new licenses for the same
|
||||||
|
material under section 10.
|
||||||
|
|
||||||
|
9. Acceptance Not Required for Having Copies.
|
||||||
|
|
||||||
|
You are not required to accept this License in order to receive or
|
||||||
|
run a copy of the Program. Ancillary propagation of a covered work
|
||||||
|
occurring solely as a consequence of using peer-to-peer transmission
|
||||||
|
to receive a copy likewise does not require acceptance. However,
|
||||||
|
nothing other than this License grants you permission to propagate or
|
||||||
|
modify any covered work. These actions infringe copyright if you do
|
||||||
|
not accept this License. Therefore, by modifying or propagating a
|
||||||
|
covered work, you indicate your acceptance of this License to do so.
|
||||||
|
|
||||||
|
10. Automatic Licensing of Downstream Recipients.
|
||||||
|
|
||||||
|
Each time you convey a covered work, the recipient automatically
|
||||||
|
receives a license from the original licensors, to run, modify and
|
||||||
|
propagate that work, subject to this License. You are not responsible
|
||||||
|
for enforcing compliance by third parties with this License.
|
||||||
|
|
||||||
|
An "entity transaction" is a transaction transferring control of an
|
||||||
|
organization, or substantially all assets of one, or subdividing an
|
||||||
|
organization, or merging organizations. If propagation of a covered
|
||||||
|
work results from an entity transaction, each party to that
|
||||||
|
transaction who receives a copy of the work also receives whatever
|
||||||
|
licenses to the work the party's predecessor in interest had or could
|
||||||
|
give under the previous paragraph, plus a right to possession of the
|
||||||
|
Corresponding Source of the work from the predecessor in interest, if
|
||||||
|
the predecessor has it or can get it with reasonable efforts.
|
||||||
|
|
||||||
|
You may not impose any further restrictions on the exercise of the
|
||||||
|
rights granted or affirmed under this License. For example, you may
|
||||||
|
not impose a license fee, royalty, or other charge for exercise of
|
||||||
|
rights granted under this License, and you may not initiate litigation
|
||||||
|
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||||
|
any patent claim is infringed by making, using, selling, offering for
|
||||||
|
sale, or importing the Program or any portion of it.
|
||||||
|
|
||||||
|
11. Patents.
|
||||||
|
|
||||||
|
A "contributor" is a copyright holder who authorizes use under this
|
||||||
|
License of the Program or a work on which the Program is based. The
|
||||||
|
work thus licensed is called the contributor's "contributor version".
|
||||||
|
|
||||||
|
A contributor's "essential patent claims" are all patent claims
|
||||||
|
owned or controlled by the contributor, whether already acquired or
|
||||||
|
hereafter acquired, that would be infringed by some manner, permitted
|
||||||
|
by this License, of making, using, or selling its contributor version,
|
||||||
|
but do not include claims that would be infringed only as a
|
||||||
|
consequence of further modification of the contributor version. For
|
||||||
|
purposes of this definition, "control" includes the right to grant
|
||||||
|
patent sublicenses in a manner consistent with the requirements of
|
||||||
|
this License.
|
||||||
|
|
||||||
|
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||||
|
patent license under the contributor's essential patent claims, to
|
||||||
|
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||||
|
propagate the contents of its contributor version.
|
||||||
|
|
||||||
|
In the following three paragraphs, a "patent license" is any express
|
||||||
|
agreement or commitment, however denominated, not to enforce a patent
|
||||||
|
(such as an express permission to practice a patent or covenant not to
|
||||||
|
sue for patent infringement). To "grant" such a patent license to a
|
||||||
|
party means to make such an agreement or commitment not to enforce a
|
||||||
|
patent against the party.
|
||||||
|
|
||||||
|
If you convey a covered work, knowingly relying on a patent license,
|
||||||
|
and the Corresponding Source of the work is not available for anyone
|
||||||
|
to copy, free of charge and under the terms of this License, through a
|
||||||
|
publicly available network server or other readily accessible means,
|
||||||
|
then you must either (1) cause the Corresponding Source to be so
|
||||||
|
available, or (2) arrange to deprive yourself of the benefit of the
|
||||||
|
patent license for this particular work, or (3) arrange, in a manner
|
||||||
|
consistent with the requirements of this License, to extend the patent
|
||||||
|
license to downstream recipients. "Knowingly relying" means you have
|
||||||
|
actual knowledge that, but for the patent license, your conveying the
|
||||||
|
covered work in a country, or your recipient's use of the covered work
|
||||||
|
in a country, would infringe one or more identifiable patents in that
|
||||||
|
country that you have reason to believe are valid.
|
||||||
|
|
||||||
|
If, pursuant to or in connection with a single transaction or
|
||||||
|
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||||
|
covered work, and grant a patent license to some of the parties
|
||||||
|
receiving the covered work authorizing them to use, propagate, modify
|
||||||
|
or convey a specific copy of the covered work, then the patent license
|
||||||
|
you grant is automatically extended to all recipients of the covered
|
||||||
|
work and works based on it.
|
||||||
|
|
||||||
|
A patent license is "discriminatory" if it does not include within
|
||||||
|
the scope of its coverage, prohibits the exercise of, or is
|
||||||
|
conditioned on the non-exercise of one or more of the rights that are
|
||||||
|
specifically granted under this License. You may not convey a covered
|
||||||
|
work if you are a party to an arrangement with a third party that is
|
||||||
|
in the business of distributing software, under which you make payment
|
||||||
|
to the third party based on the extent of your activity of conveying
|
||||||
|
the work, and under which the third party grants, to any of the
|
||||||
|
parties who would receive the covered work from you, a discriminatory
|
||||||
|
patent license (a) in connection with copies of the covered work
|
||||||
|
conveyed by you (or copies made from those copies), or (b) primarily
|
||||||
|
for and in connection with specific products or compilations that
|
||||||
|
contain the covered work, unless you entered into that arrangement,
|
||||||
|
or that patent license was granted, prior to 28 March 2007.
|
||||||
|
|
||||||
|
Nothing in this License shall be construed as excluding or limiting
|
||||||
|
any implied license or other defenses to infringement that may
|
||||||
|
otherwise be available to you under applicable patent law.
|
||||||
|
|
||||||
|
12. No Surrender of Others' Freedom.
|
||||||
|
|
||||||
|
If conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot convey a
|
||||||
|
covered work so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you may
|
||||||
|
not convey it at all. For example, if you agree to terms that obligate you
|
||||||
|
to collect a royalty for further conveying from those to whom you convey
|
||||||
|
the Program, the only way you could satisfy both those terms and this
|
||||||
|
License would be to refrain entirely from conveying the Program.
|
||||||
|
|
||||||
|
13. Use with the GNU Affero General Public License.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, you have
|
||||||
|
permission to link or combine any covered work with a work licensed
|
||||||
|
under version 3 of the GNU Affero General Public License into a single
|
||||||
|
combined work, and to convey the resulting work. The terms of this
|
||||||
|
License will continue to apply to the part which is the covered work,
|
||||||
|
but the special requirements of the GNU Affero General Public License,
|
||||||
|
section 13, concerning interaction through a network will apply to the
|
||||||
|
combination as such.
|
||||||
|
|
||||||
|
14. Revised Versions of this License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions of
|
||||||
|
the GNU General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Program specifies that a certain numbered version of the GNU General
|
||||||
|
Public License "or any later version" applies to it, you have the
|
||||||
|
option of following the terms and conditions either of that numbered
|
||||||
|
version or of any later version published by the Free Software
|
||||||
|
Foundation. If the Program does not specify a version number of the
|
||||||
|
GNU General Public License, you may choose any version ever published
|
||||||
|
by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Program specifies that a proxy can decide which future
|
||||||
|
versions of the GNU General Public License can be used, that proxy's
|
||||||
|
public statement of acceptance of a version permanently authorizes you
|
||||||
|
to choose that version for the Program.
|
||||||
|
|
||||||
|
Later license versions may give you additional or different
|
||||||
|
permissions. However, no additional obligations are imposed on any
|
||||||
|
author or copyright holder as a result of your choosing to follow a
|
||||||
|
later version.
|
||||||
|
|
||||||
|
15. Disclaimer of Warranty.
|
||||||
|
|
||||||
|
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||||
|
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||||
|
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||||
|
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||||
|
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||||
|
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
16. Limitation of Liability.
|
||||||
|
|
||||||
|
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||||
|
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||||
|
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||||
|
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||||
|
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||||
|
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||||
|
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGES.
|
||||||
|
|
||||||
|
17. Interpretation of Sections 15 and 16.
|
||||||
|
|
||||||
|
If the disclaimer of warranty and limitation of liability provided
|
||||||
|
above cannot be given local legal effect according to their terms,
|
||||||
|
reviewing courts shall apply local law that most closely approximates
|
||||||
|
an absolute waiver of all civil liability in connection with the
|
||||||
|
Program, unless a warranty or assumption of liability accompanies a
|
||||||
|
copy of the Program in return for a fee.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
state the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
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/>.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program does terminal interaction, make it output a short
|
||||||
|
notice like this when it starts in an interactive mode:
|
||||||
|
|
||||||
|
<program> Copyright (C) <year> <name of author>
|
||||||
|
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, your program's commands
|
||||||
|
might be different; for a GUI interface, you would use an "about box".
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or school,
|
||||||
|
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||||
|
For more information on this, and how to apply and follow the GNU GPL, see
|
||||||
|
<http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
The GNU General Public License does not permit incorporating your program
|
||||||
|
into proprietary programs. If your program is a subroutine library, you
|
||||||
|
may consider it more useful to permit linking proprietary applications with
|
||||||
|
the library. If this is what you want to do, use the GNU Lesser General
|
||||||
|
Public License instead of this License. But first, please read
|
||||||
|
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
|
@ -0,0 +1,12 @@
|
||||||
|
General questions:
|
||||||
|
Contact the mailing list muscle@lists.musclecard.com
|
||||||
|
(you must subscribe first at http://musclecard.com/list.html)
|
||||||
|
|
||||||
|
|
||||||
|
Contract work:
|
||||||
|
|
||||||
|
For interested parties, I am available part time for contract based work
|
||||||
|
developing drivers, middleware, and applications for a variety of
|
||||||
|
platforms based upon smart cards and cryptographic tokens.
|
||||||
|
My current hardware platforms are: Linux, Solaris, BSD,
|
||||||
|
Mac OS, and HP-UX
|
|
@ -0,0 +1,370 @@
|
||||||
|
Installation Instructions
|
||||||
|
*************************
|
||||||
|
|
||||||
|
Copyright (C) 1994-1996, 1999-2002, 2004-2013 Free Software Foundation,
|
||||||
|
Inc.
|
||||||
|
|
||||||
|
Copying and distribution of this file, with or without modification,
|
||||||
|
are permitted in any medium without royalty provided the copyright
|
||||||
|
notice and this notice are preserved. This file is offered as-is,
|
||||||
|
without warranty of any kind.
|
||||||
|
|
||||||
|
Basic Installation
|
||||||
|
==================
|
||||||
|
|
||||||
|
Briefly, the shell command `./configure && make && make install'
|
||||||
|
should configure, build, and install this package. The following
|
||||||
|
more-detailed instructions are generic; see the `README' file for
|
||||||
|
instructions specific to this package. Some packages provide this
|
||||||
|
`INSTALL' file but do not implement all of the features documented
|
||||||
|
below. The lack of an optional feature in a given package is not
|
||||||
|
necessarily a bug. More recommendations for GNU packages can be found
|
||||||
|
in *note Makefile Conventions: (standards)Makefile Conventions.
|
||||||
|
|
||||||
|
The `configure' shell script attempts to guess correct values for
|
||||||
|
various system-dependent variables used during compilation. It uses
|
||||||
|
those values to create a `Makefile' in each directory of the package.
|
||||||
|
It may also create one or more `.h' files containing system-dependent
|
||||||
|
definitions. Finally, it creates a shell script `config.status' that
|
||||||
|
you can run in the future to recreate the current configuration, and a
|
||||||
|
file `config.log' containing compiler output (useful mainly for
|
||||||
|
debugging `configure').
|
||||||
|
|
||||||
|
It can also use an optional file (typically called `config.cache'
|
||||||
|
and enabled with `--cache-file=config.cache' or simply `-C') that saves
|
||||||
|
the results of its tests to speed up reconfiguring. Caching is
|
||||||
|
disabled by default to prevent problems with accidental use of stale
|
||||||
|
cache files.
|
||||||
|
|
||||||
|
If you need to do unusual things to compile the package, please try
|
||||||
|
to figure out how `configure' could check whether to do them, and mail
|
||||||
|
diffs or instructions to the address given in the `README' so they can
|
||||||
|
be considered for the next release. If you are using the cache, and at
|
||||||
|
some point `config.cache' contains results you don't want to keep, you
|
||||||
|
may remove or edit it.
|
||||||
|
|
||||||
|
The file `configure.ac' (or `configure.in') is used to create
|
||||||
|
`configure' by a program called `autoconf'. You need `configure.ac' if
|
||||||
|
you want to change it or regenerate `configure' using a newer version
|
||||||
|
of `autoconf'.
|
||||||
|
|
||||||
|
The simplest way to compile this package is:
|
||||||
|
|
||||||
|
1. `cd' to the directory containing the package's source code and type
|
||||||
|
`./configure' to configure the package for your system.
|
||||||
|
|
||||||
|
Running `configure' might take a while. While running, it prints
|
||||||
|
some messages telling which features it is checking for.
|
||||||
|
|
||||||
|
2. Type `make' to compile the package.
|
||||||
|
|
||||||
|
3. Optionally, type `make check' to run any self-tests that come with
|
||||||
|
the package, generally using the just-built uninstalled binaries.
|
||||||
|
|
||||||
|
4. Type `make install' to install the programs and any data files and
|
||||||
|
documentation. When installing into a prefix owned by root, it is
|
||||||
|
recommended that the package be configured and built as a regular
|
||||||
|
user, and only the `make install' phase executed with root
|
||||||
|
privileges.
|
||||||
|
|
||||||
|
5. Optionally, type `make installcheck' to repeat any self-tests, but
|
||||||
|
this time using the binaries in their final installed location.
|
||||||
|
This target does not install anything. Running this target as a
|
||||||
|
regular user, particularly if the prior `make install' required
|
||||||
|
root privileges, verifies that the installation completed
|
||||||
|
correctly.
|
||||||
|
|
||||||
|
6. You can remove the program binaries and object files from the
|
||||||
|
source code directory by typing `make clean'. To also remove the
|
||||||
|
files that `configure' created (so you can compile the package for
|
||||||
|
a different kind of computer), type `make distclean'. There is
|
||||||
|
also a `make maintainer-clean' target, but that is intended mainly
|
||||||
|
for the package's developers. If you use it, you may have to get
|
||||||
|
all sorts of other programs in order to regenerate files that came
|
||||||
|
with the distribution.
|
||||||
|
|
||||||
|
7. Often, you can also type `make uninstall' to remove the installed
|
||||||
|
files again. In practice, not all packages have tested that
|
||||||
|
uninstallation works correctly, even though it is required by the
|
||||||
|
GNU Coding Standards.
|
||||||
|
|
||||||
|
8. Some packages, particularly those that use Automake, provide `make
|
||||||
|
distcheck', which can by used by developers to test that all other
|
||||||
|
targets like `make install' and `make uninstall' work correctly.
|
||||||
|
This target is generally not run by end users.
|
||||||
|
|
||||||
|
Compilers and Options
|
||||||
|
=====================
|
||||||
|
|
||||||
|
Some systems require unusual options for compilation or linking that
|
||||||
|
the `configure' script does not know about. Run `./configure --help'
|
||||||
|
for details on some of the pertinent environment variables.
|
||||||
|
|
||||||
|
You can give `configure' initial values for configuration parameters
|
||||||
|
by setting variables in the command line or in the environment. Here
|
||||||
|
is an example:
|
||||||
|
|
||||||
|
./configure CC=c99 CFLAGS=-g LIBS=-lposix
|
||||||
|
|
||||||
|
*Note Defining Variables::, for more details.
|
||||||
|
|
||||||
|
Compiling For Multiple Architectures
|
||||||
|
====================================
|
||||||
|
|
||||||
|
You can compile the package for more than one kind of computer at the
|
||||||
|
same time, by placing the object files for each architecture in their
|
||||||
|
own directory. To do this, you can use GNU `make'. `cd' to the
|
||||||
|
directory where you want the object files and executables to go and run
|
||||||
|
the `configure' script. `configure' automatically checks for the
|
||||||
|
source code in the directory that `configure' is in and in `..'. This
|
||||||
|
is known as a "VPATH" build.
|
||||||
|
|
||||||
|
With a non-GNU `make', it is safer to compile the package for one
|
||||||
|
architecture at a time in the source code directory. After you have
|
||||||
|
installed the package for one architecture, use `make distclean' before
|
||||||
|
reconfiguring for another architecture.
|
||||||
|
|
||||||
|
On MacOS X 10.5 and later systems, you can create libraries and
|
||||||
|
executables that work on multiple system types--known as "fat" or
|
||||||
|
"universal" binaries--by specifying multiple `-arch' options to the
|
||||||
|
compiler but only a single `-arch' option to the preprocessor. Like
|
||||||
|
this:
|
||||||
|
|
||||||
|
./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
|
||||||
|
CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
|
||||||
|
CPP="gcc -E" CXXCPP="g++ -E"
|
||||||
|
|
||||||
|
This is not guaranteed to produce working output in all cases, you
|
||||||
|
may have to build one architecture at a time and combine the results
|
||||||
|
using the `lipo' tool if you have problems.
|
||||||
|
|
||||||
|
Installation Names
|
||||||
|
==================
|
||||||
|
|
||||||
|
By default, `make install' installs the package's commands under
|
||||||
|
`/usr/local/bin', include files under `/usr/local/include', etc. You
|
||||||
|
can specify an installation prefix other than `/usr/local' by giving
|
||||||
|
`configure' the option `--prefix=PREFIX', where PREFIX must be an
|
||||||
|
absolute file name.
|
||||||
|
|
||||||
|
You can specify separate installation prefixes for
|
||||||
|
architecture-specific files and architecture-independent files. If you
|
||||||
|
pass the option `--exec-prefix=PREFIX' to `configure', the package uses
|
||||||
|
PREFIX as the prefix for installing programs and libraries.
|
||||||
|
Documentation and other data files still use the regular prefix.
|
||||||
|
|
||||||
|
In addition, if you use an unusual directory layout you can give
|
||||||
|
options like `--bindir=DIR' to specify different values for particular
|
||||||
|
kinds of files. Run `configure --help' for a list of the directories
|
||||||
|
you can set and what kinds of files go in them. In general, the
|
||||||
|
default for these options is expressed in terms of `${prefix}', so that
|
||||||
|
specifying just `--prefix' will affect all of the other directory
|
||||||
|
specifications that were not explicitly provided.
|
||||||
|
|
||||||
|
The most portable way to affect installation locations is to pass the
|
||||||
|
correct locations to `configure'; however, many packages provide one or
|
||||||
|
both of the following shortcuts of passing variable assignments to the
|
||||||
|
`make install' command line to change installation locations without
|
||||||
|
having to reconfigure or recompile.
|
||||||
|
|
||||||
|
The first method involves providing an override variable for each
|
||||||
|
affected directory. For example, `make install
|
||||||
|
prefix=/alternate/directory' will choose an alternate location for all
|
||||||
|
directory configuration variables that were expressed in terms of
|
||||||
|
`${prefix}'. Any directories that were specified during `configure',
|
||||||
|
but not in terms of `${prefix}', must each be overridden at install
|
||||||
|
time for the entire installation to be relocated. The approach of
|
||||||
|
makefile variable overrides for each directory variable is required by
|
||||||
|
the GNU Coding Standards, and ideally causes no recompilation.
|
||||||
|
However, some platforms have known limitations with the semantics of
|
||||||
|
shared libraries that end up requiring recompilation when using this
|
||||||
|
method, particularly noticeable in packages that use GNU Libtool.
|
||||||
|
|
||||||
|
The second method involves providing the `DESTDIR' variable. For
|
||||||
|
example, `make install DESTDIR=/alternate/directory' will prepend
|
||||||
|
`/alternate/directory' before all installation names. The approach of
|
||||||
|
`DESTDIR' overrides is not required by the GNU Coding Standards, and
|
||||||
|
does not work on platforms that have drive letters. On the other hand,
|
||||||
|
it does better at avoiding recompilation issues, and works well even
|
||||||
|
when some directory options were not specified in terms of `${prefix}'
|
||||||
|
at `configure' time.
|
||||||
|
|
||||||
|
Optional Features
|
||||||
|
=================
|
||||||
|
|
||||||
|
If the package supports it, you can cause programs to be installed
|
||||||
|
with an extra prefix or suffix on their names by giving `configure' the
|
||||||
|
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
|
||||||
|
|
||||||
|
Some packages pay attention to `--enable-FEATURE' options to
|
||||||
|
`configure', where FEATURE indicates an optional part of the package.
|
||||||
|
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
|
||||||
|
is something like `gnu-as' or `x' (for the X Window System). The
|
||||||
|
`README' should mention any `--enable-' and `--with-' options that the
|
||||||
|
package recognizes.
|
||||||
|
|
||||||
|
For packages that use the X Window System, `configure' can usually
|
||||||
|
find the X include and library files automatically, but if it doesn't,
|
||||||
|
you can use the `configure' options `--x-includes=DIR' and
|
||||||
|
`--x-libraries=DIR' to specify their locations.
|
||||||
|
|
||||||
|
Some packages offer the ability to configure how verbose the
|
||||||
|
execution of `make' will be. For these packages, running `./configure
|
||||||
|
--enable-silent-rules' sets the default to minimal output, which can be
|
||||||
|
overridden with `make V=1'; while running `./configure
|
||||||
|
--disable-silent-rules' sets the default to verbose, which can be
|
||||||
|
overridden with `make V=0'.
|
||||||
|
|
||||||
|
Particular systems
|
||||||
|
==================
|
||||||
|
|
||||||
|
On HP-UX, the default C compiler is not ANSI C compatible. If GNU
|
||||||
|
CC is not installed, it is recommended to use the following options in
|
||||||
|
order to use an ANSI C compiler:
|
||||||
|
|
||||||
|
./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
|
||||||
|
|
||||||
|
and if that doesn't work, install pre-built binaries of GCC for HP-UX.
|
||||||
|
|
||||||
|
HP-UX `make' updates targets which have the same time stamps as
|
||||||
|
their prerequisites, which makes it generally unusable when shipped
|
||||||
|
generated files such as `configure' are involved. Use GNU `make'
|
||||||
|
instead.
|
||||||
|
|
||||||
|
On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
|
||||||
|
parse its `<wchar.h>' header file. The option `-nodtk' can be used as
|
||||||
|
a workaround. If GNU CC is not installed, it is therefore recommended
|
||||||
|
to try
|
||||||
|
|
||||||
|
./configure CC="cc"
|
||||||
|
|
||||||
|
and if that doesn't work, try
|
||||||
|
|
||||||
|
./configure CC="cc -nodtk"
|
||||||
|
|
||||||
|
On Solaris, don't put `/usr/ucb' early in your `PATH'. This
|
||||||
|
directory contains several dysfunctional programs; working variants of
|
||||||
|
these programs are available in `/usr/bin'. So, if you need `/usr/ucb'
|
||||||
|
in your `PATH', put it _after_ `/usr/bin'.
|
||||||
|
|
||||||
|
On Haiku, software installed for all users goes in `/boot/common',
|
||||||
|
not `/usr/local'. It is recommended to use the following options:
|
||||||
|
|
||||||
|
./configure --prefix=/boot/common
|
||||||
|
|
||||||
|
Specifying the System Type
|
||||||
|
==========================
|
||||||
|
|
||||||
|
There may be some features `configure' cannot figure out
|
||||||
|
automatically, but needs to determine by the type of machine the package
|
||||||
|
will run on. Usually, assuming the package is built to be run on the
|
||||||
|
_same_ architectures, `configure' can figure that out, but if it prints
|
||||||
|
a message saying it cannot guess the machine type, give it the
|
||||||
|
`--build=TYPE' option. TYPE can either be a short name for the system
|
||||||
|
type, such as `sun4', or a canonical name which has the form:
|
||||||
|
|
||||||
|
CPU-COMPANY-SYSTEM
|
||||||
|
|
||||||
|
where SYSTEM can have one of these forms:
|
||||||
|
|
||||||
|
OS
|
||||||
|
KERNEL-OS
|
||||||
|
|
||||||
|
See the file `config.sub' for the possible values of each field. If
|
||||||
|
`config.sub' isn't included in this package, then this package doesn't
|
||||||
|
need to know the machine type.
|
||||||
|
|
||||||
|
If you are _building_ compiler tools for cross-compiling, you should
|
||||||
|
use the option `--target=TYPE' to select the type of system they will
|
||||||
|
produce code for.
|
||||||
|
|
||||||
|
If you want to _use_ a cross compiler, that generates code for a
|
||||||
|
platform different from the build platform, you should specify the
|
||||||
|
"host" platform (i.e., that on which the generated programs will
|
||||||
|
eventually be run) with `--host=TYPE'.
|
||||||
|
|
||||||
|
Sharing Defaults
|
||||||
|
================
|
||||||
|
|
||||||
|
If you want to set default values for `configure' scripts to share,
|
||||||
|
you can create a site shell script called `config.site' that gives
|
||||||
|
default values for variables like `CC', `cache_file', and `prefix'.
|
||||||
|
`configure' looks for `PREFIX/share/config.site' if it exists, then
|
||||||
|
`PREFIX/etc/config.site' if it exists. Or, you can set the
|
||||||
|
`CONFIG_SITE' environment variable to the location of the site script.
|
||||||
|
A warning: not all `configure' scripts look for a site script.
|
||||||
|
|
||||||
|
Defining Variables
|
||||||
|
==================
|
||||||
|
|
||||||
|
Variables not defined in a site shell script can be set in the
|
||||||
|
environment passed to `configure'. However, some packages may run
|
||||||
|
configure again during the build, and the customized values of these
|
||||||
|
variables may be lost. In order to avoid this problem, you should set
|
||||||
|
them in the `configure' command line, using `VAR=value'. For example:
|
||||||
|
|
||||||
|
./configure CC=/usr/local2/bin/gcc
|
||||||
|
|
||||||
|
causes the specified `gcc' to be used as the C compiler (unless it is
|
||||||
|
overridden in the site shell script).
|
||||||
|
|
||||||
|
Unfortunately, this technique does not work for `CONFIG_SHELL' due to
|
||||||
|
an Autoconf limitation. Until the limitation is lifted, you can use
|
||||||
|
this workaround:
|
||||||
|
|
||||||
|
CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash
|
||||||
|
|
||||||
|
`configure' Invocation
|
||||||
|
======================
|
||||||
|
|
||||||
|
`configure' recognizes the following options to control how it
|
||||||
|
operates.
|
||||||
|
|
||||||
|
`--help'
|
||||||
|
`-h'
|
||||||
|
Print a summary of all of the options to `configure', and exit.
|
||||||
|
|
||||||
|
`--help=short'
|
||||||
|
`--help=recursive'
|
||||||
|
Print a summary of the options unique to this package's
|
||||||
|
`configure', and exit. The `short' variant lists options used
|
||||||
|
only in the top level, while the `recursive' variant lists options
|
||||||
|
also present in any nested packages.
|
||||||
|
|
||||||
|
`--version'
|
||||||
|
`-V'
|
||||||
|
Print the version of Autoconf used to generate the `configure'
|
||||||
|
script, and exit.
|
||||||
|
|
||||||
|
`--cache-file=FILE'
|
||||||
|
Enable the cache: use and save the results of the tests in FILE,
|
||||||
|
traditionally `config.cache'. FILE defaults to `/dev/null' to
|
||||||
|
disable caching.
|
||||||
|
|
||||||
|
`--config-cache'
|
||||||
|
`-C'
|
||||||
|
Alias for `--cache-file=config.cache'.
|
||||||
|
|
||||||
|
`--quiet'
|
||||||
|
`--silent'
|
||||||
|
`-q'
|
||||||
|
Do not print messages saying which checks are being made. To
|
||||||
|
suppress all normal output, redirect it to `/dev/null' (any error
|
||||||
|
messages will still be shown).
|
||||||
|
|
||||||
|
`--srcdir=DIR'
|
||||||
|
Look for the package's source code in directory DIR. Usually
|
||||||
|
`configure' can determine that directory automatically.
|
||||||
|
|
||||||
|
`--prefix=DIR'
|
||||||
|
Use DIR as the installation prefix. *note Installation Names::
|
||||||
|
for more details, including other options available for fine-tuning
|
||||||
|
the installation locations.
|
||||||
|
|
||||||
|
`--no-create'
|
||||||
|
`-n'
|
||||||
|
Run the configure checks, but stop before creating any output
|
||||||
|
files.
|
||||||
|
|
||||||
|
`configure' also accepts some other, not widely useful, options. Run
|
||||||
|
`configure --help' for more details.
|
|
@ -0,0 +1,24 @@
|
||||||
|
SUBDIRS = src etc doc
|
||||||
|
|
||||||
|
fix-rights:
|
||||||
|
$(MAKE) -C src $@
|
||||||
|
|
||||||
|
ACLOCAL_AMFLAGS = -I m4
|
||||||
|
|
||||||
|
DISTCHECK_CONFIGURE_FLAGS = \
|
||||||
|
--with-systemdsystemunitdir=$$dc_install_base/$(systemdsystemunitdir)
|
||||||
|
|
||||||
|
EXTRA_DIST = \
|
||||||
|
GPL-3.0.txt \
|
||||||
|
bootstrap \
|
||||||
|
ChangeLog.git \
|
||||||
|
DRIVERS SECURITY \
|
||||||
|
HELP \
|
||||||
|
m4/ax_pthread.m4 \
|
||||||
|
m4/as-ac-expand.m4
|
||||||
|
|
||||||
|
DISTCLEANFILES = ChangeLog.git
|
||||||
|
|
||||||
|
ChangeLog.git:
|
||||||
|
git log --stat --decorate=short > $@
|
||||||
|
|
|
@ -0,0 +1,868 @@
|
||||||
|
# Makefile.in generated by automake 1.15 from Makefile.am.
|
||||||
|
# @configure_input@
|
||||||
|
|
||||||
|
# Copyright (C) 1994-2014 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
# This Makefile.in is free software; the Free Software Foundation
|
||||||
|
# gives unlimited permission to copy and/or distribute it,
|
||||||
|
# with or without modifications, as long as this notice is preserved.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||||
|
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||||
|
# PARTICULAR PURPOSE.
|
||||||
|
|
||||||
|
@SET_MAKE@
|
||||||
|
VPATH = @srcdir@
|
||||||
|
am__is_gnu_make = { \
|
||||||
|
if test -z '$(MAKELEVEL)'; then \
|
||||||
|
false; \
|
||||||
|
elif test -n '$(MAKE_HOST)'; then \
|
||||||
|
true; \
|
||||||
|
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
|
||||||
|
true; \
|
||||||
|
else \
|
||||||
|
false; \
|
||||||
|
fi; \
|
||||||
|
}
|
||||||
|
am__make_running_with_option = \
|
||||||
|
case $${target_option-} in \
|
||||||
|
?) ;; \
|
||||||
|
*) echo "am__make_running_with_option: internal error: invalid" \
|
||||||
|
"target option '$${target_option-}' specified" >&2; \
|
||||||
|
exit 1;; \
|
||||||
|
esac; \
|
||||||
|
has_opt=no; \
|
||||||
|
sane_makeflags=$$MAKEFLAGS; \
|
||||||
|
if $(am__is_gnu_make); then \
|
||||||
|
sane_makeflags=$$MFLAGS; \
|
||||||
|
else \
|
||||||
|
case $$MAKEFLAGS in \
|
||||||
|
*\\[\ \ ]*) \
|
||||||
|
bs=\\; \
|
||||||
|
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
|
||||||
|
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
|
||||||
|
esac; \
|
||||||
|
fi; \
|
||||||
|
skip_next=no; \
|
||||||
|
strip_trailopt () \
|
||||||
|
{ \
|
||||||
|
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
|
||||||
|
}; \
|
||||||
|
for flg in $$sane_makeflags; do \
|
||||||
|
test $$skip_next = yes && { skip_next=no; continue; }; \
|
||||||
|
case $$flg in \
|
||||||
|
*=*|--*) continue;; \
|
||||||
|
-*I) strip_trailopt 'I'; skip_next=yes;; \
|
||||||
|
-*I?*) strip_trailopt 'I';; \
|
||||||
|
-*O) strip_trailopt 'O'; skip_next=yes;; \
|
||||||
|
-*O?*) strip_trailopt 'O';; \
|
||||||
|
-*l) strip_trailopt 'l'; skip_next=yes;; \
|
||||||
|
-*l?*) strip_trailopt 'l';; \
|
||||||
|
-[dEDm]) skip_next=yes;; \
|
||||||
|
-[JT]) skip_next=yes;; \
|
||||||
|
esac; \
|
||||||
|
case $$flg in \
|
||||||
|
*$$target_option*) has_opt=yes; break;; \
|
||||||
|
esac; \
|
||||||
|
done; \
|
||||||
|
test $$has_opt = yes
|
||||||
|
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
|
||||||
|
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
|
||||||
|
pkgdatadir = $(datadir)/@PACKAGE@
|
||||||
|
pkgincludedir = $(includedir)/@PACKAGE@
|
||||||
|
pkglibdir = $(libdir)/@PACKAGE@
|
||||||
|
pkglibexecdir = $(libexecdir)/@PACKAGE@
|
||||||
|
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||||
|
install_sh_DATA = $(install_sh) -c -m 644
|
||||||
|
install_sh_PROGRAM = $(install_sh) -c
|
||||||
|
install_sh_SCRIPT = $(install_sh) -c
|
||||||
|
INSTALL_HEADER = $(INSTALL_DATA)
|
||||||
|
transform = $(program_transform_name)
|
||||||
|
NORMAL_INSTALL = :
|
||||||
|
PRE_INSTALL = :
|
||||||
|
POST_INSTALL = :
|
||||||
|
NORMAL_UNINSTALL = :
|
||||||
|
PRE_UNINSTALL = :
|
||||||
|
POST_UNINSTALL = :
|
||||||
|
build_triplet = @build@
|
||||||
|
host_triplet = @host@
|
||||||
|
subdir = .
|
||||||
|
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||||
|
am__aclocal_m4_deps = $(top_srcdir)/m4/as-ac-expand.m4 \
|
||||||
|
$(top_srcdir)/m4/ax_pthread.m4 $(top_srcdir)/m4/libtool.m4 \
|
||||||
|
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
|
||||||
|
$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
|
||||||
|
$(top_srcdir)/configure.ac
|
||||||
|
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||||
|
$(ACLOCAL_M4)
|
||||||
|
DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \
|
||||||
|
$(am__configure_deps) $(am__DIST_COMMON)
|
||||||
|
am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
|
||||||
|
configure.lineno config.status.lineno
|
||||||
|
mkinstalldirs = $(install_sh) -d
|
||||||
|
CONFIG_HEADER = config.h
|
||||||
|
CONFIG_CLEAN_FILES = src/PCSC/pcsclite.h
|
||||||
|
CONFIG_CLEAN_VPATH_FILES =
|
||||||
|
AM_V_P = $(am__v_P_@AM_V@)
|
||||||
|
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
|
||||||
|
am__v_P_0 = false
|
||||||
|
am__v_P_1 = :
|
||||||
|
AM_V_GEN = $(am__v_GEN_@AM_V@)
|
||||||
|
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
|
||||||
|
am__v_GEN_0 = @echo " GEN " $@;
|
||||||
|
am__v_GEN_1 =
|
||||||
|
AM_V_at = $(am__v_at_@AM_V@)
|
||||||
|
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
|
||||||
|
am__v_at_0 = @
|
||||||
|
am__v_at_1 =
|
||||||
|
SOURCES =
|
||||||
|
DIST_SOURCES =
|
||||||
|
RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
|
||||||
|
ctags-recursive dvi-recursive html-recursive info-recursive \
|
||||||
|
install-data-recursive install-dvi-recursive \
|
||||||
|
install-exec-recursive install-html-recursive \
|
||||||
|
install-info-recursive install-pdf-recursive \
|
||||||
|
install-ps-recursive install-recursive installcheck-recursive \
|
||||||
|
installdirs-recursive pdf-recursive ps-recursive \
|
||||||
|
tags-recursive uninstall-recursive
|
||||||
|
am__can_run_installinfo = \
|
||||||
|
case $$AM_UPDATE_INFO_DIR in \
|
||||||
|
n|no|NO) false;; \
|
||||||
|
*) (install-info --version) >/dev/null 2>&1;; \
|
||||||
|
esac
|
||||||
|
RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
|
||||||
|
distclean-recursive maintainer-clean-recursive
|
||||||
|
am__recursive_targets = \
|
||||||
|
$(RECURSIVE_TARGETS) \
|
||||||
|
$(RECURSIVE_CLEAN_TARGETS) \
|
||||||
|
$(am__extra_recursive_targets)
|
||||||
|
AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
|
||||||
|
cscope distdir dist dist-all distcheck
|
||||||
|
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \
|
||||||
|
$(LISP)config.h.in
|
||||||
|
# Read a list of newline-separated strings from the standard input,
|
||||||
|
# and print each of them once, without duplicates. Input order is
|
||||||
|
# *not* preserved.
|
||||||
|
am__uniquify_input = $(AWK) '\
|
||||||
|
BEGIN { nonempty = 0; } \
|
||||||
|
{ items[$$0] = 1; nonempty = 1; } \
|
||||||
|
END { if (nonempty) { for (i in items) print i; }; } \
|
||||||
|
'
|
||||||
|
# Make sure the list of sources is unique. This is necessary because,
|
||||||
|
# e.g., the same source file might be shared among _SOURCES variables
|
||||||
|
# for different programs/libraries.
|
||||||
|
am__define_uniq_tagged_files = \
|
||||||
|
list='$(am__tagged_files)'; \
|
||||||
|
unique=`for i in $$list; do \
|
||||||
|
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||||
|
done | $(am__uniquify_input)`
|
||||||
|
ETAGS = etags
|
||||||
|
CTAGS = ctags
|
||||||
|
CSCOPE = cscope
|
||||||
|
DIST_SUBDIRS = $(SUBDIRS)
|
||||||
|
am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in \
|
||||||
|
$(top_srcdir)/src/PCSC/pcsclite.h.in AUTHORS COPYING ChangeLog \
|
||||||
|
INSTALL NEWS README TODO ar-lib compile config.guess \
|
||||||
|
config.sub depcomp install-sh ltmain.sh missing ylwrap
|
||||||
|
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||||
|
distdir = $(PACKAGE)-$(VERSION)
|
||||||
|
top_distdir = $(distdir)
|
||||||
|
am__remove_distdir = \
|
||||||
|
if test -d "$(distdir)"; then \
|
||||||
|
find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \
|
||||||
|
&& rm -rf "$(distdir)" \
|
||||||
|
|| { sleep 5 && rm -rf "$(distdir)"; }; \
|
||||||
|
else :; fi
|
||||||
|
am__post_remove_distdir = $(am__remove_distdir)
|
||||||
|
am__relativize = \
|
||||||
|
dir0=`pwd`; \
|
||||||
|
sed_first='s,^\([^/]*\)/.*$$,\1,'; \
|
||||||
|
sed_rest='s,^[^/]*/*,,'; \
|
||||||
|
sed_last='s,^.*/\([^/]*\)$$,\1,'; \
|
||||||
|
sed_butlast='s,/*[^/]*$$,,'; \
|
||||||
|
while test -n "$$dir1"; do \
|
||||||
|
first=`echo "$$dir1" | sed -e "$$sed_first"`; \
|
||||||
|
if test "$$first" != "."; then \
|
||||||
|
if test "$$first" = ".."; then \
|
||||||
|
dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
|
||||||
|
dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
|
||||||
|
else \
|
||||||
|
first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
|
||||||
|
if test "$$first2" = "$$first"; then \
|
||||||
|
dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
|
||||||
|
else \
|
||||||
|
dir2="../$$dir2"; \
|
||||||
|
fi; \
|
||||||
|
dir0="$$dir0"/"$$first"; \
|
||||||
|
fi; \
|
||||||
|
fi; \
|
||||||
|
dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
|
||||||
|
done; \
|
||||||
|
reldir="$$dir2"
|
||||||
|
GZIP_ENV = --best
|
||||||
|
DIST_ARCHIVES = $(distdir).tar.bz2
|
||||||
|
DIST_TARGETS = dist-bzip2
|
||||||
|
distuninstallcheck_listfiles = find . -type f -print
|
||||||
|
am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \
|
||||||
|
| sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$'
|
||||||
|
distcleancheck_listfiles = find . -type f -print
|
||||||
|
ACLOCAL = @ACLOCAL@
|
||||||
|
ALLOCA = @ALLOCA@
|
||||||
|
AMTAR = @AMTAR@
|
||||||
|
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
|
||||||
|
AR = @AR@
|
||||||
|
AUTOCONF = @AUTOCONF@
|
||||||
|
AUTOHEADER = @AUTOHEADER@
|
||||||
|
AUTOMAKE = @AUTOMAKE@
|
||||||
|
AWK = @AWK@
|
||||||
|
CC = @CC@
|
||||||
|
CCDEPMODE = @CCDEPMODE@
|
||||||
|
CFLAGS = @CFLAGS@
|
||||||
|
COREFOUNDATION = @COREFOUNDATION@
|
||||||
|
CPP = @CPP@
|
||||||
|
CPPFLAGS = @CPPFLAGS@
|
||||||
|
CYGPATH_W = @CYGPATH_W@
|
||||||
|
DEFS = @DEFS@
|
||||||
|
DEPDIR = @DEPDIR@
|
||||||
|
DLLTOOL = @DLLTOOL@
|
||||||
|
DSYMUTIL = @DSYMUTIL@
|
||||||
|
DUMPBIN = @DUMPBIN@
|
||||||
|
ECHO_C = @ECHO_C@
|
||||||
|
ECHO_N = @ECHO_N@
|
||||||
|
ECHO_T = @ECHO_T@
|
||||||
|
EGREP = @EGREP@
|
||||||
|
EXEEXT = @EXEEXT@
|
||||||
|
FGREP = @FGREP@
|
||||||
|
GREP = @GREP@
|
||||||
|
INSTALL = @INSTALL@
|
||||||
|
INSTALL_DATA = @INSTALL_DATA@
|
||||||
|
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||||
|
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||||
|
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||||
|
IOKIT = @IOKIT@
|
||||||
|
LD = @LD@
|
||||||
|
LDFLAGS = @LDFLAGS@
|
||||||
|
LEX = @LEX@
|
||||||
|
LEXLIB = @LEXLIB@
|
||||||
|
LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
|
||||||
|
LIBOBJS = @LIBOBJS@
|
||||||
|
LIBS = @LIBS@
|
||||||
|
LIBTOOL = @LIBTOOL@
|
||||||
|
LIBUDEV_CFLAGS = @LIBUDEV_CFLAGS@
|
||||||
|
LIBUDEV_LIBS = @LIBUDEV_LIBS@
|
||||||
|
LIBUSBCONFIG = @LIBUSBCONFIG@
|
||||||
|
LIBUSB_CFLAGS = @LIBUSB_CFLAGS@
|
||||||
|
LIBUSB_LIBS = @LIBUSB_LIBS@
|
||||||
|
LIPO = @LIPO@
|
||||||
|
LN_S = @LN_S@
|
||||||
|
LTLIBOBJS = @LTLIBOBJS@
|
||||||
|
LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
|
||||||
|
MAINT = @MAINT@
|
||||||
|
MAKEINFO = @MAKEINFO@
|
||||||
|
MANIFEST_TOOL = @MANIFEST_TOOL@
|
||||||
|
MKDIR_P = @MKDIR_P@
|
||||||
|
NM = @NM@
|
||||||
|
NMEDIT = @NMEDIT@
|
||||||
|
OBJDUMP = @OBJDUMP@
|
||||||
|
OBJEXT = @OBJEXT@
|
||||||
|
OTOOL = @OTOOL@
|
||||||
|
OTOOL64 = @OTOOL64@
|
||||||
|
PACKAGE = @PACKAGE@
|
||||||
|
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||||
|
PACKAGE_NAME = @PACKAGE_NAME@
|
||||||
|
PACKAGE_STRING = @PACKAGE_STRING@
|
||||||
|
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||||
|
PACKAGE_URL = @PACKAGE_URL@
|
||||||
|
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||||
|
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||||
|
PCSCLITE_CONFIG_DIR = @PCSCLITE_CONFIG_DIR@
|
||||||
|
PKG_CONFIG = @PKG_CONFIG@
|
||||||
|
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
|
||||||
|
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
|
||||||
|
POLICY_DIR = @POLICY_DIR@
|
||||||
|
POLKIT_CFLAGS = @POLKIT_CFLAGS@
|
||||||
|
POLKIT_LIBS = @POLKIT_LIBS@
|
||||||
|
PTHREAD_CC = @PTHREAD_CC@
|
||||||
|
PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
|
||||||
|
PTHREAD_LIBS = @PTHREAD_LIBS@
|
||||||
|
RANLIB = @RANLIB@
|
||||||
|
SED = @SED@
|
||||||
|
SET_MAKE = @SET_MAKE@
|
||||||
|
SHELL = @SHELL@
|
||||||
|
STRIP = @STRIP@
|
||||||
|
SYMBOL_VISIBILITY = @SYMBOL_VISIBILITY@
|
||||||
|
VERSION = @VERSION@
|
||||||
|
abs_builddir = @abs_builddir@
|
||||||
|
abs_srcdir = @abs_srcdir@
|
||||||
|
abs_top_builddir = @abs_top_builddir@
|
||||||
|
abs_top_srcdir = @abs_top_srcdir@
|
||||||
|
ac_ct_AR = @ac_ct_AR@
|
||||||
|
ac_ct_CC = @ac_ct_CC@
|
||||||
|
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
|
||||||
|
am__include = @am__include@
|
||||||
|
am__leading_dot = @am__leading_dot@
|
||||||
|
am__quote = @am__quote@
|
||||||
|
am__tar = @am__tar@
|
||||||
|
am__untar = @am__untar@
|
||||||
|
ax_pthread_config = @ax_pthread_config@
|
||||||
|
bindir = @bindir@
|
||||||
|
build = @build@
|
||||||
|
build_alias = @build_alias@
|
||||||
|
build_cpu = @build_cpu@
|
||||||
|
build_os = @build_os@
|
||||||
|
build_vendor = @build_vendor@
|
||||||
|
builddir = @builddir@
|
||||||
|
confdir_exp = @confdir_exp@
|
||||||
|
datadir = @datadir@
|
||||||
|
datarootdir = @datarootdir@
|
||||||
|
docdir = @docdir@
|
||||||
|
dvidir = @dvidir@
|
||||||
|
exec_prefix = @exec_prefix@
|
||||||
|
host = @host@
|
||||||
|
host_alias = @host_alias@
|
||||||
|
host_cpu = @host_cpu@
|
||||||
|
host_os = @host_os@
|
||||||
|
host_to_ccid_16 = @host_to_ccid_16@
|
||||||
|
host_to_ccid_32 = @host_to_ccid_32@
|
||||||
|
host_vendor = @host_vendor@
|
||||||
|
htmldir = @htmldir@
|
||||||
|
includedir = @includedir@
|
||||||
|
infodir = @infodir@
|
||||||
|
install_sh = @install_sh@
|
||||||
|
ipcdir = @ipcdir@
|
||||||
|
libdir = @libdir@
|
||||||
|
libexecdir = @libexecdir@
|
||||||
|
localedir = @localedir@
|
||||||
|
localstatedir = @localstatedir@
|
||||||
|
localstatedir_exp = @localstatedir_exp@
|
||||||
|
mandir = @mandir@
|
||||||
|
mkdir_p = @mkdir_p@
|
||||||
|
oldincludedir = @oldincludedir@
|
||||||
|
pdfdir = @pdfdir@
|
||||||
|
prefix = @prefix@
|
||||||
|
program_transform_name = @program_transform_name@
|
||||||
|
psdir = @psdir@
|
||||||
|
runstatedir = @runstatedir@
|
||||||
|
sbindir = @sbindir@
|
||||||
|
sbindir_exp = @sbindir_exp@
|
||||||
|
serialconfdir = @serialconfdir@
|
||||||
|
sharedstatedir = @sharedstatedir@
|
||||||
|
srcdir = @srcdir@
|
||||||
|
sysconfdir = @sysconfdir@
|
||||||
|
systemdsystemunitdir = @systemdsystemunitdir@
|
||||||
|
target_alias = @target_alias@
|
||||||
|
top_build_prefix = @top_build_prefix@
|
||||||
|
top_builddir = @top_builddir@
|
||||||
|
top_srcdir = @top_srcdir@
|
||||||
|
usbdropdir = @usbdropdir@
|
||||||
|
usbdropdir_exp = @usbdropdir_exp@
|
||||||
|
SUBDIRS = src etc doc
|
||||||
|
ACLOCAL_AMFLAGS = -I m4
|
||||||
|
DISTCHECK_CONFIGURE_FLAGS = \
|
||||||
|
--with-systemdsystemunitdir=$$dc_install_base/$(systemdsystemunitdir)
|
||||||
|
|
||||||
|
EXTRA_DIST = \
|
||||||
|
GPL-3.0.txt \
|
||||||
|
bootstrap \
|
||||||
|
ChangeLog.git \
|
||||||
|
DRIVERS SECURITY \
|
||||||
|
HELP \
|
||||||
|
m4/ax_pthread.m4 \
|
||||||
|
m4/as-ac-expand.m4
|
||||||
|
|
||||||
|
DISTCLEANFILES = ChangeLog.git
|
||||||
|
all: config.h
|
||||||
|
$(MAKE) $(AM_MAKEFLAGS) all-recursive
|
||||||
|
|
||||||
|
.SUFFIXES:
|
||||||
|
am--refresh: Makefile
|
||||||
|
@:
|
||||||
|
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
|
||||||
|
@for dep in $?; do \
|
||||||
|
case '$(am__configure_deps)' in \
|
||||||
|
*$$dep*) \
|
||||||
|
echo ' cd $(srcdir) && $(AUTOMAKE) --gnu'; \
|
||||||
|
$(am__cd) $(srcdir) && $(AUTOMAKE) --gnu \
|
||||||
|
&& exit 0; \
|
||||||
|
exit 1;; \
|
||||||
|
esac; \
|
||||||
|
done; \
|
||||||
|
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \
|
||||||
|
$(am__cd) $(top_srcdir) && \
|
||||||
|
$(AUTOMAKE) --gnu Makefile
|
||||||
|
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||||
|
@case '$?' in \
|
||||||
|
*config.status*) \
|
||||||
|
echo ' $(SHELL) ./config.status'; \
|
||||||
|
$(SHELL) ./config.status;; \
|
||||||
|
*) \
|
||||||
|
echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
|
||||||
|
cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
|
||||||
|
esac;
|
||||||
|
|
||||||
|
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||||
|
$(SHELL) ./config.status --recheck
|
||||||
|
|
||||||
|
$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
|
||||||
|
$(am__cd) $(srcdir) && $(AUTOCONF)
|
||||||
|
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
|
||||||
|
$(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
|
||||||
|
$(am__aclocal_m4_deps):
|
||||||
|
|
||||||
|
config.h: stamp-h1
|
||||||
|
@test -f $@ || rm -f stamp-h1
|
||||||
|
@test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1
|
||||||
|
|
||||||
|
stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
|
||||||
|
@rm -f stamp-h1
|
||||||
|
cd $(top_builddir) && $(SHELL) ./config.status config.h
|
||||||
|
$(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
|
||||||
|
($(am__cd) $(top_srcdir) && $(AUTOHEADER))
|
||||||
|
rm -f stamp-h1
|
||||||
|
touch $@
|
||||||
|
|
||||||
|
distclean-hdr:
|
||||||
|
-rm -f config.h stamp-h1
|
||||||
|
src/PCSC/pcsclite.h: $(top_builddir)/config.status $(top_srcdir)/src/PCSC/pcsclite.h.in
|
||||||
|
cd $(top_builddir) && $(SHELL) ./config.status $@
|
||||||
|
|
||||||
|
mostlyclean-libtool:
|
||||||
|
-rm -f *.lo
|
||||||
|
|
||||||
|
clean-libtool:
|
||||||
|
-rm -rf .libs _libs
|
||||||
|
|
||||||
|
distclean-libtool:
|
||||||
|
-rm -f libtool config.lt
|
||||||
|
|
||||||
|
# This directory's subdirectories are mostly independent; you can cd
|
||||||
|
# into them and run 'make' without going through this Makefile.
|
||||||
|
# To change the values of 'make' variables: instead of editing Makefiles,
|
||||||
|
# (1) if the variable is set in 'config.status', edit 'config.status'
|
||||||
|
# (which will cause the Makefiles to be regenerated when you run 'make');
|
||||||
|
# (2) otherwise, pass the desired values on the 'make' command line.
|
||||||
|
$(am__recursive_targets):
|
||||||
|
@fail=; \
|
||||||
|
if $(am__make_keepgoing); then \
|
||||||
|
failcom='fail=yes'; \
|
||||||
|
else \
|
||||||
|
failcom='exit 1'; \
|
||||||
|
fi; \
|
||||||
|
dot_seen=no; \
|
||||||
|
target=`echo $@ | sed s/-recursive//`; \
|
||||||
|
case "$@" in \
|
||||||
|
distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
|
||||||
|
*) list='$(SUBDIRS)' ;; \
|
||||||
|
esac; \
|
||||||
|
for subdir in $$list; do \
|
||||||
|
echo "Making $$target in $$subdir"; \
|
||||||
|
if test "$$subdir" = "."; then \
|
||||||
|
dot_seen=yes; \
|
||||||
|
local_target="$$target-am"; \
|
||||||
|
else \
|
||||||
|
local_target="$$target"; \
|
||||||
|
fi; \
|
||||||
|
($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|
||||||
|
|| eval $$failcom; \
|
||||||
|
done; \
|
||||||
|
if test "$$dot_seen" = "no"; then \
|
||||||
|
$(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
|
||||||
|
fi; test -z "$$fail"
|
||||||
|
|
||||||
|
ID: $(am__tagged_files)
|
||||||
|
$(am__define_uniq_tagged_files); mkid -fID $$unique
|
||||||
|
tags: tags-recursive
|
||||||
|
TAGS: tags
|
||||||
|
|
||||||
|
tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
|
||||||
|
set x; \
|
||||||
|
here=`pwd`; \
|
||||||
|
if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
|
||||||
|
include_option=--etags-include; \
|
||||||
|
empty_fix=.; \
|
||||||
|
else \
|
||||||
|
include_option=--include; \
|
||||||
|
empty_fix=; \
|
||||||
|
fi; \
|
||||||
|
list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||||
|
if test "$$subdir" = .; then :; else \
|
||||||
|
test ! -f $$subdir/TAGS || \
|
||||||
|
set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
|
||||||
|
fi; \
|
||||||
|
done; \
|
||||||
|
$(am__define_uniq_tagged_files); \
|
||||||
|
shift; \
|
||||||
|
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
|
||||||
|
test -n "$$unique" || unique=$$empty_fix; \
|
||||||
|
if test $$# -gt 0; then \
|
||||||
|
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||||
|
"$$@" $$unique; \
|
||||||
|
else \
|
||||||
|
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||||
|
$$unique; \
|
||||||
|
fi; \
|
||||||
|
fi
|
||||||
|
ctags: ctags-recursive
|
||||||
|
|
||||||
|
CTAGS: ctags
|
||||||
|
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
|
||||||
|
$(am__define_uniq_tagged_files); \
|
||||||
|
test -z "$(CTAGS_ARGS)$$unique" \
|
||||||
|
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
|
||||||
|
$$unique
|
||||||
|
|
||||||
|
GTAGS:
|
||||||
|
here=`$(am__cd) $(top_builddir) && pwd` \
|
||||||
|
&& $(am__cd) $(top_srcdir) \
|
||||||
|
&& gtags -i $(GTAGS_ARGS) "$$here"
|
||||||
|
cscope: cscope.files
|
||||||
|
test ! -s cscope.files \
|
||||||
|
|| $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS)
|
||||||
|
clean-cscope:
|
||||||
|
-rm -f cscope.files
|
||||||
|
cscope.files: clean-cscope cscopelist
|
||||||
|
cscopelist: cscopelist-recursive
|
||||||
|
|
||||||
|
cscopelist-am: $(am__tagged_files)
|
||||||
|
list='$(am__tagged_files)'; \
|
||||||
|
case "$(srcdir)" in \
|
||||||
|
[\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
|
||||||
|
*) sdir=$(subdir)/$(srcdir) ;; \
|
||||||
|
esac; \
|
||||||
|
for i in $$list; do \
|
||||||
|
if test -f "$$i"; then \
|
||||||
|
echo "$(subdir)/$$i"; \
|
||||||
|
else \
|
||||||
|
echo "$$sdir/$$i"; \
|
||||||
|
fi; \
|
||||||
|
done >> $(top_builddir)/cscope.files
|
||||||
|
|
||||||
|
distclean-tags:
|
||||||
|
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||||
|
-rm -f cscope.out cscope.in.out cscope.po.out cscope.files
|
||||||
|
|
||||||
|
distdir: $(DISTFILES)
|
||||||
|
$(am__remove_distdir)
|
||||||
|
test -d "$(distdir)" || mkdir "$(distdir)"
|
||||||
|
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||||
|
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||||
|
list='$(DISTFILES)'; \
|
||||||
|
dist_files=`for file in $$list; do echo $$file; done | \
|
||||||
|
sed -e "s|^$$srcdirstrip/||;t" \
|
||||||
|
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
|
||||||
|
case $$dist_files in \
|
||||||
|
*/*) $(MKDIR_P) `echo "$$dist_files" | \
|
||||||
|
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
|
||||||
|
sort -u` ;; \
|
||||||
|
esac; \
|
||||||
|
for file in $$dist_files; do \
|
||||||
|
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||||
|
if test -d $$d/$$file; then \
|
||||||
|
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||||
|
if test -d "$(distdir)/$$file"; then \
|
||||||
|
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||||
|
fi; \
|
||||||
|
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||||
|
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
|
||||||
|
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||||
|
fi; \
|
||||||
|
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
|
||||||
|
else \
|
||||||
|
test -f "$(distdir)/$$file" \
|
||||||
|
|| cp -p $$d/$$file "$(distdir)/$$file" \
|
||||||
|
|| exit 1; \
|
||||||
|
fi; \
|
||||||
|
done
|
||||||
|
@list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
|
||||||
|
if test "$$subdir" = .; then :; else \
|
||||||
|
$(am__make_dryrun) \
|
||||||
|
|| test -d "$(distdir)/$$subdir" \
|
||||||
|
|| $(MKDIR_P) "$(distdir)/$$subdir" \
|
||||||
|
|| exit 1; \
|
||||||
|
dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
|
||||||
|
$(am__relativize); \
|
||||||
|
new_distdir=$$reldir; \
|
||||||
|
dir1=$$subdir; dir2="$(top_distdir)"; \
|
||||||
|
$(am__relativize); \
|
||||||
|
new_top_distdir=$$reldir; \
|
||||||
|
echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
|
||||||
|
echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
|
||||||
|
($(am__cd) $$subdir && \
|
||||||
|
$(MAKE) $(AM_MAKEFLAGS) \
|
||||||
|
top_distdir="$$new_top_distdir" \
|
||||||
|
distdir="$$new_distdir" \
|
||||||
|
am__remove_distdir=: \
|
||||||
|
am__skip_length_check=: \
|
||||||
|
am__skip_mode_fix=: \
|
||||||
|
distdir) \
|
||||||
|
|| exit 1; \
|
||||||
|
fi; \
|
||||||
|
done
|
||||||
|
-test -n "$(am__skip_mode_fix)" \
|
||||||
|
|| find "$(distdir)" -type d ! -perm -755 \
|
||||||
|
-exec chmod u+rwx,go+rx {} \; -o \
|
||||||
|
! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
|
||||||
|
! -type d ! -perm -400 -exec chmod a+r {} \; -o \
|
||||||
|
! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
|
||||||
|
|| chmod -R a+r "$(distdir)"
|
||||||
|
dist-gzip: distdir
|
||||||
|
tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
|
||||||
|
$(am__post_remove_distdir)
|
||||||
|
dist-bzip2: distdir
|
||||||
|
tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2
|
||||||
|
$(am__post_remove_distdir)
|
||||||
|
|
||||||
|
dist-lzip: distdir
|
||||||
|
tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz
|
||||||
|
$(am__post_remove_distdir)
|
||||||
|
|
||||||
|
dist-xz: distdir
|
||||||
|
tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz
|
||||||
|
$(am__post_remove_distdir)
|
||||||
|
|
||||||
|
dist-tarZ: distdir
|
||||||
|
@echo WARNING: "Support for distribution archives compressed with" \
|
||||||
|
"legacy program 'compress' is deprecated." >&2
|
||||||
|
@echo WARNING: "It will be removed altogether in Automake 2.0" >&2
|
||||||
|
tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
|
||||||
|
$(am__post_remove_distdir)
|
||||||
|
|
||||||
|
dist-shar: distdir
|
||||||
|
@echo WARNING: "Support for shar distribution archives is" \
|
||||||
|
"deprecated." >&2
|
||||||
|
@echo WARNING: "It will be removed altogether in Automake 2.0" >&2
|
||||||
|
shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
|
||||||
|
$(am__post_remove_distdir)
|
||||||
|
|
||||||
|
dist-zip: distdir
|
||||||
|
-rm -f $(distdir).zip
|
||||||
|
zip -rq $(distdir).zip $(distdir)
|
||||||
|
$(am__post_remove_distdir)
|
||||||
|
|
||||||
|
dist dist-all:
|
||||||
|
$(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:'
|
||||||
|
$(am__post_remove_distdir)
|
||||||
|
|
||||||
|
# This target untars the dist file and tries a VPATH configuration. Then
|
||||||
|
# it guarantees that the distribution is self-contained by making another
|
||||||
|
# tarfile.
|
||||||
|
distcheck: dist
|
||||||
|
case '$(DIST_ARCHIVES)' in \
|
||||||
|
*.tar.gz*) \
|
||||||
|
GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\
|
||||||
|
*.tar.bz2*) \
|
||||||
|
bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\
|
||||||
|
*.tar.lz*) \
|
||||||
|
lzip -dc $(distdir).tar.lz | $(am__untar) ;;\
|
||||||
|
*.tar.xz*) \
|
||||||
|
xz -dc $(distdir).tar.xz | $(am__untar) ;;\
|
||||||
|
*.tar.Z*) \
|
||||||
|
uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
|
||||||
|
*.shar.gz*) \
|
||||||
|
GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\
|
||||||
|
*.zip*) \
|
||||||
|
unzip $(distdir).zip ;;\
|
||||||
|
esac
|
||||||
|
chmod -R a-w $(distdir)
|
||||||
|
chmod u+w $(distdir)
|
||||||
|
mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst
|
||||||
|
chmod a-w $(distdir)
|
||||||
|
test -d $(distdir)/_build || exit 0; \
|
||||||
|
dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
|
||||||
|
&& dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
|
||||||
|
&& am__cwd=`pwd` \
|
||||||
|
&& $(am__cd) $(distdir)/_build/sub \
|
||||||
|
&& ../../configure \
|
||||||
|
$(AM_DISTCHECK_CONFIGURE_FLAGS) \
|
||||||
|
$(DISTCHECK_CONFIGURE_FLAGS) \
|
||||||
|
--srcdir=../.. --prefix="$$dc_install_base" \
|
||||||
|
&& $(MAKE) $(AM_MAKEFLAGS) \
|
||||||
|
&& $(MAKE) $(AM_MAKEFLAGS) dvi \
|
||||||
|
&& $(MAKE) $(AM_MAKEFLAGS) check \
|
||||||
|
&& $(MAKE) $(AM_MAKEFLAGS) install \
|
||||||
|
&& $(MAKE) $(AM_MAKEFLAGS) installcheck \
|
||||||
|
&& $(MAKE) $(AM_MAKEFLAGS) uninstall \
|
||||||
|
&& $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
|
||||||
|
distuninstallcheck \
|
||||||
|
&& chmod -R a-w "$$dc_install_base" \
|
||||||
|
&& ({ \
|
||||||
|
(cd ../.. && umask 077 && mkdir "$$dc_destdir") \
|
||||||
|
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
|
||||||
|
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
|
||||||
|
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
|
||||||
|
distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
|
||||||
|
} || { rm -rf "$$dc_destdir"; exit 1; }) \
|
||||||
|
&& rm -rf "$$dc_destdir" \
|
||||||
|
&& $(MAKE) $(AM_MAKEFLAGS) dist \
|
||||||
|
&& rm -rf $(DIST_ARCHIVES) \
|
||||||
|
&& $(MAKE) $(AM_MAKEFLAGS) distcleancheck \
|
||||||
|
&& cd "$$am__cwd" \
|
||||||
|
|| exit 1
|
||||||
|
$(am__post_remove_distdir)
|
||||||
|
@(echo "$(distdir) archives ready for distribution: "; \
|
||||||
|
list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
|
||||||
|
sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x'
|
||||||
|
distuninstallcheck:
|
||||||
|
@test -n '$(distuninstallcheck_dir)' || { \
|
||||||
|
echo 'ERROR: trying to run $@ with an empty' \
|
||||||
|
'$$(distuninstallcheck_dir)' >&2; \
|
||||||
|
exit 1; \
|
||||||
|
}; \
|
||||||
|
$(am__cd) '$(distuninstallcheck_dir)' || { \
|
||||||
|
echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \
|
||||||
|
exit 1; \
|
||||||
|
}; \
|
||||||
|
test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \
|
||||||
|
|| { echo "ERROR: files left after uninstall:" ; \
|
||||||
|
if test -n "$(DESTDIR)"; then \
|
||||||
|
echo " (check DESTDIR support)"; \
|
||||||
|
fi ; \
|
||||||
|
$(distuninstallcheck_listfiles) ; \
|
||||||
|
exit 1; } >&2
|
||||||
|
distcleancheck: distclean
|
||||||
|
@if test '$(srcdir)' = . ; then \
|
||||||
|
echo "ERROR: distcleancheck can only run from a VPATH build" ; \
|
||||||
|
exit 1 ; \
|
||||||
|
fi
|
||||||
|
@test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
|
||||||
|
|| { echo "ERROR: files left in build directory after distclean:" ; \
|
||||||
|
$(distcleancheck_listfiles) ; \
|
||||||
|
exit 1; } >&2
|
||||||
|
check-am: all-am
|
||||||
|
check: check-recursive
|
||||||
|
all-am: Makefile config.h
|
||||||
|
installdirs: installdirs-recursive
|
||||||
|
installdirs-am:
|
||||||
|
install: install-recursive
|
||||||
|
install-exec: install-exec-recursive
|
||||||
|
install-data: install-data-recursive
|
||||||
|
uninstall: uninstall-recursive
|
||||||
|
|
||||||
|
install-am: all-am
|
||||||
|
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||||
|
|
||||||
|
installcheck: installcheck-recursive
|
||||||
|
install-strip:
|
||||||
|
if test -z '$(STRIP)'; then \
|
||||||
|
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||||
|
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||||
|
install; \
|
||||||
|
else \
|
||||||
|
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||||
|
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||||
|
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
|
||||||
|
fi
|
||||||
|
mostlyclean-generic:
|
||||||
|
|
||||||
|
clean-generic:
|
||||||
|
|
||||||
|
distclean-generic:
|
||||||
|
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||||
|
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
|
||||||
|
-test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
|
||||||
|
|
||||||
|
maintainer-clean-generic:
|
||||||
|
@echo "This command is intended for maintainers to use"
|
||||||
|
@echo "it deletes files that may require special tools to rebuild."
|
||||||
|
clean: clean-recursive
|
||||||
|
|
||||||
|
clean-am: clean-generic clean-libtool mostlyclean-am
|
||||||
|
|
||||||
|
distclean: distclean-recursive
|
||||||
|
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
|
||||||
|
-rm -f Makefile
|
||||||
|
distclean-am: clean-am distclean-generic distclean-hdr \
|
||||||
|
distclean-libtool distclean-tags
|
||||||
|
|
||||||
|
dvi: dvi-recursive
|
||||||
|
|
||||||
|
dvi-am:
|
||||||
|
|
||||||
|
html: html-recursive
|
||||||
|
|
||||||
|
html-am:
|
||||||
|
|
||||||
|
info: info-recursive
|
||||||
|
|
||||||
|
info-am:
|
||||||
|
|
||||||
|
install-data-am:
|
||||||
|
|
||||||
|
install-dvi: install-dvi-recursive
|
||||||
|
|
||||||
|
install-dvi-am:
|
||||||
|
|
||||||
|
install-exec-am:
|
||||||
|
|
||||||
|
install-html: install-html-recursive
|
||||||
|
|
||||||
|
install-html-am:
|
||||||
|
|
||||||
|
install-info: install-info-recursive
|
||||||
|
|
||||||
|
install-info-am:
|
||||||
|
|
||||||
|
install-man:
|
||||||
|
|
||||||
|
install-pdf: install-pdf-recursive
|
||||||
|
|
||||||
|
install-pdf-am:
|
||||||
|
|
||||||
|
install-ps: install-ps-recursive
|
||||||
|
|
||||||
|
install-ps-am:
|
||||||
|
|
||||||
|
installcheck-am:
|
||||||
|
|
||||||
|
maintainer-clean: maintainer-clean-recursive
|
||||||
|
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
|
||||||
|
-rm -rf $(top_srcdir)/autom4te.cache
|
||||||
|
-rm -f Makefile
|
||||||
|
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||||
|
|
||||||
|
mostlyclean: mostlyclean-recursive
|
||||||
|
|
||||||
|
mostlyclean-am: mostlyclean-generic mostlyclean-libtool
|
||||||
|
|
||||||
|
pdf: pdf-recursive
|
||||||
|
|
||||||
|
pdf-am:
|
||||||
|
|
||||||
|
ps: ps-recursive
|
||||||
|
|
||||||
|
ps-am:
|
||||||
|
|
||||||
|
uninstall-am:
|
||||||
|
|
||||||
|
.MAKE: $(am__recursive_targets) all install-am install-strip
|
||||||
|
|
||||||
|
.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \
|
||||||
|
am--refresh check check-am clean clean-cscope clean-generic \
|
||||||
|
clean-libtool cscope cscopelist-am ctags ctags-am dist \
|
||||||
|
dist-all dist-bzip2 dist-gzip dist-lzip dist-shar dist-tarZ \
|
||||||
|
dist-xz dist-zip distcheck distclean distclean-generic \
|
||||||
|
distclean-hdr distclean-libtool distclean-tags distcleancheck \
|
||||||
|
distdir distuninstallcheck dvi dvi-am html html-am info \
|
||||||
|
info-am install install-am install-data install-data-am \
|
||||||
|
install-dvi install-dvi-am install-exec install-exec-am \
|
||||||
|
install-html install-html-am install-info install-info-am \
|
||||||
|
install-man install-pdf install-pdf-am install-ps \
|
||||||
|
install-ps-am install-strip installcheck installcheck-am \
|
||||||
|
installdirs installdirs-am maintainer-clean \
|
||||||
|
maintainer-clean-generic mostlyclean mostlyclean-generic \
|
||||||
|
mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \
|
||||||
|
uninstall-am
|
||||||
|
|
||||||
|
.PRECIOUS: Makefile
|
||||||
|
|
||||||
|
|
||||||
|
fix-rights:
|
||||||
|
$(MAKE) -C src $@
|
||||||
|
|
||||||
|
ChangeLog.git:
|
||||||
|
git log --stat --decorate=short > $@
|
||||||
|
|
||||||
|
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||||
|
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||||
|
.NOEXPORT:
|
|
@ -0,0 +1,114 @@
|
||||||
|
Title : PCSC Lite
|
||||||
|
Authors : David Corcoran, Ludovic Rousseau
|
||||||
|
Version : 1.2.9-beta10
|
||||||
|
License : See file COPYING
|
||||||
|
Document: docs/pcsc-lite.pdf
|
||||||
|
docs/ifdhandler-3.pdf
|
||||||
|
Requires: A C compiler
|
||||||
|
Make, linker tools
|
||||||
|
Lex (Lexical Analyzer).
|
||||||
|
|
||||||
|
Tested Platforms:
|
||||||
|
Linux 2.4 (Redhat 7.1, Suse 7.1/7.2, Debian 3.0)
|
||||||
|
Mac OS X 10.2, 10.3
|
||||||
|
FreeBSD, NetBSD, OpenBSD
|
||||||
|
Solaris 8 / 9
|
||||||
|
Tru64 UNIX 5.1B
|
||||||
|
AIX 4.3, 5.2
|
||||||
|
HP-UX 11
|
||||||
|
|
||||||
|
Welcome to PCSC Lite. The purpose of PCSC Lite is to
|
||||||
|
provide a Windows(R) SCard interface in a very small form factor for
|
||||||
|
communicating to smart cards and readers. PCSC Lite can be compiled
|
||||||
|
directly to a desired reader driver or can be used to dynamically
|
||||||
|
allocate/deallocate reader drivers at runtime (default).
|
||||||
|
|
||||||
|
PCSC Lite uses the same winscard API as used under Windows(R).
|
||||||
|
|
||||||
|
For security aware persons please read the SECURITY file on possible
|
||||||
|
vulnerabilites to pcsclite, how you can fix some, and how some will
|
||||||
|
be fixed.
|
||||||
|
|
||||||
|
For information on how to install driver please read the DRIVERS file.
|
||||||
|
|
||||||
|
Memory cards are supported through MCT specifications which is an APDU
|
||||||
|
like manner sent normally through the SCardTransmit() function. This
|
||||||
|
functionality is done in the driver.
|
||||||
|
|
||||||
|
INSTALLATION:
|
||||||
|
|
||||||
|
Installation is simple. Type ./configure and then make and make install.
|
||||||
|
Options:
|
||||||
|
|
||||||
|
./configure
|
||||||
|
|
||||||
|
--enable-libusb Enable USB libusb support
|
||||||
|
(on Linux, *BSD, etc.).
|
||||||
|
--enable-usbdropdir=DIR directory containing USB drivers
|
||||||
|
(default /usr/local/pcsc/drivers)
|
||||||
|
--disable-musclecarddebug Disable MuscleCard debugging messages
|
||||||
|
--enable-debugatr Enable ATR parsing debug output
|
||||||
|
--enable-scf use SCF for reader support
|
||||||
|
--prefix=location Install to <location>
|
||||||
|
--enable-confdir=DIR Use DIR as the configuration directory
|
||||||
|
(/etc by default)
|
||||||
|
--enable-runpid=FILE Store the daemon pid in file FILE
|
||||||
|
--enable-ipcdir=DIR directory containing IPC files
|
||||||
|
(default /var/run)
|
||||||
|
|
||||||
|
|
||||||
|
By running pcscd under a priveledged account you can link to
|
||||||
|
libpcsclite.so and it will act as a client to the pcscd allowing multiple
|
||||||
|
applications to be run under non-priveledged accounts.
|
||||||
|
|
||||||
|
Then type make install to copy etc/reader.conf to
|
||||||
|
/etc/reader.conf and the libraries to /usr/local/lib. If you choose
|
||||||
|
not to have your reader.conf in /etc then use --enable-confdir=DIR
|
||||||
|
|
||||||
|
You must be root to do make install in the default locations.
|
||||||
|
|
||||||
|
Be sure to edit the /etc/reader.conf file to fit your needs and make sure
|
||||||
|
your IFD Handler driver is located in the path specified as LIBRARYPATH
|
||||||
|
in reader.conf. If you are using a reader with multiple smart card slots
|
||||||
|
all you have to do is define a different FRIENDLYNAME in the reader.conf
|
||||||
|
for each reader. Both will have the same information otherwise.
|
||||||
|
|
||||||
|
There is an config file generator in the utils directory. It is called
|
||||||
|
installifd. You may use this to generate the /etc/reader.conf file.
|
||||||
|
|
||||||
|
USB users shall not use /etc/reader.conf. pcscd will give
|
||||||
|
a warning that the file does not exist or contain anything useful.
|
||||||
|
|
||||||
|
There is a test program with this package:
|
||||||
|
|
||||||
|
testpcsc: Linked to libpcsclite. Must run /usr/local/pcsc/bin/pcscd
|
||||||
|
and then ./testpcsc. pcscd must be run as root or a hardware
|
||||||
|
priveledged user. ./testpcsc can be run under any account.
|
||||||
|
|
||||||
|
LIBUSB SUPPORT:
|
||||||
|
Versions after 1.2.0 support libusb. Available on GNU/Linux and *BSD.
|
||||||
|
|
||||||
|
If you do not have libusb (or do not want to use it) on your system you
|
||||||
|
should use --disable-libusb. If you use --disable-libusb under Linux the
|
||||||
|
old USB code will be used instead.
|
||||||
|
|
||||||
|
In order to use dynamic driver loading, you need to supply a directory
|
||||||
|
called "XXXX.bundle" in the usb dropdir directory (--enable-usbdropdir=PATH).
|
||||||
|
Here, the string "XXXX" stands for an arbitrary driver name, like in
|
||||||
|
"ifd-GemPC430.bundle". An example .bundle-directory can be found in the
|
||||||
|
source distribution of the ifd-gempc driver
|
||||||
|
(http://ludovic.rousseau.free.fr/softwares/ifd-GemPC/)
|
||||||
|
|
||||||
|
SOLARIS:
|
||||||
|
Solaris PC/SC applications must link with -lsocket since
|
||||||
|
the libraries are not statically linked.
|
||||||
|
|
||||||
|
QUESTIONS:
|
||||||
|
|
||||||
|
The API documentation is provided in PDF format under the docs
|
||||||
|
directory. For questions, please email me at:
|
||||||
|
<David Corcoran> corcoran@musclecard.com
|
||||||
|
|
||||||
|
On some plateforms (GNU/Linux on mips and mipsel, FreeBSD and possibly
|
||||||
|
other *BSD suystems) you must use:
|
||||||
|
$ ./configure LDFLAGS="-lpthread"
|
|
@ -0,0 +1,16 @@
|
||||||
|
SECURITY
|
||||||
|
|
||||||
|
This file discusses security related issues with pcsc-lite and how to
|
||||||
|
handle them.
|
||||||
|
|
||||||
|
Sometimes it is dangerous to run daemons under a root account. If there is
|
||||||
|
a chance to exploit a buffer overflow you can protect sensitive information
|
||||||
|
by running it under a different account. It might be useful to create another
|
||||||
|
user with hardware priveledges and run pcscd as that user. Be sure this user
|
||||||
|
can manipulate the server sockets.
|
||||||
|
|
||||||
|
|
||||||
|
Application suggestions:
|
||||||
|
|
||||||
|
Make sure you Disconnect when you are not using the reader. Also be sure to
|
||||||
|
ReleaseContext before exiting your program.
|
|
@ -0,0 +1,11 @@
|
||||||
|
- include Apple patches and improvements (if possible/needed)
|
||||||
|
|
||||||
|
- allow to have pcscd and libpcsclite on two different machines.
|
||||||
|
That would be needed to support remote PAM login.
|
||||||
|
Maybe use unix2tcp (http://dizzy.roedu.net/unix2tcp/)
|
||||||
|
|
||||||
|
- manage power suspend/resume (in a laptop for example) and coordinate
|
||||||
|
with the driver (when/if possible)
|
||||||
|
|
||||||
|
|
||||||
|
April 2011
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,270 @@
|
||||||
|
#! /bin/sh
|
||||||
|
# Wrapper for Microsoft lib.exe
|
||||||
|
|
||||||
|
me=ar-lib
|
||||||
|
scriptversion=2012-03-01.08; # UTC
|
||||||
|
|
||||||
|
# Copyright (C) 2010-2013 Free Software Foundation, Inc.
|
||||||
|
# Written by Peter Rosin <peda@lysator.liu.se>.
|
||||||
|
#
|
||||||
|
# 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 2, 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/>.
|
||||||
|
|
||||||
|
# As a special exception to the GNU General Public License, if you
|
||||||
|
# distribute this file as part of a program that contains a
|
||||||
|
# configuration script generated by Autoconf, you may include it under
|
||||||
|
# the same distribution terms that you use for the rest of that program.
|
||||||
|
|
||||||
|
# This file is maintained in Automake, please report
|
||||||
|
# bugs to <bug-automake@gnu.org> or send patches to
|
||||||
|
# <automake-patches@gnu.org>.
|
||||||
|
|
||||||
|
|
||||||
|
# func_error message
|
||||||
|
func_error ()
|
||||||
|
{
|
||||||
|
echo "$me: $1" 1>&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
file_conv=
|
||||||
|
|
||||||
|
# func_file_conv build_file
|
||||||
|
# Convert a $build file to $host form and store it in $file
|
||||||
|
# Currently only supports Windows hosts.
|
||||||
|
func_file_conv ()
|
||||||
|
{
|
||||||
|
file=$1
|
||||||
|
case $file in
|
||||||
|
/ | /[!/]*) # absolute file, and not a UNC file
|
||||||
|
if test -z "$file_conv"; then
|
||||||
|
# lazily determine how to convert abs files
|
||||||
|
case `uname -s` in
|
||||||
|
MINGW*)
|
||||||
|
file_conv=mingw
|
||||||
|
;;
|
||||||
|
CYGWIN*)
|
||||||
|
file_conv=cygwin
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
file_conv=wine
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
case $file_conv in
|
||||||
|
mingw)
|
||||||
|
file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
|
||||||
|
;;
|
||||||
|
cygwin)
|
||||||
|
file=`cygpath -m "$file" || echo "$file"`
|
||||||
|
;;
|
||||||
|
wine)
|
||||||
|
file=`winepath -w "$file" || echo "$file"`
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# func_at_file at_file operation archive
|
||||||
|
# Iterate over all members in AT_FILE performing OPERATION on ARCHIVE
|
||||||
|
# for each of them.
|
||||||
|
# When interpreting the content of the @FILE, do NOT use func_file_conv,
|
||||||
|
# since the user would need to supply preconverted file names to
|
||||||
|
# binutils ar, at least for MinGW.
|
||||||
|
func_at_file ()
|
||||||
|
{
|
||||||
|
operation=$2
|
||||||
|
archive=$3
|
||||||
|
at_file_contents=`cat "$1"`
|
||||||
|
eval set x "$at_file_contents"
|
||||||
|
shift
|
||||||
|
|
||||||
|
for member
|
||||||
|
do
|
||||||
|
$AR -NOLOGO $operation:"$member" "$archive" || exit $?
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
case $1 in
|
||||||
|
'')
|
||||||
|
func_error "no command. Try '$0 --help' for more information."
|
||||||
|
;;
|
||||||
|
-h | --h*)
|
||||||
|
cat <<EOF
|
||||||
|
Usage: $me [--help] [--version] PROGRAM ACTION ARCHIVE [MEMBER...]
|
||||||
|
|
||||||
|
Members may be specified in a file named with @FILE.
|
||||||
|
EOF
|
||||||
|
exit $?
|
||||||
|
;;
|
||||||
|
-v | --v*)
|
||||||
|
echo "$me, version $scriptversion"
|
||||||
|
exit $?
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if test $# -lt 3; then
|
||||||
|
func_error "you must specify a program, an action and an archive"
|
||||||
|
fi
|
||||||
|
|
||||||
|
AR=$1
|
||||||
|
shift
|
||||||
|
while :
|
||||||
|
do
|
||||||
|
if test $# -lt 2; then
|
||||||
|
func_error "you must specify a program, an action and an archive"
|
||||||
|
fi
|
||||||
|
case $1 in
|
||||||
|
-lib | -LIB \
|
||||||
|
| -ltcg | -LTCG \
|
||||||
|
| -machine* | -MACHINE* \
|
||||||
|
| -subsystem* | -SUBSYSTEM* \
|
||||||
|
| -verbose | -VERBOSE \
|
||||||
|
| -wx* | -WX* )
|
||||||
|
AR="$AR $1"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
action=$1
|
||||||
|
shift
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
orig_archive=$1
|
||||||
|
shift
|
||||||
|
func_file_conv "$orig_archive"
|
||||||
|
archive=$file
|
||||||
|
|
||||||
|
# strip leading dash in $action
|
||||||
|
action=${action#-}
|
||||||
|
|
||||||
|
delete=
|
||||||
|
extract=
|
||||||
|
list=
|
||||||
|
quick=
|
||||||
|
replace=
|
||||||
|
index=
|
||||||
|
create=
|
||||||
|
|
||||||
|
while test -n "$action"
|
||||||
|
do
|
||||||
|
case $action in
|
||||||
|
d*) delete=yes ;;
|
||||||
|
x*) extract=yes ;;
|
||||||
|
t*) list=yes ;;
|
||||||
|
q*) quick=yes ;;
|
||||||
|
r*) replace=yes ;;
|
||||||
|
s*) index=yes ;;
|
||||||
|
S*) ;; # the index is always updated implicitly
|
||||||
|
c*) create=yes ;;
|
||||||
|
u*) ;; # TODO: don't ignore the update modifier
|
||||||
|
v*) ;; # TODO: don't ignore the verbose modifier
|
||||||
|
*)
|
||||||
|
func_error "unknown action specified"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
action=${action#?}
|
||||||
|
done
|
||||||
|
|
||||||
|
case $delete$extract$list$quick$replace,$index in
|
||||||
|
yes,* | ,yes)
|
||||||
|
;;
|
||||||
|
yesyes*)
|
||||||
|
func_error "more than one action specified"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
func_error "no action specified"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if test -n "$delete"; then
|
||||||
|
if test ! -f "$orig_archive"; then
|
||||||
|
func_error "archive not found"
|
||||||
|
fi
|
||||||
|
for member
|
||||||
|
do
|
||||||
|
case $1 in
|
||||||
|
@*)
|
||||||
|
func_at_file "${1#@}" -REMOVE "$archive"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
func_file_conv "$1"
|
||||||
|
$AR -NOLOGO -REMOVE:"$file" "$archive" || exit $?
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
elif test -n "$extract"; then
|
||||||
|
if test ! -f "$orig_archive"; then
|
||||||
|
func_error "archive not found"
|
||||||
|
fi
|
||||||
|
if test $# -gt 0; then
|
||||||
|
for member
|
||||||
|
do
|
||||||
|
case $1 in
|
||||||
|
@*)
|
||||||
|
func_at_file "${1#@}" -EXTRACT "$archive"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
func_file_conv "$1"
|
||||||
|
$AR -NOLOGO -EXTRACT:"$file" "$archive" || exit $?
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
else
|
||||||
|
$AR -NOLOGO -LIST "$archive" | sed -e 's/\\/\\\\/g' | while read member
|
||||||
|
do
|
||||||
|
$AR -NOLOGO -EXTRACT:"$member" "$archive" || exit $?
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
elif test -n "$quick$replace"; then
|
||||||
|
if test ! -f "$orig_archive"; then
|
||||||
|
if test -z "$create"; then
|
||||||
|
echo "$me: creating $orig_archive"
|
||||||
|
fi
|
||||||
|
orig_archive=
|
||||||
|
else
|
||||||
|
orig_archive=$archive
|
||||||
|
fi
|
||||||
|
|
||||||
|
for member
|
||||||
|
do
|
||||||
|
case $1 in
|
||||||
|
@*)
|
||||||
|
func_file_conv "${1#@}"
|
||||||
|
set x "$@" "@$file"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
func_file_conv "$1"
|
||||||
|
set x "$@" "$file"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
if test -n "$orig_archive"; then
|
||||||
|
$AR -NOLOGO -OUT:"$archive" "$orig_archive" "$@" || exit $?
|
||||||
|
else
|
||||||
|
$AR -NOLOGO -OUT:"$archive" "$@" || exit $?
|
||||||
|
fi
|
||||||
|
|
||||||
|
elif test -n "$list"; then
|
||||||
|
if test ! -f "$orig_archive"; then
|
||||||
|
func_error "archive not found"
|
||||||
|
fi
|
||||||
|
$AR -NOLOGO -LIST "$archive" || exit $?
|
||||||
|
fi
|
|
@ -0,0 +1,16 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# I use
|
||||||
|
# - autoconf (GNU Autoconf) 2.64
|
||||||
|
# - automake (GNU automake) 1.11
|
||||||
|
# - libtool (GNU libtool) 2.2.6
|
||||||
|
|
||||||
|
set -e
|
||||||
|
set -x
|
||||||
|
if test -f Makefile; then
|
||||||
|
make distclean
|
||||||
|
fi
|
||||||
|
rm -rf *.cache *.m4 config.guess config.log \
|
||||||
|
config.status config.sub depcomp ltmain.sh
|
||||||
|
#(cat m4/*.m4 > acinclude.m4 2> /dev/null)
|
||||||
|
autoreconf --verbose --install
|
|
@ -0,0 +1,347 @@
|
||||||
|
#! /bin/sh
|
||||||
|
# Wrapper for compilers which do not understand '-c -o'.
|
||||||
|
|
||||||
|
scriptversion=2012-10-14.11; # UTC
|
||||||
|
|
||||||
|
# Copyright (C) 1999-2013 Free Software Foundation, Inc.
|
||||||
|
# Written by Tom Tromey <tromey@cygnus.com>.
|
||||||
|
#
|
||||||
|
# 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 2, 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/>.
|
||||||
|
|
||||||
|
# As a special exception to the GNU General Public License, if you
|
||||||
|
# distribute this file as part of a program that contains a
|
||||||
|
# configuration script generated by Autoconf, you may include it under
|
||||||
|
# the same distribution terms that you use for the rest of that program.
|
||||||
|
|
||||||
|
# This file is maintained in Automake, please report
|
||||||
|
# bugs to <bug-automake@gnu.org> or send patches to
|
||||||
|
# <automake-patches@gnu.org>.
|
||||||
|
|
||||||
|
nl='
|
||||||
|
'
|
||||||
|
|
||||||
|
# We need space, tab and new line, in precisely that order. Quoting is
|
||||||
|
# there to prevent tools from complaining about whitespace usage.
|
||||||
|
IFS=" "" $nl"
|
||||||
|
|
||||||
|
file_conv=
|
||||||
|
|
||||||
|
# func_file_conv build_file lazy
|
||||||
|
# Convert a $build file to $host form and store it in $file
|
||||||
|
# Currently only supports Windows hosts. If the determined conversion
|
||||||
|
# type is listed in (the comma separated) LAZY, no conversion will
|
||||||
|
# take place.
|
||||||
|
func_file_conv ()
|
||||||
|
{
|
||||||
|
file=$1
|
||||||
|
case $file in
|
||||||
|
/ | /[!/]*) # absolute file, and not a UNC file
|
||||||
|
if test -z "$file_conv"; then
|
||||||
|
# lazily determine how to convert abs files
|
||||||
|
case `uname -s` in
|
||||||
|
MINGW*)
|
||||||
|
file_conv=mingw
|
||||||
|
;;
|
||||||
|
CYGWIN*)
|
||||||
|
file_conv=cygwin
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
file_conv=wine
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
case $file_conv/,$2, in
|
||||||
|
*,$file_conv,*)
|
||||||
|
;;
|
||||||
|
mingw/*)
|
||||||
|
file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
|
||||||
|
;;
|
||||||
|
cygwin/*)
|
||||||
|
file=`cygpath -m "$file" || echo "$file"`
|
||||||
|
;;
|
||||||
|
wine/*)
|
||||||
|
file=`winepath -w "$file" || echo "$file"`
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# func_cl_dashL linkdir
|
||||||
|
# Make cl look for libraries in LINKDIR
|
||||||
|
func_cl_dashL ()
|
||||||
|
{
|
||||||
|
func_file_conv "$1"
|
||||||
|
if test -z "$lib_path"; then
|
||||||
|
lib_path=$file
|
||||||
|
else
|
||||||
|
lib_path="$lib_path;$file"
|
||||||
|
fi
|
||||||
|
linker_opts="$linker_opts -LIBPATH:$file"
|
||||||
|
}
|
||||||
|
|
||||||
|
# func_cl_dashl library
|
||||||
|
# Do a library search-path lookup for cl
|
||||||
|
func_cl_dashl ()
|
||||||
|
{
|
||||||
|
lib=$1
|
||||||
|
found=no
|
||||||
|
save_IFS=$IFS
|
||||||
|
IFS=';'
|
||||||
|
for dir in $lib_path $LIB
|
||||||
|
do
|
||||||
|
IFS=$save_IFS
|
||||||
|
if $shared && test -f "$dir/$lib.dll.lib"; then
|
||||||
|
found=yes
|
||||||
|
lib=$dir/$lib.dll.lib
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
if test -f "$dir/$lib.lib"; then
|
||||||
|
found=yes
|
||||||
|
lib=$dir/$lib.lib
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
if test -f "$dir/lib$lib.a"; then
|
||||||
|
found=yes
|
||||||
|
lib=$dir/lib$lib.a
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
IFS=$save_IFS
|
||||||
|
|
||||||
|
if test "$found" != yes; then
|
||||||
|
lib=$lib.lib
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# func_cl_wrapper cl arg...
|
||||||
|
# Adjust compile command to suit cl
|
||||||
|
func_cl_wrapper ()
|
||||||
|
{
|
||||||
|
# Assume a capable shell
|
||||||
|
lib_path=
|
||||||
|
shared=:
|
||||||
|
linker_opts=
|
||||||
|
for arg
|
||||||
|
do
|
||||||
|
if test -n "$eat"; then
|
||||||
|
eat=
|
||||||
|
else
|
||||||
|
case $1 in
|
||||||
|
-o)
|
||||||
|
# configure might choose to run compile as 'compile cc -o foo foo.c'.
|
||||||
|
eat=1
|
||||||
|
case $2 in
|
||||||
|
*.o | *.[oO][bB][jJ])
|
||||||
|
func_file_conv "$2"
|
||||||
|
set x "$@" -Fo"$file"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
func_file_conv "$2"
|
||||||
|
set x "$@" -Fe"$file"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
-I)
|
||||||
|
eat=1
|
||||||
|
func_file_conv "$2" mingw
|
||||||
|
set x "$@" -I"$file"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-I*)
|
||||||
|
func_file_conv "${1#-I}" mingw
|
||||||
|
set x "$@" -I"$file"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-l)
|
||||||
|
eat=1
|
||||||
|
func_cl_dashl "$2"
|
||||||
|
set x "$@" "$lib"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-l*)
|
||||||
|
func_cl_dashl "${1#-l}"
|
||||||
|
set x "$@" "$lib"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-L)
|
||||||
|
eat=1
|
||||||
|
func_cl_dashL "$2"
|
||||||
|
;;
|
||||||
|
-L*)
|
||||||
|
func_cl_dashL "${1#-L}"
|
||||||
|
;;
|
||||||
|
-static)
|
||||||
|
shared=false
|
||||||
|
;;
|
||||||
|
-Wl,*)
|
||||||
|
arg=${1#-Wl,}
|
||||||
|
save_ifs="$IFS"; IFS=','
|
||||||
|
for flag in $arg; do
|
||||||
|
IFS="$save_ifs"
|
||||||
|
linker_opts="$linker_opts $flag"
|
||||||
|
done
|
||||||
|
IFS="$save_ifs"
|
||||||
|
;;
|
||||||
|
-Xlinker)
|
||||||
|
eat=1
|
||||||
|
linker_opts="$linker_opts $2"
|
||||||
|
;;
|
||||||
|
-*)
|
||||||
|
set x "$@" "$1"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*.cc | *.CC | *.cxx | *.CXX | *.[cC]++)
|
||||||
|
func_file_conv "$1"
|
||||||
|
set x "$@" -Tp"$file"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO])
|
||||||
|
func_file_conv "$1" mingw
|
||||||
|
set x "$@" "$file"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
set x "$@" "$1"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
if test -n "$linker_opts"; then
|
||||||
|
linker_opts="-link$linker_opts"
|
||||||
|
fi
|
||||||
|
exec "$@" $linker_opts
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
eat=
|
||||||
|
|
||||||
|
case $1 in
|
||||||
|
'')
|
||||||
|
echo "$0: No command. Try '$0 --help' for more information." 1>&2
|
||||||
|
exit 1;
|
||||||
|
;;
|
||||||
|
-h | --h*)
|
||||||
|
cat <<\EOF
|
||||||
|
Usage: compile [--help] [--version] PROGRAM [ARGS]
|
||||||
|
|
||||||
|
Wrapper for compilers which do not understand '-c -o'.
|
||||||
|
Remove '-o dest.o' from ARGS, run PROGRAM with the remaining
|
||||||
|
arguments, and rename the output as expected.
|
||||||
|
|
||||||
|
If you are trying to build a whole package this is not the
|
||||||
|
right script to run: please start by reading the file 'INSTALL'.
|
||||||
|
|
||||||
|
Report bugs to <bug-automake@gnu.org>.
|
||||||
|
EOF
|
||||||
|
exit $?
|
||||||
|
;;
|
||||||
|
-v | --v*)
|
||||||
|
echo "compile $scriptversion"
|
||||||
|
exit $?
|
||||||
|
;;
|
||||||
|
cl | *[/\\]cl | cl.exe | *[/\\]cl.exe )
|
||||||
|
func_cl_wrapper "$@" # Doesn't return...
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
ofile=
|
||||||
|
cfile=
|
||||||
|
|
||||||
|
for arg
|
||||||
|
do
|
||||||
|
if test -n "$eat"; then
|
||||||
|
eat=
|
||||||
|
else
|
||||||
|
case $1 in
|
||||||
|
-o)
|
||||||
|
# configure might choose to run compile as 'compile cc -o foo foo.c'.
|
||||||
|
# So we strip '-o arg' only if arg is an object.
|
||||||
|
eat=1
|
||||||
|
case $2 in
|
||||||
|
*.o | *.obj)
|
||||||
|
ofile=$2
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
set x "$@" -o "$2"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
*.c)
|
||||||
|
cfile=$1
|
||||||
|
set x "$@" "$1"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
set x "$@" "$1"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
if test -z "$ofile" || test -z "$cfile"; then
|
||||||
|
# If no '-o' option was seen then we might have been invoked from a
|
||||||
|
# pattern rule where we don't need one. That is ok -- this is a
|
||||||
|
# normal compilation that the losing compiler can handle. If no
|
||||||
|
# '.c' file was seen then we are probably linking. That is also
|
||||||
|
# ok.
|
||||||
|
exec "$@"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Name of file we expect compiler to create.
|
||||||
|
cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'`
|
||||||
|
|
||||||
|
# Create the lock directory.
|
||||||
|
# Note: use '[/\\:.-]' here to ensure that we don't use the same name
|
||||||
|
# that we are using for the .o file. Also, base the name on the expected
|
||||||
|
# object file name, since that is what matters with a parallel build.
|
||||||
|
lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d
|
||||||
|
while true; do
|
||||||
|
if mkdir "$lockdir" >/dev/null 2>&1; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
# FIXME: race condition here if user kills between mkdir and trap.
|
||||||
|
trap "rmdir '$lockdir'; exit 1" 1 2 15
|
||||||
|
|
||||||
|
# Run the compile.
|
||||||
|
"$@"
|
||||||
|
ret=$?
|
||||||
|
|
||||||
|
if test -f "$cofile"; then
|
||||||
|
test "$cofile" = "$ofile" || mv "$cofile" "$ofile"
|
||||||
|
elif test -f "${cofile}bj"; then
|
||||||
|
test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile"
|
||||||
|
fi
|
||||||
|
|
||||||
|
rmdir "$lockdir"
|
||||||
|
exit $ret
|
||||||
|
|
||||||
|
# Local Variables:
|
||||||
|
# mode: shell-script
|
||||||
|
# sh-indentation: 2
|
||||||
|
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||||
|
# time-stamp-start: "scriptversion="
|
||||||
|
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||||
|
# time-stamp-time-zone: "UTC"
|
||||||
|
# time-stamp-end: "; # UTC"
|
||||||
|
# End:
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,244 @@
|
||||||
|
/* config.h.in. Generated from configure.ac by autoheader. */
|
||||||
|
|
||||||
|
/* Define if building universal (internal helper macro) */
|
||||||
|
#undef AC_APPLE_UNIVERSAL_BUILD
|
||||||
|
|
||||||
|
/* display ATR parsing debug messages. */
|
||||||
|
#undef ATR_DEBUG
|
||||||
|
|
||||||
|
/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
|
||||||
|
systems. This function is required for `alloca.c' support on those systems.
|
||||||
|
*/
|
||||||
|
#undef CRAY_STACKSEG_END
|
||||||
|
|
||||||
|
/* Define to 1 if using `alloca.c'. */
|
||||||
|
#undef C_ALLOCA
|
||||||
|
|
||||||
|
/* Filter reader names */
|
||||||
|
#undef FILTER_NAMES
|
||||||
|
|
||||||
|
/* Define to 1 if you have `alloca', as a function or macro. */
|
||||||
|
#undef HAVE_ALLOCA
|
||||||
|
|
||||||
|
/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
|
||||||
|
*/
|
||||||
|
#undef HAVE_ALLOCA_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
|
||||||
|
*/
|
||||||
|
#undef HAVE_DIRENT_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||||
|
#undef HAVE_DLFCN_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <dl.h> header file. */
|
||||||
|
#undef HAVE_DL_H
|
||||||
|
|
||||||
|
/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
|
||||||
|
#undef HAVE_DOPRNT
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <fcntl.h> header file. */
|
||||||
|
#undef HAVE_FCNTL_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <getopt.h> header file. */
|
||||||
|
#undef HAVE_GETOPT_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `getopt_long' function. */
|
||||||
|
#undef HAVE_GETOPT_LONG
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||||
|
#undef HAVE_INTTYPES_H
|
||||||
|
|
||||||
|
/* Libudev is available */
|
||||||
|
#undef HAVE_LIBUDEV
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <libudev.h> header file. */
|
||||||
|
#undef HAVE_LIBUDEV_H
|
||||||
|
|
||||||
|
/* Libusb is available */
|
||||||
|
#undef HAVE_LIBUSB
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <libusb.h> header file. */
|
||||||
|
#undef HAVE_LIBUSB_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <memory.h> header file. */
|
||||||
|
#undef HAVE_MEMORY_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `nanosleep' function. */
|
||||||
|
#undef HAVE_NANOSLEEP
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
|
||||||
|
#undef HAVE_NDIR_H
|
||||||
|
|
||||||
|
/* Build polkit access control support */
|
||||||
|
#undef HAVE_POLKIT
|
||||||
|
|
||||||
|
/* Define if you have POSIX threads libraries and header files. */
|
||||||
|
#undef HAVE_PTHREAD
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `pthread_cancel' function. */
|
||||||
|
#undef HAVE_PTHREAD_CANCEL
|
||||||
|
|
||||||
|
/* Have PTHREAD_PRIO_INHERIT. */
|
||||||
|
#undef HAVE_PTHREAD_PRIO_INHERIT
|
||||||
|
|
||||||
|
/* Define to 1 if `stat' has the bug that it succeeds when given the
|
||||||
|
zero-length file name argument. */
|
||||||
|
#undef HAVE_STAT_EMPTY_STRING_BUG
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <stdint.h> header file. */
|
||||||
|
#undef HAVE_STDINT_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||||
|
#undef HAVE_STDLIB_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `strerror' function. */
|
||||||
|
#undef HAVE_STRERROR
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <strings.h> header file. */
|
||||||
|
#undef HAVE_STRINGS_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <string.h> header file. */
|
||||||
|
#undef HAVE_STRING_H
|
||||||
|
|
||||||
|
/* Define to 1 if `d_type' is a member of `struct dirent'. */
|
||||||
|
#undef HAVE_STRUCT_DIRENT_D_TYPE
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <syslog.h> header file. */
|
||||||
|
#undef HAVE_SYSLOG_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
|
||||||
|
*/
|
||||||
|
#undef HAVE_SYS_DIR_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/filio.h> header file. */
|
||||||
|
#undef HAVE_SYS_FILIO_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
|
||||||
|
*/
|
||||||
|
#undef HAVE_SYS_NDIR_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||||
|
#undef HAVE_SYS_STAT_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||||
|
#undef HAVE_SYS_TYPES_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
|
||||||
|
#undef HAVE_SYS_WAIT_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <unistd.h> header file. */
|
||||||
|
#undef HAVE_UNISTD_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `vprintf' function. */
|
||||||
|
#undef HAVE_VPRINTF
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `vsnprintf' function. */
|
||||||
|
#undef HAVE_VSNPRINTF
|
||||||
|
|
||||||
|
/* Define to 1 if `lstat' dereferences a symlink specified with a trailing
|
||||||
|
slash. */
|
||||||
|
#undef LSTAT_FOLLOWS_SLASHED_SYMLINK
|
||||||
|
|
||||||
|
/* Define to the sub-directory where libtool stores uninstalled libraries. */
|
||||||
|
#undef LT_OBJDIR
|
||||||
|
|
||||||
|
/* Disable logging support */
|
||||||
|
#undef NO_LOG
|
||||||
|
|
||||||
|
/* Name of package */
|
||||||
|
#undef PACKAGE
|
||||||
|
|
||||||
|
/* Define to the address where bug reports for this package should be sent. */
|
||||||
|
#undef PACKAGE_BUGREPORT
|
||||||
|
|
||||||
|
/* Define to the full name of this package. */
|
||||||
|
#undef PACKAGE_NAME
|
||||||
|
|
||||||
|
/* Define to the full name and version of this package. */
|
||||||
|
#undef PACKAGE_STRING
|
||||||
|
|
||||||
|
/* Define to the one symbol short name of this package. */
|
||||||
|
#undef PACKAGE_TARNAME
|
||||||
|
|
||||||
|
/* Define to the home page for this package. */
|
||||||
|
#undef PACKAGE_URL
|
||||||
|
|
||||||
|
/* Define to the version of this package. */
|
||||||
|
#undef PACKAGE_VERSION
|
||||||
|
|
||||||
|
/* pcscd filename */
|
||||||
|
#undef PCSCD_BINARY
|
||||||
|
|
||||||
|
/* Enabled PC/SC lite features */
|
||||||
|
#undef PCSCLITE_FEATURES
|
||||||
|
|
||||||
|
/* directory containing USB drivers */
|
||||||
|
#undef PCSCLITE_HP_DROPDIR
|
||||||
|
|
||||||
|
/* PC/SC target architecture */
|
||||||
|
#undef PCSC_ARCH
|
||||||
|
|
||||||
|
/* Define to necessary symbol if this constant uses a non-standard name on
|
||||||
|
your system. */
|
||||||
|
#undef PTHREAD_CREATE_JOINABLE
|
||||||
|
|
||||||
|
/* If using the C implementation of alloca, define if you know the
|
||||||
|
direction of stack growth for your system; otherwise it will be
|
||||||
|
automatically deduced at runtime.
|
||||||
|
STACK_DIRECTION > 0 => grows toward higher addresses
|
||||||
|
STACK_DIRECTION < 0 => grows toward lower addresses
|
||||||
|
STACK_DIRECTION = 0 => direction of growth unknown */
|
||||||
|
#undef STACK_DIRECTION
|
||||||
|
|
||||||
|
/* Define to 1 if you have the ANSI C header files. */
|
||||||
|
#undef STDC_HEADERS
|
||||||
|
|
||||||
|
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
|
||||||
|
#undef TIME_WITH_SYS_TIME
|
||||||
|
|
||||||
|
/* directory containing IPC files */
|
||||||
|
#undef USE_IPCDIR
|
||||||
|
|
||||||
|
/* Use serial conf file mechanism */
|
||||||
|
#undef USE_SERIAL
|
||||||
|
|
||||||
|
/* Use USB hotplug mechanism */
|
||||||
|
#undef USE_USB
|
||||||
|
|
||||||
|
/* Version number of package */
|
||||||
|
#undef VERSION
|
||||||
|
|
||||||
|
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
|
||||||
|
significant byte first (like Motorola and SPARC, unlike Intel). */
|
||||||
|
#if defined AC_APPLE_UNIVERSAL_BUILD
|
||||||
|
# if defined __BIG_ENDIAN__
|
||||||
|
# define WORDS_BIGENDIAN 1
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
# ifndef WORDS_BIGENDIAN
|
||||||
|
# undef WORDS_BIGENDIAN
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a
|
||||||
|
`char[]'. */
|
||||||
|
#undef YYTEXT_POINTER
|
||||||
|
|
||||||
|
/* Define to empty if `const' does not conform to ANSI C. */
|
||||||
|
#undef const
|
||||||
|
|
||||||
|
/* Define to `int' if <sys/types.h> doesn't define. */
|
||||||
|
#undef gid_t
|
||||||
|
|
||||||
|
/* Define to `__inline__' or `__inline' if that's what the C compiler
|
||||||
|
calls it, or to nothing if 'inline' is not supported under any name. */
|
||||||
|
#ifndef __cplusplus
|
||||||
|
#undef inline
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Define to `unsigned int' if <sys/types.h> does not define. */
|
||||||
|
#undef size_t
|
||||||
|
|
||||||
|
/* Define to `int' if <sys/types.h> doesn't define. */
|
||||||
|
#undef uid_t
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,460 @@
|
||||||
|
# -*- mode: m4; -*-
|
||||||
|
# Process this file with autoconf to produce a configure script
|
||||||
|
|
||||||
|
AC_PREREQ([2.69])
|
||||||
|
|
||||||
|
AC_INIT([pcsc-lite],[1.8.22])
|
||||||
|
AC_CONFIG_SRCDIR(src/pcscdaemon.c)
|
||||||
|
AM_INIT_AUTOMAKE(1.8 dist-bzip2 no-dist-gzip)
|
||||||
|
AC_CONFIG_HEADERS([config.h])
|
||||||
|
|
||||||
|
AC_CONFIG_MACRO_DIR(m4)
|
||||||
|
|
||||||
|
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
|
||||||
|
|
||||||
|
AC_CANONICAL_HOST
|
||||||
|
AC_PROG_CC
|
||||||
|
AC_C_BIGENDIAN
|
||||||
|
|
||||||
|
# Check for some target-specific stuff
|
||||||
|
case "$host" in
|
||||||
|
*-*-hpux*)
|
||||||
|
CPPFLAGS="$CPPFLAGS -D_HPUX_SOURCE -D_XOPEN_SOURCE_EXTENDED"
|
||||||
|
;;
|
||||||
|
*-*-solaris*)
|
||||||
|
CPPFLAGS="$CPPFLAGS -I/usr/local/include"
|
||||||
|
LDFLAGS="$LDFLAGS -L/usr/local/lib -R/usr/local/lib"
|
||||||
|
need_dash_r=1
|
||||||
|
;;
|
||||||
|
*-*-sunos4*)
|
||||||
|
CPPFLAGS="$CPPFLAGS -DSUNOS4"
|
||||||
|
;;
|
||||||
|
*-*-aix*)
|
||||||
|
CPPFLAGS="$CPPFLAGS -I/usr/local/include"
|
||||||
|
LDFLAGS="$LDFLAGS -L/usr/local/lib"
|
||||||
|
if (test "$LD" != "gcc" && test -z "$blibpath"); then
|
||||||
|
blibpath="/usr/lib:/lib:/usr/local/lib"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
*-*-osf*)
|
||||||
|
CPPFLAGS="$CPPFLAGS -D_POSIX_PII_SOCKET"
|
||||||
|
;;
|
||||||
|
*-*-darwin*)
|
||||||
|
AC_SUBST(COREFOUNDATION)
|
||||||
|
COREFOUNDATION="-Wl,-framework,CoreFoundation"
|
||||||
|
AC_SUBST(IOKIT)
|
||||||
|
IOKIT="-Wl,-framework,IOKit"
|
||||||
|
if test "$GCC" = "yes"; then
|
||||||
|
CFLAGS="$CFLAGS -no-cpp-precomp"
|
||||||
|
fi
|
||||||
|
use_libusb=no
|
||||||
|
AC_MSG_WARN([libusb disabled on Darwin for pcsc-lite])
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Options
|
||||||
|
AM_MAINTAINER_MODE
|
||||||
|
|
||||||
|
# Checks for programs
|
||||||
|
AC_PROG_CPP
|
||||||
|
AC_PROG_INSTALL
|
||||||
|
AC_PROG_LN_S
|
||||||
|
AC_PROG_MAKE_SET
|
||||||
|
AM_PROG_LEX
|
||||||
|
PKG_PROG_PKG_CONFIG
|
||||||
|
AM_PROG_CC_C_O
|
||||||
|
AM_PROG_AR
|
||||||
|
|
||||||
|
# Special check for pthread support
|
||||||
|
AX_PTHREAD([
|
||||||
|
AC_DEFINE(HAVE_PTHREAD, 1,
|
||||||
|
[Define if you have POSIX threads libraries and header files.])
|
||||||
|
],[
|
||||||
|
AC_MSG_ERROR([POSIX thread support required])
|
||||||
|
])
|
||||||
|
|
||||||
|
CC="$PTHREAD_CC"
|
||||||
|
|
||||||
|
AC_SUBST(PTHREAD_LIBS)
|
||||||
|
AC_SUBST(PTHREAD_CFLAGS)
|
||||||
|
|
||||||
|
# check for pthread_cancel()
|
||||||
|
saved_CFLAGS="$CFLAGS"
|
||||||
|
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||||
|
AC_CHECK_FUNCS(pthread_cancel)
|
||||||
|
CFLAGS="$saved_CFLAGS"
|
||||||
|
|
||||||
|
# Add libtool support
|
||||||
|
# Static lib is disabled by default. Use --enable-static if needed
|
||||||
|
LT_INIT(disable-static)
|
||||||
|
LT_INIT
|
||||||
|
# Automatically update the libtool script if it becomes out-of-date
|
||||||
|
#AC_SUBST(LIBTOOL_DEPS)
|
||||||
|
|
||||||
|
# Checks for header files
|
||||||
|
AC_HEADER_STDC
|
||||||
|
AC_HEADER_SYS_WAIT
|
||||||
|
AC_CHECK_HEADERS([getopt.h sys/filio.h syslog.h dl.h fcntl.h alloca.h])
|
||||||
|
|
||||||
|
# Checks for typedefs, structures, and compiler characteristics
|
||||||
|
AC_C_CONST
|
||||||
|
AC_TYPE_UID_T
|
||||||
|
AC_TYPE_SIZE_T
|
||||||
|
AC_HEADER_TIME
|
||||||
|
AC_STRUCT_DIRENT_D_TYPE
|
||||||
|
|
||||||
|
# Checks for library functions
|
||||||
|
AC_FUNC_ERROR_AT_LINE
|
||||||
|
AC_FUNC_STAT
|
||||||
|
AC_FUNC_VPRINTF
|
||||||
|
AC_CHECK_FUNCS(getopt_long nanosleep strerror vsnprintf)
|
||||||
|
AC_FUNC_ALLOCA
|
||||||
|
|
||||||
|
# C Compiler features
|
||||||
|
AC_C_INLINE
|
||||||
|
if test "$GCC" = "yes"; then
|
||||||
|
CFLAGS="-Wall -fno-common $CFLAGS"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# check if the compiler support -fvisibility=hidden (GCC >= 4)
|
||||||
|
saved_CFLAGS="$CFLAGS"
|
||||||
|
CFLAGS="$CFLAGS -fvisibility=hidden"
|
||||||
|
AC_MSG_CHECKING([for -fvisibility=hidden])
|
||||||
|
AC_COMPILE_IFELSE([AC_LANG_SOURCE([char foo;])],
|
||||||
|
[ AC_MSG_RESULT([yes])
|
||||||
|
SYMBOL_VISIBILITY="-fvisibility=hidden" ],
|
||||||
|
AC_MSG_RESULT([no]))
|
||||||
|
CFLAGS="$saved_CFLAGS"
|
||||||
|
AC_SUBST(SYMBOL_VISIBILITY)
|
||||||
|
|
||||||
|
AC_SEARCH_LIBS([dlopen], [dl dld], [], [
|
||||||
|
AC_MSG_ERROR([unable to find the dlopen() function])
|
||||||
|
])
|
||||||
|
|
||||||
|
# Use 'uname' output as an architecture define
|
||||||
|
PCSC_ARCH=`uname | sed -e s,/,_,`
|
||||||
|
case "$PCSC_ARCH" in
|
||||||
|
Darwin)
|
||||||
|
PCSC_ARCH=MacOS
|
||||||
|
;;
|
||||||
|
SunOS)
|
||||||
|
PCSC_ARCH=Solaris
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
AC_DEFINE_UNQUOTED(PCSC_ARCH, "$PCSC_ARCH", [PC/SC target architecture])
|
||||||
|
PCSCLITE_FEATURES="${PCSCLITE_FEATURES} $PCSC_ARCH $host"
|
||||||
|
|
||||||
|
# See if socket() is found from libsocket
|
||||||
|
AC_CHECK_LIB(socket, socket, [LIBS="$LIBS -lsocket"])
|
||||||
|
|
||||||
|
# check for mq_getattr()
|
||||||
|
AC_CHECK_LIB(rt, mq_getattr, [LIBS="$LIBS -lrt"])
|
||||||
|
|
||||||
|
# --disable-serial
|
||||||
|
AC_ARG_ENABLE(serial,
|
||||||
|
AS_HELP_STRING([--disable-serial],[do not use serial reader.conf file]),
|
||||||
|
[ use_serial="${enableval}" ], [ use_serial="yes" ] )
|
||||||
|
AM_CONDITIONAL(ENABLE_SERIAL, test "$use_serial" != "no")
|
||||||
|
if test "$use_serial" != "no"; then
|
||||||
|
AC_DEFINE(USE_SERIAL, 1, [Use serial conf file mechanism])
|
||||||
|
PCSCLITE_FEATURES="${PCSCLITE_FEATURES} serial"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --disable-usb
|
||||||
|
AC_ARG_ENABLE(usb,
|
||||||
|
AS_HELP_STRING([--disable-usb],[do not use usb hotplug]),
|
||||||
|
[ use_usb="${enableval}" ], [ use_usb="yes" ] )
|
||||||
|
AM_CONDITIONAL(ENABLE_USB, test "$use_usb" != "no")
|
||||||
|
if test "$use_usb" != "no"; then
|
||||||
|
AC_DEFINE(USE_USB, 1, [Use USB hotplug mechanism])
|
||||||
|
PCSCLITE_FEATURES="${PCSCLITE_FEATURES} usb"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --enable-libudev
|
||||||
|
AC_ARG_ENABLE(libudev,
|
||||||
|
AS_HELP_STRING([--disable-libudev],[do not use libudev]),
|
||||||
|
[ use_libudev="${enableval}" ],
|
||||||
|
[ if test "$PCSC_ARCH" != "Linux" ; then
|
||||||
|
use_libudev="no"
|
||||||
|
else
|
||||||
|
use_libudev="${use_libudev-yes}"
|
||||||
|
fi ])
|
||||||
|
|
||||||
|
# disable libudev check is USB is not used
|
||||||
|
if test "$use_usb" == "no"; then
|
||||||
|
use_libudev="no"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# check if libudev is used
|
||||||
|
if test "x$use_libudev" != xno ; then
|
||||||
|
PKG_CHECK_MODULES(LIBUDEV, libudev, [],
|
||||||
|
[ AC_MSG_ERROR([install libudev-dev or use --disable-libudev]) ])
|
||||||
|
|
||||||
|
saved_CPPFLAGS="$CPPFLAGS"
|
||||||
|
saved_LIBS="$LIBS"
|
||||||
|
|
||||||
|
CPPFLAGS="$CPPFLAGS $LIBUDEV_CFLAGS"
|
||||||
|
LIBS="$LDFLAGS $LIBUDEV_LIBS"
|
||||||
|
|
||||||
|
AC_CHECK_HEADERS(libudev.h, [],
|
||||||
|
[ AC_MSG_ERROR([libudev.h not found, use ./configure LIBUDEV_CFLAGS=...]) ])
|
||||||
|
|
||||||
|
LIBS="$LIBS $COREFOUNDATION $IOKIT"
|
||||||
|
|
||||||
|
AC_MSG_CHECKING([for udev_monitor_unref])
|
||||||
|
AC_TRY_LINK_FUNC(udev_monitor_unref, [ AC_MSG_RESULT([yes]) ],
|
||||||
|
[ AC_MSG_ERROR([udev_monitor_unref not found, use ./configure LIBUDEV_LIBS=...]) ])
|
||||||
|
|
||||||
|
# everything needed for libudev support is present
|
||||||
|
use_libudev=yes
|
||||||
|
|
||||||
|
CPPFLAGS="$saved_CPPFLAGS"
|
||||||
|
LIBS="$saved_LIBS"
|
||||||
|
fi
|
||||||
|
AC_SUBST(LIBUDEV_CFLAGS)
|
||||||
|
AC_SUBST(LIBUDEV_LIBS)
|
||||||
|
|
||||||
|
if test x$use_libudev = xyes; then
|
||||||
|
AC_DEFINE(HAVE_LIBUDEV, 1, [Libudev is available])
|
||||||
|
PCSCLITE_FEATURES="${PCSCLITE_FEATURES} libudev"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --enable-libusb
|
||||||
|
AC_ARG_ENABLE(libusb,
|
||||||
|
AS_HELP_STRING([--enable-libusb],[use libusb]),
|
||||||
|
[ use_libusb="${enableval}" ],
|
||||||
|
[ if test "x$use_libudev" = xyes ; then use_libusb="${use_libusb-no}" ;
|
||||||
|
else use_libusb="${use_libusb-yes}" ; fi ] )
|
||||||
|
|
||||||
|
# disable libusb check is USB is not used
|
||||||
|
if test "$use_usb" == "no"; then
|
||||||
|
use_libusb="no"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# check if libusb is used
|
||||||
|
if test "x$use_libusb" != xno ; then
|
||||||
|
if test "x$use_libudev" != xno ; then
|
||||||
|
AC_MSG_ERROR([You can't use libudev _and_ libusb. Select only one.])
|
||||||
|
fi
|
||||||
|
|
||||||
|
PKG_CHECK_MODULES(LIBUSB, libusb-1.0, [],
|
||||||
|
[
|
||||||
|
AC_MSG_RESULT([no])
|
||||||
|
AC_CHECK_PROG([LIBUSBCONFIG], [libusb-config], [yes])
|
||||||
|
|
||||||
|
if test "$LIBUSBCONFIG" = "yes" ; then
|
||||||
|
LIBUSB_CFLAGS="$LIBUSB_CFLAGS `libusb-config --cflags`"
|
||||||
|
LIBUSB_LIBS="$LIBUSB_LIBS `libusb-config --libs`"
|
||||||
|
else
|
||||||
|
AC_MSG_WARN([libusb-config not found.])
|
||||||
|
fi
|
||||||
|
])
|
||||||
|
|
||||||
|
saved_CPPFLAGS="$CPPFLAGS"
|
||||||
|
saved_LIBS="$LIBS"
|
||||||
|
|
||||||
|
CPPFLAGS="$CPPFLAGS $LIBUSB_CFLAGS"
|
||||||
|
LIBS="$LDFLAGS $LIBUSB_LIBS"
|
||||||
|
|
||||||
|
AC_CHECK_HEADERS(libusb.h, [],
|
||||||
|
[ AC_MSG_ERROR([libusb.h not found, use ./configure LIBUSB_CFLAGS=...]) ])
|
||||||
|
|
||||||
|
LIBS="$LIBS $COREFOUNDATION $IOKIT"
|
||||||
|
|
||||||
|
AC_MSG_CHECKING([for libusb_init])
|
||||||
|
AC_TRY_LINK_FUNC(libusb_init, [ AC_MSG_RESULT([yes]) ],
|
||||||
|
[ AC_MSG_ERROR([libusb not found, use ./configure LIBUSB_LIBS=...]) ])
|
||||||
|
|
||||||
|
# everything needed for libusb support is present
|
||||||
|
use_libusb=yes
|
||||||
|
|
||||||
|
CPPFLAGS="$saved_CPPFLAGS"
|
||||||
|
LIBS="$saved_LIBS"
|
||||||
|
fi
|
||||||
|
AC_SUBST(LIBUSB_CFLAGS)
|
||||||
|
AC_SUBST(LIBUSB_LIBS)
|
||||||
|
|
||||||
|
if test x$use_libusb = xyes; then
|
||||||
|
AC_DEFINE(HAVE_LIBUSB, 1, [Libusb is available])
|
||||||
|
PCSCLITE_FEATURES="${PCSCLITE_FEATURES} libusb"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --enable-polkit
|
||||||
|
POLKIT_MINIMUM=0.111
|
||||||
|
AC_ARG_ENABLE(polkit,
|
||||||
|
AS_HELP_STRING([--enable-polkit],
|
||||||
|
[Build with polkit support]),
|
||||||
|
use_polkit=$enableval, use_polkit=no)
|
||||||
|
if test "$use_polkit" != "no"; then
|
||||||
|
PKG_CHECK_MODULES(POLKIT, [polkit-gobject-1 >= $POLKIT_MINIMUM], [use_polkit=yes], [use_polkit=no])
|
||||||
|
if test "$use_polkit" != "no";then
|
||||||
|
AC_DEFINE([HAVE_POLKIT], 1, [Build polkit access control support])
|
||||||
|
polkit_policy_dir=$($PKG_CONFIG polkit-gobject-1 --variable=policydir)
|
||||||
|
AC_SUBST(POLICY_DIR, [$polkit_policy_dir])
|
||||||
|
else
|
||||||
|
use_polkit=no
|
||||||
|
AC_MSG_ERROR([[
|
||||||
|
***
|
||||||
|
*** polkit >= $POLKIT_MINIMUM was not found. Access control will be disabled.
|
||||||
|
*** You may get it from http://www.freedesktop.org/software/polkit/
|
||||||
|
*** ]])
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
AM_CONDITIONAL(ENABLE_POLKIT, test "$use_polkit" != "no")
|
||||||
|
|
||||||
|
# --with-systemdsystemunitdir=DIR
|
||||||
|
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 ])
|
||||||
|
|
||||||
|
# --enable-embedded
|
||||||
|
AC_ARG_ENABLE(embedded,
|
||||||
|
AS_HELP_STRING([--enable-embedded],[limit RAM and CPU ressources by disabling features (log)]),
|
||||||
|
[ use_embedded="${enableval}" ])
|
||||||
|
|
||||||
|
if test x$use_embedded = xyes; then
|
||||||
|
AC_DEFINE(NO_LOG, 1, [Disable logging support])
|
||||||
|
PCSCLITE_FEATURES="${PCSCLITE_FEATURES} nolog"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --enable-usbdropdir=DIR
|
||||||
|
AC_ARG_ENABLE(usbdropdir,
|
||||||
|
AS_HELP_STRING([--enable-usbdropdir=DIR],[directory containing USB
|
||||||
|
drivers (default /usr/local/lib/pcsc/drivers)]),
|
||||||
|
[usbdropdir="${enableval}"], [usbdropdir=false])
|
||||||
|
if test x${usbdropdir} = xfalse ; then
|
||||||
|
if test "x$libdir" != xNONE; then
|
||||||
|
usbdropdir="$libdir/pcsc/drivers"
|
||||||
|
else
|
||||||
|
usbdropdir="$ac_default_libdir/pcsc/drivers"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
AS_AC_EXPAND(usbdropdir_exp,$usbdropdir)
|
||||||
|
usbdropdir=$usbdropdir_exp
|
||||||
|
AC_DEFINE_UNQUOTED(PCSCLITE_HP_DROPDIR, "$usbdropdir", [directory containing USB drivers])
|
||||||
|
PCSCLITE_FEATURES="${PCSCLITE_FEATURES} usbdropdir=${usbdropdir}"
|
||||||
|
|
||||||
|
# --enable-debugatr
|
||||||
|
AC_ARG_ENABLE(debugatr,
|
||||||
|
AS_HELP_STRING([--enable-debugatr],[enable ATR debug messages from pcscd]),
|
||||||
|
[ case "${enableval}" in
|
||||||
|
yes) debugatr=true ;;
|
||||||
|
no) debugatr=false ;;
|
||||||
|
*) AC_MSG_ERROR([bad value ${enableval} for --enable-debugatr]) ;;
|
||||||
|
esac], [debugatr=false])
|
||||||
|
|
||||||
|
if test x${debugatr} = xtrue ; then
|
||||||
|
AC_DEFINE(ATR_DEBUG, 1, [display ATR parsing debug messages.])
|
||||||
|
PCSCLITE_FEATURES="${PCSCLITE_FEATURES} debugatr"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --enable-ipcdir=DIR
|
||||||
|
AC_ARG_ENABLE(ipcdir,
|
||||||
|
AS_HELP_STRING([--enable-ipcdir=DIR],[directory containing IPC files
|
||||||
|
(default /var/run/pcscd)]),
|
||||||
|
[ipcdir="${enableval}"], [ipcdir=false])
|
||||||
|
|
||||||
|
if test x${ipcdir} = xfalse ; then
|
||||||
|
ipcdir="/var/run/pcscd"
|
||||||
|
fi
|
||||||
|
AC_DEFINE_UNQUOTED(USE_IPCDIR, "$ipcdir", [directory containing IPC files])
|
||||||
|
PCSCLITE_FEATURES="${PCSCLITE_FEATURES} ipcdir=${ipcdir}"
|
||||||
|
|
||||||
|
CPPFLAGS="-I\${top_srcdir}/src $CPPFLAGS"
|
||||||
|
|
||||||
|
# --enable-confdir=DIR
|
||||||
|
AC_ARG_ENABLE(confdir,
|
||||||
|
AS_HELP_STRING([--enable-confdir=DIR],[directory containing reader configurations (default /etc/reader.conf.d)]),
|
||||||
|
[confdir="${enableval}"],
|
||||||
|
[confdir="${sysconfdir}/reader.conf.d"])
|
||||||
|
|
||||||
|
# --enable-filter
|
||||||
|
AC_ARG_ENABLE(filter,
|
||||||
|
AS_HELP_STRING([--enable-filter],[allow to filter readers using
|
||||||
|
PCSCLITE_FILTER_IGNORE_READER_NAMES and PCSCLITE_FILTER_EXTEND_READER_NAMES]),
|
||||||
|
[ use_filter="${enableval}" ], [ use_filter="no" ])
|
||||||
|
|
||||||
|
if test x$use_filter = xyes; then
|
||||||
|
AC_DEFINE(FILTER_NAMES, 1, [Filter reader names])
|
||||||
|
PCSCLITE_FEATURES="${PCSCLITE_FEATURES} filter"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Setup dist stuff
|
||||||
|
AC_SUBST(usbdropdir)
|
||||||
|
AC_SUBST(ipcdir)
|
||||||
|
AC_SUBST(serialconfdir)
|
||||||
|
AC_SUBST(host_to_ccid_16)
|
||||||
|
AC_SUBST(host_to_ccid_32)
|
||||||
|
AS_AC_EXPAND(confdir_exp,$confdir)
|
||||||
|
AS_AC_EXPAND(sbindir_exp,$sbindir)
|
||||||
|
AS_AC_EXPAND(localstatedir_exp,$localstatedir)
|
||||||
|
|
||||||
|
PCSCLITE_CONFIG_DIR="${confdir_exp}"
|
||||||
|
AC_SUBST(PCSCLITE_CONFIG_DIR)
|
||||||
|
PCSCLITE_FEATURES="${PCSCLITE_FEATURES} configdir=${PCSCLITE_CONFIG_DIR}"
|
||||||
|
AC_DEFINE_UNQUOTED([PCSCLITE_FEATURES], ["${PCSCLITE_FEATURES}"], [Enabled PC/SC lite features])
|
||||||
|
PCSCD_BINARY="${sbindir_exp}/pcscd"
|
||||||
|
AC_DEFINE_UNQUOTED([PCSCD_BINARY], ["$PCSCD_BINARY"], [pcscd filename])
|
||||||
|
|
||||||
|
cat << EOF
|
||||||
|
|
||||||
|
PC/SC lite has been configured with following options:
|
||||||
|
|
||||||
|
Version: ${PACKAGE_VERSION}
|
||||||
|
System binaries: $(eval eval eval echo "${sbindir_exp}")
|
||||||
|
Configuration dir: ${PCSCLITE_CONFIG_DIR}
|
||||||
|
|
||||||
|
|
||||||
|
Host: ${host}
|
||||||
|
Compiler: ${CC}
|
||||||
|
Preprocessor flags: ${CPPFLAGS}
|
||||||
|
Compiler flags: ${CFLAGS}
|
||||||
|
Preprocessor flags: ${CPPFLAGS}
|
||||||
|
Linker flags: ${LDFLAGS}
|
||||||
|
Libraries: ${LIBS}
|
||||||
|
|
||||||
|
PTHREAD_CFLAGS: ${PTHREAD_CFLAGS}
|
||||||
|
PTHREAD_LIBS: ${PTHREAD_LIBS}
|
||||||
|
PCSC_ARCH: ${PCSC_ARCH}
|
||||||
|
|
||||||
|
pcscd binary ${PCSCD_BINARY}
|
||||||
|
polkit support: ${use_polkit}
|
||||||
|
polkit policy dir: ${polkit_policy_dir}
|
||||||
|
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}
|
||||||
|
systemd unit directory: ${with_systemdsystemunitdir}
|
||||||
|
serial config dir.: ${confdir_exp}
|
||||||
|
filter: ${use_filter}
|
||||||
|
|
||||||
|
PCSCLITE_FEATURES: ${PCSCLITE_FEATURES}
|
||||||
|
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Write Makefiles
|
||||||
|
AC_CONFIG_FILES([
|
||||||
|
Makefile
|
||||||
|
doc/Makefile
|
||||||
|
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
|
||||||
|
src/PCSC/pcsclite.h
|
||||||
|
src/spy/Makefile
|
||||||
|
])
|
||||||
|
AC_OUTPUT
|
||||||
|
|
|
@ -0,0 +1,791 @@
|
||||||
|
#! /bin/sh
|
||||||
|
# depcomp - compile a program generating dependencies as side-effects
|
||||||
|
|
||||||
|
scriptversion=2013-05-30.07; # UTC
|
||||||
|
|
||||||
|
# Copyright (C) 1999-2014 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
# 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 2, 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/>.
|
||||||
|
|
||||||
|
# As a special exception to the GNU General Public License, if you
|
||||||
|
# distribute this file as part of a program that contains a
|
||||||
|
# configuration script generated by Autoconf, you may include it under
|
||||||
|
# the same distribution terms that you use for the rest of that program.
|
||||||
|
|
||||||
|
# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
|
||||||
|
|
||||||
|
case $1 in
|
||||||
|
'')
|
||||||
|
echo "$0: No command. Try '$0 --help' for more information." 1>&2
|
||||||
|
exit 1;
|
||||||
|
;;
|
||||||
|
-h | --h*)
|
||||||
|
cat <<\EOF
|
||||||
|
Usage: depcomp [--help] [--version] PROGRAM [ARGS]
|
||||||
|
|
||||||
|
Run PROGRAMS ARGS to compile a file, generating dependencies
|
||||||
|
as side-effects.
|
||||||
|
|
||||||
|
Environment variables:
|
||||||
|
depmode Dependency tracking mode.
|
||||||
|
source Source file read by 'PROGRAMS ARGS'.
|
||||||
|
object Object file output by 'PROGRAMS ARGS'.
|
||||||
|
DEPDIR directory where to store dependencies.
|
||||||
|
depfile Dependency file to output.
|
||||||
|
tmpdepfile Temporary file to use when outputting dependencies.
|
||||||
|
libtool Whether libtool is used (yes/no).
|
||||||
|
|
||||||
|
Report bugs to <bug-automake@gnu.org>.
|
||||||
|
EOF
|
||||||
|
exit $?
|
||||||
|
;;
|
||||||
|
-v | --v*)
|
||||||
|
echo "depcomp $scriptversion"
|
||||||
|
exit $?
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Get the directory component of the given path, and save it in the
|
||||||
|
# global variables '$dir'. Note that this directory component will
|
||||||
|
# be either empty or ending with a '/' character. This is deliberate.
|
||||||
|
set_dir_from ()
|
||||||
|
{
|
||||||
|
case $1 in
|
||||||
|
*/*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;;
|
||||||
|
*) dir=;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get the suffix-stripped basename of the given path, and save it the
|
||||||
|
# global variable '$base'.
|
||||||
|
set_base_from ()
|
||||||
|
{
|
||||||
|
base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'`
|
||||||
|
}
|
||||||
|
|
||||||
|
# If no dependency file was actually created by the compiler invocation,
|
||||||
|
# we still have to create a dummy depfile, to avoid errors with the
|
||||||
|
# Makefile "include basename.Plo" scheme.
|
||||||
|
make_dummy_depfile ()
|
||||||
|
{
|
||||||
|
echo "#dummy" > "$depfile"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Factor out some common post-processing of the generated depfile.
|
||||||
|
# Requires the auxiliary global variable '$tmpdepfile' to be set.
|
||||||
|
aix_post_process_depfile ()
|
||||||
|
{
|
||||||
|
# If the compiler actually managed to produce a dependency file,
|
||||||
|
# post-process it.
|
||||||
|
if test -f "$tmpdepfile"; then
|
||||||
|
# Each line is of the form 'foo.o: dependency.h'.
|
||||||
|
# Do two passes, one to just change these to
|
||||||
|
# $object: dependency.h
|
||||||
|
# and one to simply output
|
||||||
|
# dependency.h:
|
||||||
|
# which is needed to avoid the deleted-header problem.
|
||||||
|
{ sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile"
|
||||||
|
sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile"
|
||||||
|
} > "$depfile"
|
||||||
|
rm -f "$tmpdepfile"
|
||||||
|
else
|
||||||
|
make_dummy_depfile
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# A tabulation character.
|
||||||
|
tab=' '
|
||||||
|
# A newline character.
|
||||||
|
nl='
|
||||||
|
'
|
||||||
|
# Character ranges might be problematic outside the C locale.
|
||||||
|
# These definitions help.
|
||||||
|
upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ
|
||||||
|
lower=abcdefghijklmnopqrstuvwxyz
|
||||||
|
digits=0123456789
|
||||||
|
alpha=${upper}${lower}
|
||||||
|
|
||||||
|
if test -z "$depmode" || test -z "$source" || test -z "$object"; then
|
||||||
|
echo "depcomp: Variables source, object and depmode must be set" 1>&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
|
||||||
|
depfile=${depfile-`echo "$object" |
|
||||||
|
sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
|
||||||
|
tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
|
||||||
|
|
||||||
|
rm -f "$tmpdepfile"
|
||||||
|
|
||||||
|
# Avoid interferences from the environment.
|
||||||
|
gccflag= dashmflag=
|
||||||
|
|
||||||
|
# Some modes work just like other modes, but use different flags. We
|
||||||
|
# parameterize here, but still list the modes in the big case below,
|
||||||
|
# to make depend.m4 easier to write. Note that we *cannot* use a case
|
||||||
|
# here, because this file can only contain one case statement.
|
||||||
|
if test "$depmode" = hp; then
|
||||||
|
# HP compiler uses -M and no extra arg.
|
||||||
|
gccflag=-M
|
||||||
|
depmode=gcc
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "$depmode" = dashXmstdout; then
|
||||||
|
# This is just like dashmstdout with a different argument.
|
||||||
|
dashmflag=-xM
|
||||||
|
depmode=dashmstdout
|
||||||
|
fi
|
||||||
|
|
||||||
|
cygpath_u="cygpath -u -f -"
|
||||||
|
if test "$depmode" = msvcmsys; then
|
||||||
|
# This is just like msvisualcpp but w/o cygpath translation.
|
||||||
|
# Just convert the backslash-escaped backslashes to single forward
|
||||||
|
# slashes to satisfy depend.m4
|
||||||
|
cygpath_u='sed s,\\\\,/,g'
|
||||||
|
depmode=msvisualcpp
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "$depmode" = msvc7msys; then
|
||||||
|
# This is just like msvc7 but w/o cygpath translation.
|
||||||
|
# Just convert the backslash-escaped backslashes to single forward
|
||||||
|
# slashes to satisfy depend.m4
|
||||||
|
cygpath_u='sed s,\\\\,/,g'
|
||||||
|
depmode=msvc7
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "$depmode" = xlc; then
|
||||||
|
# IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information.
|
||||||
|
gccflag=-qmakedep=gcc,-MF
|
||||||
|
depmode=gcc
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$depmode" in
|
||||||
|
gcc3)
|
||||||
|
## gcc 3 implements dependency tracking that does exactly what
|
||||||
|
## we want. Yay! Note: for some reason libtool 1.4 doesn't like
|
||||||
|
## it if -MD -MP comes after the -MF stuff. Hmm.
|
||||||
|
## Unfortunately, FreeBSD c89 acceptance of flags depends upon
|
||||||
|
## the command line argument order; so add the flags where they
|
||||||
|
## appear in depend2.am. Note that the slowdown incurred here
|
||||||
|
## affects only configure: in makefiles, %FASTDEP% shortcuts this.
|
||||||
|
for arg
|
||||||
|
do
|
||||||
|
case $arg in
|
||||||
|
-c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
|
||||||
|
*) set fnord "$@" "$arg" ;;
|
||||||
|
esac
|
||||||
|
shift # fnord
|
||||||
|
shift # $arg
|
||||||
|
done
|
||||||
|
"$@"
|
||||||
|
stat=$?
|
||||||
|
if test $stat -ne 0; then
|
||||||
|
rm -f "$tmpdepfile"
|
||||||
|
exit $stat
|
||||||
|
fi
|
||||||
|
mv "$tmpdepfile" "$depfile"
|
||||||
|
;;
|
||||||
|
|
||||||
|
gcc)
|
||||||
|
## Note that this doesn't just cater to obsosete pre-3.x GCC compilers.
|
||||||
|
## but also to in-use compilers like IMB xlc/xlC and the HP C compiler.
|
||||||
|
## (see the conditional assignment to $gccflag above).
|
||||||
|
## There are various ways to get dependency output from gcc. Here's
|
||||||
|
## why we pick this rather obscure method:
|
||||||
|
## - Don't want to use -MD because we'd like the dependencies to end
|
||||||
|
## up in a subdir. Having to rename by hand is ugly.
|
||||||
|
## (We might end up doing this anyway to support other compilers.)
|
||||||
|
## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
|
||||||
|
## -MM, not -M (despite what the docs say). Also, it might not be
|
||||||
|
## supported by the other compilers which use the 'gcc' depmode.
|
||||||
|
## - Using -M directly means running the compiler twice (even worse
|
||||||
|
## than renaming).
|
||||||
|
if test -z "$gccflag"; then
|
||||||
|
gccflag=-MD,
|
||||||
|
fi
|
||||||
|
"$@" -Wp,"$gccflag$tmpdepfile"
|
||||||
|
stat=$?
|
||||||
|
if test $stat -ne 0; then
|
||||||
|
rm -f "$tmpdepfile"
|
||||||
|
exit $stat
|
||||||
|
fi
|
||||||
|
rm -f "$depfile"
|
||||||
|
echo "$object : \\" > "$depfile"
|
||||||
|
# The second -e expression handles DOS-style file names with drive
|
||||||
|
# letters.
|
||||||
|
sed -e 's/^[^:]*: / /' \
|
||||||
|
-e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
|
||||||
|
## This next piece of magic avoids the "deleted header file" problem.
|
||||||
|
## The problem is that when a header file which appears in a .P file
|
||||||
|
## is deleted, the dependency causes make to die (because there is
|
||||||
|
## typically no way to rebuild the header). We avoid this by adding
|
||||||
|
## dummy dependencies for each header file. Too bad gcc doesn't do
|
||||||
|
## this for us directly.
|
||||||
|
## Some versions of gcc put a space before the ':'. On the theory
|
||||||
|
## that the space means something, we add a space to the output as
|
||||||
|
## well. hp depmode also adds that space, but also prefixes the VPATH
|
||||||
|
## to the object. Take care to not repeat it in the output.
|
||||||
|
## Some versions of the HPUX 10.20 sed can't process this invocation
|
||||||
|
## correctly. Breaking it into two sed invocations is a workaround.
|
||||||
|
tr ' ' "$nl" < "$tmpdepfile" \
|
||||||
|
| sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \
|
||||||
|
| sed -e 's/$/ :/' >> "$depfile"
|
||||||
|
rm -f "$tmpdepfile"
|
||||||
|
;;
|
||||||
|
|
||||||
|
hp)
|
||||||
|
# This case exists only to let depend.m4 do its work. It works by
|
||||||
|
# looking at the text of this script. This case will never be run,
|
||||||
|
# since it is checked for above.
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
|
||||||
|
sgi)
|
||||||
|
if test "$libtool" = yes; then
|
||||||
|
"$@" "-Wp,-MDupdate,$tmpdepfile"
|
||||||
|
else
|
||||||
|
"$@" -MDupdate "$tmpdepfile"
|
||||||
|
fi
|
||||||
|
stat=$?
|
||||||
|
if test $stat -ne 0; then
|
||||||
|
rm -f "$tmpdepfile"
|
||||||
|
exit $stat
|
||||||
|
fi
|
||||||
|
rm -f "$depfile"
|
||||||
|
|
||||||
|
if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
|
||||||
|
echo "$object : \\" > "$depfile"
|
||||||
|
# Clip off the initial element (the dependent). Don't try to be
|
||||||
|
# clever and replace this with sed code, as IRIX sed won't handle
|
||||||
|
# lines with more than a fixed number of characters (4096 in
|
||||||
|
# IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
|
||||||
|
# the IRIX cc adds comments like '#:fec' to the end of the
|
||||||
|
# dependency line.
|
||||||
|
tr ' ' "$nl" < "$tmpdepfile" \
|
||||||
|
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \
|
||||||
|
| tr "$nl" ' ' >> "$depfile"
|
||||||
|
echo >> "$depfile"
|
||||||
|
# The second pass generates a dummy entry for each header file.
|
||||||
|
tr ' ' "$nl" < "$tmpdepfile" \
|
||||||
|
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
|
||||||
|
>> "$depfile"
|
||||||
|
else
|
||||||
|
make_dummy_depfile
|
||||||
|
fi
|
||||||
|
rm -f "$tmpdepfile"
|
||||||
|
;;
|
||||||
|
|
||||||
|
xlc)
|
||||||
|
# This case exists only to let depend.m4 do its work. It works by
|
||||||
|
# looking at the text of this script. This case will never be run,
|
||||||
|
# since it is checked for above.
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
|
||||||
|
aix)
|
||||||
|
# The C for AIX Compiler uses -M and outputs the dependencies
|
||||||
|
# in a .u file. In older versions, this file always lives in the
|
||||||
|
# current directory. Also, the AIX compiler puts '$object:' at the
|
||||||
|
# start of each line; $object doesn't have directory information.
|
||||||
|
# Version 6 uses the directory in both cases.
|
||||||
|
set_dir_from "$object"
|
||||||
|
set_base_from "$object"
|
||||||
|
if test "$libtool" = yes; then
|
||||||
|
tmpdepfile1=$dir$base.u
|
||||||
|
tmpdepfile2=$base.u
|
||||||
|
tmpdepfile3=$dir.libs/$base.u
|
||||||
|
"$@" -Wc,-M
|
||||||
|
else
|
||||||
|
tmpdepfile1=$dir$base.u
|
||||||
|
tmpdepfile2=$dir$base.u
|
||||||
|
tmpdepfile3=$dir$base.u
|
||||||
|
"$@" -M
|
||||||
|
fi
|
||||||
|
stat=$?
|
||||||
|
if test $stat -ne 0; then
|
||||||
|
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||||
|
exit $stat
|
||||||
|
fi
|
||||||
|
|
||||||
|
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||||
|
do
|
||||||
|
test -f "$tmpdepfile" && break
|
||||||
|
done
|
||||||
|
aix_post_process_depfile
|
||||||
|
;;
|
||||||
|
|
||||||
|
tcc)
|
||||||
|
# tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26
|
||||||
|
# FIXME: That version still under development at the moment of writing.
|
||||||
|
# Make that this statement remains true also for stable, released
|
||||||
|
# versions.
|
||||||
|
# It will wrap lines (doesn't matter whether long or short) with a
|
||||||
|
# trailing '\', as in:
|
||||||
|
#
|
||||||
|
# foo.o : \
|
||||||
|
# foo.c \
|
||||||
|
# foo.h \
|
||||||
|
#
|
||||||
|
# It will put a trailing '\' even on the last line, and will use leading
|
||||||
|
# spaces rather than leading tabs (at least since its commit 0394caf7
|
||||||
|
# "Emit spaces for -MD").
|
||||||
|
"$@" -MD -MF "$tmpdepfile"
|
||||||
|
stat=$?
|
||||||
|
if test $stat -ne 0; then
|
||||||
|
rm -f "$tmpdepfile"
|
||||||
|
exit $stat
|
||||||
|
fi
|
||||||
|
rm -f "$depfile"
|
||||||
|
# Each non-empty line is of the form 'foo.o : \' or ' dep.h \'.
|
||||||
|
# We have to change lines of the first kind to '$object: \'.
|
||||||
|
sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile"
|
||||||
|
# And for each line of the second kind, we have to emit a 'dep.h:'
|
||||||
|
# dummy dependency, to avoid the deleted-header problem.
|
||||||
|
sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile"
|
||||||
|
rm -f "$tmpdepfile"
|
||||||
|
;;
|
||||||
|
|
||||||
|
## The order of this option in the case statement is important, since the
|
||||||
|
## shell code in configure will try each of these formats in the order
|
||||||
|
## listed in this file. A plain '-MD' option would be understood by many
|
||||||
|
## compilers, so we must ensure this comes after the gcc and icc options.
|
||||||
|
pgcc)
|
||||||
|
# Portland's C compiler understands '-MD'.
|
||||||
|
# Will always output deps to 'file.d' where file is the root name of the
|
||||||
|
# source file under compilation, even if file resides in a subdirectory.
|
||||||
|
# The object file name does not affect the name of the '.d' file.
|
||||||
|
# pgcc 10.2 will output
|
||||||
|
# foo.o: sub/foo.c sub/foo.h
|
||||||
|
# and will wrap long lines using '\' :
|
||||||
|
# foo.o: sub/foo.c ... \
|
||||||
|
# sub/foo.h ... \
|
||||||
|
# ...
|
||||||
|
set_dir_from "$object"
|
||||||
|
# Use the source, not the object, to determine the base name, since
|
||||||
|
# that's sadly what pgcc will do too.
|
||||||
|
set_base_from "$source"
|
||||||
|
tmpdepfile=$base.d
|
||||||
|
|
||||||
|
# For projects that build the same source file twice into different object
|
||||||
|
# files, the pgcc approach of using the *source* file root name can cause
|
||||||
|
# problems in parallel builds. Use a locking strategy to avoid stomping on
|
||||||
|
# the same $tmpdepfile.
|
||||||
|
lockdir=$base.d-lock
|
||||||
|
trap "
|
||||||
|
echo '$0: caught signal, cleaning up...' >&2
|
||||||
|
rmdir '$lockdir'
|
||||||
|
exit 1
|
||||||
|
" 1 2 13 15
|
||||||
|
numtries=100
|
||||||
|
i=$numtries
|
||||||
|
while test $i -gt 0; do
|
||||||
|
# mkdir is a portable test-and-set.
|
||||||
|
if mkdir "$lockdir" 2>/dev/null; then
|
||||||
|
# This process acquired the lock.
|
||||||
|
"$@" -MD
|
||||||
|
stat=$?
|
||||||
|
# Release the lock.
|
||||||
|
rmdir "$lockdir"
|
||||||
|
break
|
||||||
|
else
|
||||||
|
# If the lock is being held by a different process, wait
|
||||||
|
# until the winning process is done or we timeout.
|
||||||
|
while test -d "$lockdir" && test $i -gt 0; do
|
||||||
|
sleep 1
|
||||||
|
i=`expr $i - 1`
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
i=`expr $i - 1`
|
||||||
|
done
|
||||||
|
trap - 1 2 13 15
|
||||||
|
if test $i -le 0; then
|
||||||
|
echo "$0: failed to acquire lock after $numtries attempts" >&2
|
||||||
|
echo "$0: check lockdir '$lockdir'" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test $stat -ne 0; then
|
||||||
|
rm -f "$tmpdepfile"
|
||||||
|
exit $stat
|
||||||
|
fi
|
||||||
|
rm -f "$depfile"
|
||||||
|
# Each line is of the form `foo.o: dependent.h',
|
||||||
|
# or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
|
||||||
|
# Do two passes, one to just change these to
|
||||||
|
# `$object: dependent.h' and one to simply `dependent.h:'.
|
||||||
|
sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
|
||||||
|
# Some versions of the HPUX 10.20 sed can't process this invocation
|
||||||
|
# correctly. Breaking it into two sed invocations is a workaround.
|
||||||
|
sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \
|
||||||
|
| sed -e 's/$/ :/' >> "$depfile"
|
||||||
|
rm -f "$tmpdepfile"
|
||||||
|
;;
|
||||||
|
|
||||||
|
hp2)
|
||||||
|
# The "hp" stanza above does not work with aCC (C++) and HP's ia64
|
||||||
|
# compilers, which have integrated preprocessors. The correct option
|
||||||
|
# to use with these is +Maked; it writes dependencies to a file named
|
||||||
|
# 'foo.d', which lands next to the object file, wherever that
|
||||||
|
# happens to be.
|
||||||
|
# Much of this is similar to the tru64 case; see comments there.
|
||||||
|
set_dir_from "$object"
|
||||||
|
set_base_from "$object"
|
||||||
|
if test "$libtool" = yes; then
|
||||||
|
tmpdepfile1=$dir$base.d
|
||||||
|
tmpdepfile2=$dir.libs/$base.d
|
||||||
|
"$@" -Wc,+Maked
|
||||||
|
else
|
||||||
|
tmpdepfile1=$dir$base.d
|
||||||
|
tmpdepfile2=$dir$base.d
|
||||||
|
"$@" +Maked
|
||||||
|
fi
|
||||||
|
stat=$?
|
||||||
|
if test $stat -ne 0; then
|
||||||
|
rm -f "$tmpdepfile1" "$tmpdepfile2"
|
||||||
|
exit $stat
|
||||||
|
fi
|
||||||
|
|
||||||
|
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
|
||||||
|
do
|
||||||
|
test -f "$tmpdepfile" && break
|
||||||
|
done
|
||||||
|
if test -f "$tmpdepfile"; then
|
||||||
|
sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile"
|
||||||
|
# Add 'dependent.h:' lines.
|
||||||
|
sed -ne '2,${
|
||||||
|
s/^ *//
|
||||||
|
s/ \\*$//
|
||||||
|
s/$/:/
|
||||||
|
p
|
||||||
|
}' "$tmpdepfile" >> "$depfile"
|
||||||
|
else
|
||||||
|
make_dummy_depfile
|
||||||
|
fi
|
||||||
|
rm -f "$tmpdepfile" "$tmpdepfile2"
|
||||||
|
;;
|
||||||
|
|
||||||
|
tru64)
|
||||||
|
# The Tru64 compiler uses -MD to generate dependencies as a side
|
||||||
|
# effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'.
|
||||||
|
# At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
|
||||||
|
# dependencies in 'foo.d' instead, so we check for that too.
|
||||||
|
# Subdirectories are respected.
|
||||||
|
set_dir_from "$object"
|
||||||
|
set_base_from "$object"
|
||||||
|
|
||||||
|
if test "$libtool" = yes; then
|
||||||
|
# Libtool generates 2 separate objects for the 2 libraries. These
|
||||||
|
# two compilations output dependencies in $dir.libs/$base.o.d and
|
||||||
|
# in $dir$base.o.d. We have to check for both files, because
|
||||||
|
# one of the two compilations can be disabled. We should prefer
|
||||||
|
# $dir$base.o.d over $dir.libs/$base.o.d because the latter is
|
||||||
|
# automatically cleaned when .libs/ is deleted, while ignoring
|
||||||
|
# the former would cause a distcleancheck panic.
|
||||||
|
tmpdepfile1=$dir$base.o.d # libtool 1.5
|
||||||
|
tmpdepfile2=$dir.libs/$base.o.d # Likewise.
|
||||||
|
tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504
|
||||||
|
"$@" -Wc,-MD
|
||||||
|
else
|
||||||
|
tmpdepfile1=$dir$base.d
|
||||||
|
tmpdepfile2=$dir$base.d
|
||||||
|
tmpdepfile3=$dir$base.d
|
||||||
|
"$@" -MD
|
||||||
|
fi
|
||||||
|
|
||||||
|
stat=$?
|
||||||
|
if test $stat -ne 0; then
|
||||||
|
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||||
|
exit $stat
|
||||||
|
fi
|
||||||
|
|
||||||
|
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||||
|
do
|
||||||
|
test -f "$tmpdepfile" && break
|
||||||
|
done
|
||||||
|
# Same post-processing that is required for AIX mode.
|
||||||
|
aix_post_process_depfile
|
||||||
|
;;
|
||||||
|
|
||||||
|
msvc7)
|
||||||
|
if test "$libtool" = yes; then
|
||||||
|
showIncludes=-Wc,-showIncludes
|
||||||
|
else
|
||||||
|
showIncludes=-showIncludes
|
||||||
|
fi
|
||||||
|
"$@" $showIncludes > "$tmpdepfile"
|
||||||
|
stat=$?
|
||||||
|
grep -v '^Note: including file: ' "$tmpdepfile"
|
||||||
|
if test $stat -ne 0; then
|
||||||
|
rm -f "$tmpdepfile"
|
||||||
|
exit $stat
|
||||||
|
fi
|
||||||
|
rm -f "$depfile"
|
||||||
|
echo "$object : \\" > "$depfile"
|
||||||
|
# The first sed program below extracts the file names and escapes
|
||||||
|
# backslashes for cygpath. The second sed program outputs the file
|
||||||
|
# name when reading, but also accumulates all include files in the
|
||||||
|
# hold buffer in order to output them again at the end. This only
|
||||||
|
# works with sed implementations that can handle large buffers.
|
||||||
|
sed < "$tmpdepfile" -n '
|
||||||
|
/^Note: including file: *\(.*\)/ {
|
||||||
|
s//\1/
|
||||||
|
s/\\/\\\\/g
|
||||||
|
p
|
||||||
|
}' | $cygpath_u | sort -u | sed -n '
|
||||||
|
s/ /\\ /g
|
||||||
|
s/\(.*\)/'"$tab"'\1 \\/p
|
||||||
|
s/.\(.*\) \\/\1:/
|
||||||
|
H
|
||||||
|
$ {
|
||||||
|
s/.*/'"$tab"'/
|
||||||
|
G
|
||||||
|
p
|
||||||
|
}' >> "$depfile"
|
||||||
|
echo >> "$depfile" # make sure the fragment doesn't end with a backslash
|
||||||
|
rm -f "$tmpdepfile"
|
||||||
|
;;
|
||||||
|
|
||||||
|
msvc7msys)
|
||||||
|
# This case exists only to let depend.m4 do its work. It works by
|
||||||
|
# looking at the text of this script. This case will never be run,
|
||||||
|
# since it is checked for above.
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
|
||||||
|
#nosideeffect)
|
||||||
|
# This comment above is used by automake to tell side-effect
|
||||||
|
# dependency tracking mechanisms from slower ones.
|
||||||
|
|
||||||
|
dashmstdout)
|
||||||
|
# Important note: in order to support this mode, a compiler *must*
|
||||||
|
# always write the preprocessed file to stdout, regardless of -o.
|
||||||
|
"$@" || exit $?
|
||||||
|
|
||||||
|
# Remove the call to Libtool.
|
||||||
|
if test "$libtool" = yes; then
|
||||||
|
while test "X$1" != 'X--mode=compile'; do
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Remove '-o $object'.
|
||||||
|
IFS=" "
|
||||||
|
for arg
|
||||||
|
do
|
||||||
|
case $arg in
|
||||||
|
-o)
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
$object)
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
set fnord "$@" "$arg"
|
||||||
|
shift # fnord
|
||||||
|
shift # $arg
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
test -z "$dashmflag" && dashmflag=-M
|
||||||
|
# Require at least two characters before searching for ':'
|
||||||
|
# in the target name. This is to cope with DOS-style filenames:
|
||||||
|
# a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise.
|
||||||
|
"$@" $dashmflag |
|
||||||
|
sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile"
|
||||||
|
rm -f "$depfile"
|
||||||
|
cat < "$tmpdepfile" > "$depfile"
|
||||||
|
# Some versions of the HPUX 10.20 sed can't process this sed invocation
|
||||||
|
# correctly. Breaking it into two sed invocations is a workaround.
|
||||||
|
tr ' ' "$nl" < "$tmpdepfile" \
|
||||||
|
| sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
|
||||||
|
| sed -e 's/$/ :/' >> "$depfile"
|
||||||
|
rm -f "$tmpdepfile"
|
||||||
|
;;
|
||||||
|
|
||||||
|
dashXmstdout)
|
||||||
|
# This case only exists to satisfy depend.m4. It is never actually
|
||||||
|
# run, as this mode is specially recognized in the preamble.
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
|
||||||
|
makedepend)
|
||||||
|
"$@" || exit $?
|
||||||
|
# Remove any Libtool call
|
||||||
|
if test "$libtool" = yes; then
|
||||||
|
while test "X$1" != 'X--mode=compile'; do
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
# X makedepend
|
||||||
|
shift
|
||||||
|
cleared=no eat=no
|
||||||
|
for arg
|
||||||
|
do
|
||||||
|
case $cleared in
|
||||||
|
no)
|
||||||
|
set ""; shift
|
||||||
|
cleared=yes ;;
|
||||||
|
esac
|
||||||
|
if test $eat = yes; then
|
||||||
|
eat=no
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
case "$arg" in
|
||||||
|
-D*|-I*)
|
||||||
|
set fnord "$@" "$arg"; shift ;;
|
||||||
|
# Strip any option that makedepend may not understand. Remove
|
||||||
|
# the object too, otherwise makedepend will parse it as a source file.
|
||||||
|
-arch)
|
||||||
|
eat=yes ;;
|
||||||
|
-*|$object)
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
set fnord "$@" "$arg"; shift ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
obj_suffix=`echo "$object" | sed 's/^.*\././'`
|
||||||
|
touch "$tmpdepfile"
|
||||||
|
${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
|
||||||
|
rm -f "$depfile"
|
||||||
|
# makedepend may prepend the VPATH from the source file name to the object.
|
||||||
|
# No need to regex-escape $object, excess matching of '.' is harmless.
|
||||||
|
sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile"
|
||||||
|
# Some versions of the HPUX 10.20 sed can't process the last invocation
|
||||||
|
# correctly. Breaking it into two sed invocations is a workaround.
|
||||||
|
sed '1,2d' "$tmpdepfile" \
|
||||||
|
| tr ' ' "$nl" \
|
||||||
|
| sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
|
||||||
|
| sed -e 's/$/ :/' >> "$depfile"
|
||||||
|
rm -f "$tmpdepfile" "$tmpdepfile".bak
|
||||||
|
;;
|
||||||
|
|
||||||
|
cpp)
|
||||||
|
# Important note: in order to support this mode, a compiler *must*
|
||||||
|
# always write the preprocessed file to stdout.
|
||||||
|
"$@" || exit $?
|
||||||
|
|
||||||
|
# Remove the call to Libtool.
|
||||||
|
if test "$libtool" = yes; then
|
||||||
|
while test "X$1" != 'X--mode=compile'; do
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Remove '-o $object'.
|
||||||
|
IFS=" "
|
||||||
|
for arg
|
||||||
|
do
|
||||||
|
case $arg in
|
||||||
|
-o)
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
$object)
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
set fnord "$@" "$arg"
|
||||||
|
shift # fnord
|
||||||
|
shift # $arg
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
"$@" -E \
|
||||||
|
| sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
|
||||||
|
-e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
|
||||||
|
| sed '$ s: \\$::' > "$tmpdepfile"
|
||||||
|
rm -f "$depfile"
|
||||||
|
echo "$object : \\" > "$depfile"
|
||||||
|
cat < "$tmpdepfile" >> "$depfile"
|
||||||
|
sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
|
||||||
|
rm -f "$tmpdepfile"
|
||||||
|
;;
|
||||||
|
|
||||||
|
msvisualcpp)
|
||||||
|
# Important note: in order to support this mode, a compiler *must*
|
||||||
|
# always write the preprocessed file to stdout.
|
||||||
|
"$@" || exit $?
|
||||||
|
|
||||||
|
# Remove the call to Libtool.
|
||||||
|
if test "$libtool" = yes; then
|
||||||
|
while test "X$1" != 'X--mode=compile'; do
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
|
||||||
|
IFS=" "
|
||||||
|
for arg
|
||||||
|
do
|
||||||
|
case "$arg" in
|
||||||
|
-o)
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
$object)
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
"-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
|
||||||
|
set fnord "$@"
|
||||||
|
shift
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
set fnord "$@" "$arg"
|
||||||
|
shift
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
"$@" -E 2>/dev/null |
|
||||||
|
sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
|
||||||
|
rm -f "$depfile"
|
||||||
|
echo "$object : \\" > "$depfile"
|
||||||
|
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile"
|
||||||
|
echo "$tab" >> "$depfile"
|
||||||
|
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
|
||||||
|
rm -f "$tmpdepfile"
|
||||||
|
;;
|
||||||
|
|
||||||
|
msvcmsys)
|
||||||
|
# This case exists only to let depend.m4 do its work. It works by
|
||||||
|
# looking at the text of this script. This case will never be run,
|
||||||
|
# since it is checked for above.
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
|
||||||
|
none)
|
||||||
|
exec "$@"
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
echo "Unknown depmode $depmode" 1>&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
exit 0
|
||||||
|
|
||||||
|
# Local Variables:
|
||||||
|
# mode: shell-script
|
||||||
|
# sh-indentation: 2
|
||||||
|
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||||
|
# time-stamp-start: "scriptversion="
|
||||||
|
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||||
|
# time-stamp-time-zone: "UTC"
|
||||||
|
# time-stamp-end: "; # UTC"
|
||||||
|
# End:
|
|
@ -0,0 +1,25 @@
|
||||||
|
# Process this file with automake to create Makefile.in.
|
||||||
|
|
||||||
|
SUBDIRS = . example
|
||||||
|
|
||||||
|
doc_DATA = \
|
||||||
|
README.DAEMON README.polkit
|
||||||
|
|
||||||
|
man_MANS = pcscd.8 reader.conf.5
|
||||||
|
man_in = pcscd.8.in reader.conf.5.in
|
||||||
|
|
||||||
|
EXTRA_DIST = $(doc_DATA) $(man_in) doxygen.conf.in formaticc.1 \
|
||||||
|
org.debian.pcsc-lite.policy
|
||||||
|
|
||||||
|
doxygen:
|
||||||
|
rm -fr api ; cd .. ; doxygen doc/doxygen.conf
|
||||||
|
# cp doxygen.css api/
|
||||||
|
|
||||||
|
if ENABLE_POLKIT
|
||||||
|
install-data-hook:
|
||||||
|
$(MKDIR_P) $(DESTDIR)/$(POLICY_DIR)
|
||||||
|
$(INSTALL_DATA) $(srcdir)/org.debian.pcsc-lite.policy $(DESTDIR)/$(POLICY_DIR)
|
||||||
|
|
||||||
|
uninstall-hook:
|
||||||
|
rm $(DESTDIR)/$(POLICY_DIR)/org.debian.pcsc-lite.policy
|
||||||
|
endif
|
|
@ -0,0 +1,834 @@
|
||||||
|
# Makefile.in generated by automake 1.15 from Makefile.am.
|
||||||
|
# @configure_input@
|
||||||
|
|
||||||
|
# Copyright (C) 1994-2014 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
# This Makefile.in is free software; the Free Software Foundation
|
||||||
|
# gives unlimited permission to copy and/or distribute it,
|
||||||
|
# with or without modifications, as long as this notice is preserved.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||||
|
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||||
|
# PARTICULAR PURPOSE.
|
||||||
|
|
||||||
|
@SET_MAKE@
|
||||||
|
|
||||||
|
# Process this file with automake to create Makefile.in.
|
||||||
|
|
||||||
|
VPATH = @srcdir@
|
||||||
|
am__is_gnu_make = { \
|
||||||
|
if test -z '$(MAKELEVEL)'; then \
|
||||||
|
false; \
|
||||||
|
elif test -n '$(MAKE_HOST)'; then \
|
||||||
|
true; \
|
||||||
|
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
|
||||||
|
true; \
|
||||||
|
else \
|
||||||
|
false; \
|
||||||
|
fi; \
|
||||||
|
}
|
||||||
|
am__make_running_with_option = \
|
||||||
|
case $${target_option-} in \
|
||||||
|
?) ;; \
|
||||||
|
*) echo "am__make_running_with_option: internal error: invalid" \
|
||||||
|
"target option '$${target_option-}' specified" >&2; \
|
||||||
|
exit 1;; \
|
||||||
|
esac; \
|
||||||
|
has_opt=no; \
|
||||||
|
sane_makeflags=$$MAKEFLAGS; \
|
||||||
|
if $(am__is_gnu_make); then \
|
||||||
|
sane_makeflags=$$MFLAGS; \
|
||||||
|
else \
|
||||||
|
case $$MAKEFLAGS in \
|
||||||
|
*\\[\ \ ]*) \
|
||||||
|
bs=\\; \
|
||||||
|
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
|
||||||
|
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
|
||||||
|
esac; \
|
||||||
|
fi; \
|
||||||
|
skip_next=no; \
|
||||||
|
strip_trailopt () \
|
||||||
|
{ \
|
||||||
|
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
|
||||||
|
}; \
|
||||||
|
for flg in $$sane_makeflags; do \
|
||||||
|
test $$skip_next = yes && { skip_next=no; continue; }; \
|
||||||
|
case $$flg in \
|
||||||
|
*=*|--*) continue;; \
|
||||||
|
-*I) strip_trailopt 'I'; skip_next=yes;; \
|
||||||
|
-*I?*) strip_trailopt 'I';; \
|
||||||
|
-*O) strip_trailopt 'O'; skip_next=yes;; \
|
||||||
|
-*O?*) strip_trailopt 'O';; \
|
||||||
|
-*l) strip_trailopt 'l'; skip_next=yes;; \
|
||||||
|
-*l?*) strip_trailopt 'l';; \
|
||||||
|
-[dEDm]) skip_next=yes;; \
|
||||||
|
-[JT]) skip_next=yes;; \
|
||||||
|
esac; \
|
||||||
|
case $$flg in \
|
||||||
|
*$$target_option*) has_opt=yes; break;; \
|
||||||
|
esac; \
|
||||||
|
done; \
|
||||||
|
test $$has_opt = yes
|
||||||
|
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
|
||||||
|
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
|
||||||
|
pkgdatadir = $(datadir)/@PACKAGE@
|
||||||
|
pkgincludedir = $(includedir)/@PACKAGE@
|
||||||
|
pkglibdir = $(libdir)/@PACKAGE@
|
||||||
|
pkglibexecdir = $(libexecdir)/@PACKAGE@
|
||||||
|
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||||
|
install_sh_DATA = $(install_sh) -c -m 644
|
||||||
|
install_sh_PROGRAM = $(install_sh) -c
|
||||||
|
install_sh_SCRIPT = $(install_sh) -c
|
||||||
|
INSTALL_HEADER = $(INSTALL_DATA)
|
||||||
|
transform = $(program_transform_name)
|
||||||
|
NORMAL_INSTALL = :
|
||||||
|
PRE_INSTALL = :
|
||||||
|
POST_INSTALL = :
|
||||||
|
NORMAL_UNINSTALL = :
|
||||||
|
PRE_UNINSTALL = :
|
||||||
|
POST_UNINSTALL = :
|
||||||
|
build_triplet = @build@
|
||||||
|
host_triplet = @host@
|
||||||
|
subdir = doc
|
||||||
|
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||||
|
am__aclocal_m4_deps = $(top_srcdir)/m4/as-ac-expand.m4 \
|
||||||
|
$(top_srcdir)/m4/ax_pthread.m4 $(top_srcdir)/m4/libtool.m4 \
|
||||||
|
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
|
||||||
|
$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
|
||||||
|
$(top_srcdir)/configure.ac
|
||||||
|
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||||
|
$(ACLOCAL_M4)
|
||||||
|
DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
|
||||||
|
mkinstalldirs = $(install_sh) -d
|
||||||
|
CONFIG_HEADER = $(top_builddir)/config.h
|
||||||
|
CONFIG_CLEAN_FILES = doxygen.conf pcscd.8 reader.conf.5
|
||||||
|
CONFIG_CLEAN_VPATH_FILES =
|
||||||
|
AM_V_P = $(am__v_P_@AM_V@)
|
||||||
|
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
|
||||||
|
am__v_P_0 = false
|
||||||
|
am__v_P_1 = :
|
||||||
|
AM_V_GEN = $(am__v_GEN_@AM_V@)
|
||||||
|
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
|
||||||
|
am__v_GEN_0 = @echo " GEN " $@;
|
||||||
|
am__v_GEN_1 =
|
||||||
|
AM_V_at = $(am__v_at_@AM_V@)
|
||||||
|
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
|
||||||
|
am__v_at_0 = @
|
||||||
|
am__v_at_1 =
|
||||||
|
SOURCES =
|
||||||
|
DIST_SOURCES =
|
||||||
|
RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
|
||||||
|
ctags-recursive dvi-recursive html-recursive info-recursive \
|
||||||
|
install-data-recursive install-dvi-recursive \
|
||||||
|
install-exec-recursive install-html-recursive \
|
||||||
|
install-info-recursive install-pdf-recursive \
|
||||||
|
install-ps-recursive install-recursive installcheck-recursive \
|
||||||
|
installdirs-recursive pdf-recursive ps-recursive \
|
||||||
|
tags-recursive uninstall-recursive
|
||||||
|
am__can_run_installinfo = \
|
||||||
|
case $$AM_UPDATE_INFO_DIR in \
|
||||||
|
n|no|NO) false;; \
|
||||||
|
*) (install-info --version) >/dev/null 2>&1;; \
|
||||||
|
esac
|
||||||
|
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
|
||||||
|
am__vpath_adj = case $$p in \
|
||||||
|
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
|
||||||
|
*) f=$$p;; \
|
||||||
|
esac;
|
||||||
|
am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
|
||||||
|
am__install_max = 40
|
||||||
|
am__nobase_strip_setup = \
|
||||||
|
srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
|
||||||
|
am__nobase_strip = \
|
||||||
|
for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
|
||||||
|
am__nobase_list = $(am__nobase_strip_setup); \
|
||||||
|
for p in $$list; do echo "$$p $$p"; done | \
|
||||||
|
sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
|
||||||
|
$(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
|
||||||
|
if (++n[$$2] == $(am__install_max)) \
|
||||||
|
{ print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
|
||||||
|
END { for (dir in files) print dir, files[dir] }'
|
||||||
|
am__base_list = \
|
||||||
|
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
|
||||||
|
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
|
||||||
|
am__uninstall_files_from_dir = { \
|
||||||
|
test -z "$$files" \
|
||||||
|
|| { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
|
||||||
|
|| { echo " ( cd '$$dir' && rm -f" $$files ")"; \
|
||||||
|
$(am__cd) "$$dir" && rm -f $$files; }; \
|
||||||
|
}
|
||||||
|
man5dir = $(mandir)/man5
|
||||||
|
am__installdirs = "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(man8dir)" \
|
||||||
|
"$(DESTDIR)$(docdir)"
|
||||||
|
man8dir = $(mandir)/man8
|
||||||
|
NROFF = nroff
|
||||||
|
MANS = $(man_MANS)
|
||||||
|
DATA = $(doc_DATA)
|
||||||
|
RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
|
||||||
|
distclean-recursive maintainer-clean-recursive
|
||||||
|
am__recursive_targets = \
|
||||||
|
$(RECURSIVE_TARGETS) \
|
||||||
|
$(RECURSIVE_CLEAN_TARGETS) \
|
||||||
|
$(am__extra_recursive_targets)
|
||||||
|
AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
|
||||||
|
distdir
|
||||||
|
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
|
||||||
|
# Read a list of newline-separated strings from the standard input,
|
||||||
|
# and print each of them once, without duplicates. Input order is
|
||||||
|
# *not* preserved.
|
||||||
|
am__uniquify_input = $(AWK) '\
|
||||||
|
BEGIN { nonempty = 0; } \
|
||||||
|
{ items[$$0] = 1; nonempty = 1; } \
|
||||||
|
END { if (nonempty) { for (i in items) print i; }; } \
|
||||||
|
'
|
||||||
|
# Make sure the list of sources is unique. This is necessary because,
|
||||||
|
# e.g., the same source file might be shared among _SOURCES variables
|
||||||
|
# for different programs/libraries.
|
||||||
|
am__define_uniq_tagged_files = \
|
||||||
|
list='$(am__tagged_files)'; \
|
||||||
|
unique=`for i in $$list; do \
|
||||||
|
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||||
|
done | $(am__uniquify_input)`
|
||||||
|
ETAGS = etags
|
||||||
|
CTAGS = ctags
|
||||||
|
DIST_SUBDIRS = $(SUBDIRS)
|
||||||
|
am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/doxygen.conf.in \
|
||||||
|
$(srcdir)/pcscd.8.in $(srcdir)/reader.conf.5.in
|
||||||
|
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||||
|
am__relativize = \
|
||||||
|
dir0=`pwd`; \
|
||||||
|
sed_first='s,^\([^/]*\)/.*$$,\1,'; \
|
||||||
|
sed_rest='s,^[^/]*/*,,'; \
|
||||||
|
sed_last='s,^.*/\([^/]*\)$$,\1,'; \
|
||||||
|
sed_butlast='s,/*[^/]*$$,,'; \
|
||||||
|
while test -n "$$dir1"; do \
|
||||||
|
first=`echo "$$dir1" | sed -e "$$sed_first"`; \
|
||||||
|
if test "$$first" != "."; then \
|
||||||
|
if test "$$first" = ".."; then \
|
||||||
|
dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
|
||||||
|
dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
|
||||||
|
else \
|
||||||
|
first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
|
||||||
|
if test "$$first2" = "$$first"; then \
|
||||||
|
dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
|
||||||
|
else \
|
||||||
|
dir2="../$$dir2"; \
|
||||||
|
fi; \
|
||||||
|
dir0="$$dir0"/"$$first"; \
|
||||||
|
fi; \
|
||||||
|
fi; \
|
||||||
|
dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
|
||||||
|
done; \
|
||||||
|
reldir="$$dir2"
|
||||||
|
ACLOCAL = @ACLOCAL@
|
||||||
|
ALLOCA = @ALLOCA@
|
||||||
|
AMTAR = @AMTAR@
|
||||||
|
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
|
||||||
|
AR = @AR@
|
||||||
|
AUTOCONF = @AUTOCONF@
|
||||||
|
AUTOHEADER = @AUTOHEADER@
|
||||||
|
AUTOMAKE = @AUTOMAKE@
|
||||||
|
AWK = @AWK@
|
||||||
|
CC = @CC@
|
||||||
|
CCDEPMODE = @CCDEPMODE@
|
||||||
|
CFLAGS = @CFLAGS@
|
||||||
|
COREFOUNDATION = @COREFOUNDATION@
|
||||||
|
CPP = @CPP@
|
||||||
|
CPPFLAGS = @CPPFLAGS@
|
||||||
|
CYGPATH_W = @CYGPATH_W@
|
||||||
|
DEFS = @DEFS@
|
||||||
|
DEPDIR = @DEPDIR@
|
||||||
|
DLLTOOL = @DLLTOOL@
|
||||||
|
DSYMUTIL = @DSYMUTIL@
|
||||||
|
DUMPBIN = @DUMPBIN@
|
||||||
|
ECHO_C = @ECHO_C@
|
||||||
|
ECHO_N = @ECHO_N@
|
||||||
|
ECHO_T = @ECHO_T@
|
||||||
|
EGREP = @EGREP@
|
||||||
|
EXEEXT = @EXEEXT@
|
||||||
|
FGREP = @FGREP@
|
||||||
|
GREP = @GREP@
|
||||||
|
INSTALL = @INSTALL@
|
||||||
|
INSTALL_DATA = @INSTALL_DATA@
|
||||||
|
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||||
|
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||||
|
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||||
|
IOKIT = @IOKIT@
|
||||||
|
LD = @LD@
|
||||||
|
LDFLAGS = @LDFLAGS@
|
||||||
|
LEX = @LEX@
|
||||||
|
LEXLIB = @LEXLIB@
|
||||||
|
LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
|
||||||
|
LIBOBJS = @LIBOBJS@
|
||||||
|
LIBS = @LIBS@
|
||||||
|
LIBTOOL = @LIBTOOL@
|
||||||
|
LIBUDEV_CFLAGS = @LIBUDEV_CFLAGS@
|
||||||
|
LIBUDEV_LIBS = @LIBUDEV_LIBS@
|
||||||
|
LIBUSBCONFIG = @LIBUSBCONFIG@
|
||||||
|
LIBUSB_CFLAGS = @LIBUSB_CFLAGS@
|
||||||
|
LIBUSB_LIBS = @LIBUSB_LIBS@
|
||||||
|
LIPO = @LIPO@
|
||||||
|
LN_S = @LN_S@
|
||||||
|
LTLIBOBJS = @LTLIBOBJS@
|
||||||
|
LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
|
||||||
|
MAINT = @MAINT@
|
||||||
|
MAKEINFO = @MAKEINFO@
|
||||||
|
MANIFEST_TOOL = @MANIFEST_TOOL@
|
||||||
|
MKDIR_P = @MKDIR_P@
|
||||||
|
NM = @NM@
|
||||||
|
NMEDIT = @NMEDIT@
|
||||||
|
OBJDUMP = @OBJDUMP@
|
||||||
|
OBJEXT = @OBJEXT@
|
||||||
|
OTOOL = @OTOOL@
|
||||||
|
OTOOL64 = @OTOOL64@
|
||||||
|
PACKAGE = @PACKAGE@
|
||||||
|
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||||
|
PACKAGE_NAME = @PACKAGE_NAME@
|
||||||
|
PACKAGE_STRING = @PACKAGE_STRING@
|
||||||
|
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||||
|
PACKAGE_URL = @PACKAGE_URL@
|
||||||
|
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||||
|
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||||
|
PCSCLITE_CONFIG_DIR = @PCSCLITE_CONFIG_DIR@
|
||||||
|
PKG_CONFIG = @PKG_CONFIG@
|
||||||
|
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
|
||||||
|
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
|
||||||
|
POLICY_DIR = @POLICY_DIR@
|
||||||
|
POLKIT_CFLAGS = @POLKIT_CFLAGS@
|
||||||
|
POLKIT_LIBS = @POLKIT_LIBS@
|
||||||
|
PTHREAD_CC = @PTHREAD_CC@
|
||||||
|
PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
|
||||||
|
PTHREAD_LIBS = @PTHREAD_LIBS@
|
||||||
|
RANLIB = @RANLIB@
|
||||||
|
SED = @SED@
|
||||||
|
SET_MAKE = @SET_MAKE@
|
||||||
|
SHELL = @SHELL@
|
||||||
|
STRIP = @STRIP@
|
||||||
|
SYMBOL_VISIBILITY = @SYMBOL_VISIBILITY@
|
||||||
|
VERSION = @VERSION@
|
||||||
|
abs_builddir = @abs_builddir@
|
||||||
|
abs_srcdir = @abs_srcdir@
|
||||||
|
abs_top_builddir = @abs_top_builddir@
|
||||||
|
abs_top_srcdir = @abs_top_srcdir@
|
||||||
|
ac_ct_AR = @ac_ct_AR@
|
||||||
|
ac_ct_CC = @ac_ct_CC@
|
||||||
|
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
|
||||||
|
am__include = @am__include@
|
||||||
|
am__leading_dot = @am__leading_dot@
|
||||||
|
am__quote = @am__quote@
|
||||||
|
am__tar = @am__tar@
|
||||||
|
am__untar = @am__untar@
|
||||||
|
ax_pthread_config = @ax_pthread_config@
|
||||||
|
bindir = @bindir@
|
||||||
|
build = @build@
|
||||||
|
build_alias = @build_alias@
|
||||||
|
build_cpu = @build_cpu@
|
||||||
|
build_os = @build_os@
|
||||||
|
build_vendor = @build_vendor@
|
||||||
|
builddir = @builddir@
|
||||||
|
confdir_exp = @confdir_exp@
|
||||||
|
datadir = @datadir@
|
||||||
|
datarootdir = @datarootdir@
|
||||||
|
docdir = @docdir@
|
||||||
|
dvidir = @dvidir@
|
||||||
|
exec_prefix = @exec_prefix@
|
||||||
|
host = @host@
|
||||||
|
host_alias = @host_alias@
|
||||||
|
host_cpu = @host_cpu@
|
||||||
|
host_os = @host_os@
|
||||||
|
host_to_ccid_16 = @host_to_ccid_16@
|
||||||
|
host_to_ccid_32 = @host_to_ccid_32@
|
||||||
|
host_vendor = @host_vendor@
|
||||||
|
htmldir = @htmldir@
|
||||||
|
includedir = @includedir@
|
||||||
|
infodir = @infodir@
|
||||||
|
install_sh = @install_sh@
|
||||||
|
ipcdir = @ipcdir@
|
||||||
|
libdir = @libdir@
|
||||||
|
libexecdir = @libexecdir@
|
||||||
|
localedir = @localedir@
|
||||||
|
localstatedir = @localstatedir@
|
||||||
|
localstatedir_exp = @localstatedir_exp@
|
||||||
|
mandir = @mandir@
|
||||||
|
mkdir_p = @mkdir_p@
|
||||||
|
oldincludedir = @oldincludedir@
|
||||||
|
pdfdir = @pdfdir@
|
||||||
|
prefix = @prefix@
|
||||||
|
program_transform_name = @program_transform_name@
|
||||||
|
psdir = @psdir@
|
||||||
|
runstatedir = @runstatedir@
|
||||||
|
sbindir = @sbindir@
|
||||||
|
sbindir_exp = @sbindir_exp@
|
||||||
|
serialconfdir = @serialconfdir@
|
||||||
|
sharedstatedir = @sharedstatedir@
|
||||||
|
srcdir = @srcdir@
|
||||||
|
sysconfdir = @sysconfdir@
|
||||||
|
systemdsystemunitdir = @systemdsystemunitdir@
|
||||||
|
target_alias = @target_alias@
|
||||||
|
top_build_prefix = @top_build_prefix@
|
||||||
|
top_builddir = @top_builddir@
|
||||||
|
top_srcdir = @top_srcdir@
|
||||||
|
usbdropdir = @usbdropdir@
|
||||||
|
usbdropdir_exp = @usbdropdir_exp@
|
||||||
|
SUBDIRS = . example
|
||||||
|
doc_DATA = \
|
||||||
|
README.DAEMON README.polkit
|
||||||
|
|
||||||
|
man_MANS = pcscd.8 reader.conf.5
|
||||||
|
man_in = pcscd.8.in reader.conf.5.in
|
||||||
|
EXTRA_DIST = $(doc_DATA) $(man_in) doxygen.conf.in formaticc.1 \
|
||||||
|
org.debian.pcsc-lite.policy
|
||||||
|
|
||||||
|
all: all-recursive
|
||||||
|
|
||||||
|
.SUFFIXES:
|
||||||
|
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
|
||||||
|
@for dep in $?; do \
|
||||||
|
case '$(am__configure_deps)' in \
|
||||||
|
*$$dep*) \
|
||||||
|
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
|
||||||
|
&& { if test -f $@; then exit 0; else break; fi; }; \
|
||||||
|
exit 1;; \
|
||||||
|
esac; \
|
||||||
|
done; \
|
||||||
|
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu doc/Makefile'; \
|
||||||
|
$(am__cd) $(top_srcdir) && \
|
||||||
|
$(AUTOMAKE) --gnu doc/Makefile
|
||||||
|
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||||
|
@case '$?' in \
|
||||||
|
*config.status*) \
|
||||||
|
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
|
||||||
|
*) \
|
||||||
|
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
|
||||||
|
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
|
||||||
|
esac;
|
||||||
|
|
||||||
|
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||||
|
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||||
|
|
||||||
|
$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
|
||||||
|
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||||
|
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
|
||||||
|
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||||
|
$(am__aclocal_m4_deps):
|
||||||
|
doxygen.conf: $(top_builddir)/config.status $(srcdir)/doxygen.conf.in
|
||||||
|
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
|
||||||
|
pcscd.8: $(top_builddir)/config.status $(srcdir)/pcscd.8.in
|
||||||
|
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
|
||||||
|
reader.conf.5: $(top_builddir)/config.status $(srcdir)/reader.conf.5.in
|
||||||
|
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
|
||||||
|
|
||||||
|
mostlyclean-libtool:
|
||||||
|
-rm -f *.lo
|
||||||
|
|
||||||
|
clean-libtool:
|
||||||
|
-rm -rf .libs _libs
|
||||||
|
install-man5: $(man_MANS)
|
||||||
|
@$(NORMAL_INSTALL)
|
||||||
|
@list1=''; \
|
||||||
|
list2='$(man_MANS)'; \
|
||||||
|
test -n "$(man5dir)" \
|
||||||
|
&& test -n "`echo $$list1$$list2`" \
|
||||||
|
|| exit 0; \
|
||||||
|
echo " $(MKDIR_P) '$(DESTDIR)$(man5dir)'"; \
|
||||||
|
$(MKDIR_P) "$(DESTDIR)$(man5dir)" || exit 1; \
|
||||||
|
{ for i in $$list1; do echo "$$i"; done; \
|
||||||
|
if test -n "$$list2"; then \
|
||||||
|
for i in $$list2; do echo "$$i"; done \
|
||||||
|
| sed -n '/\.5[a-z]*$$/p'; \
|
||||||
|
fi; \
|
||||||
|
} | while read p; do \
|
||||||
|
if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
|
||||||
|
echo "$$d$$p"; echo "$$p"; \
|
||||||
|
done | \
|
||||||
|
sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \
|
||||||
|
-e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
|
||||||
|
sed 'N;N;s,\n, ,g' | { \
|
||||||
|
list=; while read file base inst; do \
|
||||||
|
if test "$$base" = "$$inst"; then list="$$list $$file"; else \
|
||||||
|
echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man5dir)/$$inst'"; \
|
||||||
|
$(INSTALL_DATA) "$$file" "$(DESTDIR)$(man5dir)/$$inst" || exit $$?; \
|
||||||
|
fi; \
|
||||||
|
done; \
|
||||||
|
for i in $$list; do echo "$$i"; done | $(am__base_list) | \
|
||||||
|
while read files; do \
|
||||||
|
test -z "$$files" || { \
|
||||||
|
echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man5dir)'"; \
|
||||||
|
$(INSTALL_DATA) $$files "$(DESTDIR)$(man5dir)" || exit $$?; }; \
|
||||||
|
done; }
|
||||||
|
|
||||||
|
uninstall-man5:
|
||||||
|
@$(NORMAL_UNINSTALL)
|
||||||
|
@list=''; test -n "$(man5dir)" || exit 0; \
|
||||||
|
files=`{ for i in $$list; do echo "$$i"; done; \
|
||||||
|
l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \
|
||||||
|
sed -n '/\.5[a-z]*$$/p'; \
|
||||||
|
} | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \
|
||||||
|
-e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
|
||||||
|
dir='$(DESTDIR)$(man5dir)'; $(am__uninstall_files_from_dir)
|
||||||
|
install-man8: $(man_MANS)
|
||||||
|
@$(NORMAL_INSTALL)
|
||||||
|
@list1=''; \
|
||||||
|
list2='$(man_MANS)'; \
|
||||||
|
test -n "$(man8dir)" \
|
||||||
|
&& test -n "`echo $$list1$$list2`" \
|
||||||
|
|| exit 0; \
|
||||||
|
echo " $(MKDIR_P) '$(DESTDIR)$(man8dir)'"; \
|
||||||
|
$(MKDIR_P) "$(DESTDIR)$(man8dir)" || exit 1; \
|
||||||
|
{ for i in $$list1; do echo "$$i"; done; \
|
||||||
|
if test -n "$$list2"; then \
|
||||||
|
for i in $$list2; do echo "$$i"; done \
|
||||||
|
| sed -n '/\.8[a-z]*$$/p'; \
|
||||||
|
fi; \
|
||||||
|
} | while read p; do \
|
||||||
|
if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
|
||||||
|
echo "$$d$$p"; echo "$$p"; \
|
||||||
|
done | \
|
||||||
|
sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \
|
||||||
|
-e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
|
||||||
|
sed 'N;N;s,\n, ,g' | { \
|
||||||
|
list=; while read file base inst; do \
|
||||||
|
if test "$$base" = "$$inst"; then list="$$list $$file"; else \
|
||||||
|
echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \
|
||||||
|
$(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst" || exit $$?; \
|
||||||
|
fi; \
|
||||||
|
done; \
|
||||||
|
for i in $$list; do echo "$$i"; done | $(am__base_list) | \
|
||||||
|
while read files; do \
|
||||||
|
test -z "$$files" || { \
|
||||||
|
echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man8dir)'"; \
|
||||||
|
$(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \
|
||||||
|
done; }
|
||||||
|
|
||||||
|
uninstall-man8:
|
||||||
|
@$(NORMAL_UNINSTALL)
|
||||||
|
@list=''; test -n "$(man8dir)" || exit 0; \
|
||||||
|
files=`{ for i in $$list; do echo "$$i"; done; \
|
||||||
|
l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \
|
||||||
|
sed -n '/\.8[a-z]*$$/p'; \
|
||||||
|
} | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \
|
||||||
|
-e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
|
||||||
|
dir='$(DESTDIR)$(man8dir)'; $(am__uninstall_files_from_dir)
|
||||||
|
install-docDATA: $(doc_DATA)
|
||||||
|
@$(NORMAL_INSTALL)
|
||||||
|
@list='$(doc_DATA)'; test -n "$(docdir)" || list=; \
|
||||||
|
if test -n "$$list"; then \
|
||||||
|
echo " $(MKDIR_P) '$(DESTDIR)$(docdir)'"; \
|
||||||
|
$(MKDIR_P) "$(DESTDIR)$(docdir)" || exit 1; \
|
||||||
|
fi; \
|
||||||
|
for p in $$list; do \
|
||||||
|
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
|
||||||
|
echo "$$d$$p"; \
|
||||||
|
done | $(am__base_list) | \
|
||||||
|
while read files; do \
|
||||||
|
echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(docdir)'"; \
|
||||||
|
$(INSTALL_DATA) $$files "$(DESTDIR)$(docdir)" || exit $$?; \
|
||||||
|
done
|
||||||
|
|
||||||
|
uninstall-docDATA:
|
||||||
|
@$(NORMAL_UNINSTALL)
|
||||||
|
@list='$(doc_DATA)'; test -n "$(docdir)" || list=; \
|
||||||
|
files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
|
||||||
|
dir='$(DESTDIR)$(docdir)'; $(am__uninstall_files_from_dir)
|
||||||
|
|
||||||
|
# This directory's subdirectories are mostly independent; you can cd
|
||||||
|
# into them and run 'make' without going through this Makefile.
|
||||||
|
# To change the values of 'make' variables: instead of editing Makefiles,
|
||||||
|
# (1) if the variable is set in 'config.status', edit 'config.status'
|
||||||
|
# (which will cause the Makefiles to be regenerated when you run 'make');
|
||||||
|
# (2) otherwise, pass the desired values on the 'make' command line.
|
||||||
|
$(am__recursive_targets):
|
||||||
|
@fail=; \
|
||||||
|
if $(am__make_keepgoing); then \
|
||||||
|
failcom='fail=yes'; \
|
||||||
|
else \
|
||||||
|
failcom='exit 1'; \
|
||||||
|
fi; \
|
||||||
|
dot_seen=no; \
|
||||||
|
target=`echo $@ | sed s/-recursive//`; \
|
||||||
|
case "$@" in \
|
||||||
|
distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
|
||||||
|
*) list='$(SUBDIRS)' ;; \
|
||||||
|
esac; \
|
||||||
|
for subdir in $$list; do \
|
||||||
|
echo "Making $$target in $$subdir"; \
|
||||||
|
if test "$$subdir" = "."; then \
|
||||||
|
dot_seen=yes; \
|
||||||
|
local_target="$$target-am"; \
|
||||||
|
else \
|
||||||
|
local_target="$$target"; \
|
||||||
|
fi; \
|
||||||
|
($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|
||||||
|
|| eval $$failcom; \
|
||||||
|
done; \
|
||||||
|
if test "$$dot_seen" = "no"; then \
|
||||||
|
$(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
|
||||||
|
fi; test -z "$$fail"
|
||||||
|
|
||||||
|
ID: $(am__tagged_files)
|
||||||
|
$(am__define_uniq_tagged_files); mkid -fID $$unique
|
||||||
|
tags: tags-recursive
|
||||||
|
TAGS: tags
|
||||||
|
|
||||||
|
tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
|
||||||
|
set x; \
|
||||||
|
here=`pwd`; \
|
||||||
|
if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
|
||||||
|
include_option=--etags-include; \
|
||||||
|
empty_fix=.; \
|
||||||
|
else \
|
||||||
|
include_option=--include; \
|
||||||
|
empty_fix=; \
|
||||||
|
fi; \
|
||||||
|
list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||||
|
if test "$$subdir" = .; then :; else \
|
||||||
|
test ! -f $$subdir/TAGS || \
|
||||||
|
set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
|
||||||
|
fi; \
|
||||||
|
done; \
|
||||||
|
$(am__define_uniq_tagged_files); \
|
||||||
|
shift; \
|
||||||
|
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
|
||||||
|
test -n "$$unique" || unique=$$empty_fix; \
|
||||||
|
if test $$# -gt 0; then \
|
||||||
|
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||||
|
"$$@" $$unique; \
|
||||||
|
else \
|
||||||
|
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||||
|
$$unique; \
|
||||||
|
fi; \
|
||||||
|
fi
|
||||||
|
ctags: ctags-recursive
|
||||||
|
|
||||||
|
CTAGS: ctags
|
||||||
|
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
|
||||||
|
$(am__define_uniq_tagged_files); \
|
||||||
|
test -z "$(CTAGS_ARGS)$$unique" \
|
||||||
|
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
|
||||||
|
$$unique
|
||||||
|
|
||||||
|
GTAGS:
|
||||||
|
here=`$(am__cd) $(top_builddir) && pwd` \
|
||||||
|
&& $(am__cd) $(top_srcdir) \
|
||||||
|
&& gtags -i $(GTAGS_ARGS) "$$here"
|
||||||
|
cscopelist: cscopelist-recursive
|
||||||
|
|
||||||
|
cscopelist-am: $(am__tagged_files)
|
||||||
|
list='$(am__tagged_files)'; \
|
||||||
|
case "$(srcdir)" in \
|
||||||
|
[\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
|
||||||
|
*) sdir=$(subdir)/$(srcdir) ;; \
|
||||||
|
esac; \
|
||||||
|
for i in $$list; do \
|
||||||
|
if test -f "$$i"; then \
|
||||||
|
echo "$(subdir)/$$i"; \
|
||||||
|
else \
|
||||||
|
echo "$$sdir/$$i"; \
|
||||||
|
fi; \
|
||||||
|
done >> $(top_builddir)/cscope.files
|
||||||
|
|
||||||
|
distclean-tags:
|
||||||
|
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||||
|
|
||||||
|
distdir: $(DISTFILES)
|
||||||
|
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||||
|
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||||
|
list='$(DISTFILES)'; \
|
||||||
|
dist_files=`for file in $$list; do echo $$file; done | \
|
||||||
|
sed -e "s|^$$srcdirstrip/||;t" \
|
||||||
|
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
|
||||||
|
case $$dist_files in \
|
||||||
|
*/*) $(MKDIR_P) `echo "$$dist_files" | \
|
||||||
|
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
|
||||||
|
sort -u` ;; \
|
||||||
|
esac; \
|
||||||
|
for file in $$dist_files; do \
|
||||||
|
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||||
|
if test -d $$d/$$file; then \
|
||||||
|
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||||
|
if test -d "$(distdir)/$$file"; then \
|
||||||
|
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||||
|
fi; \
|
||||||
|
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||||
|
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
|
||||||
|
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||||
|
fi; \
|
||||||
|
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
|
||||||
|
else \
|
||||||
|
test -f "$(distdir)/$$file" \
|
||||||
|
|| cp -p $$d/$$file "$(distdir)/$$file" \
|
||||||
|
|| exit 1; \
|
||||||
|
fi; \
|
||||||
|
done
|
||||||
|
@list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
|
||||||
|
if test "$$subdir" = .; then :; else \
|
||||||
|
$(am__make_dryrun) \
|
||||||
|
|| test -d "$(distdir)/$$subdir" \
|
||||||
|
|| $(MKDIR_P) "$(distdir)/$$subdir" \
|
||||||
|
|| exit 1; \
|
||||||
|
dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
|
||||||
|
$(am__relativize); \
|
||||||
|
new_distdir=$$reldir; \
|
||||||
|
dir1=$$subdir; dir2="$(top_distdir)"; \
|
||||||
|
$(am__relativize); \
|
||||||
|
new_top_distdir=$$reldir; \
|
||||||
|
echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
|
||||||
|
echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
|
||||||
|
($(am__cd) $$subdir && \
|
||||||
|
$(MAKE) $(AM_MAKEFLAGS) \
|
||||||
|
top_distdir="$$new_top_distdir" \
|
||||||
|
distdir="$$new_distdir" \
|
||||||
|
am__remove_distdir=: \
|
||||||
|
am__skip_length_check=: \
|
||||||
|
am__skip_mode_fix=: \
|
||||||
|
distdir) \
|
||||||
|
|| exit 1; \
|
||||||
|
fi; \
|
||||||
|
done
|
||||||
|
check-am: all-am
|
||||||
|
check: check-recursive
|
||||||
|
all-am: Makefile $(MANS) $(DATA)
|
||||||
|
installdirs: installdirs-recursive
|
||||||
|
installdirs-am:
|
||||||
|
for dir in "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(man8dir)" "$(DESTDIR)$(docdir)"; do \
|
||||||
|
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
|
||||||
|
done
|
||||||
|
install: install-recursive
|
||||||
|
install-exec: install-exec-recursive
|
||||||
|
install-data: install-data-recursive
|
||||||
|
uninstall: uninstall-recursive
|
||||||
|
|
||||||
|
install-am: all-am
|
||||||
|
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||||
|
|
||||||
|
installcheck: installcheck-recursive
|
||||||
|
install-strip:
|
||||||
|
if test -z '$(STRIP)'; then \
|
||||||
|
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||||
|
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||||
|
install; \
|
||||||
|
else \
|
||||||
|
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||||
|
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||||
|
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
|
||||||
|
fi
|
||||||
|
mostlyclean-generic:
|
||||||
|
|
||||||
|
clean-generic:
|
||||||
|
|
||||||
|
distclean-generic:
|
||||||
|
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||||
|
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
|
||||||
|
|
||||||
|
maintainer-clean-generic:
|
||||||
|
@echo "This command is intended for maintainers to use"
|
||||||
|
@echo "it deletes files that may require special tools to rebuild."
|
||||||
|
@ENABLE_POLKIT_FALSE@install-data-hook:
|
||||||
|
@ENABLE_POLKIT_FALSE@uninstall-hook:
|
||||||
|
clean: clean-recursive
|
||||||
|
|
||||||
|
clean-am: clean-generic clean-libtool mostlyclean-am
|
||||||
|
|
||||||
|
distclean: distclean-recursive
|
||||||
|
-rm -f Makefile
|
||||||
|
distclean-am: clean-am distclean-generic distclean-tags
|
||||||
|
|
||||||
|
dvi: dvi-recursive
|
||||||
|
|
||||||
|
dvi-am:
|
||||||
|
|
||||||
|
html: html-recursive
|
||||||
|
|
||||||
|
html-am:
|
||||||
|
|
||||||
|
info: info-recursive
|
||||||
|
|
||||||
|
info-am:
|
||||||
|
|
||||||
|
install-data-am: install-docDATA install-man
|
||||||
|
@$(NORMAL_INSTALL)
|
||||||
|
$(MAKE) $(AM_MAKEFLAGS) install-data-hook
|
||||||
|
install-dvi: install-dvi-recursive
|
||||||
|
|
||||||
|
install-dvi-am:
|
||||||
|
|
||||||
|
install-exec-am:
|
||||||
|
|
||||||
|
install-html: install-html-recursive
|
||||||
|
|
||||||
|
install-html-am:
|
||||||
|
|
||||||
|
install-info: install-info-recursive
|
||||||
|
|
||||||
|
install-info-am:
|
||||||
|
|
||||||
|
install-man: install-man5 install-man8
|
||||||
|
|
||||||
|
install-pdf: install-pdf-recursive
|
||||||
|
|
||||||
|
install-pdf-am:
|
||||||
|
|
||||||
|
install-ps: install-ps-recursive
|
||||||
|
|
||||||
|
install-ps-am:
|
||||||
|
|
||||||
|
installcheck-am:
|
||||||
|
|
||||||
|
maintainer-clean: maintainer-clean-recursive
|
||||||
|
-rm -f Makefile
|
||||||
|
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||||
|
|
||||||
|
mostlyclean: mostlyclean-recursive
|
||||||
|
|
||||||
|
mostlyclean-am: mostlyclean-generic mostlyclean-libtool
|
||||||
|
|
||||||
|
pdf: pdf-recursive
|
||||||
|
|
||||||
|
pdf-am:
|
||||||
|
|
||||||
|
ps: ps-recursive
|
||||||
|
|
||||||
|
ps-am:
|
||||||
|
|
||||||
|
uninstall-am: uninstall-docDATA uninstall-man
|
||||||
|
@$(NORMAL_INSTALL)
|
||||||
|
$(MAKE) $(AM_MAKEFLAGS) uninstall-hook
|
||||||
|
uninstall-man: uninstall-man5 uninstall-man8
|
||||||
|
|
||||||
|
.MAKE: $(am__recursive_targets) install-am install-data-am \
|
||||||
|
install-strip uninstall-am
|
||||||
|
|
||||||
|
.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \
|
||||||
|
check-am clean clean-generic clean-libtool cscopelist-am ctags \
|
||||||
|
ctags-am distclean distclean-generic distclean-libtool \
|
||||||
|
distclean-tags distdir dvi dvi-am html html-am info info-am \
|
||||||
|
install install-am install-data install-data-am \
|
||||||
|
install-data-hook install-docDATA install-dvi install-dvi-am \
|
||||||
|
install-exec install-exec-am install-html install-html-am \
|
||||||
|
install-info install-info-am install-man install-man5 \
|
||||||
|
install-man8 install-pdf install-pdf-am install-ps \
|
||||||
|
install-ps-am install-strip installcheck installcheck-am \
|
||||||
|
installdirs installdirs-am maintainer-clean \
|
||||||
|
maintainer-clean-generic mostlyclean mostlyclean-generic \
|
||||||
|
mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \
|
||||||
|
uninstall-am uninstall-docDATA uninstall-hook uninstall-man \
|
||||||
|
uninstall-man5 uninstall-man8
|
||||||
|
|
||||||
|
.PRECIOUS: Makefile
|
||||||
|
|
||||||
|
|
||||||
|
doxygen:
|
||||||
|
rm -fr api ; cd .. ; doxygen doc/doxygen.conf
|
||||||
|
# cp doxygen.css api/
|
||||||
|
|
||||||
|
@ENABLE_POLKIT_TRUE@install-data-hook:
|
||||||
|
@ENABLE_POLKIT_TRUE@ $(MKDIR_P) $(DESTDIR)/$(POLICY_DIR)
|
||||||
|
@ENABLE_POLKIT_TRUE@ $(INSTALL_DATA) $(srcdir)/org.debian.pcsc-lite.policy $(DESTDIR)/$(POLICY_DIR)
|
||||||
|
|
||||||
|
@ENABLE_POLKIT_TRUE@uninstall-hook:
|
||||||
|
@ENABLE_POLKIT_TRUE@ rm $(DESTDIR)/$(POLICY_DIR)/org.debian.pcsc-lite.policy
|
||||||
|
|
||||||
|
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||||
|
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||||
|
.NOEXPORT:
|
|
@ -0,0 +1,15 @@
|
||||||
|
To install pcsc-lite as a daemon that is automatically started up at
|
||||||
|
boot you must use the following command in one of your rc files or add an
|
||||||
|
entry to your rc.d/init.d/ directory for Redhat/Mandrake users.
|
||||||
|
|
||||||
|
nohup /usr/local/pcsc/bin/pcscd </dev/null >> /var/log/pcscd.log 2>&1 &
|
||||||
|
|
||||||
|
|
||||||
|
If you installed using ./configure --enable-daemon then just use:
|
||||||
|
|
||||||
|
pcscd
|
||||||
|
|
||||||
|
Mac OS X Users may create a Startup by doing the following:
|
||||||
|
Copy the files SmartcardServices and StartupParameters.plist from the
|
||||||
|
/etc directory to /System/Library/StartupItems/SmartcardServices.
|
||||||
|
( You will have to create the SmartcardServices directory )
|
|
@ -0,0 +1,39 @@
|
||||||
|
When pcsc-lite is compiled using the --enable-polkit option then
|
||||||
|
polkit will be used to control access to the pcsc-lite daemon.
|
||||||
|
|
||||||
|
That allows more fine grained access control to smart cards that
|
||||||
|
is tied to the system processes rather than solely depending on
|
||||||
|
the smart card controls (e.g., only console users can access the
|
||||||
|
card and so on).
|
||||||
|
|
||||||
|
Polkit is documented at:
|
||||||
|
http://www.freedesktop.org/software/polkit/docs/latest/polkit.8.html
|
||||||
|
|
||||||
|
A default polkit policy is shipped with pcsc-lite in
|
||||||
|
org.debian.pcsc-lite.policy. The policy file allows restricting access
|
||||||
|
to the daemon as well as access to smart cards.
|
||||||
|
|
||||||
|
Polkit allows for additional rules, e.g., restricting access to
|
||||||
|
particular smart cards. The rules are javascript files placed
|
||||||
|
in /usr/share/polkit-1/rules.d/. To make specific smart card
|
||||||
|
reader accessible by the web server (run as www-data user) you
|
||||||
|
may use the following rules:
|
||||||
|
|
||||||
|
polkit.addRule(function(action, subject) {
|
||||||
|
if (action.id == "org.debian.pcsc-lite.access_card" &&
|
||||||
|
action.lookup("reader") == 'name of reader' &&
|
||||||
|
subject.user == "www-data") {
|
||||||
|
return polkit.Result.YES;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
polkit.addRule(function(action, subject) {
|
||||||
|
if (action.id == "org.debian.pcsc-lite.access_pcsc" &&
|
||||||
|
subject.user == "www-data") {
|
||||||
|
return polkit.Result.YES;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
Note that the name of the reader can be obtained using "opensc-tool -l"
|
||||||
|
or "pcsc_scan".
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,6 @@
|
||||||
|
# Process this file with automake to create Makefile.in.
|
||||||
|
|
||||||
|
noinst_PROGRAMS = pcsc_demo
|
||||||
|
pcsc_demo_SOURCES = pcsc_demo.c
|
||||||
|
pcsc_demo_CFLAGS = -I$(top_srcdir)/src/PCSC -I$(top_builddir)/src/PCSC
|
||||||
|
pcsc_demo_LDADD = $(top_builddir)/src/libpcsclite.la
|
|
@ -0,0 +1,638 @@
|
||||||
|
# Makefile.in generated by automake 1.15 from Makefile.am.
|
||||||
|
# @configure_input@
|
||||||
|
|
||||||
|
# Copyright (C) 1994-2014 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
# This Makefile.in is free software; the Free Software Foundation
|
||||||
|
# gives unlimited permission to copy and/or distribute it,
|
||||||
|
# with or without modifications, as long as this notice is preserved.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||||
|
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||||
|
# PARTICULAR PURPOSE.
|
||||||
|
|
||||||
|
@SET_MAKE@
|
||||||
|
|
||||||
|
# Process this file with automake to create Makefile.in.
|
||||||
|
|
||||||
|
VPATH = @srcdir@
|
||||||
|
am__is_gnu_make = { \
|
||||||
|
if test -z '$(MAKELEVEL)'; then \
|
||||||
|
false; \
|
||||||
|
elif test -n '$(MAKE_HOST)'; then \
|
||||||
|
true; \
|
||||||
|
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
|
||||||
|
true; \
|
||||||
|
else \
|
||||||
|
false; \
|
||||||
|
fi; \
|
||||||
|
}
|
||||||
|
am__make_running_with_option = \
|
||||||
|
case $${target_option-} in \
|
||||||
|
?) ;; \
|
||||||
|
*) echo "am__make_running_with_option: internal error: invalid" \
|
||||||
|
"target option '$${target_option-}' specified" >&2; \
|
||||||
|
exit 1;; \
|
||||||
|
esac; \
|
||||||
|
has_opt=no; \
|
||||||
|
sane_makeflags=$$MAKEFLAGS; \
|
||||||
|
if $(am__is_gnu_make); then \
|
||||||
|
sane_makeflags=$$MFLAGS; \
|
||||||
|
else \
|
||||||
|
case $$MAKEFLAGS in \
|
||||||
|
*\\[\ \ ]*) \
|
||||||
|
bs=\\; \
|
||||||
|
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
|
||||||
|
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
|
||||||
|
esac; \
|
||||||
|
fi; \
|
||||||
|
skip_next=no; \
|
||||||
|
strip_trailopt () \
|
||||||
|
{ \
|
||||||
|
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
|
||||||
|
}; \
|
||||||
|
for flg in $$sane_makeflags; do \
|
||||||
|
test $$skip_next = yes && { skip_next=no; continue; }; \
|
||||||
|
case $$flg in \
|
||||||
|
*=*|--*) continue;; \
|
||||||
|
-*I) strip_trailopt 'I'; skip_next=yes;; \
|
||||||
|
-*I?*) strip_trailopt 'I';; \
|
||||||
|
-*O) strip_trailopt 'O'; skip_next=yes;; \
|
||||||
|
-*O?*) strip_trailopt 'O';; \
|
||||||
|
-*l) strip_trailopt 'l'; skip_next=yes;; \
|
||||||
|
-*l?*) strip_trailopt 'l';; \
|
||||||
|
-[dEDm]) skip_next=yes;; \
|
||||||
|
-[JT]) skip_next=yes;; \
|
||||||
|
esac; \
|
||||||
|
case $$flg in \
|
||||||
|
*$$target_option*) has_opt=yes; break;; \
|
||||||
|
esac; \
|
||||||
|
done; \
|
||||||
|
test $$has_opt = yes
|
||||||
|
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
|
||||||
|
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
|
||||||
|
pkgdatadir = $(datadir)/@PACKAGE@
|
||||||
|
pkgincludedir = $(includedir)/@PACKAGE@
|
||||||
|
pkglibdir = $(libdir)/@PACKAGE@
|
||||||
|
pkglibexecdir = $(libexecdir)/@PACKAGE@
|
||||||
|
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||||
|
install_sh_DATA = $(install_sh) -c -m 644
|
||||||
|
install_sh_PROGRAM = $(install_sh) -c
|
||||||
|
install_sh_SCRIPT = $(install_sh) -c
|
||||||
|
INSTALL_HEADER = $(INSTALL_DATA)
|
||||||
|
transform = $(program_transform_name)
|
||||||
|
NORMAL_INSTALL = :
|
||||||
|
PRE_INSTALL = :
|
||||||
|
POST_INSTALL = :
|
||||||
|
NORMAL_UNINSTALL = :
|
||||||
|
PRE_UNINSTALL = :
|
||||||
|
POST_UNINSTALL = :
|
||||||
|
build_triplet = @build@
|
||||||
|
host_triplet = @host@
|
||||||
|
noinst_PROGRAMS = pcsc_demo$(EXEEXT)
|
||||||
|
subdir = doc/example
|
||||||
|
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||||
|
am__aclocal_m4_deps = $(top_srcdir)/m4/as-ac-expand.m4 \
|
||||||
|
$(top_srcdir)/m4/ax_pthread.m4 $(top_srcdir)/m4/libtool.m4 \
|
||||||
|
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
|
||||||
|
$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
|
||||||
|
$(top_srcdir)/configure.ac
|
||||||
|
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||||
|
$(ACLOCAL_M4)
|
||||||
|
DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
|
||||||
|
mkinstalldirs = $(install_sh) -d
|
||||||
|
CONFIG_HEADER = $(top_builddir)/config.h
|
||||||
|
CONFIG_CLEAN_FILES =
|
||||||
|
CONFIG_CLEAN_VPATH_FILES =
|
||||||
|
PROGRAMS = $(noinst_PROGRAMS)
|
||||||
|
am_pcsc_demo_OBJECTS = pcsc_demo-pcsc_demo.$(OBJEXT)
|
||||||
|
pcsc_demo_OBJECTS = $(am_pcsc_demo_OBJECTS)
|
||||||
|
pcsc_demo_DEPENDENCIES = $(top_builddir)/src/libpcsclite.la
|
||||||
|
AM_V_lt = $(am__v_lt_@AM_V@)
|
||||||
|
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
|
||||||
|
am__v_lt_0 = --silent
|
||||||
|
am__v_lt_1 =
|
||||||
|
pcsc_demo_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
|
||||||
|
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(pcsc_demo_CFLAGS) \
|
||||||
|
$(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
|
||||||
|
AM_V_P = $(am__v_P_@AM_V@)
|
||||||
|
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
|
||||||
|
am__v_P_0 = false
|
||||||
|
am__v_P_1 = :
|
||||||
|
AM_V_GEN = $(am__v_GEN_@AM_V@)
|
||||||
|
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
|
||||||
|
am__v_GEN_0 = @echo " GEN " $@;
|
||||||
|
am__v_GEN_1 =
|
||||||
|
AM_V_at = $(am__v_at_@AM_V@)
|
||||||
|
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
|
||||||
|
am__v_at_0 = @
|
||||||
|
am__v_at_1 =
|
||||||
|
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
|
||||||
|
depcomp = $(SHELL) $(top_srcdir)/depcomp
|
||||||
|
am__depfiles_maybe = depfiles
|
||||||
|
am__mv = mv -f
|
||||||
|
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
|
||||||
|
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||||
|
LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
|
||||||
|
$(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
|
||||||
|
$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
|
||||||
|
$(AM_CFLAGS) $(CFLAGS)
|
||||||
|
AM_V_CC = $(am__v_CC_@AM_V@)
|
||||||
|
am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
|
||||||
|
am__v_CC_0 = @echo " CC " $@;
|
||||||
|
am__v_CC_1 =
|
||||||
|
CCLD = $(CC)
|
||||||
|
LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
|
||||||
|
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
|
||||||
|
$(AM_LDFLAGS) $(LDFLAGS) -o $@
|
||||||
|
AM_V_CCLD = $(am__v_CCLD_@AM_V@)
|
||||||
|
am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
|
||||||
|
am__v_CCLD_0 = @echo " CCLD " $@;
|
||||||
|
am__v_CCLD_1 =
|
||||||
|
SOURCES = $(pcsc_demo_SOURCES)
|
||||||
|
DIST_SOURCES = $(pcsc_demo_SOURCES)
|
||||||
|
am__can_run_installinfo = \
|
||||||
|
case $$AM_UPDATE_INFO_DIR in \
|
||||||
|
n|no|NO) false;; \
|
||||||
|
*) (install-info --version) >/dev/null 2>&1;; \
|
||||||
|
esac
|
||||||
|
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
|
||||||
|
# Read a list of newline-separated strings from the standard input,
|
||||||
|
# and print each of them once, without duplicates. Input order is
|
||||||
|
# *not* preserved.
|
||||||
|
am__uniquify_input = $(AWK) '\
|
||||||
|
BEGIN { nonempty = 0; } \
|
||||||
|
{ items[$$0] = 1; nonempty = 1; } \
|
||||||
|
END { if (nonempty) { for (i in items) print i; }; } \
|
||||||
|
'
|
||||||
|
# Make sure the list of sources is unique. This is necessary because,
|
||||||
|
# e.g., the same source file might be shared among _SOURCES variables
|
||||||
|
# for different programs/libraries.
|
||||||
|
am__define_uniq_tagged_files = \
|
||||||
|
list='$(am__tagged_files)'; \
|
||||||
|
unique=`for i in $$list; do \
|
||||||
|
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||||
|
done | $(am__uniquify_input)`
|
||||||
|
ETAGS = etags
|
||||||
|
CTAGS = ctags
|
||||||
|
am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
|
||||||
|
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||||
|
ACLOCAL = @ACLOCAL@
|
||||||
|
ALLOCA = @ALLOCA@
|
||||||
|
AMTAR = @AMTAR@
|
||||||
|
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
|
||||||
|
AR = @AR@
|
||||||
|
AUTOCONF = @AUTOCONF@
|
||||||
|
AUTOHEADER = @AUTOHEADER@
|
||||||
|
AUTOMAKE = @AUTOMAKE@
|
||||||
|
AWK = @AWK@
|
||||||
|
CC = @CC@
|
||||||
|
CCDEPMODE = @CCDEPMODE@
|
||||||
|
CFLAGS = @CFLAGS@
|
||||||
|
COREFOUNDATION = @COREFOUNDATION@
|
||||||
|
CPP = @CPP@
|
||||||
|
CPPFLAGS = @CPPFLAGS@
|
||||||
|
CYGPATH_W = @CYGPATH_W@
|
||||||
|
DEFS = @DEFS@
|
||||||
|
DEPDIR = @DEPDIR@
|
||||||
|
DLLTOOL = @DLLTOOL@
|
||||||
|
DSYMUTIL = @DSYMUTIL@
|
||||||
|
DUMPBIN = @DUMPBIN@
|
||||||
|
ECHO_C = @ECHO_C@
|
||||||
|
ECHO_N = @ECHO_N@
|
||||||
|
ECHO_T = @ECHO_T@
|
||||||
|
EGREP = @EGREP@
|
||||||
|
EXEEXT = @EXEEXT@
|
||||||
|
FGREP = @FGREP@
|
||||||
|
GREP = @GREP@
|
||||||
|
INSTALL = @INSTALL@
|
||||||
|
INSTALL_DATA = @INSTALL_DATA@
|
||||||
|
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||||
|
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||||
|
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||||
|
IOKIT = @IOKIT@
|
||||||
|
LD = @LD@
|
||||||
|
LDFLAGS = @LDFLAGS@
|
||||||
|
LEX = @LEX@
|
||||||
|
LEXLIB = @LEXLIB@
|
||||||
|
LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
|
||||||
|
LIBOBJS = @LIBOBJS@
|
||||||
|
LIBS = @LIBS@
|
||||||
|
LIBTOOL = @LIBTOOL@
|
||||||
|
LIBUDEV_CFLAGS = @LIBUDEV_CFLAGS@
|
||||||
|
LIBUDEV_LIBS = @LIBUDEV_LIBS@
|
||||||
|
LIBUSBCONFIG = @LIBUSBCONFIG@
|
||||||
|
LIBUSB_CFLAGS = @LIBUSB_CFLAGS@
|
||||||
|
LIBUSB_LIBS = @LIBUSB_LIBS@
|
||||||
|
LIPO = @LIPO@
|
||||||
|
LN_S = @LN_S@
|
||||||
|
LTLIBOBJS = @LTLIBOBJS@
|
||||||
|
LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
|
||||||
|
MAINT = @MAINT@
|
||||||
|
MAKEINFO = @MAKEINFO@
|
||||||
|
MANIFEST_TOOL = @MANIFEST_TOOL@
|
||||||
|
MKDIR_P = @MKDIR_P@
|
||||||
|
NM = @NM@
|
||||||
|
NMEDIT = @NMEDIT@
|
||||||
|
OBJDUMP = @OBJDUMP@
|
||||||
|
OBJEXT = @OBJEXT@
|
||||||
|
OTOOL = @OTOOL@
|
||||||
|
OTOOL64 = @OTOOL64@
|
||||||
|
PACKAGE = @PACKAGE@
|
||||||
|
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||||
|
PACKAGE_NAME = @PACKAGE_NAME@
|
||||||
|
PACKAGE_STRING = @PACKAGE_STRING@
|
||||||
|
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||||
|
PACKAGE_URL = @PACKAGE_URL@
|
||||||
|
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||||
|
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||||
|
PCSCLITE_CONFIG_DIR = @PCSCLITE_CONFIG_DIR@
|
||||||
|
PKG_CONFIG = @PKG_CONFIG@
|
||||||
|
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
|
||||||
|
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
|
||||||
|
POLICY_DIR = @POLICY_DIR@
|
||||||
|
POLKIT_CFLAGS = @POLKIT_CFLAGS@
|
||||||
|
POLKIT_LIBS = @POLKIT_LIBS@
|
||||||
|
PTHREAD_CC = @PTHREAD_CC@
|
||||||
|
PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
|
||||||
|
PTHREAD_LIBS = @PTHREAD_LIBS@
|
||||||
|
RANLIB = @RANLIB@
|
||||||
|
SED = @SED@
|
||||||
|
SET_MAKE = @SET_MAKE@
|
||||||
|
SHELL = @SHELL@
|
||||||
|
STRIP = @STRIP@
|
||||||
|
SYMBOL_VISIBILITY = @SYMBOL_VISIBILITY@
|
||||||
|
VERSION = @VERSION@
|
||||||
|
abs_builddir = @abs_builddir@
|
||||||
|
abs_srcdir = @abs_srcdir@
|
||||||
|
abs_top_builddir = @abs_top_builddir@
|
||||||
|
abs_top_srcdir = @abs_top_srcdir@
|
||||||
|
ac_ct_AR = @ac_ct_AR@
|
||||||
|
ac_ct_CC = @ac_ct_CC@
|
||||||
|
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
|
||||||
|
am__include = @am__include@
|
||||||
|
am__leading_dot = @am__leading_dot@
|
||||||
|
am__quote = @am__quote@
|
||||||
|
am__tar = @am__tar@
|
||||||
|
am__untar = @am__untar@
|
||||||
|
ax_pthread_config = @ax_pthread_config@
|
||||||
|
bindir = @bindir@
|
||||||
|
build = @build@
|
||||||
|
build_alias = @build_alias@
|
||||||
|
build_cpu = @build_cpu@
|
||||||
|
build_os = @build_os@
|
||||||
|
build_vendor = @build_vendor@
|
||||||
|
builddir = @builddir@
|
||||||
|
confdir_exp = @confdir_exp@
|
||||||
|
datadir = @datadir@
|
||||||
|
datarootdir = @datarootdir@
|
||||||
|
docdir = @docdir@
|
||||||
|
dvidir = @dvidir@
|
||||||
|
exec_prefix = @exec_prefix@
|
||||||
|
host = @host@
|
||||||
|
host_alias = @host_alias@
|
||||||
|
host_cpu = @host_cpu@
|
||||||
|
host_os = @host_os@
|
||||||
|
host_to_ccid_16 = @host_to_ccid_16@
|
||||||
|
host_to_ccid_32 = @host_to_ccid_32@
|
||||||
|
host_vendor = @host_vendor@
|
||||||
|
htmldir = @htmldir@
|
||||||
|
includedir = @includedir@
|
||||||
|
infodir = @infodir@
|
||||||
|
install_sh = @install_sh@
|
||||||
|
ipcdir = @ipcdir@
|
||||||
|
libdir = @libdir@
|
||||||
|
libexecdir = @libexecdir@
|
||||||
|
localedir = @localedir@
|
||||||
|
localstatedir = @localstatedir@
|
||||||
|
localstatedir_exp = @localstatedir_exp@
|
||||||
|
mandir = @mandir@
|
||||||
|
mkdir_p = @mkdir_p@
|
||||||
|
oldincludedir = @oldincludedir@
|
||||||
|
pdfdir = @pdfdir@
|
||||||
|
prefix = @prefix@
|
||||||
|
program_transform_name = @program_transform_name@
|
||||||
|
psdir = @psdir@
|
||||||
|
runstatedir = @runstatedir@
|
||||||
|
sbindir = @sbindir@
|
||||||
|
sbindir_exp = @sbindir_exp@
|
||||||
|
serialconfdir = @serialconfdir@
|
||||||
|
sharedstatedir = @sharedstatedir@
|
||||||
|
srcdir = @srcdir@
|
||||||
|
sysconfdir = @sysconfdir@
|
||||||
|
systemdsystemunitdir = @systemdsystemunitdir@
|
||||||
|
target_alias = @target_alias@
|
||||||
|
top_build_prefix = @top_build_prefix@
|
||||||
|
top_builddir = @top_builddir@
|
||||||
|
top_srcdir = @top_srcdir@
|
||||||
|
usbdropdir = @usbdropdir@
|
||||||
|
usbdropdir_exp = @usbdropdir_exp@
|
||||||
|
pcsc_demo_SOURCES = pcsc_demo.c
|
||||||
|
pcsc_demo_CFLAGS = -I$(top_srcdir)/src/PCSC -I$(top_builddir)/src/PCSC
|
||||||
|
pcsc_demo_LDADD = $(top_builddir)/src/libpcsclite.la
|
||||||
|
all: all-am
|
||||||
|
|
||||||
|
.SUFFIXES:
|
||||||
|
.SUFFIXES: .c .lo .o .obj
|
||||||
|
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
|
||||||
|
@for dep in $?; do \
|
||||||
|
case '$(am__configure_deps)' in \
|
||||||
|
*$$dep*) \
|
||||||
|
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
|
||||||
|
&& { if test -f $@; then exit 0; else break; fi; }; \
|
||||||
|
exit 1;; \
|
||||||
|
esac; \
|
||||||
|
done; \
|
||||||
|
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu doc/example/Makefile'; \
|
||||||
|
$(am__cd) $(top_srcdir) && \
|
||||||
|
$(AUTOMAKE) --gnu doc/example/Makefile
|
||||||
|
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||||
|
@case '$?' in \
|
||||||
|
*config.status*) \
|
||||||
|
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
|
||||||
|
*) \
|
||||||
|
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
|
||||||
|
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
|
||||||
|
esac;
|
||||||
|
|
||||||
|
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||||
|
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||||
|
|
||||||
|
$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
|
||||||
|
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||||
|
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
|
||||||
|
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||||
|
$(am__aclocal_m4_deps):
|
||||||
|
|
||||||
|
clean-noinstPROGRAMS:
|
||||||
|
@list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \
|
||||||
|
echo " rm -f" $$list; \
|
||||||
|
rm -f $$list || exit $$?; \
|
||||||
|
test -n "$(EXEEXT)" || exit 0; \
|
||||||
|
list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
|
||||||
|
echo " rm -f" $$list; \
|
||||||
|
rm -f $$list
|
||||||
|
|
||||||
|
pcsc_demo$(EXEEXT): $(pcsc_demo_OBJECTS) $(pcsc_demo_DEPENDENCIES) $(EXTRA_pcsc_demo_DEPENDENCIES)
|
||||||
|
@rm -f pcsc_demo$(EXEEXT)
|
||||||
|
$(AM_V_CCLD)$(pcsc_demo_LINK) $(pcsc_demo_OBJECTS) $(pcsc_demo_LDADD) $(LIBS)
|
||||||
|
|
||||||
|
mostlyclean-compile:
|
||||||
|
-rm -f *.$(OBJEXT)
|
||||||
|
|
||||||
|
distclean-compile:
|
||||||
|
-rm -f *.tab.c
|
||||||
|
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcsc_demo-pcsc_demo.Po@am__quote@
|
||||||
|
|
||||||
|
.c.o:
|
||||||
|
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
|
||||||
|
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
|
||||||
|
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||||
|
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||||
|
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
|
||||||
|
|
||||||
|
.c.obj:
|
||||||
|
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
|
||||||
|
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
|
||||||
|
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||||
|
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||||
|
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
|
||||||
|
|
||||||
|
.c.lo:
|
||||||
|
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
|
||||||
|
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
|
||||||
|
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
|
||||||
|
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||||
|
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
|
||||||
|
|
||||||
|
pcsc_demo-pcsc_demo.o: pcsc_demo.c
|
||||||
|
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcsc_demo_CFLAGS) $(CFLAGS) -MT pcsc_demo-pcsc_demo.o -MD -MP -MF $(DEPDIR)/pcsc_demo-pcsc_demo.Tpo -c -o pcsc_demo-pcsc_demo.o `test -f 'pcsc_demo.c' || echo '$(srcdir)/'`pcsc_demo.c
|
||||||
|
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcsc_demo-pcsc_demo.Tpo $(DEPDIR)/pcsc_demo-pcsc_demo.Po
|
||||||
|
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pcsc_demo.c' object='pcsc_demo-pcsc_demo.o' libtool=no @AMDEPBACKSLASH@
|
||||||
|
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||||
|
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcsc_demo_CFLAGS) $(CFLAGS) -c -o pcsc_demo-pcsc_demo.o `test -f 'pcsc_demo.c' || echo '$(srcdir)/'`pcsc_demo.c
|
||||||
|
|
||||||
|
pcsc_demo-pcsc_demo.obj: pcsc_demo.c
|
||||||
|
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcsc_demo_CFLAGS) $(CFLAGS) -MT pcsc_demo-pcsc_demo.obj -MD -MP -MF $(DEPDIR)/pcsc_demo-pcsc_demo.Tpo -c -o pcsc_demo-pcsc_demo.obj `if test -f 'pcsc_demo.c'; then $(CYGPATH_W) 'pcsc_demo.c'; else $(CYGPATH_W) '$(srcdir)/pcsc_demo.c'; fi`
|
||||||
|
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcsc_demo-pcsc_demo.Tpo $(DEPDIR)/pcsc_demo-pcsc_demo.Po
|
||||||
|
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pcsc_demo.c' object='pcsc_demo-pcsc_demo.obj' libtool=no @AMDEPBACKSLASH@
|
||||||
|
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||||
|
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcsc_demo_CFLAGS) $(CFLAGS) -c -o pcsc_demo-pcsc_demo.obj `if test -f 'pcsc_demo.c'; then $(CYGPATH_W) 'pcsc_demo.c'; else $(CYGPATH_W) '$(srcdir)/pcsc_demo.c'; fi`
|
||||||
|
|
||||||
|
mostlyclean-libtool:
|
||||||
|
-rm -f *.lo
|
||||||
|
|
||||||
|
clean-libtool:
|
||||||
|
-rm -rf .libs _libs
|
||||||
|
|
||||||
|
ID: $(am__tagged_files)
|
||||||
|
$(am__define_uniq_tagged_files); mkid -fID $$unique
|
||||||
|
tags: tags-am
|
||||||
|
TAGS: tags
|
||||||
|
|
||||||
|
tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
|
||||||
|
set x; \
|
||||||
|
here=`pwd`; \
|
||||||
|
$(am__define_uniq_tagged_files); \
|
||||||
|
shift; \
|
||||||
|
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
|
||||||
|
test -n "$$unique" || unique=$$empty_fix; \
|
||||||
|
if test $$# -gt 0; then \
|
||||||
|
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||||
|
"$$@" $$unique; \
|
||||||
|
else \
|
||||||
|
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||||
|
$$unique; \
|
||||||
|
fi; \
|
||||||
|
fi
|
||||||
|
ctags: ctags-am
|
||||||
|
|
||||||
|
CTAGS: ctags
|
||||||
|
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
|
||||||
|
$(am__define_uniq_tagged_files); \
|
||||||
|
test -z "$(CTAGS_ARGS)$$unique" \
|
||||||
|
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
|
||||||
|
$$unique
|
||||||
|
|
||||||
|
GTAGS:
|
||||||
|
here=`$(am__cd) $(top_builddir) && pwd` \
|
||||||
|
&& $(am__cd) $(top_srcdir) \
|
||||||
|
&& gtags -i $(GTAGS_ARGS) "$$here"
|
||||||
|
cscopelist: cscopelist-am
|
||||||
|
|
||||||
|
cscopelist-am: $(am__tagged_files)
|
||||||
|
list='$(am__tagged_files)'; \
|
||||||
|
case "$(srcdir)" in \
|
||||||
|
[\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
|
||||||
|
*) sdir=$(subdir)/$(srcdir) ;; \
|
||||||
|
esac; \
|
||||||
|
for i in $$list; do \
|
||||||
|
if test -f "$$i"; then \
|
||||||
|
echo "$(subdir)/$$i"; \
|
||||||
|
else \
|
||||||
|
echo "$$sdir/$$i"; \
|
||||||
|
fi; \
|
||||||
|
done >> $(top_builddir)/cscope.files
|
||||||
|
|
||||||
|
distclean-tags:
|
||||||
|
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||||
|
|
||||||
|
distdir: $(DISTFILES)
|
||||||
|
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||||
|
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||||
|
list='$(DISTFILES)'; \
|
||||||
|
dist_files=`for file in $$list; do echo $$file; done | \
|
||||||
|
sed -e "s|^$$srcdirstrip/||;t" \
|
||||||
|
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
|
||||||
|
case $$dist_files in \
|
||||||
|
*/*) $(MKDIR_P) `echo "$$dist_files" | \
|
||||||
|
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
|
||||||
|
sort -u` ;; \
|
||||||
|
esac; \
|
||||||
|
for file in $$dist_files; do \
|
||||||
|
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||||
|
if test -d $$d/$$file; then \
|
||||||
|
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||||
|
if test -d "$(distdir)/$$file"; then \
|
||||||
|
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||||
|
fi; \
|
||||||
|
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||||
|
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
|
||||||
|
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||||
|
fi; \
|
||||||
|
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
|
||||||
|
else \
|
||||||
|
test -f "$(distdir)/$$file" \
|
||||||
|
|| cp -p $$d/$$file "$(distdir)/$$file" \
|
||||||
|
|| exit 1; \
|
||||||
|
fi; \
|
||||||
|
done
|
||||||
|
check-am: all-am
|
||||||
|
check: check-am
|
||||||
|
all-am: Makefile $(PROGRAMS)
|
||||||
|
installdirs:
|
||||||
|
install: install-am
|
||||||
|
install-exec: install-exec-am
|
||||||
|
install-data: install-data-am
|
||||||
|
uninstall: uninstall-am
|
||||||
|
|
||||||
|
install-am: all-am
|
||||||
|
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||||
|
|
||||||
|
installcheck: installcheck-am
|
||||||
|
install-strip:
|
||||||
|
if test -z '$(STRIP)'; then \
|
||||||
|
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||||
|
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||||
|
install; \
|
||||||
|
else \
|
||||||
|
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||||
|
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||||
|
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
|
||||||
|
fi
|
||||||
|
mostlyclean-generic:
|
||||||
|
|
||||||
|
clean-generic:
|
||||||
|
|
||||||
|
distclean-generic:
|
||||||
|
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||||
|
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
|
||||||
|
|
||||||
|
maintainer-clean-generic:
|
||||||
|
@echo "This command is intended for maintainers to use"
|
||||||
|
@echo "it deletes files that may require special tools to rebuild."
|
||||||
|
clean: clean-am
|
||||||
|
|
||||||
|
clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \
|
||||||
|
mostlyclean-am
|
||||||
|
|
||||||
|
distclean: distclean-am
|
||||||
|
-rm -rf ./$(DEPDIR)
|
||||||
|
-rm -f Makefile
|
||||||
|
distclean-am: clean-am distclean-compile distclean-generic \
|
||||||
|
distclean-tags
|
||||||
|
|
||||||
|
dvi: dvi-am
|
||||||
|
|
||||||
|
dvi-am:
|
||||||
|
|
||||||
|
html: html-am
|
||||||
|
|
||||||
|
html-am:
|
||||||
|
|
||||||
|
info: info-am
|
||||||
|
|
||||||
|
info-am:
|
||||||
|
|
||||||
|
install-data-am:
|
||||||
|
|
||||||
|
install-dvi: install-dvi-am
|
||||||
|
|
||||||
|
install-dvi-am:
|
||||||
|
|
||||||
|
install-exec-am:
|
||||||
|
|
||||||
|
install-html: install-html-am
|
||||||
|
|
||||||
|
install-html-am:
|
||||||
|
|
||||||
|
install-info: install-info-am
|
||||||
|
|
||||||
|
install-info-am:
|
||||||
|
|
||||||
|
install-man:
|
||||||
|
|
||||||
|
install-pdf: install-pdf-am
|
||||||
|
|
||||||
|
install-pdf-am:
|
||||||
|
|
||||||
|
install-ps: install-ps-am
|
||||||
|
|
||||||
|
install-ps-am:
|
||||||
|
|
||||||
|
installcheck-am:
|
||||||
|
|
||||||
|
maintainer-clean: maintainer-clean-am
|
||||||
|
-rm -rf ./$(DEPDIR)
|
||||||
|
-rm -f Makefile
|
||||||
|
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||||
|
|
||||||
|
mostlyclean: mostlyclean-am
|
||||||
|
|
||||||
|
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
|
||||||
|
mostlyclean-libtool
|
||||||
|
|
||||||
|
pdf: pdf-am
|
||||||
|
|
||||||
|
pdf-am:
|
||||||
|
|
||||||
|
ps: ps-am
|
||||||
|
|
||||||
|
ps-am:
|
||||||
|
|
||||||
|
uninstall-am:
|
||||||
|
|
||||||
|
.MAKE: install-am install-strip
|
||||||
|
|
||||||
|
.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
|
||||||
|
clean-libtool clean-noinstPROGRAMS cscopelist-am ctags \
|
||||||
|
ctags-am distclean distclean-compile distclean-generic \
|
||||||
|
distclean-libtool distclean-tags distdir dvi dvi-am html \
|
||||||
|
html-am info info-am install install-am install-data \
|
||||||
|
install-data-am install-dvi install-dvi-am install-exec \
|
||||||
|
install-exec-am install-html install-html-am install-info \
|
||||||
|
install-info-am install-man install-pdf install-pdf-am \
|
||||||
|
install-ps install-ps-am install-strip installcheck \
|
||||||
|
installcheck-am installdirs maintainer-clean \
|
||||||
|
maintainer-clean-generic mostlyclean mostlyclean-compile \
|
||||||
|
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
|
||||||
|
tags tags-am uninstall uninstall-am
|
||||||
|
|
||||||
|
.PRECIOUS: Makefile
|
||||||
|
|
||||||
|
|
||||||
|
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||||
|
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||||
|
.NOEXPORT:
|
|
@ -0,0 +1,285 @@
|
||||||
|
/*
|
||||||
|
* Sample program to use PC/SC API.
|
||||||
|
*
|
||||||
|
* MUSCLE SmartCard Development ( http://pcsclite.alioth.debian.org/pcsclite.html )
|
||||||
|
*
|
||||||
|
* Copyright (C) 2003-2011
|
||||||
|
* Ludovic Rousseau <ludovic.rousseau@free.fr>
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <PCSC/wintypes.h>
|
||||||
|
#include <PCSC/winscard.h>
|
||||||
|
|
||||||
|
#ifndef TRUE
|
||||||
|
#define TRUE 1
|
||||||
|
#define FALSE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* PCSC error message pretty print */
|
||||||
|
#define PCSC_ERROR(rv, text) \
|
||||||
|
if (rv != SCARD_S_SUCCESS) \
|
||||||
|
{ \
|
||||||
|
printf(text ": %s (0x%lX)\n", pcsc_stringify_error(rv), rv); \
|
||||||
|
goto end; \
|
||||||
|
} \
|
||||||
|
else \
|
||||||
|
{ \
|
||||||
|
printf(text ": OK\n\n"); \
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
LONG rv;
|
||||||
|
SCARDCONTEXT hContext;
|
||||||
|
DWORD dwReaders;
|
||||||
|
LPSTR mszReaders = NULL;
|
||||||
|
char *ptr, **readers = NULL;
|
||||||
|
int nbReaders;
|
||||||
|
SCARDHANDLE hCard;
|
||||||
|
DWORD dwActiveProtocol, dwReaderLen, dwState, dwProt, dwAtrLen;
|
||||||
|
BYTE pbAtr[MAX_ATR_SIZE] = "";
|
||||||
|
char pbReader[MAX_READERNAME] = "";
|
||||||
|
int reader_nb;
|
||||||
|
unsigned int i;
|
||||||
|
const SCARD_IO_REQUEST *pioSendPci;
|
||||||
|
SCARD_IO_REQUEST pioRecvPci;
|
||||||
|
BYTE pbRecvBuffer[10];
|
||||||
|
BYTE pbSendBuffer[] = { 0x00, 0xA4, 0x00, 0x00, 0x02, 0x3F, 0x00 };
|
||||||
|
DWORD dwSendLength, dwRecvLength;
|
||||||
|
|
||||||
|
printf("PC/SC sample code\n");
|
||||||
|
printf("V 1.4 2003-2009, Ludovic Rousseau <ludovic.rousseau@free.fr>\n");
|
||||||
|
|
||||||
|
printf("\nTHIS PROGRAM IS NOT DESIGNED AS A TESTING TOOL FOR END USERS!\n");
|
||||||
|
printf("Do NOT use it unless you really know what you do.\n\n");
|
||||||
|
|
||||||
|
rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
|
||||||
|
if (rv != SCARD_S_SUCCESS)
|
||||||
|
{
|
||||||
|
printf("SCardEstablishContext: Cannot Connect to Resource Manager %lX\n", rv);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Retrieve the available readers list. */
|
||||||
|
dwReaders = SCARD_AUTOALLOCATE;
|
||||||
|
rv = SCardListReaders(hContext, NULL, (LPSTR)&mszReaders, &dwReaders);
|
||||||
|
PCSC_ERROR(rv, "SCardListReaders")
|
||||||
|
|
||||||
|
/* Extract readers from the null separated string and get the total
|
||||||
|
* number of readers */
|
||||||
|
nbReaders = 0;
|
||||||
|
ptr = mszReaders;
|
||||||
|
while (*ptr != '\0')
|
||||||
|
{
|
||||||
|
ptr += strlen(ptr)+1;
|
||||||
|
nbReaders++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nbReaders == 0)
|
||||||
|
{
|
||||||
|
printf("No reader found\n");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allocate the readers table */
|
||||||
|
readers = calloc(nbReaders, sizeof(char *));
|
||||||
|
if (NULL == readers)
|
||||||
|
{
|
||||||
|
printf("Not enough memory for readers[]\n");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fill the readers table */
|
||||||
|
nbReaders = 0;
|
||||||
|
ptr = mszReaders;
|
||||||
|
while (*ptr != '\0')
|
||||||
|
{
|
||||||
|
printf("%d: %s\n", nbReaders, ptr);
|
||||||
|
readers[nbReaders] = ptr;
|
||||||
|
ptr += strlen(ptr)+1;
|
||||||
|
nbReaders++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc > 1)
|
||||||
|
{
|
||||||
|
reader_nb = atoi(argv[1]);
|
||||||
|
if (reader_nb < 0 || reader_nb >= nbReaders)
|
||||||
|
{
|
||||||
|
printf("Wrong reader index: %d\n", reader_nb);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
reader_nb = 0;
|
||||||
|
|
||||||
|
/* connect to a card */
|
||||||
|
dwActiveProtocol = -1;
|
||||||
|
rv = SCardConnect(hContext, readers[reader_nb], SCARD_SHARE_SHARED,
|
||||||
|
SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard, &dwActiveProtocol);
|
||||||
|
printf(" Protocol: %ld\n", dwActiveProtocol);
|
||||||
|
PCSC_ERROR(rv, "SCardConnect")
|
||||||
|
|
||||||
|
/* get card status */
|
||||||
|
dwAtrLen = sizeof(pbAtr);
|
||||||
|
dwReaderLen = sizeof(pbReader);
|
||||||
|
rv = SCardStatus(hCard, /*NULL*/ pbReader, &dwReaderLen, &dwState, &dwProt,
|
||||||
|
pbAtr, &dwAtrLen);
|
||||||
|
printf(" Reader: %s (length %ld bytes)\n", pbReader, dwReaderLen);
|
||||||
|
printf(" State: 0x%lX\n", dwState);
|
||||||
|
printf(" Prot: %ld\n", dwProt);
|
||||||
|
printf(" ATR (length %ld bytes):", dwAtrLen);
|
||||||
|
for (i=0; i<dwAtrLen; i++)
|
||||||
|
printf(" %02X", pbAtr[i]);
|
||||||
|
printf("\n");
|
||||||
|
PCSC_ERROR(rv, "SCardStatus")
|
||||||
|
|
||||||
|
switch(dwActiveProtocol)
|
||||||
|
{
|
||||||
|
case SCARD_PROTOCOL_T0:
|
||||||
|
pioSendPci = SCARD_PCI_T0;
|
||||||
|
break;
|
||||||
|
case SCARD_PROTOCOL_T1:
|
||||||
|
pioSendPci = SCARD_PCI_T1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("Unknown protocol\n");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* exchange APDU */
|
||||||
|
dwSendLength = sizeof(pbSendBuffer);
|
||||||
|
dwRecvLength = sizeof(pbRecvBuffer);
|
||||||
|
printf("Sending: ");
|
||||||
|
for (i=0; i<dwSendLength; i++)
|
||||||
|
printf("%02X ", pbSendBuffer[i]);
|
||||||
|
printf("\n");
|
||||||
|
rv = SCardTransmit(hCard, pioSendPci, pbSendBuffer, dwSendLength,
|
||||||
|
&pioRecvPci, pbRecvBuffer, &dwRecvLength);
|
||||||
|
printf("Received: ");
|
||||||
|
for (i=0; i<dwRecvLength; i++)
|
||||||
|
printf("%02X ", pbRecvBuffer[i]);
|
||||||
|
printf("\n");
|
||||||
|
PCSC_ERROR(rv, "SCardTransmit")
|
||||||
|
|
||||||
|
/* card disconnect */
|
||||||
|
rv = SCardDisconnect(hCard, SCARD_LEAVE_CARD);
|
||||||
|
PCSC_ERROR(rv, "SCardDisconnect")
|
||||||
|
|
||||||
|
/* connect to a card */
|
||||||
|
dwActiveProtocol = -1;
|
||||||
|
rv = SCardConnect(hContext, readers[reader_nb], SCARD_SHARE_SHARED,
|
||||||
|
SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard, &dwActiveProtocol);
|
||||||
|
printf(" Protocol: %ld\n", dwActiveProtocol);
|
||||||
|
PCSC_ERROR(rv, "SCardConnect")
|
||||||
|
|
||||||
|
/* exchange APDU */
|
||||||
|
dwSendLength = sizeof(pbSendBuffer);
|
||||||
|
dwRecvLength = sizeof(pbRecvBuffer);
|
||||||
|
printf("Sending: ");
|
||||||
|
for (i=0; i<dwSendLength; i++)
|
||||||
|
printf("%02X ", pbSendBuffer[i]);
|
||||||
|
printf("\n");
|
||||||
|
rv = SCardTransmit(hCard, pioSendPci, pbSendBuffer, dwSendLength,
|
||||||
|
&pioRecvPci, pbRecvBuffer, &dwRecvLength);
|
||||||
|
printf("Received: ");
|
||||||
|
for (i=0; i<dwRecvLength; i++)
|
||||||
|
printf("%02X ", pbRecvBuffer[i]);
|
||||||
|
printf("\n");
|
||||||
|
PCSC_ERROR(rv, "SCardTransmit")
|
||||||
|
|
||||||
|
/* card reconnect */
|
||||||
|
rv = SCardReconnect(hCard, SCARD_SHARE_SHARED,
|
||||||
|
SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, SCARD_LEAVE_CARD,
|
||||||
|
&dwActiveProtocol);
|
||||||
|
PCSC_ERROR(rv, "SCardReconnect")
|
||||||
|
|
||||||
|
/* get card status */
|
||||||
|
dwAtrLen = sizeof(pbAtr);
|
||||||
|
dwReaderLen = sizeof(pbReader);
|
||||||
|
rv = SCardStatus(hCard, /*NULL*/ pbReader, &dwReaderLen, &dwState, &dwProt,
|
||||||
|
pbAtr, &dwAtrLen);
|
||||||
|
printf(" Reader: %s (length %ld bytes)\n", pbReader, dwReaderLen);
|
||||||
|
printf(" State: 0x%lX\n", dwState);
|
||||||
|
printf(" Prot: %ld\n", dwProt);
|
||||||
|
printf(" ATR (length %ld bytes):", dwAtrLen);
|
||||||
|
for (i=0; i<dwAtrLen; i++)
|
||||||
|
printf(" %02X", pbAtr[i]);
|
||||||
|
printf("\n");
|
||||||
|
PCSC_ERROR(rv, "SCardStatus")
|
||||||
|
|
||||||
|
/* get card status change */
|
||||||
|
{
|
||||||
|
/* check only one reader */
|
||||||
|
SCARD_READERSTATE rgReaderStates[1];
|
||||||
|
|
||||||
|
rgReaderStates[0].szReader = pbReader;
|
||||||
|
rgReaderStates[0].dwCurrentState = SCARD_STATE_UNAWARE;
|
||||||
|
|
||||||
|
rv = SCardGetStatusChange(hContext, 0, rgReaderStates, 1);
|
||||||
|
printf(" state: 0x%04lX\n", rgReaderStates[0].dwEventState);
|
||||||
|
PCSC_ERROR(rv, "SCardGetStatusChange")
|
||||||
|
}
|
||||||
|
|
||||||
|
/* begin transaction */
|
||||||
|
rv = SCardBeginTransaction(hCard);
|
||||||
|
PCSC_ERROR(rv, "SCardBeginTransaction")
|
||||||
|
|
||||||
|
/* exchange APDU */
|
||||||
|
dwSendLength = sizeof(pbSendBuffer);
|
||||||
|
dwRecvLength = sizeof(pbRecvBuffer);
|
||||||
|
printf("Sending: ");
|
||||||
|
for (i=0; i<dwSendLength; i++)
|
||||||
|
printf("%02X ", pbSendBuffer[i]);
|
||||||
|
printf("\n");
|
||||||
|
rv = SCardTransmit(hCard, pioSendPci, pbSendBuffer, dwSendLength,
|
||||||
|
&pioRecvPci, pbRecvBuffer, &dwRecvLength);
|
||||||
|
printf("Received: ");
|
||||||
|
for (i=0; i<dwRecvLength; i++)
|
||||||
|
printf("%02X ", pbRecvBuffer[i]);
|
||||||
|
printf("\n");
|
||||||
|
PCSC_ERROR(rv, "SCardTransmit")
|
||||||
|
|
||||||
|
/* end transaction */
|
||||||
|
rv = SCardEndTransaction(hCard, SCARD_LEAVE_CARD);
|
||||||
|
PCSC_ERROR(rv, "SCardEndTransaction")
|
||||||
|
|
||||||
|
/* card disconnect */
|
||||||
|
rv = SCardDisconnect(hCard, SCARD_UNPOWER_CARD);
|
||||||
|
PCSC_ERROR(rv, "SCardDisconnect")
|
||||||
|
|
||||||
|
end:
|
||||||
|
/* free allocated memory */
|
||||||
|
if (mszReaders)
|
||||||
|
SCardFreeMemory(hContext, mszReaders);
|
||||||
|
|
||||||
|
/* We try to leave things as clean as possible */
|
||||||
|
rv = SCardReleaseContext(hContext);
|
||||||
|
if (rv != SCARD_S_SUCCESS)
|
||||||
|
printf("SCardReleaseContext: %s (0x%lX)\n", pcsc_stringify_error(rv),
|
||||||
|
rv);
|
||||||
|
|
||||||
|
if (readers)
|
||||||
|
free(readers);
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
} /* main */
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
.TH formaticc 1 "August 2005" Muscle "PC/SC Lite"
|
||||||
|
.SH NAME
|
||||||
|
formaticc \- An APDU robot for pcsc\-lite
|
||||||
|
.
|
||||||
|
.SH SYNTAX
|
||||||
|
.B formaticc
|
||||||
|
.
|
||||||
|
.SH DESCRIPTION
|
||||||
|
.B formaticc
|
||||||
|
sends one or more request APDU's to a smart card and get responses.
|
||||||
|
.PP
|
||||||
|
.B formaticc
|
||||||
|
takes a set of APDU's from an input file
|
||||||
|
and generates an output file with the data returned by the card.
|
||||||
|
.PP
|
||||||
|
The input and output file names and the identification of the reader
|
||||||
|
to connect to are prompted to the user.
|
||||||
|
.PP
|
||||||
|
The input file contains an APDU per line. Each line contains the length in
|
||||||
|
bytes of the APDU and the APDU octets in hexadecimal notation, separated by
|
||||||
|
space characters. The generated output file contains response APDU's
|
||||||
|
following the same format.
|
||||||
|
.
|
||||||
|
.SH "EXAMPLE FILES"
|
||||||
|
.TP
|
||||||
|
sample input file:
|
||||||
|
05 C0 84 00 00 08
|
||||||
|
05 C0 84 00 00 08
|
||||||
|
07 C0 A4 00 00 02 3F 00
|
||||||
|
07 C0 A4 00 00 02 3F 00
|
||||||
|
.TP
|
||||||
|
sample output file:
|
||||||
|
02 6e 00
|
||||||
|
.SH AUTHORS
|
||||||
|
This manual page was written by Carlos Prados <cprados@debian.org>,
|
||||||
|
for the Debian GNU/Linux system (but may be used by others).
|
||||||
|
.
|
||||||
|
.SH "SEE ALSO"
|
||||||
|
.BR pcscd (8)
|
|
@ -0,0 +1,30 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE policyconfig PUBLIC
|
||||||
|
"-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
|
||||||
|
"http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd">
|
||||||
|
<policyconfig>
|
||||||
|
<vendor>The PCSC-lite Project</vendor>
|
||||||
|
<vendor_url>http://pcsclite.alioth.debian.org/</vendor_url>
|
||||||
|
<!-- <icon_name>smart-card</icon_name> -->
|
||||||
|
|
||||||
|
<action id="org.debian.pcsc-lite.access_pcsc">
|
||||||
|
<description>Access to the PC/SC daemon</description>
|
||||||
|
<message>Authentication is required to access the PC/SC daemon</message>
|
||||||
|
<defaults>
|
||||||
|
<allow_any>no</allow_any>
|
||||||
|
<allow_inactive>no</allow_inactive>
|
||||||
|
<allow_active>yes</allow_active>
|
||||||
|
</defaults>
|
||||||
|
</action>
|
||||||
|
|
||||||
|
<action id="org.debian.pcsc-lite.access_card">
|
||||||
|
<description>Access to the smart card</description>
|
||||||
|
<message>Authentication is required to access the smart card</message>
|
||||||
|
<defaults>
|
||||||
|
<allow_any>no</allow_any>
|
||||||
|
<allow_inactive>no</allow_inactive>
|
||||||
|
<allow_active>yes</allow_active>
|
||||||
|
</defaults>
|
||||||
|
</action>
|
||||||
|
|
||||||
|
</policyconfig>
|
|
@ -0,0 +1,131 @@
|
||||||
|
.TH PCSCD 8 "January 2007" Muscle "PC/SC Lite"
|
||||||
|
.SH NAME
|
||||||
|
pcscd \- PC/SC Smart Card Daemon
|
||||||
|
.
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B pcscd
|
||||||
|
.RI [ options ]
|
||||||
|
.
|
||||||
|
.SH OPTIONS
|
||||||
|
.TP
|
||||||
|
.BR -a ", " \-\-apdu
|
||||||
|
log APDUs and SW using the debug method (see
|
||||||
|
.BR \-\-debug ).
|
||||||
|
.TP
|
||||||
|
.BR \-c ", " \-\-config " \fIfile\fP"
|
||||||
|
Specifies the file \fIfile\fP as an alternate location for
|
||||||
|
.IR @confdir_exp@/reader.conf .
|
||||||
|
.TP
|
||||||
|
.BR \-f ", " \-\-foreground
|
||||||
|
Runs pcscd in the foreground and sends log messages to stderr instead of
|
||||||
|
syslog(3).
|
||||||
|
.TP
|
||||||
|
.BR \-T ", " \-\-color
|
||||||
|
force use of colored logs.
|
||||||
|
.TP
|
||||||
|
.BR \-d ", " \-\-debug
|
||||||
|
use the lowest log level. Any log message of this level or above will be
|
||||||
|
sent to stderr or syslog(3) depending on the use of
|
||||||
|
.BR \-\-foreground .
|
||||||
|
.TP
|
||||||
|
.B \-\-info
|
||||||
|
use info log level. This is the default log level.
|
||||||
|
.TP
|
||||||
|
.BR \-e ", " \-\-error
|
||||||
|
use error log level.
|
||||||
|
.TP
|
||||||
|
.BR \-C ", " \-\-critical
|
||||||
|
use critical log level.
|
||||||
|
.PP
|
||||||
|
The log levels are ordered as: debug < info < error < critical. Use a
|
||||||
|
log level l will log this level and all the levels above it.
|
||||||
|
.TP
|
||||||
|
.B \-\-force\-reader\-polling
|
||||||
|
ignore the IFD_GENERATE_HOTPLUG reader capability
|
||||||
|
.TP
|
||||||
|
.BR \-t ", " \-\-max\-thread
|
||||||
|
maximum number of threads (default 200).
|
||||||
|
|
||||||
|
This is the maximum number of clients (SCardEstablishContext) that pcscd
|
||||||
|
can handle.
|
||||||
|
.TP
|
||||||
|
.BR \-s ", " \-\-max\-card\-handle\-per\-thread
|
||||||
|
maximum number of card handle per thread (default: 200).
|
||||||
|
|
||||||
|
This is the maximum number of card handle (SCardConnect) per client
|
||||||
|
(SCardEstablishContext).
|
||||||
|
.TP
|
||||||
|
.BR \-r ", " \-\-max\-card\-handle\-per\-reader
|
||||||
|
maximum number of card handle per reader (default: 200)
|
||||||
|
|
||||||
|
This is the maximum number of card handle (SCardConnect) per reader.
|
||||||
|
.TP
|
||||||
|
.BR \-h ", " \-\-help
|
||||||
|
Displays information about the pcscd command line
|
||||||
|
.TP
|
||||||
|
.BR \-v ", " \-\-version
|
||||||
|
Displays the program version number
|
||||||
|
.TP
|
||||||
|
.BR \-H ", " \-\-hotplug
|
||||||
|
Ask pcscd to re-read the
|
||||||
|
.I @confdir_exp@/reader.conf
|
||||||
|
file to detect added or removed non-USB readers (serial or PCMCIA).
|
||||||
|
.
|
||||||
|
.TP
|
||||||
|
.BR \-x ", " \-\-auto\-exit
|
||||||
|
pcscd will quit after 60 seconds of inactivity. This is used when pcscd
|
||||||
|
os started on demand by systemd.
|
||||||
|
.TP
|
||||||
|
.BR \-S ", " \-\-reader\-name\-no\-serial
|
||||||
|
Do not include the USB serial number in the reader name.
|
||||||
|
.TP
|
||||||
|
.BR \-I ", " \-\-reader\-name\-no\-interface
|
||||||
|
Do not include the USB interface name in the reader name.
|
||||||
|
.SH DESCRIPTION
|
||||||
|
pcscd is the daemon program for pcsc-lite. It is a resource manager that
|
||||||
|
coordinates communications with smart card readers and smart cards and
|
||||||
|
cryptographic tokens that are connected to the system.
|
||||||
|
.PP
|
||||||
|
It allows applications to access smart cards and readers using the
|
||||||
|
winscard API but without knowing details of the card or reader.
|
||||||
|
.PP
|
||||||
|
pcscd coordinates the loading of drivers for card readers.
|
||||||
|
.
|
||||||
|
.SH "SERIAL SMART CARD READER DRIVERS"
|
||||||
|
Smart card reader drivers are placed in the
|
||||||
|
.I @usbdropdir@
|
||||||
|
directory. Each driver is simply an
|
||||||
|
.I .so
|
||||||
|
file. pcscd locates the driver using the
|
||||||
|
.I @confdir_exp@/reader.conf
|
||||||
|
file. See the
|
||||||
|
.BR reader.conf (5)
|
||||||
|
manual page for more information.
|
||||||
|
.PP
|
||||||
|
Some drivers are available at \fIhttp://pcsclite.alioth.debian.org/musclecard.com/drivers.html\fP.
|
||||||
|
.
|
||||||
|
.SH "USB SMART CARD READER DRIVERS"
|
||||||
|
USB smart card reader drivers are located in
|
||||||
|
.I @usbdropdir@
|
||||||
|
directory as a bundle. You shall not add a USB driver in
|
||||||
|
.I @confdir_exp@/reader.conf
|
||||||
|
file.
|
||||||
|
.
|
||||||
|
.SH FILES
|
||||||
|
.I @confdir_exp@/reader.conf
|
||||||
|
: Reader configuration file
|
||||||
|
.PP
|
||||||
|
.I @ipcdir@/pcscd.pid
|
||||||
|
: process id of the running pcscd
|
||||||
|
.PP
|
||||||
|
.I @usbdropdir@
|
||||||
|
: directory containing bundles for USB drivers
|
||||||
|
.
|
||||||
|
.SH "SEE ALSO"
|
||||||
|
.BR bundleTool (8),
|
||||||
|
.BR reader.conf (5),
|
||||||
|
.BR syslog (3)
|
||||||
|
.
|
||||||
|
.SH AUTHORS
|
||||||
|
David Corcoran <corcoran@musclecard.com> and Ludovic Rousseau
|
||||||
|
<ludovic.rousseau@free.fr>
|
|
@ -0,0 +1,78 @@
|
||||||
|
.TH READER.CONF 5 "August 2005" Muscle "PC/SC Lite"
|
||||||
|
.SH NAME
|
||||||
|
reader.conf \- configuration file for pcscd readers' drivers
|
||||||
|
.
|
||||||
|
.SH DESCRIPTION
|
||||||
|
The
|
||||||
|
.I @confdir_exp@/reader.conf
|
||||||
|
file contains configuration information for serial and (some) PCMCIA
|
||||||
|
smart card readers.
|
||||||
|
.PP
|
||||||
|
USB readers SHALL NOT be configured using this file.
|
||||||
|
.B pcscd
|
||||||
|
uses another mechanism to automatically load USB drivers.
|
||||||
|
.
|
||||||
|
.SH SYNTAX
|
||||||
|
The
|
||||||
|
.I @confdir_exp@/reader.conf
|
||||||
|
is a regular text file. Each reader must be defined by four fields:
|
||||||
|
.PP
|
||||||
|
FRIENDLYNAME TEXT_STRING
|
||||||
|
DEVICENAME FILENAME
|
||||||
|
LIBPATH FILENAME
|
||||||
|
CHANNELID NUMBER
|
||||||
|
.PP
|
||||||
|
The "FRIENDLYNAME" field is an arbitrary text used to identify the
|
||||||
|
reader. This text is displayed by commands like
|
||||||
|
.BR pcsc_scan (1)
|
||||||
|
that prints the names of all the connected and detected readers.
|
||||||
|
.PP
|
||||||
|
The "DEVICENAME" field was not used for old drivers (using the IFD
|
||||||
|
handler version 2.0 or earlier). It is now (IFD handler version 3.0) used
|
||||||
|
to identify the physical port on which the reader is connected. This
|
||||||
|
is the device name of this port. It is dependent of the OS kernel. The
|
||||||
|
first serial port device is called
|
||||||
|
.I /dev/ttyS0
|
||||||
|
under Linux and
|
||||||
|
.I /dev/cuaa0
|
||||||
|
under FreeBSD.
|
||||||
|
.PP
|
||||||
|
The "LIBPATH" field is the filename of the driver code. The driver is
|
||||||
|
a dynamically loaded piece of code (generally a
|
||||||
|
.IR drivername.so* file).
|
||||||
|
.PP
|
||||||
|
The "CHANNELID" is no more used for recent drivers (IFD handler 3.0) and
|
||||||
|
has been superseded by "DEVICENAME". If you have an old driver this
|
||||||
|
field is used to indicate the port to use. You should read your driver
|
||||||
|
documentation to know what information is needed here. It should be the
|
||||||
|
serial port number for a serial reader.
|
||||||
|
.
|
||||||
|
.SH EXAMPLE
|
||||||
|
# Gemplus GemPCTwin reader with serial communication
|
||||||
|
# connected to the first serial port
|
||||||
|
FRIENDLYNAME "GemPCTwin serial"
|
||||||
|
DEVICENAME /dev/ttyS0
|
||||||
|
LIBPATH @usbdropdir@/serial/libccidtwin.so.0.4.1
|
||||||
|
CHANNELID 1
|
||||||
|
.
|
||||||
|
.SH DEBUGGING
|
||||||
|
In order to set up your
|
||||||
|
.I @confdir_exp@/reader.conf
|
||||||
|
file correctly you may want to have debug messages from
|
||||||
|
.BR pcscd .
|
||||||
|
I recommend you to start
|
||||||
|
.B pscsd
|
||||||
|
in the foreground and debug mode using:
|
||||||
|
# pcscd \-\-foreground \-\-debug
|
||||||
|
.PP
|
||||||
|
If everything seems OK you can use the
|
||||||
|
.B pcsc_scan
|
||||||
|
command to print the list of correctly detected readers and try to get
|
||||||
|
the ATR of your smart cards.
|
||||||
|
.
|
||||||
|
.SH AUTHOR
|
||||||
|
Ludovic Rousseau <ludovic.rousseau@free.fr>
|
||||||
|
.
|
||||||
|
.SH SEE ALSO
|
||||||
|
.BR pcscd (8),
|
||||||
|
.BR pcsc_scan (1)
|
|
@ -0,0 +1,9 @@
|
||||||
|
if HAVE_SYSTEMD
|
||||||
|
SCRIPT_IN_FILES = \
|
||||||
|
pcscd.service.in \
|
||||||
|
pcscd.socket.in
|
||||||
|
|
||||||
|
systemdsystemunit_DATA = \
|
||||||
|
pcscd.service \
|
||||||
|
pcscd.socket
|
||||||
|
endif
|
|
@ -0,0 +1,538 @@
|
||||||
|
# Makefile.in generated by automake 1.15 from Makefile.am.
|
||||||
|
# @configure_input@
|
||||||
|
|
||||||
|
# Copyright (C) 1994-2014 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
# This Makefile.in is free software; the Free Software Foundation
|
||||||
|
# gives unlimited permission to copy and/or distribute it,
|
||||||
|
# with or without modifications, as long as this notice is preserved.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||||
|
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||||
|
# PARTICULAR PURPOSE.
|
||||||
|
|
||||||
|
@SET_MAKE@
|
||||||
|
|
||||||
|
VPATH = @srcdir@
|
||||||
|
am__is_gnu_make = { \
|
||||||
|
if test -z '$(MAKELEVEL)'; then \
|
||||||
|
false; \
|
||||||
|
elif test -n '$(MAKE_HOST)'; then \
|
||||||
|
true; \
|
||||||
|
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
|
||||||
|
true; \
|
||||||
|
else \
|
||||||
|
false; \
|
||||||
|
fi; \
|
||||||
|
}
|
||||||
|
am__make_running_with_option = \
|
||||||
|
case $${target_option-} in \
|
||||||
|
?) ;; \
|
||||||
|
*) echo "am__make_running_with_option: internal error: invalid" \
|
||||||
|
"target option '$${target_option-}' specified" >&2; \
|
||||||
|
exit 1;; \
|
||||||
|
esac; \
|
||||||
|
has_opt=no; \
|
||||||
|
sane_makeflags=$$MAKEFLAGS; \
|
||||||
|
if $(am__is_gnu_make); then \
|
||||||
|
sane_makeflags=$$MFLAGS; \
|
||||||
|
else \
|
||||||
|
case $$MAKEFLAGS in \
|
||||||
|
*\\[\ \ ]*) \
|
||||||
|
bs=\\; \
|
||||||
|
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
|
||||||
|
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
|
||||||
|
esac; \
|
||||||
|
fi; \
|
||||||
|
skip_next=no; \
|
||||||
|
strip_trailopt () \
|
||||||
|
{ \
|
||||||
|
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
|
||||||
|
}; \
|
||||||
|
for flg in $$sane_makeflags; do \
|
||||||
|
test $$skip_next = yes && { skip_next=no; continue; }; \
|
||||||
|
case $$flg in \
|
||||||
|
*=*|--*) continue;; \
|
||||||
|
-*I) strip_trailopt 'I'; skip_next=yes;; \
|
||||||
|
-*I?*) strip_trailopt 'I';; \
|
||||||
|
-*O) strip_trailopt 'O'; skip_next=yes;; \
|
||||||
|
-*O?*) strip_trailopt 'O';; \
|
||||||
|
-*l) strip_trailopt 'l'; skip_next=yes;; \
|
||||||
|
-*l?*) strip_trailopt 'l';; \
|
||||||
|
-[dEDm]) skip_next=yes;; \
|
||||||
|
-[JT]) skip_next=yes;; \
|
||||||
|
esac; \
|
||||||
|
case $$flg in \
|
||||||
|
*$$target_option*) has_opt=yes; break;; \
|
||||||
|
esac; \
|
||||||
|
done; \
|
||||||
|
test $$has_opt = yes
|
||||||
|
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
|
||||||
|
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
|
||||||
|
pkgdatadir = $(datadir)/@PACKAGE@
|
||||||
|
pkgincludedir = $(includedir)/@PACKAGE@
|
||||||
|
pkglibdir = $(libdir)/@PACKAGE@
|
||||||
|
pkglibexecdir = $(libexecdir)/@PACKAGE@
|
||||||
|
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||||
|
install_sh_DATA = $(install_sh) -c -m 644
|
||||||
|
install_sh_PROGRAM = $(install_sh) -c
|
||||||
|
install_sh_SCRIPT = $(install_sh) -c
|
||||||
|
INSTALL_HEADER = $(INSTALL_DATA)
|
||||||
|
transform = $(program_transform_name)
|
||||||
|
NORMAL_INSTALL = :
|
||||||
|
PRE_INSTALL = :
|
||||||
|
POST_INSTALL = :
|
||||||
|
NORMAL_UNINSTALL = :
|
||||||
|
PRE_UNINSTALL = :
|
||||||
|
POST_UNINSTALL = :
|
||||||
|
build_triplet = @build@
|
||||||
|
host_triplet = @host@
|
||||||
|
subdir = etc
|
||||||
|
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||||
|
am__aclocal_m4_deps = $(top_srcdir)/m4/as-ac-expand.m4 \
|
||||||
|
$(top_srcdir)/m4/ax_pthread.m4 $(top_srcdir)/m4/libtool.m4 \
|
||||||
|
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
|
||||||
|
$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
|
||||||
|
$(top_srcdir)/configure.ac
|
||||||
|
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||||
|
$(ACLOCAL_M4)
|
||||||
|
DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
|
||||||
|
mkinstalldirs = $(install_sh) -d
|
||||||
|
CONFIG_HEADER = $(top_builddir)/config.h
|
||||||
|
CONFIG_CLEAN_FILES = pcscd.service pcscd.socket
|
||||||
|
CONFIG_CLEAN_VPATH_FILES =
|
||||||
|
AM_V_P = $(am__v_P_@AM_V@)
|
||||||
|
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
|
||||||
|
am__v_P_0 = false
|
||||||
|
am__v_P_1 = :
|
||||||
|
AM_V_GEN = $(am__v_GEN_@AM_V@)
|
||||||
|
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
|
||||||
|
am__v_GEN_0 = @echo " GEN " $@;
|
||||||
|
am__v_GEN_1 =
|
||||||
|
AM_V_at = $(am__v_at_@AM_V@)
|
||||||
|
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
|
||||||
|
am__v_at_0 = @
|
||||||
|
am__v_at_1 =
|
||||||
|
SOURCES =
|
||||||
|
DIST_SOURCES =
|
||||||
|
am__can_run_installinfo = \
|
||||||
|
case $$AM_UPDATE_INFO_DIR in \
|
||||||
|
n|no|NO) false;; \
|
||||||
|
*) (install-info --version) >/dev/null 2>&1;; \
|
||||||
|
esac
|
||||||
|
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
|
||||||
|
am__vpath_adj = case $$p in \
|
||||||
|
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
|
||||||
|
*) f=$$p;; \
|
||||||
|
esac;
|
||||||
|
am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
|
||||||
|
am__install_max = 40
|
||||||
|
am__nobase_strip_setup = \
|
||||||
|
srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
|
||||||
|
am__nobase_strip = \
|
||||||
|
for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
|
||||||
|
am__nobase_list = $(am__nobase_strip_setup); \
|
||||||
|
for p in $$list; do echo "$$p $$p"; done | \
|
||||||
|
sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
|
||||||
|
$(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
|
||||||
|
if (++n[$$2] == $(am__install_max)) \
|
||||||
|
{ print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
|
||||||
|
END { for (dir in files) print dir, files[dir] }'
|
||||||
|
am__base_list = \
|
||||||
|
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
|
||||||
|
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
|
||||||
|
am__uninstall_files_from_dir = { \
|
||||||
|
test -z "$$files" \
|
||||||
|
|| { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
|
||||||
|
|| { echo " ( cd '$$dir' && rm -f" $$files ")"; \
|
||||||
|
$(am__cd) "$$dir" && rm -f $$files; }; \
|
||||||
|
}
|
||||||
|
am__installdirs = "$(DESTDIR)$(systemdsystemunitdir)"
|
||||||
|
DATA = $(systemdsystemunit_DATA)
|
||||||
|
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
|
||||||
|
am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/pcscd.service.in \
|
||||||
|
$(srcdir)/pcscd.socket.in
|
||||||
|
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||||
|
ACLOCAL = @ACLOCAL@
|
||||||
|
ALLOCA = @ALLOCA@
|
||||||
|
AMTAR = @AMTAR@
|
||||||
|
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
|
||||||
|
AR = @AR@
|
||||||
|
AUTOCONF = @AUTOCONF@
|
||||||
|
AUTOHEADER = @AUTOHEADER@
|
||||||
|
AUTOMAKE = @AUTOMAKE@
|
||||||
|
AWK = @AWK@
|
||||||
|
CC = @CC@
|
||||||
|
CCDEPMODE = @CCDEPMODE@
|
||||||
|
CFLAGS = @CFLAGS@
|
||||||
|
COREFOUNDATION = @COREFOUNDATION@
|
||||||
|
CPP = @CPP@
|
||||||
|
CPPFLAGS = @CPPFLAGS@
|
||||||
|
CYGPATH_W = @CYGPATH_W@
|
||||||
|
DEFS = @DEFS@
|
||||||
|
DEPDIR = @DEPDIR@
|
||||||
|
DLLTOOL = @DLLTOOL@
|
||||||
|
DSYMUTIL = @DSYMUTIL@
|
||||||
|
DUMPBIN = @DUMPBIN@
|
||||||
|
ECHO_C = @ECHO_C@
|
||||||
|
ECHO_N = @ECHO_N@
|
||||||
|
ECHO_T = @ECHO_T@
|
||||||
|
EGREP = @EGREP@
|
||||||
|
EXEEXT = @EXEEXT@
|
||||||
|
FGREP = @FGREP@
|
||||||
|
GREP = @GREP@
|
||||||
|
INSTALL = @INSTALL@
|
||||||
|
INSTALL_DATA = @INSTALL_DATA@
|
||||||
|
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||||
|
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||||
|
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||||
|
IOKIT = @IOKIT@
|
||||||
|
LD = @LD@
|
||||||
|
LDFLAGS = @LDFLAGS@
|
||||||
|
LEX = @LEX@
|
||||||
|
LEXLIB = @LEXLIB@
|
||||||
|
LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
|
||||||
|
LIBOBJS = @LIBOBJS@
|
||||||
|
LIBS = @LIBS@
|
||||||
|
LIBTOOL = @LIBTOOL@
|
||||||
|
LIBUDEV_CFLAGS = @LIBUDEV_CFLAGS@
|
||||||
|
LIBUDEV_LIBS = @LIBUDEV_LIBS@
|
||||||
|
LIBUSBCONFIG = @LIBUSBCONFIG@
|
||||||
|
LIBUSB_CFLAGS = @LIBUSB_CFLAGS@
|
||||||
|
LIBUSB_LIBS = @LIBUSB_LIBS@
|
||||||
|
LIPO = @LIPO@
|
||||||
|
LN_S = @LN_S@
|
||||||
|
LTLIBOBJS = @LTLIBOBJS@
|
||||||
|
LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
|
||||||
|
MAINT = @MAINT@
|
||||||
|
MAKEINFO = @MAKEINFO@
|
||||||
|
MANIFEST_TOOL = @MANIFEST_TOOL@
|
||||||
|
MKDIR_P = @MKDIR_P@
|
||||||
|
NM = @NM@
|
||||||
|
NMEDIT = @NMEDIT@
|
||||||
|
OBJDUMP = @OBJDUMP@
|
||||||
|
OBJEXT = @OBJEXT@
|
||||||
|
OTOOL = @OTOOL@
|
||||||
|
OTOOL64 = @OTOOL64@
|
||||||
|
PACKAGE = @PACKAGE@
|
||||||
|
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||||
|
PACKAGE_NAME = @PACKAGE_NAME@
|
||||||
|
PACKAGE_STRING = @PACKAGE_STRING@
|
||||||
|
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||||
|
PACKAGE_URL = @PACKAGE_URL@
|
||||||
|
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||||
|
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||||
|
PCSCLITE_CONFIG_DIR = @PCSCLITE_CONFIG_DIR@
|
||||||
|
PKG_CONFIG = @PKG_CONFIG@
|
||||||
|
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
|
||||||
|
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
|
||||||
|
POLICY_DIR = @POLICY_DIR@
|
||||||
|
POLKIT_CFLAGS = @POLKIT_CFLAGS@
|
||||||
|
POLKIT_LIBS = @POLKIT_LIBS@
|
||||||
|
PTHREAD_CC = @PTHREAD_CC@
|
||||||
|
PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
|
||||||
|
PTHREAD_LIBS = @PTHREAD_LIBS@
|
||||||
|
RANLIB = @RANLIB@
|
||||||
|
SED = @SED@
|
||||||
|
SET_MAKE = @SET_MAKE@
|
||||||
|
SHELL = @SHELL@
|
||||||
|
STRIP = @STRIP@
|
||||||
|
SYMBOL_VISIBILITY = @SYMBOL_VISIBILITY@
|
||||||
|
VERSION = @VERSION@
|
||||||
|
abs_builddir = @abs_builddir@
|
||||||
|
abs_srcdir = @abs_srcdir@
|
||||||
|
abs_top_builddir = @abs_top_builddir@
|
||||||
|
abs_top_srcdir = @abs_top_srcdir@
|
||||||
|
ac_ct_AR = @ac_ct_AR@
|
||||||
|
ac_ct_CC = @ac_ct_CC@
|
||||||
|
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
|
||||||
|
am__include = @am__include@
|
||||||
|
am__leading_dot = @am__leading_dot@
|
||||||
|
am__quote = @am__quote@
|
||||||
|
am__tar = @am__tar@
|
||||||
|
am__untar = @am__untar@
|
||||||
|
ax_pthread_config = @ax_pthread_config@
|
||||||
|
bindir = @bindir@
|
||||||
|
build = @build@
|
||||||
|
build_alias = @build_alias@
|
||||||
|
build_cpu = @build_cpu@
|
||||||
|
build_os = @build_os@
|
||||||
|
build_vendor = @build_vendor@
|
||||||
|
builddir = @builddir@
|
||||||
|
confdir_exp = @confdir_exp@
|
||||||
|
datadir = @datadir@
|
||||||
|
datarootdir = @datarootdir@
|
||||||
|
docdir = @docdir@
|
||||||
|
dvidir = @dvidir@
|
||||||
|
exec_prefix = @exec_prefix@
|
||||||
|
host = @host@
|
||||||
|
host_alias = @host_alias@
|
||||||
|
host_cpu = @host_cpu@
|
||||||
|
host_os = @host_os@
|
||||||
|
host_to_ccid_16 = @host_to_ccid_16@
|
||||||
|
host_to_ccid_32 = @host_to_ccid_32@
|
||||||
|
host_vendor = @host_vendor@
|
||||||
|
htmldir = @htmldir@
|
||||||
|
includedir = @includedir@
|
||||||
|
infodir = @infodir@
|
||||||
|
install_sh = @install_sh@
|
||||||
|
ipcdir = @ipcdir@
|
||||||
|
libdir = @libdir@
|
||||||
|
libexecdir = @libexecdir@
|
||||||
|
localedir = @localedir@
|
||||||
|
localstatedir = @localstatedir@
|
||||||
|
localstatedir_exp = @localstatedir_exp@
|
||||||
|
mandir = @mandir@
|
||||||
|
mkdir_p = @mkdir_p@
|
||||||
|
oldincludedir = @oldincludedir@
|
||||||
|
pdfdir = @pdfdir@
|
||||||
|
prefix = @prefix@
|
||||||
|
program_transform_name = @program_transform_name@
|
||||||
|
psdir = @psdir@
|
||||||
|
runstatedir = @runstatedir@
|
||||||
|
sbindir = @sbindir@
|
||||||
|
sbindir_exp = @sbindir_exp@
|
||||||
|
serialconfdir = @serialconfdir@
|
||||||
|
sharedstatedir = @sharedstatedir@
|
||||||
|
srcdir = @srcdir@
|
||||||
|
sysconfdir = @sysconfdir@
|
||||||
|
systemdsystemunitdir = @systemdsystemunitdir@
|
||||||
|
target_alias = @target_alias@
|
||||||
|
top_build_prefix = @top_build_prefix@
|
||||||
|
top_builddir = @top_builddir@
|
||||||
|
top_srcdir = @top_srcdir@
|
||||||
|
usbdropdir = @usbdropdir@
|
||||||
|
usbdropdir_exp = @usbdropdir_exp@
|
||||||
|
@HAVE_SYSTEMD_TRUE@SCRIPT_IN_FILES = \
|
||||||
|
@HAVE_SYSTEMD_TRUE@ pcscd.service.in \
|
||||||
|
@HAVE_SYSTEMD_TRUE@ pcscd.socket.in
|
||||||
|
|
||||||
|
@HAVE_SYSTEMD_TRUE@systemdsystemunit_DATA = \
|
||||||
|
@HAVE_SYSTEMD_TRUE@ pcscd.service \
|
||||||
|
@HAVE_SYSTEMD_TRUE@ pcscd.socket
|
||||||
|
|
||||||
|
all: all-am
|
||||||
|
|
||||||
|
.SUFFIXES:
|
||||||
|
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
|
||||||
|
@for dep in $?; do \
|
||||||
|
case '$(am__configure_deps)' in \
|
||||||
|
*$$dep*) \
|
||||||
|
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
|
||||||
|
&& { if test -f $@; then exit 0; else break; fi; }; \
|
||||||
|
exit 1;; \
|
||||||
|
esac; \
|
||||||
|
done; \
|
||||||
|
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu etc/Makefile'; \
|
||||||
|
$(am__cd) $(top_srcdir) && \
|
||||||
|
$(AUTOMAKE) --gnu etc/Makefile
|
||||||
|
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||||
|
@case '$?' in \
|
||||||
|
*config.status*) \
|
||||||
|
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
|
||||||
|
*) \
|
||||||
|
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
|
||||||
|
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
|
||||||
|
esac;
|
||||||
|
|
||||||
|
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||||
|
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||||
|
|
||||||
|
$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
|
||||||
|
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||||
|
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
|
||||||
|
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||||
|
$(am__aclocal_m4_deps):
|
||||||
|
pcscd.service: $(top_builddir)/config.status $(srcdir)/pcscd.service.in
|
||||||
|
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
|
||||||
|
pcscd.socket: $(top_builddir)/config.status $(srcdir)/pcscd.socket.in
|
||||||
|
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
|
||||||
|
|
||||||
|
mostlyclean-libtool:
|
||||||
|
-rm -f *.lo
|
||||||
|
|
||||||
|
clean-libtool:
|
||||||
|
-rm -rf .libs _libs
|
||||||
|
install-systemdsystemunitDATA: $(systemdsystemunit_DATA)
|
||||||
|
@$(NORMAL_INSTALL)
|
||||||
|
@list='$(systemdsystemunit_DATA)'; test -n "$(systemdsystemunitdir)" || list=; \
|
||||||
|
if test -n "$$list"; then \
|
||||||
|
echo " $(MKDIR_P) '$(DESTDIR)$(systemdsystemunitdir)'"; \
|
||||||
|
$(MKDIR_P) "$(DESTDIR)$(systemdsystemunitdir)" || exit 1; \
|
||||||
|
fi; \
|
||||||
|
for p in $$list; do \
|
||||||
|
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
|
||||||
|
echo "$$d$$p"; \
|
||||||
|
done | $(am__base_list) | \
|
||||||
|
while read files; do \
|
||||||
|
echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(systemdsystemunitdir)'"; \
|
||||||
|
$(INSTALL_DATA) $$files "$(DESTDIR)$(systemdsystemunitdir)" || exit $$?; \
|
||||||
|
done
|
||||||
|
|
||||||
|
uninstall-systemdsystemunitDATA:
|
||||||
|
@$(NORMAL_UNINSTALL)
|
||||||
|
@list='$(systemdsystemunit_DATA)'; test -n "$(systemdsystemunitdir)" || list=; \
|
||||||
|
files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
|
||||||
|
dir='$(DESTDIR)$(systemdsystemunitdir)'; $(am__uninstall_files_from_dir)
|
||||||
|
tags TAGS:
|
||||||
|
|
||||||
|
ctags CTAGS:
|
||||||
|
|
||||||
|
cscope cscopelist:
|
||||||
|
|
||||||
|
|
||||||
|
distdir: $(DISTFILES)
|
||||||
|
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||||
|
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||||
|
list='$(DISTFILES)'; \
|
||||||
|
dist_files=`for file in $$list; do echo $$file; done | \
|
||||||
|
sed -e "s|^$$srcdirstrip/||;t" \
|
||||||
|
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
|
||||||
|
case $$dist_files in \
|
||||||
|
*/*) $(MKDIR_P) `echo "$$dist_files" | \
|
||||||
|
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
|
||||||
|
sort -u` ;; \
|
||||||
|
esac; \
|
||||||
|
for file in $$dist_files; do \
|
||||||
|
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||||
|
if test -d $$d/$$file; then \
|
||||||
|
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||||
|
if test -d "$(distdir)/$$file"; then \
|
||||||
|
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||||
|
fi; \
|
||||||
|
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||||
|
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
|
||||||
|
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||||
|
fi; \
|
||||||
|
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
|
||||||
|
else \
|
||||||
|
test -f "$(distdir)/$$file" \
|
||||||
|
|| cp -p $$d/$$file "$(distdir)/$$file" \
|
||||||
|
|| exit 1; \
|
||||||
|
fi; \
|
||||||
|
done
|
||||||
|
check-am: all-am
|
||||||
|
check: check-am
|
||||||
|
all-am: Makefile $(DATA)
|
||||||
|
installdirs:
|
||||||
|
for dir in "$(DESTDIR)$(systemdsystemunitdir)"; do \
|
||||||
|
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
|
||||||
|
done
|
||||||
|
install: install-am
|
||||||
|
install-exec: install-exec-am
|
||||||
|
install-data: install-data-am
|
||||||
|
uninstall: uninstall-am
|
||||||
|
|
||||||
|
install-am: all-am
|
||||||
|
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||||
|
|
||||||
|
installcheck: installcheck-am
|
||||||
|
install-strip:
|
||||||
|
if test -z '$(STRIP)'; then \
|
||||||
|
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||||
|
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||||
|
install; \
|
||||||
|
else \
|
||||||
|
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||||
|
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||||
|
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
|
||||||
|
fi
|
||||||
|
mostlyclean-generic:
|
||||||
|
|
||||||
|
clean-generic:
|
||||||
|
|
||||||
|
distclean-generic:
|
||||||
|
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||||
|
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
|
||||||
|
|
||||||
|
maintainer-clean-generic:
|
||||||
|
@echo "This command is intended for maintainers to use"
|
||||||
|
@echo "it deletes files that may require special tools to rebuild."
|
||||||
|
clean: clean-am
|
||||||
|
|
||||||
|
clean-am: clean-generic clean-libtool mostlyclean-am
|
||||||
|
|
||||||
|
distclean: distclean-am
|
||||||
|
-rm -f Makefile
|
||||||
|
distclean-am: clean-am distclean-generic
|
||||||
|
|
||||||
|
dvi: dvi-am
|
||||||
|
|
||||||
|
dvi-am:
|
||||||
|
|
||||||
|
html: html-am
|
||||||
|
|
||||||
|
html-am:
|
||||||
|
|
||||||
|
info: info-am
|
||||||
|
|
||||||
|
info-am:
|
||||||
|
|
||||||
|
install-data-am: install-systemdsystemunitDATA
|
||||||
|
|
||||||
|
install-dvi: install-dvi-am
|
||||||
|
|
||||||
|
install-dvi-am:
|
||||||
|
|
||||||
|
install-exec-am:
|
||||||
|
|
||||||
|
install-html: install-html-am
|
||||||
|
|
||||||
|
install-html-am:
|
||||||
|
|
||||||
|
install-info: install-info-am
|
||||||
|
|
||||||
|
install-info-am:
|
||||||
|
|
||||||
|
install-man:
|
||||||
|
|
||||||
|
install-pdf: install-pdf-am
|
||||||
|
|
||||||
|
install-pdf-am:
|
||||||
|
|
||||||
|
install-ps: install-ps-am
|
||||||
|
|
||||||
|
install-ps-am:
|
||||||
|
|
||||||
|
installcheck-am:
|
||||||
|
|
||||||
|
maintainer-clean: maintainer-clean-am
|
||||||
|
-rm -f Makefile
|
||||||
|
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||||
|
|
||||||
|
mostlyclean: mostlyclean-am
|
||||||
|
|
||||||
|
mostlyclean-am: mostlyclean-generic mostlyclean-libtool
|
||||||
|
|
||||||
|
pdf: pdf-am
|
||||||
|
|
||||||
|
pdf-am:
|
||||||
|
|
||||||
|
ps: ps-am
|
||||||
|
|
||||||
|
ps-am:
|
||||||
|
|
||||||
|
uninstall-am: uninstall-systemdsystemunitDATA
|
||||||
|
|
||||||
|
.MAKE: install-am install-strip
|
||||||
|
|
||||||
|
.PHONY: all all-am check check-am clean clean-generic clean-libtool \
|
||||||
|
cscopelist-am ctags-am distclean distclean-generic \
|
||||||
|
distclean-libtool distdir dvi dvi-am html html-am info info-am \
|
||||||
|
install install-am install-data install-data-am install-dvi \
|
||||||
|
install-dvi-am install-exec install-exec-am install-html \
|
||||||
|
install-html-am install-info install-info-am install-man \
|
||||||
|
install-pdf install-pdf-am install-ps install-ps-am \
|
||||||
|
install-strip install-systemdsystemunitDATA installcheck \
|
||||||
|
installcheck-am installdirs maintainer-clean \
|
||||||
|
maintainer-clean-generic mostlyclean mostlyclean-generic \
|
||||||
|
mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \
|
||||||
|
uninstall-am uninstall-systemdsystemunitDATA
|
||||||
|
|
||||||
|
.PRECIOUS: Makefile
|
||||||
|
|
||||||
|
|
||||||
|
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||||
|
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||||
|
.NOEXPORT:
|
|
@ -0,0 +1,10 @@
|
||||||
|
[Unit]
|
||||||
|
Description=PC/SC Smart Card Daemon
|
||||||
|
Requires=pcscd.socket
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart=@sbindir_exp@/pcscd --foreground --auto-exit
|
||||||
|
ExecReload=@sbindir_exp@/pcscd --hotplug
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
Also=pcscd.socket
|
|
@ -0,0 +1,8 @@
|
||||||
|
[Unit]
|
||||||
|
Description=PC/SC Smart Card Daemon Activation Socket
|
||||||
|
|
||||||
|
[Socket]
|
||||||
|
ListenStream=@ipcdir@/pcscd.comm
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=sockets.target
|
|
@ -0,0 +1,527 @@
|
||||||
|
#!/bin/sh
|
||||||
|
# install - install a program, script, or datafile
|
||||||
|
|
||||||
|
scriptversion=2011-11-20.07; # UTC
|
||||||
|
|
||||||
|
# This originates from X11R5 (mit/util/scripts/install.sh), which was
|
||||||
|
# later released in X11R6 (xc/config/util/install.sh) with the
|
||||||
|
# following copyright and license.
|
||||||
|
#
|
||||||
|
# Copyright (C) 1994 X Consortium
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||||
|
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
|
||||||
|
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
#
|
||||||
|
# Except as contained in this notice, the name of the X Consortium shall not
|
||||||
|
# be used in advertising or otherwise to promote the sale, use or other deal-
|
||||||
|
# ings in this Software without prior written authorization from the X Consor-
|
||||||
|
# tium.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# FSF changes to this file are in the public domain.
|
||||||
|
#
|
||||||
|
# Calling this script install-sh is preferred over install.sh, to prevent
|
||||||
|
# 'make' implicit rules from creating a file called install from it
|
||||||
|
# when there is no Makefile.
|
||||||
|
#
|
||||||
|
# This script is compatible with the BSD install script, but was written
|
||||||
|
# from scratch.
|
||||||
|
|
||||||
|
nl='
|
||||||
|
'
|
||||||
|
IFS=" "" $nl"
|
||||||
|
|
||||||
|
# set DOITPROG to echo to test this script
|
||||||
|
|
||||||
|
# Don't use :- since 4.3BSD and earlier shells don't like it.
|
||||||
|
doit=${DOITPROG-}
|
||||||
|
if test -z "$doit"; then
|
||||||
|
doit_exec=exec
|
||||||
|
else
|
||||||
|
doit_exec=$doit
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Put in absolute file names if you don't have them in your path;
|
||||||
|
# or use environment vars.
|
||||||
|
|
||||||
|
chgrpprog=${CHGRPPROG-chgrp}
|
||||||
|
chmodprog=${CHMODPROG-chmod}
|
||||||
|
chownprog=${CHOWNPROG-chown}
|
||||||
|
cmpprog=${CMPPROG-cmp}
|
||||||
|
cpprog=${CPPROG-cp}
|
||||||
|
mkdirprog=${MKDIRPROG-mkdir}
|
||||||
|
mvprog=${MVPROG-mv}
|
||||||
|
rmprog=${RMPROG-rm}
|
||||||
|
stripprog=${STRIPPROG-strip}
|
||||||
|
|
||||||
|
posix_glob='?'
|
||||||
|
initialize_posix_glob='
|
||||||
|
test "$posix_glob" != "?" || {
|
||||||
|
if (set -f) 2>/dev/null; then
|
||||||
|
posix_glob=
|
||||||
|
else
|
||||||
|
posix_glob=:
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
'
|
||||||
|
|
||||||
|
posix_mkdir=
|
||||||
|
|
||||||
|
# Desired mode of installed file.
|
||||||
|
mode=0755
|
||||||
|
|
||||||
|
chgrpcmd=
|
||||||
|
chmodcmd=$chmodprog
|
||||||
|
chowncmd=
|
||||||
|
mvcmd=$mvprog
|
||||||
|
rmcmd="$rmprog -f"
|
||||||
|
stripcmd=
|
||||||
|
|
||||||
|
src=
|
||||||
|
dst=
|
||||||
|
dir_arg=
|
||||||
|
dst_arg=
|
||||||
|
|
||||||
|
copy_on_change=false
|
||||||
|
no_target_directory=
|
||||||
|
|
||||||
|
usage="\
|
||||||
|
Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
|
||||||
|
or: $0 [OPTION]... SRCFILES... DIRECTORY
|
||||||
|
or: $0 [OPTION]... -t DIRECTORY SRCFILES...
|
||||||
|
or: $0 [OPTION]... -d DIRECTORIES...
|
||||||
|
|
||||||
|
In the 1st form, copy SRCFILE to DSTFILE.
|
||||||
|
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
|
||||||
|
In the 4th, create DIRECTORIES.
|
||||||
|
|
||||||
|
Options:
|
||||||
|
--help display this help and exit.
|
||||||
|
--version display version info and exit.
|
||||||
|
|
||||||
|
-c (ignored)
|
||||||
|
-C install only if different (preserve the last data modification time)
|
||||||
|
-d create directories instead of installing files.
|
||||||
|
-g GROUP $chgrpprog installed files to GROUP.
|
||||||
|
-m MODE $chmodprog installed files to MODE.
|
||||||
|
-o USER $chownprog installed files to USER.
|
||||||
|
-s $stripprog installed files.
|
||||||
|
-t DIRECTORY install into DIRECTORY.
|
||||||
|
-T report an error if DSTFILE is a directory.
|
||||||
|
|
||||||
|
Environment variables override the default commands:
|
||||||
|
CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
|
||||||
|
RMPROG STRIPPROG
|
||||||
|
"
|
||||||
|
|
||||||
|
while test $# -ne 0; do
|
||||||
|
case $1 in
|
||||||
|
-c) ;;
|
||||||
|
|
||||||
|
-C) copy_on_change=true;;
|
||||||
|
|
||||||
|
-d) dir_arg=true;;
|
||||||
|
|
||||||
|
-g) chgrpcmd="$chgrpprog $2"
|
||||||
|
shift;;
|
||||||
|
|
||||||
|
--help) echo "$usage"; exit $?;;
|
||||||
|
|
||||||
|
-m) mode=$2
|
||||||
|
case $mode in
|
||||||
|
*' '* | *' '* | *'
|
||||||
|
'* | *'*'* | *'?'* | *'['*)
|
||||||
|
echo "$0: invalid mode: $mode" >&2
|
||||||
|
exit 1;;
|
||||||
|
esac
|
||||||
|
shift;;
|
||||||
|
|
||||||
|
-o) chowncmd="$chownprog $2"
|
||||||
|
shift;;
|
||||||
|
|
||||||
|
-s) stripcmd=$stripprog;;
|
||||||
|
|
||||||
|
-t) dst_arg=$2
|
||||||
|
# Protect names problematic for 'test' and other utilities.
|
||||||
|
case $dst_arg in
|
||||||
|
-* | [=\(\)!]) dst_arg=./$dst_arg;;
|
||||||
|
esac
|
||||||
|
shift;;
|
||||||
|
|
||||||
|
-T) no_target_directory=true;;
|
||||||
|
|
||||||
|
--version) echo "$0 $scriptversion"; exit $?;;
|
||||||
|
|
||||||
|
--) shift
|
||||||
|
break;;
|
||||||
|
|
||||||
|
-*) echo "$0: invalid option: $1" >&2
|
||||||
|
exit 1;;
|
||||||
|
|
||||||
|
*) break;;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
|
||||||
|
# When -d is used, all remaining arguments are directories to create.
|
||||||
|
# When -t is used, the destination is already specified.
|
||||||
|
# Otherwise, the last argument is the destination. Remove it from $@.
|
||||||
|
for arg
|
||||||
|
do
|
||||||
|
if test -n "$dst_arg"; then
|
||||||
|
# $@ is not empty: it contains at least $arg.
|
||||||
|
set fnord "$@" "$dst_arg"
|
||||||
|
shift # fnord
|
||||||
|
fi
|
||||||
|
shift # arg
|
||||||
|
dst_arg=$arg
|
||||||
|
# Protect names problematic for 'test' and other utilities.
|
||||||
|
case $dst_arg in
|
||||||
|
-* | [=\(\)!]) dst_arg=./$dst_arg;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test $# -eq 0; then
|
||||||
|
if test -z "$dir_arg"; then
|
||||||
|
echo "$0: no input file specified." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
# It's OK to call 'install-sh -d' without argument.
|
||||||
|
# This can happen when creating conditional directories.
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test -z "$dir_arg"; then
|
||||||
|
do_exit='(exit $ret); exit $ret'
|
||||||
|
trap "ret=129; $do_exit" 1
|
||||||
|
trap "ret=130; $do_exit" 2
|
||||||
|
trap "ret=141; $do_exit" 13
|
||||||
|
trap "ret=143; $do_exit" 15
|
||||||
|
|
||||||
|
# Set umask so as not to create temps with too-generous modes.
|
||||||
|
# However, 'strip' requires both read and write access to temps.
|
||||||
|
case $mode in
|
||||||
|
# Optimize common cases.
|
||||||
|
*644) cp_umask=133;;
|
||||||
|
*755) cp_umask=22;;
|
||||||
|
|
||||||
|
*[0-7])
|
||||||
|
if test -z "$stripcmd"; then
|
||||||
|
u_plus_rw=
|
||||||
|
else
|
||||||
|
u_plus_rw='% 200'
|
||||||
|
fi
|
||||||
|
cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
|
||||||
|
*)
|
||||||
|
if test -z "$stripcmd"; then
|
||||||
|
u_plus_rw=
|
||||||
|
else
|
||||||
|
u_plus_rw=,u+rw
|
||||||
|
fi
|
||||||
|
cp_umask=$mode$u_plus_rw;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
for src
|
||||||
|
do
|
||||||
|
# Protect names problematic for 'test' and other utilities.
|
||||||
|
case $src in
|
||||||
|
-* | [=\(\)!]) src=./$src;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if test -n "$dir_arg"; then
|
||||||
|
dst=$src
|
||||||
|
dstdir=$dst
|
||||||
|
test -d "$dstdir"
|
||||||
|
dstdir_status=$?
|
||||||
|
else
|
||||||
|
|
||||||
|
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command
|
||||||
|
# might cause directories to be created, which would be especially bad
|
||||||
|
# if $src (and thus $dsttmp) contains '*'.
|
||||||
|
if test ! -f "$src" && test ! -d "$src"; then
|
||||||
|
echo "$0: $src does not exist." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test -z "$dst_arg"; then
|
||||||
|
echo "$0: no destination specified." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
dst=$dst_arg
|
||||||
|
|
||||||
|
# If destination is a directory, append the input filename; won't work
|
||||||
|
# if double slashes aren't ignored.
|
||||||
|
if test -d "$dst"; then
|
||||||
|
if test -n "$no_target_directory"; then
|
||||||
|
echo "$0: $dst_arg: Is a directory" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
dstdir=$dst
|
||||||
|
dst=$dstdir/`basename "$src"`
|
||||||
|
dstdir_status=0
|
||||||
|
else
|
||||||
|
# Prefer dirname, but fall back on a substitute if dirname fails.
|
||||||
|
dstdir=`
|
||||||
|
(dirname "$dst") 2>/dev/null ||
|
||||||
|
expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
|
||||||
|
X"$dst" : 'X\(//\)[^/]' \| \
|
||||||
|
X"$dst" : 'X\(//\)$' \| \
|
||||||
|
X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
|
||||||
|
echo X"$dst" |
|
||||||
|
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
|
||||||
|
s//\1/
|
||||||
|
q
|
||||||
|
}
|
||||||
|
/^X\(\/\/\)[^/].*/{
|
||||||
|
s//\1/
|
||||||
|
q
|
||||||
|
}
|
||||||
|
/^X\(\/\/\)$/{
|
||||||
|
s//\1/
|
||||||
|
q
|
||||||
|
}
|
||||||
|
/^X\(\/\).*/{
|
||||||
|
s//\1/
|
||||||
|
q
|
||||||
|
}
|
||||||
|
s/.*/./; q'
|
||||||
|
`
|
||||||
|
|
||||||
|
test -d "$dstdir"
|
||||||
|
dstdir_status=$?
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
obsolete_mkdir_used=false
|
||||||
|
|
||||||
|
if test $dstdir_status != 0; then
|
||||||
|
case $posix_mkdir in
|
||||||
|
'')
|
||||||
|
# Create intermediate dirs using mode 755 as modified by the umask.
|
||||||
|
# This is like FreeBSD 'install' as of 1997-10-28.
|
||||||
|
umask=`umask`
|
||||||
|
case $stripcmd.$umask in
|
||||||
|
# Optimize common cases.
|
||||||
|
*[2367][2367]) mkdir_umask=$umask;;
|
||||||
|
.*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
|
||||||
|
|
||||||
|
*[0-7])
|
||||||
|
mkdir_umask=`expr $umask + 22 \
|
||||||
|
- $umask % 100 % 40 + $umask % 20 \
|
||||||
|
- $umask % 10 % 4 + $umask % 2
|
||||||
|
`;;
|
||||||
|
*) mkdir_umask=$umask,go-w;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# With -d, create the new directory with the user-specified mode.
|
||||||
|
# Otherwise, rely on $mkdir_umask.
|
||||||
|
if test -n "$dir_arg"; then
|
||||||
|
mkdir_mode=-m$mode
|
||||||
|
else
|
||||||
|
mkdir_mode=
|
||||||
|
fi
|
||||||
|
|
||||||
|
posix_mkdir=false
|
||||||
|
case $umask in
|
||||||
|
*[123567][0-7][0-7])
|
||||||
|
# POSIX mkdir -p sets u+wx bits regardless of umask, which
|
||||||
|
# is incompatible with FreeBSD 'install' when (umask & 300) != 0.
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
|
||||||
|
trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
|
||||||
|
|
||||||
|
if (umask $mkdir_umask &&
|
||||||
|
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
if test -z "$dir_arg" || {
|
||||||
|
# Check for POSIX incompatibilities with -m.
|
||||||
|
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
|
||||||
|
# other-writable bit of parent directory when it shouldn't.
|
||||||
|
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
|
||||||
|
ls_ld_tmpdir=`ls -ld "$tmpdir"`
|
||||||
|
case $ls_ld_tmpdir in
|
||||||
|
d????-?r-*) different_mode=700;;
|
||||||
|
d????-?--*) different_mode=755;;
|
||||||
|
*) false;;
|
||||||
|
esac &&
|
||||||
|
$mkdirprog -m$different_mode -p -- "$tmpdir" && {
|
||||||
|
ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
|
||||||
|
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
then posix_mkdir=:
|
||||||
|
fi
|
||||||
|
rmdir "$tmpdir/d" "$tmpdir"
|
||||||
|
else
|
||||||
|
# Remove any dirs left behind by ancient mkdir implementations.
|
||||||
|
rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
|
||||||
|
fi
|
||||||
|
trap '' 0;;
|
||||||
|
esac;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if
|
||||||
|
$posix_mkdir && (
|
||||||
|
umask $mkdir_umask &&
|
||||||
|
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
|
||||||
|
)
|
||||||
|
then :
|
||||||
|
else
|
||||||
|
|
||||||
|
# The umask is ridiculous, or mkdir does not conform to POSIX,
|
||||||
|
# or it failed possibly due to a race condition. Create the
|
||||||
|
# directory the slow way, step by step, checking for races as we go.
|
||||||
|
|
||||||
|
case $dstdir in
|
||||||
|
/*) prefix='/';;
|
||||||
|
[-=\(\)!]*) prefix='./';;
|
||||||
|
*) prefix='';;
|
||||||
|
esac
|
||||||
|
|
||||||
|
eval "$initialize_posix_glob"
|
||||||
|
|
||||||
|
oIFS=$IFS
|
||||||
|
IFS=/
|
||||||
|
$posix_glob set -f
|
||||||
|
set fnord $dstdir
|
||||||
|
shift
|
||||||
|
$posix_glob set +f
|
||||||
|
IFS=$oIFS
|
||||||
|
|
||||||
|
prefixes=
|
||||||
|
|
||||||
|
for d
|
||||||
|
do
|
||||||
|
test X"$d" = X && continue
|
||||||
|
|
||||||
|
prefix=$prefix$d
|
||||||
|
if test -d "$prefix"; then
|
||||||
|
prefixes=
|
||||||
|
else
|
||||||
|
if $posix_mkdir; then
|
||||||
|
(umask=$mkdir_umask &&
|
||||||
|
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
|
||||||
|
# Don't fail if two instances are running concurrently.
|
||||||
|
test -d "$prefix" || exit 1
|
||||||
|
else
|
||||||
|
case $prefix in
|
||||||
|
*\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
|
||||||
|
*) qprefix=$prefix;;
|
||||||
|
esac
|
||||||
|
prefixes="$prefixes '$qprefix'"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
prefix=$prefix/
|
||||||
|
done
|
||||||
|
|
||||||
|
if test -n "$prefixes"; then
|
||||||
|
# Don't fail if two instances are running concurrently.
|
||||||
|
(umask $mkdir_umask &&
|
||||||
|
eval "\$doit_exec \$mkdirprog $prefixes") ||
|
||||||
|
test -d "$dstdir" || exit 1
|
||||||
|
obsolete_mkdir_used=true
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test -n "$dir_arg"; then
|
||||||
|
{ test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
|
||||||
|
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
|
||||||
|
{ test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
|
||||||
|
test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
|
||||||
|
else
|
||||||
|
|
||||||
|
# Make a couple of temp file names in the proper directory.
|
||||||
|
dsttmp=$dstdir/_inst.$$_
|
||||||
|
rmtmp=$dstdir/_rm.$$_
|
||||||
|
|
||||||
|
# Trap to clean up those temp files at exit.
|
||||||
|
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
|
||||||
|
|
||||||
|
# Copy the file name to the temp name.
|
||||||
|
(umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
|
||||||
|
|
||||||
|
# and set any options; do chmod last to preserve setuid bits.
|
||||||
|
#
|
||||||
|
# If any of these fail, we abort the whole thing. If we want to
|
||||||
|
# ignore errors from any of these, just make sure not to ignore
|
||||||
|
# errors from the above "$doit $cpprog $src $dsttmp" command.
|
||||||
|
#
|
||||||
|
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
|
||||||
|
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
|
||||||
|
{ test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
|
||||||
|
{ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
|
||||||
|
|
||||||
|
# If -C, don't bother to copy if it wouldn't change the file.
|
||||||
|
if $copy_on_change &&
|
||||||
|
old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
|
||||||
|
new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
|
||||||
|
|
||||||
|
eval "$initialize_posix_glob" &&
|
||||||
|
$posix_glob set -f &&
|
||||||
|
set X $old && old=:$2:$4:$5:$6 &&
|
||||||
|
set X $new && new=:$2:$4:$5:$6 &&
|
||||||
|
$posix_glob set +f &&
|
||||||
|
|
||||||
|
test "$old" = "$new" &&
|
||||||
|
$cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
rm -f "$dsttmp"
|
||||||
|
else
|
||||||
|
# Rename the file to the real destination.
|
||||||
|
$doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
|
||||||
|
|
||||||
|
# The rename failed, perhaps because mv can't rename something else
|
||||||
|
# to itself, or perhaps because mv is so ancient that it does not
|
||||||
|
# support -f.
|
||||||
|
{
|
||||||
|
# Now remove or move aside any old file at destination location.
|
||||||
|
# We try this two ways since rm can't unlink itself on some
|
||||||
|
# systems and the destination file might be busy for other
|
||||||
|
# reasons. In this case, the final cleanup might fail but the new
|
||||||
|
# file should still install successfully.
|
||||||
|
{
|
||||||
|
test ! -f "$dst" ||
|
||||||
|
$doit $rmcmd -f "$dst" 2>/dev/null ||
|
||||||
|
{ $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
|
||||||
|
{ $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
|
||||||
|
} ||
|
||||||
|
{ echo "$0: cannot unlink or rename $dst" >&2
|
||||||
|
(exit 1); exit 1
|
||||||
|
}
|
||||||
|
} &&
|
||||||
|
|
||||||
|
# Now rename the file to the real destination.
|
||||||
|
$doit $mvcmd "$dsttmp" "$dst"
|
||||||
|
}
|
||||||
|
fi || exit 1
|
||||||
|
|
||||||
|
trap '' 0
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Local variables:
|
||||||
|
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||||
|
# time-stamp-start: "scriptversion="
|
||||||
|
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||||
|
# time-stamp-time-zone: "UTC"
|
||||||
|
# time-stamp-end: "; # UTC"
|
||||||
|
# End:
|
|
@ -0,0 +1,43 @@
|
||||||
|
dnl as-ac-expand.m4 0.2.0
|
||||||
|
dnl autostars m4 macro for expanding directories using configure's prefix
|
||||||
|
dnl thomas@apestaart.org
|
||||||
|
|
||||||
|
dnl AS_AC_EXPAND(VAR, CONFIGURE_VAR)
|
||||||
|
dnl example
|
||||||
|
dnl AS_AC_EXPAND(SYSCONFDIR, $sysconfdir)
|
||||||
|
dnl will set SYSCONFDIR to /usr/local/etc if prefix=/usr/local
|
||||||
|
|
||||||
|
AC_DEFUN([AS_AC_EXPAND],
|
||||||
|
[
|
||||||
|
EXP_VAR=[$1]
|
||||||
|
FROM_VAR=[$2]
|
||||||
|
|
||||||
|
dnl first expand prefix and exec_prefix if necessary
|
||||||
|
prefix_save=$prefix
|
||||||
|
exec_prefix_save=$exec_prefix
|
||||||
|
|
||||||
|
dnl if no prefix given, then use /usr/local, the default prefix
|
||||||
|
if test "x$prefix" = "xNONE"; then
|
||||||
|
prefix="$ac_default_prefix"
|
||||||
|
fi
|
||||||
|
dnl if no exec_prefix given, then use prefix
|
||||||
|
if test "x$exec_prefix" = "xNONE"; then
|
||||||
|
exec_prefix=$prefix
|
||||||
|
fi
|
||||||
|
|
||||||
|
full_var="$FROM_VAR"
|
||||||
|
dnl loop until it doesn't change anymore
|
||||||
|
while true; do
|
||||||
|
new_full_var="`eval echo $full_var`"
|
||||||
|
if test "x$new_full_var" = "x$full_var"; then break; fi
|
||||||
|
full_var=$new_full_var
|
||||||
|
done
|
||||||
|
|
||||||
|
dnl clean up
|
||||||
|
full_var=$new_full_var
|
||||||
|
AC_SUBST([$1], "$full_var")
|
||||||
|
|
||||||
|
dnl restore prefix and exec_prefix
|
||||||
|
prefix=$prefix_save
|
||||||
|
exec_prefix=$exec_prefix_save
|
||||||
|
])
|
|
@ -0,0 +1,309 @@
|
||||||
|
# ===========================================================================
|
||||||
|
# http://www.gnu.org/software/autoconf-archive/ax_pthread.html
|
||||||
|
# ===========================================================================
|
||||||
|
#
|
||||||
|
# SYNOPSIS
|
||||||
|
#
|
||||||
|
# AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
|
||||||
|
#
|
||||||
|
# DESCRIPTION
|
||||||
|
#
|
||||||
|
# This macro figures out how to build C programs using POSIX threads. It
|
||||||
|
# sets the PTHREAD_LIBS output variable to the threads library and linker
|
||||||
|
# flags, and the PTHREAD_CFLAGS output variable to any special C compiler
|
||||||
|
# flags that are needed. (The user can also force certain compiler
|
||||||
|
# flags/libs to be tested by setting these environment variables.)
|
||||||
|
#
|
||||||
|
# Also sets PTHREAD_CC to any special C compiler that is needed for
|
||||||
|
# multi-threaded programs (defaults to the value of CC otherwise). (This
|
||||||
|
# is necessary on AIX to use the special cc_r compiler alias.)
|
||||||
|
#
|
||||||
|
# NOTE: You are assumed to not only compile your program with these flags,
|
||||||
|
# but also link it with them as well. e.g. you should link with
|
||||||
|
# $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
|
||||||
|
#
|
||||||
|
# If you are only building threads programs, you may wish to use these
|
||||||
|
# variables in your default LIBS, CFLAGS, and CC:
|
||||||
|
#
|
||||||
|
# LIBS="$PTHREAD_LIBS $LIBS"
|
||||||
|
# CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||||
|
# CC="$PTHREAD_CC"
|
||||||
|
#
|
||||||
|
# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant
|
||||||
|
# has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to that name
|
||||||
|
# (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
|
||||||
|
#
|
||||||
|
# Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the
|
||||||
|
# PTHREAD_PRIO_INHERIT symbol is defined when compiling with
|
||||||
|
# PTHREAD_CFLAGS.
|
||||||
|
#
|
||||||
|
# ACTION-IF-FOUND is a list of shell commands to run if a threads library
|
||||||
|
# is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it
|
||||||
|
# is not found. If ACTION-IF-FOUND is not specified, the default action
|
||||||
|
# will define HAVE_PTHREAD.
|
||||||
|
#
|
||||||
|
# Please let the authors know if this macro fails on any platform, or if
|
||||||
|
# you have any other suggestions or comments. This macro was based on work
|
||||||
|
# by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help
|
||||||
|
# from M. Frigo), as well as ac_pthread and hb_pthread macros posted by
|
||||||
|
# Alejandro Forero Cuervo to the autoconf macro repository. We are also
|
||||||
|
# grateful for the helpful feedback of numerous users.
|
||||||
|
#
|
||||||
|
# Updated for Autoconf 2.68 by Daniel Richard G.
|
||||||
|
#
|
||||||
|
# LICENSE
|
||||||
|
#
|
||||||
|
# Copyright (c) 2008 Steven G. Johnson <stevenj@alum.mit.edu>
|
||||||
|
# Copyright (c) 2011 Daniel Richard G. <skunk@iSKUNK.ORG>
|
||||||
|
#
|
||||||
|
# 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/>.
|
||||||
|
#
|
||||||
|
# As a special exception, the respective Autoconf Macro's copyright owner
|
||||||
|
# gives unlimited permission to copy, distribute and modify the configure
|
||||||
|
# scripts that are the output of Autoconf when processing the Macro. You
|
||||||
|
# need not follow the terms of the GNU General Public License when using
|
||||||
|
# or distributing such scripts, even though portions of the text of the
|
||||||
|
# Macro appear in them. The GNU General Public License (GPL) does govern
|
||||||
|
# all other use of the material that constitutes the Autoconf Macro.
|
||||||
|
#
|
||||||
|
# This special exception to the GPL applies to versions of the Autoconf
|
||||||
|
# Macro released by the Autoconf Archive. When you make and distribute a
|
||||||
|
# modified version of the Autoconf Macro, you may extend this special
|
||||||
|
# exception to the GPL to apply to your modified version as well.
|
||||||
|
|
||||||
|
#serial 18
|
||||||
|
|
||||||
|
AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD])
|
||||||
|
AC_DEFUN([AX_PTHREAD], [
|
||||||
|
AC_REQUIRE([AC_CANONICAL_HOST])
|
||||||
|
AC_LANG_PUSH([C])
|
||||||
|
ax_pthread_ok=no
|
||||||
|
|
||||||
|
# We used to check for pthread.h first, but this fails if pthread.h
|
||||||
|
# requires special compiler flags (e.g. on True64 or Sequent).
|
||||||
|
# It gets checked for in the link test anyway.
|
||||||
|
|
||||||
|
# First of all, check if the user has set any of the PTHREAD_LIBS,
|
||||||
|
# etcetera environment variables, and if threads linking works using
|
||||||
|
# them:
|
||||||
|
if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
|
||||||
|
save_CFLAGS="$CFLAGS"
|
||||||
|
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||||
|
save_LIBS="$LIBS"
|
||||||
|
LIBS="$PTHREAD_LIBS $LIBS"
|
||||||
|
AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])
|
||||||
|
AC_TRY_LINK_FUNC(pthread_join, ax_pthread_ok=yes)
|
||||||
|
AC_MSG_RESULT($ax_pthread_ok)
|
||||||
|
if test x"$ax_pthread_ok" = xno; then
|
||||||
|
PTHREAD_LIBS=""
|
||||||
|
PTHREAD_CFLAGS=""
|
||||||
|
fi
|
||||||
|
LIBS="$save_LIBS"
|
||||||
|
CFLAGS="$save_CFLAGS"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# We must check for the threads library under a number of different
|
||||||
|
# names; the ordering is very important because some systems
|
||||||
|
# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
|
||||||
|
# libraries is broken (non-POSIX).
|
||||||
|
|
||||||
|
# Create a list of thread flags to try. Items starting with a "-" are
|
||||||
|
# C compiler flags, and other items are library names, except for "none"
|
||||||
|
# which indicates that we try without any flags at all, and "pthread-config"
|
||||||
|
# which is a program returning the flags for the Pth emulation library.
|
||||||
|
|
||||||
|
ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
|
||||||
|
|
||||||
|
# The ordering *is* (sometimes) important. Some notes on the
|
||||||
|
# individual items follow:
|
||||||
|
|
||||||
|
# pthreads: AIX (must check this before -lpthread)
|
||||||
|
# none: in case threads are in libc; should be tried before -Kthread and
|
||||||
|
# other compiler flags to prevent continual compiler warnings
|
||||||
|
# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
|
||||||
|
# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
|
||||||
|
# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
|
||||||
|
# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
|
||||||
|
# -pthreads: Solaris/gcc
|
||||||
|
# -mthreads: Mingw32/gcc, Lynx/gcc
|
||||||
|
# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
|
||||||
|
# doesn't hurt to check since this sometimes defines pthreads too;
|
||||||
|
# also defines -D_REENTRANT)
|
||||||
|
# ... -mt is also the pthreads flag for HP/aCC
|
||||||
|
# pthread: Linux, etcetera
|
||||||
|
# --thread-safe: KAI C++
|
||||||
|
# pthread-config: use pthread-config program (for GNU Pth library)
|
||||||
|
|
||||||
|
case ${host_os} in
|
||||||
|
solaris*)
|
||||||
|
|
||||||
|
# On Solaris (at least, for some versions), libc contains stubbed
|
||||||
|
# (non-functional) versions of the pthreads routines, so link-based
|
||||||
|
# tests will erroneously succeed. (We need to link with -pthreads/-mt/
|
||||||
|
# -lpthread.) (The stubs are missing pthread_cleanup_push, or rather
|
||||||
|
# a function called by this macro, so we could check for that, but
|
||||||
|
# who knows whether they'll stub that too in a future libc.) So,
|
||||||
|
# we'll just look for -pthreads and -lpthread first:
|
||||||
|
|
||||||
|
ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags"
|
||||||
|
;;
|
||||||
|
|
||||||
|
darwin*)
|
||||||
|
ax_pthread_flags="-pthread $ax_pthread_flags"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if test x"$ax_pthread_ok" = xno; then
|
||||||
|
for flag in $ax_pthread_flags; do
|
||||||
|
|
||||||
|
case $flag in
|
||||||
|
none)
|
||||||
|
AC_MSG_CHECKING([whether pthreads work without any flags])
|
||||||
|
;;
|
||||||
|
|
||||||
|
-*)
|
||||||
|
AC_MSG_CHECKING([whether pthreads work with $flag])
|
||||||
|
PTHREAD_CFLAGS="$flag"
|
||||||
|
;;
|
||||||
|
|
||||||
|
pthread-config)
|
||||||
|
AC_CHECK_PROG(ax_pthread_config, pthread-config, yes, no)
|
||||||
|
if test x"$ax_pthread_config" = xno; then continue; fi
|
||||||
|
PTHREAD_CFLAGS="`pthread-config --cflags`"
|
||||||
|
PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
AC_MSG_CHECKING([for the pthreads library -l$flag])
|
||||||
|
PTHREAD_LIBS="-l$flag"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
save_LIBS="$LIBS"
|
||||||
|
save_CFLAGS="$CFLAGS"
|
||||||
|
LIBS="$PTHREAD_LIBS $LIBS"
|
||||||
|
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||||
|
|
||||||
|
# Check for various functions. We must include pthread.h,
|
||||||
|
# since some functions may be macros. (On the Sequent, we
|
||||||
|
# need a special flag -Kthread to make this header compile.)
|
||||||
|
# We check for pthread_join because it is in -lpthread on IRIX
|
||||||
|
# while pthread_create is in libc. We check for pthread_attr_init
|
||||||
|
# due to DEC craziness with -lpthreads. We check for
|
||||||
|
# pthread_cleanup_push because it is one of the few pthread
|
||||||
|
# functions on Solaris that doesn't have a non-functional libc stub.
|
||||||
|
# We try pthread_create on general principles.
|
||||||
|
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>
|
||||||
|
static void routine(void *a) { a = 0; }
|
||||||
|
static void *start_routine(void *a) { return a; }],
|
||||||
|
[pthread_t th; pthread_attr_t attr;
|
||||||
|
pthread_create(&th, 0, start_routine, 0);
|
||||||
|
pthread_join(th, 0);
|
||||||
|
pthread_attr_init(&attr);
|
||||||
|
pthread_cleanup_push(routine, 0);
|
||||||
|
pthread_cleanup_pop(0) /* ; */])],
|
||||||
|
[ax_pthread_ok=yes],
|
||||||
|
[])
|
||||||
|
|
||||||
|
LIBS="$save_LIBS"
|
||||||
|
CFLAGS="$save_CFLAGS"
|
||||||
|
|
||||||
|
AC_MSG_RESULT($ax_pthread_ok)
|
||||||
|
if test "x$ax_pthread_ok" = xyes; then
|
||||||
|
break;
|
||||||
|
fi
|
||||||
|
|
||||||
|
PTHREAD_LIBS=""
|
||||||
|
PTHREAD_CFLAGS=""
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Various other checks:
|
||||||
|
if test "x$ax_pthread_ok" = xyes; then
|
||||||
|
save_LIBS="$LIBS"
|
||||||
|
LIBS="$PTHREAD_LIBS $LIBS"
|
||||||
|
save_CFLAGS="$CFLAGS"
|
||||||
|
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||||
|
|
||||||
|
# Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
|
||||||
|
AC_MSG_CHECKING([for joinable pthread attribute])
|
||||||
|
attr_name=unknown
|
||||||
|
for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
|
||||||
|
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>],
|
||||||
|
[int attr = $attr; return attr /* ; */])],
|
||||||
|
[attr_name=$attr; break],
|
||||||
|
[])
|
||||||
|
done
|
||||||
|
AC_MSG_RESULT($attr_name)
|
||||||
|
if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then
|
||||||
|
AC_DEFINE_UNQUOTED(PTHREAD_CREATE_JOINABLE, $attr_name,
|
||||||
|
[Define to necessary symbol if this constant
|
||||||
|
uses a non-standard name on your system.])
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_MSG_CHECKING([if more special flags are required for pthreads])
|
||||||
|
flag=no
|
||||||
|
case ${host_os} in
|
||||||
|
aix* | freebsd* | darwin*) flag="-D_THREAD_SAFE";;
|
||||||
|
osf* | hpux*) flag="-D_REENTRANT";;
|
||||||
|
solaris*)
|
||||||
|
if test "$GCC" = "yes"; then
|
||||||
|
flag="-D_REENTRANT"
|
||||||
|
else
|
||||||
|
flag="-mt -D_REENTRANT"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
AC_MSG_RESULT(${flag})
|
||||||
|
if test "x$flag" != xno; then
|
||||||
|
PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT],
|
||||||
|
ax_cv_PTHREAD_PRIO_INHERIT, [
|
||||||
|
AC_LINK_IFELSE([
|
||||||
|
AC_LANG_PROGRAM([[#include <pthread.h>]], [[int i = PTHREAD_PRIO_INHERIT;]])],
|
||||||
|
[ax_cv_PTHREAD_PRIO_INHERIT=yes],
|
||||||
|
[ax_cv_PTHREAD_PRIO_INHERIT=no])
|
||||||
|
])
|
||||||
|
AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes"],
|
||||||
|
AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], 1, [Have PTHREAD_PRIO_INHERIT.]))
|
||||||
|
|
||||||
|
LIBS="$save_LIBS"
|
||||||
|
CFLAGS="$save_CFLAGS"
|
||||||
|
|
||||||
|
# More AIX lossage: must compile with xlc_r or cc_r
|
||||||
|
if test x"$GCC" != xyes; then
|
||||||
|
AC_CHECK_PROGS(PTHREAD_CC, xlc_r cc_r, ${CC})
|
||||||
|
else
|
||||||
|
PTHREAD_CC=$CC
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
PTHREAD_CC="$CC"
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_SUBST(PTHREAD_LIBS)
|
||||||
|
AC_SUBST(PTHREAD_CFLAGS)
|
||||||
|
AC_SUBST(PTHREAD_CC)
|
||||||
|
|
||||||
|
# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
|
||||||
|
if test x"$ax_pthread_ok" = xyes; then
|
||||||
|
ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1])
|
||||||
|
:
|
||||||
|
else
|
||||||
|
ax_pthread_ok=no
|
||||||
|
$2
|
||||||
|
fi
|
||||||
|
AC_LANG_POP
|
||||||
|
])dnl AX_PTHREAD
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,437 @@
|
||||||
|
# Helper functions for option handling. -*- Autoconf -*-
|
||||||
|
#
|
||||||
|
# Copyright (C) 2004-2005, 2007-2009, 2011-2015 Free Software
|
||||||
|
# Foundation, Inc.
|
||||||
|
# Written by Gary V. Vaughan, 2004
|
||||||
|
#
|
||||||
|
# This file is free software; the Free Software Foundation gives
|
||||||
|
# unlimited permission to copy and/or distribute it, with or without
|
||||||
|
# modifications, as long as this notice is preserved.
|
||||||
|
|
||||||
|
# serial 8 ltoptions.m4
|
||||||
|
|
||||||
|
# This is to help aclocal find these macros, as it can't see m4_define.
|
||||||
|
AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])])
|
||||||
|
|
||||||
|
|
||||||
|
# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME)
|
||||||
|
# ------------------------------------------
|
||||||
|
m4_define([_LT_MANGLE_OPTION],
|
||||||
|
[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])])
|
||||||
|
|
||||||
|
|
||||||
|
# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME)
|
||||||
|
# ---------------------------------------
|
||||||
|
# Set option OPTION-NAME for macro MACRO-NAME, and if there is a
|
||||||
|
# matching handler defined, dispatch to it. Other OPTION-NAMEs are
|
||||||
|
# saved as a flag.
|
||||||
|
m4_define([_LT_SET_OPTION],
|
||||||
|
[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl
|
||||||
|
m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]),
|
||||||
|
_LT_MANGLE_DEFUN([$1], [$2]),
|
||||||
|
[m4_warning([Unknown $1 option '$2'])])[]dnl
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET])
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
|
||||||
|
m4_define([_LT_IF_OPTION],
|
||||||
|
[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])])
|
||||||
|
|
||||||
|
|
||||||
|
# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET)
|
||||||
|
# -------------------------------------------------------
|
||||||
|
# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME
|
||||||
|
# are set.
|
||||||
|
m4_define([_LT_UNLESS_OPTIONS],
|
||||||
|
[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
|
||||||
|
[m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option),
|
||||||
|
[m4_define([$0_found])])])[]dnl
|
||||||
|
m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3
|
||||||
|
])[]dnl
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST)
|
||||||
|
# ----------------------------------------
|
||||||
|
# OPTION-LIST is a space-separated list of Libtool options associated
|
||||||
|
# with MACRO-NAME. If any OPTION has a matching handler declared with
|
||||||
|
# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about
|
||||||
|
# the unknown option and exit.
|
||||||
|
m4_defun([_LT_SET_OPTIONS],
|
||||||
|
[# Set options
|
||||||
|
m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
|
||||||
|
[_LT_SET_OPTION([$1], _LT_Option)])
|
||||||
|
|
||||||
|
m4_if([$1],[LT_INIT],[
|
||||||
|
dnl
|
||||||
|
dnl Simply set some default values (i.e off) if boolean options were not
|
||||||
|
dnl specified:
|
||||||
|
_LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no
|
||||||
|
])
|
||||||
|
_LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no
|
||||||
|
])
|
||||||
|
dnl
|
||||||
|
dnl If no reference was made to various pairs of opposing options, then
|
||||||
|
dnl we run the default mode handler for the pair. For example, if neither
|
||||||
|
dnl 'shared' nor 'disable-shared' was passed, we enable building of shared
|
||||||
|
dnl archives by default:
|
||||||
|
_LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED])
|
||||||
|
_LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC])
|
||||||
|
_LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC])
|
||||||
|
_LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install],
|
||||||
|
[_LT_ENABLE_FAST_INSTALL])
|
||||||
|
_LT_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4],
|
||||||
|
[_LT_WITH_AIX_SONAME([aix])])
|
||||||
|
])
|
||||||
|
])# _LT_SET_OPTIONS
|
||||||
|
|
||||||
|
|
||||||
|
## --------------------------------- ##
|
||||||
|
## Macros to handle LT_INIT options. ##
|
||||||
|
## --------------------------------- ##
|
||||||
|
|
||||||
|
# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME)
|
||||||
|
# -----------------------------------------
|
||||||
|
m4_define([_LT_MANGLE_DEFUN],
|
||||||
|
[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])])
|
||||||
|
|
||||||
|
|
||||||
|
# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE)
|
||||||
|
# -----------------------------------------------
|
||||||
|
m4_define([LT_OPTION_DEFINE],
|
||||||
|
[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl
|
||||||
|
])# LT_OPTION_DEFINE
|
||||||
|
|
||||||
|
|
||||||
|
# dlopen
|
||||||
|
# ------
|
||||||
|
LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes
|
||||||
|
])
|
||||||
|
|
||||||
|
AU_DEFUN([AC_LIBTOOL_DLOPEN],
|
||||||
|
[_LT_SET_OPTION([LT_INIT], [dlopen])
|
||||||
|
AC_DIAGNOSE([obsolete],
|
||||||
|
[$0: Remove this warning and the call to _LT_SET_OPTION when you
|
||||||
|
put the 'dlopen' option into LT_INIT's first parameter.])
|
||||||
|
])
|
||||||
|
|
||||||
|
dnl aclocal-1.4 backwards compatibility:
|
||||||
|
dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], [])
|
||||||
|
|
||||||
|
|
||||||
|
# win32-dll
|
||||||
|
# ---------
|
||||||
|
# Declare package support for building win32 dll's.
|
||||||
|
LT_OPTION_DEFINE([LT_INIT], [win32-dll],
|
||||||
|
[enable_win32_dll=yes
|
||||||
|
|
||||||
|
case $host in
|
||||||
|
*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*)
|
||||||
|
AC_CHECK_TOOL(AS, as, false)
|
||||||
|
AC_CHECK_TOOL(DLLTOOL, dlltool, false)
|
||||||
|
AC_CHECK_TOOL(OBJDUMP, objdump, false)
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
test -z "$AS" && AS=as
|
||||||
|
_LT_DECL([], [AS], [1], [Assembler program])dnl
|
||||||
|
|
||||||
|
test -z "$DLLTOOL" && DLLTOOL=dlltool
|
||||||
|
_LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl
|
||||||
|
|
||||||
|
test -z "$OBJDUMP" && OBJDUMP=objdump
|
||||||
|
_LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl
|
||||||
|
])# win32-dll
|
||||||
|
|
||||||
|
AU_DEFUN([AC_LIBTOOL_WIN32_DLL],
|
||||||
|
[AC_REQUIRE([AC_CANONICAL_HOST])dnl
|
||||||
|
_LT_SET_OPTION([LT_INIT], [win32-dll])
|
||||||
|
AC_DIAGNOSE([obsolete],
|
||||||
|
[$0: Remove this warning and the call to _LT_SET_OPTION when you
|
||||||
|
put the 'win32-dll' option into LT_INIT's first parameter.])
|
||||||
|
])
|
||||||
|
|
||||||
|
dnl aclocal-1.4 backwards compatibility:
|
||||||
|
dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], [])
|
||||||
|
|
||||||
|
|
||||||
|
# _LT_ENABLE_SHARED([DEFAULT])
|
||||||
|
# ----------------------------
|
||||||
|
# implement the --enable-shared flag, and supports the 'shared' and
|
||||||
|
# 'disable-shared' LT_INIT options.
|
||||||
|
# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'.
|
||||||
|
m4_define([_LT_ENABLE_SHARED],
|
||||||
|
[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl
|
||||||
|
AC_ARG_ENABLE([shared],
|
||||||
|
[AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@],
|
||||||
|
[build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])],
|
||||||
|
[p=${PACKAGE-default}
|
||||||
|
case $enableval in
|
||||||
|
yes) enable_shared=yes ;;
|
||||||
|
no) enable_shared=no ;;
|
||||||
|
*)
|
||||||
|
enable_shared=no
|
||||||
|
# Look at the argument we got. We use all the common list separators.
|
||||||
|
lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
|
||||||
|
for pkg in $enableval; do
|
||||||
|
IFS=$lt_save_ifs
|
||||||
|
if test "X$pkg" = "X$p"; then
|
||||||
|
enable_shared=yes
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
IFS=$lt_save_ifs
|
||||||
|
;;
|
||||||
|
esac],
|
||||||
|
[enable_shared=]_LT_ENABLE_SHARED_DEFAULT)
|
||||||
|
|
||||||
|
_LT_DECL([build_libtool_libs], [enable_shared], [0],
|
||||||
|
[Whether or not to build shared libraries])
|
||||||
|
])# _LT_ENABLE_SHARED
|
||||||
|
|
||||||
|
LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])])
|
||||||
|
LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])])
|
||||||
|
|
||||||
|
# Old names:
|
||||||
|
AC_DEFUN([AC_ENABLE_SHARED],
|
||||||
|
[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared])
|
||||||
|
])
|
||||||
|
|
||||||
|
AC_DEFUN([AC_DISABLE_SHARED],
|
||||||
|
[_LT_SET_OPTION([LT_INIT], [disable-shared])
|
||||||
|
])
|
||||||
|
|
||||||
|
AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)])
|
||||||
|
AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)])
|
||||||
|
|
||||||
|
dnl aclocal-1.4 backwards compatibility:
|
||||||
|
dnl AC_DEFUN([AM_ENABLE_SHARED], [])
|
||||||
|
dnl AC_DEFUN([AM_DISABLE_SHARED], [])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# _LT_ENABLE_STATIC([DEFAULT])
|
||||||
|
# ----------------------------
|
||||||
|
# implement the --enable-static flag, and support the 'static' and
|
||||||
|
# 'disable-static' LT_INIT options.
|
||||||
|
# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'.
|
||||||
|
m4_define([_LT_ENABLE_STATIC],
|
||||||
|
[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl
|
||||||
|
AC_ARG_ENABLE([static],
|
||||||
|
[AS_HELP_STRING([--enable-static@<:@=PKGS@:>@],
|
||||||
|
[build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])],
|
||||||
|
[p=${PACKAGE-default}
|
||||||
|
case $enableval in
|
||||||
|
yes) enable_static=yes ;;
|
||||||
|
no) enable_static=no ;;
|
||||||
|
*)
|
||||||
|
enable_static=no
|
||||||
|
# Look at the argument we got. We use all the common list separators.
|
||||||
|
lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
|
||||||
|
for pkg in $enableval; do
|
||||||
|
IFS=$lt_save_ifs
|
||||||
|
if test "X$pkg" = "X$p"; then
|
||||||
|
enable_static=yes
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
IFS=$lt_save_ifs
|
||||||
|
;;
|
||||||
|
esac],
|
||||||
|
[enable_static=]_LT_ENABLE_STATIC_DEFAULT)
|
||||||
|
|
||||||
|
_LT_DECL([build_old_libs], [enable_static], [0],
|
||||||
|
[Whether or not to build static libraries])
|
||||||
|
])# _LT_ENABLE_STATIC
|
||||||
|
|
||||||
|
LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])])
|
||||||
|
LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])])
|
||||||
|
|
||||||
|
# Old names:
|
||||||
|
AC_DEFUN([AC_ENABLE_STATIC],
|
||||||
|
[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static])
|
||||||
|
])
|
||||||
|
|
||||||
|
AC_DEFUN([AC_DISABLE_STATIC],
|
||||||
|
[_LT_SET_OPTION([LT_INIT], [disable-static])
|
||||||
|
])
|
||||||
|
|
||||||
|
AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)])
|
||||||
|
AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)])
|
||||||
|
|
||||||
|
dnl aclocal-1.4 backwards compatibility:
|
||||||
|
dnl AC_DEFUN([AM_ENABLE_STATIC], [])
|
||||||
|
dnl AC_DEFUN([AM_DISABLE_STATIC], [])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# _LT_ENABLE_FAST_INSTALL([DEFAULT])
|
||||||
|
# ----------------------------------
|
||||||
|
# implement the --enable-fast-install flag, and support the 'fast-install'
|
||||||
|
# and 'disable-fast-install' LT_INIT options.
|
||||||
|
# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'.
|
||||||
|
m4_define([_LT_ENABLE_FAST_INSTALL],
|
||||||
|
[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl
|
||||||
|
AC_ARG_ENABLE([fast-install],
|
||||||
|
[AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@],
|
||||||
|
[optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])],
|
||||||
|
[p=${PACKAGE-default}
|
||||||
|
case $enableval in
|
||||||
|
yes) enable_fast_install=yes ;;
|
||||||
|
no) enable_fast_install=no ;;
|
||||||
|
*)
|
||||||
|
enable_fast_install=no
|
||||||
|
# Look at the argument we got. We use all the common list separators.
|
||||||
|
lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
|
||||||
|
for pkg in $enableval; do
|
||||||
|
IFS=$lt_save_ifs
|
||||||
|
if test "X$pkg" = "X$p"; then
|
||||||
|
enable_fast_install=yes
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
IFS=$lt_save_ifs
|
||||||
|
;;
|
||||||
|
esac],
|
||||||
|
[enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT)
|
||||||
|
|
||||||
|
_LT_DECL([fast_install], [enable_fast_install], [0],
|
||||||
|
[Whether or not to optimize for fast installation])dnl
|
||||||
|
])# _LT_ENABLE_FAST_INSTALL
|
||||||
|
|
||||||
|
LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])])
|
||||||
|
LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])])
|
||||||
|
|
||||||
|
# Old names:
|
||||||
|
AU_DEFUN([AC_ENABLE_FAST_INSTALL],
|
||||||
|
[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install])
|
||||||
|
AC_DIAGNOSE([obsolete],
|
||||||
|
[$0: Remove this warning and the call to _LT_SET_OPTION when you put
|
||||||
|
the 'fast-install' option into LT_INIT's first parameter.])
|
||||||
|
])
|
||||||
|
|
||||||
|
AU_DEFUN([AC_DISABLE_FAST_INSTALL],
|
||||||
|
[_LT_SET_OPTION([LT_INIT], [disable-fast-install])
|
||||||
|
AC_DIAGNOSE([obsolete],
|
||||||
|
[$0: Remove this warning and the call to _LT_SET_OPTION when you put
|
||||||
|
the 'disable-fast-install' option into LT_INIT's first parameter.])
|
||||||
|
])
|
||||||
|
|
||||||
|
dnl aclocal-1.4 backwards compatibility:
|
||||||
|
dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], [])
|
||||||
|
dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], [])
|
||||||
|
|
||||||
|
|
||||||
|
# _LT_WITH_AIX_SONAME([DEFAULT])
|
||||||
|
# ----------------------------------
|
||||||
|
# implement the --with-aix-soname flag, and support the `aix-soname=aix'
|
||||||
|
# and `aix-soname=both' and `aix-soname=svr4' LT_INIT options. DEFAULT
|
||||||
|
# is either `aix', `both' or `svr4'. If omitted, it defaults to `aix'.
|
||||||
|
m4_define([_LT_WITH_AIX_SONAME],
|
||||||
|
[m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl
|
||||||
|
shared_archive_member_spec=
|
||||||
|
case $host,$enable_shared in
|
||||||
|
power*-*-aix[[5-9]]*,yes)
|
||||||
|
AC_MSG_CHECKING([which variant of shared library versioning to provide])
|
||||||
|
AC_ARG_WITH([aix-soname],
|
||||||
|
[AS_HELP_STRING([--with-aix-soname=aix|svr4|both],
|
||||||
|
[shared library versioning (aka "SONAME") variant to provide on AIX, @<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])],
|
||||||
|
[case $withval in
|
||||||
|
aix|svr4|both)
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
AC_MSG_ERROR([Unknown argument to --with-aix-soname])
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
lt_cv_with_aix_soname=$with_aix_soname],
|
||||||
|
[AC_CACHE_VAL([lt_cv_with_aix_soname],
|
||||||
|
[lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT)
|
||||||
|
with_aix_soname=$lt_cv_with_aix_soname])
|
||||||
|
AC_MSG_RESULT([$with_aix_soname])
|
||||||
|
if test aix != "$with_aix_soname"; then
|
||||||
|
# For the AIX way of multilib, we name the shared archive member
|
||||||
|
# based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o',
|
||||||
|
# and 'shr.imp' or 'shr_64.imp', respectively, for the Import File.
|
||||||
|
# Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag,
|
||||||
|
# the AIX toolchain works better with OBJECT_MODE set (default 32).
|
||||||
|
if test 64 = "${OBJECT_MODE-32}"; then
|
||||||
|
shared_archive_member_spec=shr_64
|
||||||
|
else
|
||||||
|
shared_archive_member_spec=shr
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
with_aix_soname=aix
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
_LT_DECL([], [shared_archive_member_spec], [0],
|
||||||
|
[Shared archive member basename, for filename based shared library versioning on AIX])dnl
|
||||||
|
])# _LT_WITH_AIX_SONAME
|
||||||
|
|
||||||
|
LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])])
|
||||||
|
LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])])
|
||||||
|
LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])])
|
||||||
|
|
||||||
|
|
||||||
|
# _LT_WITH_PIC([MODE])
|
||||||
|
# --------------------
|
||||||
|
# implement the --with-pic flag, and support the 'pic-only' and 'no-pic'
|
||||||
|
# LT_INIT options.
|
||||||
|
# MODE is either 'yes' or 'no'. If omitted, it defaults to 'both'.
|
||||||
|
m4_define([_LT_WITH_PIC],
|
||||||
|
[AC_ARG_WITH([pic],
|
||||||
|
[AS_HELP_STRING([--with-pic@<:@=PKGS@:>@],
|
||||||
|
[try to use only PIC/non-PIC objects @<:@default=use both@:>@])],
|
||||||
|
[lt_p=${PACKAGE-default}
|
||||||
|
case $withval in
|
||||||
|
yes|no) pic_mode=$withval ;;
|
||||||
|
*)
|
||||||
|
pic_mode=default
|
||||||
|
# Look at the argument we got. We use all the common list separators.
|
||||||
|
lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
|
||||||
|
for lt_pkg in $withval; do
|
||||||
|
IFS=$lt_save_ifs
|
||||||
|
if test "X$lt_pkg" = "X$lt_p"; then
|
||||||
|
pic_mode=yes
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
IFS=$lt_save_ifs
|
||||||
|
;;
|
||||||
|
esac],
|
||||||
|
[pic_mode=m4_default([$1], [default])])
|
||||||
|
|
||||||
|
_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl
|
||||||
|
])# _LT_WITH_PIC
|
||||||
|
|
||||||
|
LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])])
|
||||||
|
LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])])
|
||||||
|
|
||||||
|
# Old name:
|
||||||
|
AU_DEFUN([AC_LIBTOOL_PICMODE],
|
||||||
|
[_LT_SET_OPTION([LT_INIT], [pic-only])
|
||||||
|
AC_DIAGNOSE([obsolete],
|
||||||
|
[$0: Remove this warning and the call to _LT_SET_OPTION when you
|
||||||
|
put the 'pic-only' option into LT_INIT's first parameter.])
|
||||||
|
])
|
||||||
|
|
||||||
|
dnl aclocal-1.4 backwards compatibility:
|
||||||
|
dnl AC_DEFUN([AC_LIBTOOL_PICMODE], [])
|
||||||
|
|
||||||
|
## ----------------- ##
|
||||||
|
## LTDL_INIT Options ##
|
||||||
|
## ----------------- ##
|
||||||
|
|
||||||
|
m4_define([_LTDL_MODE], [])
|
||||||
|
LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive],
|
||||||
|
[m4_define([_LTDL_MODE], [nonrecursive])])
|
||||||
|
LT_OPTION_DEFINE([LTDL_INIT], [recursive],
|
||||||
|
[m4_define([_LTDL_MODE], [recursive])])
|
||||||
|
LT_OPTION_DEFINE([LTDL_INIT], [subproject],
|
||||||
|
[m4_define([_LTDL_MODE], [subproject])])
|
||||||
|
|
||||||
|
m4_define([_LTDL_TYPE], [])
|
||||||
|
LT_OPTION_DEFINE([LTDL_INIT], [installable],
|
||||||
|
[m4_define([_LTDL_TYPE], [installable])])
|
||||||
|
LT_OPTION_DEFINE([LTDL_INIT], [convenience],
|
||||||
|
[m4_define([_LTDL_TYPE], [convenience])])
|
|
@ -0,0 +1,123 @@
|
||||||
|
# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*-
|
||||||
|
#
|
||||||
|
# Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
|
||||||
|
# Written by Gary V. Vaughan, 2004
|
||||||
|
#
|
||||||
|
# This file is free software; the Free Software Foundation gives
|
||||||
|
# unlimited permission to copy and/or distribute it, with or without
|
||||||
|
# modifications, as long as this notice is preserved.
|
||||||
|
|
||||||
|
# serial 6 ltsugar.m4
|
||||||
|
|
||||||
|
# This is to help aclocal find these macros, as it can't see m4_define.
|
||||||
|
AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])])
|
||||||
|
|
||||||
|
|
||||||
|
# lt_join(SEP, ARG1, [ARG2...])
|
||||||
|
# -----------------------------
|
||||||
|
# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their
|
||||||
|
# associated separator.
|
||||||
|
# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier
|
||||||
|
# versions in m4sugar had bugs.
|
||||||
|
m4_define([lt_join],
|
||||||
|
[m4_if([$#], [1], [],
|
||||||
|
[$#], [2], [[$2]],
|
||||||
|
[m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])])
|
||||||
|
m4_define([_lt_join],
|
||||||
|
[m4_if([$#$2], [2], [],
|
||||||
|
[m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])])
|
||||||
|
|
||||||
|
|
||||||
|
# lt_car(LIST)
|
||||||
|
# lt_cdr(LIST)
|
||||||
|
# ------------
|
||||||
|
# Manipulate m4 lists.
|
||||||
|
# These macros are necessary as long as will still need to support
|
||||||
|
# Autoconf-2.59 which quotes differently.
|
||||||
|
m4_define([lt_car], [[$1]])
|
||||||
|
m4_define([lt_cdr],
|
||||||
|
[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])],
|
||||||
|
[$#], 1, [],
|
||||||
|
[m4_dquote(m4_shift($@))])])
|
||||||
|
m4_define([lt_unquote], $1)
|
||||||
|
|
||||||
|
|
||||||
|
# lt_append(MACRO-NAME, STRING, [SEPARATOR])
|
||||||
|
# ------------------------------------------
|
||||||
|
# Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'.
|
||||||
|
# Note that neither SEPARATOR nor STRING are expanded; they are appended
|
||||||
|
# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked).
|
||||||
|
# No SEPARATOR is output if MACRO-NAME was previously undefined (different
|
||||||
|
# than defined and empty).
|
||||||
|
#
|
||||||
|
# This macro is needed until we can rely on Autoconf 2.62, since earlier
|
||||||
|
# versions of m4sugar mistakenly expanded SEPARATOR but not STRING.
|
||||||
|
m4_define([lt_append],
|
||||||
|
[m4_define([$1],
|
||||||
|
m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...])
|
||||||
|
# ----------------------------------------------------------
|
||||||
|
# Produce a SEP delimited list of all paired combinations of elements of
|
||||||
|
# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list
|
||||||
|
# has the form PREFIXmINFIXSUFFIXn.
|
||||||
|
# Needed until we can rely on m4_combine added in Autoconf 2.62.
|
||||||
|
m4_define([lt_combine],
|
||||||
|
[m4_if(m4_eval([$# > 3]), [1],
|
||||||
|
[m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl
|
||||||
|
[[m4_foreach([_Lt_prefix], [$2],
|
||||||
|
[m4_foreach([_Lt_suffix],
|
||||||
|
]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[,
|
||||||
|
[_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])])
|
||||||
|
|
||||||
|
|
||||||
|
# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ])
|
||||||
|
# -----------------------------------------------------------------------
|
||||||
|
# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited
|
||||||
|
# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ.
|
||||||
|
m4_define([lt_if_append_uniq],
|
||||||
|
[m4_ifdef([$1],
|
||||||
|
[m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1],
|
||||||
|
[lt_append([$1], [$2], [$3])$4],
|
||||||
|
[$5])],
|
||||||
|
[lt_append([$1], [$2], [$3])$4])])
|
||||||
|
|
||||||
|
|
||||||
|
# lt_dict_add(DICT, KEY, VALUE)
|
||||||
|
# -----------------------------
|
||||||
|
m4_define([lt_dict_add],
|
||||||
|
[m4_define([$1($2)], [$3])])
|
||||||
|
|
||||||
|
|
||||||
|
# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE)
|
||||||
|
# --------------------------------------------
|
||||||
|
m4_define([lt_dict_add_subkey],
|
||||||
|
[m4_define([$1($2:$3)], [$4])])
|
||||||
|
|
||||||
|
|
||||||
|
# lt_dict_fetch(DICT, KEY, [SUBKEY])
|
||||||
|
# ----------------------------------
|
||||||
|
m4_define([lt_dict_fetch],
|
||||||
|
[m4_ifval([$3],
|
||||||
|
m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]),
|
||||||
|
m4_ifdef([$1($2)], [m4_defn([$1($2)])]))])
|
||||||
|
|
||||||
|
|
||||||
|
# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE])
|
||||||
|
# -----------------------------------------------------------------
|
||||||
|
m4_define([lt_if_dict_fetch],
|
||||||
|
[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4],
|
||||||
|
[$5],
|
||||||
|
[$6])])
|
||||||
|
|
||||||
|
|
||||||
|
# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...])
|
||||||
|
# --------------------------------------------------------------
|
||||||
|
m4_define([lt_dict_filter],
|
||||||
|
[m4_if([$5], [], [],
|
||||||
|
[lt_join(m4_quote(m4_default([$4], [[, ]])),
|
||||||
|
lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]),
|
||||||
|
[lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl
|
||||||
|
])
|
|
@ -0,0 +1,23 @@
|
||||||
|
# ltversion.m4 -- version numbers -*- Autoconf -*-
|
||||||
|
#
|
||||||
|
# Copyright (C) 2004, 2011-2015 Free Software Foundation, Inc.
|
||||||
|
# Written by Scott James Remnant, 2004
|
||||||
|
#
|
||||||
|
# This file is free software; the Free Software Foundation gives
|
||||||
|
# unlimited permission to copy and/or distribute it, with or without
|
||||||
|
# modifications, as long as this notice is preserved.
|
||||||
|
|
||||||
|
# @configure_input@
|
||||||
|
|
||||||
|
# serial 4179 ltversion.m4
|
||||||
|
# This file is part of GNU Libtool
|
||||||
|
|
||||||
|
m4_define([LT_PACKAGE_VERSION], [2.4.6])
|
||||||
|
m4_define([LT_PACKAGE_REVISION], [2.4.6])
|
||||||
|
|
||||||
|
AC_DEFUN([LTVERSION_VERSION],
|
||||||
|
[macro_version='2.4.6'
|
||||||
|
macro_revision='2.4.6'
|
||||||
|
_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?])
|
||||||
|
_LT_DECL(, macro_revision, 0)
|
||||||
|
])
|
|
@ -0,0 +1,98 @@
|
||||||
|
# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*-
|
||||||
|
#
|
||||||
|
# Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc.
|
||||||
|
# Written by Scott James Remnant, 2004.
|
||||||
|
#
|
||||||
|
# This file is free software; the Free Software Foundation gives
|
||||||
|
# unlimited permission to copy and/or distribute it, with or without
|
||||||
|
# modifications, as long as this notice is preserved.
|
||||||
|
|
||||||
|
# serial 5 lt~obsolete.m4
|
||||||
|
|
||||||
|
# These exist entirely to fool aclocal when bootstrapping libtool.
|
||||||
|
#
|
||||||
|
# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN)
|
||||||
|
# which have later been changed to m4_define as they aren't part of the
|
||||||
|
# exported API, or moved to Autoconf or Automake where they belong.
|
||||||
|
#
|
||||||
|
# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN
|
||||||
|
# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us
|
||||||
|
# using a macro with the same name in our local m4/libtool.m4 it'll
|
||||||
|
# pull the old libtool.m4 in (it doesn't see our shiny new m4_define
|
||||||
|
# and doesn't know about Autoconf macros at all.)
|
||||||
|
#
|
||||||
|
# So we provide this file, which has a silly filename so it's always
|
||||||
|
# included after everything else. This provides aclocal with the
|
||||||
|
# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything
|
||||||
|
# because those macros already exist, or will be overwritten later.
|
||||||
|
# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6.
|
||||||
|
#
|
||||||
|
# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here.
|
||||||
|
# Yes, that means every name once taken will need to remain here until
|
||||||
|
# we give up compatibility with versions before 1.7, at which point
|
||||||
|
# we need to keep only those names which we still refer to.
|
||||||
|
|
||||||
|
# This is to help aclocal find these macros, as it can't see m4_define.
|
||||||
|
AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])])
|
||||||
|
|
||||||
|
m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])])
|
||||||
|
m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])])
|
||||||
|
m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])])
|
||||||
|
m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])])
|
||||||
|
m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])])
|
||||||
|
m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])])
|
||||||
|
m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])])
|
||||||
|
m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])])
|
||||||
|
m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])])
|
||||||
|
m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])])
|
||||||
|
m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])])
|
||||||
|
m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])])
|
||||||
|
m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])])
|
||||||
|
m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])])
|
||||||
|
m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])])
|
||||||
|
m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])])
|
||||||
|
m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])])
|
||||||
|
m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])])
|
||||||
|
m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])])
|
||||||
|
m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])])
|
||||||
|
m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])])
|
||||||
|
m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])])
|
||||||
|
m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])])
|
||||||
|
m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])])
|
||||||
|
m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])])
|
||||||
|
m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])])
|
||||||
|
m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])])
|
||||||
|
m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])])
|
||||||
|
m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])])
|
||||||
|
m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])])
|
||||||
|
m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])])
|
||||||
|
m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])])
|
||||||
|
m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])])
|
||||||
|
m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])])
|
||||||
|
m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])])
|
||||||
|
m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])])
|
||||||
|
m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])])
|
||||||
|
m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])])
|
||||||
|
m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])])
|
||||||
|
m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])])
|
||||||
|
m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])])
|
||||||
|
m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])])
|
||||||
|
m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])])
|
||||||
|
m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])])
|
||||||
|
m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])])
|
||||||
|
m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])])
|
||||||
|
m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])])
|
||||||
|
m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])])
|
||||||
|
m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])])
|
||||||
|
m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])])
|
||||||
|
m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])])
|
||||||
|
m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])])
|
||||||
|
m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])])
|
||||||
|
m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])])
|
||||||
|
m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])])
|
||||||
|
m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])])
|
||||||
|
m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])])
|
||||||
|
m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])])
|
||||||
|
m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])])
|
||||||
|
m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])])
|
||||||
|
m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])])
|
|
@ -0,0 +1,215 @@
|
||||||
|
#! /bin/sh
|
||||||
|
# Common wrapper for a few potentially missing GNU programs.
|
||||||
|
|
||||||
|
scriptversion=2013-10-28.13; # UTC
|
||||||
|
|
||||||
|
# Copyright (C) 1996-2013 Free Software Foundation, Inc.
|
||||||
|
# Originally written by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
|
||||||
|
|
||||||
|
# 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 2, 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/>.
|
||||||
|
|
||||||
|
# As a special exception to the GNU General Public License, if you
|
||||||
|
# distribute this file as part of a program that contains a
|
||||||
|
# configuration script generated by Autoconf, you may include it under
|
||||||
|
# the same distribution terms that you use for the rest of that program.
|
||||||
|
|
||||||
|
if test $# -eq 0; then
|
||||||
|
echo 1>&2 "Try '$0 --help' for more information"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
case $1 in
|
||||||
|
|
||||||
|
--is-lightweight)
|
||||||
|
# Used by our autoconf macros to check whether the available missing
|
||||||
|
# script is modern enough.
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
|
||||||
|
--run)
|
||||||
|
# Back-compat with the calling convention used by older automake.
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
|
||||||
|
-h|--h|--he|--hel|--help)
|
||||||
|
echo "\
|
||||||
|
$0 [OPTION]... PROGRAM [ARGUMENT]...
|
||||||
|
|
||||||
|
Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due
|
||||||
|
to PROGRAM being missing or too old.
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-h, --help display this help and exit
|
||||||
|
-v, --version output version information and exit
|
||||||
|
|
||||||
|
Supported PROGRAM values:
|
||||||
|
aclocal autoconf autoheader autom4te automake makeinfo
|
||||||
|
bison yacc flex lex help2man
|
||||||
|
|
||||||
|
Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and
|
||||||
|
'g' are ignored when checking the name.
|
||||||
|
|
||||||
|
Send bug reports to <bug-automake@gnu.org>."
|
||||||
|
exit $?
|
||||||
|
;;
|
||||||
|
|
||||||
|
-v|--v|--ve|--ver|--vers|--versi|--versio|--version)
|
||||||
|
echo "missing $scriptversion (GNU Automake)"
|
||||||
|
exit $?
|
||||||
|
;;
|
||||||
|
|
||||||
|
-*)
|
||||||
|
echo 1>&2 "$0: unknown '$1' option"
|
||||||
|
echo 1>&2 "Try '$0 --help' for more information"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Run the given program, remember its exit status.
|
||||||
|
"$@"; st=$?
|
||||||
|
|
||||||
|
# If it succeeded, we are done.
|
||||||
|
test $st -eq 0 && exit 0
|
||||||
|
|
||||||
|
# Also exit now if we it failed (or wasn't found), and '--version' was
|
||||||
|
# passed; such an option is passed most likely to detect whether the
|
||||||
|
# program is present and works.
|
||||||
|
case $2 in --version|--help) exit $st;; esac
|
||||||
|
|
||||||
|
# Exit code 63 means version mismatch. This often happens when the user
|
||||||
|
# tries to use an ancient version of a tool on a file that requires a
|
||||||
|
# minimum version.
|
||||||
|
if test $st -eq 63; then
|
||||||
|
msg="probably too old"
|
||||||
|
elif test $st -eq 127; then
|
||||||
|
# Program was missing.
|
||||||
|
msg="missing on your system"
|
||||||
|
else
|
||||||
|
# Program was found and executed, but failed. Give up.
|
||||||
|
exit $st
|
||||||
|
fi
|
||||||
|
|
||||||
|
perl_URL=http://www.perl.org/
|
||||||
|
flex_URL=http://flex.sourceforge.net/
|
||||||
|
gnu_software_URL=http://www.gnu.org/software
|
||||||
|
|
||||||
|
program_details ()
|
||||||
|
{
|
||||||
|
case $1 in
|
||||||
|
aclocal|automake)
|
||||||
|
echo "The '$1' program is part of the GNU Automake package:"
|
||||||
|
echo "<$gnu_software_URL/automake>"
|
||||||
|
echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:"
|
||||||
|
echo "<$gnu_software_URL/autoconf>"
|
||||||
|
echo "<$gnu_software_URL/m4/>"
|
||||||
|
echo "<$perl_URL>"
|
||||||
|
;;
|
||||||
|
autoconf|autom4te|autoheader)
|
||||||
|
echo "The '$1' program is part of the GNU Autoconf package:"
|
||||||
|
echo "<$gnu_software_URL/autoconf/>"
|
||||||
|
echo "It also requires GNU m4 and Perl in order to run:"
|
||||||
|
echo "<$gnu_software_URL/m4/>"
|
||||||
|
echo "<$perl_URL>"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
give_advice ()
|
||||||
|
{
|
||||||
|
# Normalize program name to check for.
|
||||||
|
normalized_program=`echo "$1" | sed '
|
||||||
|
s/^gnu-//; t
|
||||||
|
s/^gnu//; t
|
||||||
|
s/^g//; t'`
|
||||||
|
|
||||||
|
printf '%s\n' "'$1' is $msg."
|
||||||
|
|
||||||
|
configure_deps="'configure.ac' or m4 files included by 'configure.ac'"
|
||||||
|
case $normalized_program in
|
||||||
|
autoconf*)
|
||||||
|
echo "You should only need it if you modified 'configure.ac',"
|
||||||
|
echo "or m4 files included by it."
|
||||||
|
program_details 'autoconf'
|
||||||
|
;;
|
||||||
|
autoheader*)
|
||||||
|
echo "You should only need it if you modified 'acconfig.h' or"
|
||||||
|
echo "$configure_deps."
|
||||||
|
program_details 'autoheader'
|
||||||
|
;;
|
||||||
|
automake*)
|
||||||
|
echo "You should only need it if you modified 'Makefile.am' or"
|
||||||
|
echo "$configure_deps."
|
||||||
|
program_details 'automake'
|
||||||
|
;;
|
||||||
|
aclocal*)
|
||||||
|
echo "You should only need it if you modified 'acinclude.m4' or"
|
||||||
|
echo "$configure_deps."
|
||||||
|
program_details 'aclocal'
|
||||||
|
;;
|
||||||
|
autom4te*)
|
||||||
|
echo "You might have modified some maintainer files that require"
|
||||||
|
echo "the 'autom4te' program to be rebuilt."
|
||||||
|
program_details 'autom4te'
|
||||||
|
;;
|
||||||
|
bison*|yacc*)
|
||||||
|
echo "You should only need it if you modified a '.y' file."
|
||||||
|
echo "You may want to install the GNU Bison package:"
|
||||||
|
echo "<$gnu_software_URL/bison/>"
|
||||||
|
;;
|
||||||
|
lex*|flex*)
|
||||||
|
echo "You should only need it if you modified a '.l' file."
|
||||||
|
echo "You may want to install the Fast Lexical Analyzer package:"
|
||||||
|
echo "<$flex_URL>"
|
||||||
|
;;
|
||||||
|
help2man*)
|
||||||
|
echo "You should only need it if you modified a dependency" \
|
||||||
|
"of a man page."
|
||||||
|
echo "You may want to install the GNU Help2man package:"
|
||||||
|
echo "<$gnu_software_URL/help2man/>"
|
||||||
|
;;
|
||||||
|
makeinfo*)
|
||||||
|
echo "You should only need it if you modified a '.texi' file, or"
|
||||||
|
echo "any other file indirectly affecting the aspect of the manual."
|
||||||
|
echo "You might want to install the Texinfo package:"
|
||||||
|
echo "<$gnu_software_URL/texinfo/>"
|
||||||
|
echo "The spurious makeinfo call might also be the consequence of"
|
||||||
|
echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might"
|
||||||
|
echo "want to install GNU make:"
|
||||||
|
echo "<$gnu_software_URL/make/>"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "You might have modified some files without having the proper"
|
||||||
|
echo "tools for further handling them. Check the 'README' file, it"
|
||||||
|
echo "often tells you about the needed prerequisites for installing"
|
||||||
|
echo "this package. You may also peek at any GNU archive site, in"
|
||||||
|
echo "case some other package contains this missing '$1' program."
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
give_advice "$1" | sed -e '1s/^/WARNING: /' \
|
||||||
|
-e '2,$s/^/ /' >&2
|
||||||
|
|
||||||
|
# Propagate the correct exit status (expected to be 127 for a program
|
||||||
|
# not found, 63 for a program that failed due to version mismatch).
|
||||||
|
exit $st
|
||||||
|
|
||||||
|
# Local variables:
|
||||||
|
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||||
|
# time-stamp-start: "scriptversion="
|
||||||
|
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||||
|
# time-stamp-time-zone: "UTC"
|
||||||
|
# time-stamp-end: "; # UTC"
|
||||||
|
# End:
|
|
@ -0,0 +1,153 @@
|
||||||
|
SUBDIRS = spy
|
||||||
|
|
||||||
|
AM_CPPFLAGS = -I$(top_srcdir)/src/PCSC -I$(top_builddir)/src/PCSC \
|
||||||
|
$(SYMBOL_VISIBILITY)
|
||||||
|
|
||||||
|
lib_LTLIBRARIES = libpcsclite.la
|
||||||
|
|
||||||
|
sbin_PROGRAMS = pcscd
|
||||||
|
noinst_PROGRAMS = testpcsc pcsc-wirecheck pcsc-wirecheck-gen
|
||||||
|
|
||||||
|
if ENABLE_SERIAL
|
||||||
|
SERIAL_CONFIG = configfile.l
|
||||||
|
endif
|
||||||
|
|
||||||
|
if ENABLE_USB
|
||||||
|
USB_CONFIG = tokenparser.l \
|
||||||
|
hotplug_libudev.c \
|
||||||
|
hotplug_libusb.c \
|
||||||
|
hotplug_linux.c \
|
||||||
|
hotplug_macosx.c
|
||||||
|
endif
|
||||||
|
|
||||||
|
libpcsclite_la_SOURCES = \
|
||||||
|
debug.c \
|
||||||
|
error.c \
|
||||||
|
winscard_clnt.c \
|
||||||
|
simclist.c \
|
||||||
|
sys_unix.c \
|
||||||
|
utils.c \
|
||||||
|
winscard_msg.c
|
||||||
|
libpcsclite_la_LDFLAGS = -version-info 1:0:0
|
||||||
|
libpcsclite_la_CFLAGS = $(CFLAGS) $(PTHREAD_CFLAGS) -DLIBPCSCLITE -DSIMCLIST_NO_DUMPRESTORE
|
||||||
|
libpcsclite_la_LIBADD = $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
|
||||||
|
|
||||||
|
pcscd_SOURCES = \
|
||||||
|
auth.c \
|
||||||
|
auth.h \
|
||||||
|
atrhandler.c \
|
||||||
|
atrhandler.h \
|
||||||
|
configfile.h \
|
||||||
|
$(SERIAL_CONFIG) \
|
||||||
|
debuglog.c \
|
||||||
|
dyn_generic.h \
|
||||||
|
dyn_hpux.c \
|
||||||
|
dyn_macosx.c \
|
||||||
|
dyn_unix.c \
|
||||||
|
eventhandler.c \
|
||||||
|
eventhandler.h \
|
||||||
|
hotplug_generic.c \
|
||||||
|
hotplug.h \
|
||||||
|
ifdwrapper.c \
|
||||||
|
ifdwrapper.h \
|
||||||
|
misc.h \
|
||||||
|
parser.h \
|
||||||
|
pcscdaemon.c \
|
||||||
|
pcscd.h \
|
||||||
|
PCSC/debuglog.h \
|
||||||
|
PCSC/ifdhandler.h \
|
||||||
|
PCSC/pcsclite.h \
|
||||||
|
PCSC/winscard.h \
|
||||||
|
PCSC/wintypes.h \
|
||||||
|
prothandler.c \
|
||||||
|
prothandler.h \
|
||||||
|
readerfactory.c \
|
||||||
|
readerfactory.h \
|
||||||
|
sd-daemon.c \
|
||||||
|
sd-daemon.h \
|
||||||
|
simclist.c \
|
||||||
|
simclist.h \
|
||||||
|
sys_generic.h \
|
||||||
|
sys_unix.c \
|
||||||
|
$(USB_CONFIG) \
|
||||||
|
utils.c \
|
||||||
|
utils.h \
|
||||||
|
winscard.c \
|
||||||
|
winscard_msg.c \
|
||||||
|
winscard_msg.h \
|
||||||
|
winscard_msg_srv.c \
|
||||||
|
winscard_svc.c \
|
||||||
|
winscard_svc.h
|
||||||
|
pcscd_CFLAGS = $(CFLAGS) $(PTHREAD_CFLAGS) $(LIBUSB_CFLAGS) $(LIBUDEV_CFLAGS) \
|
||||||
|
$(POLKIT_CFLAGS) \
|
||||||
|
-DPCSCD -DSIMCLIST_NO_DUMPRESTORE
|
||||||
|
pcscd_LDFLAGS = $(LDFLAGS) -export-dynamic
|
||||||
|
pcscd_LDADD = \
|
||||||
|
$(PTHREAD_LIBS) $(COREFOUNDATION) \
|
||||||
|
$(LIBUSB_LIBS) $(IOKIT) $(LIBUDEV_LIBS) \
|
||||||
|
$(PTHREAD_LIBS) $(PTHREAD_CFLAGS) \
|
||||||
|
$(POLKIT_LIBS)
|
||||||
|
|
||||||
|
fix-rights: install-sbinPROGRAMS
|
||||||
|
chgrp pcscd $(DESTDIR)$(sbindir)/pcscd
|
||||||
|
chmod g+s $(DESTDIR)$(sbindir)/pcscd
|
||||||
|
|
||||||
|
update-systemd:
|
||||||
|
curl -O http://cgit.freedesktop.org/systemd/plain/src/sd-daemon.c
|
||||||
|
curl -O http://cgit.freedesktop.org/systemd/systemd/plain/src/systemd/sd-daemon.h
|
||||||
|
|
||||||
|
testpcsc_SOURCES = testpcsc.c
|
||||||
|
testpcsc_LDADD = libpcsclite.la
|
||||||
|
|
||||||
|
pcsc_wirecheck_gen_SOURCES = \
|
||||||
|
pcsc-wirecheck-gen.c
|
||||||
|
|
||||||
|
# pcsc_wirecheck_gen_CPPFLAGS := $(LIBPCSCLITE_CFLAGS)
|
||||||
|
|
||||||
|
pcsc_wirecheck_SOURCES = \
|
||||||
|
lassert.h \
|
||||||
|
pcsc-wirecheck-dist.c \
|
||||||
|
pcsc-wirecheck-main.c
|
||||||
|
|
||||||
|
# pcsc_wirecheck_CFLAGS := $(LIBPCSCLITE_CFLAGS) -DCOMPAT_64BIT_SERVER=1
|
||||||
|
|
||||||
|
$(srcdir)/pcsc-wirecheck-dist.c: pcsc-wirecheck-gen
|
||||||
|
@if test -f $@ ; then \
|
||||||
|
echo "touch $@" ; \
|
||||||
|
touch $@ ; \
|
||||||
|
else \
|
||||||
|
echo "rm -f $@" ; \
|
||||||
|
rm -f $@ ; \
|
||||||
|
echo "./pcsc-wirecheck-gen > $@.tmp" ; \
|
||||||
|
./pcsc-wirecheck-gen > $@.tmp ; \
|
||||||
|
echo "mv $@.tmp $@" ; \
|
||||||
|
mv $@.tmp $@ ; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
.PHONY: regen
|
||||||
|
|
||||||
|
regen: pcsc-wirecheck-gen
|
||||||
|
rm -f $(srcdir)/pcsc-wirecheck-dist.c
|
||||||
|
./pcsc-wirecheck-gen > $(srcdir)/pcsc-wirecheck-dist.c.tmp
|
||||||
|
mv $(srcdir)/pcsc-wirecheck-dist.c.tmp $(srcdir)/pcsc-wirecheck-dist.c
|
||||||
|
|
||||||
|
nobase_include_HEADERS = \
|
||||||
|
PCSC/debuglog.h \
|
||||||
|
PCSC/ifdhandler.h \
|
||||||
|
PCSC/reader.h \
|
||||||
|
PCSC/winscard.h \
|
||||||
|
PCSC/wintypes.h
|
||||||
|
|
||||||
|
nodistheaderdir = $(includedir)/PCSC
|
||||||
|
nodistheader_DATA = PCSC/pcsclite.h
|
||||||
|
|
||||||
|
pcdir= $(libdir)/pkgconfig
|
||||||
|
pc_DATA = libpcsclite.pc
|
||||||
|
|
||||||
|
# Hack to be able to use flex -P to enable linking of multiple lexer
|
||||||
|
# sources into one library, until we find a way to make automake handle
|
||||||
|
# this automagically. This breaks if lex is not flex!!
|
||||||
|
tokenparser.c: tokenparser.l
|
||||||
|
$(SHELL) $(YLWRAP) $< lex.tp.c $@ -- "$(LEX)" -Ptp $(AM_LFLAGS) $(LFLAGS)
|
||||||
|
|
||||||
|
EXTRA_DIST = README_INTERNALS.txt
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,133 @@
|
||||||
|
/*
|
||||||
|
* MUSCLE SmartCard Development ( http://pcsclite.alioth.debian.org/pcsclite.html )
|
||||||
|
*
|
||||||
|
* Copyright (C) 1999-2004
|
||||||
|
* David Corcoran <corcoran@musclecard.com>
|
||||||
|
* Copyright (C) 1999-2011
|
||||||
|
* Ludovic Rousseau <ludovic.rousseau@free.fr>
|
||||||
|
*
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. The name of the author may not be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief This handles debugging.
|
||||||
|
*
|
||||||
|
* @note log message is sent to syslog or stderr depending on --foreground
|
||||||
|
* command line argument
|
||||||
|
*
|
||||||
|
* @code
|
||||||
|
* Log1(priority, "text");
|
||||||
|
* log "text" with priority level priority
|
||||||
|
* Log2(priority, "text: %d", 1234);
|
||||||
|
* log "text: 1234"
|
||||||
|
* the format string can be anything printf() can understand
|
||||||
|
* Log3(priority, "text: %d %d", 1234, 5678);
|
||||||
|
* log "text: 1234 5678"
|
||||||
|
* the format string can be anything printf() can understand
|
||||||
|
* LogXxd(priority, msg, buffer, size);
|
||||||
|
* log "msg" + a hex dump of size bytes of buffer[]
|
||||||
|
* @endcode
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __debuglog_h__
|
||||||
|
#define __debuglog_h__
|
||||||
|
|
||||||
|
#ifndef PCSC_API
|
||||||
|
#define PCSC_API
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum {
|
||||||
|
DEBUGLOG_NO_DEBUG = 0,
|
||||||
|
DEBUGLOG_SYSLOG_DEBUG,
|
||||||
|
DEBUGLOG_STDOUT_DEBUG,
|
||||||
|
DEBUGLOG_STDOUT_COLOR_DEBUG
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DEBUG_CATEGORY_NOTHING 0
|
||||||
|
#define DEBUG_CATEGORY_APDU 1
|
||||||
|
#define DEBUG_CATEGORY_SW 2
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PCSC_LOG_DEBUG = 0,
|
||||||
|
PCSC_LOG_INFO,
|
||||||
|
PCSC_LOG_ERROR,
|
||||||
|
PCSC_LOG_CRITICAL
|
||||||
|
};
|
||||||
|
|
||||||
|
/* You can't do #ifndef __FUNCTION__ */
|
||||||
|
#if !defined(__GNUC__) && !defined(__IBMC__)
|
||||||
|
#define __FUNCTION__ ""
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __GNUC__
|
||||||
|
#define __attribute__(x) /*nothing*/
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef NO_LOG
|
||||||
|
|
||||||
|
#define Log0(priority) do { } while(0)
|
||||||
|
#define Log1(priority, fmt) do { } while(0)
|
||||||
|
#define Log2(priority, fmt, data) do { } while(0)
|
||||||
|
#define Log3(priority, fmt, data1, data2) do { } while(0)
|
||||||
|
#define Log4(priority, fmt, data1, data2, data3) do { } while(0)
|
||||||
|
#define Log5(priority, fmt, data1, data2, data3, data4) do { } while(0)
|
||||||
|
#define Log9(priority, fmt, data1, data2, data3, data4, data5, data6, data7, data8) do { } while(0)
|
||||||
|
#define LogXxd(priority, msg, buffer, size) do { } while(0)
|
||||||
|
|
||||||
|
#define DebugLogA(a)
|
||||||
|
#define DebugLogB(a, b)
|
||||||
|
#define DebugLogC(a, b,c)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define Log0(priority) log_msg(priority, "%s:%d:%s()", __FILE__, __LINE__, __FUNCTION__)
|
||||||
|
#define Log1(priority, fmt) log_msg(priority, "%s:%d:%s() " fmt, __FILE__, __LINE__, __FUNCTION__)
|
||||||
|
#define Log2(priority, fmt, data) log_msg(priority, "%s:%d:%s() " fmt, __FILE__, __LINE__, __FUNCTION__, data)
|
||||||
|
#define Log3(priority, fmt, data1, data2) log_msg(priority, "%s:%d:%s() " fmt, __FILE__, __LINE__, __FUNCTION__, data1, data2)
|
||||||
|
#define Log4(priority, fmt, data1, data2, data3) log_msg(priority, "%s:%d:%s() " fmt, __FILE__, __LINE__, __FUNCTION__, data1, data2, data3)
|
||||||
|
#define Log5(priority, fmt, data1, data2, data3, data4) log_msg(priority, "%s:%d:%s() " fmt, __FILE__, __LINE__, __FUNCTION__, data1, data2, data3, data4)
|
||||||
|
#define Log9(priority, fmt, data1, data2, data3, data4, data5, data6, data7, data8) log_msg(priority, "%s:%d:%s() " fmt, __FILE__, __LINE__, __FUNCTION__, data1, data2, data3, data4, data5, data6, data7, data8)
|
||||||
|
#define LogXxd(priority, msg, buffer, size) log_xxd(priority, msg, buffer, size)
|
||||||
|
|
||||||
|
#define DebugLogA(a) Log1(PCSC_LOG_INFO, a)
|
||||||
|
#define DebugLogB(a, b) Log2(PCSC_LOG_INFO, a, b)
|
||||||
|
#define DebugLogC(a, b,c) Log3(PCSC_LOG_INFO, a, b, c)
|
||||||
|
|
||||||
|
#endif /* NO_LOG */
|
||||||
|
|
||||||
|
PCSC_API void log_msg(const int priority, const char *fmt, ...)
|
||||||
|
__attribute__((format(printf, 2, 3)));
|
||||||
|
|
||||||
|
PCSC_API void log_xxd(const int priority, const char *msg,
|
||||||
|
const unsigned char *buffer, const int size);
|
||||||
|
|
||||||
|
void DebugLogSuppress(const int);
|
||||||
|
void DebugLogSetLogType(const int);
|
||||||
|
void DebugLogSetCategory(const int);
|
||||||
|
void DebugLogCategory(const int, const unsigned char *, const int);
|
||||||
|
PCSC_API void DebugLogSetLevel(const int level);
|
||||||
|
|
||||||
|
#endif /* __debuglog_h__ */
|
||||||
|
|
|
@ -0,0 +1,827 @@
|
||||||
|
/*
|
||||||
|
* MUSCLE SmartCard Development ( http://pcsclite.alioth.debian.org/pcsclite.html )
|
||||||
|
*
|
||||||
|
* Copyright (C) 1999-2004
|
||||||
|
* David Corcoran <corcoran@musclecard.com>
|
||||||
|
* Copyright (C) 2003-2004
|
||||||
|
* Damien Sauveron <damien.sauveron@labri.fr>
|
||||||
|
* Copyright (C) 2002-2011
|
||||||
|
* Ludovic Rousseau <ludovic.rousseau@free.fr>
|
||||||
|
*
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. The name of the author may not be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @defgroup IFDHandler IFDHandler
|
||||||
|
* @brief This provides reader specific low-level calls.
|
||||||
|
|
||||||
|
The routines specified hereafter will allow you to write an IFD handler
|
||||||
|
for the PC/SC Lite resource manager. Please use the complement
|
||||||
|
developer's kit complete with headers and Makefile at:
|
||||||
|
http://www.musclecard.com/drivers.html
|
||||||
|
|
||||||
|
This gives a common API for communication to most readers in a
|
||||||
|
homogeneous fashion. This document assumes that the driver developer is
|
||||||
|
experienced with standards such as ISO-7816-(1, 2, 3, 4), EMV and MCT
|
||||||
|
specifications. For listings of these specifications please access the
|
||||||
|
above web site.
|
||||||
|
|
||||||
|
@section UsbReaders USB readers
|
||||||
|
|
||||||
|
USB readers use the bundle approach so that the reader can be loaded
|
||||||
|
and unloaded upon automatic detection of the device. The bundle
|
||||||
|
approach is simple: the actual library is just embedded in a
|
||||||
|
directory so additional information can be gathered about the device.
|
||||||
|
|
||||||
|
A bundle looks like the following:
|
||||||
|
|
||||||
|
@verbatim
|
||||||
|
GenericReader.bundle/
|
||||||
|
Contents/
|
||||||
|
Info.plist - XML file describing the reader
|
||||||
|
MacOS/ - Driver directory for OS X
|
||||||
|
Solaris/ - Driver directory for Solaris
|
||||||
|
Linux/ - Driver directory for Linux
|
||||||
|
HPUX/ - Driver directory for HPUX
|
||||||
|
@endverbatim
|
||||||
|
|
||||||
|
The @c Info.plist file describes the driver and gives the loader
|
||||||
|
all the necessary information. The following must be contained in the
|
||||||
|
@c Info.plist file:
|
||||||
|
|
||||||
|
@subsection ifdVendorID
|
||||||
|
|
||||||
|
The vendor ID of the USB device.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
@verbatim
|
||||||
|
<key>ifdVendorID</key>
|
||||||
|
<string>0x04E6</string>
|
||||||
|
@endverbatim
|
||||||
|
|
||||||
|
You may have an OEM of this reader in which an additional @c <string>
|
||||||
|
can be used like in the below example:
|
||||||
|
|
||||||
|
@verbatim
|
||||||
|
<key>ifdVendorID</key>
|
||||||
|
<array>
|
||||||
|
<string>0x04E6</string>
|
||||||
|
<string>0x0973</string>
|
||||||
|
</array>
|
||||||
|
@endverbatim
|
||||||
|
|
||||||
|
If multiples exist all the other parameters must have a second value
|
||||||
|
also. You may chose not to support this feature but it is useful when
|
||||||
|
reader vendors OEM products so you only distribute one driver.
|
||||||
|
|
||||||
|
|
||||||
|
The CCID driver from Ludovic Rousseau
|
||||||
|
http://pcsclite.alioth.debian.org/ccid.html uses this feature since the
|
||||||
|
same driver supports many different readers.
|
||||||
|
|
||||||
|
@subsection ifdProductID
|
||||||
|
|
||||||
|
The product id of the USB device.
|
||||||
|
|
||||||
|
@verbatim
|
||||||
|
<key>ifdProductID</key>
|
||||||
|
<string>0x3437</string>
|
||||||
|
@endverbatim
|
||||||
|
|
||||||
|
@subsection ifdFriendlyName
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
@verbatim
|
||||||
|
<key>ifdFriendlyName</key>
|
||||||
|
<string>SCM Microsystems USB Reader</string>
|
||||||
|
@endverbatim
|
||||||
|
|
||||||
|
The reader name must use the ASCII character set.
|
||||||
|
|
||||||
|
@subsection CFBundleExecutable
|
||||||
|
|
||||||
|
The executable name which exists in the particular platform's directory.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
@verbatim
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>libccid.so.0.4.2</string>
|
||||||
|
@endverbatim
|
||||||
|
|
||||||
|
@subsection ifdCapabilities
|
||||||
|
|
||||||
|
List of capabilities supported by the driver. This is a bit field. Possible values are:
|
||||||
|
|
||||||
|
- 0
|
||||||
|
No special capabilities
|
||||||
|
- 1 IFD_GENERATE_HOTPLUG
|
||||||
|
The driver supports the hot plug feature.
|
||||||
|
|
||||||
|
Complete sample file:
|
||||||
|
|
||||||
|
@verbatim
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN"
|
||||||
|
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>English</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>BNDL</string>
|
||||||
|
<key>CFBundleSignature</key>
|
||||||
|
<string>????</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>0.0.1d1</string>
|
||||||
|
<key>ifdCapabilities</key>
|
||||||
|
<string>0x00000000</string>
|
||||||
|
<key>ifdProtocolSupport</key>
|
||||||
|
<string>0x00000001</string>
|
||||||
|
<key>ifdVersionNumber</key>
|
||||||
|
<string>0x00000001</string>
|
||||||
|
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>libfoobar.so.x.y</string>
|
||||||
|
|
||||||
|
<key>ifdManufacturerString</key>
|
||||||
|
<string>Foo bar inc.</string>
|
||||||
|
|
||||||
|
<key>ifdProductString</key>
|
||||||
|
<string>Driver for Foobar reader, version x.y</string>
|
||||||
|
|
||||||
|
<key>ifdVendorID</key>
|
||||||
|
<string>0x1234</string>
|
||||||
|
|
||||||
|
<key>ifdProductID</key>
|
||||||
|
<string>0x5678</string>
|
||||||
|
|
||||||
|
<key>ifdFriendlyName</key>
|
||||||
|
<string>Foobar USB reader</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
|
@endverbatim
|
||||||
|
|
||||||
|
As indicated in the XML file the DTD is available at
|
||||||
|
http://www.apple.com/DTDs/PropertyList-1.0.dtd.
|
||||||
|
|
||||||
|
@section SerialReaders Serial readers
|
||||||
|
|
||||||
|
Serial drivers must be configured to operate on a particular port and
|
||||||
|
respond to a particular name. The @c reader.conf file is used for this
|
||||||
|
purpose.
|
||||||
|
|
||||||
|
It has the following syntax:
|
||||||
|
|
||||||
|
@verbatim
|
||||||
|
# Configuration file for pcsc-lite
|
||||||
|
# David Corcoran <corcoran@musclecard.com>
|
||||||
|
|
||||||
|
FRIENDLYNAME Generic Reader
|
||||||
|
DEVICENAME /dev/ttyS0
|
||||||
|
LIBPATH /usr/lib/pcsc/drivers/libgen_ifd.so
|
||||||
|
CHANNELID 1
|
||||||
|
@endverbatim
|
||||||
|
|
||||||
|
The pound sign # denotes a comment.
|
||||||
|
|
||||||
|
@subsection FRIENDLYNAME
|
||||||
|
The FRIENDLYNAME field is an arbitrary text used to identify the reader.
|
||||||
|
This text is displayed by commands like @c pcsc_scan
|
||||||
|
http://ludovic.rousseau.free.fr/softwares/pcsc-tools/ that prints the
|
||||||
|
names of all the connected and detected readers.
|
||||||
|
|
||||||
|
@subsection DEVICENAME
|
||||||
|
The DEVICENAME field was not used for old drivers (using the IFD handler
|
||||||
|
version 2.0 or previous). It is now (IFD handler version 3.0) used to
|
||||||
|
identify the physical port on which the reader is connected. This is
|
||||||
|
the device name of this port. It is dependent of the OS kernel. For
|
||||||
|
example the first serial port device is called @c /dev/ttyS0 under Linux
|
||||||
|
and @c /dev/cuaa0 under FreeBSD.
|
||||||
|
|
||||||
|
If you want to use IFDHCreateChannel() instead of
|
||||||
|
IFDHCreateChannelByName() then do not use any DEVICENAME line in the
|
||||||
|
configuration file. IFDHCreateChannel() will then be called with the
|
||||||
|
CHANNELID parameter.
|
||||||
|
|
||||||
|
@subsection LIBPATH
|
||||||
|
The LIBPATH field is the filename of the driver code. The driver is a
|
||||||
|
dynamically loaded piece of code (generally a @c drivername.so* file).
|
||||||
|
|
||||||
|
@subsection CHANNELID
|
||||||
|
The CHANNELID is no more used for recent drivers (IFD handler 3.0) and
|
||||||
|
has been superseded by DEVICENAME.
|
||||||
|
|
||||||
|
If you have an old driver this field is used to indicate the port to
|
||||||
|
use. You should read your driver documentation to know what information
|
||||||
|
is needed here. It should be the serial port number for a serial reader.
|
||||||
|
|
||||||
|
CHANNELID was the numeric version of the port in which the reader will
|
||||||
|
be located. This may be done by a symbolic link where @c /dev/pcsc/1 is
|
||||||
|
the first device which may be a symbolic link to @c /dev/ttyS0 or
|
||||||
|
whichever location your reader resides.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _ifd_handler_h_
|
||||||
|
#define _ifd_handler_h_
|
||||||
|
|
||||||
|
#include <pcsclite.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* List of data structures available to ifdhandler
|
||||||
|
*/
|
||||||
|
typedef struct _DEVICE_CAPABILITIES
|
||||||
|
{
|
||||||
|
LPSTR Vendor_Name; /**< Tag 0x0100 */
|
||||||
|
LPSTR IFD_Type; /**< Tag 0x0101 */
|
||||||
|
DWORD IFD_Version; /**< Tag 0x0102 */
|
||||||
|
LPSTR IFD_Serial; /**< Tag 0x0103 */
|
||||||
|
DWORD IFD_Channel_ID; /**< Tag 0x0110 */
|
||||||
|
|
||||||
|
DWORD Asynch_Supported; /**< Tag 0x0120 */
|
||||||
|
DWORD Default_Clock; /**< Tag 0x0121 */
|
||||||
|
DWORD Max_Clock; /**< Tag 0x0122 */
|
||||||
|
DWORD Default_Data_Rate; /**< Tag 0x0123 */
|
||||||
|
DWORD Max_Data_Rate; /**< Tag 0x0124 */
|
||||||
|
DWORD Max_IFSD; /**< Tag 0x0125 */
|
||||||
|
DWORD Synch_Supported; /**< Tag 0x0126 */
|
||||||
|
DWORD Power_Mgmt; /**< Tag 0x0131 */
|
||||||
|
DWORD Card_Auth_Devices; /**< Tag 0x0140 */
|
||||||
|
DWORD User_Auth_Device; /**< Tag 0x0142 */
|
||||||
|
DWORD Mechanics_Supported; /**< Tag 0x0150 */
|
||||||
|
DWORD Vendor_Features; /**< Tag 0x0180 - 0x01F0 User Defined. */
|
||||||
|
}
|
||||||
|
DEVICE_CAPABILITIES, *PDEVICE_CAPABILITIES;
|
||||||
|
|
||||||
|
typedef struct _ICC_STATE
|
||||||
|
{
|
||||||
|
UCHAR ICC_Presence; /**< Tag 0x0300 */
|
||||||
|
UCHAR ICC_Interface_Status; /**< Tag 0x0301 */
|
||||||
|
UCHAR ATR[MAX_ATR_SIZE]; /**< Tag 0x0303 */
|
||||||
|
UCHAR ICC_Type; /**< Tag 0x0304 */
|
||||||
|
}
|
||||||
|
ICC_STATE, *PICC_STATE;
|
||||||
|
|
||||||
|
typedef struct _PROTOCOL_OPTIONS
|
||||||
|
{
|
||||||
|
DWORD Protocol_Type; /**< Tag 0x0201 */
|
||||||
|
DWORD Current_Clock; /**< Tag 0x0202 */
|
||||||
|
DWORD Current_F; /**< Tag 0x0203 */
|
||||||
|
DWORD Current_D; /**< Tag 0x0204 */
|
||||||
|
DWORD Current_N; /**< Tag 0x0205 */
|
||||||
|
DWORD Current_W; /**< Tag 0x0206 */
|
||||||
|
DWORD Current_IFSC; /**< Tag 0x0207 */
|
||||||
|
DWORD Current_IFSD; /**< Tag 0x0208 */
|
||||||
|
DWORD Current_BWT; /**< Tag 0x0209 */
|
||||||
|
DWORD Current_CWT; /**< Tag 0x020A */
|
||||||
|
DWORD Current_EBC; /**< Tag 0x020B */
|
||||||
|
}
|
||||||
|
PROTOCOL_OPTIONS, *PPROTOCOL_OPTIONS;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use by SCardTransmit()
|
||||||
|
*/
|
||||||
|
typedef struct _SCARD_IO_HEADER
|
||||||
|
{
|
||||||
|
DWORD Protocol;
|
||||||
|
DWORD Length;
|
||||||
|
}
|
||||||
|
SCARD_IO_HEADER, *PSCARD_IO_HEADER;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The list of tags should be alot more but this is all I use in the
|
||||||
|
* meantime
|
||||||
|
*/
|
||||||
|
#define TAG_IFD_ATR 0x0303 /**< ATR */
|
||||||
|
#define TAG_IFD_SLOTNUM 0x0180 /**< select a slot */
|
||||||
|
#define TAG_IFD_SLOT_THREAD_SAFE 0x0FAC /**< support access to different slots of the reader */
|
||||||
|
#define TAG_IFD_THREAD_SAFE 0x0FAD /**< driver is thread safe */
|
||||||
|
#define TAG_IFD_SLOTS_NUMBER 0x0FAE /**< number of slots of the reader */
|
||||||
|
#define TAG_IFD_SIMULTANEOUS_ACCESS 0x0FAF /**< number of reader the driver can manage */
|
||||||
|
#define TAG_IFD_POLLING_THREAD 0x0FB0 /**< not used. See TAG_IFD_POLLING_THREAD_WITH_TIMEOUT */
|
||||||
|
#define TAG_IFD_POLLING_THREAD_KILLABLE 0x0FB1 /**< the polling thread can be killed */
|
||||||
|
#define TAG_IFD_STOP_POLLING_THREAD 0x0FB2 /**< method used to stop the polling thread (instead of just pthread_kill()) */
|
||||||
|
#define TAG_IFD_POLLING_THREAD_WITH_TIMEOUT 0x0FB3 /**< driver uses a polling thread with a timeout parameter */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* IFD Handler version number enummerations
|
||||||
|
*/
|
||||||
|
#define IFD_HVERSION_1_0 0x00010000
|
||||||
|
#define IFD_HVERSION_2_0 0x00020000
|
||||||
|
#define IFD_HVERSION_3_0 0x00030000
|
||||||
|
|
||||||
|
/*
|
||||||
|
* List of defines available to ifdhandler
|
||||||
|
*/
|
||||||
|
#define IFD_POWER_UP 500 /**< power up the card */
|
||||||
|
#define IFD_POWER_DOWN 501 /**< power down the card */
|
||||||
|
#define IFD_RESET 502 /**< warm reset */
|
||||||
|
|
||||||
|
#define IFD_NEGOTIATE_PTS1 1 /**< negotiate PTS1 */
|
||||||
|
#define IFD_NEGOTIATE_PTS2 2 /**< negotiate PTS2 */
|
||||||
|
#define IFD_NEGOTIATE_PTS3 4 /**< negotiate PTS3 */
|
||||||
|
|
||||||
|
#define IFD_SUCCESS 0 /**< no error */
|
||||||
|
#define IFD_ERROR_TAG 600 /**< tag unknown */
|
||||||
|
#define IFD_ERROR_SET_FAILURE 601 /**< set failed */
|
||||||
|
#define IFD_ERROR_VALUE_READ_ONLY 602 /**< value is read only */
|
||||||
|
#define IFD_ERROR_PTS_FAILURE 605 /**< failed to negotiate PTS */
|
||||||
|
#define IFD_ERROR_NOT_SUPPORTED 606
|
||||||
|
#define IFD_PROTOCOL_NOT_SUPPORTED 607 /**< requested protocol not supported */
|
||||||
|
#define IFD_ERROR_POWER_ACTION 608 /**< power up failed */
|
||||||
|
#define IFD_ERROR_SWALLOW 609
|
||||||
|
#define IFD_ERROR_EJECT 610
|
||||||
|
#define IFD_ERROR_CONFISCATE 611
|
||||||
|
#define IFD_COMMUNICATION_ERROR 612 /**< generic error */
|
||||||
|
#define IFD_RESPONSE_TIMEOUT 613 /**< timeout */
|
||||||
|
#define IFD_NOT_SUPPORTED 614 /**< request is not supported */
|
||||||
|
#define IFD_ICC_PRESENT 615 /**< card is present */
|
||||||
|
#define IFD_ICC_NOT_PRESENT 616 /**< card is absent */
|
||||||
|
/**
|
||||||
|
* The \ref IFD_NO_SUCH_DEVICE error must be returned by the driver when
|
||||||
|
* it detects the reader is no more present. This will tell pcscd to
|
||||||
|
* remove the reader from the list of available readers.
|
||||||
|
*/
|
||||||
|
#define IFD_NO_SUCH_DEVICE 617
|
||||||
|
#define IFD_ERROR_INSUFFICIENT_BUFFER 618 /**< buffer is too small */
|
||||||
|
|
||||||
|
#ifndef RESPONSECODE_DEFINED_IN_WINTYPES_H
|
||||||
|
typedef long RESPONSECODE;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If you want to compile a V2.0 IFDHandler, define IFDHANDLERv2
|
||||||
|
* before you include this file.
|
||||||
|
*
|
||||||
|
* By default it is setup for for most recent version of the API (V3.0)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef IFDHANDLERv2
|
||||||
|
|
||||||
|
/*
|
||||||
|
* List of Defined Functions Available to IFD_Handler 3.0
|
||||||
|
*
|
||||||
|
* All the functions of IFD_Handler 2.0 are available
|
||||||
|
* IFDHCreateChannelByName() is new
|
||||||
|
* IFDHControl() API changed
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function is required to open a communications channel to the port
|
||||||
|
listed by @p DeviceName.
|
||||||
|
|
||||||
|
Once the channel is opened the reader must be in a state in which it is
|
||||||
|
possible to query IFDHICCPresence() for card status.
|
||||||
|
|
||||||
|
@ingroup IFDHandler
|
||||||
|
@param[in] Lun Logical Unit Number\n
|
||||||
|
Use this for multiple card slots or multiple readers. 0xXXXXYYYY -
|
||||||
|
XXXX multiple readers, YYYY multiple slots. The resource manager will
|
||||||
|
set these automatically. By default the resource manager loads a new
|
||||||
|
instance of the driver so if your reader does not have more than one
|
||||||
|
smart card slot then ignore the Lun in all the functions.\n
|
||||||
|
\n
|
||||||
|
PC/SC supports the loading of multiple readers through one instance of
|
||||||
|
the driver in which XXXX is important. XXXX identifies the unique
|
||||||
|
reader in which the driver communicates to. The driver should set up
|
||||||
|
an array of structures that asociate this XXXX with the underlying
|
||||||
|
details of the particular reader.
|
||||||
|
|
||||||
|
@param[in] DeviceName Filename to use by the driver.\n
|
||||||
|
For drivers configured by @p /etc/reader.conf this is the value of the
|
||||||
|
field \ref DEVICENAME.
|
||||||
|
\n
|
||||||
|
For USB drivers the @p DeviceName must start with @p usb:VID/PID. VID
|
||||||
|
is the Vendor ID and PID is the Product ID. Both are a 4-digits hex
|
||||||
|
number.
|
||||||
|
|
||||||
|
Typically the string is generated by:
|
||||||
|
|
||||||
|
@code
|
||||||
|
printf("usb:%04x/%04x", idVendor, idProduct);
|
||||||
|
@endcode
|
||||||
|
|
||||||
|
The @p DeviceName string may also contain a more specialised
|
||||||
|
identification string. This additional information is used to
|
||||||
|
differentiate between two identical readers connected at the same time.
|
||||||
|
In this case the driver can't differentiate the two readers using VID
|
||||||
|
and PID and must use some additional information identifying the USB
|
||||||
|
port used by each reader.
|
||||||
|
|
||||||
|
- libusb
|
||||||
|
|
||||||
|
For USB drivers using libusb-1.0 http://libusb.sourceforge.net/ for USB
|
||||||
|
abstraction the @p DeviceName the string may be generated by:
|
||||||
|
|
||||||
|
@code
|
||||||
|
printf("usb:%04x/%04x:libusb-1.0:%d:%d:%d",
|
||||||
|
idVendor, idProduct, bus_number, device_address, interface)
|
||||||
|
@endcode
|
||||||
|
|
||||||
|
So it is something like: <tt>usb:08e6/3437:libusb-1.0:7:99:0</tt> under
|
||||||
|
GNU/Linux.
|
||||||
|
|
||||||
|
- libudev
|
||||||
|
|
||||||
|
If pcscd is compiled with libudev support instead of libusb (default
|
||||||
|
since pcsc-lite 1.6.8) the string will look like:
|
||||||
|
|
||||||
|
@code
|
||||||
|
printf("usb:%04x/%04x:libudev:%d:%s", idVendor, idProduct,
|
||||||
|
bInterfaceNumber, devpath);
|
||||||
|
@endcode
|
||||||
|
|
||||||
|
bInterfaceNumber is the number of the interface on the device. It is
|
||||||
|
only usefull for devices with more than one CCID interface.
|
||||||
|
|
||||||
|
devpath is the filename of the device on the file system.
|
||||||
|
|
||||||
|
So it is something like:
|
||||||
|
<tt>usb:08e6/3437:libudev:0:/dev/bus/usb/008/047</tt>
|
||||||
|
under GNU/Linux.
|
||||||
|
|
||||||
|
- other
|
||||||
|
|
||||||
|
If the driver does not understand the <tt>:libusb:</tt> or
|
||||||
|
<tt>:libudev:</tt> scheme or if a new scheme is used, the driver should
|
||||||
|
ignore the part it does not understand instead of failing.
|
||||||
|
|
||||||
|
The driver shall recognize the <tt>usb:VID/PID</tt> part and, only if
|
||||||
|
possible, the remaining of the DeviceName field.
|
||||||
|
|
||||||
|
It is the responsibility of the driver to correctly identify the reader.
|
||||||
|
|
||||||
|
@return Error codes
|
||||||
|
@retval IFD_SUCCESS Successful (\ref IFD_SUCCESS)
|
||||||
|
@retval IFD_COMMUNICATION_ERROR Error has occurred (\ref IFD_COMMUNICATION_ERROR)
|
||||||
|
@retval IFD_NO_SUCH_DEVICE The reader is no more present (\ref IFD_NO_SUCH_DEVICE)
|
||||||
|
*/
|
||||||
|
RESPONSECODE IFDHCreateChannelByName(DWORD Lun, LPSTR DeviceName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function performs a data exchange with the reader (not the card)
|
||||||
|
specified by Lun. It is responsible for abstracting functionality such
|
||||||
|
as PIN pads, biometrics, LCD panels, etc. You should follow the MCT and
|
||||||
|
CTBCS specifications for a list of accepted commands to implement. This
|
||||||
|
function is fully voluntary and does not have to be implemented unless
|
||||||
|
you want extended functionality.
|
||||||
|
|
||||||
|
@ingroup IFDHandler
|
||||||
|
@param[in] Lun Logical Unit Number
|
||||||
|
@param[in] dwControlCode Control code for the operation\n
|
||||||
|
This value identifies the specific operation to be performed. This
|
||||||
|
value is driver specific.
|
||||||
|
@param[in] TxBuffer Transmit data
|
||||||
|
@param[in] TxLength Length of this buffer
|
||||||
|
@param[out] RxBuffer Receive data
|
||||||
|
@param[in] RxLength Length of the response buffer
|
||||||
|
@param[out] pdwBytesReturned Length of response\n
|
||||||
|
This function will be passed the length of the buffer RxBuffer in
|
||||||
|
RxLength and it must set the length of the received data in
|
||||||
|
pdwBytesReturned.
|
||||||
|
|
||||||
|
@note
|
||||||
|
@p *pdwBytesReturned should be set to zero on error.
|
||||||
|
|
||||||
|
@return Error codes
|
||||||
|
@retval IFD_SUCCESS Successful (\ref IFD_SUCCESS)
|
||||||
|
@retval IFD_COMMUNICATION_ERROR Error has occurred (\ref IFD_COMMUNICATION_ERROR)
|
||||||
|
@retval IFD_RESPONSE_TIMEOUT The response timed out (\ref IFD_RESPONSE_TIMEOUT)
|
||||||
|
@retval IFD_NO_SUCH_DEVICE The reader is no more present (\ref IFD_NO_SUCH_DEVICE)
|
||||||
|
*/
|
||||||
|
RESPONSECODE IFDHControl(DWORD Lun, DWORD dwControlCode, PUCHAR
|
||||||
|
TxBuffer, DWORD TxLength, PUCHAR RxBuffer, DWORD RxLength,
|
||||||
|
LPDWORD pdwBytesReturned);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Available in IFD_Handler 2.0
|
||||||
|
*
|
||||||
|
* @deprecated
|
||||||
|
* You should use the new form of IFDHControl()
|
||||||
|
*/
|
||||||
|
RESPONSECODE IFDHControl(DWORD Lun, PUCHAR TxBuffer, DWORD TxLength,
|
||||||
|
PUCHAR RxBuffer, PDWORD RxLength);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* common functions in IFD_Handler 2.0 and 3.0
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
This function is required to open a communications channel to the port
|
||||||
|
listed by Channel. For example, the first serial reader on COM1 would
|
||||||
|
link to @p /dev/pcsc/1 which would be a symbolic link to @p /dev/ttyS0
|
||||||
|
on some machines This is used to help with inter-machine independence.
|
||||||
|
|
||||||
|
On machines with no /dev directory the driver writer may choose to map
|
||||||
|
their Channel to whatever they feel is appropriate.
|
||||||
|
|
||||||
|
Once the channel is opened the reader must be in a state in which it is
|
||||||
|
possible to query IFDHICCPresence() for card status.
|
||||||
|
|
||||||
|
USB readers can ignore the @p Channel parameter and query the USB bus
|
||||||
|
for the particular reader by manufacturer and product id.
|
||||||
|
|
||||||
|
@ingroup IFDHandler
|
||||||
|
@param[in] Lun Logical Unit Number\n
|
||||||
|
Use this for multiple card slots or multiple readers. 0xXXXXYYYY -
|
||||||
|
XXXX multiple readers, YYYY multiple slots. The resource manager will
|
||||||
|
set these automatically. By default the resource manager loads a new
|
||||||
|
instance of the driver so if your reader does not have more than one
|
||||||
|
smart card slot then ignore the Lun in all the functions.\n
|
||||||
|
\n
|
||||||
|
PC/SC supports the loading of multiple readers through one instance of
|
||||||
|
the driver in which XXXX is important. XXXX identifies the unique
|
||||||
|
reader in which the driver communicates to. The driver should set up
|
||||||
|
an array of structures that associate this XXXX with the underlying
|
||||||
|
details of the particular reader.
|
||||||
|
@param[in] Channel Channel ID
|
||||||
|
This is denoted by the following:
|
||||||
|
- 0x000001 @p /dev/pcsc/1
|
||||||
|
- 0x000002 @p /dev/pcsc/2
|
||||||
|
- 0x000003 @p /dev/pcsc/3
|
||||||
|
- 0x000004 @p /dev/pcsc/4
|
||||||
|
|
||||||
|
@return Error codes
|
||||||
|
@retval IFD_SUCCESS Successful (\ref IFD_SUCCESS)
|
||||||
|
@retval IFD_COMMUNICATION_ERROR Error has occurred (\ref IFD_COMMUNICATION_ERROR)
|
||||||
|
@retval IFD_NO_SUCH_DEVICE The reader is no more present (\ref IFD_NO_SUCH_DEVICE)
|
||||||
|
|
||||||
|
*/
|
||||||
|
RESPONSECODE IFDHCreateChannel(DWORD Lun, DWORD Channel);
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function should close the reader communication channel for the
|
||||||
|
particular reader. Prior to closing the communication channel the reader
|
||||||
|
should make sure the card is powered down and the terminal is also
|
||||||
|
powered down.
|
||||||
|
|
||||||
|
@ingroup IFDHandler
|
||||||
|
@param[in] Lun Logical Unit Number
|
||||||
|
|
||||||
|
@return Error codes
|
||||||
|
@retval IFD_SUCCESS Successful (\ref IFD_SUCCESS)
|
||||||
|
@retval IFD_COMMUNICATION_ERROR Error has occurred (\ref IFD_COMMUNICATION_ERROR)
|
||||||
|
@retval IFD_NO_SUCH_DEVICE The reader is no more present (\ref IFD_NO_SUCH_DEVICE)
|
||||||
|
*/
|
||||||
|
RESPONSECODE IFDHCloseChannel(DWORD Lun);
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function should get the slot/card capabilities for a particular
|
||||||
|
slot/card specified by Lun. Again, if you have only 1 card slot and
|
||||||
|
don't mind loading a new driver for each reader then ignore Lun.
|
||||||
|
|
||||||
|
@ingroup IFDHandler
|
||||||
|
@param[in] Lun Logical Unit Number
|
||||||
|
@param[in] Tag Tag of the desired data value
|
||||||
|
- \ref TAG_IFD_ATR
|
||||||
|
Return the ATR and its size (implementation is mandatory).
|
||||||
|
- \ref TAG_IFD_SLOTNUM
|
||||||
|
Unused/deprecated
|
||||||
|
- \ref SCARD_ATTR_ATR_STRING
|
||||||
|
Same as \ref TAG_IFD_ATR but this one is not mandatory. It is defined
|
||||||
|
in Microsoft PC/SC SCardGetAttrib().
|
||||||
|
- \ref TAG_IFD_SIMULTANEOUS_ACCESS
|
||||||
|
Return the number of sessions (readers) the driver can handle in
|
||||||
|
<tt>Value[0]</tt>.
|
||||||
|
This is used for multiple readers sharing the same driver.
|
||||||
|
- \ref TAG_IFD_THREAD_SAFE
|
||||||
|
If the driver supports more than one reader (see
|
||||||
|
\ref TAG_IFD_SIMULTANEOUS_ACCESS above) this tag indicates if the
|
||||||
|
driver supports access to multiple readers at the same time.
|
||||||
|
- <tt>Value[0] = 0</tt>: the driver DOES NOT support simultaneous accesses.
|
||||||
|
- <tt>Value[0] = 1</tt>: the driver supports simultaneous accesses.
|
||||||
|
- \ref TAG_IFD_SLOTS_NUMBER
|
||||||
|
Return the number of slots in this reader in <tt>Value[0]</tt>.
|
||||||
|
- \ref TAG_IFD_SLOT_THREAD_SAFE
|
||||||
|
If the reader has more than one slot (see \ref TAG_IFD_SLOTS_NUMBER
|
||||||
|
above) this tag indicates if the driver supports access to multiple
|
||||||
|
slots of the same reader at the same time.
|
||||||
|
- <tt>value[0] = 0</tt>: the driver supports only 1 slot access at a time.
|
||||||
|
- <tt>value[0] = 1</tt>: the driver supports simultaneous slot accesses.
|
||||||
|
- \ref TAG_IFD_POLLING_THREAD
|
||||||
|
Unused/deprecated
|
||||||
|
- \ref TAG_IFD_POLLING_THREAD_WITH_TIMEOUT
|
||||||
|
If the driver provides a polling thread then @p Value is a pointer to
|
||||||
|
this function. The function prototype is:
|
||||||
|
@verbatim
|
||||||
|
RESPONSECODE foo(DWORD Lun, int timeout);
|
||||||
|
@endverbatim
|
||||||
|
- \ref TAG_IFD_POLLING_THREAD_KILLABLE
|
||||||
|
Tell if the polling thread can be killed (pthread_kill()) by pcscd
|
||||||
|
- <tt>value[0] = 0</tt>: the driver can NOT be stopped using
|
||||||
|
pthread_cancel(). The driver must then implement
|
||||||
|
\ref TAG_IFD_STOP_POLLING_THREAD
|
||||||
|
- <tt>value[0] = 1</tt>: the driver can be stopped using pthread_cancel()
|
||||||
|
- \ref TAG_IFD_STOP_POLLING_THREAD
|
||||||
|
Returns a pointer in @p Value to the function used to stop the polling
|
||||||
|
thread returned by \ref TAG_IFD_POLLING_THREAD_WITH_TIMEOUT. The
|
||||||
|
function prototype is:
|
||||||
|
@verbatim
|
||||||
|
RESPONSECODE foo(DWORD Lun);
|
||||||
|
@endverbatim
|
||||||
|
@param[in,out] Length Length of the desired data value
|
||||||
|
@param[out] Value Value of the desired data
|
||||||
|
|
||||||
|
@return Error codes
|
||||||
|
@retval IFD_SUCCESS Successful (\ref IFD_SUCCESS)
|
||||||
|
@retval IFD_ERROR_INSUFFICIENT_BUFFER Buffer is too small (\ref IFD_ERROR_INSUFFICIENT_BUFFER)
|
||||||
|
@retval IFD_COMMUNICATION_ERROR Error has occurred (\ref IFD_COMMUNICATION_ERROR)
|
||||||
|
@retval IFD_ERROR_TAG Invalid tag given (\ref IFD_ERROR_TAG)
|
||||||
|
@retval IFD_NO_SUCH_DEVICE The reader is no more present (\ref IFD_NO_SUCH_DEVICE)
|
||||||
|
*/
|
||||||
|
RESPONSECODE IFDHGetCapabilities(DWORD Lun, DWORD Tag, PDWORD Length,
|
||||||
|
PUCHAR Value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function should set the slot/card capabilities for a particular
|
||||||
|
slot/card specified by @p Lun. Again, if you have only 1 card slot and
|
||||||
|
don't mind loading a new driver for each reader then ignore @p Lun.
|
||||||
|
|
||||||
|
@ingroup IFDHandler
|
||||||
|
@param[in] Lun Logical Unit Number
|
||||||
|
@param[in] Tag Tag of the desired data value
|
||||||
|
@param[in,out] Length Length of the desired data value
|
||||||
|
@param[out] Value Value of the desired data
|
||||||
|
|
||||||
|
This function is also called when the application uses the PC/SC
|
||||||
|
SCardGetAttrib() function. The list of supported tags is not limited.
|
||||||
|
|
||||||
|
@return Error codes
|
||||||
|
@retval IFD_SUCCESS Successful (\ref IFD_SUCCESS)
|
||||||
|
@retval IFD_ERROR_TAG Invalid tag given (\ref IFD_ERROR_TAG)
|
||||||
|
@retval IFD_ERROR_SET_FAILURE Could not set value (\ref IFD_ERROR_SET_FAILURE)
|
||||||
|
@retval IFD_ERROR_VALUE_READ_ONLY Trying to set read only value (\ref IFD_ERROR_VALUE_READ_ONLY)
|
||||||
|
@retval IFD_NO_SUCH_DEVICE The reader is no more present (\ref IFD_NO_SUCH_DEVICE)
|
||||||
|
*/
|
||||||
|
RESPONSECODE IFDHSetCapabilities(DWORD Lun, DWORD Tag, DWORD Length, PUCHAR Value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function should set the Protocol Type Selection (PTS) of a
|
||||||
|
particular card/slot using the three PTS parameters sent
|
||||||
|
|
||||||
|
@ingroup IFDHandler
|
||||||
|
@param[in] Lun Logical Unit Number
|
||||||
|
@param[in] Protocol Desired protocol
|
||||||
|
- \ref SCARD_PROTOCOL_T0
|
||||||
|
T=0 protocol
|
||||||
|
- \ref SCARD_PROTOCOL_T1
|
||||||
|
T=1 protocol
|
||||||
|
@param[in] Flags Logical OR of possible values to determine which PTS values
|
||||||
|
to negotiate
|
||||||
|
- \ref IFD_NEGOTIATE_PTS1
|
||||||
|
- \ref IFD_NEGOTIATE_PTS2
|
||||||
|
- \ref IFD_NEGOTIATE_PTS3
|
||||||
|
@param[in] PTS1 1st PTS Value
|
||||||
|
@param[in] PTS2 2nd PTS Value
|
||||||
|
@param[in] PTS3 3rd PTS Value\n
|
||||||
|
See ISO 7816/EMV documentation.
|
||||||
|
|
||||||
|
@return Error codes
|
||||||
|
@retval IFD_SUCCESS Successful (\ref IFD_SUCCESS)
|
||||||
|
@retval IFD_ERROR_PTS_FAILURE Could not set PTS value (\ref IFD_ERROR_PTS_FAILURE)
|
||||||
|
@retval IFD_COMMUNICATION_ERROR Error has occurred (\ref IFD_COMMUNICATION_ERROR)
|
||||||
|
@retval IFD_PROTOCOL_NOT_SUPPORTED Protocol is not supported (\ref IFD_PROTOCOL_NOT_SUPPORTED)
|
||||||
|
@retval IFD_NOT_SUPPORTED Action not supported (\ref IFD_NOT_SUPPORTED)
|
||||||
|
@retval IFD_NO_SUCH_DEVICE The reader is no more present (\ref IFD_NO_SUCH_DEVICE)
|
||||||
|
*/
|
||||||
|
RESPONSECODE IFDHSetProtocolParameters(DWORD Lun, DWORD Protocol, UCHAR Flags,
|
||||||
|
UCHAR PTS1, UCHAR PTS2, UCHAR PTS3);
|
||||||
|
/**
|
||||||
|
This function controls the power and reset signals of the smart card
|
||||||
|
reader at the particular reader/slot specified by @p Lun.
|
||||||
|
|
||||||
|
@ingroup IFDHandler
|
||||||
|
@param[in] Lun Logical Unit Number
|
||||||
|
@param[in] Action Action to be taken on the card
|
||||||
|
- \ref IFD_POWER_UP
|
||||||
|
Power up the card (store and return Atr and AtrLength)
|
||||||
|
- \ref IFD_POWER_DOWN
|
||||||
|
Power down the card (Atr and AtrLength should be zeroed)
|
||||||
|
- \ref IFD_RESET
|
||||||
|
Perform a warm reset of the card (no power down). If the card is not powered then power up the card (store and return Atr and AtrLength)
|
||||||
|
@param[out] Atr Answer to Reset (ATR) of the card\n
|
||||||
|
The driver is responsible for caching this value in case
|
||||||
|
IFDHGetCapabilities() is called requesting the ATR and its length. The
|
||||||
|
ATR length should not exceed \ref MAX_ATR_SIZE.
|
||||||
|
@param[in,out] AtrLength Length of the ATR\n
|
||||||
|
This should not exceed \ref MAX_ATR_SIZE.
|
||||||
|
|
||||||
|
@note
|
||||||
|
Memory cards without an ATR should return \ref IFD_SUCCESS on reset but the
|
||||||
|
Atr should be zeroed and the length should be zero Reset errors should
|
||||||
|
return zero for the AtrLength and return \ref IFD_ERROR_POWER_ACTION.
|
||||||
|
|
||||||
|
@return Error codes
|
||||||
|
@retval IFD_SUCCESS Successful (\ref IFD_SUCCESS)
|
||||||
|
@retval IFD_ERROR_POWER_ACTION Error powering/resetting card (\ref IFD_ERROR_POWER_ACTION)
|
||||||
|
@retval IFD_COMMUNICATION_ERROR Error has occurred (\ref IFD_COMMUNICATION_ERROR)
|
||||||
|
@retval IFD_NOT_SUPPORTED Action not supported (\ref IFD_NOT_SUPPORTED)
|
||||||
|
@retval IFD_NO_SUCH_DEVICE The reader is no more present (\ref IFD_NO_SUCH_DEVICE)
|
||||||
|
*/
|
||||||
|
RESPONSECODE IFDHPowerICC(DWORD Lun, DWORD Action, PUCHAR Atr, PDWORD
|
||||||
|
AtrLength);
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function performs an APDU exchange with the card/slot specified by
|
||||||
|
Lun. The driver is responsible for performing any protocol specific
|
||||||
|
exchanges such as T=0, 1, etc. differences. Calling this function will
|
||||||
|
abstract all protocol differences.
|
||||||
|
|
||||||
|
@ingroup IFDHandler
|
||||||
|
@param[in] Lun Logical Unit Number
|
||||||
|
@param[in] SendPci contains two structure members
|
||||||
|
- Protocol 0, 1, ... 14\n
|
||||||
|
T=0 ... T=14
|
||||||
|
- Length\n
|
||||||
|
Not used.
|
||||||
|
@param[in] TxBuffer Transmit APDU\n
|
||||||
|
Example: "\x00\xA4\x00\x00\x02\x3F\x00"
|
||||||
|
@param[in] TxLength Length of this buffer
|
||||||
|
@param[out] RxBuffer Receive APDU\n
|
||||||
|
Example: "\x61\x14"
|
||||||
|
@param[in,out] RxLength Length of the received APDU\n
|
||||||
|
This function will be passed the size of the buffer of RxBuffer and
|
||||||
|
this function is responsible for setting this to the length of the
|
||||||
|
received APDU response. This should be ZERO on all errors. The
|
||||||
|
resource manager will take responsibility of zeroing out any temporary
|
||||||
|
APDU buffers for security reasons.
|
||||||
|
@param[out] RecvPci contains two structure members
|
||||||
|
- Protocol - 0, 1, ... 14\n
|
||||||
|
T=0 ... T=14
|
||||||
|
- Length\n
|
||||||
|
Not used.
|
||||||
|
|
||||||
|
@note
|
||||||
|
The driver is responsible for knowing what type of card it has. If the
|
||||||
|
current slot/card contains a memory card then this command should ignore
|
||||||
|
the Protocol and use the MCT style commands for support for these style
|
||||||
|
cards and transmit them appropriately. If your reader does not support
|
||||||
|
memory cards or you don't want to implement this functionality, then
|
||||||
|
ignore this.
|
||||||
|
@par
|
||||||
|
RxLength should be set to zero on error.
|
||||||
|
@par
|
||||||
|
The driver is not responsible for doing an automatic Get Response
|
||||||
|
command for received buffers containing 61 XX.
|
||||||
|
|
||||||
|
@return Error codes
|
||||||
|
@retval IFD_SUCCESS Successful (\ref IFD_SUCCESS)
|
||||||
|
@retval IFD_COMMUNICATION_ERROR Error has occurred (\ref IFD_COMMUNICATION_ERROR)
|
||||||
|
@retval IFD_RESPONSE_TIMEOUT The response timed out (\ref IFD_RESPONSE_TIMEOUT)
|
||||||
|
@retval IFD_ICC_NOT_PRESENT ICC is not present (\ref IFD_ICC_NOT_PRESENT)
|
||||||
|
@retval IFD_NOT_SUPPORTED Action not supported (\ref IFD_NOT_SUPPORTED)
|
||||||
|
@retval IFD_NO_SUCH_DEVICE The reader is no more present (\ref IFD_NO_SUCH_DEVICE)
|
||||||
|
*/
|
||||||
|
RESPONSECODE IFDHTransmitToICC(DWORD Lun, SCARD_IO_HEADER SendPci,
|
||||||
|
PUCHAR TxBuffer, DWORD TxLength, PUCHAR RxBuffer, PDWORD
|
||||||
|
RxLength, PSCARD_IO_HEADER RecvPci);
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function returns the status of the card inserted in the reader/slot
|
||||||
|
specified by @p Lun. In cases where the device supports asynchronous
|
||||||
|
card insertion/removal detection, it is advised that the driver manages
|
||||||
|
this through a thread so the driver does not have to send and receive a
|
||||||
|
command each time this function is called.
|
||||||
|
|
||||||
|
@ingroup IFDHandler
|
||||||
|
@param[in] Lun Logical Unit Number
|
||||||
|
|
||||||
|
@return Error codes
|
||||||
|
@retval IFD_SUCCESS Successful (\ref IFD_SUCCESS)
|
||||||
|
@retval IFD_COMMUNICATION_ERROR Error has occurred (\ref IFD_COMMUNICATION_ERROR)
|
||||||
|
@retval IFD_ICC_NOT_PRESENT ICC is not present (\ref IFD_ICC_NOT_PRESENT)
|
||||||
|
@retval IFD_NO_SUCH_DEVICE The reader is no more present (\ref IFD_NO_SUCH_DEVICE)
|
||||||
|
*/
|
||||||
|
RESPONSECODE IFDHICCPresence(DWORD Lun);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,309 @@
|
||||||
|
/*
|
||||||
|
* MUSCLE SmartCard Development ( http://pcsclite.alioth.debian.org/pcsclite.html )
|
||||||
|
*
|
||||||
|
* Copyright (C) 1999-2004
|
||||||
|
* David Corcoran <corcoran@musclecard.com>
|
||||||
|
* Copyright (C) 2002-2011
|
||||||
|
* Ludovic Rousseau <ludovic.rousseau@free.fr>
|
||||||
|
* Copyright (C) 2005
|
||||||
|
* Martin Paljak <martin@paljak.pri.ee>
|
||||||
|
*
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. The name of the author may not be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief This keeps a list of defines for pcsc-lite.
|
||||||
|
*
|
||||||
|
* Error codes from http://msdn.microsoft.com/en-us/library/aa924526.aspx
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __pcsclite_h__
|
||||||
|
#define __pcsclite_h__
|
||||||
|
|
||||||
|
#include <wintypes.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef LONG SCARDCONTEXT; /**< \p hContext returned by SCardEstablishContext() */
|
||||||
|
typedef SCARDCONTEXT *PSCARDCONTEXT;
|
||||||
|
typedef SCARDCONTEXT *LPSCARDCONTEXT;
|
||||||
|
typedef LONG SCARDHANDLE; /**< \p hCard returned by SCardConnect() */
|
||||||
|
typedef SCARDHANDLE *PSCARDHANDLE;
|
||||||
|
typedef SCARDHANDLE *LPSCARDHANDLE;
|
||||||
|
|
||||||
|
#define MAX_ATR_SIZE 33 /**< Maximum ATR size */
|
||||||
|
|
||||||
|
/* Set structure elements aligment on bytes
|
||||||
|
* http://gcc.gnu.org/onlinedocs/gcc/Structure_002dPacking-Pragmas.html */
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#pragma pack(1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
const char *szReader;
|
||||||
|
void *pvUserData;
|
||||||
|
DWORD dwCurrentState;
|
||||||
|
DWORD dwEventState;
|
||||||
|
DWORD cbAtr;
|
||||||
|
unsigned char rgbAtr[MAX_ATR_SIZE];
|
||||||
|
}
|
||||||
|
SCARD_READERSTATE, *LPSCARD_READERSTATE;
|
||||||
|
|
||||||
|
/** Protocol Control Information (PCI) */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
unsigned long dwProtocol; /**< Protocol identifier */
|
||||||
|
unsigned long cbPciLength; /**< Protocol Control Inf Length */
|
||||||
|
}
|
||||||
|
SCARD_IO_REQUEST, *PSCARD_IO_REQUEST, *LPSCARD_IO_REQUEST;
|
||||||
|
|
||||||
|
typedef const SCARD_IO_REQUEST *LPCSCARD_IO_REQUEST;
|
||||||
|
|
||||||
|
extern const SCARD_IO_REQUEST g_rgSCardT0Pci, g_rgSCardT1Pci, g_rgSCardRawPci;
|
||||||
|
|
||||||
|
/* restore default structure elements alignment */
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#pragma pack()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SCARD_PCI_T0 (&g_rgSCardT0Pci) /**< protocol control information (PCI) for T=0 */
|
||||||
|
#define SCARD_PCI_T1 (&g_rgSCardT1Pci) /**< protocol control information (PCI) for T=1 */
|
||||||
|
#define SCARD_PCI_RAW (&g_rgSCardRawPci) /**< protocol control information (PCI) for RAW protocol */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup ErrorCodes ErrorCodes
|
||||||
|
* @brief Error code documentation
|
||||||
|
*
|
||||||
|
* The error codes descriptions are from
|
||||||
|
* http://msdn.microsoft.com/en-us/library/aa924526.aspx
|
||||||
|
*/
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_S_SUCCESS ((LONG)0x00000000) /**< No error was encountered. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_F_INTERNAL_ERROR ((LONG)0x80100001) /**< An internal consistency check failed. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_CANCELLED ((LONG)0x80100002) /**< The action was cancelled by an SCardCancel request. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_INVALID_HANDLE ((LONG)0x80100003) /**< The supplied handle was invalid. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_INVALID_PARAMETER ((LONG)0x80100004) /**< One or more of the supplied parameters could not be properly interpreted. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_INVALID_TARGET ((LONG)0x80100005) /**< Registry startup information is missing or invalid. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_NO_MEMORY ((LONG)0x80100006) /**< Not enough memory available to complete this command. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_F_WAITED_TOO_LONG ((LONG)0x80100007) /**< An internal consistency timer has expired. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_INSUFFICIENT_BUFFER ((LONG)0x80100008) /**< The data buffer to receive returned data is too small for the returned data. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_UNKNOWN_READER ((LONG)0x80100009) /**< The specified reader name is not recognized. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_TIMEOUT ((LONG)0x8010000A) /**< The user-specified timeout value has expired. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_SHARING_VIOLATION ((LONG)0x8010000B) /**< The smart card cannot be accessed because of other connections outstanding. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_NO_SMARTCARD ((LONG)0x8010000C) /**< The operation requires a Smart Card, but no Smart Card is currently in the device. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_UNKNOWN_CARD ((LONG)0x8010000D) /**< The specified smart card name is not recognized. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_CANT_DISPOSE ((LONG)0x8010000E) /**< The system could not dispose of the media in the requested manner. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_PROTO_MISMATCH ((LONG)0x8010000F) /**< The requested protocols are incompatible with the protocol currently in use with the smart card. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_NOT_READY ((LONG)0x80100010) /**< The reader or smart card is not ready to accept commands. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_INVALID_VALUE ((LONG)0x80100011) /**< One or more of the supplied parameters values could not be properly interpreted. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_SYSTEM_CANCELLED ((LONG)0x80100012) /**< The action was cancelled by the system, presumably to log off or shut down. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_F_COMM_ERROR ((LONG)0x80100013) /**< An internal communications error has been detected. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_F_UNKNOWN_ERROR ((LONG)0x80100014) /**< An internal error has been detected, but the source is unknown. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_INVALID_ATR ((LONG)0x80100015) /**< An ATR obtained from the registry is not a valid ATR string. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_NOT_TRANSACTED ((LONG)0x80100016) /**< An attempt was made to end a non-existent transaction. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_READER_UNAVAILABLE ((LONG)0x80100017) /**< The specified reader is not currently available for use. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_P_SHUTDOWN ((LONG)0x80100018) /**< The operation has been aborted to allow the server application to exit. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_PCI_TOO_SMALL ((LONG)0x80100019) /**< The PCI Receive buffer was too small. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_READER_UNSUPPORTED ((LONG)0x8010001A) /**< The reader driver does not meet minimal requirements for support. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_DUPLICATE_READER ((LONG)0x8010001B) /**< The reader driver did not produce a unique reader name. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_CARD_UNSUPPORTED ((LONG)0x8010001C) /**< The smart card does not meet minimal requirements for support. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_NO_SERVICE ((LONG)0x8010001D) /**< The Smart card resource manager is not running. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_SERVICE_STOPPED ((LONG)0x8010001E) /**< The Smart card resource manager has shut down. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_UNEXPECTED ((LONG)0x8010001F) /**< An unexpected card error has occurred. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_UNSUPPORTED_FEATURE ((LONG)0x8010001F) /**< This smart card does not support the requested feature. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_ICC_INSTALLATION ((LONG)0x80100020) /**< No primary provider can be found for the smart card. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_ICC_CREATEORDER ((LONG)0x80100021) /**< The requested order of object creation is not supported. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
/* #define SCARD_E_UNSUPPORTED_FEATURE ((LONG)0x80100022) / **< This smart card does not support the requested feature. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_DIR_NOT_FOUND ((LONG)0x80100023) /**< The identified directory does not exist in the smart card. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_FILE_NOT_FOUND ((LONG)0x80100024) /**< The identified file does not exist in the smart card. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_NO_DIR ((LONG)0x80100025) /**< The supplied path does not represent a smart card directory. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_NO_FILE ((LONG)0x80100026) /**< The supplied path does not represent a smart card file. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_NO_ACCESS ((LONG)0x80100027) /**< Access is denied to this file. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_WRITE_TOO_MANY ((LONG)0x80100028) /**< The smart card does not have enough memory to store the information. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_BAD_SEEK ((LONG)0x80100029) /**< There was an error trying to set the smart card file object pointer. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_INVALID_CHV ((LONG)0x8010002A) /**< The supplied PIN is incorrect. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_UNKNOWN_RES_MNG ((LONG)0x8010002B) /**< An unrecognized error code was returned from a layered component. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_NO_SUCH_CERTIFICATE ((LONG)0x8010002C) /**< The requested certificate does not exist. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_CERTIFICATE_UNAVAILABLE ((LONG)0x8010002D) /**< The requested certificate could not be obtained. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_NO_READERS_AVAILABLE ((LONG)0x8010002E) /**< Cannot find a smart card reader. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_COMM_DATA_LOST ((LONG)0x8010002F) /**< A communications error with the smart card has been detected. Retry the operation. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_NO_KEY_CONTAINER ((LONG)0x80100030) /**< The requested key container does not exist on the smart card. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_SERVER_TOO_BUSY ((LONG)0x80100031) /**< The Smart Card Resource Manager is too busy to complete this operation. */
|
||||||
|
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_W_UNSUPPORTED_CARD ((LONG)0x80100065) /**< The reader cannot communicate with the card, due to ATR string configuration conflicts. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_W_UNRESPONSIVE_CARD ((LONG)0x80100066) /**< The smart card is not responding to a reset. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_W_UNPOWERED_CARD ((LONG)0x80100067) /**< Power has been removed from the smart card, so that further communication is not possible. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_W_RESET_CARD ((LONG)0x80100068) /**< The smart card has been reset, so any shared state information is invalid. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_W_REMOVED_CARD ((LONG)0x80100069) /**< The smart card has been removed, so further communication is not possible. */
|
||||||
|
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_W_SECURITY_VIOLATION ((LONG)0x8010006A) /**< Access was denied because of a security violation. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_W_WRONG_CHV ((LONG)0x8010006B) /**< The card cannot be accessed because the wrong PIN was presented. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_W_CHV_BLOCKED ((LONG)0x8010006C) /**< The card cannot be accessed because the maximum number of PIN entry attempts has been reached. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_W_EOF ((LONG)0x8010006D) /**< The end of the smart card file has been reached. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_W_CANCELLED_BY_USER ((LONG)0x8010006E) /**< The user pressed "Cancel" on a Smart Card Selection Dialog. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_W_CARD_NOT_AUTHENTICATED ((LONG)0x8010006F) /**< No PIN was presented to the smart card. */
|
||||||
|
|
||||||
|
#define SCARD_AUTOALLOCATE (DWORD)(-1) /**< see SCardFreeMemory() */
|
||||||
|
#define SCARD_SCOPE_USER 0x0000 /**< Scope in user space */
|
||||||
|
#define SCARD_SCOPE_TERMINAL 0x0001 /**< Scope in terminal */
|
||||||
|
#define SCARD_SCOPE_SYSTEM 0x0002 /**< Scope in system */
|
||||||
|
#define SCARD_SCOPE_GLOBAL 0x0003 /**< Scope is global */
|
||||||
|
|
||||||
|
#define SCARD_PROTOCOL_UNDEFINED 0x0000 /**< protocol not set */
|
||||||
|
#define SCARD_PROTOCOL_UNSET SCARD_PROTOCOL_UNDEFINED /* backward compat */
|
||||||
|
#define SCARD_PROTOCOL_T0 0x0001 /**< T=0 active protocol. */
|
||||||
|
#define SCARD_PROTOCOL_T1 0x0002 /**< T=1 active protocol. */
|
||||||
|
#define SCARD_PROTOCOL_RAW 0x0004 /**< Raw active protocol. */
|
||||||
|
#define SCARD_PROTOCOL_T15 0x0008 /**< T=15 protocol. */
|
||||||
|
|
||||||
|
#define SCARD_PROTOCOL_ANY (SCARD_PROTOCOL_T0|SCARD_PROTOCOL_T1) /**< IFD determines prot. */
|
||||||
|
|
||||||
|
#define SCARD_SHARE_EXCLUSIVE 0x0001 /**< Exclusive mode only */
|
||||||
|
#define SCARD_SHARE_SHARED 0x0002 /**< Shared mode only */
|
||||||
|
#define SCARD_SHARE_DIRECT 0x0003 /**< Raw mode only */
|
||||||
|
|
||||||
|
#define SCARD_LEAVE_CARD 0x0000 /**< Do nothing on close */
|
||||||
|
#define SCARD_RESET_CARD 0x0001 /**< Reset on close */
|
||||||
|
#define SCARD_UNPOWER_CARD 0x0002 /**< Power down on close */
|
||||||
|
#define SCARD_EJECT_CARD 0x0003 /**< Eject on close */
|
||||||
|
|
||||||
|
#define SCARD_UNKNOWN 0x0001 /**< Unknown state */
|
||||||
|
#define SCARD_ABSENT 0x0002 /**< Card is absent */
|
||||||
|
#define SCARD_PRESENT 0x0004 /**< Card is present */
|
||||||
|
#define SCARD_SWALLOWED 0x0008 /**< Card not powered */
|
||||||
|
#define SCARD_POWERED 0x0010 /**< Card is powered */
|
||||||
|
#define SCARD_NEGOTIABLE 0x0020 /**< Ready for PTS */
|
||||||
|
#define SCARD_SPECIFIC 0x0040 /**< PTS has been set */
|
||||||
|
|
||||||
|
#define SCARD_STATE_UNAWARE 0x0000 /**< App wants status */
|
||||||
|
#define SCARD_STATE_IGNORE 0x0001 /**< Ignore this reader */
|
||||||
|
#define SCARD_STATE_CHANGED 0x0002 /**< State has changed */
|
||||||
|
#define SCARD_STATE_UNKNOWN 0x0004 /**< Reader unknown */
|
||||||
|
#define SCARD_STATE_UNAVAILABLE 0x0008 /**< Status unavailable */
|
||||||
|
#define SCARD_STATE_EMPTY 0x0010 /**< Card removed */
|
||||||
|
#define SCARD_STATE_PRESENT 0x0020 /**< Card inserted */
|
||||||
|
#define SCARD_STATE_ATRMATCH 0x0040 /**< ATR matches card */
|
||||||
|
#define SCARD_STATE_EXCLUSIVE 0x0080 /**< Exclusive Mode */
|
||||||
|
#define SCARD_STATE_INUSE 0x0100 /**< Shared Mode */
|
||||||
|
#define SCARD_STATE_MUTE 0x0200 /**< Unresponsive card */
|
||||||
|
#define SCARD_STATE_UNPOWERED 0x0400 /**< Unpowered card */
|
||||||
|
|
||||||
|
#ifndef INFINITE
|
||||||
|
#define INFINITE 0xFFFFFFFF /**< Infinite timeout */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define PCSCLITE_VERSION_NUMBER "1.8.22" /**< Current version */
|
||||||
|
/** Maximum readers context (a slot is count as a reader) */
|
||||||
|
#define PCSCLITE_MAX_READERS_CONTEXTS 16
|
||||||
|
|
||||||
|
#define MAX_READERNAME 128
|
||||||
|
|
||||||
|
#ifndef SCARD_ATR_LENGTH
|
||||||
|
#define SCARD_ATR_LENGTH MAX_ATR_SIZE /**< Maximum ATR size */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The message and buffer sizes must be multiples of 16.
|
||||||
|
* The max message size must be at least large enough
|
||||||
|
* to accomodate the transmit_struct
|
||||||
|
*/
|
||||||
|
#define MAX_BUFFER_SIZE 264 /**< Maximum Tx/Rx Buffer for short APDU */
|
||||||
|
#define MAX_BUFFER_SIZE_EXTENDED (4 + 3 + (1<<16) + 3 + 2) /**< enhanced (64K + APDU + Lc + Le + SW) Tx/Rx Buffer */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Gets a stringified error response
|
||||||
|
*/
|
||||||
|
const char *pcsc_stringify_error(const LONG);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,309 @@
|
||||||
|
/*
|
||||||
|
* MUSCLE SmartCard Development ( http://pcsclite.alioth.debian.org/pcsclite.html )
|
||||||
|
*
|
||||||
|
* Copyright (C) 1999-2004
|
||||||
|
* David Corcoran <corcoran@musclecard.com>
|
||||||
|
* Copyright (C) 2002-2011
|
||||||
|
* Ludovic Rousseau <ludovic.rousseau@free.fr>
|
||||||
|
* Copyright (C) 2005
|
||||||
|
* Martin Paljak <martin@paljak.pri.ee>
|
||||||
|
*
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. The name of the author may not be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief This keeps a list of defines for pcsc-lite.
|
||||||
|
*
|
||||||
|
* Error codes from http://msdn.microsoft.com/en-us/library/aa924526.aspx
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __pcsclite_h__
|
||||||
|
#define __pcsclite_h__
|
||||||
|
|
||||||
|
#include <wintypes.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef LONG SCARDCONTEXT; /**< \p hContext returned by SCardEstablishContext() */
|
||||||
|
typedef SCARDCONTEXT *PSCARDCONTEXT;
|
||||||
|
typedef SCARDCONTEXT *LPSCARDCONTEXT;
|
||||||
|
typedef LONG SCARDHANDLE; /**< \p hCard returned by SCardConnect() */
|
||||||
|
typedef SCARDHANDLE *PSCARDHANDLE;
|
||||||
|
typedef SCARDHANDLE *LPSCARDHANDLE;
|
||||||
|
|
||||||
|
#define MAX_ATR_SIZE 33 /**< Maximum ATR size */
|
||||||
|
|
||||||
|
/* Set structure elements aligment on bytes
|
||||||
|
* http://gcc.gnu.org/onlinedocs/gcc/Structure_002dPacking-Pragmas.html */
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#pragma pack(1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
const char *szReader;
|
||||||
|
void *pvUserData;
|
||||||
|
DWORD dwCurrentState;
|
||||||
|
DWORD dwEventState;
|
||||||
|
DWORD cbAtr;
|
||||||
|
unsigned char rgbAtr[MAX_ATR_SIZE];
|
||||||
|
}
|
||||||
|
SCARD_READERSTATE, *LPSCARD_READERSTATE;
|
||||||
|
|
||||||
|
/** Protocol Control Information (PCI) */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
unsigned long dwProtocol; /**< Protocol identifier */
|
||||||
|
unsigned long cbPciLength; /**< Protocol Control Inf Length */
|
||||||
|
}
|
||||||
|
SCARD_IO_REQUEST, *PSCARD_IO_REQUEST, *LPSCARD_IO_REQUEST;
|
||||||
|
|
||||||
|
typedef const SCARD_IO_REQUEST *LPCSCARD_IO_REQUEST;
|
||||||
|
|
||||||
|
extern const SCARD_IO_REQUEST g_rgSCardT0Pci, g_rgSCardT1Pci, g_rgSCardRawPci;
|
||||||
|
|
||||||
|
/* restore default structure elements alignment */
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#pragma pack()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SCARD_PCI_T0 (&g_rgSCardT0Pci) /**< protocol control information (PCI) for T=0 */
|
||||||
|
#define SCARD_PCI_T1 (&g_rgSCardT1Pci) /**< protocol control information (PCI) for T=1 */
|
||||||
|
#define SCARD_PCI_RAW (&g_rgSCardRawPci) /**< protocol control information (PCI) for RAW protocol */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup ErrorCodes ErrorCodes
|
||||||
|
* @brief Error code documentation
|
||||||
|
*
|
||||||
|
* The error codes descriptions are from
|
||||||
|
* http://msdn.microsoft.com/en-us/library/aa924526.aspx
|
||||||
|
*/
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_S_SUCCESS ((LONG)0x00000000) /**< No error was encountered. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_F_INTERNAL_ERROR ((LONG)0x80100001) /**< An internal consistency check failed. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_CANCELLED ((LONG)0x80100002) /**< The action was cancelled by an SCardCancel request. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_INVALID_HANDLE ((LONG)0x80100003) /**< The supplied handle was invalid. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_INVALID_PARAMETER ((LONG)0x80100004) /**< One or more of the supplied parameters could not be properly interpreted. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_INVALID_TARGET ((LONG)0x80100005) /**< Registry startup information is missing or invalid. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_NO_MEMORY ((LONG)0x80100006) /**< Not enough memory available to complete this command. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_F_WAITED_TOO_LONG ((LONG)0x80100007) /**< An internal consistency timer has expired. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_INSUFFICIENT_BUFFER ((LONG)0x80100008) /**< The data buffer to receive returned data is too small for the returned data. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_UNKNOWN_READER ((LONG)0x80100009) /**< The specified reader name is not recognized. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_TIMEOUT ((LONG)0x8010000A) /**< The user-specified timeout value has expired. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_SHARING_VIOLATION ((LONG)0x8010000B) /**< The smart card cannot be accessed because of other connections outstanding. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_NO_SMARTCARD ((LONG)0x8010000C) /**< The operation requires a Smart Card, but no Smart Card is currently in the device. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_UNKNOWN_CARD ((LONG)0x8010000D) /**< The specified smart card name is not recognized. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_CANT_DISPOSE ((LONG)0x8010000E) /**< The system could not dispose of the media in the requested manner. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_PROTO_MISMATCH ((LONG)0x8010000F) /**< The requested protocols are incompatible with the protocol currently in use with the smart card. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_NOT_READY ((LONG)0x80100010) /**< The reader or smart card is not ready to accept commands. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_INVALID_VALUE ((LONG)0x80100011) /**< One or more of the supplied parameters values could not be properly interpreted. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_SYSTEM_CANCELLED ((LONG)0x80100012) /**< The action was cancelled by the system, presumably to log off or shut down. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_F_COMM_ERROR ((LONG)0x80100013) /**< An internal communications error has been detected. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_F_UNKNOWN_ERROR ((LONG)0x80100014) /**< An internal error has been detected, but the source is unknown. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_INVALID_ATR ((LONG)0x80100015) /**< An ATR obtained from the registry is not a valid ATR string. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_NOT_TRANSACTED ((LONG)0x80100016) /**< An attempt was made to end a non-existent transaction. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_READER_UNAVAILABLE ((LONG)0x80100017) /**< The specified reader is not currently available for use. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_P_SHUTDOWN ((LONG)0x80100018) /**< The operation has been aborted to allow the server application to exit. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_PCI_TOO_SMALL ((LONG)0x80100019) /**< The PCI Receive buffer was too small. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_READER_UNSUPPORTED ((LONG)0x8010001A) /**< The reader driver does not meet minimal requirements for support. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_DUPLICATE_READER ((LONG)0x8010001B) /**< The reader driver did not produce a unique reader name. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_CARD_UNSUPPORTED ((LONG)0x8010001C) /**< The smart card does not meet minimal requirements for support. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_NO_SERVICE ((LONG)0x8010001D) /**< The Smart card resource manager is not running. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_SERVICE_STOPPED ((LONG)0x8010001E) /**< The Smart card resource manager has shut down. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_UNEXPECTED ((LONG)0x8010001F) /**< An unexpected card error has occurred. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_UNSUPPORTED_FEATURE ((LONG)0x8010001F) /**< This smart card does not support the requested feature. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_ICC_INSTALLATION ((LONG)0x80100020) /**< No primary provider can be found for the smart card. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_ICC_CREATEORDER ((LONG)0x80100021) /**< The requested order of object creation is not supported. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
/* #define SCARD_E_UNSUPPORTED_FEATURE ((LONG)0x80100022) / **< This smart card does not support the requested feature. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_DIR_NOT_FOUND ((LONG)0x80100023) /**< The identified directory does not exist in the smart card. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_FILE_NOT_FOUND ((LONG)0x80100024) /**< The identified file does not exist in the smart card. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_NO_DIR ((LONG)0x80100025) /**< The supplied path does not represent a smart card directory. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_NO_FILE ((LONG)0x80100026) /**< The supplied path does not represent a smart card file. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_NO_ACCESS ((LONG)0x80100027) /**< Access is denied to this file. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_WRITE_TOO_MANY ((LONG)0x80100028) /**< The smart card does not have enough memory to store the information. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_BAD_SEEK ((LONG)0x80100029) /**< There was an error trying to set the smart card file object pointer. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_INVALID_CHV ((LONG)0x8010002A) /**< The supplied PIN is incorrect. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_UNKNOWN_RES_MNG ((LONG)0x8010002B) /**< An unrecognized error code was returned from a layered component. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_NO_SUCH_CERTIFICATE ((LONG)0x8010002C) /**< The requested certificate does not exist. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_CERTIFICATE_UNAVAILABLE ((LONG)0x8010002D) /**< The requested certificate could not be obtained. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_NO_READERS_AVAILABLE ((LONG)0x8010002E) /**< Cannot find a smart card reader. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_COMM_DATA_LOST ((LONG)0x8010002F) /**< A communications error with the smart card has been detected. Retry the operation. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_NO_KEY_CONTAINER ((LONG)0x80100030) /**< The requested key container does not exist on the smart card. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_E_SERVER_TOO_BUSY ((LONG)0x80100031) /**< The Smart Card Resource Manager is too busy to complete this operation. */
|
||||||
|
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_W_UNSUPPORTED_CARD ((LONG)0x80100065) /**< The reader cannot communicate with the card, due to ATR string configuration conflicts. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_W_UNRESPONSIVE_CARD ((LONG)0x80100066) /**< The smart card is not responding to a reset. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_W_UNPOWERED_CARD ((LONG)0x80100067) /**< Power has been removed from the smart card, so that further communication is not possible. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_W_RESET_CARD ((LONG)0x80100068) /**< The smart card has been reset, so any shared state information is invalid. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_W_REMOVED_CARD ((LONG)0x80100069) /**< The smart card has been removed, so further communication is not possible. */
|
||||||
|
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_W_SECURITY_VIOLATION ((LONG)0x8010006A) /**< Access was denied because of a security violation. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_W_WRONG_CHV ((LONG)0x8010006B) /**< The card cannot be accessed because the wrong PIN was presented. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_W_CHV_BLOCKED ((LONG)0x8010006C) /**< The card cannot be accessed because the maximum number of PIN entry attempts has been reached. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_W_EOF ((LONG)0x8010006D) /**< The end of the smart card file has been reached. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_W_CANCELLED_BY_USER ((LONG)0x8010006E) /**< The user pressed "Cancel" on a Smart Card Selection Dialog. */
|
||||||
|
/** @ingroup ErrorCodes */
|
||||||
|
#define SCARD_W_CARD_NOT_AUTHENTICATED ((LONG)0x8010006F) /**< No PIN was presented to the smart card. */
|
||||||
|
|
||||||
|
#define SCARD_AUTOALLOCATE (DWORD)(-1) /**< see SCardFreeMemory() */
|
||||||
|
#define SCARD_SCOPE_USER 0x0000 /**< Scope in user space */
|
||||||
|
#define SCARD_SCOPE_TERMINAL 0x0001 /**< Scope in terminal */
|
||||||
|
#define SCARD_SCOPE_SYSTEM 0x0002 /**< Scope in system */
|
||||||
|
#define SCARD_SCOPE_GLOBAL 0x0003 /**< Scope is global */
|
||||||
|
|
||||||
|
#define SCARD_PROTOCOL_UNDEFINED 0x0000 /**< protocol not set */
|
||||||
|
#define SCARD_PROTOCOL_UNSET SCARD_PROTOCOL_UNDEFINED /* backward compat */
|
||||||
|
#define SCARD_PROTOCOL_T0 0x0001 /**< T=0 active protocol. */
|
||||||
|
#define SCARD_PROTOCOL_T1 0x0002 /**< T=1 active protocol. */
|
||||||
|
#define SCARD_PROTOCOL_RAW 0x0004 /**< Raw active protocol. */
|
||||||
|
#define SCARD_PROTOCOL_T15 0x0008 /**< T=15 protocol. */
|
||||||
|
|
||||||
|
#define SCARD_PROTOCOL_ANY (SCARD_PROTOCOL_T0|SCARD_PROTOCOL_T1) /**< IFD determines prot. */
|
||||||
|
|
||||||
|
#define SCARD_SHARE_EXCLUSIVE 0x0001 /**< Exclusive mode only */
|
||||||
|
#define SCARD_SHARE_SHARED 0x0002 /**< Shared mode only */
|
||||||
|
#define SCARD_SHARE_DIRECT 0x0003 /**< Raw mode only */
|
||||||
|
|
||||||
|
#define SCARD_LEAVE_CARD 0x0000 /**< Do nothing on close */
|
||||||
|
#define SCARD_RESET_CARD 0x0001 /**< Reset on close */
|
||||||
|
#define SCARD_UNPOWER_CARD 0x0002 /**< Power down on close */
|
||||||
|
#define SCARD_EJECT_CARD 0x0003 /**< Eject on close */
|
||||||
|
|
||||||
|
#define SCARD_UNKNOWN 0x0001 /**< Unknown state */
|
||||||
|
#define SCARD_ABSENT 0x0002 /**< Card is absent */
|
||||||
|
#define SCARD_PRESENT 0x0004 /**< Card is present */
|
||||||
|
#define SCARD_SWALLOWED 0x0008 /**< Card not powered */
|
||||||
|
#define SCARD_POWERED 0x0010 /**< Card is powered */
|
||||||
|
#define SCARD_NEGOTIABLE 0x0020 /**< Ready for PTS */
|
||||||
|
#define SCARD_SPECIFIC 0x0040 /**< PTS has been set */
|
||||||
|
|
||||||
|
#define SCARD_STATE_UNAWARE 0x0000 /**< App wants status */
|
||||||
|
#define SCARD_STATE_IGNORE 0x0001 /**< Ignore this reader */
|
||||||
|
#define SCARD_STATE_CHANGED 0x0002 /**< State has changed */
|
||||||
|
#define SCARD_STATE_UNKNOWN 0x0004 /**< Reader unknown */
|
||||||
|
#define SCARD_STATE_UNAVAILABLE 0x0008 /**< Status unavailable */
|
||||||
|
#define SCARD_STATE_EMPTY 0x0010 /**< Card removed */
|
||||||
|
#define SCARD_STATE_PRESENT 0x0020 /**< Card inserted */
|
||||||
|
#define SCARD_STATE_ATRMATCH 0x0040 /**< ATR matches card */
|
||||||
|
#define SCARD_STATE_EXCLUSIVE 0x0080 /**< Exclusive Mode */
|
||||||
|
#define SCARD_STATE_INUSE 0x0100 /**< Shared Mode */
|
||||||
|
#define SCARD_STATE_MUTE 0x0200 /**< Unresponsive card */
|
||||||
|
#define SCARD_STATE_UNPOWERED 0x0400 /**< Unpowered card */
|
||||||
|
|
||||||
|
#ifndef INFINITE
|
||||||
|
#define INFINITE 0xFFFFFFFF /**< Infinite timeout */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define PCSCLITE_VERSION_NUMBER "@VERSION@" /**< Current version */
|
||||||
|
/** Maximum readers context (a slot is count as a reader) */
|
||||||
|
#define PCSCLITE_MAX_READERS_CONTEXTS 16
|
||||||
|
|
||||||
|
#define MAX_READERNAME 128
|
||||||
|
|
||||||
|
#ifndef SCARD_ATR_LENGTH
|
||||||
|
#define SCARD_ATR_LENGTH MAX_ATR_SIZE /**< Maximum ATR size */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The message and buffer sizes must be multiples of 16.
|
||||||
|
* The max message size must be at least large enough
|
||||||
|
* to accomodate the transmit_struct
|
||||||
|
*/
|
||||||
|
#define MAX_BUFFER_SIZE 264 /**< Maximum Tx/Rx Buffer for short APDU */
|
||||||
|
#define MAX_BUFFER_SIZE_EXTENDED (4 + 3 + (1<<16) + 3 + 2) /**< enhanced (64K + APDU + Lc + Le + SW) Tx/Rx Buffer */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Gets a stringified error response
|
||||||
|
*/
|
||||||
|
const char *pcsc_stringify_error(const LONG);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,271 @@
|
||||||
|
/*
|
||||||
|
* MUSCLE SmartCard Development ( http://pcsclite.alioth.debian.org/pcsclite.html )
|
||||||
|
*
|
||||||
|
* Copyright (C) 1999-2005
|
||||||
|
* David Corcoran <corcoran@musclecard.com>
|
||||||
|
* Copyright (C) 2005-2009
|
||||||
|
* Ludovic Rousseau <ludovic.rousseau@free.fr>
|
||||||
|
*
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. The name of the author may not be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief This keeps a list of defines shared between the driver and the application
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __reader_h__
|
||||||
|
#define __reader_h__
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tags for requesting card and reader attributes
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define SCARD_ATTR_VALUE(Class, Tag) ((((ULONG)(Class)) << 16) | ((ULONG)(Tag)))
|
||||||
|
|
||||||
|
#define SCARD_CLASS_VENDOR_INFO 1 /**< Vendor information definitions */
|
||||||
|
#define SCARD_CLASS_COMMUNICATIONS 2 /**< Communication definitions */
|
||||||
|
#define SCARD_CLASS_PROTOCOL 3 /**< Protocol definitions */
|
||||||
|
#define SCARD_CLASS_POWER_MGMT 4 /**< Power Management definitions */
|
||||||
|
#define SCARD_CLASS_SECURITY 5 /**< Security Assurance definitions */
|
||||||
|
#define SCARD_CLASS_MECHANICAL 6 /**< Mechanical characteristic definitions */
|
||||||
|
#define SCARD_CLASS_VENDOR_DEFINED 7 /**< Vendor specific definitions */
|
||||||
|
#define SCARD_CLASS_IFD_PROTOCOL 8 /**< Interface Device Protocol options */
|
||||||
|
#define SCARD_CLASS_ICC_STATE 9 /**< ICC State specific definitions */
|
||||||
|
#define SCARD_CLASS_SYSTEM 0x7fff /**< System-specific definitions */
|
||||||
|
|
||||||
|
#define SCARD_ATTR_VENDOR_NAME SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0100) /**< Vendor name. */
|
||||||
|
#define SCARD_ATTR_VENDOR_IFD_TYPE SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0101) /**< Vendor-supplied interface device type (model designation of reader). */
|
||||||
|
#define SCARD_ATTR_VENDOR_IFD_VERSION SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0102) /**< Vendor-supplied interface device version (DWORD in the form 0xMMmmbbbb where MM = major version, mm = minor version, and bbbb = build number). */
|
||||||
|
#define SCARD_ATTR_VENDOR_IFD_SERIAL_NO SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0103) /**< Vendor-supplied interface device serial number. */
|
||||||
|
#define SCARD_ATTR_CHANNEL_ID SCARD_ATTR_VALUE(SCARD_CLASS_COMMUNICATIONS, 0x0110) /**< DWORD encoded as 0xDDDDCCCC, where DDDD = data channel type and CCCC = channel number */
|
||||||
|
#define SCARD_ATTR_ASYNC_PROTOCOL_TYPES SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0120) /**< FIXME */
|
||||||
|
#define SCARD_ATTR_DEFAULT_CLK SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0121) /**< Default clock rate, in kHz. */
|
||||||
|
#define SCARD_ATTR_MAX_CLK SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0122) /**< Maximum clock rate, in kHz. */
|
||||||
|
#define SCARD_ATTR_DEFAULT_DATA_RATE SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0123) /**< Default data rate, in bps. */
|
||||||
|
#define SCARD_ATTR_MAX_DATA_RATE SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0124) /**< Maximum data rate, in bps. */
|
||||||
|
#define SCARD_ATTR_MAX_IFSD SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0125) /**< Maximum bytes for information file size device. */
|
||||||
|
#define SCARD_ATTR_SYNC_PROTOCOL_TYPES SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0126) /**< FIXME */
|
||||||
|
#define SCARD_ATTR_POWER_MGMT_SUPPORT SCARD_ATTR_VALUE(SCARD_CLASS_POWER_MGMT, 0x0131) /**< Zero if device does not support power down while smart card is inserted. Nonzero otherwise. */
|
||||||
|
#define SCARD_ATTR_USER_TO_CARD_AUTH_DEVICE SCARD_ATTR_VALUE(SCARD_CLASS_SECURITY, 0x0140) /**< FIXME */
|
||||||
|
#define SCARD_ATTR_USER_AUTH_INPUT_DEVICE SCARD_ATTR_VALUE(SCARD_CLASS_SECURITY, 0x0142) /**< FIXME */
|
||||||
|
#define SCARD_ATTR_CHARACTERISTICS SCARD_ATTR_VALUE(SCARD_CLASS_MECHANICAL, 0x0150) /**< DWORD indicating which mechanical characteristics are supported. If zero, no special characteristics are supported. Note that multiple bits can be set */
|
||||||
|
|
||||||
|
#define SCARD_ATTR_CURRENT_PROTOCOL_TYPE SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0201) /**< FIXME */
|
||||||
|
#define SCARD_ATTR_CURRENT_CLK SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0202) /**< Current clock rate, in kHz. */
|
||||||
|
#define SCARD_ATTR_CURRENT_F SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0203) /**< Clock conversion factor. */
|
||||||
|
#define SCARD_ATTR_CURRENT_D SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0204) /**< Bit rate conversion factor. */
|
||||||
|
#define SCARD_ATTR_CURRENT_N SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0205) /**< Current guard time. */
|
||||||
|
#define SCARD_ATTR_CURRENT_W SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0206) /**< Current work waiting time. */
|
||||||
|
#define SCARD_ATTR_CURRENT_IFSC SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0207) /**< Current byte size for information field size card. */
|
||||||
|
#define SCARD_ATTR_CURRENT_IFSD SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0208) /**< Current byte size for information field size device. */
|
||||||
|
#define SCARD_ATTR_CURRENT_BWT SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0209) /**< Current block waiting time. */
|
||||||
|
#define SCARD_ATTR_CURRENT_CWT SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x020a) /**< Current character waiting time. */
|
||||||
|
#define SCARD_ATTR_CURRENT_EBC_ENCODING SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x020b) /**< Current error block control encoding. */
|
||||||
|
#define SCARD_ATTR_EXTENDED_BWT SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x020c) /**< FIXME */
|
||||||
|
|
||||||
|
#define SCARD_ATTR_ICC_PRESENCE SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0300) /**< Single byte indicating smart card presence */
|
||||||
|
#define SCARD_ATTR_ICC_INTERFACE_STATUS SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0301) /**< Single byte. Zero if smart card electrical contact is not active; nonzero if contact is active. */
|
||||||
|
#define SCARD_ATTR_CURRENT_IO_STATE SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0302) /**< FIXME */
|
||||||
|
#define SCARD_ATTR_ATR_STRING SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0303) /**< Answer to reset (ATR) string. */
|
||||||
|
#define SCARD_ATTR_ICC_TYPE_PER_ATR SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0304) /**< Single byte indicating smart card type */
|
||||||
|
|
||||||
|
#define SCARD_ATTR_ESC_RESET SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_DEFINED, 0xA000) /**< FIXME */
|
||||||
|
#define SCARD_ATTR_ESC_CANCEL SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_DEFINED, 0xA003) /**< FIXME */
|
||||||
|
#define SCARD_ATTR_ESC_AUTHREQUEST SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_DEFINED, 0xA005) /**< FIXME */
|
||||||
|
#define SCARD_ATTR_MAXINPUT SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_DEFINED, 0xA007) /**< FIXME */
|
||||||
|
|
||||||
|
#define SCARD_ATTR_DEVICE_UNIT SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0001) /**< Instance of this vendor's reader attached to the computer. The first instance will be device unit 0, the next will be unit 1 (if it is the same brand of reader) and so on. Two different brands of readers will both have zero for this value. */
|
||||||
|
#define SCARD_ATTR_DEVICE_IN_USE SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0002) /**< Reserved for future use. */
|
||||||
|
#define SCARD_ATTR_DEVICE_FRIENDLY_NAME_A SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0003)
|
||||||
|
#define SCARD_ATTR_DEVICE_SYSTEM_NAME_A SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0004)
|
||||||
|
#define SCARD_ATTR_DEVICE_FRIENDLY_NAME_W SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0005)
|
||||||
|
#define SCARD_ATTR_DEVICE_SYSTEM_NAME_W SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0006)
|
||||||
|
#define SCARD_ATTR_SUPRESS_T1_IFS_REQUEST SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0007) /**< FIXME */
|
||||||
|
|
||||||
|
#ifdef UNICODE
|
||||||
|
#define SCARD_ATTR_DEVICE_FRIENDLY_NAME SCARD_ATTR_DEVICE_FRIENDLY_NAME_W /**< Reader's display name. */
|
||||||
|
#define SCARD_ATTR_DEVICE_SYSTEM_NAME SCARD_ATTR_DEVICE_SYSTEM_NAME_W /**< Reader's system name. */
|
||||||
|
#else
|
||||||
|
#define SCARD_ATTR_DEVICE_FRIENDLY_NAME SCARD_ATTR_DEVICE_FRIENDLY_NAME_A /**< Reader's display name. */
|
||||||
|
#define SCARD_ATTR_DEVICE_SYSTEM_NAME SCARD_ATTR_DEVICE_SYSTEM_NAME_A /**< Reader's system name. */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide source compatibility on different platforms
|
||||||
|
*/
|
||||||
|
#define SCARD_CTL_CODE(code) (0x42000000 + (code))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PC/SC part 10 v2.02.07 March 2010 reader tags
|
||||||
|
*/
|
||||||
|
#define CM_IOCTL_GET_FEATURE_REQUEST SCARD_CTL_CODE(3400)
|
||||||
|
|
||||||
|
#define FEATURE_VERIFY_PIN_START 0x01
|
||||||
|
#define FEATURE_VERIFY_PIN_FINISH 0x02
|
||||||
|
#define FEATURE_MODIFY_PIN_START 0x03
|
||||||
|
#define FEATURE_MODIFY_PIN_FINISH 0x04
|
||||||
|
#define FEATURE_GET_KEY_PRESSED 0x05
|
||||||
|
#define FEATURE_VERIFY_PIN_DIRECT 0x06 /**< Verify PIN */
|
||||||
|
#define FEATURE_MODIFY_PIN_DIRECT 0x07 /**< Modify PIN */
|
||||||
|
#define FEATURE_MCT_READER_DIRECT 0x08
|
||||||
|
#define FEATURE_MCT_UNIVERSAL 0x09
|
||||||
|
#define FEATURE_IFD_PIN_PROPERTIES 0x0A /**< retrieve properties of the IFD regarding PIN handling */
|
||||||
|
#define FEATURE_ABORT 0x0B
|
||||||
|
#define FEATURE_SET_SPE_MESSAGE 0x0C
|
||||||
|
#define FEATURE_VERIFY_PIN_DIRECT_APP_ID 0x0D
|
||||||
|
#define FEATURE_MODIFY_PIN_DIRECT_APP_ID 0x0E
|
||||||
|
#define FEATURE_WRITE_DISPLAY 0x0F
|
||||||
|
#define FEATURE_GET_KEY 0x10
|
||||||
|
#define FEATURE_IFD_DISPLAY_PROPERTIES 0x11
|
||||||
|
#define FEATURE_GET_TLV_PROPERTIES 0x12
|
||||||
|
#define FEATURE_CCID_ESC_COMMAND 0x13
|
||||||
|
#define FEATURE_EXECUTE_PACE 0x20
|
||||||
|
|
||||||
|
/* structures used (but not defined) in PC/SC Part 10:
|
||||||
|
* "IFDs with Secure Pin Entry Capabilities" */
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
/* Set structure elements aligment on bytes
|
||||||
|
* http://gcc.gnu.org/onlinedocs/gcc/Structure_002dPacking-Pragmas.html */
|
||||||
|
#if defined(__APPLE__) | defined(sun)
|
||||||
|
#pragma pack(1)
|
||||||
|
#else
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** the structure must be 6-bytes long */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint8_t tag;
|
||||||
|
uint8_t length;
|
||||||
|
uint32_t value; /**< This value is always in BIG ENDIAN format as documented in PCSC v2 part 10 ch 2.2 page 2. You can use ntohl() for example */
|
||||||
|
} PCSC_TLV_STRUCTURE;
|
||||||
|
|
||||||
|
/** Since CCID 1.4.1 (revision 5252) the byte order is no more important
|
||||||
|
* These macros are now deprecated and should be removed in the future */
|
||||||
|
#define HOST_TO_CCID_16(x) (x)
|
||||||
|
#define HOST_TO_CCID_32(x) (x)
|
||||||
|
|
||||||
|
/** structure used with \ref FEATURE_VERIFY_PIN_DIRECT */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint8_t bTimerOut; /**< timeout is seconds (00 means use default timeout) */
|
||||||
|
uint8_t bTimerOut2; /**< timeout in seconds after first key stroke */
|
||||||
|
uint8_t bmFormatString; /**< formatting options */
|
||||||
|
uint8_t bmPINBlockString; /**< bits 7-4 bit size of PIN length in APDU,
|
||||||
|
* bits 3-0 PIN block size in bytes after
|
||||||
|
* justification and formatting */
|
||||||
|
uint8_t bmPINLengthFormat; /**< bits 7-5 RFU,
|
||||||
|
* bit 4 set if system units are bytes, clear if
|
||||||
|
* system units are bits,
|
||||||
|
* bits 3-0 PIN length position in system units */
|
||||||
|
uint16_t wPINMaxExtraDigit; /**< 0xXXYY where XX is minimum PIN size in digits,
|
||||||
|
and YY is maximum PIN size in digits */
|
||||||
|
uint8_t bEntryValidationCondition; /**< Conditions under which PIN entry should
|
||||||
|
* be considered complete */
|
||||||
|
uint8_t bNumberMessage; /**< Number of messages to display for PIN verification */
|
||||||
|
uint16_t wLangId; /**< Language for messages */
|
||||||
|
uint8_t bMsgIndex; /**< Message index (should be 00) */
|
||||||
|
uint8_t bTeoPrologue[3]; /**< T=1 block prologue field to use (fill with 00) */
|
||||||
|
uint32_t ulDataLength; /**< length of Data to be sent to the ICC */
|
||||||
|
uint8_t abData
|
||||||
|
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
|
||||||
|
[] /* valid C99 code */
|
||||||
|
#else
|
||||||
|
[0] /* non-standard, but usually working code */
|
||||||
|
#endif
|
||||||
|
; /**< Data to send to the ICC */
|
||||||
|
} PIN_VERIFY_STRUCTURE;
|
||||||
|
|
||||||
|
/** structure used with \ref FEATURE_MODIFY_PIN_DIRECT */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint8_t bTimerOut; /**< timeout is seconds (00 means use default timeout) */
|
||||||
|
uint8_t bTimerOut2; /**< timeout in seconds after first key stroke */
|
||||||
|
uint8_t bmFormatString; /**< formatting options */
|
||||||
|
uint8_t bmPINBlockString; /**< bits 7-4 bit size of PIN length in APDU,
|
||||||
|
* bits 3-0 PIN block size in bytes after
|
||||||
|
* justification and formatting */
|
||||||
|
uint8_t bmPINLengthFormat; /**< bits 7-5 RFU,
|
||||||
|
* bit 4 set if system units are bytes, clear if
|
||||||
|
* system units are bits,
|
||||||
|
* bits 3-0 PIN length position in system units */
|
||||||
|
uint8_t bInsertionOffsetOld; /**< Insertion position offset in bytes for
|
||||||
|
the current PIN */
|
||||||
|
uint8_t bInsertionOffsetNew; /**< Insertion position offset in bytes for
|
||||||
|
the new PIN */
|
||||||
|
uint16_t wPINMaxExtraDigit;
|
||||||
|
/**< 0xXXYY where XX is minimum PIN size in digits,
|
||||||
|
and YY is maximum PIN size in digits */
|
||||||
|
uint8_t bConfirmPIN; /**< Flags governing need for confirmation of new PIN */
|
||||||
|
uint8_t bEntryValidationCondition; /**< Conditions under which PIN entry should
|
||||||
|
* be considered complete */
|
||||||
|
uint8_t bNumberMessage; /**< Number of messages to display for PIN verification*/
|
||||||
|
uint16_t wLangId; /**< Language for messages */
|
||||||
|
uint8_t bMsgIndex1; /**< index of 1st prompting message */
|
||||||
|
uint8_t bMsgIndex2; /**< index of 2d prompting message */
|
||||||
|
uint8_t bMsgIndex3; /**< index of 3d prompting message */
|
||||||
|
uint8_t bTeoPrologue[3]; /**< T=1 block prologue field to use (fill with 00) */
|
||||||
|
uint32_t ulDataLength; /**< length of Data to be sent to the ICC */
|
||||||
|
uint8_t abData
|
||||||
|
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
|
||||||
|
[] /* valid C99 code */
|
||||||
|
#else
|
||||||
|
[0] /* non-standard, but usually working code */
|
||||||
|
#endif
|
||||||
|
; /**< Data to send to the ICC */
|
||||||
|
} PIN_MODIFY_STRUCTURE;
|
||||||
|
|
||||||
|
/** structure used with \ref FEATURE_IFD_PIN_PROPERTIES */
|
||||||
|
typedef struct {
|
||||||
|
uint16_t wLcdLayout; /**< display characteristics */
|
||||||
|
uint8_t bEntryValidationCondition;
|
||||||
|
uint8_t bTimeOut2;
|
||||||
|
} PIN_PROPERTIES_STRUCTURE;
|
||||||
|
|
||||||
|
/* restore default structure elements alignment */
|
||||||
|
#if defined(__APPLE__) | defined(sun)
|
||||||
|
#pragma pack()
|
||||||
|
#else
|
||||||
|
#pragma pack(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* properties returned by FEATURE_GET_TLV_PROPERTIES */
|
||||||
|
#define PCSCv2_PART10_PROPERTY_wLcdLayout 1
|
||||||
|
#define PCSCv2_PART10_PROPERTY_bEntryValidationCondition 2
|
||||||
|
#define PCSCv2_PART10_PROPERTY_bTimeOut2 3
|
||||||
|
#define PCSCv2_PART10_PROPERTY_wLcdMaxCharacters 4
|
||||||
|
#define PCSCv2_PART10_PROPERTY_wLcdMaxLines 5
|
||||||
|
#define PCSCv2_PART10_PROPERTY_bMinPINSize 6
|
||||||
|
#define PCSCv2_PART10_PROPERTY_bMaxPINSize 7
|
||||||
|
#define PCSCv2_PART10_PROPERTY_sFirmwareID 8
|
||||||
|
#define PCSCv2_PART10_PROPERTY_bPPDUSupport 9
|
||||||
|
#define PCSCv2_PART10_PROPERTY_dwMaxAPDUDataSize 10
|
||||||
|
#define PCSCv2_PART10_PROPERTY_wIdVendor 11
|
||||||
|
#define PCSCv2_PART10_PROPERTY_wIdProduct 12
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,123 @@
|
||||||
|
/*
|
||||||
|
* MUSCLE SmartCard Development ( http://pcsclite.alioth.debian.org/pcsclite.html )
|
||||||
|
*
|
||||||
|
* Copyright (C) 1999-2003
|
||||||
|
* David Corcoran <corcoran@musclecard.com>
|
||||||
|
* Copyright (C) 2002-2009
|
||||||
|
* Ludovic Rousseau <ludovic.rousseau@free.fr>
|
||||||
|
*
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. The name of the author may not be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief This handles smart card reader communications.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __winscard_h__
|
||||||
|
#define __winscard_h__
|
||||||
|
|
||||||
|
#include <pcsclite.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef PCSC_API
|
||||||
|
#define PCSC_API
|
||||||
|
#endif
|
||||||
|
|
||||||
|
PCSC_API LONG SCardEstablishContext(DWORD dwScope,
|
||||||
|
/*@null@*/ LPCVOID pvReserved1, /*@null@*/ LPCVOID pvReserved2,
|
||||||
|
/*@out@*/ LPSCARDCONTEXT phContext);
|
||||||
|
|
||||||
|
PCSC_API LONG SCardReleaseContext(SCARDCONTEXT hContext);
|
||||||
|
|
||||||
|
PCSC_API LONG SCardIsValidContext(SCARDCONTEXT hContext);
|
||||||
|
|
||||||
|
PCSC_API LONG SCardConnect(SCARDCONTEXT hContext,
|
||||||
|
LPCSTR szReader,
|
||||||
|
DWORD dwShareMode,
|
||||||
|
DWORD dwPreferredProtocols,
|
||||||
|
/*@out@*/ LPSCARDHANDLE phCard, /*@out@*/ LPDWORD pdwActiveProtocol);
|
||||||
|
|
||||||
|
PCSC_API LONG SCardReconnect(SCARDHANDLE hCard,
|
||||||
|
DWORD dwShareMode,
|
||||||
|
DWORD dwPreferredProtocols,
|
||||||
|
DWORD dwInitialization, /*@out@*/ LPDWORD pdwActiveProtocol);
|
||||||
|
|
||||||
|
PCSC_API LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition);
|
||||||
|
|
||||||
|
PCSC_API LONG SCardBeginTransaction(SCARDHANDLE hCard);
|
||||||
|
|
||||||
|
PCSC_API LONG SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition);
|
||||||
|
|
||||||
|
PCSC_API LONG SCardStatus(SCARDHANDLE hCard,
|
||||||
|
/*@null@*/ /*@out@*/ LPSTR mszReaderName,
|
||||||
|
/*@null@*/ /*@out@*/ LPDWORD pcchReaderLen,
|
||||||
|
/*@null@*/ /*@out@*/ LPDWORD pdwState,
|
||||||
|
/*@null@*/ /*@out@*/ LPDWORD pdwProtocol,
|
||||||
|
/*@null@*/ /*@out@*/ LPBYTE pbAtr,
|
||||||
|
/*@null@*/ /*@out@*/ LPDWORD pcbAtrLen);
|
||||||
|
|
||||||
|
PCSC_API LONG SCardGetStatusChange(SCARDCONTEXT hContext,
|
||||||
|
DWORD dwTimeout,
|
||||||
|
SCARD_READERSTATE *rgReaderStates, DWORD cReaders);
|
||||||
|
|
||||||
|
PCSC_API LONG SCardControl(SCARDHANDLE hCard, DWORD dwControlCode,
|
||||||
|
LPCVOID pbSendBuffer, DWORD cbSendLength,
|
||||||
|
/*@out@*/ LPVOID pbRecvBuffer, DWORD cbRecvLength,
|
||||||
|
LPDWORD lpBytesReturned);
|
||||||
|
|
||||||
|
PCSC_API LONG SCardTransmit(SCARDHANDLE hCard,
|
||||||
|
const SCARD_IO_REQUEST *pioSendPci,
|
||||||
|
LPCBYTE pbSendBuffer, DWORD cbSendLength,
|
||||||
|
/*@out@*/ SCARD_IO_REQUEST *pioRecvPci,
|
||||||
|
/*@out@*/ LPBYTE pbRecvBuffer, LPDWORD pcbRecvLength);
|
||||||
|
|
||||||
|
PCSC_API LONG SCardListReaderGroups(SCARDCONTEXT hContext,
|
||||||
|
/*@out@*/ LPSTR mszGroups, LPDWORD pcchGroups);
|
||||||
|
|
||||||
|
PCSC_API LONG SCardListReaders(SCARDCONTEXT hContext,
|
||||||
|
/*@null@*/ /*@out@*/ LPCSTR mszGroups,
|
||||||
|
/*@null@*/ /*@out@*/ LPSTR mszReaders,
|
||||||
|
/*@out@*/ LPDWORD pcchReaders);
|
||||||
|
|
||||||
|
PCSC_API LONG SCardFreeMemory(SCARDCONTEXT hContext, LPCVOID pvMem);
|
||||||
|
|
||||||
|
PCSC_API LONG SCardCancel(SCARDCONTEXT hContext);
|
||||||
|
|
||||||
|
PCSC_API LONG SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId,
|
||||||
|
/*@out@*/ LPBYTE pbAttr, LPDWORD pcbAttrLen);
|
||||||
|
|
||||||
|
PCSC_API LONG SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId,
|
||||||
|
LPCBYTE pbAttr, DWORD cbAttrLen);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,115 @@
|
||||||
|
/*
|
||||||
|
* MUSCLE SmartCard Development ( http://pcsclite.alioth.debian.org/pcsclite.html )
|
||||||
|
*
|
||||||
|
* Copyright (C) 1999
|
||||||
|
* David Corcoran <corcoran@musclecard.com>
|
||||||
|
* Copyright (C) 2002-2011
|
||||||
|
* Ludovic Rousseau <ludovic.rousseau@free.fr>
|
||||||
|
*
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. The name of the author may not be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief This keeps a list of Windows(R) types.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __wintypes_h__
|
||||||
|
#define __wintypes_h__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#ifndef BYTE
|
||||||
|
typedef uint8_t BYTE;
|
||||||
|
#endif
|
||||||
|
typedef uint8_t UCHAR;
|
||||||
|
typedef UCHAR *PUCHAR;
|
||||||
|
typedef uint16_t USHORT;
|
||||||
|
|
||||||
|
#ifndef __COREFOUNDATION_CFPLUGINCOM__
|
||||||
|
typedef uint32_t ULONG;
|
||||||
|
typedef void *LPVOID;
|
||||||
|
typedef int16_t BOOL;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef ULONG *PULONG;
|
||||||
|
typedef const void *LPCVOID;
|
||||||
|
typedef uint32_t DWORD;
|
||||||
|
typedef DWORD *PDWORD;
|
||||||
|
typedef uint16_t WORD;
|
||||||
|
typedef int32_t LONG;
|
||||||
|
typedef const char *LPCSTR;
|
||||||
|
typedef const BYTE *LPCBYTE;
|
||||||
|
typedef BYTE *LPBYTE;
|
||||||
|
typedef DWORD *LPDWORD;
|
||||||
|
typedef char *LPSTR;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#ifndef BYTE
|
||||||
|
typedef unsigned char BYTE;
|
||||||
|
#endif
|
||||||
|
typedef unsigned char UCHAR;
|
||||||
|
typedef UCHAR *PUCHAR;
|
||||||
|
typedef unsigned short USHORT;
|
||||||
|
|
||||||
|
#ifndef __COREFOUNDATION_CFPLUGINCOM__
|
||||||
|
typedef unsigned long ULONG;
|
||||||
|
typedef void *LPVOID;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef const void *LPCVOID;
|
||||||
|
typedef unsigned long DWORD;
|
||||||
|
typedef DWORD *PDWORD;
|
||||||
|
typedef long LONG;
|
||||||
|
typedef const char *LPCSTR;
|
||||||
|
typedef const BYTE *LPCBYTE;
|
||||||
|
typedef BYTE *LPBYTE;
|
||||||
|
typedef DWORD *LPDWORD;
|
||||||
|
typedef char *LPSTR;
|
||||||
|
|
||||||
|
/* these types were deprecated but still used by old drivers and
|
||||||
|
* applications. So just declare and use them. */
|
||||||
|
typedef LPSTR LPTSTR;
|
||||||
|
typedef LPCSTR LPCTSTR;
|
||||||
|
|
||||||
|
/* types unused by pcsc-lite */
|
||||||
|
typedef short BOOL;
|
||||||
|
typedef unsigned short WORD;
|
||||||
|
typedef ULONG *PULONG;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,231 @@
|
||||||
|
Some internal docs
|
||||||
|
==================
|
||||||
|
|
||||||
|
This file is not complete and may even not be exact. I (Ludovic
|
||||||
|
Rousseau) am not the author of pcsc-lite so I may have missed points.
|
||||||
|
|
||||||
|
The documentation corresponds to post pcsc-lite-1.2.0 compiled for
|
||||||
|
GNU/Linux. Information may be wrong for other pcsc-lite versions.
|
||||||
|
|
||||||
|
|
||||||
|
History:
|
||||||
|
--------
|
||||||
|
v 1.0, Jan 6 2002
|
||||||
|
v 1.1, Jun 2004
|
||||||
|
|
||||||
|
|
||||||
|
compositions:
|
||||||
|
-------------
|
||||||
|
pcscd (daemon)
|
||||||
|
atrhandler.c
|
||||||
|
configfile.l
|
||||||
|
debuglog.c
|
||||||
|
dyn_hpux.c (this file is OS dependant)
|
||||||
|
dyn_macosx.c (this file is OS dependant)
|
||||||
|
dyn_unix.c (this file is OS dependant)
|
||||||
|
eventhandler.c
|
||||||
|
hotplug_generic.c
|
||||||
|
hotplug_libusb.c
|
||||||
|
hotplug_linux.c (this file is OS dependant)
|
||||||
|
hotplug_macosx.c (this file is OS dependant)
|
||||||
|
ifdwrapper.c
|
||||||
|
pcscdaemon.c
|
||||||
|
powermgt_generic.c
|
||||||
|
powermgt_macosx.c (this file is OS dependant)
|
||||||
|
prothandler.c
|
||||||
|
readerfactory.c
|
||||||
|
sys_unix.c (this file is OS dependant)
|
||||||
|
thread_unix.c (this file is OS dependant)
|
||||||
|
tokenparser.l
|
||||||
|
winscard.c
|
||||||
|
winscard_msg.c
|
||||||
|
winscard_msg_srv.c
|
||||||
|
winscard_svc.c
|
||||||
|
|
||||||
|
libpcsclite.la (client library)
|
||||||
|
debug.c
|
||||||
|
dyn_hpux.c
|
||||||
|
dyn_macosx.c
|
||||||
|
dyn_unix.c
|
||||||
|
error.c
|
||||||
|
sys_unix.c
|
||||||
|
thread_unix.c
|
||||||
|
winscard_clnt.c or winscard_scf.c
|
||||||
|
winscard_msg.c
|
||||||
|
|
||||||
|
|
||||||
|
PC/SC Lite Concepts:
|
||||||
|
--------------------
|
||||||
|
These concepts will be available after the next release of pcsc-lite-1.2.0.
|
||||||
|
I (Damien Sauveron) will try to explain the following concepts:
|
||||||
|
|
||||||
|
Maximum applications
|
||||||
|
PCSCLITE_MAX_APPLICATIONS
|
||||||
|
|
||||||
|
Maximum contexts by application
|
||||||
|
PCSCLITE_MAX_APPLICATION_CONTEXTS
|
||||||
|
|
||||||
|
Maximum of applications contexts that PC/SC Ressources Manager can accept
|
||||||
|
PCSCLITE_MAX_APPLICATIONS_CONTEXTS
|
||||||
|
= PCSCLITE_MAX_APPLICATIONS * PCSCLITE_MAX_APPLICATION_CONTEXTS
|
||||||
|
|
||||||
|
Maximum channels on a reader context
|
||||||
|
PCSCLITE_MAX_READER_CONTEXT_CHANNELS
|
||||||
|
|
||||||
|
Maximum channels on an application context
|
||||||
|
PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS
|
||||||
|
|
||||||
|
Maximum readers context (a slot is counted as a reader)
|
||||||
|
PCSCLITE_MAX_READERS_CONTEXTS
|
||||||
|
|
||||||
|
First imagine:
|
||||||
|
- 3 PC/SC daemons started on 3 different hosts (it is possible to
|
||||||
|
connect to PC/SC daemons over the network with SCardEstablishContext
|
||||||
|
even if it is not yet implemented in PC/SC Lite): PC/SC D1, PC/SC D2,
|
||||||
|
PC/SC D3
|
||||||
|
- 4 applications: App A, App B, App C, App D
|
||||||
|
- 2 readers R1 and R2 but where R2 has 2 slots that we call R2S1 and
|
||||||
|
R2S2
|
||||||
|
|
||||||
|
On the following figure the (1), (2), ... (7) are some APPLICATION_CONTEXTS.
|
||||||
|
Also App A has 3 APPLICATION_CONTEXTS. Each of them is created by
|
||||||
|
SCardEstablishContext.
|
||||||
|
|
||||||
|
PC/SC D1 handles 5 APPLICATIONS_CONTEXTS.
|
||||||
|
|
||||||
|
PC/SC D1 also handles 3 READERS_CONTEXTS. These contexts are created for
|
||||||
|
example by the plug of the readers.
|
||||||
|
|
||||||
|
The maximum of applications contexts that PC/SC Ressources Manager can
|
||||||
|
accept is thus PCSCLITE_MAX_APPLICATIONS *
|
||||||
|
PCSCLITE_MAX_APPLICATION_CONTEXTS.
|
||||||
|
|
||||||
|
On each of these contexts on the application side there are some
|
||||||
|
APPLICATION_CONTEXT_CHANNELS. They are created by SCardConnect.
|
||||||
|
|
||||||
|
And on each of these contexts on the reader side there are some
|
||||||
|
READER_CONTEXT_CHANNELS.
|
||||||
|
|
||||||
|
|
||||||
|
PC/SC D2
|
||||||
|
\ (3) (1) -- R1
|
||||||
|
------ -------- /
|
||||||
|
\ / \ /
|
||||||
|
App A PC/SC D1---- R2S1
|
||||||
|
\ / | | | \
|
||||||
|
-------- | | | \
|
||||||
|
(2) | | | -- R2S2
|
||||||
|
PC/SC D3 | | |
|
||||||
|
\ (4) (5) | | |
|
||||||
|
-------App B -----------/ | |
|
||||||
|
(6) | |
|
||||||
|
App C -------------/ |
|
||||||
|
(7) |
|
||||||
|
App D ---------------/
|
||||||
|
|
||||||
|
For simplify, there are 3 differents roles: Application, PC/SC Daemon
|
||||||
|
and IFDhandler/reader.
|
||||||
|
|
||||||
|
Between these role there are some contexts and on the top of them there
|
||||||
|
are the channels.
|
||||||
|
|
||||||
|
|
||||||
|
Daemon global variables:
|
||||||
|
------------------------
|
||||||
|
readerfactory.c
|
||||||
|
static PREADER_CONTEXT sReadersContexts[PCSCLITE_MAX_READERS_CONTEXTS];
|
||||||
|
static DWORD *dwNumReadersContexts = 0;
|
||||||
|
|
||||||
|
dwNumReadersContexts is the number of Readers Contexts
|
||||||
|
sReadersContexts[] contains the Readers Contexts
|
||||||
|
|
||||||
|
|
||||||
|
eventhandler.c
|
||||||
|
static PREADER_STATE readerStates[PCSCLITE_MAX_READERS_CONTEXTS];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
IPC communication between pcscd and libpcsclite?:
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
|
pcscd and lipcsclite communicates through a named socket.
|
||||||
|
With post 1.2.0 pcsc-lite versions the client (libpcsclite) and the
|
||||||
|
server (pcscd) exchange a protocol version. With 1.2.0 and before the
|
||||||
|
protocol is 0:0 (major:minor).
|
||||||
|
|
||||||
|
The SCardControl() API changed from
|
||||||
|
LONG SCardControl(SCARDHANDLE hCard,
|
||||||
|
LPCBYTE pbSendBuffer,
|
||||||
|
DWORD cbSendLength,
|
||||||
|
LPBYTE pbRecvBuffer,
|
||||||
|
LPDWORD pcbRecvLength);
|
||||||
|
to
|
||||||
|
LONG SCardControl(SCARDHANDLE hCard,
|
||||||
|
DWORD dwControlCode, <-- new
|
||||||
|
LPCVOID lpInBuffer,
|
||||||
|
DWORD nInBufferSize,
|
||||||
|
LPVOID lpOutBuffer,
|
||||||
|
DWORD nOutBufferSize,
|
||||||
|
LPDWORD lpBytesReturned); <-- new
|
||||||
|
|
||||||
|
This change was made to map Windows API.
|
||||||
|
|
||||||
|
This change also has an impact on the ifd handler (smart card driver).
|
||||||
|
The IFDHandler v3.0 use for post 1.2.0 version uses the new
|
||||||
|
IFDHControl() API.
|
||||||
|
|
||||||
|
We can have:
|
||||||
|
- libpcsclite0, pcscd (<= 1.2.0) and ifdhandler 1.0 or 2.0
|
||||||
|
=> old SCardControl
|
||||||
|
- libpcsclite0, pcscd (> 1.2.0) and ifdhandler 1.0 or 2.0
|
||||||
|
=> old SCardControl
|
||||||
|
- libpcsclite1, pcscd (> 1.2.0) and ifdhandler 1.0 or 2.0
|
||||||
|
=> old SCardControl
|
||||||
|
- libpcsclite1, pcscd (> 1.2.0) and ifdhandler 3.0
|
||||||
|
=> new SCardControl
|
||||||
|
- libpcsclite1, pcscd (<= 1.2.0)
|
||||||
|
=> does not work
|
||||||
|
|
||||||
|
|
||||||
|
Memory structures
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
pcscd side:
|
||||||
|
|
||||||
|
- pcscd open/creates a shared memory segment (EHInitializeEventStructures()
|
||||||
|
in eventhandler.c)
|
||||||
|
- static PREADER_STATE readerStates[PCSCLITE_MAX_READERS_CONTEXTS]; is
|
||||||
|
an array of pointers on READER_STATE. Each entry readerStates[i]
|
||||||
|
points to a memory shared segment. It contains the state of each
|
||||||
|
readers.
|
||||||
|
|
||||||
|
- reader contexts are also created and maintained
|
||||||
|
- static PREADER_CONTEXT sReadersContexts[PCSCLITE_MAX_READERS_CONTEXTS];
|
||||||
|
is an array of pointers on READER_CONTEXT
|
||||||
|
- the structure is allocated by RFAllocateReaderSpace() in
|
||||||
|
readerfactory.c
|
||||||
|
- each READER_CONTEXT contains a pointer to a READER_STATE for the
|
||||||
|
context
|
||||||
|
|
||||||
|
|
||||||
|
libpcsclite side:
|
||||||
|
|
||||||
|
- the library open the shared memory segment (SCardEstablishContextTH()
|
||||||
|
in winscard_clnt.c)
|
||||||
|
- each entry readerStates[i] gets a reference to the memory segment of
|
||||||
|
the server.
|
||||||
|
|
||||||
|
The memory is READ ONLY on the library side.
|
||||||
|
|
||||||
|
|
||||||
|
Inter-thread communication:
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
- to kill a context
|
||||||
|
|
||||||
|
/* Set the thread to 0 to exit thread */
|
||||||
|
rContext->dwLockId = 0xFFFF;
|
||||||
|
|
||||||
|
--
|
||||||
|
Ludovic Rousseau <ludovic.rouseau@free.fr>
|
||||||
|
|
|
@ -0,0 +1,226 @@
|
||||||
|
/*
|
||||||
|
* MUSCLE SmartCard Development ( http://pcsclite.alioth.debian.org/pcsclite.html )
|
||||||
|
*
|
||||||
|
* Copyright (C) 1999-2002
|
||||||
|
* David Corcoran <corcoran@musclecard.com>
|
||||||
|
* Copyright (C) 2002-2011
|
||||||
|
* Ludovic Rousseau <ludovic.rousseau@free.fr>
|
||||||
|
*
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. The name of the author may not be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* @brief This keeps track of smart card protocols, timing issues
|
||||||
|
* and ATR (Answer-to-Reset) handling.
|
||||||
|
*
|
||||||
|
* @note use ./configure --enable-debugatr to enable debug messages
|
||||||
|
* to be logged.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "misc.h"
|
||||||
|
#include "pcsclite.h"
|
||||||
|
#include "debuglog.h"
|
||||||
|
#include "atrhandler.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Uncomment the following for ATR debugging
|
||||||
|
* or use ./configure --enable-debugatr
|
||||||
|
*/
|
||||||
|
/* #define ATR_DEBUG */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief parse an ATR
|
||||||
|
*
|
||||||
|
* @param[out] availableProtocols available protocols
|
||||||
|
* @param[out] currentProtocol current protocol
|
||||||
|
* @param[in] pucAtr ATR
|
||||||
|
* @param[in] dwLength ATR length
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
short ATRDecodeAtr(int *availableProtocols, int *currentProtocol,
|
||||||
|
PUCHAR pucAtr, DWORD dwLength)
|
||||||
|
{
|
||||||
|
USHORT p;
|
||||||
|
UCHAR Y1i, T; /* MSN/LSN of TDi */
|
||||||
|
int i = 1; /* value of the index in TAi, TBi, etc. */
|
||||||
|
|
||||||
|
#ifdef ATR_DEBUG
|
||||||
|
if (dwLength > 0)
|
||||||
|
LogXxd(PCSC_LOG_DEBUG, "ATR: ", pucAtr, dwLength);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (dwLength < 2)
|
||||||
|
return 0; /** @retval 0 Atr must have TS and T0 */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Zero out the bitmasks
|
||||||
|
*/
|
||||||
|
*availableProtocols = SCARD_PROTOCOL_UNDEFINED;
|
||||||
|
*currentProtocol = SCARD_PROTOCOL_UNDEFINED;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Decode the TS byte
|
||||||
|
*/
|
||||||
|
if ((pucAtr[0] != 0x3F) && (pucAtr[0] != 0x3B))
|
||||||
|
return 0; /** @retval 0 Unable to decode TS byte */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Here comes the platform dependant stuff
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Decode the T0 byte
|
||||||
|
*/
|
||||||
|
Y1i = pucAtr[1] >> 4; /* Get the MSN in Y1 */
|
||||||
|
|
||||||
|
p = 2;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Examine Y1
|
||||||
|
*/
|
||||||
|
do
|
||||||
|
{
|
||||||
|
short TAi, TBi, TCi, TDi; /* Interface characters */
|
||||||
|
|
||||||
|
TAi = (Y1i & 0x01) ? pucAtr[p++] : -1;
|
||||||
|
TBi = (Y1i & 0x02) ? pucAtr[p++] : -1;
|
||||||
|
TCi = (Y1i & 0x04) ? pucAtr[p++] : -1;
|
||||||
|
TDi = (Y1i & 0x08) ? pucAtr[p++] : -1;
|
||||||
|
|
||||||
|
/* We don't use TBi and TCi but we must calculate them because
|
||||||
|
* of the p++ in the formulae */
|
||||||
|
(void)TBi;
|
||||||
|
(void)TCi;
|
||||||
|
|
||||||
|
#ifdef ATR_DEBUG
|
||||||
|
Log9(PCSC_LOG_DEBUG,
|
||||||
|
"TA%d: %02X, TB%d: %02X, TC%d: %02X, TD%d: %02X",
|
||||||
|
i, TAi, i, TBi, i, TCi, i, TDi);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Examine TDi to determine protocol and more
|
||||||
|
*/
|
||||||
|
if (TDi >= 0)
|
||||||
|
{
|
||||||
|
Y1i = TDi >> 4; /* Get the MSN in Y1 */
|
||||||
|
T = TDi & 0x0F; /* Get the LSN in K */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the current protocol TD1 (first TD only)
|
||||||
|
*/
|
||||||
|
if (*currentProtocol == SCARD_PROTOCOL_UNDEFINED)
|
||||||
|
{
|
||||||
|
switch (T)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
*currentProtocol = SCARD_PROTOCOL_T0;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
*currentProtocol = SCARD_PROTOCOL_T1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 0; /** @retval 0 Unable to decode LNS */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ATR_DEBUG
|
||||||
|
Log2(PCSC_LOG_DEBUG, "T=%d Protocol Found", T);
|
||||||
|
#endif
|
||||||
|
if (0 == T)
|
||||||
|
{
|
||||||
|
*availableProtocols |= SCARD_PROTOCOL_T0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (1 == T)
|
||||||
|
{
|
||||||
|
*availableProtocols |= SCARD_PROTOCOL_T1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (15 == T)
|
||||||
|
{
|
||||||
|
*availableProtocols |= SCARD_PROTOCOL_T15;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Do nothing for now since other protocols are not
|
||||||
|
* supported at this time
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Y1i = 0;
|
||||||
|
|
||||||
|
/* test presence of TA2 */
|
||||||
|
if ((2 == i) && (TAi >= 0))
|
||||||
|
{
|
||||||
|
T = TAi & 0x0F;
|
||||||
|
#ifdef ATR_DEBUG
|
||||||
|
Log2(PCSC_LOG_DEBUG, "Specific mode: T=%d", T);
|
||||||
|
#endif
|
||||||
|
switch (T)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
*currentProtocol = *availableProtocols = SCARD_PROTOCOL_T0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
*currentProtocol = *availableProtocols = SCARD_PROTOCOL_T1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 0; /** @retval 0 Unable do decode T protocol */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p > MAX_ATR_SIZE)
|
||||||
|
return 0; /** @retval 0 Maximum attribute size */
|
||||||
|
|
||||||
|
/* next interface characters index */
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
while (Y1i != 0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If TDx is not set then the current must be T0
|
||||||
|
*/
|
||||||
|
if (*currentProtocol == SCARD_PROTOCOL_UNDEFINED)
|
||||||
|
{
|
||||||
|
*currentProtocol = SCARD_PROTOCOL_T0;
|
||||||
|
*availableProtocols |= SCARD_PROTOCOL_T0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ATR_DEBUG
|
||||||
|
Log3(PCSC_LOG_DEBUG, "CurrentProtocol: %d, AvailableProtocols: %d",
|
||||||
|
*currentProtocol, *availableProtocols);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 1; /** @retval 1 Success */
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
* MUSCLE SmartCard Development ( http://pcsclite.alioth.debian.org/pcsclite.html )
|
||||||
|
*
|
||||||
|
* Copyright (C) 1999-2002
|
||||||
|
* David Corcoran <corcoran@musclecard.com>
|
||||||
|
* Copyright (C) 2002-2009
|
||||||
|
* Ludovic Rousseau <ludovic.rousseau@free.fr>
|
||||||
|
*
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. The name of the author may not be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief This keeps track of smart card protocols, timing issues
|
||||||
|
* and Answer to Reset ATR handling.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __atrhandler_h__
|
||||||
|
#define __atrhandler_h__
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Decodes the ATR
|
||||||
|
*/
|
||||||
|
short ATRDecodeAtr(/*@out@*/ int *availableProtocols, int *currentProtocol,
|
||||||
|
PUCHAR pucAtr, DWORD dwLength);
|
||||||
|
|
||||||
|
#endif /* __atrhandler_h__ */
|
|
@ -0,0 +1,160 @@
|
||||||
|
/*
|
||||||
|
* MUSCLE SmartCard Development ( http://pcsclite.alioth.debian.org/pcsclite.html )
|
||||||
|
*
|
||||||
|
* Copyright (C) 2013 Red Hat
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||||
|
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||||
|
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||||
|
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||||
|
* DAMAGE.
|
||||||
|
*
|
||||||
|
* Author: Nikos Mavrogiannopoulos <nmav@redhat.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief polkit authorization of clients
|
||||||
|
*
|
||||||
|
* IsClientAuthorized() checks whether the connecting client is authorized
|
||||||
|
* to access the resources using polkit.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "debuglog.h"
|
||||||
|
#include "auth.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#if defined(HAVE_POLKIT) && defined(SO_PEERCRED)
|
||||||
|
|
||||||
|
#include <polkit/polkit.h>
|
||||||
|
|
||||||
|
/* Returns non zero when the client is authorized */
|
||||||
|
unsigned IsClientAuthorized(int socket, const char* action, const char* reader)
|
||||||
|
{
|
||||||
|
struct ucred cr;
|
||||||
|
socklen_t cr_len;
|
||||||
|
int ret;
|
||||||
|
PolkitSubject *subject;
|
||||||
|
PolkitAuthority *authority;
|
||||||
|
PolkitAuthorizationResult *result;
|
||||||
|
PolkitDetails *details;
|
||||||
|
GError *error = NULL;
|
||||||
|
char action_name[128];
|
||||||
|
|
||||||
|
snprintf(action_name, sizeof(action_name), "org.debian.pcsc-lite.%s", action);
|
||||||
|
|
||||||
|
cr_len = sizeof(cr);
|
||||||
|
ret = getsockopt(socket, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len);
|
||||||
|
if (ret == -1)
|
||||||
|
{
|
||||||
|
int e = errno;
|
||||||
|
Log2(PCSC_LOG_CRITICAL,
|
||||||
|
"Error obtaining client process credentials: %s", strerror(e));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
authority = polkit_authority_get_sync(NULL, NULL);
|
||||||
|
if (authority == NULL)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_CRITICAL, "polkit_authority_get_sync failed");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
subject = polkit_unix_process_new_for_owner(cr.pid, 0, cr.uid);
|
||||||
|
if (subject == NULL)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_CRITICAL, "polkit_unix_process_new_for_owner failed");
|
||||||
|
ret = 0;
|
||||||
|
goto cleanup1;
|
||||||
|
}
|
||||||
|
|
||||||
|
details = polkit_details_new();
|
||||||
|
if (details == NULL)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_CRITICAL, "polkit_details_new failed");
|
||||||
|
ret = 0;
|
||||||
|
goto cleanup0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reader != NULL)
|
||||||
|
polkit_details_insert(details, "reader", reader);
|
||||||
|
|
||||||
|
result = polkit_authority_check_authorization_sync(authority, subject,
|
||||||
|
action_name, details,
|
||||||
|
POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
|
||||||
|
NULL,
|
||||||
|
&error);
|
||||||
|
|
||||||
|
if (result == NULL)
|
||||||
|
{
|
||||||
|
Log2(PCSC_LOG_CRITICAL, "Error in authorization: %s", error->message);
|
||||||
|
g_error_free(error);
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (polkit_authorization_result_get_is_authorized(result))
|
||||||
|
{
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret == 0)
|
||||||
|
{
|
||||||
|
Log4(PCSC_LOG_CRITICAL,
|
||||||
|
"Process %u (user: %u) is NOT authorized for action: %s",
|
||||||
|
(unsigned)cr.pid, (unsigned)cr.uid, action);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_object_unref(subject);
|
||||||
|
cleanup0:
|
||||||
|
g_object_unref(details);
|
||||||
|
cleanup1:
|
||||||
|
g_object_unref(authority);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
unsigned IsClientAuthorized(int socket, const char* action, const char* reader)
|
||||||
|
{
|
||||||
|
(void)socket;
|
||||||
|
(void)action;
|
||||||
|
(void)reader;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* MUSCLE SmartCard Development ( http://pcsclite.alioth.debian.org/pcsclite.html )
|
||||||
|
*
|
||||||
|
* Copyright (C) 2013 Red Hat
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||||
|
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||||
|
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||||
|
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||||
|
* DAMAGE.
|
||||||
|
*
|
||||||
|
* Author: Nikos Mavrogiannopoulos <nmav@redhat.com>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
unsigned IsClientAuthorized(int socket, const char* action, const char* reader);
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* Header file for reading lexical config files.
|
||||||
|
*
|
||||||
|
* MUSCLE SmartCard Development ( http://pcsclite.alioth.debian.org/pcsclite.html )
|
||||||
|
*
|
||||||
|
* Copyright (C) 1999-2002
|
||||||
|
* David Corcoran <corcoran@musclecard.com>
|
||||||
|
* Copyright (C) 2002-2010
|
||||||
|
* Ludovic Rousseau <ludovic.rousseau@free.fr>
|
||||||
|
*
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. The name of the author may not be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __configfile_h__
|
||||||
|
#define __configfile_h__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int DBGetReaderList(const char *readerconf,
|
||||||
|
/*@out@*/ SerialReader **caller_reader_list);
|
||||||
|
|
||||||
|
int DBGetReaderListDir(const char *readerconf_dir,
|
||||||
|
/*@out@*/ SerialReader **caller_reader_list);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __configfile_h__ */
|
|
@ -0,0 +1,396 @@
|
||||||
|
/*
|
||||||
|
* Reads lexical config files and updates database.
|
||||||
|
*
|
||||||
|
* MUSCLE SmartCard Development ( http://pcsclite.alioth.debian.org/pcsclite.html )
|
||||||
|
*
|
||||||
|
* Copyright (C) 1999-2002
|
||||||
|
* David Corcoran <corcoran@musclecard.com>
|
||||||
|
* Copyright (C) 2004
|
||||||
|
* Damien Sauveron <damien.sauveron@labri.fr>
|
||||||
|
* Copyright (C) 2004-2010
|
||||||
|
* Ludovic Rousseau <ludovic.rousseau@free.fr>
|
||||||
|
*
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. The name of the author may not be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
%{
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include "wintypes.h"
|
||||||
|
#include "pcscd.h"
|
||||||
|
#include "readerfactory.h"
|
||||||
|
#include "configfile.h"
|
||||||
|
|
||||||
|
int evaluatetoken(char *pcToken);
|
||||||
|
|
||||||
|
static int iLinenumber;
|
||||||
|
static int iOldLinenumber;
|
||||||
|
static char *pcPrevious;
|
||||||
|
static char *pcCurrent;
|
||||||
|
static char *pcFriendlyname;
|
||||||
|
static char *pcDevicename;
|
||||||
|
static char *pcLibpath;
|
||||||
|
static char *pcChannelid;
|
||||||
|
static int badError;
|
||||||
|
static SerialReader *reader_list;
|
||||||
|
static int reader_list_size;
|
||||||
|
const char *ConfFile;
|
||||||
|
|
||||||
|
void tok_error(char *pcToken_error);
|
||||||
|
|
||||||
|
%}
|
||||||
|
|
||||||
|
%option nounput
|
||||||
|
%option noinput
|
||||||
|
%option noyywrap
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
||||||
|
#.* {}
|
||||||
|
"\n" { iLinenumber++; }
|
||||||
|
(\"[^"\n]*["\n])|(\'[^'\n]*['\n]) { (void)evaluatetoken(yytext); }
|
||||||
|
[ \t] {}
|
||||||
|
([A-Z]|[a-z]|[0-9]|[\\\/\-\.\_\@:])+ { (void)evaluatetoken(yytext); }
|
||||||
|
. { iOldLinenumber = iLinenumber; tok_error(yytext); }
|
||||||
|
%%
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "misc.h"
|
||||||
|
#include "pcsclite.h"
|
||||||
|
#include "pcscd.h"
|
||||||
|
#include "debuglog.h"
|
||||||
|
#include "sys_generic.h"
|
||||||
|
#include "readerfactory.h"
|
||||||
|
|
||||||
|
int evaluatetoken(char *pcToken)
|
||||||
|
{
|
||||||
|
if (pcPrevious == NULL)
|
||||||
|
{ /* This is the key */
|
||||||
|
pcPrevious = strdup(pcToken);
|
||||||
|
iOldLinenumber = iLinenumber;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* first and second tokens are not on the same line */
|
||||||
|
if (iOldLinenumber != iLinenumber)
|
||||||
|
{
|
||||||
|
tok_error(pcPrevious);
|
||||||
|
pcPrevious = strdup(pcToken);
|
||||||
|
iOldLinenumber = iLinenumber;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pcCurrent = pcToken;
|
||||||
|
if (strcmp(pcPrevious, "FRIENDLYNAME") == 0)
|
||||||
|
{
|
||||||
|
if (pcFriendlyname == NULL)
|
||||||
|
{
|
||||||
|
size_t n, p;
|
||||||
|
|
||||||
|
pcFriendlyname = malloc(strlen(pcCurrent) + 1);
|
||||||
|
for (n = 0, p = 0; n < strlen(pcCurrent); n++)
|
||||||
|
{
|
||||||
|
if (pcCurrent[n] != '"')
|
||||||
|
{ /* Strip off the quotes */
|
||||||
|
pcFriendlyname[p++] = pcCurrent[n];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pcFriendlyname[p++] = '\0';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tok_error(pcPrevious);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (strcmp(pcPrevious, "DEVICENAME") == 0)
|
||||||
|
{
|
||||||
|
if (pcDevicename == NULL)
|
||||||
|
{
|
||||||
|
struct stat fStatBuf;
|
||||||
|
|
||||||
|
pcDevicename = strdup(pcCurrent);
|
||||||
|
if ((NULL == strchr(pcDevicename, ':'))
|
||||||
|
&& (stat(pcDevicename, &fStatBuf) != 0))
|
||||||
|
{
|
||||||
|
Log3(PCSC_LOG_CRITICAL, "Error with device %s: %s",
|
||||||
|
pcDevicename, strerror(errno));
|
||||||
|
Log1(PCSC_LOG_CRITICAL, "You should remove the DEVICENAME line if your driver does not use this field");
|
||||||
|
badError = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tok_error(pcPrevious);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (strcmp(pcPrevious, "LIBPATH") == 0)
|
||||||
|
{
|
||||||
|
if (pcLibpath == NULL)
|
||||||
|
{
|
||||||
|
struct stat fStatBuf;
|
||||||
|
|
||||||
|
pcLibpath = strdup(pcCurrent);
|
||||||
|
if (stat(pcLibpath, &fStatBuf) != 0)
|
||||||
|
{
|
||||||
|
Log3(PCSC_LOG_CRITICAL, "Error with library %s: %s",
|
||||||
|
pcLibpath, strerror(errno));
|
||||||
|
badError = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strstr(pcLibpath, ".bundle") != NULL)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_ERROR, "WARNING *************************************");
|
||||||
|
Log2(PCSC_LOG_ERROR, "WARNING: USB drivers SHOULD NOT be declared in reader.conf: %s", pcLibpath);
|
||||||
|
Log1(PCSC_LOG_ERROR, "WARNING *************************************");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tok_error(pcPrevious);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (strcmp(pcPrevious, "CHANNELID") == 0)
|
||||||
|
{
|
||||||
|
if (pcChannelid == NULL)
|
||||||
|
pcChannelid = strdup(pcCurrent);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tok_error(pcPrevious);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tok_error(pcPrevious);
|
||||||
|
free(pcPrevious);
|
||||||
|
pcPrevious = NULL;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(pcPrevious);
|
||||||
|
pcPrevious = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* CHANNELID and DEVICENAME are both optional but not at the same time */
|
||||||
|
if (pcFriendlyname && pcLibpath && badError != 1
|
||||||
|
&& (pcChannelid || pcDevicename))
|
||||||
|
{
|
||||||
|
int channelId;
|
||||||
|
static char* defaultDeviceName = (char *)"";
|
||||||
|
|
||||||
|
Log2(PCSC_LOG_DEBUG, "Add reader: %s", pcFriendlyname);
|
||||||
|
if (0 == reader_list_size)
|
||||||
|
{
|
||||||
|
/* one real reader and one end marker */
|
||||||
|
reader_list_size = 2;
|
||||||
|
reader_list = malloc(reader_list_size * sizeof(SerialReader));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
reader_list_size++;
|
||||||
|
reader_list = realloc(reader_list, reader_list_size *
|
||||||
|
sizeof(SerialReader));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* end marker */
|
||||||
|
reader_list[reader_list_size-1].pcFriendlyname = NULL;
|
||||||
|
|
||||||
|
/* the DEVICENAME parameter is optional */
|
||||||
|
if (NULL == pcDevicename)
|
||||||
|
pcDevicename = defaultDeviceName;
|
||||||
|
|
||||||
|
if (pcChannelid)
|
||||||
|
channelId = strtoul(pcChannelid, NULL, 0);
|
||||||
|
else
|
||||||
|
channelId = 0;
|
||||||
|
reader_list[reader_list_size-2].pcFriendlyname = strdup(pcFriendlyname);
|
||||||
|
reader_list[reader_list_size-2].pcDevicename = strdup(pcDevicename);
|
||||||
|
reader_list[reader_list_size-2].pcLibpath = strdup(pcLibpath),
|
||||||
|
reader_list[reader_list_size-2].channelId = channelId;
|
||||||
|
|
||||||
|
free(pcFriendlyname);
|
||||||
|
pcFriendlyname = NULL;
|
||||||
|
|
||||||
|
if (pcDevicename != defaultDeviceName)
|
||||||
|
free(pcDevicename);
|
||||||
|
pcDevicename = NULL;
|
||||||
|
|
||||||
|
free(pcLibpath);
|
||||||
|
pcLibpath = NULL;
|
||||||
|
|
||||||
|
if (pcChannelid)
|
||||||
|
free(pcChannelid);
|
||||||
|
pcChannelid = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tok_error(char *token_error)
|
||||||
|
{
|
||||||
|
#ifdef NO_LOG
|
||||||
|
(void)token_error;
|
||||||
|
#endif
|
||||||
|
Log4(PCSC_LOG_ERROR, "tok_error: invalid value line %d in %s: %s",
|
||||||
|
iOldLinenumber, ConfFile, token_error);
|
||||||
|
badError = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DBGetReaderListDir(const char *readerconf_dir,
|
||||||
|
SerialReader **caller_reader_list)
|
||||||
|
{
|
||||||
|
DIR *dir;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
/* (re)start with an empty list */
|
||||||
|
reader_list = NULL;
|
||||||
|
reader_list_size = 0;
|
||||||
|
|
||||||
|
dir = opendir(readerconf_dir);
|
||||||
|
if (dir)
|
||||||
|
{
|
||||||
|
/* the configuration file is a directory */
|
||||||
|
struct dirent *direntry;
|
||||||
|
|
||||||
|
Log2(PCSC_LOG_DEBUG, "Parsing conf directory: %s", readerconf_dir);
|
||||||
|
|
||||||
|
/* for each configuration file */
|
||||||
|
while ((direntry = readdir(dir)) != NULL)
|
||||||
|
{
|
||||||
|
char filename[FILENAME_MAX];
|
||||||
|
int r;
|
||||||
|
|
||||||
|
snprintf(filename, sizeof(filename), "%s/%s",
|
||||||
|
readerconf_dir, direntry->d_name);
|
||||||
|
|
||||||
|
/* skip non regular files */
|
||||||
|
#ifdef HAVE_STRUCT_DIRENT_D_TYPE
|
||||||
|
if (direntry->d_type == DT_UNKNOWN)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
struct stat st;
|
||||||
|
|
||||||
|
if (lstat(filename, &st) != 0)
|
||||||
|
{
|
||||||
|
Log2(PCSC_LOG_DEBUG, "Skipping non statable file: %s",
|
||||||
|
direntry->d_name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!S_ISREG(st.st_mode))
|
||||||
|
{
|
||||||
|
Log2(PCSC_LOG_DEBUG, "Skipping non regular file: %s",
|
||||||
|
direntry->d_name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifdef HAVE_STRUCT_DIRENT_D_TYPE
|
||||||
|
else
|
||||||
|
if (direntry->d_type != DT_REG)
|
||||||
|
{
|
||||||
|
Log2(PCSC_LOG_DEBUG, "Skipping non regular file: %s",
|
||||||
|
direntry->d_name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* skip files starting with . like ., .., .svn, etc */
|
||||||
|
if ('.' == direntry->d_name[0])
|
||||||
|
{
|
||||||
|
Log2(PCSC_LOG_DEBUG, "Skipping hidden file: %s",
|
||||||
|
direntry->d_name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* each call to DBGetReaderList() will append to the list */
|
||||||
|
r = DBGetReaderList(filename, caller_reader_list);
|
||||||
|
|
||||||
|
/* set the global return value to the latest error */
|
||||||
|
if (r)
|
||||||
|
ret = r;
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir(dir);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
/* the configuration file is really a file */
|
||||||
|
ret = DBGetReaderList(readerconf_dir, caller_reader_list);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DBGetReaderList(const char *readerconf, SerialReader **caller_reader_list)
|
||||||
|
{
|
||||||
|
FILE *configFile = NULL;
|
||||||
|
|
||||||
|
*caller_reader_list = NULL; /* no list by default */
|
||||||
|
|
||||||
|
/* used by tok_error() */
|
||||||
|
ConfFile = readerconf;
|
||||||
|
|
||||||
|
Log2(PCSC_LOG_DEBUG, "Parsing conf file: %s", ConfFile);
|
||||||
|
|
||||||
|
configFile = fopen(readerconf, "r");
|
||||||
|
|
||||||
|
if (configFile == NULL)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
yyin = configFile;
|
||||||
|
|
||||||
|
/* (re)start with a clean state */
|
||||||
|
iLinenumber = 1;
|
||||||
|
iOldLinenumber = -1;
|
||||||
|
pcFriendlyname = NULL;
|
||||||
|
pcDevicename = NULL;
|
||||||
|
pcLibpath = NULL;
|
||||||
|
pcChannelid = NULL;
|
||||||
|
pcPrevious = NULL;
|
||||||
|
pcCurrent = NULL;
|
||||||
|
badError = 0;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
(void)yylex();
|
||||||
|
}
|
||||||
|
while (!feof(configFile));
|
||||||
|
yylex_destroy();
|
||||||
|
|
||||||
|
(void)fclose(configFile);
|
||||||
|
|
||||||
|
*caller_reader_list = reader_list;
|
||||||
|
|
||||||
|
if (badError == 1)
|
||||||
|
return -1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
} /* End of configfile.c */
|
||||||
|
|
|
@ -0,0 +1,155 @@
|
||||||
|
/*
|
||||||
|
* MUSCLE SmartCard Development ( http://pcsclite.alioth.debian.org/pcsclite.html )
|
||||||
|
*
|
||||||
|
* Copyright (C) 1999-2002
|
||||||
|
* David Corcoran <corcoran@musclecard.com>
|
||||||
|
* Copyright (C) 2002-2011
|
||||||
|
* Ludovic Rousseau <ludovic.rousseau@free.fr>
|
||||||
|
*
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. The name of the author may not be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief This handles debugging for libpcsclite.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "misc.h"
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/* We shall not export the log_msg() sumbol */
|
||||||
|
#undef PCSC_API
|
||||||
|
#include "debuglog.h"
|
||||||
|
|
||||||
|
#define DEBUG_BUF_SIZE 2048
|
||||||
|
|
||||||
|
#ifdef NO_LOG
|
||||||
|
|
||||||
|
void log_msg(const int priority, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
(void)priority;
|
||||||
|
(void)fmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
/** default level is quiet to avoid polluting fd 2 (possibly NOT stderr) */
|
||||||
|
static char LogLevel = PCSC_LOG_CRITICAL+1;
|
||||||
|
|
||||||
|
static signed char LogDoColor = 0; /**< no color by default */
|
||||||
|
|
||||||
|
static void log_init(void)
|
||||||
|
{
|
||||||
|
char *e;
|
||||||
|
|
||||||
|
#ifdef LIBPCSCLITE
|
||||||
|
e = getenv("PCSCLITE_DEBUG");
|
||||||
|
#else
|
||||||
|
e = getenv("MUSCLECARD_DEBUG");
|
||||||
|
#endif
|
||||||
|
if (e)
|
||||||
|
LogLevel = atoi(e);
|
||||||
|
|
||||||
|
/* log to stderr and stderr is a tty? */
|
||||||
|
if (isatty(fileno(stderr)))
|
||||||
|
{
|
||||||
|
char *term;
|
||||||
|
|
||||||
|
term = getenv("TERM");
|
||||||
|
if (term)
|
||||||
|
{
|
||||||
|
const char *terms[] = { "linux", "xterm", "xterm-color", "Eterm", "rxvt", "rxvt-unicode" };
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
/* for each known color terminal */
|
||||||
|
for (i = 0; i < COUNT_OF(terms); i++)
|
||||||
|
{
|
||||||
|
/* we found a supported term? */
|
||||||
|
if (0 == strcmp(terms[i], term))
|
||||||
|
{
|
||||||
|
LogDoColor = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} /* log_init */
|
||||||
|
|
||||||
|
void log_msg(const int priority, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
char DebugBuffer[DEBUG_BUF_SIZE];
|
||||||
|
va_list argptr;
|
||||||
|
static int is_initialized = 0;
|
||||||
|
|
||||||
|
if (!is_initialized)
|
||||||
|
{
|
||||||
|
log_init();
|
||||||
|
is_initialized = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priority < LogLevel) /* log priority lower than threshold? */
|
||||||
|
return;
|
||||||
|
|
||||||
|
va_start(argptr, fmt);
|
||||||
|
(void)vsnprintf(DebugBuffer, DEBUG_BUF_SIZE, fmt, argptr);
|
||||||
|
va_end(argptr);
|
||||||
|
|
||||||
|
{
|
||||||
|
if (LogDoColor)
|
||||||
|
{
|
||||||
|
const char *color_pfx = "", *color_sfx = "\33[0m";
|
||||||
|
|
||||||
|
switch (priority)
|
||||||
|
{
|
||||||
|
case PCSC_LOG_CRITICAL:
|
||||||
|
color_pfx = "\33[01;31m"; /* bright + Red */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PCSC_LOG_ERROR:
|
||||||
|
color_pfx = "\33[35m"; /* Magenta */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PCSC_LOG_INFO:
|
||||||
|
color_pfx = "\33[34m"; /* Blue */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PCSC_LOG_DEBUG:
|
||||||
|
color_pfx = ""; /* normal (black) */
|
||||||
|
color_sfx = "";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fprintf(stderr, "%s%s%s\n", color_pfx, DebugBuffer, color_sfx);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
fprintf(stderr, "%s\n", DebugBuffer);
|
||||||
|
}
|
||||||
|
} /* log_msg */
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,357 @@
|
||||||
|
/*
|
||||||
|
* MUSCLE SmartCard Development ( http://pcsclite.alioth.debian.org/pcsclite.html )
|
||||||
|
*
|
||||||
|
* Copyright (C) 1999-2002
|
||||||
|
* David Corcoran <corcoran@musclecard.com>
|
||||||
|
* Copyright (C) 2002-2011
|
||||||
|
* Ludovic Rousseau <ludovic.rousseau@free.fr>
|
||||||
|
*
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. The name of the author may not be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief This handles debugging for pcscd.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#ifdef HAVE_SYSLOG_H
|
||||||
|
#include <syslog.h>
|
||||||
|
#endif
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include "pcsclite.h"
|
||||||
|
#include "misc.h"
|
||||||
|
#include "debuglog.h"
|
||||||
|
#include "sys_generic.h"
|
||||||
|
|
||||||
|
#ifdef NO_LOG
|
||||||
|
|
||||||
|
void log_msg(const int priority, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
(void)priority;
|
||||||
|
(void)fmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void log_xxd(const int priority, const char *msg, const unsigned char *buffer,
|
||||||
|
const int len)
|
||||||
|
{
|
||||||
|
(void)priority;
|
||||||
|
(void)msg;
|
||||||
|
(void)buffer;
|
||||||
|
(void)len;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DebugLogSetLogType(const int dbgtype)
|
||||||
|
{
|
||||||
|
(void)dbgtype;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DebugLogSetLevel(const int level)
|
||||||
|
{
|
||||||
|
(void)level;
|
||||||
|
}
|
||||||
|
|
||||||
|
INTERNAL void DebugLogSetCategory(const int dbginfo)
|
||||||
|
{
|
||||||
|
(void)dbginfo;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
INTERNAL void DebugLogCategory(const int category, const unsigned char *buffer,
|
||||||
|
const int len)
|
||||||
|
{
|
||||||
|
(void)category;
|
||||||
|
(void)buffer;
|
||||||
|
(void)len;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Max string size dumping a maxmium of 2 lines of 80 characters
|
||||||
|
*/
|
||||||
|
#define DEBUG_BUF_SIZE 2048
|
||||||
|
|
||||||
|
static char LogMsgType = DEBUGLOG_NO_DEBUG;
|
||||||
|
static char LogCategory = DEBUG_CATEGORY_NOTHING;
|
||||||
|
|
||||||
|
/** default level */
|
||||||
|
static char LogLevel = PCSC_LOG_ERROR;
|
||||||
|
|
||||||
|
static signed char LogDoColor = 0; /**< no color by default */
|
||||||
|
|
||||||
|
static void log_line(const int priority, const char *DebugBuffer);
|
||||||
|
|
||||||
|
void log_msg(const int priority, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
char DebugBuffer[DEBUG_BUF_SIZE];
|
||||||
|
va_list argptr;
|
||||||
|
|
||||||
|
if ((priority < LogLevel) /* log priority lower than threshold? */
|
||||||
|
|| (DEBUGLOG_NO_DEBUG == LogMsgType))
|
||||||
|
return;
|
||||||
|
|
||||||
|
va_start(argptr, fmt);
|
||||||
|
vsnprintf(DebugBuffer, sizeof DebugBuffer, fmt, argptr);
|
||||||
|
va_end(argptr);
|
||||||
|
|
||||||
|
log_line(priority, DebugBuffer);
|
||||||
|
} /* log_msg */
|
||||||
|
|
||||||
|
static void log_line(const int priority, const char *DebugBuffer)
|
||||||
|
{
|
||||||
|
if (DEBUGLOG_SYSLOG_DEBUG == LogMsgType)
|
||||||
|
syslog(LOG_INFO, "%s", DebugBuffer);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
static struct timeval last_time = { 0, 0 };
|
||||||
|
struct timeval new_time = { 0, 0 };
|
||||||
|
struct timeval tmp;
|
||||||
|
int delta;
|
||||||
|
|
||||||
|
gettimeofday(&new_time, NULL);
|
||||||
|
if (0 == last_time.tv_sec)
|
||||||
|
last_time = new_time;
|
||||||
|
|
||||||
|
tmp.tv_sec = new_time.tv_sec - last_time.tv_sec;
|
||||||
|
tmp.tv_usec = new_time.tv_usec - last_time.tv_usec;
|
||||||
|
if (tmp.tv_usec < 0)
|
||||||
|
{
|
||||||
|
tmp.tv_sec--;
|
||||||
|
tmp.tv_usec += 1000000;
|
||||||
|
}
|
||||||
|
if (tmp.tv_sec < 100)
|
||||||
|
delta = tmp.tv_sec * 1000000 + tmp.tv_usec;
|
||||||
|
else
|
||||||
|
delta = 99999999;
|
||||||
|
|
||||||
|
last_time = new_time;
|
||||||
|
|
||||||
|
if (LogDoColor)
|
||||||
|
{
|
||||||
|
const char *color_pfx = "", *color_sfx = "\33[0m";
|
||||||
|
const char *time_pfx = "\33[36m", *time_sfx = color_sfx;
|
||||||
|
|
||||||
|
switch (priority)
|
||||||
|
{
|
||||||
|
case PCSC_LOG_CRITICAL:
|
||||||
|
color_pfx = "\33[01;31m"; /* bright + Red */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PCSC_LOG_ERROR:
|
||||||
|
color_pfx = "\33[35m"; /* Magenta */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PCSC_LOG_INFO:
|
||||||
|
color_pfx = "\33[34m"; /* Blue */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PCSC_LOG_DEBUG:
|
||||||
|
color_pfx = ""; /* normal (black) */
|
||||||
|
color_sfx = "";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%s%.8d%s %s%s%s\n", time_pfx, delta, time_sfx,
|
||||||
|
color_pfx, DebugBuffer, color_sfx);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("%.8d %s\n", delta, DebugBuffer);
|
||||||
|
}
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
} /* log_line */
|
||||||
|
|
||||||
|
static void log_xxd_always(const int priority, const char *msg,
|
||||||
|
const unsigned char *buffer, const int len)
|
||||||
|
{
|
||||||
|
char DebugBuffer[len*3 + strlen(msg) +1];
|
||||||
|
int i;
|
||||||
|
char *c;
|
||||||
|
|
||||||
|
/* DebugBuffer is always big enough for msg */
|
||||||
|
strcpy(DebugBuffer, msg);
|
||||||
|
c = DebugBuffer + strlen(DebugBuffer);
|
||||||
|
|
||||||
|
for (i = 0; (i < len); ++i)
|
||||||
|
{
|
||||||
|
/* 2 hex characters, 1 space, 1 NUL : total 4 characters */
|
||||||
|
snprintf(c, 4, "%02X ", buffer[i]);
|
||||||
|
c += 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_line(priority, DebugBuffer);
|
||||||
|
} /* log_xxd_always */
|
||||||
|
|
||||||
|
void log_xxd(const int priority, const char *msg, const unsigned char *buffer,
|
||||||
|
const int len)
|
||||||
|
{
|
||||||
|
if ((priority < LogLevel) /* log priority lower than threshold? */
|
||||||
|
|| (DEBUGLOG_NO_DEBUG == LogMsgType))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* len is an error value? */
|
||||||
|
if (len < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
log_xxd_always(priority, msg, buffer, len);
|
||||||
|
} /* log_xxd */
|
||||||
|
|
||||||
|
void DebugLogSetLogType(const int dbgtype)
|
||||||
|
{
|
||||||
|
switch (dbgtype)
|
||||||
|
{
|
||||||
|
case DEBUGLOG_NO_DEBUG:
|
||||||
|
case DEBUGLOG_SYSLOG_DEBUG:
|
||||||
|
case DEBUGLOG_STDOUT_DEBUG:
|
||||||
|
case DEBUGLOG_STDOUT_COLOR_DEBUG:
|
||||||
|
LogMsgType = dbgtype;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Log2(PCSC_LOG_CRITICAL, "unknown log type (%d), using stdout",
|
||||||
|
dbgtype);
|
||||||
|
LogMsgType = DEBUGLOG_STDOUT_DEBUG;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* log to stdout and stdout is a tty? */
|
||||||
|
if ((DEBUGLOG_STDOUT_DEBUG == LogMsgType && isatty(fileno(stdout)))
|
||||||
|
|| (DEBUGLOG_STDOUT_COLOR_DEBUG == LogMsgType))
|
||||||
|
{
|
||||||
|
char *term;
|
||||||
|
|
||||||
|
term = getenv("TERM");
|
||||||
|
if (term)
|
||||||
|
{
|
||||||
|
const char *terms[] = { "linux", "xterm", "xterm-color", "Eterm", "rxvt", "rxvt-unicode", "xterm-256color" };
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
/* for each known color terminal */
|
||||||
|
for (i = 0; i < COUNT_OF(terms); i++)
|
||||||
|
{
|
||||||
|
/* we found a supported term? */
|
||||||
|
if (0 == strcmp(terms[i], term))
|
||||||
|
{
|
||||||
|
LogDoColor = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DebugLogSetLevel(const int level)
|
||||||
|
{
|
||||||
|
LogLevel = level;
|
||||||
|
switch (level)
|
||||||
|
{
|
||||||
|
case PCSC_LOG_CRITICAL:
|
||||||
|
case PCSC_LOG_ERROR:
|
||||||
|
/* do not log anything */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PCSC_LOG_INFO:
|
||||||
|
Log1(PCSC_LOG_INFO, "debug level=info");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PCSC_LOG_DEBUG:
|
||||||
|
Log1(PCSC_LOG_DEBUG, "debug level=debug");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
LogLevel = PCSC_LOG_INFO;
|
||||||
|
Log2(PCSC_LOG_CRITICAL, "unknown level (%d), using level=info",
|
||||||
|
level);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
INTERNAL void DebugLogSetCategory(const int dbginfo)
|
||||||
|
{
|
||||||
|
/* use a negative number to UNset
|
||||||
|
* typically use ~DEBUG_CATEGORY_APDU
|
||||||
|
*/
|
||||||
|
if (dbginfo < 0)
|
||||||
|
LogCategory &= dbginfo;
|
||||||
|
else
|
||||||
|
LogCategory |= dbginfo;
|
||||||
|
|
||||||
|
if (LogCategory & DEBUG_CATEGORY_APDU)
|
||||||
|
Log1(PCSC_LOG_INFO, "Debug options: APDU");
|
||||||
|
}
|
||||||
|
|
||||||
|
INTERNAL void DebugLogCategory(const int category, const unsigned char *buffer,
|
||||||
|
const int len)
|
||||||
|
{
|
||||||
|
if ((category & DEBUG_CATEGORY_APDU)
|
||||||
|
&& (LogCategory & DEBUG_CATEGORY_APDU))
|
||||||
|
log_xxd_always(PCSC_LOG_INFO, "APDU: ", buffer, len);
|
||||||
|
|
||||||
|
if ((category & DEBUG_CATEGORY_SW)
|
||||||
|
&& (LogCategory & DEBUG_CATEGORY_APDU))
|
||||||
|
log_xxd_always(PCSC_LOG_INFO, "SW: ", buffer, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* old function supported for backward object code compatibility
|
||||||
|
* defined only for pcscd
|
||||||
|
*/
|
||||||
|
#ifdef PCSCD
|
||||||
|
void debug_msg(const char *fmt, ...);
|
||||||
|
void debug_msg(const char *fmt, ...)
|
||||||
|
{
|
||||||
|
char DebugBuffer[DEBUG_BUF_SIZE];
|
||||||
|
va_list argptr;
|
||||||
|
|
||||||
|
if (DEBUGLOG_NO_DEBUG == LogMsgType)
|
||||||
|
return;
|
||||||
|
|
||||||
|
va_start(argptr, fmt);
|
||||||
|
vsnprintf(DebugBuffer, sizeof DebugBuffer, fmt, argptr);
|
||||||
|
va_end(argptr);
|
||||||
|
|
||||||
|
if (DEBUGLOG_SYSLOG_DEBUG == LogMsgType)
|
||||||
|
syslog(LOG_INFO, "%s", DebugBuffer);
|
||||||
|
else
|
||||||
|
puts(DebugBuffer);
|
||||||
|
} /* debug_msg */
|
||||||
|
|
||||||
|
void debug_xxd(const char *msg, const unsigned char *buffer, const int len);
|
||||||
|
void debug_xxd(const char *msg, const unsigned char *buffer, const int len)
|
||||||
|
{
|
||||||
|
log_xxd(PCSC_LOG_ERROR, msg, buffer, len);
|
||||||
|
} /* debug_xxd */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* NO_LOG */
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* MUSCLE SmartCard Development ( http://pcsclite.alioth.debian.org/pcsclite.html )
|
||||||
|
*
|
||||||
|
* Copyright (C) 1999
|
||||||
|
* David Corcoran <corcoran@musclecard.com>
|
||||||
|
* Copyright (C) 2002-2009
|
||||||
|
* Ludovic Rousseau <ludovic.rousseau@free.fr>
|
||||||
|
*
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. The name of the author may not be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief This abstracts dynamic library loading functions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __dyn_generic_h__
|
||||||
|
#define __dyn_generic_h__
|
||||||
|
|
||||||
|
LONG DYN_LoadLibrary(void **, char *);
|
||||||
|
LONG DYN_CloseLibrary(void **);
|
||||||
|
LONG DYN_GetAddress(void *, /*@out@*/ void **, const char *, int);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,108 @@
|
||||||
|
/*
|
||||||
|
* MUSCLE SmartCard Development ( http://pcsclite.alioth.debian.org/pcsclite.html )
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001
|
||||||
|
* David Corcoran <corcoran@musclecard.com>
|
||||||
|
* Copyright (C) 2002-2010
|
||||||
|
* Ludovic Rousseau <ludovic.rousseau@free.fr>
|
||||||
|
*
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. The name of the author may not be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @file
|
||||||
|
* @brief This abstracts dynamic library loading functions and timing.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include <string.h>
|
||||||
|
#ifdef HAVE_DL_H
|
||||||
|
#include <dl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "pcsclite.h"
|
||||||
|
#include "debuglog.h"
|
||||||
|
#include "dyn_generic.h"
|
||||||
|
|
||||||
|
LONG DYN_LoadLibrary(void **pvLHandle, char *pcLibrary)
|
||||||
|
{
|
||||||
|
|
||||||
|
shl_t myHandle;
|
||||||
|
|
||||||
|
*pvLHandle = 0;
|
||||||
|
myHandle =
|
||||||
|
shl_load(pcLibrary, BIND_IMMEDIATE | BIND_VERBOSE | BIND_NOSTART,
|
||||||
|
0L);
|
||||||
|
|
||||||
|
if (myHandle == 0)
|
||||||
|
{
|
||||||
|
Log3(PCSC_LOG_ERROR, "%s: %s", pcLibrary, strerror(errno));
|
||||||
|
return SCARD_F_UNKNOWN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
*pvLHandle = (void *) myHandle;
|
||||||
|
return SCARD_S_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
LONG DYN_CloseLibrary(void **pvLHandle)
|
||||||
|
{
|
||||||
|
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
rv = shl_unload((shl_t) * pvLHandle);
|
||||||
|
*pvLHandle = 0;
|
||||||
|
|
||||||
|
if (rv == -1)
|
||||||
|
{
|
||||||
|
Log2(PCSC_LOG_ERROR, "%s", strerror(errno));
|
||||||
|
return SCARD_F_UNKNOWN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SCARD_S_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
LONG DYN_GetAddress(void *pvLHandle, void **pvFHandle, const char *pcFunction,
|
||||||
|
int mayfail)
|
||||||
|
{
|
||||||
|
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
*pvFHandle = 0;
|
||||||
|
rv = shl_findsym((shl_t *) & pvLHandle, pcFunction, TYPE_PROCEDURE,
|
||||||
|
pvFHandle);
|
||||||
|
|
||||||
|
if (rv == -1)
|
||||||
|
{
|
||||||
|
Log3(mayfail ? PCSC_LOG_INFO : PCSC_LOG_ERROR, "%s: %s",
|
||||||
|
pcFunction, strerror(errno));
|
||||||
|
rv = SCARD_F_UNKNOWN_ERROR;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
rv = SCARD_S_SUCCESS;
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* HAVE_DL_H */
|
||||||
|
|
|
@ -0,0 +1,133 @@
|
||||||
|
/*
|
||||||
|
* MUSCLE SmartCard Development ( http://pcsclite.alioth.debian.org/pcsclite.html )
|
||||||
|
*
|
||||||
|
* Copyright (C) 2000
|
||||||
|
* David Corcoran <corcoran@musclecard.com>
|
||||||
|
* Copyright (C) 2002-2010
|
||||||
|
* Ludovic Rousseau <ludovic.rousseau@free.fr>
|
||||||
|
*
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. The name of the author may not be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief This abstracts dynamic library loading functions and timing.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "misc.h"
|
||||||
|
#include "pcsclite.h"
|
||||||
|
#include "debuglog.h"
|
||||||
|
#include "dyn_generic.h"
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#include <CoreFoundation/CFBundle.h>
|
||||||
|
#include <CoreFoundation/CFString.h>
|
||||||
|
#include <CoreFoundation/CFURL.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* / Load a module (if needed)
|
||||||
|
*/
|
||||||
|
int DYN_LoadLibrary(void **pvLHandle, char *pcLibrary)
|
||||||
|
{
|
||||||
|
|
||||||
|
CFStringRef bundlePath;
|
||||||
|
CFURLRef bundleURL;
|
||||||
|
CFBundleRef bundle;
|
||||||
|
|
||||||
|
*pvLHandle = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @@@ kCFStringEncodingMacRoman might be wrong on non US systems.
|
||||||
|
*/
|
||||||
|
|
||||||
|
bundlePath = CFStringCreateWithCString(NULL, pcLibrary,
|
||||||
|
kCFStringEncodingMacRoman);
|
||||||
|
if (bundlePath == NULL)
|
||||||
|
return SCARD_E_NO_MEMORY;
|
||||||
|
|
||||||
|
bundleURL = CFURLCreateWithFileSystemPath(NULL, bundlePath,
|
||||||
|
kCFURLPOSIXPathStyle, TRUE);
|
||||||
|
CFRelease(bundlePath);
|
||||||
|
if (bundleURL == NULL)
|
||||||
|
return SCARD_E_NO_MEMORY;
|
||||||
|
|
||||||
|
bundle = CFBundleCreate(NULL, bundleURL);
|
||||||
|
CFRelease(bundleURL);
|
||||||
|
if (bundle == NULL)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_ERROR, "CFBundleCreate");
|
||||||
|
return SCARD_F_UNKNOWN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CFBundleLoadExecutable(bundle))
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_ERROR, "CFBundleLoadExecutable");
|
||||||
|
CFRelease(bundle);
|
||||||
|
return SCARD_F_UNKNOWN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
*pvLHandle = (void *) bundle;
|
||||||
|
|
||||||
|
return SCARD_S_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DYN_CloseLibrary(void **pvLHandle)
|
||||||
|
{
|
||||||
|
|
||||||
|
CFBundleRef bundle = (CFBundleRef) * pvLHandle;
|
||||||
|
|
||||||
|
if (CFBundleIsExecutableLoaded(bundle) == TRUE)
|
||||||
|
{
|
||||||
|
CFBundleUnloadExecutable(bundle);
|
||||||
|
CFRelease(bundle);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Log1(PCSC_LOG_ERROR, "Cannot unload library.");
|
||||||
|
|
||||||
|
*pvLHandle = 0;
|
||||||
|
return SCARD_S_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DYN_GetAddress(void *pvLHandle, void **pvFHandle, const char *pcFunction,
|
||||||
|
int mayfail)
|
||||||
|
{
|
||||||
|
(void)mayfail;
|
||||||
|
|
||||||
|
CFBundleRef bundle = (CFBundleRef) pvLHandle;
|
||||||
|
CFStringRef cfName = CFStringCreateWithCString(NULL, pcFunction,
|
||||||
|
kCFStringEncodingMacRoman);
|
||||||
|
if (cfName == NULL)
|
||||||
|
return SCARD_E_NO_MEMORY;
|
||||||
|
|
||||||
|
*pvFHandle = CFBundleGetFunctionPointerForName(bundle, cfName);
|
||||||
|
CFRelease(cfName);
|
||||||
|
if (*pvFHandle == NULL)
|
||||||
|
return SCARD_F_UNKNOWN_ERROR;
|
||||||
|
|
||||||
|
return SCARD_S_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __APPLE__ */
|
|
@ -0,0 +1,115 @@
|
||||||
|
/*
|
||||||
|
* MUSCLE SmartCard Development ( http://pcsclite.alioth.debian.org/pcsclite.html )
|
||||||
|
*
|
||||||
|
* Copyright (C) 1999-2002
|
||||||
|
* David Corcoran <corcoran@musclecard.com>
|
||||||
|
* Copyright (C) 2002-2010
|
||||||
|
* Ludovic Rousseau <ludovic.rousseau@free.fr>
|
||||||
|
*
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. The name of the author may not be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief This abstracts dynamic library loading functions and timing.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#if defined(HAVE_DLFCN_H) && !defined(HAVE_DL_H) && !defined(__APPLE__)
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "misc.h"
|
||||||
|
#include "pcsclite.h"
|
||||||
|
#include "debuglog.h"
|
||||||
|
#include "dyn_generic.h"
|
||||||
|
|
||||||
|
INTERNAL LONG DYN_LoadLibrary(void **pvLHandle, char *pcLibrary)
|
||||||
|
{
|
||||||
|
*pvLHandle = NULL;
|
||||||
|
#ifndef PCSCLITE_STATIC_DRIVER
|
||||||
|
*pvLHandle = dlopen(pcLibrary, RTLD_LAZY);
|
||||||
|
|
||||||
|
if (*pvLHandle == NULL)
|
||||||
|
{
|
||||||
|
Log3(PCSC_LOG_CRITICAL, "%s: %s", pcLibrary, dlerror());
|
||||||
|
return SCARD_F_UNKNOWN_ERROR;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return SCARD_S_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
INTERNAL LONG DYN_CloseLibrary(void **pvLHandle)
|
||||||
|
{
|
||||||
|
#ifndef PCSCLITE_STATIC_DRIVER
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = dlclose(*pvLHandle);
|
||||||
|
*pvLHandle = NULL;
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
Log2(PCSC_LOG_CRITICAL, "%s", dlerror());
|
||||||
|
return SCARD_F_UNKNOWN_ERROR;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return SCARD_S_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
INTERNAL LONG DYN_GetAddress(void *pvLHandle, void **pvFHandle,
|
||||||
|
const char *pcFunction, int mayfail)
|
||||||
|
{
|
||||||
|
char pcFunctionName[256];
|
||||||
|
LONG rv = SCARD_S_SUCCESS;
|
||||||
|
|
||||||
|
/* Some platforms might need a leading underscore for the symbol */
|
||||||
|
(void)snprintf(pcFunctionName, sizeof(pcFunctionName), "_%s", pcFunction);
|
||||||
|
|
||||||
|
*pvFHandle = NULL;
|
||||||
|
#ifndef PCSCLITE_STATIC_DRIVER
|
||||||
|
*pvFHandle = dlsym(pvLHandle, pcFunctionName);
|
||||||
|
|
||||||
|
/* Failed? Try again without the leading underscore */
|
||||||
|
if (*pvFHandle == NULL)
|
||||||
|
*pvFHandle = dlsym(pvLHandle, pcFunction);
|
||||||
|
|
||||||
|
if (*pvFHandle == NULL)
|
||||||
|
{
|
||||||
|
#ifdef NO_LOG
|
||||||
|
(void)mayfail;
|
||||||
|
#endif
|
||||||
|
Log3(mayfail ? PCSC_LOG_INFO : PCSC_LOG_CRITICAL, "%s: %s",
|
||||||
|
pcFunction, dlerror());
|
||||||
|
rv = SCARD_F_UNKNOWN_ERROR;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* HAVE_DLFCN_H && !HAVE_DL_H && !__APPLE__ */
|
|
@ -0,0 +1,243 @@
|
||||||
|
/*
|
||||||
|
* MUSCLE SmartCard Development ( http://pcsclite.alioth.debian.org/pcsclite.html )
|
||||||
|
*
|
||||||
|
* Copyright (C) 1999-2002
|
||||||
|
* David Corcoran <corcoran@musclecard.com>
|
||||||
|
* Copyright (C) 2006-2009
|
||||||
|
* Ludovic Rousseau <ludovic.rousseau@free.fr>
|
||||||
|
*
|
||||||
|
* This file is dual licenced:
|
||||||
|
* - BSD-like, see the COPYING file
|
||||||
|
* - GNU Lesser General Licence 2.1 or (at your option) any later version.
|
||||||
|
*
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. The name of the author may not be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief This handles pcsc_stringify_error()
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "misc.h"
|
||||||
|
#include "pcsclite.h"
|
||||||
|
#include "string.h"
|
||||||
|
|
||||||
|
#ifdef NO_LOG
|
||||||
|
PCSC_API const char* pcsc_stringify_error(const LONG pcscError)
|
||||||
|
{
|
||||||
|
static char strError[] = "0x12345678";
|
||||||
|
|
||||||
|
snprintf(strError, sizeof(strError), "0x%08lX", pcscError);
|
||||||
|
|
||||||
|
return strError;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/**
|
||||||
|
* @brief Returns a human readable text for the given PC/SC error code.
|
||||||
|
*
|
||||||
|
* @warning
|
||||||
|
* The returned string uses a Thread-Local Storage (TLS) buffer and is valid:
|
||||||
|
* -# only while the thread on which it was obtained is alive.
|
||||||
|
* -# until the next call to this function on the same thread.
|
||||||
|
*
|
||||||
|
* @ingroup API
|
||||||
|
* @param[in] pcscError Error code to be translated to text.
|
||||||
|
*
|
||||||
|
* @return Text representing the error code passed.
|
||||||
|
*
|
||||||
|
* @code
|
||||||
|
* SCARDCONTEXT hContext;
|
||||||
|
* LONG rv;
|
||||||
|
* rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
|
||||||
|
* if (rv != SCARD_S_SUCCESS)
|
||||||
|
* printf("SCardEstablishContext: %s (0x%lX)\n",
|
||||||
|
* pcsc_stringify_error(rv), rv);
|
||||||
|
* @endcode
|
||||||
|
*/
|
||||||
|
PCSC_API const char* pcsc_stringify_error(const LONG pcscError)
|
||||||
|
{
|
||||||
|
/* Use a Thread-local storage so that the returned buffer
|
||||||
|
* is thread safe */
|
||||||
|
static __thread char strError[75];
|
||||||
|
const char *msg = NULL;
|
||||||
|
|
||||||
|
switch (pcscError)
|
||||||
|
{
|
||||||
|
case SCARD_S_SUCCESS:
|
||||||
|
msg = "Command successful.";
|
||||||
|
break;
|
||||||
|
case SCARD_F_INTERNAL_ERROR:
|
||||||
|
msg = "Internal error.";
|
||||||
|
break;
|
||||||
|
case SCARD_E_CANCELLED:
|
||||||
|
msg = "Command cancelled.";
|
||||||
|
break;
|
||||||
|
case SCARD_E_INVALID_HANDLE:
|
||||||
|
msg = "Invalid handle.";
|
||||||
|
break;
|
||||||
|
case SCARD_E_INVALID_PARAMETER:
|
||||||
|
msg = "Invalid parameter given.";
|
||||||
|
break;
|
||||||
|
case SCARD_E_INVALID_TARGET:
|
||||||
|
msg = "Invalid target given.";
|
||||||
|
break;
|
||||||
|
case SCARD_E_NO_MEMORY:
|
||||||
|
msg = "Not enough memory.";
|
||||||
|
break;
|
||||||
|
case SCARD_F_WAITED_TOO_LONG:
|
||||||
|
msg = "Waited too long.";
|
||||||
|
break;
|
||||||
|
case SCARD_E_INSUFFICIENT_BUFFER:
|
||||||
|
msg = "Insufficient buffer.";
|
||||||
|
break;
|
||||||
|
case SCARD_E_UNKNOWN_READER:
|
||||||
|
msg = "Unknown reader specified.";
|
||||||
|
break;
|
||||||
|
case SCARD_E_TIMEOUT:
|
||||||
|
msg = "Command timeout.";
|
||||||
|
break;
|
||||||
|
case SCARD_E_SHARING_VIOLATION:
|
||||||
|
msg = "Sharing violation.";
|
||||||
|
break;
|
||||||
|
case SCARD_E_NO_SMARTCARD:
|
||||||
|
msg = "No smart card inserted.";
|
||||||
|
break;
|
||||||
|
case SCARD_E_UNKNOWN_CARD:
|
||||||
|
msg = "Unknown card.";
|
||||||
|
break;
|
||||||
|
case SCARD_E_CANT_DISPOSE:
|
||||||
|
msg = "Cannot dispose handle.";
|
||||||
|
break;
|
||||||
|
case SCARD_E_PROTO_MISMATCH:
|
||||||
|
msg = "Card protocol mismatch.";
|
||||||
|
break;
|
||||||
|
case SCARD_E_NOT_READY:
|
||||||
|
msg = "Subsystem not ready.";
|
||||||
|
break;
|
||||||
|
case SCARD_E_INVALID_VALUE:
|
||||||
|
msg = "Invalid value given.";
|
||||||
|
break;
|
||||||
|
case SCARD_E_SYSTEM_CANCELLED:
|
||||||
|
msg = "System cancelled.";
|
||||||
|
break;
|
||||||
|
case SCARD_F_COMM_ERROR:
|
||||||
|
msg = "RPC transport error.";
|
||||||
|
break;
|
||||||
|
case SCARD_F_UNKNOWN_ERROR:
|
||||||
|
msg = "Unknown error.";
|
||||||
|
break;
|
||||||
|
case SCARD_E_INVALID_ATR:
|
||||||
|
msg = "Invalid ATR.";
|
||||||
|
break;
|
||||||
|
case SCARD_E_NOT_TRANSACTED:
|
||||||
|
msg = "Transaction failed.";
|
||||||
|
break;
|
||||||
|
case SCARD_E_READER_UNAVAILABLE:
|
||||||
|
msg = "Reader is unavailable.";
|
||||||
|
break;
|
||||||
|
/* case SCARD_P_SHUTDOWN: */
|
||||||
|
case SCARD_E_PCI_TOO_SMALL:
|
||||||
|
msg = "PCI struct too small.";
|
||||||
|
break;
|
||||||
|
case SCARD_E_READER_UNSUPPORTED:
|
||||||
|
msg = "Reader is unsupported.";
|
||||||
|
break;
|
||||||
|
case SCARD_E_DUPLICATE_READER:
|
||||||
|
msg = "Reader already exists.";
|
||||||
|
break;
|
||||||
|
case SCARD_E_CARD_UNSUPPORTED:
|
||||||
|
msg = "Card is unsupported.";
|
||||||
|
break;
|
||||||
|
case SCARD_E_NO_SERVICE:
|
||||||
|
msg = "Service not available.";
|
||||||
|
break;
|
||||||
|
case SCARD_E_SERVICE_STOPPED:
|
||||||
|
msg = "Service was stopped.";
|
||||||
|
break;
|
||||||
|
/* case SCARD_E_UNEXPECTED: */
|
||||||
|
/* case SCARD_E_ICC_CREATEORDER: */
|
||||||
|
/* case SCARD_E_UNSUPPORTED_FEATURE: */
|
||||||
|
/* case SCARD_E_DIR_NOT_FOUND: */
|
||||||
|
/* case SCARD_E_NO_DIR: */
|
||||||
|
/* case SCARD_E_NO_FILE: */
|
||||||
|
/* case SCARD_E_NO_ACCESS: */
|
||||||
|
/* case SCARD_E_WRITE_TOO_MANY: */
|
||||||
|
/* case SCARD_E_BAD_SEEK: */
|
||||||
|
/* case SCARD_E_INVALID_CHV: */
|
||||||
|
/* case SCARD_E_UNKNOWN_RES_MNG: */
|
||||||
|
/* case SCARD_E_NO_SUCH_CERTIFICATE: */
|
||||||
|
/* case SCARD_E_CERTIFICATE_UNAVAILABLE: */
|
||||||
|
case SCARD_E_NO_READERS_AVAILABLE:
|
||||||
|
msg = "Cannot find a smart card reader.";
|
||||||
|
break;
|
||||||
|
/* case SCARD_E_COMM_DATA_LOST: */
|
||||||
|
/* case SCARD_E_NO_KEY_CONTAINER: */
|
||||||
|
/* case SCARD_E_SERVER_TOO_BUSY: */
|
||||||
|
case SCARD_W_UNSUPPORTED_CARD:
|
||||||
|
msg = "Card is not supported.";
|
||||||
|
break;
|
||||||
|
case SCARD_W_UNRESPONSIVE_CARD:
|
||||||
|
msg = "Card is unresponsive.";
|
||||||
|
break;
|
||||||
|
case SCARD_W_UNPOWERED_CARD:
|
||||||
|
msg = "Card is unpowered.";
|
||||||
|
break;
|
||||||
|
case SCARD_W_RESET_CARD:
|
||||||
|
msg = "Card was reset.";
|
||||||
|
break;
|
||||||
|
case SCARD_W_REMOVED_CARD:
|
||||||
|
msg = "Card was removed.";
|
||||||
|
break;
|
||||||
|
/* case SCARD_W_SECURITY_VIOLATION: */
|
||||||
|
/* case SCARD_W_WRONG_CHV: */
|
||||||
|
/* case SCARD_W_CHV_BLOCKED: */
|
||||||
|
/* case SCARD_W_EOF: */
|
||||||
|
/* case SCARD_W_CANCELLED_BY_USER: */
|
||||||
|
/* case SCARD_W_CARD_NOT_AUTHENTICATED: */
|
||||||
|
|
||||||
|
case SCARD_E_UNSUPPORTED_FEATURE:
|
||||||
|
msg = "Feature not supported.";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
(void)snprintf(strError, sizeof(strError)-1, "Unknown error: 0x%08lX",
|
||||||
|
pcscError);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (msg)
|
||||||
|
(void)strncpy(strError, msg, sizeof(strError));
|
||||||
|
else
|
||||||
|
(void)snprintf(strError, sizeof(strError)-1, "Unknown error: 0x%08lX",
|
||||||
|
pcscError);
|
||||||
|
|
||||||
|
/* add a null byte */
|
||||||
|
strError[sizeof(strError)-1] = '\0';
|
||||||
|
|
||||||
|
return strError;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,508 @@
|
||||||
|
/*
|
||||||
|
* MUSCLE SmartCard Development ( http://pcsclite.alioth.debian.org/pcsclite.html )
|
||||||
|
*
|
||||||
|
* Copyright (C) 2000-2002
|
||||||
|
* David Corcoran <corcoran@musclecard.com>
|
||||||
|
* Copyright (C) 2002-2011
|
||||||
|
* Ludovic Rousseau <ludovic.rousseau@free.fr>
|
||||||
|
*
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. The name of the author may not be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief This keeps track of card insertion/removal events
|
||||||
|
* and updates ATR, protocol, and status information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
#include "misc.h"
|
||||||
|
#include "pcscd.h"
|
||||||
|
#include "debuglog.h"
|
||||||
|
#include "readerfactory.h"
|
||||||
|
#include "eventhandler.h"
|
||||||
|
#include "dyn_generic.h"
|
||||||
|
#include "sys_generic.h"
|
||||||
|
#include "ifdwrapper.h"
|
||||||
|
#include "prothandler.h"
|
||||||
|
#include "utils.h"
|
||||||
|
#include "winscard_svc.h"
|
||||||
|
#include "simclist.h"
|
||||||
|
|
||||||
|
static list_t ClientsWaitingForEvent; /**< list of client file descriptors */
|
||||||
|
pthread_mutex_t ClientsWaitingForEvent_lock; /**< lock for the above list */
|
||||||
|
|
||||||
|
static void EHStatusHandlerThread(READER_CONTEXT *);
|
||||||
|
|
||||||
|
LONG EHRegisterClientForEvent(int32_t filedes)
|
||||||
|
{
|
||||||
|
(void)pthread_mutex_lock(&ClientsWaitingForEvent_lock);
|
||||||
|
|
||||||
|
(void)list_append(&ClientsWaitingForEvent, &filedes);
|
||||||
|
|
||||||
|
(void)pthread_mutex_unlock(&ClientsWaitingForEvent_lock);
|
||||||
|
|
||||||
|
return SCARD_S_SUCCESS;
|
||||||
|
} /* EHRegisterClientForEvent */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Try to unregisted a client
|
||||||
|
* If no client is found then do not log an error
|
||||||
|
*/
|
||||||
|
LONG EHTryToUnregisterClientForEvent(int32_t filedes)
|
||||||
|
{
|
||||||
|
LONG rv = SCARD_S_SUCCESS;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
(void)pthread_mutex_lock(&ClientsWaitingForEvent_lock);
|
||||||
|
|
||||||
|
ret = list_delete(&ClientsWaitingForEvent, &filedes);
|
||||||
|
|
||||||
|
(void)pthread_mutex_unlock(&ClientsWaitingForEvent_lock);
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
rv = SCARD_F_INTERNAL_ERROR;
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
} /* EHTryToUnregisterClientForEvent */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregister a client and log an error if the client is not found
|
||||||
|
*/
|
||||||
|
LONG EHUnregisterClientForEvent(int32_t filedes)
|
||||||
|
{
|
||||||
|
LONG rv = EHTryToUnregisterClientForEvent(filedes);
|
||||||
|
|
||||||
|
if (rv < 0)
|
||||||
|
Log2(PCSC_LOG_ERROR, "Can't remove client: %d", filedes);
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
} /* EHUnregisterClientForEvent */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends an asynchronous event to any waiting client
|
||||||
|
*/
|
||||||
|
void EHSignalEventToClients(void)
|
||||||
|
{
|
||||||
|
int32_t filedes;
|
||||||
|
|
||||||
|
(void)pthread_mutex_lock(&ClientsWaitingForEvent_lock);
|
||||||
|
|
||||||
|
(void)list_iterator_start(&ClientsWaitingForEvent);
|
||||||
|
while (list_iterator_hasnext(&ClientsWaitingForEvent))
|
||||||
|
{
|
||||||
|
filedes = *(int32_t *)list_iterator_next(&ClientsWaitingForEvent);
|
||||||
|
MSGSignalClient(filedes, SCARD_S_SUCCESS);
|
||||||
|
}
|
||||||
|
(void)list_iterator_stop(&ClientsWaitingForEvent);
|
||||||
|
|
||||||
|
(void)list_clear(&ClientsWaitingForEvent);
|
||||||
|
|
||||||
|
(void)pthread_mutex_unlock(&ClientsWaitingForEvent_lock);
|
||||||
|
} /* EHSignalEventToClients */
|
||||||
|
|
||||||
|
LONG EHInitializeEventStructures(void)
|
||||||
|
{
|
||||||
|
(void)list_init(&ClientsWaitingForEvent);
|
||||||
|
|
||||||
|
/* request to store copies, and provide the metric function */
|
||||||
|
(void)list_attributes_copy(&ClientsWaitingForEvent, list_meter_int32_t, 1);
|
||||||
|
|
||||||
|
/* setting the comparator, so the list can sort, find the min, max etc */
|
||||||
|
(void)list_attributes_comparator(&ClientsWaitingForEvent, list_comparator_int32_t);
|
||||||
|
|
||||||
|
(void)pthread_mutex_init(&ClientsWaitingForEvent_lock, NULL);
|
||||||
|
|
||||||
|
return SCARD_S_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
LONG EHDeinitializeEventStructures(void)
|
||||||
|
{
|
||||||
|
list_destroy(&ClientsWaitingForEvent);
|
||||||
|
pthread_mutex_destroy(&ClientsWaitingForEvent_lock);
|
||||||
|
|
||||||
|
return SCARD_S_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EHDestroyEventHandler(READER_CONTEXT * rContext)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
DWORD dwGetSize;
|
||||||
|
UCHAR ucGetData[1];
|
||||||
|
|
||||||
|
if ('\0' == rContext->readerState->readerName[0])
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_INFO, "Thread already stomped.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the thread to 0 to exit thread
|
||||||
|
*/
|
||||||
|
rContext->hLockId = 0xFFFF;
|
||||||
|
|
||||||
|
Log1(PCSC_LOG_INFO, "Stomping thread.");
|
||||||
|
|
||||||
|
/* kill the "polling" thread */
|
||||||
|
dwGetSize = sizeof(ucGetData);
|
||||||
|
rv = IFDGetCapabilities(rContext, TAG_IFD_POLLING_THREAD_KILLABLE,
|
||||||
|
&dwGetSize, ucGetData);
|
||||||
|
|
||||||
|
#ifdef HAVE_PTHREAD_CANCEL
|
||||||
|
if ((IFD_SUCCESS == rv) && (1 == dwGetSize) && ucGetData[0])
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_INFO, "Killing polling thread");
|
||||||
|
(void)pthread_cancel(rContext->pthThread);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
/* ask to stop the "polling" thread */
|
||||||
|
RESPONSECODE (*fct)(DWORD) = NULL;
|
||||||
|
|
||||||
|
dwGetSize = sizeof(fct);
|
||||||
|
rv = IFDGetCapabilities(rContext, TAG_IFD_STOP_POLLING_THREAD,
|
||||||
|
&dwGetSize, (PUCHAR)&fct);
|
||||||
|
|
||||||
|
if ((IFD_SUCCESS == rv) && (dwGetSize == sizeof(fct)))
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_INFO, "Request stopping of polling thread");
|
||||||
|
fct(rContext->slot);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Log1(PCSC_LOG_INFO, "Waiting polling thread");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* wait for the thread to finish */
|
||||||
|
rv = pthread_join(rContext->pthThread, NULL);
|
||||||
|
if (rv)
|
||||||
|
Log2(PCSC_LOG_ERROR, "pthread_join failed: %s", strerror(rv));
|
||||||
|
|
||||||
|
/* Zero the thread */
|
||||||
|
rContext->pthThread = 0;
|
||||||
|
|
||||||
|
Log1(PCSC_LOG_INFO, "Thread stomped.");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LONG EHSpawnEventHandler(READER_CONTEXT * rContext)
|
||||||
|
{
|
||||||
|
LONG rv;
|
||||||
|
DWORD dwStatus = 0;
|
||||||
|
|
||||||
|
rv = IFDStatusICC(rContext, &dwStatus);
|
||||||
|
if (rv != SCARD_S_SUCCESS)
|
||||||
|
{
|
||||||
|
Log2(PCSC_LOG_ERROR, "Initial Check Failed on %s",
|
||||||
|
rContext->readerState->readerName);
|
||||||
|
return SCARD_F_UNKNOWN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = ThreadCreate(&rContext->pthThread, 0,
|
||||||
|
(PCSCLITE_THREAD_FUNCTION( ))EHStatusHandlerThread, (LPVOID) rContext);
|
||||||
|
if (rv)
|
||||||
|
{
|
||||||
|
Log2(PCSC_LOG_ERROR, "ThreadCreate failed: %s", strerror(rv));
|
||||||
|
return SCARD_E_NO_MEMORY;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return SCARD_S_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void EHStatusHandlerThread(READER_CONTEXT * rContext)
|
||||||
|
{
|
||||||
|
LONG rv;
|
||||||
|
#ifndef NO_LOG
|
||||||
|
const char *readerName;
|
||||||
|
#endif
|
||||||
|
DWORD dwStatus;
|
||||||
|
uint32_t readerState;
|
||||||
|
int32_t readerSharing;
|
||||||
|
DWORD dwCurrentState;
|
||||||
|
#ifndef DISABLE_AUTO_POWER_ON
|
||||||
|
DWORD dwAtrLen;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Zero out everything
|
||||||
|
*/
|
||||||
|
dwStatus = 0;
|
||||||
|
|
||||||
|
#ifndef NO_LOG
|
||||||
|
readerName = rContext->readerState->readerName;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
rv = IFDStatusICC(rContext, &dwStatus);
|
||||||
|
|
||||||
|
if ((SCARD_S_SUCCESS == rv) && (dwStatus & SCARD_PRESENT))
|
||||||
|
{
|
||||||
|
#ifdef DISABLE_AUTO_POWER_ON
|
||||||
|
rContext->readerState->cardAtrLength = 0;
|
||||||
|
rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED;
|
||||||
|
readerState = SCARD_PRESENT;
|
||||||
|
Log1(PCSC_LOG_INFO, "Skip card power on");
|
||||||
|
#else
|
||||||
|
dwAtrLen = sizeof(rContext->readerState->cardAtr);
|
||||||
|
rv = IFDPowerICC(rContext, IFD_POWER_UP,
|
||||||
|
rContext->readerState->cardAtr, &dwAtrLen);
|
||||||
|
rContext->readerState->cardAtrLength = dwAtrLen;
|
||||||
|
|
||||||
|
/* the protocol is unset after a power on */
|
||||||
|
rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED;
|
||||||
|
|
||||||
|
if (rv == IFD_SUCCESS)
|
||||||
|
{
|
||||||
|
readerState = SCARD_PRESENT | SCARD_POWERED | SCARD_NEGOTIABLE;
|
||||||
|
rContext->powerState = POWER_STATE_POWERED;
|
||||||
|
Log1(PCSC_LOG_DEBUG, "powerState: POWER_STATE_POWERED");
|
||||||
|
|
||||||
|
if (rContext->readerState->cardAtrLength > 0)
|
||||||
|
{
|
||||||
|
LogXxd(PCSC_LOG_INFO, "Card ATR: ",
|
||||||
|
rContext->readerState->cardAtr,
|
||||||
|
rContext->readerState->cardAtrLength);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Log1(PCSC_LOG_INFO, "Card ATR: (NULL)");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
readerState = SCARD_PRESENT | SCARD_SWALLOWED;
|
||||||
|
rContext->powerState = POWER_STATE_UNPOWERED;
|
||||||
|
Log1(PCSC_LOG_DEBUG, "powerState: POWER_STATE_UNPOWERED");
|
||||||
|
Log3(PCSC_LOG_ERROR, "Error powering up card: %ld 0x%04lX", rv, rv);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
dwCurrentState = SCARD_PRESENT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
readerState = SCARD_ABSENT;
|
||||||
|
rContext->readerState->cardAtrLength = 0;
|
||||||
|
rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED;
|
||||||
|
|
||||||
|
dwCurrentState = SCARD_ABSENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set all the public attributes to this reader
|
||||||
|
*/
|
||||||
|
rContext->readerState->readerState = readerState;
|
||||||
|
rContext->readerState->readerSharing = readerSharing = rContext->contexts;
|
||||||
|
|
||||||
|
EHSignalEventToClients();
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
dwStatus = 0;
|
||||||
|
|
||||||
|
rv = IFDStatusICC(rContext, &dwStatus);
|
||||||
|
|
||||||
|
if (rv != SCARD_S_SUCCESS)
|
||||||
|
{
|
||||||
|
Log2(PCSC_LOG_ERROR, "Error communicating to: %s", readerName);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set error status on this reader while errors occur
|
||||||
|
*/
|
||||||
|
rContext->readerState->readerState = SCARD_UNKNOWN;
|
||||||
|
rContext->readerState->cardAtrLength = 0;
|
||||||
|
rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED;
|
||||||
|
|
||||||
|
dwCurrentState = SCARD_UNKNOWN;
|
||||||
|
|
||||||
|
EHSignalEventToClients();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dwStatus & SCARD_ABSENT)
|
||||||
|
{
|
||||||
|
if (dwCurrentState == SCARD_PRESENT ||
|
||||||
|
dwCurrentState == SCARD_UNKNOWN)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Change the status structure
|
||||||
|
*/
|
||||||
|
Log2(PCSC_LOG_INFO, "Card Removed From %s", readerName);
|
||||||
|
/*
|
||||||
|
* Notify the card has been removed
|
||||||
|
*/
|
||||||
|
(void)RFSetReaderEventState(rContext, SCARD_REMOVED);
|
||||||
|
|
||||||
|
rContext->readerState->cardAtrLength = 0;
|
||||||
|
rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED;
|
||||||
|
rContext->readerState->readerState = SCARD_ABSENT;
|
||||||
|
dwCurrentState = SCARD_ABSENT;
|
||||||
|
|
||||||
|
rContext->readerState->eventCounter++;
|
||||||
|
if (rContext->readerState->eventCounter > 0xFFFF)
|
||||||
|
rContext->readerState->eventCounter = 0;
|
||||||
|
|
||||||
|
EHSignalEventToClients();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (dwStatus & SCARD_PRESENT)
|
||||||
|
{
|
||||||
|
if (dwCurrentState == SCARD_ABSENT ||
|
||||||
|
dwCurrentState == SCARD_UNKNOWN)
|
||||||
|
{
|
||||||
|
#ifdef DISABLE_AUTO_POWER_ON
|
||||||
|
rContext->readerState->cardAtrLength = 0;
|
||||||
|
rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED;
|
||||||
|
rContext->readerState->readerState = SCARD_PRESENT;
|
||||||
|
rContext->powerState = POWER_STATE_UNPOWERED;
|
||||||
|
Log1(PCSC_LOG_DEBUG, "powerState: POWER_STATE_UNPOWERED");
|
||||||
|
rv = IFD_SUCCESS;
|
||||||
|
Log1(PCSC_LOG_INFO, "Skip card power on");
|
||||||
|
#else
|
||||||
|
/*
|
||||||
|
* Power and reset the card
|
||||||
|
*/
|
||||||
|
dwAtrLen = sizeof(rContext->readerState->cardAtr);
|
||||||
|
rv = IFDPowerICC(rContext, IFD_POWER_UP,
|
||||||
|
rContext->readerState->cardAtr, &dwAtrLen);
|
||||||
|
rContext->readerState->cardAtrLength = dwAtrLen;
|
||||||
|
|
||||||
|
/* the protocol is unset after a power on */
|
||||||
|
rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED;
|
||||||
|
|
||||||
|
if (rv == IFD_SUCCESS)
|
||||||
|
{
|
||||||
|
rContext->readerState->readerState = SCARD_PRESENT | SCARD_POWERED | SCARD_NEGOTIABLE;
|
||||||
|
rContext->powerState = POWER_STATE_POWERED;
|
||||||
|
Log1(PCSC_LOG_DEBUG, "powerState: POWER_STATE_POWERED");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rContext->readerState->readerState = SCARD_PRESENT | SCARD_SWALLOWED;
|
||||||
|
rContext->powerState = POWER_STATE_UNPOWERED;
|
||||||
|
Log1(PCSC_LOG_DEBUG, "powerState: POWER_STATE_UNPOWERED");
|
||||||
|
rContext->readerState->cardAtrLength = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
dwCurrentState = SCARD_PRESENT;
|
||||||
|
|
||||||
|
rContext->readerState->eventCounter++;
|
||||||
|
if (rContext->readerState->eventCounter > 0xFFFF)
|
||||||
|
rContext->readerState->eventCounter = 0;
|
||||||
|
|
||||||
|
Log2(PCSC_LOG_INFO, "Card inserted into %s", readerName);
|
||||||
|
|
||||||
|
EHSignalEventToClients();
|
||||||
|
|
||||||
|
if (rv == IFD_SUCCESS)
|
||||||
|
{
|
||||||
|
if (rContext->readerState->cardAtrLength > 0)
|
||||||
|
{
|
||||||
|
LogXxd(PCSC_LOG_INFO, "Card ATR: ",
|
||||||
|
rContext->readerState->cardAtr,
|
||||||
|
rContext->readerState->cardAtrLength);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Log1(PCSC_LOG_INFO, "Card ATR: (NULL)");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Log1(PCSC_LOG_ERROR,"Error powering up card.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sharing may change w/o an event pass it on
|
||||||
|
*/
|
||||||
|
if (readerSharing != rContext->contexts)
|
||||||
|
{
|
||||||
|
readerSharing = rContext->contexts;
|
||||||
|
rContext->readerState->readerSharing = readerSharing;
|
||||||
|
EHSignalEventToClients();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rContext->pthCardEvent)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
int timeout;
|
||||||
|
|
||||||
|
#ifndef DISABLE_ON_DEMAND_POWER_ON
|
||||||
|
if (POWER_STATE_POWERED == rContext->powerState)
|
||||||
|
/* The card is powered but not yet used */
|
||||||
|
timeout = PCSCLITE_POWER_OFF_GRACE_PERIOD;
|
||||||
|
else
|
||||||
|
/* The card is already in use or not used at all */
|
||||||
|
#endif
|
||||||
|
timeout = PCSCLITE_STATUS_EVENT_TIMEOUT;
|
||||||
|
|
||||||
|
ret = rContext->pthCardEvent(rContext->slot, timeout);
|
||||||
|
if (IFD_SUCCESS != ret)
|
||||||
|
(void)SYS_USleep(PCSCLITE_STATUS_POLL_RATE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
(void)SYS_USleep(PCSCLITE_STATUS_POLL_RATE);
|
||||||
|
|
||||||
|
#ifndef DISABLE_ON_DEMAND_POWER_ON
|
||||||
|
/* the card is powered but not used */
|
||||||
|
(void)pthread_mutex_lock(&rContext->powerState_lock);
|
||||||
|
if (POWER_STATE_POWERED == rContext->powerState)
|
||||||
|
{
|
||||||
|
/* power down */
|
||||||
|
IFDPowerICC(rContext, IFD_POWER_DOWN, NULL, NULL);
|
||||||
|
rContext->powerState = POWER_STATE_UNPOWERED;
|
||||||
|
Log1(PCSC_LOG_DEBUG, "powerState: POWER_STATE_UNPOWERED");
|
||||||
|
|
||||||
|
/* the protocol is unset after a power down */
|
||||||
|
rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* the card was in use */
|
||||||
|
if (POWER_STATE_GRACE_PERIOD == rContext->powerState)
|
||||||
|
{
|
||||||
|
/* the next state should be UNPOWERED unless the
|
||||||
|
* card is used again */
|
||||||
|
rContext->powerState = POWER_STATE_POWERED;
|
||||||
|
Log1(PCSC_LOG_DEBUG, "powerState: POWER_STATE_POWERED");
|
||||||
|
}
|
||||||
|
(void)pthread_mutex_unlock(&rContext->powerState_lock);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (rContext->hLockId == 0xFFFF)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Exit and notify the caller
|
||||||
|
*/
|
||||||
|
Log1(PCSC_LOG_INFO, "Die");
|
||||||
|
rContext->hLockId = 0;
|
||||||
|
(void)pthread_exit(NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
/*
|
||||||
|
* MUSCLE SmartCard Development ( http://pcsclite.alioth.debian.org/pcsclite.html )
|
||||||
|
*
|
||||||
|
* Copyright (C) 1999-2002
|
||||||
|
* David Corcoran <corcoran@musclecard.com>
|
||||||
|
* Copyright (C) 2002-2010
|
||||||
|
* Ludovic Rousseau <ludovic.rousseau@free.fr>
|
||||||
|
*
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. The name of the author may not be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief This handles card insertion/removal events, updates ATR,
|
||||||
|
* protocol, and status information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __eventhandler_h__
|
||||||
|
#define __eventhandler_h__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define an exported public reader state structure so each
|
||||||
|
* application gets instant notification of changes in state.
|
||||||
|
*/
|
||||||
|
typedef struct pubReaderStatesList
|
||||||
|
{
|
||||||
|
char readerName[MAX_READERNAME]; /**< reader name */
|
||||||
|
uint32_t eventCounter; /**< number of card events */
|
||||||
|
uint32_t readerState; /**< SCARD_* bit field */
|
||||||
|
int32_t readerSharing; /**< PCSCLITE_SHARING_* sharing status */
|
||||||
|
|
||||||
|
UCHAR cardAtr[MAX_ATR_SIZE]; /**< ATR */
|
||||||
|
uint32_t cardAtrLength; /**< ATR length */
|
||||||
|
uint32_t cardProtocol; /**< SCARD_PROTOCOL_* value */
|
||||||
|
}
|
||||||
|
READER_STATE;
|
||||||
|
|
||||||
|
LONG EHTryToUnregisterClientForEvent(int32_t filedes);
|
||||||
|
LONG EHRegisterClientForEvent(int32_t filedes);
|
||||||
|
LONG EHUnregisterClientForEvent(int32_t filedes);
|
||||||
|
void EHSignalEventToClients(void);
|
||||||
|
LONG EHInitializeEventStructures(void);
|
||||||
|
LONG EHDeinitializeEventStructures(void);
|
||||||
|
LONG EHSpawnEventHandler(READER_CONTEXT *);
|
||||||
|
void EHDestroyEventHandler(READER_CONTEXT *);
|
||||||
|
|
||||||
|
/** One application is using the reader */
|
||||||
|
#define PCSCLITE_SHARING_LAST_CONTEXT 1
|
||||||
|
/** No application is using the reader */
|
||||||
|
#define PCSCLITE_SHARING_NO_CONTEXT 0
|
||||||
|
/** Reader used in exclusive mode */
|
||||||
|
#define PCSCLITE_SHARING_EXCLUSIVE_CONTEXT -1
|
||||||
|
|
||||||
|
/** Special value to indicate that power up has not yet happen
|
||||||
|
* This is used to auto start mode to wait until the reader is
|
||||||
|
* ready and the (possible) card has been powered up */
|
||||||
|
#define READER_NOT_INITIALIZED (MAX_ATR_SIZE+1)
|
||||||
|
|
||||||
|
#endif /* __eventhandler_h__ */
|
|
@ -0,0 +1,59 @@
|
||||||
|
/*
|
||||||
|
* MUSCLE SmartCard Development ( http://pcsclite.alioth.debian.org/pcsclite.html )
|
||||||
|
*
|
||||||
|
* Copyright (C) 2000-2003
|
||||||
|
* David Corcoran <corcoran@musclecard.com>
|
||||||
|
* Copyright (C) 2002-2009
|
||||||
|
* Ludovic Rousseau <ludovic.rousseau@free.fr>
|
||||||
|
*
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. The name of the author may not be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief This provides a search API for hot pluggble devices.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __hotplug_h__
|
||||||
|
#define __hotplug_h__
|
||||||
|
|
||||||
|
#ifndef PCSCLITE_HP_DROPDIR
|
||||||
|
#define PCSCLITE_HP_DROPDIR "/usr/local/pcsc/drivers/"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define PCSCLITE_HP_MANUKEY_NAME "ifdVendorID"
|
||||||
|
#define PCSCLITE_HP_PRODKEY_NAME "ifdProductID"
|
||||||
|
#define PCSCLITE_HP_NAMEKEY_NAME "ifdFriendlyName"
|
||||||
|
#define PCSCLITE_HP_LIBRKEY_NAME "CFBundleExecutable"
|
||||||
|
#define PCSCLITE_HP_CPCTKEY_NAME "ifdCapabilities"
|
||||||
|
#define PCSCLITE_HP_CFBUNDLE_NAME "CFBundleName"
|
||||||
|
|
||||||
|
#define PCSCLITE_HP_BASE_PORT 0x200000
|
||||||
|
|
||||||
|
LONG HPSearchHotPluggables(void);
|
||||||
|
ULONG HPRegisterForHotplugEvents(void);
|
||||||
|
LONG HPStopHotPluggables(void);
|
||||||
|
void HPReCheckSerialReaders(void);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,72 @@
|
||||||
|
/*
|
||||||
|
* MUSCLE SmartCard Development ( http://pcsclite.alioth.debian.org/pcsclite.html )
|
||||||
|
*
|
||||||
|
* Copyright (C) 2000-2003
|
||||||
|
* David Corcoran <corcoran@musclecard.com>
|
||||||
|
* Copyright (C) 2002-2011
|
||||||
|
* Ludovic Rousseau <ludovic.rousseau@free.fr>
|
||||||
|
*
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. The name of the author may not be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief This provides a search API for hot pluggble devices.
|
||||||
|
*
|
||||||
|
* Check for platforms that have their own specific support.
|
||||||
|
* It's easier and flexible to do it here, rather than
|
||||||
|
* with automake conditionals in src/Makefile.am.
|
||||||
|
* No, it's still not a perfect solution design wise.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "pcsclite.h"
|
||||||
|
|
||||||
|
#ifndef TRUE
|
||||||
|
#define TRUE 1
|
||||||
|
#define FALSE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(__APPLE__) && !defined(HAVE_LIBUSB) && !defined(__linux__) && !defined(HAVE_LIBUDEV)
|
||||||
|
|
||||||
|
LONG HPSearchHotPluggables(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG HPRegisterForHotplugEvents(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
LONG HPStopHotPluggables(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HPReCheckSerialReaders(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,788 @@
|
||||||
|
/*
|
||||||
|
* MUSCLE SmartCard Development ( http://pcsclite.alioth.debian.org/pcsclite.html )
|
||||||
|
*
|
||||||
|
* Copyright (C) 2011
|
||||||
|
* Ludovic Rousseau <ludovic.rousseau@free.fr>
|
||||||
|
* Copyright (C) 2014
|
||||||
|
* Stefani Seibold <stefani@seibold.net>
|
||||||
|
*
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. The name of the author may not be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief This provides a search API for hot plugable devices using libudev
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#if defined(HAVE_LIBUDEV) && defined(USE_USB)
|
||||||
|
|
||||||
|
#define _GNU_SOURCE /* for asprintf(3) */
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <libudev.h>
|
||||||
|
#include <poll.h>
|
||||||
|
|
||||||
|
#include "debuglog.h"
|
||||||
|
#include "parser.h"
|
||||||
|
#include "readerfactory.h"
|
||||||
|
#include "sys_generic.h"
|
||||||
|
#include "hotplug.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
#ifndef TEMP_FAILURE_RETRY
|
||||||
|
#define TEMP_FAILURE_RETRY(expression) \
|
||||||
|
(__extension__ \
|
||||||
|
({ long int __result; \
|
||||||
|
do __result = (long int) (expression); \
|
||||||
|
while (__result == -1L && errno == EINTR); \
|
||||||
|
__result; }))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#undef DEBUG_HOTPLUG
|
||||||
|
|
||||||
|
#define FALSE 0
|
||||||
|
#define TRUE 1
|
||||||
|
|
||||||
|
extern char Add_Interface_In_Name;
|
||||||
|
extern char Add_Serial_In_Name;
|
||||||
|
|
||||||
|
static pthread_t usbNotifyThread;
|
||||||
|
static int driverSize = -1;
|
||||||
|
static struct udev *Udev;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* keep track of drivers in a dynamically allocated array
|
||||||
|
*/
|
||||||
|
static struct _driverTracker
|
||||||
|
{
|
||||||
|
unsigned int manuID;
|
||||||
|
unsigned int productID;
|
||||||
|
|
||||||
|
char *bundleName;
|
||||||
|
char *libraryPath;
|
||||||
|
char *readerName;
|
||||||
|
char *CFBundleName;
|
||||||
|
} *driverTracker = NULL;
|
||||||
|
#define DRIVER_TRACKER_SIZE_STEP 10
|
||||||
|
|
||||||
|
/* The CCID driver already supports 176 readers.
|
||||||
|
* We start with a big array size to avoid reallocation. */
|
||||||
|
#define DRIVER_TRACKER_INITIAL_SIZE 200
|
||||||
|
|
||||||
|
/**
|
||||||
|
* keep track of PCSCLITE_MAX_READERS_CONTEXTS simultaneous readers
|
||||||
|
*/
|
||||||
|
static struct _readerTracker
|
||||||
|
{
|
||||||
|
char *devpath; /**< device name seen by udev */
|
||||||
|
char *fullName; /**< full reader name (including serial number) */
|
||||||
|
char *sysname; /**< sysfs path */
|
||||||
|
} readerTracker[PCSCLITE_MAX_READERS_CONTEXTS];
|
||||||
|
|
||||||
|
|
||||||
|
static LONG HPReadBundleValues(void)
|
||||||
|
{
|
||||||
|
LONG rv;
|
||||||
|
DIR *hpDir;
|
||||||
|
struct dirent *currFP = NULL;
|
||||||
|
char fullPath[FILENAME_MAX];
|
||||||
|
char fullLibPath[FILENAME_MAX];
|
||||||
|
int listCount = 0;
|
||||||
|
|
||||||
|
hpDir = opendir(PCSCLITE_HP_DROPDIR);
|
||||||
|
|
||||||
|
if (NULL == hpDir)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_ERROR, "Cannot open PC/SC drivers directory: " PCSCLITE_HP_DROPDIR);
|
||||||
|
Log1(PCSC_LOG_ERROR, "Disabling USB support for pcscd.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allocate a first array */
|
||||||
|
driverSize = DRIVER_TRACKER_INITIAL_SIZE;
|
||||||
|
driverTracker = calloc(driverSize, sizeof(*driverTracker));
|
||||||
|
if (NULL == driverTracker)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_CRITICAL, "Not enough memory");
|
||||||
|
(void)closedir(hpDir);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define GET_KEY(key, values) \
|
||||||
|
rv = LTPBundleFindValueWithKey(&plist, key, values); \
|
||||||
|
if (rv) \
|
||||||
|
{ \
|
||||||
|
Log2(PCSC_LOG_ERROR, "Value/Key not defined for " key " in %s", \
|
||||||
|
fullPath); \
|
||||||
|
continue; \
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((currFP = readdir(hpDir)) != 0)
|
||||||
|
{
|
||||||
|
if (strstr(currFP->d_name, ".bundle") != 0)
|
||||||
|
{
|
||||||
|
unsigned int alias;
|
||||||
|
list_t plist, *values;
|
||||||
|
list_t *manuIDs, *productIDs, *readerNames;
|
||||||
|
char *CFBundleName;
|
||||||
|
char *libraryPath;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The bundle exists - let's form a full path name and get the
|
||||||
|
* vendor and product ID's for this particular bundle
|
||||||
|
*/
|
||||||
|
(void)snprintf(fullPath, sizeof(fullPath), "%s/%s/Contents/Info.plist",
|
||||||
|
PCSCLITE_HP_DROPDIR, currFP->d_name);
|
||||||
|
fullPath[sizeof(fullPath) - 1] = '\0';
|
||||||
|
|
||||||
|
rv = bundleParse(fullPath, &plist);
|
||||||
|
if (rv)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* get CFBundleExecutable */
|
||||||
|
GET_KEY(PCSCLITE_HP_LIBRKEY_NAME, &values)
|
||||||
|
libraryPath = list_get_at(values, 0);
|
||||||
|
(void)snprintf(fullLibPath, sizeof(fullLibPath),
|
||||||
|
"%s/%s/Contents/%s/%s",
|
||||||
|
PCSCLITE_HP_DROPDIR, currFP->d_name, PCSC_ARCH,
|
||||||
|
libraryPath);
|
||||||
|
fullLibPath[sizeof(fullLibPath) - 1] = '\0';
|
||||||
|
|
||||||
|
GET_KEY(PCSCLITE_HP_MANUKEY_NAME, &manuIDs)
|
||||||
|
GET_KEY(PCSCLITE_HP_PRODKEY_NAME, &productIDs)
|
||||||
|
GET_KEY(PCSCLITE_HP_NAMEKEY_NAME, &readerNames)
|
||||||
|
|
||||||
|
if ((list_size(manuIDs) != list_size(productIDs))
|
||||||
|
|| (list_size(manuIDs) != list_size(readerNames)))
|
||||||
|
{
|
||||||
|
Log2(PCSC_LOG_CRITICAL, "Error parsing %s", fullPath);
|
||||||
|
(void)closedir(hpDir);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get CFBundleName */
|
||||||
|
rv = LTPBundleFindValueWithKey(&plist, PCSCLITE_HP_CFBUNDLE_NAME,
|
||||||
|
&values);
|
||||||
|
if (rv)
|
||||||
|
CFBundleName = NULL;
|
||||||
|
else
|
||||||
|
CFBundleName = strdup(list_get_at(values, 0));
|
||||||
|
|
||||||
|
/* while we find a nth ifdVendorID in Info.plist */
|
||||||
|
for (alias=0; alias<list_size(manuIDs); alias++)
|
||||||
|
{
|
||||||
|
char *value;
|
||||||
|
|
||||||
|
/* variables entries */
|
||||||
|
value = list_get_at(manuIDs, alias);
|
||||||
|
driverTracker[listCount].manuID = strtol(value, NULL, 16);
|
||||||
|
|
||||||
|
value = list_get_at(productIDs, alias);
|
||||||
|
driverTracker[listCount].productID = strtol(value, NULL, 16);
|
||||||
|
|
||||||
|
driverTracker[listCount].readerName = strdup(list_get_at(readerNames, alias));
|
||||||
|
|
||||||
|
/* constant entries for a same driver */
|
||||||
|
driverTracker[listCount].bundleName = strdup(currFP->d_name);
|
||||||
|
driverTracker[listCount].libraryPath = strdup(fullLibPath);
|
||||||
|
driverTracker[listCount].CFBundleName = CFBundleName;
|
||||||
|
|
||||||
|
#ifdef DEBUG_HOTPLUG
|
||||||
|
Log2(PCSC_LOG_INFO, "Found driver for: %s",
|
||||||
|
driverTracker[listCount].readerName);
|
||||||
|
#endif
|
||||||
|
listCount++;
|
||||||
|
if (listCount >= driverSize)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* increase the array size */
|
||||||
|
driverSize += DRIVER_TRACKER_SIZE_STEP;
|
||||||
|
#ifdef DEBUG_HOTPLUG
|
||||||
|
Log2(PCSC_LOG_INFO,
|
||||||
|
"Increase driverTracker to %d entries", driverSize);
|
||||||
|
#endif
|
||||||
|
driverTracker = realloc(driverTracker,
|
||||||
|
driverSize * sizeof(*driverTracker));
|
||||||
|
if (NULL == driverTracker)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_CRITICAL, "Not enough memory");
|
||||||
|
driverSize = -1;
|
||||||
|
(void)closedir(hpDir);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* clean the newly allocated entries */
|
||||||
|
for (i=driverSize-DRIVER_TRACKER_SIZE_STEP; i<driverSize; i++)
|
||||||
|
{
|
||||||
|
driverTracker[i].manuID = 0;
|
||||||
|
driverTracker[i].productID = 0;
|
||||||
|
driverTracker[i].bundleName = NULL;
|
||||||
|
driverTracker[i].libraryPath = NULL;
|
||||||
|
driverTracker[i].readerName = NULL;
|
||||||
|
driverTracker[i].CFBundleName = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bundleRelease(&plist);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
driverSize = listCount;
|
||||||
|
(void)closedir(hpDir);
|
||||||
|
|
||||||
|
#ifdef DEBUG_HOTPLUG
|
||||||
|
Log2(PCSC_LOG_INFO, "Found drivers for %d readers", listCount);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
} /* HPReadBundleValues */
|
||||||
|
|
||||||
|
|
||||||
|
/*@null@*/ static struct _driverTracker *get_driver(struct udev_device *dev,
|
||||||
|
const char *devpath, struct _driverTracker **classdriver)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
unsigned int idVendor, idProduct;
|
||||||
|
static struct _driverTracker *driver;
|
||||||
|
const char *str;
|
||||||
|
|
||||||
|
str = udev_device_get_sysattr_value(dev, "idVendor");
|
||||||
|
if (!str)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_ERROR, "udev_device_get_sysattr_value() failed");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
idVendor = strtol(str, NULL, 16);
|
||||||
|
|
||||||
|
str = udev_device_get_sysattr_value(dev, "idProduct");
|
||||||
|
if (!str)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_ERROR, "udev_device_get_sysattr_value() failed");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
idProduct = strtol(str, NULL, 16);
|
||||||
|
|
||||||
|
#ifdef NO_LOG
|
||||||
|
(void)devpath;
|
||||||
|
#endif
|
||||||
|
Log4(PCSC_LOG_DEBUG,
|
||||||
|
"Looking for a driver for VID: 0x%04X, PID: 0x%04X, path: %s",
|
||||||
|
idVendor, idProduct, devpath);
|
||||||
|
|
||||||
|
*classdriver = NULL;
|
||||||
|
driver = NULL;
|
||||||
|
/* check if the device is supported by one driver */
|
||||||
|
for (i=0; i<driverSize; i++)
|
||||||
|
{
|
||||||
|
if (driverTracker[i].libraryPath != NULL &&
|
||||||
|
idVendor == driverTracker[i].manuID &&
|
||||||
|
idProduct == driverTracker[i].productID)
|
||||||
|
{
|
||||||
|
if ((driverTracker[i].CFBundleName != NULL)
|
||||||
|
&& (0 == strcmp(driverTracker[i].CFBundleName, "CCIDCLASSDRIVER")))
|
||||||
|
*classdriver = &driverTracker[i];
|
||||||
|
else
|
||||||
|
/* it is not a CCID Class driver */
|
||||||
|
driver = &driverTracker[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if we found a specific driver */
|
||||||
|
if (driver)
|
||||||
|
return driver;
|
||||||
|
|
||||||
|
/* else return the Class driver (if any) */
|
||||||
|
return *classdriver;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void HPRemoveDevice(struct udev_device *dev)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
const char *devpath;
|
||||||
|
struct udev_device *parent;
|
||||||
|
const char *sysname;
|
||||||
|
|
||||||
|
/* The device pointed to by dev contains information about
|
||||||
|
the interface. In order to get information about the USB
|
||||||
|
device, get the parent device with the subsystem/devtype pair
|
||||||
|
of "usb"/"usb_device". This will be several levels up the
|
||||||
|
tree, but the function will find it.*/
|
||||||
|
parent = udev_device_get_parent_with_subsystem_devtype(dev, "usb",
|
||||||
|
"usb_device");
|
||||||
|
if (!parent)
|
||||||
|
return;
|
||||||
|
|
||||||
|
devpath = udev_device_get_devnode(parent);
|
||||||
|
if (!devpath)
|
||||||
|
{
|
||||||
|
/* the device disapeared? */
|
||||||
|
Log1(PCSC_LOG_ERROR, "udev_device_get_devnode() failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sysname = udev_device_get_sysname(dev);
|
||||||
|
if (!sysname)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_ERROR, "udev_device_get_sysname() failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=0; i<PCSCLITE_MAX_READERS_CONTEXTS; i++)
|
||||||
|
{
|
||||||
|
if (readerTracker[i].fullName && !strcmp(sysname, readerTracker[i].sysname))
|
||||||
|
{
|
||||||
|
Log4(PCSC_LOG_INFO, "Removing USB device[%d]: %s at %s", i,
|
||||||
|
readerTracker[i].fullName, readerTracker[i].devpath);
|
||||||
|
|
||||||
|
RFRemoveReader(readerTracker[i].fullName, PCSCLITE_HP_BASE_PORT + i);
|
||||||
|
|
||||||
|
free(readerTracker[i].devpath);
|
||||||
|
readerTracker[i].devpath = NULL;
|
||||||
|
free(readerTracker[i].fullName);
|
||||||
|
readerTracker[i].fullName = NULL;
|
||||||
|
free(readerTracker[i].sysname);
|
||||||
|
readerTracker[i].sysname = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void HPAddDevice(struct udev_device *dev)
|
||||||
|
{
|
||||||
|
int index, a;
|
||||||
|
char *deviceName = NULL;
|
||||||
|
char *fullname = NULL;
|
||||||
|
struct _driverTracker *driver, *classdriver;
|
||||||
|
const char *sSerialNumber = NULL, *sInterfaceName = NULL;
|
||||||
|
const char *sInterfaceNumber;
|
||||||
|
LONG ret;
|
||||||
|
int bInterfaceNumber;
|
||||||
|
const char *devpath;
|
||||||
|
struct udev_device *parent;
|
||||||
|
const char *sysname;
|
||||||
|
|
||||||
|
/* The device pointed to by dev contains information about
|
||||||
|
the interface. In order to get information about the USB
|
||||||
|
device, get the parent device with the subsystem/devtype pair
|
||||||
|
of "usb"/"usb_device". This will be several levels up the
|
||||||
|
tree, but the function will find it.*/
|
||||||
|
parent = udev_device_get_parent_with_subsystem_devtype(dev, "usb",
|
||||||
|
"usb_device");
|
||||||
|
if (!parent)
|
||||||
|
return;
|
||||||
|
|
||||||
|
devpath = udev_device_get_devnode(parent);
|
||||||
|
if (!devpath)
|
||||||
|
{
|
||||||
|
/* the device disapeared? */
|
||||||
|
Log1(PCSC_LOG_ERROR, "udev_device_get_devnode() failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
driver = get_driver(parent, devpath, &classdriver);
|
||||||
|
if (NULL == driver)
|
||||||
|
{
|
||||||
|
/* not a smart card reader */
|
||||||
|
#ifdef DEBUG_HOTPLUG
|
||||||
|
Log2(PCSC_LOG_DEBUG, "%s is not a supported smart card reader",
|
||||||
|
devpath);
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sysname = udev_device_get_sysname(dev);
|
||||||
|
if (!sysname)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_ERROR, "udev_device_get_sysname() failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check for duplicated add */
|
||||||
|
for (index=0; index<PCSCLITE_MAX_READERS_CONTEXTS; index++)
|
||||||
|
{
|
||||||
|
if (readerTracker[index].fullName && !strcmp(sysname, readerTracker[index].sysname))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Log2(PCSC_LOG_INFO, "Adding USB device: %s", driver->readerName);
|
||||||
|
|
||||||
|
sInterfaceNumber = udev_device_get_sysattr_value(dev, "bInterfaceNumber");
|
||||||
|
if (sInterfaceNumber)
|
||||||
|
bInterfaceNumber = atoi(sInterfaceNumber);
|
||||||
|
else
|
||||||
|
bInterfaceNumber = 0;
|
||||||
|
|
||||||
|
a = asprintf(&deviceName, "usb:%04x/%04x:libudev:%d:%s",
|
||||||
|
driver->manuID, driver->productID, bInterfaceNumber, devpath);
|
||||||
|
if (-1 == a)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_ERROR, "asprintf() failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* find a free entry */
|
||||||
|
for (index=0; index<PCSCLITE_MAX_READERS_CONTEXTS; index++)
|
||||||
|
{
|
||||||
|
if (NULL == readerTracker[index].fullName)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PCSCLITE_MAX_READERS_CONTEXTS == index)
|
||||||
|
{
|
||||||
|
Log2(PCSC_LOG_ERROR,
|
||||||
|
"Not enough reader entries. Already found %d readers", index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Add_Interface_In_Name)
|
||||||
|
sInterfaceName = udev_device_get_sysattr_value(dev, "interface");
|
||||||
|
|
||||||
|
if (Add_Serial_In_Name)
|
||||||
|
sSerialNumber = udev_device_get_sysattr_value(parent, "serial");
|
||||||
|
|
||||||
|
/* name from the Info.plist file */
|
||||||
|
fullname = strdup(driver->readerName);
|
||||||
|
|
||||||
|
/* interface name from the device (if any) */
|
||||||
|
if (sInterfaceName)
|
||||||
|
{
|
||||||
|
char *result;
|
||||||
|
|
||||||
|
/* create a new name */
|
||||||
|
a = asprintf(&result, "%s [%s]", fullname, sInterfaceName);
|
||||||
|
if (-1 == a)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_ERROR, "asprintf() failed");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(fullname);
|
||||||
|
fullname = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* serial number from the device (if any) */
|
||||||
|
if (sSerialNumber)
|
||||||
|
{
|
||||||
|
/* only add the serial number if it is not already present in the
|
||||||
|
* interface name */
|
||||||
|
if (!sInterfaceName || NULL == strstr(sInterfaceName, sSerialNumber))
|
||||||
|
{
|
||||||
|
char *result;
|
||||||
|
|
||||||
|
/* create a new name */
|
||||||
|
a = asprintf(&result, "%s (%s)", fullname, sSerialNumber);
|
||||||
|
if (-1 == a)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_ERROR, "asprintf() failed");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(fullname);
|
||||||
|
fullname = result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
readerTracker[index].fullName = strdup(fullname);
|
||||||
|
readerTracker[index].devpath = strdup(devpath);
|
||||||
|
readerTracker[index].sysname = strdup(sysname);
|
||||||
|
|
||||||
|
ret = RFAddReader(fullname, PCSCLITE_HP_BASE_PORT + index,
|
||||||
|
driver->libraryPath, deviceName);
|
||||||
|
if ((SCARD_S_SUCCESS != ret) && (SCARD_E_UNKNOWN_READER != ret))
|
||||||
|
{
|
||||||
|
Log2(PCSC_LOG_ERROR, "Failed adding USB device: %s",
|
||||||
|
driver->readerName);
|
||||||
|
|
||||||
|
if (classdriver && driver != classdriver)
|
||||||
|
{
|
||||||
|
/* the reader can also be used by the a class driver */
|
||||||
|
ret = RFAddReader(fullname, PCSCLITE_HP_BASE_PORT + index,
|
||||||
|
classdriver->libraryPath, deviceName);
|
||||||
|
if ((SCARD_S_SUCCESS != ret) && (SCARD_E_UNKNOWN_READER != ret))
|
||||||
|
{
|
||||||
|
Log2(PCSC_LOG_ERROR, "Failed adding USB device: %s",
|
||||||
|
driver->readerName);
|
||||||
|
(void)CheckForOpenCT();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
(void)CheckForOpenCT();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SCARD_S_SUCCESS != ret)
|
||||||
|
{
|
||||||
|
/* adding the reader failed */
|
||||||
|
free(readerTracker[index].devpath);
|
||||||
|
readerTracker[index].devpath = NULL;
|
||||||
|
free(readerTracker[index].fullName);
|
||||||
|
readerTracker[index].fullName = NULL;
|
||||||
|
free(readerTracker[index].sysname);
|
||||||
|
readerTracker[index].sysname = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
free(fullname);
|
||||||
|
free(deviceName);
|
||||||
|
} /* HPAddDevice */
|
||||||
|
|
||||||
|
|
||||||
|
static void HPScanUSB(struct udev *udev)
|
||||||
|
{
|
||||||
|
struct udev_enumerate *enumerate;
|
||||||
|
struct udev_list_entry *devices, *dev_list_entry;
|
||||||
|
|
||||||
|
/* Create a list of the devices in the 'usb' subsystem. */
|
||||||
|
enumerate = udev_enumerate_new(udev);
|
||||||
|
udev_enumerate_add_match_subsystem(enumerate, "usb");
|
||||||
|
udev_enumerate_scan_devices(enumerate);
|
||||||
|
devices = udev_enumerate_get_list_entry(enumerate);
|
||||||
|
|
||||||
|
/* For each item enumerated */
|
||||||
|
udev_list_entry_foreach(dev_list_entry, devices)
|
||||||
|
{
|
||||||
|
struct udev_device *dev;
|
||||||
|
const char *devpath;
|
||||||
|
|
||||||
|
/* Get the filename of the /sys entry for the device
|
||||||
|
and create a udev_device object (dev) representing it */
|
||||||
|
devpath = udev_list_entry_get_name(dev_list_entry);
|
||||||
|
dev = udev_device_new_from_syspath(udev, devpath);
|
||||||
|
|
||||||
|
#ifdef DEBUG_HOTPLUG
|
||||||
|
Log2(PCSC_LOG_DEBUG, "Found matching USB device: %s", devpath);
|
||||||
|
#endif
|
||||||
|
HPAddDevice(dev);
|
||||||
|
|
||||||
|
/* free device */
|
||||||
|
udev_device_unref(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Free the enumerator object */
|
||||||
|
udev_enumerate_unref(enumerate);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void HPEstablishUSBNotifications(void *arg)
|
||||||
|
{
|
||||||
|
struct udev_monitor *udev_monitor = arg;
|
||||||
|
int r;
|
||||||
|
int fd;
|
||||||
|
struct pollfd pfd;
|
||||||
|
|
||||||
|
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
|
||||||
|
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
|
||||||
|
|
||||||
|
/* udev monitor file descriptor */
|
||||||
|
fd = udev_monitor_get_fd(udev_monitor);
|
||||||
|
if (fd < 0)
|
||||||
|
{
|
||||||
|
Log2(PCSC_LOG_ERROR, "udev_monitor_get_fd() error: %d", fd);
|
||||||
|
pthread_exit(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
pfd.fd = fd;
|
||||||
|
pfd.events = POLLIN;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
struct udev_device *dev;
|
||||||
|
|
||||||
|
#ifdef DEBUG_HOTPLUG
|
||||||
|
Log0(PCSC_LOG_INFO);
|
||||||
|
#endif
|
||||||
|
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
|
||||||
|
|
||||||
|
/* wait for a udev event */
|
||||||
|
r = TEMP_FAILURE_RETRY(poll(&pfd, 1, -1));
|
||||||
|
if (r < 0)
|
||||||
|
{
|
||||||
|
Log2(PCSC_LOG_ERROR, "select(): %s", strerror(errno));
|
||||||
|
pthread_exit(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
|
||||||
|
|
||||||
|
dev = udev_monitor_receive_device(udev_monitor);
|
||||||
|
if (dev)
|
||||||
|
{
|
||||||
|
const char *action = udev_device_get_action(dev);
|
||||||
|
|
||||||
|
if (action)
|
||||||
|
{
|
||||||
|
if (!strcmp("remove", action))
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_INFO, "USB Device removed");
|
||||||
|
HPRemoveDevice(dev);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (!strcmp("add", action))
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_INFO, "USB Device add");
|
||||||
|
HPAddDevice(dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* free device */
|
||||||
|
udev_device_unref(dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_exit(NULL);
|
||||||
|
} /* HPEstablishUSBNotifications */
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* Start a thread waiting for hotplug events
|
||||||
|
*/
|
||||||
|
LONG HPSearchHotPluggables(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i=0; i<PCSCLITE_MAX_READERS_CONTEXTS; i++)
|
||||||
|
{
|
||||||
|
readerTracker[i].devpath = NULL;
|
||||||
|
readerTracker[i].fullName = NULL;
|
||||||
|
readerTracker[i].sysname = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return HPReadBundleValues();
|
||||||
|
} /* HPSearchHotPluggables */
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop the hotplug thread
|
||||||
|
*/
|
||||||
|
LONG HPStopHotPluggables(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (driverSize <= 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!Udev)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
pthread_cancel(usbNotifyThread);
|
||||||
|
pthread_join(usbNotifyThread, NULL);
|
||||||
|
|
||||||
|
for (i=0; i<driverSize; i++)
|
||||||
|
{
|
||||||
|
/* free strings allocated by strdup() */
|
||||||
|
free(driverTracker[i].bundleName);
|
||||||
|
free(driverTracker[i].libraryPath);
|
||||||
|
free(driverTracker[i].readerName);
|
||||||
|
}
|
||||||
|
free(driverTracker);
|
||||||
|
|
||||||
|
udev_unref(Udev);
|
||||||
|
|
||||||
|
Udev = NULL;
|
||||||
|
driverSize = -1;
|
||||||
|
|
||||||
|
Log1(PCSC_LOG_INFO, "Hotplug stopped");
|
||||||
|
return 0;
|
||||||
|
} /* HPStopHotPluggables */
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets up callbacks for device hotplug events.
|
||||||
|
*/
|
||||||
|
ULONG HPRegisterForHotplugEvents(void)
|
||||||
|
{
|
||||||
|
struct udev_monitor *udev_monitor;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (driverSize <= 0)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_INFO, "No bundle files in pcsc drivers directory: "
|
||||||
|
PCSCLITE_HP_DROPDIR);
|
||||||
|
Log1(PCSC_LOG_INFO, "Disabling USB support for pcscd");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create the udev object */
|
||||||
|
Udev = udev_new();
|
||||||
|
if (!Udev)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_ERROR, "udev_new() failed");
|
||||||
|
return SCARD_F_INTERNAL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
udev_monitor = udev_monitor_new_from_netlink(Udev, "udev");
|
||||||
|
if (NULL == udev_monitor)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_ERROR, "udev_monitor_new_from_netlink() error");
|
||||||
|
pthread_exit(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* filter only the interfaces */
|
||||||
|
r = udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "usb",
|
||||||
|
"usb_interface");
|
||||||
|
if (r)
|
||||||
|
{
|
||||||
|
Log2(PCSC_LOG_ERROR, "udev_monitor_filter_add_match_subsystem_devtype() error: %d\n", r);
|
||||||
|
pthread_exit(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
r = udev_monitor_enable_receiving(udev_monitor);
|
||||||
|
if (r)
|
||||||
|
{
|
||||||
|
Log2(PCSC_LOG_ERROR, "udev_monitor_enable_receiving() error: %d\n", r);
|
||||||
|
pthread_exit(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* scan the USB bus at least once before accepting client connections */
|
||||||
|
HPScanUSB(Udev);
|
||||||
|
|
||||||
|
if (ThreadCreate(&usbNotifyThread, 0,
|
||||||
|
(PCSCLITE_THREAD_FUNCTION( )) HPEstablishUSBNotifications, udev_monitor))
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_ERROR, "ThreadCreate() failed");
|
||||||
|
return SCARD_F_INTERNAL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
} /* HPRegisterForHotplugEvents */
|
||||||
|
|
||||||
|
|
||||||
|
void HPReCheckSerialReaders(void)
|
||||||
|
{
|
||||||
|
/* nothing to do here */
|
||||||
|
#ifdef DEBUG_HOTPLUG
|
||||||
|
Log0(PCSC_LOG_ERROR);
|
||||||
|
#endif
|
||||||
|
} /* HPReCheckSerialReaders */
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,660 @@
|
||||||
|
/*
|
||||||
|
* MUSCLE SmartCard Development ( http://pcsclite.alioth.debian.org/pcsclite.html )
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001-2004
|
||||||
|
* David Corcoran <corcoran@musclecard.com>
|
||||||
|
* Copyright (C) 2003-2011
|
||||||
|
* Ludovic Rousseau <ludovic.rousseau@free.fr>
|
||||||
|
* Copyright (C) 2003
|
||||||
|
* Toni Andjelkovic <toni@soth.at>
|
||||||
|
* Copyright (C) 2003-2004
|
||||||
|
* Damien Sauveron <damien.sauveron@labri.fr>
|
||||||
|
*
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. The name of the author may not be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief This provides a search API for hot pluggble devices.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#ifdef HAVE_LIBUSB
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <libusb.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
#include "misc.h"
|
||||||
|
#include "wintypes.h"
|
||||||
|
#include "pcscd.h"
|
||||||
|
#include "debuglog.h"
|
||||||
|
#include "parser.h"
|
||||||
|
#include "readerfactory.h"
|
||||||
|
#include "winscard_msg.h"
|
||||||
|
#include "sys_generic.h"
|
||||||
|
#include "hotplug.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
#undef DEBUG_HOTPLUG
|
||||||
|
|
||||||
|
/* format is "%d:%d:%d", bus_number, device_address, interface */
|
||||||
|
#define BUS_DEVICE_STRSIZE 10+1+10+1+10+1
|
||||||
|
|
||||||
|
#define READER_ABSENT 0
|
||||||
|
#define READER_PRESENT 1
|
||||||
|
#define READER_FAILED 2
|
||||||
|
|
||||||
|
#define FALSE 0
|
||||||
|
#define TRUE 1
|
||||||
|
|
||||||
|
extern char Add_Serial_In_Name;
|
||||||
|
|
||||||
|
/* we use the default libusb context */
|
||||||
|
#define ctx NULL
|
||||||
|
|
||||||
|
pthread_mutex_t usbNotifierMutex;
|
||||||
|
|
||||||
|
static pthread_t usbNotifyThread;
|
||||||
|
static int driverSize = -1;
|
||||||
|
static char AraKiriHotPlug = FALSE;
|
||||||
|
static int rescan_pipe[] = { -1, -1 };
|
||||||
|
extern int HPForceReaderPolling;
|
||||||
|
|
||||||
|
/* values of ifdCapabilities bits */
|
||||||
|
#define IFD_GENERATE_HOTPLUG 1
|
||||||
|
|
||||||
|
/**
|
||||||
|
* keep track of drivers in a dynamically allocated array
|
||||||
|
*/
|
||||||
|
static struct _driverTracker
|
||||||
|
{
|
||||||
|
unsigned int manuID;
|
||||||
|
unsigned int productID;
|
||||||
|
|
||||||
|
char *bundleName;
|
||||||
|
char *libraryPath;
|
||||||
|
char *readerName;
|
||||||
|
int ifdCapabilities;
|
||||||
|
} *driverTracker = NULL;
|
||||||
|
#define DRIVER_TRACKER_SIZE_STEP 8
|
||||||
|
|
||||||
|
/**
|
||||||
|
* keep track of PCSCLITE_MAX_READERS_CONTEXTS simultaneous readers
|
||||||
|
*/
|
||||||
|
static struct _readerTracker
|
||||||
|
{
|
||||||
|
char status;
|
||||||
|
char bus_device[BUS_DEVICE_STRSIZE]; /**< device name */
|
||||||
|
char *fullName; /**< full reader name (including serial number) */
|
||||||
|
} readerTracker[PCSCLITE_MAX_READERS_CONTEXTS];
|
||||||
|
|
||||||
|
static LONG HPAddHotPluggable(struct libusb_device *dev,
|
||||||
|
struct libusb_device_descriptor desc,
|
||||||
|
const char bus_device[], int interface,
|
||||||
|
struct _driverTracker *driver);
|
||||||
|
static LONG HPRemoveHotPluggable(int reader_index);
|
||||||
|
|
||||||
|
static LONG HPReadBundleValues(void)
|
||||||
|
{
|
||||||
|
LONG rv;
|
||||||
|
DIR *hpDir;
|
||||||
|
struct dirent *currFP = NULL;
|
||||||
|
char fullPath[FILENAME_MAX];
|
||||||
|
char fullLibPath[FILENAME_MAX];
|
||||||
|
int listCount = 0;
|
||||||
|
|
||||||
|
hpDir = opendir(PCSCLITE_HP_DROPDIR);
|
||||||
|
|
||||||
|
if (hpDir == NULL)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_ERROR, "Cannot open PC/SC drivers directory: " PCSCLITE_HP_DROPDIR);
|
||||||
|
Log1(PCSC_LOG_ERROR, "Disabling USB support for pcscd.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allocate a first array */
|
||||||
|
driverTracker = calloc(DRIVER_TRACKER_SIZE_STEP, sizeof(*driverTracker));
|
||||||
|
if (NULL == driverTracker)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_CRITICAL, "Not enough memory");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
driverSize = DRIVER_TRACKER_SIZE_STEP;
|
||||||
|
|
||||||
|
#define GET_KEY(key, values) \
|
||||||
|
rv = LTPBundleFindValueWithKey(&plist, key, values); \
|
||||||
|
if (rv) \
|
||||||
|
{ \
|
||||||
|
Log2(PCSC_LOG_ERROR, "Value/Key not defined for " key " in %s", \
|
||||||
|
fullPath); \
|
||||||
|
continue; \
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((currFP = readdir(hpDir)) != 0)
|
||||||
|
{
|
||||||
|
if (strstr(currFP->d_name, ".bundle") != 0)
|
||||||
|
{
|
||||||
|
unsigned int alias;
|
||||||
|
list_t plist, *values;
|
||||||
|
list_t *manuIDs, *productIDs, *readerNames;
|
||||||
|
char *libraryPath;
|
||||||
|
int ifdCapabilities;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The bundle exists - let's form a full path name and get the
|
||||||
|
* vendor and product ID's for this particular bundle
|
||||||
|
*/
|
||||||
|
snprintf(fullPath, sizeof(fullPath), "%s/%s/Contents/Info.plist",
|
||||||
|
PCSCLITE_HP_DROPDIR, currFP->d_name);
|
||||||
|
fullPath[sizeof(fullPath) - 1] = '\0';
|
||||||
|
|
||||||
|
rv = bundleParse(fullPath, &plist);
|
||||||
|
if (rv)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* get CFBundleExecutable */
|
||||||
|
GET_KEY(PCSCLITE_HP_LIBRKEY_NAME, &values)
|
||||||
|
libraryPath = list_get_at(values, 0);
|
||||||
|
(void)snprintf(fullLibPath, sizeof(fullLibPath),
|
||||||
|
"%s/%s/Contents/%s/%s",
|
||||||
|
PCSCLITE_HP_DROPDIR, currFP->d_name, PCSC_ARCH,
|
||||||
|
libraryPath);
|
||||||
|
fullLibPath[sizeof(fullLibPath) - 1] = '\0';
|
||||||
|
|
||||||
|
/* Get ifdCapabilities */
|
||||||
|
GET_KEY(PCSCLITE_HP_CPCTKEY_NAME, &values)
|
||||||
|
ifdCapabilities = strtol(list_get_at(values, 0), NULL, 16);
|
||||||
|
|
||||||
|
GET_KEY(PCSCLITE_HP_MANUKEY_NAME, &manuIDs)
|
||||||
|
GET_KEY(PCSCLITE_HP_PRODKEY_NAME, &productIDs)
|
||||||
|
GET_KEY(PCSCLITE_HP_NAMEKEY_NAME, &readerNames)
|
||||||
|
|
||||||
|
/* while we find a nth ifdVendorID in Info.plist */
|
||||||
|
for (alias=0; alias<list_size(manuIDs); alias++)
|
||||||
|
{
|
||||||
|
char *value;
|
||||||
|
|
||||||
|
/* variables entries */
|
||||||
|
value = list_get_at(manuIDs, alias);
|
||||||
|
driverTracker[listCount].manuID = strtol(value, NULL, 16);
|
||||||
|
|
||||||
|
value = list_get_at(productIDs, alias);
|
||||||
|
driverTracker[listCount].productID = strtol(value, NULL, 16);
|
||||||
|
|
||||||
|
driverTracker[listCount].readerName = strdup(list_get_at(readerNames, alias));
|
||||||
|
|
||||||
|
/* constant entries for a same driver */
|
||||||
|
driverTracker[listCount].bundleName = strdup(currFP->d_name);
|
||||||
|
driverTracker[listCount].libraryPath = strdup(fullLibPath);
|
||||||
|
driverTracker[listCount].ifdCapabilities = ifdCapabilities;
|
||||||
|
|
||||||
|
#ifdef DEBUG_HOTPLUG
|
||||||
|
Log2(PCSC_LOG_INFO, "Found driver for: %s",
|
||||||
|
driverTracker[listCount].readerName);
|
||||||
|
#endif
|
||||||
|
listCount++;
|
||||||
|
if (listCount >= driverSize)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* increase the array size */
|
||||||
|
driverSize += DRIVER_TRACKER_SIZE_STEP;
|
||||||
|
#ifdef DEBUG_HOTPLUG
|
||||||
|
Log2(PCSC_LOG_INFO,
|
||||||
|
"Increase driverTracker to %d entries", driverSize);
|
||||||
|
#endif
|
||||||
|
driverTracker = realloc(driverTracker,
|
||||||
|
driverSize * sizeof(*driverTracker));
|
||||||
|
if (NULL == driverTracker)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_CRITICAL, "Not enough memory");
|
||||||
|
driverSize = -1;
|
||||||
|
closedir(hpDir);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* clean the newly allocated entries */
|
||||||
|
for (i=driverSize-DRIVER_TRACKER_SIZE_STEP; i<driverSize; i++)
|
||||||
|
{
|
||||||
|
driverTracker[i].manuID = 0;
|
||||||
|
driverTracker[i].productID = 0;
|
||||||
|
driverTracker[i].bundleName = NULL;
|
||||||
|
driverTracker[i].libraryPath = NULL;
|
||||||
|
driverTracker[i].readerName = NULL;
|
||||||
|
driverTracker[i].ifdCapabilities = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bundleRelease(&plist);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
driverSize = listCount;
|
||||||
|
closedir(hpDir);
|
||||||
|
|
||||||
|
if (driverSize == 0)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_INFO, "No bundle files in pcsc drivers directory: " PCSCLITE_HP_DROPDIR);
|
||||||
|
Log1(PCSC_LOG_INFO, "Disabling USB support for pcscd");
|
||||||
|
}
|
||||||
|
#ifdef DEBUG_HOTPLUG
|
||||||
|
else
|
||||||
|
Log2(PCSC_LOG_INFO, "Found drivers for %d readers", listCount);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return driverSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void HPRescanUsbBus(void)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
char bus_device[BUS_DEVICE_STRSIZE];
|
||||||
|
libusb_device **devs, *dev;
|
||||||
|
ssize_t cnt;
|
||||||
|
|
||||||
|
for (i=0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
|
||||||
|
/* clear rollcall */
|
||||||
|
readerTracker[i].status = READER_ABSENT;
|
||||||
|
|
||||||
|
cnt = libusb_get_device_list(ctx, &devs);
|
||||||
|
if (cnt < 0)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_CRITICAL, "libusb_get_device_list() failed\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* For each USB device */
|
||||||
|
cnt = 0;
|
||||||
|
while ((dev = devs[cnt++]) != NULL)
|
||||||
|
{
|
||||||
|
struct libusb_device_descriptor desc;
|
||||||
|
struct libusb_config_descriptor *config_desc;
|
||||||
|
uint8_t bus_number = libusb_get_bus_number(dev);
|
||||||
|
uint8_t device_address = libusb_get_device_address(dev);
|
||||||
|
|
||||||
|
int r = libusb_get_device_descriptor(dev, &desc);
|
||||||
|
if (r < 0)
|
||||||
|
{
|
||||||
|
Log3(PCSC_LOG_ERROR, "failed to get device descriptor for %d/%d",
|
||||||
|
bus_number, device_address);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = libusb_get_active_config_descriptor(dev, &config_desc);
|
||||||
|
if (r < 0)
|
||||||
|
{
|
||||||
|
Log3(PCSC_LOG_ERROR, "failed to get device config for %d/%d",
|
||||||
|
bus_number, device_address);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check if the device is supported by one driver */
|
||||||
|
for (i=0; i<driverSize; i++)
|
||||||
|
{
|
||||||
|
if (driverTracker[i].libraryPath != NULL &&
|
||||||
|
desc.idVendor == driverTracker[i].manuID &&
|
||||||
|
desc.idProduct == driverTracker[i].productID)
|
||||||
|
{
|
||||||
|
int interface;
|
||||||
|
|
||||||
|
#ifdef DEBUG_HOTPLUG
|
||||||
|
Log3(PCSC_LOG_DEBUG, "Found matching USB device: %d:%d",
|
||||||
|
bus_number, device_address);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (interface = 0; interface < config_desc->bNumInterfaces;
|
||||||
|
interface++)
|
||||||
|
{
|
||||||
|
int newreader;
|
||||||
|
|
||||||
|
/* A known device has been found */
|
||||||
|
snprintf(bus_device, BUS_DEVICE_STRSIZE, "%d:%d:%d",
|
||||||
|
bus_number, device_address, interface);
|
||||||
|
bus_device[BUS_DEVICE_STRSIZE - 1] = '\0';
|
||||||
|
newreader = TRUE;
|
||||||
|
|
||||||
|
/* Check if the reader is a new one */
|
||||||
|
for (j=0; j<PCSCLITE_MAX_READERS_CONTEXTS; j++)
|
||||||
|
{
|
||||||
|
if (strncmp(readerTracker[j].bus_device,
|
||||||
|
bus_device, BUS_DEVICE_STRSIZE) == 0)
|
||||||
|
{
|
||||||
|
/* The reader is already known */
|
||||||
|
readerTracker[j].status = READER_PRESENT;
|
||||||
|
newreader = FALSE;
|
||||||
|
#ifdef DEBUG_HOTPLUG
|
||||||
|
Log2(PCSC_LOG_DEBUG, "Refresh USB device: %s",
|
||||||
|
bus_device);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* New reader found */
|
||||||
|
if (newreader)
|
||||||
|
{
|
||||||
|
if (config_desc->bNumInterfaces > 1)
|
||||||
|
HPAddHotPluggable(dev, desc, bus_device,
|
||||||
|
interface, &driverTracker[i]);
|
||||||
|
else
|
||||||
|
HPAddHotPluggable(dev, desc, bus_device,
|
||||||
|
-1, &driverTracker[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
libusb_free_config_descriptor(config_desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* check if all the previously found readers are still present
|
||||||
|
*/
|
||||||
|
for (i=0; i<PCSCLITE_MAX_READERS_CONTEXTS; i++)
|
||||||
|
{
|
||||||
|
if ((readerTracker[i].status == READER_ABSENT) &&
|
||||||
|
(readerTracker[i].fullName != NULL))
|
||||||
|
HPRemoveHotPluggable(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (AraKiriHotPlug)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
for (i=0; i<driverSize; i++)
|
||||||
|
{
|
||||||
|
/* free strings allocated by strdup() */
|
||||||
|
free(driverTracker[i].bundleName);
|
||||||
|
free(driverTracker[i].libraryPath);
|
||||||
|
free(driverTracker[i].readerName);
|
||||||
|
}
|
||||||
|
free(driverTracker);
|
||||||
|
|
||||||
|
Log1(PCSC_LOG_INFO, "Hotplug stopped");
|
||||||
|
pthread_exit(&retval);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* free the libusb allocated list & devices */
|
||||||
|
libusb_free_device_list(devs, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void HPEstablishUSBNotifications(int pipefd[2])
|
||||||
|
{
|
||||||
|
int i, do_polling;
|
||||||
|
int r;
|
||||||
|
char c = 42; /* magic value */
|
||||||
|
|
||||||
|
r = libusb_init(ctx);
|
||||||
|
if (r < 0)
|
||||||
|
{
|
||||||
|
Log2(PCSC_LOG_CRITICAL, "libusb_init failed: %d", r);
|
||||||
|
/* emergency exit */
|
||||||
|
kill(getpid(), SIGTERM);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* scan the USB bus for devices at startup */
|
||||||
|
HPRescanUsbBus();
|
||||||
|
|
||||||
|
/* signal that the initially connected readers are now visible */
|
||||||
|
write(pipefd[1], &c, 1);
|
||||||
|
|
||||||
|
/* if at least one driver do not have IFD_GENERATE_HOTPLUG */
|
||||||
|
do_polling = FALSE;
|
||||||
|
for (i=0; i<driverSize; i++)
|
||||||
|
if (driverTracker[i].libraryPath)
|
||||||
|
if ((driverTracker[i].ifdCapabilities & IFD_GENERATE_HOTPLUG) == 0)
|
||||||
|
{
|
||||||
|
Log2(PCSC_LOG_INFO,
|
||||||
|
"Driver %s does not support IFD_GENERATE_HOTPLUG. Using active polling instead.",
|
||||||
|
driverTracker[i].bundleName);
|
||||||
|
if (HPForceReaderPolling < 1)
|
||||||
|
HPForceReaderPolling = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HPForceReaderPolling)
|
||||||
|
{
|
||||||
|
Log2(PCSC_LOG_INFO,
|
||||||
|
"Polling forced every %d second(s)", HPForceReaderPolling);
|
||||||
|
do_polling = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (do_polling)
|
||||||
|
{
|
||||||
|
while (!AraKiriHotPlug)
|
||||||
|
{
|
||||||
|
SYS_Sleep(HPForceReaderPolling);
|
||||||
|
HPRescanUsbBus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char dummy;
|
||||||
|
|
||||||
|
pipe(rescan_pipe);
|
||||||
|
while (read(rescan_pipe[0], &dummy, sizeof(dummy)) > 0)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_INFO, "Reload serial configuration");
|
||||||
|
HPRescanUsbBus();
|
||||||
|
#ifdef USE_SERIAL
|
||||||
|
RFReCheckReaderConf();
|
||||||
|
#endif
|
||||||
|
Log1(PCSC_LOG_INFO, "End reload serial configuration");
|
||||||
|
}
|
||||||
|
close(rescan_pipe[0]);
|
||||||
|
rescan_pipe[0] = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LONG HPSearchHotPluggables(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i=0; i<PCSCLITE_MAX_READERS_CONTEXTS; i++)
|
||||||
|
{
|
||||||
|
readerTracker[i].status = READER_ABSENT;
|
||||||
|
readerTracker[i].bus_device[0] = '\0';
|
||||||
|
readerTracker[i].fullName = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HPReadBundleValues() > 0)
|
||||||
|
{
|
||||||
|
int pipefd[2];
|
||||||
|
char c;
|
||||||
|
|
||||||
|
if (pipe(pipefd) == -1)
|
||||||
|
{
|
||||||
|
Log2(PCSC_LOG_ERROR, "pipe: %s", strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ThreadCreate(&usbNotifyThread, THREAD_ATTR_DETACHED,
|
||||||
|
(PCSCLITE_THREAD_FUNCTION( )) HPEstablishUSBNotifications, pipefd);
|
||||||
|
|
||||||
|
/* Wait for initial readers to setup */
|
||||||
|
read(pipefd[0], &c, 1);
|
||||||
|
|
||||||
|
/* cleanup pipe fd */
|
||||||
|
close(pipefd[0]);
|
||||||
|
close(pipefd[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
LONG HPStopHotPluggables(void)
|
||||||
|
{
|
||||||
|
AraKiriHotPlug = TRUE;
|
||||||
|
if (rescan_pipe[1] >= 0)
|
||||||
|
{
|
||||||
|
close(rescan_pipe[1]);
|
||||||
|
rescan_pipe[1] = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static LONG HPAddHotPluggable(struct libusb_device *dev,
|
||||||
|
struct libusb_device_descriptor desc,
|
||||||
|
const char bus_device[], int interface,
|
||||||
|
struct _driverTracker *driver)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char deviceName[MAX_DEVICENAME];
|
||||||
|
|
||||||
|
Log2(PCSC_LOG_INFO, "Adding USB device: %s", bus_device);
|
||||||
|
|
||||||
|
if (interface >= 0)
|
||||||
|
snprintf(deviceName, sizeof(deviceName), "usb:%04x/%04x:libhal:/org/freedesktop/Hal/devices/usb_device_%04x_%04x_serialnotneeded_if%d",
|
||||||
|
desc.idVendor, desc.idProduct, desc.idVendor, desc.idProduct,
|
||||||
|
interface);
|
||||||
|
else
|
||||||
|
snprintf(deviceName, sizeof(deviceName), "usb:%04x/%04x:libusb-1.0:%s",
|
||||||
|
desc.idVendor, desc.idProduct, bus_device);
|
||||||
|
|
||||||
|
deviceName[sizeof(deviceName) -1] = '\0';
|
||||||
|
|
||||||
|
pthread_mutex_lock(&usbNotifierMutex);
|
||||||
|
|
||||||
|
/* find a free entry */
|
||||||
|
for (i=0; i<PCSCLITE_MAX_READERS_CONTEXTS; i++)
|
||||||
|
{
|
||||||
|
if (readerTracker[i].fullName == NULL)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i==PCSCLITE_MAX_READERS_CONTEXTS)
|
||||||
|
{
|
||||||
|
Log2(PCSC_LOG_ERROR,
|
||||||
|
"Not enough reader entries. Already found %d readers", i);
|
||||||
|
pthread_mutex_unlock(&usbNotifierMutex);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
strncpy(readerTracker[i].bus_device, bus_device,
|
||||||
|
sizeof(readerTracker[i].bus_device));
|
||||||
|
readerTracker[i].bus_device[sizeof(readerTracker[i].bus_device) - 1] = '\0';
|
||||||
|
|
||||||
|
if (Add_Serial_In_Name && desc.iSerialNumber)
|
||||||
|
{
|
||||||
|
libusb_device_handle *device;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = libusb_open(dev, &device);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
Log2(PCSC_LOG_ERROR, "libusb_open failed: %d", ret);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unsigned char serialNumber[MAX_READERNAME];
|
||||||
|
|
||||||
|
ret = libusb_get_string_descriptor_ascii(device, desc.iSerialNumber,
|
||||||
|
serialNumber, MAX_READERNAME);
|
||||||
|
libusb_close(device);
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
Log2(PCSC_LOG_ERROR,
|
||||||
|
"libusb_get_string_descriptor_ascii failed: %d", ret);
|
||||||
|
readerTracker[i].fullName = strdup(driver->readerName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char fullname[MAX_READERNAME];
|
||||||
|
|
||||||
|
snprintf(fullname, sizeof(fullname), "%s (%s)",
|
||||||
|
driver->readerName, serialNumber);
|
||||||
|
readerTracker[i].fullName = strdup(fullname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
readerTracker[i].fullName = strdup(driver->readerName);
|
||||||
|
|
||||||
|
if (RFAddReader(readerTracker[i].fullName, PCSCLITE_HP_BASE_PORT + i,
|
||||||
|
driver->libraryPath, deviceName) == SCARD_S_SUCCESS)
|
||||||
|
readerTracker[i].status = READER_PRESENT;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
readerTracker[i].status = READER_FAILED;
|
||||||
|
|
||||||
|
(void)CheckForOpenCT();
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&usbNotifierMutex);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
} /* End of function */
|
||||||
|
|
||||||
|
static LONG HPRemoveHotPluggable(int reader_index)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&usbNotifierMutex);
|
||||||
|
|
||||||
|
Log3(PCSC_LOG_INFO, "Removing USB device[%d]: %s", reader_index,
|
||||||
|
readerTracker[reader_index].bus_device);
|
||||||
|
|
||||||
|
RFRemoveReader(readerTracker[reader_index].fullName,
|
||||||
|
PCSCLITE_HP_BASE_PORT + reader_index);
|
||||||
|
free(readerTracker[reader_index].fullName);
|
||||||
|
readerTracker[reader_index].status = READER_ABSENT;
|
||||||
|
readerTracker[reader_index].bus_device[0] = '\0';
|
||||||
|
readerTracker[reader_index].fullName = NULL;
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&usbNotifierMutex);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
} /* End of function */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets up callbacks for device hotplug events.
|
||||||
|
*/
|
||||||
|
ULONG HPRegisterForHotplugEvents(void)
|
||||||
|
{
|
||||||
|
(void)pthread_mutex_init(&usbNotifierMutex, NULL);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HPReCheckSerialReaders(void)
|
||||||
|
{
|
||||||
|
Log0(PCSC_LOG_INFO);
|
||||||
|
if (rescan_pipe[1] >= 0)
|
||||||
|
{
|
||||||
|
char dummy = 0;
|
||||||
|
write(rescan_pipe[1], &dummy, sizeof(dummy));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,472 @@
|
||||||
|
/*
|
||||||
|
* MUSCLE SmartCard Development ( http://pcsclite.alioth.debian.org/pcsclite.html )
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001-2003
|
||||||
|
* David Corcoran <corcoran@musclecard.com>
|
||||||
|
* Copyright (C) 2002-2011
|
||||||
|
* Ludovic Rousseau <ludovic.rousseau@free.fr>
|
||||||
|
*
|
||||||
|
* The USB code was based partly on Johannes Erdfelt
|
||||||
|
* libusb code found at libusb.sourceforge.net
|
||||||
|
*
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. The name of the author may not be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief This provides a search API for hot pluggble devices.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#if defined(__linux__) && !defined(HAVE_LIBUSB) && !defined(HAVE_LIBUDEV)
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
#include "misc.h"
|
||||||
|
#include "pcsclite.h"
|
||||||
|
#include "pcscd.h"
|
||||||
|
#include "debuglog.h"
|
||||||
|
#include "parser.h"
|
||||||
|
#include "readerfactory.h"
|
||||||
|
#include "winscard_msg.h"
|
||||||
|
#include "sys_generic.h"
|
||||||
|
#include "hotplug.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
#undef DEBUG_HOTPLUG
|
||||||
|
#define PCSCLITE_USB_PATH "/proc/bus/usb"
|
||||||
|
|
||||||
|
#define FALSE 0
|
||||||
|
#define TRUE 1
|
||||||
|
|
||||||
|
pthread_mutex_t usbNotifierMutex;
|
||||||
|
|
||||||
|
struct usb_device_descriptor
|
||||||
|
{
|
||||||
|
u_int8_t bLength;
|
||||||
|
u_int8_t bDescriptorType;
|
||||||
|
u_int16_t bcdUSB;
|
||||||
|
u_int8_t bDeviceClass;
|
||||||
|
u_int8_t bDeviceSubClass;
|
||||||
|
u_int8_t bDeviceProtocol;
|
||||||
|
u_int8_t bMaxPacketSize0;
|
||||||
|
u_int16_t idVendor;
|
||||||
|
u_int16_t idProduct;
|
||||||
|
u_int16_t bcdDevice;
|
||||||
|
u_int8_t iManufacturer;
|
||||||
|
u_int8_t iProduct;
|
||||||
|
u_int8_t iSerialNumber;
|
||||||
|
u_int8_t bNumConfigurations;
|
||||||
|
}
|
||||||
|
__attribute__ ((packed));
|
||||||
|
|
||||||
|
static LONG HPAddHotPluggable(int, unsigned long);
|
||||||
|
static LONG HPRemoveHotPluggable(int, unsigned long);
|
||||||
|
static LONG HPReadBundleValues(void);
|
||||||
|
static void HPEstablishUSBNotifications(void);
|
||||||
|
|
||||||
|
static pthread_t usbNotifyThread;
|
||||||
|
static int AraKiriHotPlug = FALSE;
|
||||||
|
static int bundleSize = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A list to keep track of 20 simultaneous readers
|
||||||
|
*/
|
||||||
|
static struct _bundleTracker
|
||||||
|
{
|
||||||
|
long manuID;
|
||||||
|
long productID;
|
||||||
|
|
||||||
|
struct _deviceNumber {
|
||||||
|
int id;
|
||||||
|
char status;
|
||||||
|
} deviceNumber[PCSCLITE_MAX_READERS_CONTEXTS];
|
||||||
|
|
||||||
|
char *bundleName;
|
||||||
|
char *libraryPath;
|
||||||
|
char *readerName;
|
||||||
|
}
|
||||||
|
bundleTracker[PCSCLITE_MAX_READERS_CONTEXTS];
|
||||||
|
|
||||||
|
static LONG HPReadBundleValues(void)
|
||||||
|
{
|
||||||
|
LONG rv;
|
||||||
|
DIR *hpDir;
|
||||||
|
struct dirent *currFP = 0;
|
||||||
|
char fullPath[FILENAME_MAX];
|
||||||
|
char fullLibPath[FILENAME_MAX];
|
||||||
|
unsigned int listCount = 0;
|
||||||
|
|
||||||
|
hpDir = opendir(PCSCLITE_HP_DROPDIR);
|
||||||
|
|
||||||
|
if (hpDir == NULL)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_INFO,
|
||||||
|
"Cannot open PC/SC drivers directory: " PCSCLITE_HP_DROPDIR);
|
||||||
|
Log1(PCSC_LOG_INFO, "Disabling USB support for pcscd.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define GET_KEY(key, values) \
|
||||||
|
rv = LTPBundleFindValueWithKey(&plist, key, values); \
|
||||||
|
if (rv) \
|
||||||
|
{ \
|
||||||
|
Log2(PCSC_LOG_ERROR, "Value/Key not defined for " key " in %s", \
|
||||||
|
fullPath); \
|
||||||
|
continue; \
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((currFP = readdir(hpDir)) != 0)
|
||||||
|
{
|
||||||
|
if (strstr(currFP->d_name, ".bundle") != 0)
|
||||||
|
{
|
||||||
|
unsigned int alias;
|
||||||
|
list_t plist, *values;
|
||||||
|
list_t *manuIDs, *productIDs, *readerNames;
|
||||||
|
char *libraryPath;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The bundle exists - let's form a full path name and get the
|
||||||
|
* vendor and product ID's for this particular bundle
|
||||||
|
*/
|
||||||
|
snprintf(fullPath, FILENAME_MAX, "%s/%s/Contents/Info.plist",
|
||||||
|
PCSCLITE_HP_DROPDIR, currFP->d_name);
|
||||||
|
fullPath[FILENAME_MAX - 1] = '\0';
|
||||||
|
|
||||||
|
rv = bundleParse(fullPath, &plist);
|
||||||
|
if (rv)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* get CFBundleExecutable */
|
||||||
|
GET_KEY(PCSCLITE_HP_LIBRKEY_NAME, &values)
|
||||||
|
libraryPath = list_get_at(values, 0);
|
||||||
|
(void)snprintf(fullLibPath, sizeof(fullLibPath),
|
||||||
|
"%s/%s/Contents/%s/%s",
|
||||||
|
PCSCLITE_HP_DROPDIR, currFP->d_name, PCSC_ARCH,
|
||||||
|
libraryPath);
|
||||||
|
fullLibPath[sizeof(fullLibPath) - 1] = '\0';
|
||||||
|
|
||||||
|
GET_KEY(PCSCLITE_HP_CPCTKEY_NAME, &values)
|
||||||
|
GET_KEY(PCSCLITE_HP_MANUKEY_NAME, &manuIDs)
|
||||||
|
GET_KEY(PCSCLITE_HP_PRODKEY_NAME, &productIDs)
|
||||||
|
GET_KEY(PCSCLITE_HP_NAMEKEY_NAME, &readerNames)
|
||||||
|
|
||||||
|
/* while we find a nth ifdVendorID in Info.plist */
|
||||||
|
for (alias=0; alias<list_size(manuIDs); alias++)
|
||||||
|
{
|
||||||
|
char *value;
|
||||||
|
|
||||||
|
/* variables entries */
|
||||||
|
value = list_get_at(manuIDs, alias);
|
||||||
|
bundleTracker[listCount].manuID = strtol(value, NULL, 16);
|
||||||
|
|
||||||
|
value = list_get_at(productIDs, alias);
|
||||||
|
bundleTracker[listCount].productID = strtol(value, NULL, 16);
|
||||||
|
|
||||||
|
bundleTracker[listCount].readerName = strdup(list_get_at(readerNames, alias));
|
||||||
|
|
||||||
|
/* constant entries for a same driver */
|
||||||
|
bundleTracker[listCount].bundleName = strdup(currFP->d_name);
|
||||||
|
bundleTracker[listCount].libraryPath = strdup(fullLibPath);
|
||||||
|
|
||||||
|
#ifdef DEBUG_HOTPLUG
|
||||||
|
Log2(PCSC_LOG_INFO, "Found driver for: %s",
|
||||||
|
bundleTracker[listCount].readerName);
|
||||||
|
#endif
|
||||||
|
listCount++;
|
||||||
|
|
||||||
|
if (listCount >= COUNT_OF(bundleTracker))
|
||||||
|
{
|
||||||
|
Log2(PCSC_LOG_CRITICAL, "Too many readers declared. Maximum is %zd", COUNT_OF(bundleTracker));
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bundleRelease(&plist);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
end:
|
||||||
|
bundleSize = listCount;
|
||||||
|
|
||||||
|
if (bundleSize == 0)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_INFO,
|
||||||
|
"No bundle files in pcsc drivers directory: " PCSCLITE_HP_DROPDIR);
|
||||||
|
Log1(PCSC_LOG_INFO, "Disabling USB support for pcscd");
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir(hpDir);
|
||||||
|
return bundleSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void HPEstablishUSBNotifications(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
int i, j, usbDeviceStatus;
|
||||||
|
DIR *dir, *dirB;
|
||||||
|
struct dirent *entry, *entryB;
|
||||||
|
int deviceNumber;
|
||||||
|
int suspectDeviceNumber;
|
||||||
|
char dirpath[FILENAME_MAX];
|
||||||
|
char filename[FILENAME_MAX];
|
||||||
|
int fd, ret;
|
||||||
|
struct usb_device_descriptor usbDescriptor;
|
||||||
|
|
||||||
|
usbDeviceStatus = 0;
|
||||||
|
suspectDeviceNumber = 0;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
for (i = 0; i < bundleSize; i++)
|
||||||
|
{
|
||||||
|
usbDeviceStatus = 0;
|
||||||
|
suspectDeviceNumber = 0;
|
||||||
|
|
||||||
|
for (j=0; j < PCSCLITE_MAX_READERS_CONTEXTS; j++)
|
||||||
|
/* clear rollcall */
|
||||||
|
bundleTracker[i].deviceNumber[j].status = 0;
|
||||||
|
|
||||||
|
dir = NULL;
|
||||||
|
dir = opendir(PCSCLITE_USB_PATH);
|
||||||
|
if (dir == NULL)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_ERROR,
|
||||||
|
"Cannot open USB path directory: " PCSCLITE_USB_PATH);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry = NULL;
|
||||||
|
while ((entry = readdir(dir)) != 0)
|
||||||
|
{
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Skip anything starting with a
|
||||||
|
*/
|
||||||
|
if (entry->d_name[0] == '.')
|
||||||
|
continue;
|
||||||
|
if (!strchr("0123456789",
|
||||||
|
entry->d_name[strlen(entry->d_name) - 1]))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(dirpath, sizeof dirpath, "%s/%s",
|
||||||
|
PCSCLITE_USB_PATH, entry->d_name);
|
||||||
|
|
||||||
|
dirB = opendir(dirpath);
|
||||||
|
|
||||||
|
if (dirB == NULL)
|
||||||
|
{
|
||||||
|
Log2(PCSC_LOG_ERROR,
|
||||||
|
"USB path seems to have disappeared %s", dirpath);
|
||||||
|
closedir(dir);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((entryB = readdir(dirB)) != NULL)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Skip anything starting with a
|
||||||
|
*/
|
||||||
|
if (entryB->d_name[0] == '.')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Get the device number so we can distinguish
|
||||||
|
multiple readers */
|
||||||
|
snprintf(filename, sizeof filename, "%s/%s",
|
||||||
|
dirpath, entryB->d_name);
|
||||||
|
deviceNumber = atoi(entryB->d_name);
|
||||||
|
|
||||||
|
fd = open(filename, O_RDONLY);
|
||||||
|
if (fd < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ret = read(fd, (void *) &usbDescriptor,
|
||||||
|
sizeof(usbDescriptor));
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Device is found and we don't know about it
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (usbDescriptor.idVendor == bundleTracker[i].manuID &&
|
||||||
|
usbDescriptor.idProduct == bundleTracker[i].productID &&
|
||||||
|
usbDescriptor.idVendor !=0 &&
|
||||||
|
usbDescriptor.idProduct != 0)
|
||||||
|
{
|
||||||
|
for (j=0; j < PCSCLITE_MAX_READERS_CONTEXTS; j++)
|
||||||
|
{
|
||||||
|
if (bundleTracker[i].deviceNumber[j].id == deviceNumber &&
|
||||||
|
bundleTracker[i].deviceNumber[j].id != 0)
|
||||||
|
{
|
||||||
|
bundleTracker[i].deviceNumber[j].status = 1; /* i'm here */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (j == PCSCLITE_MAX_READERS_CONTEXTS)
|
||||||
|
{
|
||||||
|
usbDeviceStatus = 1;
|
||||||
|
suspectDeviceNumber = deviceNumber;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* End of while */
|
||||||
|
|
||||||
|
closedir(dirB);
|
||||||
|
|
||||||
|
} /* End of while */
|
||||||
|
|
||||||
|
|
||||||
|
if (usbDeviceStatus == 1)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&usbNotifierMutex);
|
||||||
|
|
||||||
|
for (j=0; j < PCSCLITE_MAX_READERS_CONTEXTS; j++)
|
||||||
|
{
|
||||||
|
if (bundleTracker[i].deviceNumber[j].id == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (j == PCSCLITE_MAX_READERS_CONTEXTS)
|
||||||
|
Log1(PCSC_LOG_ERROR,
|
||||||
|
"Too many identical readers plugged in");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HPAddHotPluggable(i, j+1);
|
||||||
|
bundleTracker[i].deviceNumber[j].id = suspectDeviceNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&usbNotifierMutex);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (usbDeviceStatus == 0)
|
||||||
|
{
|
||||||
|
|
||||||
|
for (j=0; j < PCSCLITE_MAX_READERS_CONTEXTS; j++)
|
||||||
|
{
|
||||||
|
if (bundleTracker[i].deviceNumber[j].id != 0 &&
|
||||||
|
bundleTracker[i].deviceNumber[j].status == 0)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&usbNotifierMutex);
|
||||||
|
HPRemoveHotPluggable(i, j+1);
|
||||||
|
bundleTracker[i].deviceNumber[j].id = 0;
|
||||||
|
pthread_mutex_unlock(&usbNotifierMutex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Do nothing - no USB devices found
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dir)
|
||||||
|
closedir(dir);
|
||||||
|
|
||||||
|
} /* End of for..loop */
|
||||||
|
|
||||||
|
SYS_Sleep(1);
|
||||||
|
if (AraKiriHotPlug)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
Log1(PCSC_LOG_INFO, "Hotplug stopped");
|
||||||
|
pthread_exit(&retval);
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* End of while loop */
|
||||||
|
}
|
||||||
|
|
||||||
|
LONG HPSearchHotPluggables(void)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
|
||||||
|
{
|
||||||
|
bundleTracker[i].productID = 0;
|
||||||
|
bundleTracker[i].manuID = 0;
|
||||||
|
|
||||||
|
for (j=0; j < PCSCLITE_MAX_READERS_CONTEXTS; j++)
|
||||||
|
bundleTracker[i].deviceNumber[j].id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HPReadBundleValues() > 0)
|
||||||
|
ThreadCreate(&usbNotifyThread, THREAD_ATTR_DETACHED,
|
||||||
|
(PCSCLITE_THREAD_FUNCTION( )) HPEstablishUSBNotifications, 0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
LONG HPStopHotPluggables(void)
|
||||||
|
{
|
||||||
|
AraKiriHotPlug = TRUE;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static LONG HPAddHotPluggable(int i, unsigned long usbAddr)
|
||||||
|
{
|
||||||
|
/* NOTE: The deviceName is an empty string "" until someone implements
|
||||||
|
* the code to get it */
|
||||||
|
RFAddReader(bundleTracker[i].readerName, PCSCLITE_HP_BASE_PORT + usbAddr,
|
||||||
|
bundleTracker[i].libraryPath, "");
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
} /* End of function */
|
||||||
|
|
||||||
|
static LONG HPRemoveHotPluggable(int i, unsigned long usbAddr)
|
||||||
|
{
|
||||||
|
RFRemoveReader(bundleTracker[i].readerName, PCSCLITE_HP_BASE_PORT + usbAddr);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
} /* End of function */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets up callbacks for device hotplug events.
|
||||||
|
*/
|
||||||
|
ULONG HPRegisterForHotplugEvents(void)
|
||||||
|
{
|
||||||
|
(void)pthread_mutex_init(&usbNotifierMutex, NULL);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HPReCheckSerialReaders(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __linux__ && !HAVE_LIBUSB */
|
|
@ -0,0 +1,855 @@
|
||||||
|
/*
|
||||||
|
* MUSCLE SmartCard Development ( http://pcsclite.alioth.debian.org/pcsclite.html )
|
||||||
|
*
|
||||||
|
* Copyright (C) 2002-2004
|
||||||
|
* Stephen M. Webb <stephenw@cryptocard.com>
|
||||||
|
* Copyright (C) 2002-2011
|
||||||
|
* Ludovic Rousseau <ludovic.rousseau@free.fr>
|
||||||
|
* Copyright (C) 2002
|
||||||
|
* David Corcoran <corcoran@musclecard.com>
|
||||||
|
* Copyright (C) 2003
|
||||||
|
* Antti Tapaninen
|
||||||
|
*
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. The name of the author may not be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief This provides a search API for hot pluggble devices.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "misc.h"
|
||||||
|
#include "pcscd.h"
|
||||||
|
|
||||||
|
#if defined(__APPLE__) && !defined(HAVE_LIBUSB)
|
||||||
|
#include <CoreFoundation/CoreFoundation.h>
|
||||||
|
#include <IOKit/IOCFPlugIn.h>
|
||||||
|
#include <IOKit/IOKitLib.h>
|
||||||
|
#include <IOKit/usb/IOUSBLib.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "debuglog.h"
|
||||||
|
#include "parser.h"
|
||||||
|
#include "readerfactory.h"
|
||||||
|
#include "winscard_msg.h"
|
||||||
|
#include "utils.h"
|
||||||
|
#include "hotplug.h"
|
||||||
|
|
||||||
|
#undef DEBUG_HOTPLUG
|
||||||
|
|
||||||
|
/*
|
||||||
|
* An aggregation of useful information on a driver bundle in the
|
||||||
|
* drop directory.
|
||||||
|
*/
|
||||||
|
typedef struct HPDriver
|
||||||
|
{
|
||||||
|
UInt32 m_vendorId; /* unique vendor's manufacturer code */
|
||||||
|
UInt32 m_productId; /* manufacturer's unique product code */
|
||||||
|
char *m_friendlyName; /* bundle friendly name */
|
||||||
|
char *m_libPath; /* bundle's plugin library location */
|
||||||
|
} HPDriver, *HPDriverVector;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* An aggregation on information on currently active reader drivers.
|
||||||
|
*/
|
||||||
|
typedef struct HPDevice
|
||||||
|
{
|
||||||
|
HPDriver *m_driver; /* driver bundle information */
|
||||||
|
UInt32 m_address; /* unique system address of device */
|
||||||
|
struct HPDevice *m_next; /* next device in list */
|
||||||
|
} HPDevice, *HPDeviceList;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Pointer to a list of (currently) known hotplug reader devices (and their
|
||||||
|
* drivers).
|
||||||
|
*/
|
||||||
|
static HPDeviceList sDeviceList = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A callback to handle the asynchronous appearance of new devices that are
|
||||||
|
* candidates for PCSC readers.
|
||||||
|
*/
|
||||||
|
static void HPDeviceAppeared(void *refCon, io_iterator_t iterator)
|
||||||
|
{
|
||||||
|
kern_return_t kret;
|
||||||
|
io_service_t obj;
|
||||||
|
|
||||||
|
(void)refCon;
|
||||||
|
|
||||||
|
while ((obj = IOIteratorNext(iterator)))
|
||||||
|
kret = IOObjectRelease(obj);
|
||||||
|
|
||||||
|
HPSearchHotPluggables();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A callback to handle the asynchronous disappearance of devices that are
|
||||||
|
* possibly PCSC readers.
|
||||||
|
*/
|
||||||
|
static void HPDeviceDisappeared(void *refCon, io_iterator_t iterator)
|
||||||
|
{
|
||||||
|
kern_return_t kret;
|
||||||
|
io_service_t obj;
|
||||||
|
|
||||||
|
(void)refCon;
|
||||||
|
|
||||||
|
while ((obj = IOIteratorNext(iterator)))
|
||||||
|
kret = IOObjectRelease(obj);
|
||||||
|
|
||||||
|
HPSearchHotPluggables();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates a vector of driver bundle info structures from the hot-plug driver
|
||||||
|
* directory.
|
||||||
|
*
|
||||||
|
* Returns NULL on error and a pointer to an allocated HPDriver vector on
|
||||||
|
* success. The caller must free the HPDriver with a call to
|
||||||
|
* HPDriversRelease().
|
||||||
|
*/
|
||||||
|
static HPDriverVector HPDriversGetFromDirectory(const char *driverBundlePath)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_HOTPLUG
|
||||||
|
Log2(PCSC_LOG_DEBUG, "Entering HPDriversGetFromDirectory: %s",
|
||||||
|
driverBundlePath);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int readersNumber = 0;
|
||||||
|
HPDriverVector bundleVector = NULL;
|
||||||
|
CFArrayRef bundleArray;
|
||||||
|
CFStringRef driverBundlePathString =
|
||||||
|
CFStringCreateWithCString(kCFAllocatorDefault,
|
||||||
|
driverBundlePath,
|
||||||
|
kCFStringEncodingMacRoman);
|
||||||
|
CFURLRef pluginUrl = CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
|
||||||
|
driverBundlePathString,
|
||||||
|
kCFURLPOSIXPathStyle, TRUE);
|
||||||
|
|
||||||
|
CFRelease(driverBundlePathString);
|
||||||
|
if (!pluginUrl)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_ERROR, "error getting plugin directory URL");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
bundleArray = CFBundleCreateBundlesFromDirectory(kCFAllocatorDefault,
|
||||||
|
pluginUrl, NULL);
|
||||||
|
if (!bundleArray)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_ERROR, "error getting plugin directory bundles");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
CFRelease(pluginUrl);
|
||||||
|
|
||||||
|
size_t bundleArraySize = CFArrayGetCount(bundleArray);
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
/* get the number of readers (including aliases) */
|
||||||
|
for (i = 0; i < bundleArraySize; i++)
|
||||||
|
{
|
||||||
|
CFBundleRef currBundle =
|
||||||
|
(CFBundleRef) CFArrayGetValueAtIndex(bundleArray, i);
|
||||||
|
CFDictionaryRef dict = CFBundleGetInfoDictionary(currBundle);
|
||||||
|
|
||||||
|
const void * blobValue = CFDictionaryGetValue(dict,
|
||||||
|
CFSTR(PCSCLITE_HP_MANUKEY_NAME));
|
||||||
|
|
||||||
|
if (!blobValue)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_ERROR, "error getting vendor ID from bundle");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CFGetTypeID(blobValue) == CFArrayGetTypeID())
|
||||||
|
{
|
||||||
|
/* alias found, each reader count as 1 */
|
||||||
|
CFArrayRef propertyArray = blobValue;
|
||||||
|
readersNumber += CFArrayGetCount(propertyArray);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
/* No alias, only one reader supported */
|
||||||
|
readersNumber++;
|
||||||
|
}
|
||||||
|
#ifdef DEBUG_HOTPLUG
|
||||||
|
Log2(PCSC_LOG_DEBUG, "Total of %d readers supported", readersNumber);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* The last entry is an end marker (m_vendorId = 0)
|
||||||
|
* see checks in HPDriversMatchUSBDevices:503
|
||||||
|
* and HPDriverVectorRelease:376 */
|
||||||
|
readersNumber++;
|
||||||
|
|
||||||
|
bundleVector = calloc(readersNumber, sizeof(HPDriver));
|
||||||
|
if (!bundleVector)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_ERROR, "memory allocation failure");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
HPDriver *driverBundle = bundleVector;
|
||||||
|
for (i = 0; i < bundleArraySize; i++)
|
||||||
|
{
|
||||||
|
CFBundleRef currBundle =
|
||||||
|
(CFBundleRef) CFArrayGetValueAtIndex(bundleArray, i);
|
||||||
|
CFDictionaryRef dict = CFBundleGetInfoDictionary(currBundle);
|
||||||
|
|
||||||
|
CFURLRef bundleUrl = CFBundleCopyBundleURL(currBundle);
|
||||||
|
CFStringRef bundlePath = CFURLCopyPath(bundleUrl);
|
||||||
|
|
||||||
|
driverBundle->m_libPath = strdup(CFStringGetCStringPtr(bundlePath,
|
||||||
|
CFStringGetSystemEncoding()));
|
||||||
|
|
||||||
|
const void * blobValue = CFDictionaryGetValue(dict,
|
||||||
|
CFSTR(PCSCLITE_HP_MANUKEY_NAME));
|
||||||
|
|
||||||
|
if (!blobValue)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_ERROR, "error getting vendor ID from bundle");
|
||||||
|
return bundleVector;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CFGetTypeID(blobValue) == CFArrayGetTypeID())
|
||||||
|
{
|
||||||
|
CFArrayRef vendorArray = blobValue;
|
||||||
|
CFArrayRef productArray;
|
||||||
|
CFArrayRef friendlyNameArray;
|
||||||
|
char *libPath = driverBundle->m_libPath;
|
||||||
|
|
||||||
|
#ifdef DEBUG_HOTPLUG
|
||||||
|
Log2(PCSC_LOG_DEBUG, "Driver with aliases: %s", libPath);
|
||||||
|
#endif
|
||||||
|
/* get list of ProductID */
|
||||||
|
productArray = CFDictionaryGetValue(dict,
|
||||||
|
CFSTR(PCSCLITE_HP_PRODKEY_NAME));
|
||||||
|
if (!productArray)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_ERROR, "error getting product ID from bundle");
|
||||||
|
return bundleVector;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get list of FriendlyName */
|
||||||
|
friendlyNameArray = CFDictionaryGetValue(dict,
|
||||||
|
CFSTR(PCSCLITE_HP_NAMEKEY_NAME));
|
||||||
|
if (!friendlyNameArray)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_ERROR, "error getting product ID from bundle");
|
||||||
|
return bundleVector;
|
||||||
|
}
|
||||||
|
|
||||||
|
int reader_nb = CFArrayGetCount(vendorArray);
|
||||||
|
|
||||||
|
if (reader_nb != CFArrayGetCount(productArray))
|
||||||
|
{
|
||||||
|
Log3(PCSC_LOG_ERROR,
|
||||||
|
"Malformed Info.plist: %d vendors and %ld products",
|
||||||
|
reader_nb, CFArrayGetCount(productArray));
|
||||||
|
return bundleVector;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reader_nb != CFArrayGetCount(friendlyNameArray))
|
||||||
|
{
|
||||||
|
Log3(PCSC_LOG_ERROR,
|
||||||
|
"Malformed Info.plist: %d vendors and %ld friendlynames",
|
||||||
|
reader_nb, CFArrayGetCount(friendlyNameArray));
|
||||||
|
return bundleVector;
|
||||||
|
}
|
||||||
|
|
||||||
|
int j;
|
||||||
|
for (j=0; j<reader_nb; j++)
|
||||||
|
{
|
||||||
|
CFStringRef strValue = CFArrayGetValueAtIndex(vendorArray, j);
|
||||||
|
|
||||||
|
driverBundle->m_vendorId = strtoul(CFStringGetCStringPtr(strValue,
|
||||||
|
CFStringGetSystemEncoding()), NULL, 16);
|
||||||
|
|
||||||
|
strValue = CFArrayGetValueAtIndex(productArray, j);
|
||||||
|
driverBundle->m_productId = strtoul(CFStringGetCStringPtr(strValue,
|
||||||
|
CFStringGetSystemEncoding()), NULL, 16);
|
||||||
|
|
||||||
|
strValue = CFArrayGetValueAtIndex(friendlyNameArray, j);
|
||||||
|
const char *cstr = CFStringGetCStringPtr(strValue,
|
||||||
|
CFStringGetSystemEncoding());
|
||||||
|
|
||||||
|
driverBundle->m_friendlyName = strdup(cstr);
|
||||||
|
if (!driverBundle->m_libPath)
|
||||||
|
driverBundle->m_libPath = strdup(libPath);
|
||||||
|
|
||||||
|
#ifdef DEBUG_HOTPLUG
|
||||||
|
Log2(PCSC_LOG_DEBUG, "VendorID: 0x%04X",
|
||||||
|
driverBundle->m_vendorId);
|
||||||
|
Log2(PCSC_LOG_DEBUG, "ProductID: 0x%04X",
|
||||||
|
driverBundle->m_productId);
|
||||||
|
Log2(PCSC_LOG_DEBUG, "Friendly name: %s",
|
||||||
|
driverBundle->m_friendlyName);
|
||||||
|
Log2(PCSC_LOG_DEBUG, "Driver: %s", driverBundle->m_libPath);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* go to next bundle in the vector */
|
||||||
|
driverBundle++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CFStringRef strValue = blobValue;
|
||||||
|
|
||||||
|
#ifdef DEBUG_HOTPLUG
|
||||||
|
Log3(PCSC_LOG_DEBUG, "Driver without alias: %s %s",
|
||||||
|
driverBundle->m_friendlyName, driverBundle->m_libPath);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
driverBundle->m_vendorId = strtoul(CFStringGetCStringPtr(strValue,
|
||||||
|
CFStringGetSystemEncoding()), NULL, 16);
|
||||||
|
|
||||||
|
strValue = (CFStringRef) CFDictionaryGetValue(dict,
|
||||||
|
CFSTR(PCSCLITE_HP_PRODKEY_NAME));
|
||||||
|
if (!strValue)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_ERROR, "error getting product ID from bundle");
|
||||||
|
return bundleVector;
|
||||||
|
}
|
||||||
|
driverBundle->m_productId = strtoul(CFStringGetCStringPtr(strValue,
|
||||||
|
CFStringGetSystemEncoding()), NULL, 16);
|
||||||
|
|
||||||
|
strValue = (CFStringRef) CFDictionaryGetValue(dict,
|
||||||
|
CFSTR(PCSCLITE_HP_NAMEKEY_NAME));
|
||||||
|
if (!strValue)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_ERROR, "error getting product friendly name from bundle");
|
||||||
|
driverBundle->m_friendlyName = strdup("unnamed device");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const char *cstr = CFStringGetCStringPtr(strValue,
|
||||||
|
CFStringGetSystemEncoding());
|
||||||
|
|
||||||
|
driverBundle->m_friendlyName = strdup(cstr);
|
||||||
|
}
|
||||||
|
#ifdef DEBUG_HOTPLUG
|
||||||
|
Log2(PCSC_LOG_DEBUG, "VendorID: 0x%04X", driverBundle->m_vendorId);
|
||||||
|
Log2(PCSC_LOG_DEBUG, "ProductID: 0x%04X", driverBundle->m_productId);
|
||||||
|
Log2(PCSC_LOG_DEBUG, "Friendly name: %s", driverBundle->m_friendlyName);
|
||||||
|
Log2(PCSC_LOG_DEBUG, "Driver: %s", driverBundle->m_libPath);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* go to next bundle in the vector */
|
||||||
|
driverBundle++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CFRelease(bundleArray);
|
||||||
|
return bundleVector;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copies a driver bundle instance.
|
||||||
|
*/
|
||||||
|
static HPDriver *HPDriverCopy(HPDriver * rhs)
|
||||||
|
{
|
||||||
|
if (!rhs)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
HPDriver *newDriverBundle = calloc(1, sizeof(HPDriver));
|
||||||
|
|
||||||
|
if (!newDriverBundle)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
newDriverBundle->m_vendorId = rhs->m_vendorId;
|
||||||
|
newDriverBundle->m_productId = rhs->m_productId;
|
||||||
|
newDriverBundle->m_friendlyName = strdup(rhs->m_friendlyName);
|
||||||
|
newDriverBundle->m_libPath = strdup(rhs->m_libPath);
|
||||||
|
|
||||||
|
return newDriverBundle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Releases resources allocated to a driver bundle vector.
|
||||||
|
*/
|
||||||
|
static void HPDriverRelease(HPDriver * driverBundle)
|
||||||
|
{
|
||||||
|
if (driverBundle)
|
||||||
|
{
|
||||||
|
free(driverBundle->m_friendlyName);
|
||||||
|
free(driverBundle->m_libPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Releases resources allocated to a driver bundle vector.
|
||||||
|
*/
|
||||||
|
static void HPDriverVectorRelease(HPDriverVector driverBundleVector)
|
||||||
|
{
|
||||||
|
if (driverBundleVector)
|
||||||
|
{
|
||||||
|
HPDriver *b;
|
||||||
|
|
||||||
|
for (b = driverBundleVector; b->m_vendorId; ++b)
|
||||||
|
HPDriverRelease(b);
|
||||||
|
|
||||||
|
free(driverBundleVector);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Inserts a new reader device in the list.
|
||||||
|
*/
|
||||||
|
static HPDeviceList
|
||||||
|
HPDeviceListInsert(HPDeviceList list, HPDriver * bundle, UInt32 address)
|
||||||
|
{
|
||||||
|
HPDevice *newReader = calloc(1, sizeof(HPDevice));
|
||||||
|
|
||||||
|
if (!newReader)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_ERROR, "memory allocation failure");
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
newReader->m_driver = HPDriverCopy(bundle);
|
||||||
|
newReader->m_address = address;
|
||||||
|
newReader->m_next = list;
|
||||||
|
|
||||||
|
return newReader;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Frees resources allocated to a HPDeviceList.
|
||||||
|
*/
|
||||||
|
static void HPDeviceListRelease(HPDeviceList list)
|
||||||
|
{
|
||||||
|
HPDevice *p;
|
||||||
|
|
||||||
|
for (p = list; p; p = p->m_next)
|
||||||
|
HPDriverRelease(p->m_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compares two driver bundle instances for equality.
|
||||||
|
*/
|
||||||
|
static int HPDeviceEquals(HPDevice * a, HPDevice * b)
|
||||||
|
{
|
||||||
|
return (a->m_driver->m_vendorId == b->m_driver->m_vendorId)
|
||||||
|
&& (a->m_driver->m_productId == b->m_driver->m_productId)
|
||||||
|
&& (a->m_address == b->m_address);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Finds USB devices currently registered in the system that match any of
|
||||||
|
* the drivers detected in the driver bundle vector.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
HPDriversMatchUSBDevices(HPDriverVector driverBundle,
|
||||||
|
HPDeviceList * readerList)
|
||||||
|
{
|
||||||
|
CFDictionaryRef usbMatch = IOServiceMatching("IOUSBDevice");
|
||||||
|
|
||||||
|
if (0 == usbMatch)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_ERROR,
|
||||||
|
"error getting USB match from IOServiceMatching()");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
io_iterator_t usbIter;
|
||||||
|
kern_return_t kret = IOServiceGetMatchingServices(kIOMasterPortDefault,
|
||||||
|
usbMatch, &usbIter);
|
||||||
|
|
||||||
|
if (kret != 0)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_ERROR,
|
||||||
|
"error getting iterator from IOServiceGetMatchingServices()");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
IOIteratorReset(usbIter);
|
||||||
|
io_object_t usbDevice = 0;
|
||||||
|
|
||||||
|
while ((usbDevice = IOIteratorNext(usbIter)))
|
||||||
|
{
|
||||||
|
char namebuf[1024];
|
||||||
|
|
||||||
|
kret = IORegistryEntryGetName(usbDevice, namebuf);
|
||||||
|
if (kret != 0)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_ERROR,
|
||||||
|
"error getting device name from IORegistryEntryGetName()");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
IOCFPlugInInterface **iodev;
|
||||||
|
SInt32 score;
|
||||||
|
|
||||||
|
kret = IOCreatePlugInInterfaceForService(usbDevice,
|
||||||
|
kIOUSBDeviceUserClientTypeID,
|
||||||
|
kIOCFPlugInInterfaceID, &iodev, &score);
|
||||||
|
if (kret != 0)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_ERROR, "error getting plugin interface from IOCreatePlugInInterfaceForService()");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
IOObjectRelease(usbDevice);
|
||||||
|
|
||||||
|
IOUSBDeviceInterface **usbdev;
|
||||||
|
HRESULT hres = (*iodev)->QueryInterface(iodev,
|
||||||
|
CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID),
|
||||||
|
(LPVOID *) & usbdev);
|
||||||
|
|
||||||
|
(*iodev)->Release(iodev);
|
||||||
|
if (hres)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_ERROR,
|
||||||
|
"error querying interface in QueryInterface()");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
UInt16 vendorId = 0;
|
||||||
|
UInt16 productId = 0;
|
||||||
|
UInt32 usbAddress = 0;
|
||||||
|
|
||||||
|
kret = (*usbdev)->GetDeviceVendor(usbdev, &vendorId);
|
||||||
|
kret = (*usbdev)->GetDeviceProduct(usbdev, &productId);
|
||||||
|
kret = (*usbdev)->GetLocationID(usbdev, &usbAddress);
|
||||||
|
(*usbdev)->Release(usbdev);
|
||||||
|
|
||||||
|
#ifdef DEBUG_HOTPLUG
|
||||||
|
Log4(PCSC_LOG_DEBUG, "Found USB device 0x%04X:0x%04X at 0x%X",
|
||||||
|
vendorId, productId, usbAddress);
|
||||||
|
#endif
|
||||||
|
HPDriver *driver;
|
||||||
|
for (driver = driverBundle; driver->m_vendorId; ++driver)
|
||||||
|
{
|
||||||
|
if ((driver->m_vendorId == vendorId)
|
||||||
|
&& (driver->m_productId == productId))
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_HOTPLUG
|
||||||
|
Log4(PCSC_LOG_DEBUG, "Adding USB device %04X:%04X at 0x%X",
|
||||||
|
vendorId, productId, usbAddress);
|
||||||
|
#endif
|
||||||
|
*readerList =
|
||||||
|
HPDeviceListInsert(*readerList, driver, usbAddress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IOObjectRelease(usbIter);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Finds PC Card devices currently registered in the system that match any of
|
||||||
|
* the drivers detected in the driver bundle vector.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
HPDriversMatchPCCardDevices(HPDriver * driverBundle,
|
||||||
|
HPDeviceList * readerList)
|
||||||
|
{
|
||||||
|
CFDictionaryRef pccMatch = IOServiceMatching("IOPCCard16Device");
|
||||||
|
|
||||||
|
if (pccMatch == NULL)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_ERROR,
|
||||||
|
"error getting PCCard match from IOServiceMatching()");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
io_iterator_t pccIter;
|
||||||
|
kern_return_t kret =
|
||||||
|
IOServiceGetMatchingServices(kIOMasterPortDefault, pccMatch,
|
||||||
|
&pccIter);
|
||||||
|
if (kret != 0)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_ERROR,
|
||||||
|
"error getting iterator from IOServiceGetMatchingServices()");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
IOIteratorReset(pccIter);
|
||||||
|
io_object_t pccDevice = 0;
|
||||||
|
|
||||||
|
while ((pccDevice = IOIteratorNext(pccIter)))
|
||||||
|
{
|
||||||
|
char namebuf[1024];
|
||||||
|
|
||||||
|
kret = IORegistryEntryGetName(pccDevice, namebuf);
|
||||||
|
if (kret != 0)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_ERROR, "error getting plugin interface from IOCreatePlugInInterfaceForService()");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
UInt32 vendorId = 0;
|
||||||
|
UInt32 productId = 0;
|
||||||
|
UInt32 pccAddress = 0;
|
||||||
|
CFTypeRef valueRef =
|
||||||
|
IORegistryEntryCreateCFProperty(pccDevice, CFSTR("VendorID"),
|
||||||
|
kCFAllocatorDefault, 0);
|
||||||
|
|
||||||
|
if (!valueRef)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_ERROR, "error getting vendor");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CFNumberGetValue((CFNumberRef) valueRef, kCFNumberSInt32Type,
|
||||||
|
&vendorId);
|
||||||
|
}
|
||||||
|
valueRef =
|
||||||
|
IORegistryEntryCreateCFProperty(pccDevice, CFSTR("DeviceID"),
|
||||||
|
kCFAllocatorDefault, 0);
|
||||||
|
if (!valueRef)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_ERROR, "error getting device");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CFNumberGetValue((CFNumberRef) valueRef, kCFNumberSInt32Type,
|
||||||
|
&productId);
|
||||||
|
}
|
||||||
|
valueRef =
|
||||||
|
IORegistryEntryCreateCFProperty(pccDevice, CFSTR("SocketNumber"),
|
||||||
|
kCFAllocatorDefault, 0);
|
||||||
|
if (!valueRef)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_ERROR, "error getting PC Card socket");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CFNumberGetValue((CFNumberRef) valueRef, kCFNumberSInt32Type,
|
||||||
|
&pccAddress);
|
||||||
|
}
|
||||||
|
HPDriver *driver = driverBundle;
|
||||||
|
|
||||||
|
for (; driver->m_vendorId; ++driver)
|
||||||
|
{
|
||||||
|
if ((driver->m_vendorId == vendorId)
|
||||||
|
&& (driver->m_productId == productId))
|
||||||
|
{
|
||||||
|
*readerList =
|
||||||
|
HPDeviceListInsert(*readerList, driver, pccAddress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
IOObjectRelease(pccIter);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void HPEstablishUSBNotification(void)
|
||||||
|
{
|
||||||
|
io_iterator_t deviceAddedIterator;
|
||||||
|
io_iterator_t deviceRemovedIterator;
|
||||||
|
CFMutableDictionaryRef matchingDictionary;
|
||||||
|
IONotificationPortRef notificationPort;
|
||||||
|
IOReturn kret;
|
||||||
|
|
||||||
|
notificationPort = IONotificationPortCreate(kIOMasterPortDefault);
|
||||||
|
CFRunLoopAddSource(CFRunLoopGetCurrent(),
|
||||||
|
IONotificationPortGetRunLoopSource(notificationPort),
|
||||||
|
kCFRunLoopDefaultMode);
|
||||||
|
|
||||||
|
matchingDictionary = IOServiceMatching("IOUSBDevice");
|
||||||
|
if (!matchingDictionary)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_ERROR, "IOServiceMatching() failed");
|
||||||
|
}
|
||||||
|
matchingDictionary =
|
||||||
|
(CFMutableDictionaryRef) CFRetain(matchingDictionary);
|
||||||
|
|
||||||
|
kret = IOServiceAddMatchingNotification(notificationPort,
|
||||||
|
kIOMatchedNotification,
|
||||||
|
matchingDictionary, HPDeviceAppeared, NULL, &deviceAddedIterator);
|
||||||
|
if (kret)
|
||||||
|
{
|
||||||
|
Log2(PCSC_LOG_ERROR,
|
||||||
|
"IOServiceAddMatchingNotification()-1 failed with code %d", kret);
|
||||||
|
}
|
||||||
|
HPDeviceAppeared(NULL, deviceAddedIterator);
|
||||||
|
|
||||||
|
kret = IOServiceAddMatchingNotification(notificationPort,
|
||||||
|
kIOTerminatedNotification,
|
||||||
|
matchingDictionary,
|
||||||
|
HPDeviceDisappeared, NULL, &deviceRemovedIterator);
|
||||||
|
if (kret)
|
||||||
|
{
|
||||||
|
Log2(PCSC_LOG_ERROR,
|
||||||
|
"IOServiceAddMatchingNotification()-2 failed with code %d", kret);
|
||||||
|
}
|
||||||
|
HPDeviceDisappeared(NULL, deviceRemovedIterator);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void HPEstablishPCCardNotification(void)
|
||||||
|
{
|
||||||
|
io_iterator_t deviceAddedIterator;
|
||||||
|
io_iterator_t deviceRemovedIterator;
|
||||||
|
CFMutableDictionaryRef matchingDictionary;
|
||||||
|
IONotificationPortRef notificationPort;
|
||||||
|
IOReturn kret;
|
||||||
|
|
||||||
|
notificationPort = IONotificationPortCreate(kIOMasterPortDefault);
|
||||||
|
CFRunLoopAddSource(CFRunLoopGetCurrent(),
|
||||||
|
IONotificationPortGetRunLoopSource(notificationPort),
|
||||||
|
kCFRunLoopDefaultMode);
|
||||||
|
|
||||||
|
matchingDictionary = IOServiceMatching("IOPCCard16Device");
|
||||||
|
if (!matchingDictionary)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_ERROR, "IOServiceMatching() failed");
|
||||||
|
}
|
||||||
|
matchingDictionary =
|
||||||
|
(CFMutableDictionaryRef) CFRetain(matchingDictionary);
|
||||||
|
|
||||||
|
kret = IOServiceAddMatchingNotification(notificationPort,
|
||||||
|
kIOMatchedNotification,
|
||||||
|
matchingDictionary, HPDeviceAppeared, NULL, &deviceAddedIterator);
|
||||||
|
if (kret)
|
||||||
|
{
|
||||||
|
Log2(PCSC_LOG_ERROR,
|
||||||
|
"IOServiceAddMatchingNotification()-1 failed with code %d", kret);
|
||||||
|
}
|
||||||
|
HPDeviceAppeared(NULL, deviceAddedIterator);
|
||||||
|
|
||||||
|
kret = IOServiceAddMatchingNotification(notificationPort,
|
||||||
|
kIOTerminatedNotification,
|
||||||
|
matchingDictionary,
|
||||||
|
HPDeviceDisappeared, NULL, &deviceRemovedIterator);
|
||||||
|
if (kret)
|
||||||
|
{
|
||||||
|
Log2(PCSC_LOG_ERROR,
|
||||||
|
"IOServiceAddMatchingNotification()-2 failed with code %d", kret);
|
||||||
|
}
|
||||||
|
HPDeviceDisappeared(NULL, deviceRemovedIterator);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Thread runner (does not return).
|
||||||
|
*/
|
||||||
|
static void HPDeviceNotificationThread(void)
|
||||||
|
{
|
||||||
|
HPEstablishUSBNotification();
|
||||||
|
HPEstablishPCCardNotification();
|
||||||
|
CFRunLoopRun();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Scans the hotplug driver directory and looks in the system for
|
||||||
|
* matching devices.
|
||||||
|
* Adds or removes matching readers as necessary.
|
||||||
|
*/
|
||||||
|
LONG HPSearchHotPluggables(void)
|
||||||
|
{
|
||||||
|
HPDriver *drivers = HPDriversGetFromDirectory(PCSCLITE_HP_DROPDIR);
|
||||||
|
|
||||||
|
if (!drivers)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
HPDeviceList devices = NULL;
|
||||||
|
|
||||||
|
if (HPDriversMatchUSBDevices(drivers, &devices))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (HPDriversMatchPCCardDevices(drivers, &devices))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
HPDevice *a;
|
||||||
|
|
||||||
|
for (a = devices; a; a = a->m_next)
|
||||||
|
{
|
||||||
|
int found = FALSE;
|
||||||
|
HPDevice *b;
|
||||||
|
|
||||||
|
for (b = sDeviceList; b; b = b->m_next)
|
||||||
|
{
|
||||||
|
if (HPDeviceEquals(a, b))
|
||||||
|
{
|
||||||
|
found = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
char deviceName[MAX_DEVICENAME];
|
||||||
|
|
||||||
|
/* the format should be "usb:%04x/%04x" but Apple uses the
|
||||||
|
* friendly name instead */
|
||||||
|
snprintf(deviceName, sizeof(deviceName),
|
||||||
|
"%s", a->m_driver->m_friendlyName);
|
||||||
|
deviceName[sizeof(deviceName)-1] = '\0';
|
||||||
|
|
||||||
|
RFAddReader(a->m_driver->m_friendlyName,
|
||||||
|
PCSCLITE_HP_BASE_PORT + a->m_address, a->m_driver->m_libPath,
|
||||||
|
deviceName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (a = sDeviceList; a; a = a->m_next)
|
||||||
|
{
|
||||||
|
int found = FALSE;
|
||||||
|
HPDevice *b;
|
||||||
|
|
||||||
|
for (b = devices; b; b = b->m_next)
|
||||||
|
{
|
||||||
|
if (HPDeviceEquals(a, b))
|
||||||
|
{
|
||||||
|
found = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
RFRemoveReader(a->m_driver->m_friendlyName,
|
||||||
|
PCSCLITE_HP_BASE_PORT + a->m_address);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HPDeviceListRelease(sDeviceList);
|
||||||
|
sDeviceList = devices;
|
||||||
|
HPDriverVectorRelease(drivers);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pthread_t sHotplugWatcherThread;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sets up callbacks for device hotplug events.
|
||||||
|
*/
|
||||||
|
ULONG HPRegisterForHotplugEvents(void)
|
||||||
|
{
|
||||||
|
ThreadCreate(&sHotplugWatcherThread,
|
||||||
|
THREAD_ATTR_DEFAULT,
|
||||||
|
(PCSCLITE_THREAD_FUNCTION( )) HPDeviceNotificationThread, NULL);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
LONG HPStopHotPluggables(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HPReCheckSerialReaders(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __APPLE__ */
|
||||||
|
|
|
@ -0,0 +1,554 @@
|
||||||
|
/*
|
||||||
|
* MUSCLE SmartCard Development ( http://pcsclite.alioth.debian.org/pcsclite.html )
|
||||||
|
*
|
||||||
|
* Copyright (C) 1999-2004
|
||||||
|
* David Corcoran <corcoran@musclecard.com>
|
||||||
|
* Copyright (C) 2003-2004
|
||||||
|
* Damien Sauveron <damien.sauveron@labri.fr>
|
||||||
|
* Copyright (C) 2002-2011
|
||||||
|
* Ludovic Rousseau <ludovic.rousseau@free.fr>
|
||||||
|
*
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. The name of the author may not be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief This wraps the dynamic ifdhandler functions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "misc.h"
|
||||||
|
#include "pcscd.h"
|
||||||
|
#include "debuglog.h"
|
||||||
|
#include "readerfactory.h"
|
||||||
|
#include "ifdwrapper.h"
|
||||||
|
#include "atrhandler.h"
|
||||||
|
#include "dyn_generic.h"
|
||||||
|
#include "sys_generic.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
#ifdef PCSCLITE_STATIC_DRIVER
|
||||||
|
/* check that either IFDHANDLERv2 or IFDHANDLERv3 is
|
||||||
|
* defined */
|
||||||
|
#if ! (defined(IFDHANDLERv2) || defined(IFDHANDLERv3))
|
||||||
|
#error IFDHANDLER version not defined
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the protocol type selection (PTS).
|
||||||
|
* This function sets the appropriate protocol to be used on the card.
|
||||||
|
*/
|
||||||
|
LONG IFDSetPTS(READER_CONTEXT * rContext, DWORD dwProtocol, UCHAR ucFlags,
|
||||||
|
UCHAR ucPTS1, UCHAR ucPTS2, UCHAR ucPTS3)
|
||||||
|
{
|
||||||
|
RESPONSECODE rv;
|
||||||
|
|
||||||
|
#ifndef PCSCLITE_STATIC_DRIVER
|
||||||
|
RESPONSECODE(*IFDH_set_protocol_parameters) (DWORD, DWORD, UCHAR,
|
||||||
|
UCHAR, UCHAR, UCHAR) = NULL;
|
||||||
|
|
||||||
|
IFDH_set_protocol_parameters = (RESPONSECODE(*)(DWORD, DWORD, UCHAR,
|
||||||
|
UCHAR, UCHAR, UCHAR))
|
||||||
|
rContext->psFunctions.psFunctions_v2.pvfSetProtocolParameters;
|
||||||
|
|
||||||
|
if (NULL == IFDH_set_protocol_parameters)
|
||||||
|
return SCARD_E_UNSUPPORTED_FEATURE;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Locking is done in winscard.c SCardConnect() and SCardReconnect()
|
||||||
|
*
|
||||||
|
* This avoids to renegotiate the protocol and confuse the card
|
||||||
|
* Error returned by CCID driver is: CCID_Receive Procedure byte conflict
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PCSCLITE_STATIC_DRIVER
|
||||||
|
rv = (*IFDH_set_protocol_parameters) (rContext->slot,
|
||||||
|
dwProtocol, ucFlags, ucPTS1, ucPTS2, ucPTS3);
|
||||||
|
#else
|
||||||
|
rv = IFDHSetProtocolParameters(rContext->slot, dwProtocol, ucFlags,
|
||||||
|
ucPTS1, ucPTS2, ucPTS3);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open a communication channel to the IFD.
|
||||||
|
*/
|
||||||
|
LONG IFDOpenIFD(READER_CONTEXT * rContext)
|
||||||
|
{
|
||||||
|
RESPONSECODE rv = 0;
|
||||||
|
|
||||||
|
#ifndef PCSCLITE_STATIC_DRIVER
|
||||||
|
RESPONSECODE(*IFDH_create_channel) (DWORD, DWORD) = NULL;
|
||||||
|
RESPONSECODE(*IFDH_create_channel_by_name) (DWORD, LPSTR) = NULL;
|
||||||
|
|
||||||
|
if (rContext->version == IFD_HVERSION_2_0)
|
||||||
|
IFDH_create_channel =
|
||||||
|
rContext->psFunctions.psFunctions_v2.pvfCreateChannel;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
IFDH_create_channel =
|
||||||
|
rContext->psFunctions.psFunctions_v3.pvfCreateChannel;
|
||||||
|
IFDH_create_channel_by_name =
|
||||||
|
rContext->psFunctions.psFunctions_v3.pvfCreateChannelByName;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* LOCK THIS CODE REGION */
|
||||||
|
(void)pthread_mutex_lock(rContext->mMutex);
|
||||||
|
|
||||||
|
#ifndef PCSCLITE_STATIC_DRIVER
|
||||||
|
if (rContext->version == IFD_HVERSION_2_0)
|
||||||
|
{
|
||||||
|
rv = (*IFDH_create_channel) (rContext->slot, rContext->port);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
/* use device name only if defined */
|
||||||
|
if (rContext->device[0] != '\0')
|
||||||
|
rv = (*IFDH_create_channel_by_name) (rContext->slot, rContext->device);
|
||||||
|
else
|
||||||
|
rv = (*IFDH_create_channel) (rContext->slot, rContext->port);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#if defined(IFDHANDLERv2)
|
||||||
|
rv = IFDHCreateChannel(rContext->slot, rContext->port);
|
||||||
|
#else
|
||||||
|
{
|
||||||
|
/* Use device name only if defined */
|
||||||
|
if (rContext->device[0] != '\0')
|
||||||
|
rv = IFDHCreateChannelByName(rContext->slot, rContext->device);
|
||||||
|
else
|
||||||
|
rv = IFDHCreateChannel(rContext->slot, rContext->port);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* END OF LOCKED REGION */
|
||||||
|
(void)pthread_mutex_unlock(rContext->mMutex);
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close a communication channel to the IFD.
|
||||||
|
*/
|
||||||
|
LONG IFDCloseIFD(READER_CONTEXT * rContext)
|
||||||
|
{
|
||||||
|
RESPONSECODE rv;
|
||||||
|
int repeat;
|
||||||
|
|
||||||
|
#ifndef PCSCLITE_STATIC_DRIVER
|
||||||
|
RESPONSECODE(*IFDH_close_channel) (DWORD) = NULL;
|
||||||
|
|
||||||
|
IFDH_close_channel = rContext->psFunctions.psFunctions_v2.pvfCloseChannel;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* TRY TO LOCK THIS CODE REGION */
|
||||||
|
repeat = 5;
|
||||||
|
again:
|
||||||
|
rv = pthread_mutex_trylock(rContext->mMutex);
|
||||||
|
if (EBUSY == rv)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_ERROR, "Locking failed");
|
||||||
|
repeat--;
|
||||||
|
if (repeat)
|
||||||
|
{
|
||||||
|
(void)SYS_USleep(100*1000); /* 100 ms */
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef PCSCLITE_STATIC_DRIVER
|
||||||
|
rv = (*IFDH_close_channel) (rContext->slot);
|
||||||
|
#else
|
||||||
|
rv = IFDHCloseChannel(rContext->slot);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* END OF LOCKED REGION */
|
||||||
|
(void)pthread_mutex_unlock(rContext->mMutex);
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set capabilities in the reader.
|
||||||
|
*/
|
||||||
|
LONG IFDSetCapabilities(READER_CONTEXT * rContext, DWORD dwTag,
|
||||||
|
DWORD dwLength, PUCHAR pucValue)
|
||||||
|
{
|
||||||
|
RESPONSECODE rv;
|
||||||
|
|
||||||
|
#ifndef PCSCLITE_STATIC_DRIVER
|
||||||
|
RESPONSECODE(*IFDH_set_capabilities) (DWORD, DWORD, DWORD, PUCHAR) = NULL;
|
||||||
|
|
||||||
|
IFDH_set_capabilities = rContext->psFunctions.psFunctions_v2.pvfSetCapabilities;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Let the calling function lock this otherwise a deadlock will
|
||||||
|
* result
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PCSCLITE_STATIC_DRIVER
|
||||||
|
rv = (*IFDH_set_capabilities) (rContext->slot, dwTag,
|
||||||
|
dwLength, pucValue);
|
||||||
|
#else
|
||||||
|
rv = IFDHSetCapabilities(rContext->slot, dwTag, dwLength, pucValue);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get's capabilities in the reader.
|
||||||
|
* Other functions int this file will call
|
||||||
|
* the driver directly to not cause a deadlock.
|
||||||
|
*/
|
||||||
|
LONG IFDGetCapabilities(READER_CONTEXT * rContext, DWORD dwTag,
|
||||||
|
PDWORD pdwLength, PUCHAR pucValue)
|
||||||
|
{
|
||||||
|
RESPONSECODE rv;
|
||||||
|
|
||||||
|
#ifndef PCSCLITE_STATIC_DRIVER
|
||||||
|
RESPONSECODE(*IFDH_get_capabilities) (DWORD, DWORD, PDWORD, /*@out@*/ PUCHAR) = NULL;
|
||||||
|
|
||||||
|
IFDH_get_capabilities =
|
||||||
|
rContext->psFunctions.psFunctions_v2.pvfGetCapabilities;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* LOCK THIS CODE REGION */
|
||||||
|
(void)pthread_mutex_lock(rContext->mMutex);
|
||||||
|
|
||||||
|
#ifndef PCSCLITE_STATIC_DRIVER
|
||||||
|
rv = (*IFDH_get_capabilities) (rContext->slot, dwTag, pdwLength, pucValue);
|
||||||
|
#else
|
||||||
|
rv = IFDHGetCapabilities(rContext->slot, dwTag, pdwLength, pucValue);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* END OF LOCKED REGION */
|
||||||
|
(void)pthread_mutex_unlock(rContext->mMutex);
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Power up/down or reset's an ICC located in the IFD.
|
||||||
|
*/
|
||||||
|
LONG IFDPowerICC(READER_CONTEXT * rContext, DWORD dwAction,
|
||||||
|
PUCHAR pucAtr, PDWORD pdwAtrLen)
|
||||||
|
{
|
||||||
|
RESPONSECODE rv;
|
||||||
|
DWORD dwStatus;
|
||||||
|
UCHAR dummyAtr[MAX_ATR_SIZE];
|
||||||
|
DWORD dummyAtrLen = sizeof(dummyAtr);
|
||||||
|
|
||||||
|
#ifndef PCSCLITE_STATIC_DRIVER
|
||||||
|
RESPONSECODE(*IFDH_power_icc) (DWORD, DWORD, PUCHAR, PDWORD) = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Zero out everything
|
||||||
|
*/
|
||||||
|
dwStatus = 0;
|
||||||
|
|
||||||
|
if (NULL == pucAtr)
|
||||||
|
pucAtr = dummyAtr;
|
||||||
|
if (NULL == pdwAtrLen)
|
||||||
|
pdwAtrLen = &dummyAtrLen;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check that the card is inserted first
|
||||||
|
*/
|
||||||
|
rv = IFDStatusICC(rContext, &dwStatus);
|
||||||
|
if (rv != SCARD_S_SUCCESS)
|
||||||
|
return rv;
|
||||||
|
|
||||||
|
if (dwStatus & SCARD_ABSENT)
|
||||||
|
return SCARD_W_REMOVED_CARD;
|
||||||
|
#ifndef PCSCLITE_STATIC_DRIVER
|
||||||
|
IFDH_power_icc = rContext->psFunctions.psFunctions_v2.pvfPowerICC;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* LOCK THIS CODE REGION */
|
||||||
|
(void)pthread_mutex_lock(rContext->mMutex);
|
||||||
|
|
||||||
|
#ifndef PCSCLITE_STATIC_DRIVER
|
||||||
|
rv = (*IFDH_power_icc) (rContext->slot, dwAction, pucAtr, pdwAtrLen);
|
||||||
|
#else
|
||||||
|
rv = IFDHPowerICC(rContext->slot, dwAction, pucAtr, pdwAtrLen);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* END OF LOCKED REGION */
|
||||||
|
(void)pthread_mutex_unlock(rContext->mMutex);
|
||||||
|
|
||||||
|
/* use clean values in case of error */
|
||||||
|
if (rv != IFD_SUCCESS)
|
||||||
|
{
|
||||||
|
*pdwAtrLen = 0;
|
||||||
|
pucAtr[0] = '\0';
|
||||||
|
|
||||||
|
if (rv == IFD_NO_SUCH_DEVICE)
|
||||||
|
{
|
||||||
|
(void)SendHotplugSignal();
|
||||||
|
return SCARD_E_READER_UNAVAILABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SCARD_E_NOT_TRANSACTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide statistical information about the IFD and ICC including insertions,
|
||||||
|
* atr, powering status/etc.
|
||||||
|
*/
|
||||||
|
LONG IFDStatusICC(READER_CONTEXT * rContext, PDWORD pdwStatus)
|
||||||
|
{
|
||||||
|
RESPONSECODE rv;
|
||||||
|
DWORD dwCardStatus = 0;
|
||||||
|
|
||||||
|
#ifndef PCSCLITE_STATIC_DRIVER
|
||||||
|
RESPONSECODE(*IFDH_icc_presence) (DWORD) = NULL;
|
||||||
|
|
||||||
|
IFDH_icc_presence = rContext->psFunctions.psFunctions_v2.pvfICCPresence;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* LOCK THIS CODE REGION */
|
||||||
|
(void)pthread_mutex_lock(rContext->mMutex);
|
||||||
|
|
||||||
|
#ifndef PCSCLITE_STATIC_DRIVER
|
||||||
|
rv = (*IFDH_icc_presence) (rContext->slot);
|
||||||
|
#else
|
||||||
|
rv = IFDHICCPresence(rContext->slot);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* END OF LOCKED REGION */
|
||||||
|
(void)pthread_mutex_unlock(rContext->mMutex);
|
||||||
|
|
||||||
|
if (rv == IFD_SUCCESS || rv == IFD_ICC_PRESENT)
|
||||||
|
dwCardStatus |= SCARD_PRESENT;
|
||||||
|
else
|
||||||
|
if (rv == IFD_ICC_NOT_PRESENT)
|
||||||
|
dwCardStatus |= SCARD_ABSENT;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log2(PCSC_LOG_ERROR, "Card not transacted: %ld", rv);
|
||||||
|
*pdwStatus = SCARD_UNKNOWN;
|
||||||
|
|
||||||
|
if (rv == IFD_NO_SUCH_DEVICE)
|
||||||
|
{
|
||||||
|
(void)SendHotplugSignal();
|
||||||
|
return SCARD_E_READER_UNAVAILABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SCARD_E_NOT_TRANSACTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
*pdwStatus = dwCardStatus;
|
||||||
|
|
||||||
|
return SCARD_S_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Function: IFDControl Purpose : This function provides a means for
|
||||||
|
* toggling a specific action on the reader such as swallow, eject,
|
||||||
|
* biometric.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Valid only for IFDHandler version 2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
LONG IFDControl_v2(READER_CONTEXT * rContext, PUCHAR TxBuffer,
|
||||||
|
DWORD TxLength, PUCHAR RxBuffer, PDWORD RxLength)
|
||||||
|
{
|
||||||
|
RESPONSECODE rv = IFD_SUCCESS;
|
||||||
|
|
||||||
|
#ifndef PCSCLITE_STATIC_DRIVER
|
||||||
|
RESPONSECODE(*IFDH_control_v2) (DWORD, PUCHAR, DWORD, /*@out@*/ PUCHAR,
|
||||||
|
PDWORD);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (rContext->version != IFD_HVERSION_2_0)
|
||||||
|
return SCARD_E_UNSUPPORTED_FEATURE;
|
||||||
|
|
||||||
|
#ifndef PCSCLITE_STATIC_DRIVER
|
||||||
|
IFDH_control_v2 = rContext->psFunctions.psFunctions_v2.pvfControl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* LOCK THIS CODE REGION */
|
||||||
|
(void)pthread_mutex_lock(rContext->mMutex);
|
||||||
|
|
||||||
|
#ifndef PCSCLITE_STATIC_DRIVER
|
||||||
|
rv = (*IFDH_control_v2) (rContext->slot, TxBuffer, TxLength,
|
||||||
|
RxBuffer, RxLength);
|
||||||
|
#elif defined(IFDHANDLERv2)
|
||||||
|
rv = IFDHControl(rContext->slot, TxBuffer, TxLength,
|
||||||
|
RxBuffer, RxLength);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* END OF LOCKED REGION */
|
||||||
|
(void)pthread_mutex_unlock(rContext->mMutex);
|
||||||
|
|
||||||
|
if (rv == IFD_SUCCESS)
|
||||||
|
return SCARD_S_SUCCESS;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log2(PCSC_LOG_ERROR, "Card not transacted: %ld", rv);
|
||||||
|
LogXxd(PCSC_LOG_DEBUG, "TxBuffer ", TxBuffer, TxLength);
|
||||||
|
LogXxd(PCSC_LOG_DEBUG, "RxBuffer ", RxBuffer, *RxLength);
|
||||||
|
return SCARD_E_NOT_TRANSACTED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide a means for toggling a specific action on the reader such as
|
||||||
|
* swallow, eject, biometric.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Valid only for IFDHandler version 3.0 and up
|
||||||
|
*/
|
||||||
|
|
||||||
|
LONG IFDControl(READER_CONTEXT * rContext, DWORD ControlCode,
|
||||||
|
LPCVOID TxBuffer, DWORD TxLength, LPVOID RxBuffer, DWORD RxLength,
|
||||||
|
LPDWORD BytesReturned)
|
||||||
|
{
|
||||||
|
RESPONSECODE rv = IFD_SUCCESS;
|
||||||
|
|
||||||
|
#ifndef PCSCLITE_STATIC_DRIVER
|
||||||
|
RESPONSECODE(*IFDH_control) (DWORD, DWORD, LPCVOID, DWORD, LPVOID, DWORD, LPDWORD);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (rContext->version < IFD_HVERSION_3_0)
|
||||||
|
return SCARD_E_UNSUPPORTED_FEATURE;
|
||||||
|
|
||||||
|
#ifndef PCSCLITE_STATIC_DRIVER
|
||||||
|
IFDH_control = rContext->psFunctions.psFunctions_v3.pvfControl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* LOCK THIS CODE REGION */
|
||||||
|
(void)pthread_mutex_lock(rContext->mMutex);
|
||||||
|
|
||||||
|
#ifndef PCSCLITE_STATIC_DRIVER
|
||||||
|
rv = (*IFDH_control) (rContext->slot, ControlCode, TxBuffer,
|
||||||
|
TxLength, RxBuffer, RxLength, BytesReturned);
|
||||||
|
#elif defined(IFDHANDLERv3)
|
||||||
|
rv = IFDHControl(rContext->slot, ControlCode, TxBuffer,
|
||||||
|
TxLength, RxBuffer, RxLength, BytesReturned);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* END OF LOCKED REGION */
|
||||||
|
(void)pthread_mutex_unlock(rContext->mMutex);
|
||||||
|
|
||||||
|
if (rv == IFD_SUCCESS)
|
||||||
|
return SCARD_S_SUCCESS;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log2(PCSC_LOG_ERROR, "Card not transacted: %ld", rv);
|
||||||
|
Log3(PCSC_LOG_DEBUG, "ControlCode: 0x%.8lX BytesReturned: %ld",
|
||||||
|
ControlCode, *BytesReturned);
|
||||||
|
LogXxd(PCSC_LOG_DEBUG, "TxBuffer ", TxBuffer, TxLength);
|
||||||
|
LogXxd(PCSC_LOG_DEBUG, "RxBuffer ", RxBuffer, *BytesReturned);
|
||||||
|
|
||||||
|
if (rv == IFD_NO_SUCH_DEVICE)
|
||||||
|
{
|
||||||
|
(void)SendHotplugSignal();
|
||||||
|
return SCARD_E_READER_UNAVAILABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((IFD_ERROR_NOT_SUPPORTED == rv) || (IFD_NOT_SUPPORTED == rv))
|
||||||
|
return SCARD_E_UNSUPPORTED_FEATURE;
|
||||||
|
|
||||||
|
if (IFD_ERROR_INSUFFICIENT_BUFFER ==rv)
|
||||||
|
return SCARD_E_INSUFFICIENT_BUFFER;
|
||||||
|
|
||||||
|
return SCARD_E_NOT_TRANSACTED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transmit an APDU to the ICC.
|
||||||
|
*/
|
||||||
|
LONG IFDTransmit(READER_CONTEXT * rContext, SCARD_IO_HEADER pioTxPci,
|
||||||
|
PUCHAR pucTxBuffer, DWORD dwTxLength, PUCHAR pucRxBuffer,
|
||||||
|
PDWORD pdwRxLength, PSCARD_IO_HEADER pioRxPci)
|
||||||
|
{
|
||||||
|
RESPONSECODE rv;
|
||||||
|
|
||||||
|
#ifndef PCSCLITE_STATIC_DRIVER
|
||||||
|
RESPONSECODE(*IFDH_transmit_to_icc) (DWORD, SCARD_IO_HEADER, PUCHAR,
|
||||||
|
DWORD, /*@out@*/ PUCHAR, PDWORD, PSCARD_IO_HEADER) = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* log the APDU */
|
||||||
|
DebugLogCategory(DEBUG_CATEGORY_APDU, pucTxBuffer, dwTxLength);
|
||||||
|
|
||||||
|
#ifndef PCSCLITE_STATIC_DRIVER
|
||||||
|
IFDH_transmit_to_icc =
|
||||||
|
rContext->psFunctions.psFunctions_v2.pvfTransmitToICC;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* LOCK THIS CODE REGION */
|
||||||
|
(void)pthread_mutex_lock(rContext->mMutex);
|
||||||
|
|
||||||
|
#ifndef PCSCLITE_STATIC_DRIVER
|
||||||
|
rv = (*IFDH_transmit_to_icc) (rContext->slot, pioTxPci, (LPBYTE)
|
||||||
|
pucTxBuffer, dwTxLength, pucRxBuffer, pdwRxLength, pioRxPci);
|
||||||
|
#else
|
||||||
|
rv = IFDHTransmitToICC(rContext->slot, pioTxPci,
|
||||||
|
(LPBYTE) pucTxBuffer, dwTxLength,
|
||||||
|
pucRxBuffer, pdwRxLength, pioRxPci);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* END OF LOCKED REGION */
|
||||||
|
(void)pthread_mutex_unlock(rContext->mMutex);
|
||||||
|
|
||||||
|
/* log the returned status word */
|
||||||
|
DebugLogCategory(DEBUG_CATEGORY_SW, pucRxBuffer, *pdwRxLength);
|
||||||
|
|
||||||
|
if (rv == IFD_SUCCESS)
|
||||||
|
return SCARD_S_SUCCESS;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log2(PCSC_LOG_ERROR, "Card not transacted: %ld", rv);
|
||||||
|
|
||||||
|
if (rv == IFD_NO_SUCH_DEVICE)
|
||||||
|
{
|
||||||
|
(void)SendHotplugSignal();
|
||||||
|
return SCARD_E_READER_UNAVAILABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SCARD_E_NOT_TRANSACTED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
* MUSCLE SmartCard Development ( http://pcsclite.alioth.debian.org/pcsclite.html )
|
||||||
|
*
|
||||||
|
* Copyright (C) 1999-2004
|
||||||
|
* David Corcoran <corcoran@musclecard.com>
|
||||||
|
* Copyright (C) 2002-2010
|
||||||
|
* Ludovic Rousseau <ludovic.rouseau@free.fr>
|
||||||
|
*
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. The name of the author may not be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief This wraps the dynamic ifdhandler functions. The abstraction will
|
||||||
|
* eventually allow multiple card slots in the same terminal.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ifdwrapper_h__
|
||||||
|
#define __ifdwrapper_h__
|
||||||
|
|
||||||
|
LONG IFDOpenIFD(READER_CONTEXT *);
|
||||||
|
LONG IFDCloseIFD(READER_CONTEXT *);
|
||||||
|
LONG IFDPowerICC(READER_CONTEXT *, DWORD, PUCHAR, /*@out@*/ PDWORD);
|
||||||
|
LONG IFDStatusICC(READER_CONTEXT *, /*@out@*/ PDWORD);
|
||||||
|
LONG IFDControl_v2(READER_CONTEXT *, PUCHAR, DWORD, /*@out@*/ PUCHAR,
|
||||||
|
PDWORD);
|
||||||
|
LONG IFDControl(READER_CONTEXT *, DWORD, LPCVOID, DWORD, LPVOID,
|
||||||
|
DWORD, LPDWORD);
|
||||||
|
LONG IFDTransmit(READER_CONTEXT *, SCARD_IO_HEADER,
|
||||||
|
PUCHAR, DWORD, /*@out@*/ PUCHAR, PDWORD, PSCARD_IO_HEADER);
|
||||||
|
LONG IFDSetPTS(READER_CONTEXT *, DWORD, UCHAR, UCHAR, UCHAR, UCHAR);
|
||||||
|
LONG IFDSetCapabilities(READER_CONTEXT *, DWORD, DWORD, PUCHAR);
|
||||||
|
LONG IFDGetCapabilities(READER_CONTEXT *, DWORD, PDWORD, /*@out@*/ PUCHAR);
|
||||||
|
|
||||||
|
#endif /* __ifdwrapper_h__ */
|
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2007
|
||||||
|
* Jacob Berkman
|
||||||
|
* Copyright (C) 2008
|
||||||
|
* Ludovic Rousseau <ludovic.rousseau@free.fr>
|
||||||
|
*
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. The name of the author may not be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LASSERT_H
|
||||||
|
#define LASSERT_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
#define FAIL exit (1)
|
||||||
|
#else
|
||||||
|
#define FAIL return 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define LASSERT(cond) \
|
||||||
|
({ \
|
||||||
|
if (! (cond)) \
|
||||||
|
{ \
|
||||||
|
fprintf (stderr, "%s:%d: assertion FAILED: " #cond "\n", \
|
||||||
|
__FILE__, __LINE__); \
|
||||||
|
FAIL; \
|
||||||
|
} \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define LASSERTF(cond, fmt, a...) \
|
||||||
|
({ \
|
||||||
|
if (! (cond)) \
|
||||||
|
{ \
|
||||||
|
fprintf (stderr, "%s:%d: assertion FAILED: " #cond ": " fmt, \
|
||||||
|
__FILE__, __LINE__, ## a); \
|
||||||
|
FAIL; \
|
||||||
|
} \
|
||||||
|
})
|
||||||
|
|
||||||
|
#endif /* LASSERT_H */
|
|
@ -0,0 +1,13 @@
|
||||||
|
prefix=@prefix@
|
||||||
|
exec_prefix=@exec_prefix@
|
||||||
|
libdir=@libdir@
|
||||||
|
includedir=@includedir@/PCSC
|
||||||
|
usbdropdir=@usbdropdir@
|
||||||
|
serialconfdir=@confdir_exp@
|
||||||
|
|
||||||
|
Name: PCSC Lite
|
||||||
|
Description: PC/SC smart card interface
|
||||||
|
Version: @VERSION@
|
||||||
|
Libs: -L${libdir} -lpcsclite
|
||||||
|
Libs.private: @PTHREAD_LIBS@
|
||||||
|
Cflags: -I${includedir} @PTHREAD_CFLAGS@
|
|
@ -0,0 +1,85 @@
|
||||||
|
/*
|
||||||
|
* This handles GCC attributes
|
||||||
|
*
|
||||||
|
* MUSCLE SmartCard Development ( http://pcsclite.alioth.debian.org/pcsclite.html )
|
||||||
|
*
|
||||||
|
* Copyright (C) 2005-2010
|
||||||
|
* Ludovic Rousseau <ludovic.rousseau@free.fr>
|
||||||
|
*
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. The name of the author may not be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __misc_h__
|
||||||
|
#define __misc_h__
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Declare the function as internal to the library: the function name is
|
||||||
|
* not exported and can't be used by a program linked to the library
|
||||||
|
*
|
||||||
|
* see http://gcc.gnu.org/onlinedocs/gcc-3.3.5/gcc/Function-Attributes.html#Function-Attributes
|
||||||
|
* see http://www.nedprod.com/programs/gccvisibility.html
|
||||||
|
*/
|
||||||
|
#if defined(__GNUC__) && \
|
||||||
|
(__GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) || \
|
||||||
|
defined(__SUNPRO_C) && __SUNPRO_C >= 0x590
|
||||||
|
#define INTERNAL __attribute__ ((visibility("hidden")))
|
||||||
|
#define PCSC_API __attribute__ ((visibility("default")))
|
||||||
|
#elif defined(__SUNPRO_C) && __SUNPRO_C >= 0x550
|
||||||
|
/* http://wikis.sun.com/display/SunStudio/Macros+for+Shared+Library+Symbol+Visibility */
|
||||||
|
#define INTERNAL __hidden
|
||||||
|
#define PCSC_API __global
|
||||||
|
#else
|
||||||
|
#define INTERNAL
|
||||||
|
#define PCSC_API
|
||||||
|
#endif
|
||||||
|
#define EXTERNAL PCSC_API
|
||||||
|
|
||||||
|
#if defined __GNUC__
|
||||||
|
|
||||||
|
/* GNU Compiler Collection (GCC) */
|
||||||
|
#define CONSTRUCTOR __attribute__ ((constructor))
|
||||||
|
#define DESTRUCTOR __attribute__ ((destructor))
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
/* SUN C compiler does not use __attribute__ but #pragma init (function)
|
||||||
|
* We can't use a # inside a #define so it is not possible to use
|
||||||
|
* #define CONSTRUCTOR_DECLARATION(x) #pragma init (x)
|
||||||
|
* The #pragma is used directly where needed */
|
||||||
|
|
||||||
|
/* any other */
|
||||||
|
#define CONSTRUCTOR
|
||||||
|
#define DESTRUCTOR
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef min
|
||||||
|
#define min(a,b) (((a) < (b)) ? (a) : (b))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef COUNT_OF
|
||||||
|
#define COUNT_OF(arr) (sizeof(arr)/sizeof(arr[0]))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __misc_h__ */
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* MUSCLE SmartCard Development ( http://pcsclite.alioth.debian.org/pcsclite.html )
|
||||||
|
*
|
||||||
|
* Copyright (C) 2003
|
||||||
|
* Toni Andjelkovic <toni@soth.at>
|
||||||
|
* Copyright (C) 2003-2009
|
||||||
|
* Ludovic Rousseau <ludovic.rousseau@free.fr>
|
||||||
|
*
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. The name of the author may not be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief Reads lexical config files and updates database.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __parser_h__
|
||||||
|
#define __parser_h__
|
||||||
|
|
||||||
|
#include "simclist.h"
|
||||||
|
|
||||||
|
struct bundleElt
|
||||||
|
{
|
||||||
|
char *key;
|
||||||
|
list_t values;
|
||||||
|
};
|
||||||
|
|
||||||
|
int LTPBundleFindValueWithKey(list_t *l, const char *key, list_t **values);
|
||||||
|
int bundleParse(const char *fileName, list_t *l);
|
||||||
|
void bundleRelease(list_t *l);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,367 @@
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include "PCSC/pcsclite.h"
|
||||||
|
#include "pcscd.h"
|
||||||
|
#include "readerfactory.h"
|
||||||
|
#include "eventhandler.h"
|
||||||
|
#include "winscard_msg.h"
|
||||||
|
|
||||||
|
#include "lassert.h"
|
||||||
|
|
||||||
|
int pcsc_assert_wire_constants(void);
|
||||||
|
int pcsc_assert_wire_constants(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
/* Constants... */
|
||||||
|
|
||||||
|
LASSERTF(PROTOCOL_VERSION_MAJOR == 4," found %lld\n",
|
||||||
|
(long long)PROTOCOL_VERSION_MAJOR);
|
||||||
|
LASSERTF(PROTOCOL_VERSION_MINOR == 3," found %lld\n",
|
||||||
|
(long long)PROTOCOL_VERSION_MINOR);
|
||||||
|
|
||||||
|
LASSERTF(MAX_READERNAME == 128," found %lld\n",
|
||||||
|
(long long)MAX_READERNAME);
|
||||||
|
LASSERTF(MAX_ATR_SIZE == 33," found %lld\n",
|
||||||
|
(long long)MAX_ATR_SIZE);
|
||||||
|
LASSERTF(MAX_BUFFER_SIZE == 264," found %lld\n",
|
||||||
|
(long long)MAX_BUFFER_SIZE);
|
||||||
|
|
||||||
|
/* enum pcsc_msg_commands */
|
||||||
|
LASSERTF(SCARD_ESTABLISH_CONTEXT == 1, " found %lld\n",
|
||||||
|
(long long)SCARD_ESTABLISH_CONTEXT);
|
||||||
|
LASSERTF(SCARD_RELEASE_CONTEXT == 2, " found %lld\n",
|
||||||
|
(long long)SCARD_RELEASE_CONTEXT);
|
||||||
|
LASSERTF(SCARD_LIST_READERS == 3, " found %lld\n",
|
||||||
|
(long long)SCARD_LIST_READERS);
|
||||||
|
LASSERTF(SCARD_CONNECT == 4, " found %lld\n",
|
||||||
|
(long long)SCARD_CONNECT);
|
||||||
|
LASSERTF(SCARD_RECONNECT == 5, " found %lld\n",
|
||||||
|
(long long)SCARD_RECONNECT);
|
||||||
|
LASSERTF(SCARD_DISCONNECT == 6, " found %lld\n",
|
||||||
|
(long long)SCARD_DISCONNECT);
|
||||||
|
LASSERTF(SCARD_BEGIN_TRANSACTION == 7, " found %lld\n",
|
||||||
|
(long long)SCARD_BEGIN_TRANSACTION);
|
||||||
|
LASSERTF(SCARD_END_TRANSACTION == 8, " found %lld\n",
|
||||||
|
(long long)SCARD_END_TRANSACTION);
|
||||||
|
LASSERTF(SCARD_TRANSMIT == 9, " found %lld\n",
|
||||||
|
(long long)SCARD_TRANSMIT);
|
||||||
|
LASSERTF(SCARD_CONTROL == 10, " found %lld\n",
|
||||||
|
(long long)SCARD_CONTROL);
|
||||||
|
LASSERTF(SCARD_STATUS == 11, " found %lld\n",
|
||||||
|
(long long)SCARD_STATUS);
|
||||||
|
LASSERTF(SCARD_GET_STATUS_CHANGE == 12, " found %lld\n",
|
||||||
|
(long long)SCARD_GET_STATUS_CHANGE);
|
||||||
|
LASSERTF(SCARD_CANCEL == 13, " found %lld\n",
|
||||||
|
(long long)SCARD_CANCEL);
|
||||||
|
LASSERTF(SCARD_CANCEL_TRANSACTION == 14, " found %lld\n",
|
||||||
|
(long long)SCARD_CANCEL_TRANSACTION);
|
||||||
|
LASSERTF(SCARD_GET_ATTRIB == 15, " found %lld\n",
|
||||||
|
(long long)SCARD_GET_ATTRIB);
|
||||||
|
LASSERTF(SCARD_SET_ATTRIB == 16, " found %lld\n",
|
||||||
|
(long long)SCARD_SET_ATTRIB);
|
||||||
|
LASSERTF(CMD_VERSION == 17, " found %lld\n",
|
||||||
|
(long long)CMD_VERSION);
|
||||||
|
LASSERTF(CMD_GET_READERS_STATE == 18, " found %lld\n",
|
||||||
|
(long long)CMD_GET_READERS_STATE);
|
||||||
|
LASSERTF(CMD_WAIT_READER_STATE_CHANGE == 19, " found %lld\n",
|
||||||
|
(long long)CMD_WAIT_READER_STATE_CHANGE);
|
||||||
|
LASSERTF(CMD_STOP_WAITING_READER_STATE_CHANGE == 20, " found %lld\n",
|
||||||
|
(long long)CMD_STOP_WAITING_READER_STATE_CHANGE);
|
||||||
|
/* Types... */
|
||||||
|
|
||||||
|
/* Checks for struct version_struct */
|
||||||
|
LASSERTF((int)sizeof(struct version_struct) == 12, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(struct version_struct));
|
||||||
|
LASSERTF((int)offsetof(struct version_struct, major) == 0, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct version_struct, major));
|
||||||
|
LASSERTF((int)sizeof(((struct version_struct *)0)->major) == 4, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct version_struct *)0)->major));
|
||||||
|
LASSERTF((int)offsetof(struct version_struct, minor) == 4, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct version_struct, minor));
|
||||||
|
LASSERTF((int)sizeof(((struct version_struct *)0)->minor) == 4, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct version_struct *)0)->minor));
|
||||||
|
LASSERTF((int)offsetof(struct version_struct, rv) == 8, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct version_struct, rv));
|
||||||
|
LASSERTF((int)sizeof(((struct version_struct *)0)->rv) == 4, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct version_struct *)0)->rv));
|
||||||
|
|
||||||
|
/* Checks for struct client_struct */
|
||||||
|
LASSERTF((int)sizeof(struct client_struct) == 4, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(struct client_struct));
|
||||||
|
LASSERTF((int)offsetof(struct client_struct, hContext) == 0, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct client_struct, hContext));
|
||||||
|
LASSERTF((int)sizeof(((struct client_struct *)0)->hContext) == 4, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct client_struct *)0)->hContext));
|
||||||
|
|
||||||
|
/* Checks for struct establish_struct */
|
||||||
|
LASSERTF((int)sizeof(struct establish_struct) == 12, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(struct establish_struct));
|
||||||
|
LASSERTF((int)offsetof(struct establish_struct, dwScope) == 0, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct establish_struct, dwScope));
|
||||||
|
LASSERTF((int)sizeof(((struct establish_struct *)0)->dwScope) == 4, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct establish_struct *)0)->dwScope));
|
||||||
|
LASSERTF((int)offsetof(struct establish_struct, hContext) == 4, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct establish_struct, hContext));
|
||||||
|
LASSERTF((int)sizeof(((struct establish_struct *)0)->hContext) == 4, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct establish_struct *)0)->hContext));
|
||||||
|
LASSERTF((int)offsetof(struct establish_struct, rv) == 8, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct establish_struct, rv));
|
||||||
|
LASSERTF((int)sizeof(((struct establish_struct *)0)->rv) == 4, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct establish_struct *)0)->rv));
|
||||||
|
|
||||||
|
/* Checks for struct release_struct */
|
||||||
|
LASSERTF((int)sizeof(struct release_struct) == 8, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(struct release_struct));
|
||||||
|
LASSERTF((int)offsetof(struct release_struct, hContext) == 0, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct release_struct, hContext));
|
||||||
|
LASSERTF((int)sizeof(((struct release_struct *)0)->hContext) == 4, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct release_struct *)0)->hContext));
|
||||||
|
LASSERTF((int)offsetof(struct release_struct, rv) == 4, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct release_struct, rv));
|
||||||
|
LASSERTF((int)sizeof(((struct release_struct *)0)->rv) == 4, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct release_struct *)0)->rv));
|
||||||
|
|
||||||
|
/* Checks for struct connect_struct */
|
||||||
|
LASSERTF((int)sizeof(struct connect_struct) == 152, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(struct connect_struct));
|
||||||
|
LASSERTF((int)offsetof(struct connect_struct, hContext) == 0, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct connect_struct, hContext));
|
||||||
|
LASSERTF((int)sizeof(((struct connect_struct *)0)->hContext) == 4, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct connect_struct *)0)->hContext));
|
||||||
|
LASSERTF((int)offsetof(struct connect_struct, szReader) == 4, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct connect_struct, szReader));
|
||||||
|
LASSERTF((int)sizeof(((struct connect_struct *)0)->szReader) == 128, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct connect_struct *)0)->szReader));
|
||||||
|
LASSERTF((int)offsetof(struct connect_struct, dwShareMode) == 132, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct connect_struct, dwShareMode));
|
||||||
|
LASSERTF((int)sizeof(((struct connect_struct *)0)->dwShareMode) == 4, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct connect_struct *)0)->dwShareMode));
|
||||||
|
LASSERTF((int)offsetof(struct connect_struct, dwPreferredProtocols) == 136, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct connect_struct, dwPreferredProtocols));
|
||||||
|
LASSERTF((int)sizeof(((struct connect_struct *)0)->dwPreferredProtocols) == 4, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct connect_struct *)0)->dwPreferredProtocols));
|
||||||
|
LASSERTF((int)offsetof(struct connect_struct, hCard) == 140, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct connect_struct, hCard));
|
||||||
|
LASSERTF((int)sizeof(((struct connect_struct *)0)->hCard) == 4, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct connect_struct *)0)->hCard));
|
||||||
|
LASSERTF((int)offsetof(struct connect_struct, dwActiveProtocol) == 144, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct connect_struct, dwActiveProtocol));
|
||||||
|
LASSERTF((int)sizeof(((struct connect_struct *)0)->dwActiveProtocol) == 4, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct connect_struct *)0)->dwActiveProtocol));
|
||||||
|
LASSERTF((int)offsetof(struct connect_struct, rv) == 148, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct connect_struct, rv));
|
||||||
|
LASSERTF((int)sizeof(((struct connect_struct *)0)->rv) == 4, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct connect_struct *)0)->rv));
|
||||||
|
|
||||||
|
/* Checks for struct reconnect_struct */
|
||||||
|
LASSERTF((int)sizeof(struct reconnect_struct) == 24, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(struct reconnect_struct));
|
||||||
|
LASSERTF((int)offsetof(struct reconnect_struct, hCard) == 0, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct reconnect_struct, hCard));
|
||||||
|
LASSERTF((int)sizeof(((struct reconnect_struct *)0)->hCard) == 4, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct reconnect_struct *)0)->hCard));
|
||||||
|
LASSERTF((int)offsetof(struct reconnect_struct, dwShareMode) == 4, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct reconnect_struct, dwShareMode));
|
||||||
|
LASSERTF((int)sizeof(((struct reconnect_struct *)0)->dwShareMode) == 4, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct reconnect_struct *)0)->dwShareMode));
|
||||||
|
LASSERTF((int)offsetof(struct reconnect_struct, dwPreferredProtocols) == 8, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct reconnect_struct, dwPreferredProtocols));
|
||||||
|
LASSERTF((int)sizeof(((struct reconnect_struct *)0)->dwPreferredProtocols) == 4, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct reconnect_struct *)0)->dwPreferredProtocols));
|
||||||
|
LASSERTF((int)offsetof(struct reconnect_struct, dwInitialization) == 12, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct reconnect_struct, dwInitialization));
|
||||||
|
LASSERTF((int)sizeof(((struct reconnect_struct *)0)->dwInitialization) == 4, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct reconnect_struct *)0)->dwInitialization));
|
||||||
|
LASSERTF((int)offsetof(struct reconnect_struct, dwActiveProtocol) == 16, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct reconnect_struct, dwActiveProtocol));
|
||||||
|
LASSERTF((int)sizeof(((struct reconnect_struct *)0)->dwActiveProtocol) == 4, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct reconnect_struct *)0)->dwActiveProtocol));
|
||||||
|
LASSERTF((int)offsetof(struct reconnect_struct, rv) == 20, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct reconnect_struct, rv));
|
||||||
|
LASSERTF((int)sizeof(((struct reconnect_struct *)0)->rv) == 4, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct reconnect_struct *)0)->rv));
|
||||||
|
|
||||||
|
/* Checks for struct disconnect_struct */
|
||||||
|
LASSERTF((int)sizeof(struct disconnect_struct) == 12, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(struct disconnect_struct));
|
||||||
|
LASSERTF((int)offsetof(struct disconnect_struct, hCard) == 0, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct disconnect_struct, hCard));
|
||||||
|
LASSERTF((int)sizeof(((struct disconnect_struct *)0)->hCard) == 4, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct disconnect_struct *)0)->hCard));
|
||||||
|
LASSERTF((int)offsetof(struct disconnect_struct, dwDisposition) == 4, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct disconnect_struct, dwDisposition));
|
||||||
|
LASSERTF((int)sizeof(((struct disconnect_struct *)0)->dwDisposition) == 4, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct disconnect_struct *)0)->dwDisposition));
|
||||||
|
LASSERTF((int)offsetof(struct disconnect_struct, rv) == 8, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct disconnect_struct, rv));
|
||||||
|
LASSERTF((int)sizeof(((struct disconnect_struct *)0)->rv) == 4, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct disconnect_struct *)0)->rv));
|
||||||
|
|
||||||
|
/* Checks for struct begin_struct */
|
||||||
|
LASSERTF((int)sizeof(struct begin_struct) == 8, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(struct begin_struct));
|
||||||
|
LASSERTF((int)offsetof(struct begin_struct, hCard) == 0, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct begin_struct, hCard));
|
||||||
|
LASSERTF((int)sizeof(((struct begin_struct *)0)->hCard) == 4, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct begin_struct *)0)->hCard));
|
||||||
|
LASSERTF((int)offsetof(struct begin_struct, rv) == 4, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct begin_struct, rv));
|
||||||
|
LASSERTF((int)sizeof(((struct begin_struct *)0)->rv) == 4, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct begin_struct *)0)->rv));
|
||||||
|
|
||||||
|
/* Checks for struct end_struct */
|
||||||
|
LASSERTF((int)sizeof(struct end_struct) == 12, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(struct end_struct));
|
||||||
|
LASSERTF((int)offsetof(struct end_struct, hCard) == 0, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct end_struct, hCard));
|
||||||
|
LASSERTF((int)sizeof(((struct end_struct *)0)->hCard) == 4, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct end_struct *)0)->hCard));
|
||||||
|
LASSERTF((int)offsetof(struct end_struct, dwDisposition) == 4, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct end_struct, dwDisposition));
|
||||||
|
LASSERTF((int)sizeof(((struct end_struct *)0)->dwDisposition) == 4, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct end_struct *)0)->dwDisposition));
|
||||||
|
LASSERTF((int)offsetof(struct end_struct, rv) == 8, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct end_struct, rv));
|
||||||
|
LASSERTF((int)sizeof(((struct end_struct *)0)->rv) == 4, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct end_struct *)0)->rv));
|
||||||
|
|
||||||
|
/* Checks for struct cancel_struct */
|
||||||
|
LASSERTF((int)sizeof(struct cancel_struct) == 8, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(struct cancel_struct));
|
||||||
|
LASSERTF((int)offsetof(struct cancel_struct, hContext) == 0, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct cancel_struct, hContext));
|
||||||
|
LASSERTF((int)sizeof(((struct cancel_struct *)0)->hContext) == 4, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct cancel_struct *)0)->hContext));
|
||||||
|
LASSERTF((int)offsetof(struct cancel_struct, rv) == 4, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct cancel_struct, rv));
|
||||||
|
LASSERTF((int)sizeof(((struct cancel_struct *)0)->rv) == 4, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct cancel_struct *)0)->rv));
|
||||||
|
|
||||||
|
/* Checks for struct status_struct */
|
||||||
|
LASSERTF((int)sizeof(struct status_struct) == 8, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(struct status_struct));
|
||||||
|
LASSERTF((int)offsetof(struct status_struct, hCard) == 0, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct status_struct, hCard));
|
||||||
|
LASSERTF((int)sizeof(((struct status_struct *)0)->hCard) == 4, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct status_struct *)0)->hCard));
|
||||||
|
LASSERTF((int)offsetof(struct status_struct, rv) == 4, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct status_struct, rv));
|
||||||
|
LASSERTF((int)sizeof(((struct status_struct *)0)->rv) == 4, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct status_struct *)0)->rv));
|
||||||
|
|
||||||
|
/* Checks for struct transmit_struct */
|
||||||
|
LASSERTF((int)sizeof(struct transmit_struct) == 32, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(struct transmit_struct));
|
||||||
|
LASSERTF((int)offsetof(struct transmit_struct, hCard) == 0, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct transmit_struct, hCard));
|
||||||
|
LASSERTF((int)sizeof(((struct transmit_struct *)0)->hCard) == 4, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct transmit_struct *)0)->hCard));
|
||||||
|
LASSERTF((int)offsetof(struct transmit_struct, ioSendPciProtocol) == 4, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct transmit_struct, ioSendPciProtocol));
|
||||||
|
LASSERTF((int)sizeof(((struct transmit_struct *)0)->ioSendPciProtocol) == 4, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct transmit_struct *)0)->ioSendPciProtocol));
|
||||||
|
LASSERTF((int)offsetof(struct transmit_struct, ioSendPciLength) == 8, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct transmit_struct, ioSendPciLength));
|
||||||
|
LASSERTF((int)sizeof(((struct transmit_struct *)0)->ioSendPciLength) == 4, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct transmit_struct *)0)->ioSendPciLength));
|
||||||
|
LASSERTF((int)offsetof(struct transmit_struct, cbSendLength) == 12, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct transmit_struct, cbSendLength));
|
||||||
|
LASSERTF((int)sizeof(((struct transmit_struct *)0)->cbSendLength) == 4, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct transmit_struct *)0)->cbSendLength));
|
||||||
|
LASSERTF((int)offsetof(struct transmit_struct, ioRecvPciProtocol) == 16, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct transmit_struct, ioRecvPciProtocol));
|
||||||
|
LASSERTF((int)sizeof(((struct transmit_struct *)0)->ioRecvPciProtocol) == 4, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct transmit_struct *)0)->ioRecvPciProtocol));
|
||||||
|
LASSERTF((int)offsetof(struct transmit_struct, ioRecvPciLength) == 20, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct transmit_struct, ioRecvPciLength));
|
||||||
|
LASSERTF((int)sizeof(((struct transmit_struct *)0)->ioRecvPciLength) == 4, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct transmit_struct *)0)->ioRecvPciLength));
|
||||||
|
LASSERTF((int)offsetof(struct transmit_struct, pcbRecvLength) == 24, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct transmit_struct, pcbRecvLength));
|
||||||
|
LASSERTF((int)sizeof(((struct transmit_struct *)0)->pcbRecvLength) == 4, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct transmit_struct *)0)->pcbRecvLength));
|
||||||
|
LASSERTF((int)offsetof(struct transmit_struct, rv) == 28, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct transmit_struct, rv));
|
||||||
|
LASSERTF((int)sizeof(((struct transmit_struct *)0)->rv) == 4, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct transmit_struct *)0)->rv));
|
||||||
|
|
||||||
|
/* Checks for struct control_struct */
|
||||||
|
LASSERTF((int)sizeof(struct control_struct) == 24, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(struct control_struct));
|
||||||
|
LASSERTF((int)offsetof(struct control_struct, hCard) == 0, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct control_struct, hCard));
|
||||||
|
LASSERTF((int)sizeof(((struct control_struct *)0)->hCard) == 4, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct control_struct *)0)->hCard));
|
||||||
|
LASSERTF((int)offsetof(struct control_struct, dwControlCode) == 4, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct control_struct, dwControlCode));
|
||||||
|
LASSERTF((int)sizeof(((struct control_struct *)0)->dwControlCode) == 4, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct control_struct *)0)->dwControlCode));
|
||||||
|
LASSERTF((int)offsetof(struct control_struct, cbSendLength) == 8, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct control_struct, cbSendLength));
|
||||||
|
LASSERTF((int)sizeof(((struct control_struct *)0)->cbSendLength) == 4, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct control_struct *)0)->cbSendLength));
|
||||||
|
LASSERTF((int)offsetof(struct control_struct, cbRecvLength) == 12, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct control_struct, cbRecvLength));
|
||||||
|
LASSERTF((int)sizeof(((struct control_struct *)0)->cbRecvLength) == 4, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct control_struct *)0)->cbRecvLength));
|
||||||
|
LASSERTF((int)offsetof(struct control_struct, dwBytesReturned) == 16, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct control_struct, dwBytesReturned));
|
||||||
|
LASSERTF((int)sizeof(((struct control_struct *)0)->dwBytesReturned) == 4, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct control_struct *)0)->dwBytesReturned));
|
||||||
|
LASSERTF((int)offsetof(struct control_struct, rv) == 20, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct control_struct, rv));
|
||||||
|
LASSERTF((int)sizeof(((struct control_struct *)0)->rv) == 4, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct control_struct *)0)->rv));
|
||||||
|
|
||||||
|
/* Checks for struct getset_struct */
|
||||||
|
LASSERTF((int)sizeof(struct getset_struct) == 280, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(struct getset_struct));
|
||||||
|
LASSERTF((int)offsetof(struct getset_struct, hCard) == 0, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct getset_struct, hCard));
|
||||||
|
LASSERTF((int)sizeof(((struct getset_struct *)0)->hCard) == 4, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct getset_struct *)0)->hCard));
|
||||||
|
LASSERTF((int)offsetof(struct getset_struct, dwAttrId) == 4, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct getset_struct, dwAttrId));
|
||||||
|
LASSERTF((int)sizeof(((struct getset_struct *)0)->dwAttrId) == 4, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct getset_struct *)0)->dwAttrId));
|
||||||
|
LASSERTF((int)offsetof(struct getset_struct, cbAttrLen) == 272, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct getset_struct, cbAttrLen));
|
||||||
|
LASSERTF((int)sizeof(((struct getset_struct *)0)->cbAttrLen) == 4, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct getset_struct *)0)->cbAttrLen));
|
||||||
|
LASSERTF((int)offsetof(struct getset_struct, rv) == 276, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct getset_struct, rv));
|
||||||
|
LASSERTF((int)sizeof(((struct getset_struct *)0)->rv) == 4, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct getset_struct *)0)->rv));
|
||||||
|
|
||||||
|
/* Checks for struct pubReaderStatesList */
|
||||||
|
LASSERTF((int)sizeof(struct pubReaderStatesList) == 184, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(struct pubReaderStatesList));
|
||||||
|
LASSERTF((int)offsetof(struct pubReaderStatesList, readerName) == 0, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct pubReaderStatesList, readerName));
|
||||||
|
LASSERTF((int)sizeof(((struct pubReaderStatesList *)0)->readerName) == 128, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct pubReaderStatesList *)0)->readerName));
|
||||||
|
LASSERTF((int)offsetof(struct pubReaderStatesList, readerState) == 132, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct pubReaderStatesList, readerState));
|
||||||
|
LASSERTF((int)sizeof(((struct pubReaderStatesList *)0)->readerState) == 4, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct pubReaderStatesList *)0)->readerState));
|
||||||
|
LASSERTF((int)offsetof(struct pubReaderStatesList, readerSharing) == 136, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct pubReaderStatesList, readerSharing));
|
||||||
|
LASSERTF((int)sizeof(((struct pubReaderStatesList *)0)->readerSharing) == 4, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct pubReaderStatesList *)0)->readerSharing));
|
||||||
|
LASSERTF((int)offsetof(struct pubReaderStatesList, cardAtr) == 140, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct pubReaderStatesList, cardAtr));
|
||||||
|
LASSERTF((int)sizeof(((struct pubReaderStatesList *)0)->cardAtr) == 33, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct pubReaderStatesList *)0)->cardAtr));
|
||||||
|
LASSERTF((int)offsetof(struct pubReaderStatesList, cardAtrLength) == 176, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct pubReaderStatesList, cardAtrLength));
|
||||||
|
LASSERTF((int)sizeof(((struct pubReaderStatesList *)0)->cardAtrLength) == 4, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct pubReaderStatesList *)0)->cardAtrLength));
|
||||||
|
LASSERTF((int)offsetof(struct pubReaderStatesList, cardProtocol) == 180, " found %lld\n",
|
||||||
|
(long long)(int)offsetof(struct pubReaderStatesList, cardProtocol));
|
||||||
|
LASSERTF((int)sizeof(((struct pubReaderStatesList *)0)->cardProtocol) == 4, " found %lld\n",
|
||||||
|
(long long)(int)sizeof(((struct pubReaderStatesList *)0)->cardProtocol));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,282 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2007
|
||||||
|
* Jacob Berkman
|
||||||
|
* Copyright (C) 2007-2010
|
||||||
|
* Ludovic Rousseau <ludovic.rousseau@free.fr>
|
||||||
|
*
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. The name of the author may not be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include "PCSC/pcsclite.h"
|
||||||
|
#include "pcscd.h"
|
||||||
|
#include "winscard_msg.h"
|
||||||
|
#include "readerfactory.h"
|
||||||
|
#include "eventhandler.h"
|
||||||
|
|
||||||
|
#define BLANK_LINE() \
|
||||||
|
do { \
|
||||||
|
printf("\n"); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define COMMENT(c) \
|
||||||
|
do { \
|
||||||
|
printf(" /* "c" */\n"); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define STRINGIFY(a) #a
|
||||||
|
|
||||||
|
|
||||||
|
#define CHECK_CDEFINE(a) \
|
||||||
|
printf(" CLASSERT("#a" == "STRINGIFY(a) ");\n")
|
||||||
|
|
||||||
|
#define CHECK_CVALUE(a) \
|
||||||
|
printf(" CLASSERT("#a" == %lld);\n", (long long)a)
|
||||||
|
|
||||||
|
#define CHECK_DEFINE(a) \
|
||||||
|
do { \
|
||||||
|
printf(" LASSERTF("#a" == "STRINGIFY(a) \
|
||||||
|
",\" found %%lld\\n\",\n " \
|
||||||
|
"(long long)"#a");\n"); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define CHECK_VALUE(a) \
|
||||||
|
do { \
|
||||||
|
printf(" LASSERTF("#a \
|
||||||
|
" == %lld, \" found %%lld\\n\",\n "\
|
||||||
|
"(long long)"#a");\n", (long long)a); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define CHECK_VALUE_64(a) \
|
||||||
|
do { \
|
||||||
|
printf(" LASSERTF("#a \
|
||||||
|
" == %lldULL, \" found %%lld\\n\",\n "\
|
||||||
|
"(long long)"#a");\n", (long long)a); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define CHECK_MEMBER_OFFSET(s,m) \
|
||||||
|
do { \
|
||||||
|
CHECK_VALUE((int)offsetof(struct s, m)); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define CHECK_MEMBER_SIZEOF(s,m) \
|
||||||
|
do { \
|
||||||
|
CHECK_VALUE((int)sizeof(((struct s *)0)->m)); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define CHECK_MEMBER(s,m) \
|
||||||
|
do { \
|
||||||
|
CHECK_MEMBER_OFFSET(s, m); \
|
||||||
|
CHECK_MEMBER_SIZEOF(s, m); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define CHECK_STRUCT(s) \
|
||||||
|
do { \
|
||||||
|
COMMENT("Checks for struct "#s); \
|
||||||
|
CHECK_VALUE((int)sizeof(struct s)); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
static void
|
||||||
|
check_constants (void)
|
||||||
|
{
|
||||||
|
COMMENT ("Constants...");
|
||||||
|
|
||||||
|
BLANK_LINE ();
|
||||||
|
CHECK_DEFINE (PROTOCOL_VERSION_MAJOR);
|
||||||
|
CHECK_DEFINE (PROTOCOL_VERSION_MINOR);
|
||||||
|
|
||||||
|
BLANK_LINE ();
|
||||||
|
CHECK_DEFINE (MAX_READERNAME);
|
||||||
|
CHECK_DEFINE (MAX_ATR_SIZE);
|
||||||
|
CHECK_DEFINE (MAX_BUFFER_SIZE);
|
||||||
|
|
||||||
|
BLANK_LINE ();
|
||||||
|
COMMENT ("enum pcsc_msg_commands");
|
||||||
|
CHECK_VALUE (SCARD_ESTABLISH_CONTEXT);
|
||||||
|
CHECK_VALUE (SCARD_RELEASE_CONTEXT);
|
||||||
|
CHECK_VALUE (SCARD_LIST_READERS);
|
||||||
|
CHECK_VALUE (SCARD_CONNECT);
|
||||||
|
CHECK_VALUE (SCARD_RECONNECT);
|
||||||
|
CHECK_VALUE (SCARD_DISCONNECT);
|
||||||
|
CHECK_VALUE (SCARD_BEGIN_TRANSACTION);
|
||||||
|
CHECK_VALUE (SCARD_END_TRANSACTION);
|
||||||
|
CHECK_VALUE (SCARD_TRANSMIT);
|
||||||
|
CHECK_VALUE (SCARD_CONTROL);
|
||||||
|
CHECK_VALUE (SCARD_STATUS);
|
||||||
|
CHECK_VALUE (SCARD_GET_STATUS_CHANGE);
|
||||||
|
CHECK_VALUE (SCARD_CANCEL);
|
||||||
|
CHECK_VALUE (SCARD_CANCEL_TRANSACTION);
|
||||||
|
CHECK_VALUE (SCARD_GET_ATTRIB);
|
||||||
|
CHECK_VALUE (SCARD_SET_ATTRIB);
|
||||||
|
CHECK_VALUE (CMD_VERSION);
|
||||||
|
CHECK_VALUE (CMD_GET_READERS_STATE);
|
||||||
|
CHECK_VALUE (CMD_WAIT_READER_STATE_CHANGE);
|
||||||
|
CHECK_VALUE (CMD_STOP_WAITING_READER_STATE_CHANGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
check_types (void)
|
||||||
|
{
|
||||||
|
COMMENT ("Types...");
|
||||||
|
|
||||||
|
BLANK_LINE ();
|
||||||
|
CHECK_STRUCT (version_struct);
|
||||||
|
CHECK_MEMBER (version_struct, major);
|
||||||
|
CHECK_MEMBER (version_struct, minor);
|
||||||
|
CHECK_MEMBER (version_struct, rv);
|
||||||
|
|
||||||
|
BLANK_LINE ();
|
||||||
|
CHECK_STRUCT (client_struct);
|
||||||
|
CHECK_MEMBER (client_struct, hContext);
|
||||||
|
|
||||||
|
BLANK_LINE ();
|
||||||
|
CHECK_STRUCT (establish_struct);
|
||||||
|
CHECK_MEMBER (establish_struct, dwScope);
|
||||||
|
CHECK_MEMBER (establish_struct, hContext);
|
||||||
|
CHECK_MEMBER (establish_struct, rv);
|
||||||
|
|
||||||
|
BLANK_LINE ();
|
||||||
|
CHECK_STRUCT (release_struct);
|
||||||
|
CHECK_MEMBER (release_struct, hContext);
|
||||||
|
CHECK_MEMBER (release_struct, rv);
|
||||||
|
|
||||||
|
BLANK_LINE ();
|
||||||
|
CHECK_STRUCT (connect_struct);
|
||||||
|
CHECK_MEMBER (connect_struct, hContext);
|
||||||
|
CHECK_MEMBER (connect_struct, szReader);
|
||||||
|
CHECK_MEMBER (connect_struct, dwShareMode);
|
||||||
|
CHECK_MEMBER (connect_struct, dwPreferredProtocols);
|
||||||
|
CHECK_MEMBER (connect_struct, hCard);
|
||||||
|
CHECK_MEMBER (connect_struct, dwActiveProtocol);
|
||||||
|
CHECK_MEMBER (connect_struct, rv);
|
||||||
|
|
||||||
|
BLANK_LINE ();
|
||||||
|
CHECK_STRUCT (reconnect_struct);
|
||||||
|
CHECK_MEMBER (reconnect_struct, hCard);
|
||||||
|
CHECK_MEMBER (reconnect_struct, dwShareMode);
|
||||||
|
CHECK_MEMBER (reconnect_struct, dwPreferredProtocols);
|
||||||
|
CHECK_MEMBER (reconnect_struct, dwInitialization);
|
||||||
|
CHECK_MEMBER (reconnect_struct, dwActiveProtocol);
|
||||||
|
CHECK_MEMBER (reconnect_struct, rv);
|
||||||
|
|
||||||
|
BLANK_LINE ();
|
||||||
|
CHECK_STRUCT (disconnect_struct);
|
||||||
|
CHECK_MEMBER (disconnect_struct, hCard);
|
||||||
|
CHECK_MEMBER (disconnect_struct, dwDisposition);
|
||||||
|
CHECK_MEMBER (disconnect_struct, rv);
|
||||||
|
|
||||||
|
BLANK_LINE ();
|
||||||
|
CHECK_STRUCT (begin_struct);
|
||||||
|
CHECK_MEMBER (begin_struct, hCard);
|
||||||
|
CHECK_MEMBER (begin_struct, rv);
|
||||||
|
|
||||||
|
BLANK_LINE ();
|
||||||
|
CHECK_STRUCT (end_struct);
|
||||||
|
CHECK_MEMBER (end_struct, hCard);
|
||||||
|
CHECK_MEMBER (end_struct, dwDisposition);
|
||||||
|
CHECK_MEMBER (end_struct, rv);
|
||||||
|
|
||||||
|
BLANK_LINE ();
|
||||||
|
CHECK_STRUCT (cancel_struct);
|
||||||
|
CHECK_MEMBER (cancel_struct, hContext);
|
||||||
|
CHECK_MEMBER (cancel_struct, rv);
|
||||||
|
|
||||||
|
BLANK_LINE ();
|
||||||
|
CHECK_STRUCT (status_struct);
|
||||||
|
CHECK_MEMBER (status_struct, hCard);
|
||||||
|
CHECK_MEMBER (status_struct, rv);
|
||||||
|
|
||||||
|
BLANK_LINE ();
|
||||||
|
CHECK_STRUCT (transmit_struct);
|
||||||
|
CHECK_MEMBER (transmit_struct, hCard);
|
||||||
|
CHECK_MEMBER (transmit_struct, ioSendPciProtocol);
|
||||||
|
CHECK_MEMBER (transmit_struct, ioSendPciLength);
|
||||||
|
CHECK_MEMBER (transmit_struct, cbSendLength);
|
||||||
|
CHECK_MEMBER (transmit_struct, ioRecvPciProtocol);
|
||||||
|
CHECK_MEMBER (transmit_struct, ioRecvPciLength);
|
||||||
|
CHECK_MEMBER (transmit_struct, pcbRecvLength);
|
||||||
|
CHECK_MEMBER (transmit_struct, rv);
|
||||||
|
|
||||||
|
BLANK_LINE ();
|
||||||
|
CHECK_STRUCT (control_struct);
|
||||||
|
CHECK_MEMBER (control_struct, hCard);
|
||||||
|
CHECK_MEMBER (control_struct, dwControlCode);
|
||||||
|
CHECK_MEMBER (control_struct, cbSendLength);
|
||||||
|
CHECK_MEMBER (control_struct, cbRecvLength);
|
||||||
|
CHECK_MEMBER (control_struct, dwBytesReturned);
|
||||||
|
CHECK_MEMBER (control_struct, rv);
|
||||||
|
|
||||||
|
BLANK_LINE ();
|
||||||
|
CHECK_STRUCT (getset_struct);
|
||||||
|
CHECK_MEMBER (getset_struct, hCard);
|
||||||
|
CHECK_MEMBER (getset_struct, dwAttrId);
|
||||||
|
CHECK_MEMBER (getset_struct, cbAttrLen);
|
||||||
|
CHECK_MEMBER (getset_struct, rv);
|
||||||
|
|
||||||
|
BLANK_LINE ();
|
||||||
|
CHECK_STRUCT (pubReaderStatesList);
|
||||||
|
CHECK_MEMBER (pubReaderStatesList, readerName);
|
||||||
|
CHECK_MEMBER (pubReaderStatesList, readerState);
|
||||||
|
CHECK_MEMBER (pubReaderStatesList, readerSharing);
|
||||||
|
CHECK_MEMBER (pubReaderStatesList, cardAtr);
|
||||||
|
CHECK_MEMBER (pubReaderStatesList, cardAtrLength);
|
||||||
|
CHECK_MEMBER (pubReaderStatesList, cardProtocol);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(/*@unused@*/ int argc, /*@unused@*/ char **argv)
|
||||||
|
{
|
||||||
|
(void)argc;
|
||||||
|
(void)argv;
|
||||||
|
|
||||||
|
printf ("#include <sys/types.h>\n"
|
||||||
|
"#include <time.h>\n"
|
||||||
|
"#include <stddef.h>\n\n"
|
||||||
|
"#include \"PCSC/pcsclite.h\"\n"
|
||||||
|
"#include \"pcscd.h\"\n"
|
||||||
|
"#include \"readerfactory.h\"\n"
|
||||||
|
"#include \"eventhandler.h\"\n"
|
||||||
|
"#include \"winscard_msg.h\"\n\n"
|
||||||
|
"#include \"lassert.h\"\n\n"
|
||||||
|
"int pcsc_assert_wire_constants(void);\n"
|
||||||
|
"int pcsc_assert_wire_constants(void)\n"
|
||||||
|
"{\n");
|
||||||
|
|
||||||
|
BLANK_LINE ();
|
||||||
|
|
||||||
|
check_constants ();
|
||||||
|
check_types ();
|
||||||
|
|
||||||
|
BLANK_LINE ();
|
||||||
|
|
||||||
|
printf ("return 0;\n");
|
||||||
|
printf ("}\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int pcsc_assert_wire_constants(void);
|
||||||
|
|
||||||
|
int
|
||||||
|
main (/*@unused@*/ int argc, /*@unused@*/ char **argv)
|
||||||
|
{
|
||||||
|
(void)argc;
|
||||||
|
(void)argv;
|
||||||
|
|
||||||
|
printf("Checking ABI...\n");
|
||||||
|
if (0 == pcsc_assert_wire_constants ())
|
||||||
|
printf("OK\n");
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,86 @@
|
||||||
|
/*
|
||||||
|
* MUSCLE SmartCard Development ( http://pcsclite.alioth.debian.org/pcsclite.html )
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006-2011
|
||||||
|
* Ludovic Rousseau <ludovic.rousseau@free.fr>
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. The name of the author may not be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief This keeps a list of defines for pcsc-lite.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __pcscd_h__
|
||||||
|
#define __pcscd_h__
|
||||||
|
|
||||||
|
#define TIME_BEFORE_SUICIDE 60
|
||||||
|
|
||||||
|
#define SCARD_RESET 0x0001 /**< Card was reset */
|
||||||
|
#define SCARD_INSERTED 0x0002 /**< Card was inserted */
|
||||||
|
#define SCARD_REMOVED 0x0004 /**< Card was removed */
|
||||||
|
|
||||||
|
#define PCSCLITE_CONFIG_DIR "/etc/reader.conf.d"
|
||||||
|
|
||||||
|
#define PCSCLITE_IPC_DIR USE_IPCDIR
|
||||||
|
#define PCSCLITE_RUN_PID PCSCLITE_IPC_DIR "/pcscd.pid"
|
||||||
|
|
||||||
|
#define PCSCLITE_CSOCK_NAME PCSCLITE_IPC_DIR "/pcscd.comm"
|
||||||
|
|
||||||
|
#define PCSCLITE_VERSION_NUMBER "1.8.22" /**< Current version */
|
||||||
|
#define PCSCLITE_STATUS_POLL_RATE 400000 /**< Status polling rate */
|
||||||
|
#define PCSCLITE_LOCK_POLL_RATE 100000 /**< Lock polling rate */
|
||||||
|
|
||||||
|
#define PCSC_MAX_CONTEXT_THREADS 200
|
||||||
|
#define PCSC_MAX_CONTEXT_CARD_HANDLES 200
|
||||||
|
#define PCSC_MAX_READER_HANDLES 200
|
||||||
|
|
||||||
|
#define PCSCLITE_STATUS_WAIT 200000 /**< Status Change Sleep */
|
||||||
|
#define MAX_DEVICENAME 255
|
||||||
|
|
||||||
|
/** Different values for struct ReaderContext powerState field */
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
POWER_STATE_UNPOWERED, /**< auto power off */
|
||||||
|
POWER_STATE_POWERED, /**< powered */
|
||||||
|
POWER_STATE_GRACE_PERIOD, /**< card was in use */
|
||||||
|
POWER_STATE_INUSE /**< card is used */
|
||||||
|
};
|
||||||
|
|
||||||
|
/** time to wait before powering down an unused card */
|
||||||
|
#define PCSCLITE_POWER_OFF_GRACE_PERIOD 5*1000 /* 5 second */
|
||||||
|
|
||||||
|
/** normal timeout for pthCardEvent driver function when
|
||||||
|
* no card or card in use */
|
||||||
|
#define PCSCLITE_STATUS_EVENT_TIMEOUT 10*60*1000 /* 10 minutes */
|
||||||
|
|
||||||
|
/* Uncomment the next line if you do NOT want to use auto power off */
|
||||||
|
/* #define DISABLE_ON_DEMAND_POWER_ON */
|
||||||
|
|
||||||
|
/* Uncomment the next line if you do not want the card to be powered on
|
||||||
|
* when inserted */
|
||||||
|
/* #define DISABLE_AUTO_POWER_ON */
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,86 @@
|
||||||
|
/*
|
||||||
|
* MUSCLE SmartCard Development ( http://pcsclite.alioth.debian.org/pcsclite.html )
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006-2011
|
||||||
|
* Ludovic Rousseau <ludovic.rousseau@free.fr>
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. The name of the author may not be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief This keeps a list of defines for pcsc-lite.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __pcscd_h__
|
||||||
|
#define __pcscd_h__
|
||||||
|
|
||||||
|
#define TIME_BEFORE_SUICIDE 60
|
||||||
|
|
||||||
|
#define SCARD_RESET 0x0001 /**< Card was reset */
|
||||||
|
#define SCARD_INSERTED 0x0002 /**< Card was inserted */
|
||||||
|
#define SCARD_REMOVED 0x0004 /**< Card was removed */
|
||||||
|
|
||||||
|
#define PCSCLITE_CONFIG_DIR "@PCSCLITE_CONFIG_DIR@"
|
||||||
|
|
||||||
|
#define PCSCLITE_IPC_DIR USE_IPCDIR
|
||||||
|
#define PCSCLITE_RUN_PID PCSCLITE_IPC_DIR "/pcscd.pid"
|
||||||
|
|
||||||
|
#define PCSCLITE_CSOCK_NAME PCSCLITE_IPC_DIR "/pcscd.comm"
|
||||||
|
|
||||||
|
#define PCSCLITE_VERSION_NUMBER "@VERSION@" /**< Current version */
|
||||||
|
#define PCSCLITE_STATUS_POLL_RATE 400000 /**< Status polling rate */
|
||||||
|
#define PCSCLITE_LOCK_POLL_RATE 100000 /**< Lock polling rate */
|
||||||
|
|
||||||
|
#define PCSC_MAX_CONTEXT_THREADS 200
|
||||||
|
#define PCSC_MAX_CONTEXT_CARD_HANDLES 200
|
||||||
|
#define PCSC_MAX_READER_HANDLES 200
|
||||||
|
|
||||||
|
#define PCSCLITE_STATUS_WAIT 200000 /**< Status Change Sleep */
|
||||||
|
#define MAX_DEVICENAME 255
|
||||||
|
|
||||||
|
/** Different values for struct ReaderContext powerState field */
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
POWER_STATE_UNPOWERED, /**< auto power off */
|
||||||
|
POWER_STATE_POWERED, /**< powered */
|
||||||
|
POWER_STATE_GRACE_PERIOD, /**< card was in use */
|
||||||
|
POWER_STATE_INUSE /**< card is used */
|
||||||
|
};
|
||||||
|
|
||||||
|
/** time to wait before powering down an unused card */
|
||||||
|
#define PCSCLITE_POWER_OFF_GRACE_PERIOD 5*1000 /* 5 second */
|
||||||
|
|
||||||
|
/** normal timeout for pthCardEvent driver function when
|
||||||
|
* no card or card in use */
|
||||||
|
#define PCSCLITE_STATUS_EVENT_TIMEOUT 10*60*1000 /* 10 minutes */
|
||||||
|
|
||||||
|
/* Uncomment the next line if you do NOT want to use auto power off */
|
||||||
|
/* #define DISABLE_ON_DEMAND_POWER_ON */
|
||||||
|
|
||||||
|
/* Uncomment the next line if you do not want the card to be powered on
|
||||||
|
* when inserted */
|
||||||
|
/* #define DISABLE_AUTO_POWER_ON */
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,881 @@
|
||||||
|
/*
|
||||||
|
* MUSCLE SmartCard Development ( http://pcsclite.alioth.debian.org/pcsclite.html )
|
||||||
|
*
|
||||||
|
* Copyright (C) 1999-2002
|
||||||
|
* David Corcoran <corcoran@musclecard.com>
|
||||||
|
* Copyright (C) 2002-2011
|
||||||
|
* Ludovic Rousseau <ludovic.rousseau@free.fr>
|
||||||
|
*
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. The name of the author may not be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief This is the main pcscd daemon.
|
||||||
|
*
|
||||||
|
* The function \c main() starts up the communication environment.\n
|
||||||
|
* Then an endless loop is calld to look for Client connections. For each
|
||||||
|
* Client connection a call to \c CreateContextThread() is done.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include <time.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#ifdef HAVE_GETOPT_H
|
||||||
|
#include <getopt.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "misc.h"
|
||||||
|
#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"
|
||||||
|
#include "hotplug.h"
|
||||||
|
#include "readerfactory.h"
|
||||||
|
#include "configfile.h"
|
||||||
|
#include "utils.h"
|
||||||
|
#include "eventhandler.h"
|
||||||
|
|
||||||
|
#ifndef TRUE
|
||||||
|
#define TRUE 1
|
||||||
|
#define FALSE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
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};
|
||||||
|
static int signal_handler_fd[] = {-1, -1};
|
||||||
|
char Add_Serial_In_Name = TRUE;
|
||||||
|
char Add_Interface_In_Name = TRUE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Some internal functions
|
||||||
|
*/
|
||||||
|
static void at_exit(void);
|
||||||
|
static void clean_temp_files(void);
|
||||||
|
static void signal_trap(int);
|
||||||
|
static void print_version(void);
|
||||||
|
static void print_usage(char const * const);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The Server's Message Queue Listener function.
|
||||||
|
*
|
||||||
|
* An endless loop calls the function \c ProcessEventsServer() to check for
|
||||||
|
* messages sent by clients.
|
||||||
|
* If the message is valid, \c CreateContextThread() is called to serve this
|
||||||
|
* request.
|
||||||
|
*/
|
||||||
|
static void SVCServiceRunLoop(void)
|
||||||
|
{
|
||||||
|
int rsp;
|
||||||
|
LONG rv;
|
||||||
|
uint32_t dwClientID; /* Connection ID used to reference the Client */
|
||||||
|
|
||||||
|
while (TRUE)
|
||||||
|
{
|
||||||
|
if (AraKiri)
|
||||||
|
{
|
||||||
|
/* stop the hotpug thread and waits its exit */
|
||||||
|
#ifdef USE_USB
|
||||||
|
(void)HPStopHotPluggables();
|
||||||
|
#endif
|
||||||
|
(void)SYS_Sleep(1);
|
||||||
|
|
||||||
|
/* now stop all the drivers */
|
||||||
|
RFCleanupReaders();
|
||||||
|
EHDeinitializeEventStructures();
|
||||||
|
ContextsDeinitialize();
|
||||||
|
at_exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (rsp = ProcessEventsServer(&dwClientID))
|
||||||
|
{
|
||||||
|
|
||||||
|
case 0:
|
||||||
|
Log2(PCSC_LOG_DEBUG, "A new context thread creation is requested: %d", dwClientID);
|
||||||
|
rv = CreateContextThread(&dwClientID);
|
||||||
|
|
||||||
|
if (rv != SCARD_S_SUCCESS)
|
||||||
|
Log1(PCSC_LOG_ERROR, "Problem during the context thread creation");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
/*
|
||||||
|
* timeout in ProcessEventsServer(): do nothing
|
||||||
|
* this is used to catch the Ctrl-C signal at some time when
|
||||||
|
* nothing else happens
|
||||||
|
*/
|
||||||
|
break;
|
||||||
|
|
||||||
|
case -1:
|
||||||
|
Log1(PCSC_LOG_ERROR, "Error in ProcessEventsServer");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case -2:
|
||||||
|
/* Nothing to do in case of a syscall interrupted
|
||||||
|
* It happens when SIGUSR1 (reload) or SIGINT (Ctrl-C) is received
|
||||||
|
* We just try again */
|
||||||
|
|
||||||
|
/* we wait a bit so that the signal handler thread can do
|
||||||
|
* its job and set AraKiri if needed */
|
||||||
|
SYS_USleep(1000);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
Log2(PCSC_LOG_ERROR, "ProcessEventsServer unknown retval: %d",
|
||||||
|
rsp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* thread dedicated to handle signals
|
||||||
|
*
|
||||||
|
* a signal handler can not call any function. See signal(7) for a list
|
||||||
|
* of function that are safe to call from a signal handler.
|
||||||
|
* The functions syslog(), gettimeofday() and remove() are NOT safe.
|
||||||
|
*/
|
||||||
|
static void *signal_thread(void *arg)
|
||||||
|
{
|
||||||
|
(void)arg;
|
||||||
|
|
||||||
|
while (TRUE)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
int sig;
|
||||||
|
|
||||||
|
r = read(signal_handler_fd[0], &sig, sizeof sig);
|
||||||
|
if (r < 0)
|
||||||
|
{
|
||||||
|
Log2(PCSC_LOG_ERROR, "read failed: %s", strerror(errno));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Log2(PCSC_LOG_INFO, "Received signal: %d", sig);
|
||||||
|
|
||||||
|
/* signal for hotplug */
|
||||||
|
if (SIGUSR1 == sig)
|
||||||
|
{
|
||||||
|
#ifdef USE_USB
|
||||||
|
if (! AraKiri)
|
||||||
|
HPReCheckSerialReaders();
|
||||||
|
#endif
|
||||||
|
/* Reenable the signal handler.
|
||||||
|
* This is needed on Solaris and HPUX. */
|
||||||
|
(void)signal(SIGUSR1, signal_trap);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* do not wait if asked to terminate
|
||||||
|
* avoids waiting after the reader(s) in shutdown for example */
|
||||||
|
if (SIGTERM == sig)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_INFO, "Direct suicide");
|
||||||
|
at_exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SIGALRM == sig)
|
||||||
|
{
|
||||||
|
/* normal exit without error */
|
||||||
|
ExitValue = EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* the signal handler is called several times for the same Ctrl-C */
|
||||||
|
if (AraKiri == FALSE)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_INFO, "Preparing for suicide");
|
||||||
|
AraKiri = TRUE;
|
||||||
|
|
||||||
|
/* if still in the init/loading phase the AraKiri will not be
|
||||||
|
* seen by the main event loop
|
||||||
|
*/
|
||||||
|
if (Init)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_INFO, "Suicide during init");
|
||||||
|
at_exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* if pcscd do not want to die */
|
||||||
|
static int lives = 2;
|
||||||
|
|
||||||
|
lives--;
|
||||||
|
/* no live left. Something is blocking the normal death. */
|
||||||
|
if (0 == lives)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_INFO, "Forced suicide");
|
||||||
|
at_exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
char setToForeground;
|
||||||
|
char HotPlug;
|
||||||
|
char *newReaderConfig;
|
||||||
|
struct stat fStatBuf;
|
||||||
|
int customMaxThreadCounter = 0;
|
||||||
|
int customMaxReaderHandles = 0;
|
||||||
|
int customMaxThreadCardHandles = 0;
|
||||||
|
int opt;
|
||||||
|
int r;
|
||||||
|
#ifdef HAVE_GETOPT_LONG
|
||||||
|
int option_index = 0;
|
||||||
|
static struct option long_options[] = {
|
||||||
|
{"config", 1, NULL, 'c'},
|
||||||
|
{"foreground", 0, NULL, 'f'},
|
||||||
|
{"color", 0, NULL, 'T'},
|
||||||
|
{"help", 0, NULL, 'h'},
|
||||||
|
{"version", 0, NULL, 'v'},
|
||||||
|
{"apdu", 0, NULL, 'a'},
|
||||||
|
{"debug", 0, NULL, 'd'},
|
||||||
|
{"info", 0, NULL, 'i'},
|
||||||
|
{"error", 0, NULL, 'e'},
|
||||||
|
{"critical", 0, NULL, 'C'},
|
||||||
|
{"hotplug", 0, NULL, 'H'},
|
||||||
|
{"force-reader-polling", optional_argument, NULL, 0},
|
||||||
|
{"max-thread", 1, NULL, 't'},
|
||||||
|
{"max-card-handle-per-thread", 1, NULL, 's'},
|
||||||
|
{"max-card-handle-per-reader", 1, NULL, 'r'},
|
||||||
|
{"auto-exit", 0, NULL, 'x'},
|
||||||
|
{"reader-name-no-serial", 0, NULL, 'S'},
|
||||||
|
{"reader-name-no-interface", 0, NULL, 'I'},
|
||||||
|
{NULL, 0, NULL, 0}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
#define OPT_STRING "c:fTdhvaieCHt:r:s:xSI"
|
||||||
|
|
||||||
|
newReaderConfig = NULL;
|
||||||
|
setToForeground = FALSE;
|
||||||
|
HotPlug = FALSE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* test the version
|
||||||
|
*/
|
||||||
|
if (strcmp(PCSCLITE_VERSION_NUMBER, VERSION) != 0)
|
||||||
|
{
|
||||||
|
printf("BUILD ERROR: The release version number PCSCLITE_VERSION_NUMBER\n");
|
||||||
|
printf(" in pcsclite.h (%s) does not match the release version number\n",
|
||||||
|
PCSCLITE_VERSION_NUMBER);
|
||||||
|
printf(" generated in config.h (%s) (see configure.in).\n", VERSION);
|
||||||
|
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Init the PRNG */
|
||||||
|
SYS_InitRandom();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* By default we create a daemon (not connected to any output)
|
||||||
|
* so log to syslog to have error messages.
|
||||||
|
*/
|
||||||
|
DebugLogSetLogType(DEBUGLOG_SYSLOG_DEBUG);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handle any command line arguments
|
||||||
|
*/
|
||||||
|
#ifdef HAVE_GETOPT_LONG
|
||||||
|
while ((opt = getopt_long (argc, argv, OPT_STRING, long_options, &option_index)) != -1) {
|
||||||
|
#else
|
||||||
|
while ((opt = getopt (argc, argv, OPT_STRING)) != -1) {
|
||||||
|
#endif
|
||||||
|
switch (opt) {
|
||||||
|
#ifdef HAVE_GETOPT_LONG
|
||||||
|
case 0:
|
||||||
|
if (strcmp(long_options[option_index].name,
|
||||||
|
"force-reader-polling") == 0)
|
||||||
|
HPForceReaderPolling = optarg ? abs(atoi(optarg)) : 1;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
case 'c':
|
||||||
|
Log2(PCSC_LOG_INFO, "using new config file: %s", optarg);
|
||||||
|
newReaderConfig = optarg;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'f':
|
||||||
|
setToForeground = TRUE;
|
||||||
|
/* debug to stdout instead of default syslog */
|
||||||
|
DebugLogSetLogType(DEBUGLOG_STDOUT_DEBUG);
|
||||||
|
Log1(PCSC_LOG_INFO,
|
||||||
|
"pcscd set to foreground with debug send to stdout");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'T':
|
||||||
|
DebugLogSetLogType(DEBUGLOG_STDOUT_COLOR_DEBUG);
|
||||||
|
Log1(PCSC_LOG_INFO, "Force colored logs");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'd':
|
||||||
|
DebugLogSetLevel(PCSC_LOG_DEBUG);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'i':
|
||||||
|
DebugLogSetLevel(PCSC_LOG_INFO);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'e':
|
||||||
|
DebugLogSetLevel(PCSC_LOG_ERROR);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'C':
|
||||||
|
DebugLogSetLevel(PCSC_LOG_CRITICAL);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'h':
|
||||||
|
print_usage (argv[0]);
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
|
||||||
|
case 'v':
|
||||||
|
print_version ();
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
|
||||||
|
case 'a':
|
||||||
|
DebugLogSetCategory(DEBUG_CATEGORY_APDU);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'H':
|
||||||
|
/* debug to stdout instead of default syslog */
|
||||||
|
DebugLogSetLogType(DEBUGLOG_STDOUT_DEBUG);
|
||||||
|
HotPlug = TRUE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 't':
|
||||||
|
customMaxThreadCounter = optarg ? atoi(optarg) : 0;
|
||||||
|
Log2(PCSC_LOG_INFO, "setting customMaxThreadCounter to: %d",
|
||||||
|
customMaxThreadCounter);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'r':
|
||||||
|
customMaxReaderHandles = optarg ? atoi(optarg) : 0;
|
||||||
|
Log2(PCSC_LOG_INFO, "setting customMaxReaderHandles to: %d",
|
||||||
|
customMaxReaderHandles);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 's':
|
||||||
|
customMaxThreadCardHandles = optarg ? atoi(optarg) : 0;
|
||||||
|
Log2(PCSC_LOG_INFO, "setting customMaxThreadCardHandles to: %d",
|
||||||
|
customMaxThreadCardHandles);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'x':
|
||||||
|
AutoExit = TRUE;
|
||||||
|
Log2(PCSC_LOG_INFO, "Auto exit after %d seconds of inactivity",
|
||||||
|
TIME_BEFORE_SUICIDE);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'S':
|
||||||
|
Add_Serial_In_Name = FALSE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'I':
|
||||||
|
Add_Interface_In_Name = FALSE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
print_usage (argv[0]);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argv[optind])
|
||||||
|
{
|
||||||
|
printf("Unknown option: %s\n", argv[optind]);
|
||||||
|
print_usage(argv[0]);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
Log1(PCSC_LOG_INFO, "Started by systemd");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
SocketActivated = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* test the presence of /var/run/pcscd/pcscd.comm
|
||||||
|
*/
|
||||||
|
|
||||||
|
rv = stat(PCSCLITE_CSOCK_NAME, &fStatBuf);
|
||||||
|
|
||||||
|
/* if the file exist and pcscd was _not_ started by systemd */
|
||||||
|
if (rv == 0 && !SocketActivated)
|
||||||
|
{
|
||||||
|
pid_t pid;
|
||||||
|
|
||||||
|
/* read the pid file to get the old pid and test if the old pcscd is
|
||||||
|
* still running
|
||||||
|
*/
|
||||||
|
pid = GetDaemonPid();
|
||||||
|
|
||||||
|
if (pid != -1)
|
||||||
|
{
|
||||||
|
if (HotPlug)
|
||||||
|
return SendHotplugSignal();
|
||||||
|
|
||||||
|
rv = kill(pid, 0);
|
||||||
|
if (0 == rv)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_CRITICAL,
|
||||||
|
"file " PCSCLITE_CSOCK_NAME " already exists.");
|
||||||
|
Log2(PCSC_LOG_CRITICAL,
|
||||||
|
"Another pcscd (pid: %ld) seems to be running.", (long)pid);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (ESRCH == errno)
|
||||||
|
{
|
||||||
|
/* the old pcscd is dead. make some cleanup */
|
||||||
|
clean_temp_files();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* permission denied or other error */
|
||||||
|
Log2(PCSC_LOG_CRITICAL, "kill failed: %s", strerror(errno));
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (HotPlug)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_CRITICAL, "file " PCSCLITE_RUN_PID " do not exist");
|
||||||
|
Log1(PCSC_LOG_CRITICAL, "Hotplug failed");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (HotPlug)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_CRITICAL, "Hotplug failed: pcscd is not running");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* like in daemon(3): changes the current working directory to the
|
||||||
|
* root ("/") */
|
||||||
|
r = chdir("/");
|
||||||
|
if (r < 0)
|
||||||
|
{
|
||||||
|
Log2(PCSC_LOG_CRITICAL, "chdir() failed: %s", strerror(errno));
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If this is set to one the user has asked it not to fork
|
||||||
|
*/
|
||||||
|
if (!setToForeground)
|
||||||
|
{
|
||||||
|
int pid;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
if (pipe(pipefd) == -1)
|
||||||
|
{
|
||||||
|
Log2(PCSC_LOG_CRITICAL, "pipe() failed: %s", strerror(errno));
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
pid = fork();
|
||||||
|
if (-1 == pid)
|
||||||
|
{
|
||||||
|
Log2(PCSC_LOG_CRITICAL, "fork() failed: %s", strerror(errno));
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* like in daemon(3): redirect standard input, standard output
|
||||||
|
* and standard error to /dev/null */
|
||||||
|
fd = open("/dev/null", O_RDWR);
|
||||||
|
if (fd != -1)
|
||||||
|
{
|
||||||
|
dup2(fd, STDIN_FILENO);
|
||||||
|
dup2(fd, STDOUT_FILENO);
|
||||||
|
dup2(fd, STDERR_FILENO);
|
||||||
|
|
||||||
|
/* do not close stdin, stdout or stderr */
|
||||||
|
if (fd > 2)
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pid)
|
||||||
|
/* in the father */
|
||||||
|
{
|
||||||
|
char buf;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* close write side */
|
||||||
|
close(pipefd[1]);
|
||||||
|
|
||||||
|
/* wait for the son to write the return code */
|
||||||
|
ret = read(pipefd[0], &buf, 1);
|
||||||
|
if (ret <= 0)
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
close(pipefd[0]);
|
||||||
|
|
||||||
|
/* exit code */
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
/* in the son */
|
||||||
|
{
|
||||||
|
/* close read side */
|
||||||
|
close(pipefd[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* cleanly remove /var/run/pcscd/files when exiting
|
||||||
|
* signal_trap() does just set a global variable used by the main loop
|
||||||
|
*/
|
||||||
|
(void)signal(SIGQUIT, signal_trap);
|
||||||
|
(void)signal(SIGTERM, signal_trap); /* default kill signal & init round 1 */
|
||||||
|
(void)signal(SIGINT, signal_trap); /* sent by Ctrl-C */
|
||||||
|
|
||||||
|
/* exits on SIGALARM to allow pcscd to suicide if not used */
|
||||||
|
(void)signal(SIGALRM, signal_trap);
|
||||||
|
|
||||||
|
if (pipe(signal_handler_fd) == -1)
|
||||||
|
{
|
||||||
|
Log2(PCSC_LOG_CRITICAL, "pipe() failed: %s", strerror(errno));
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_t signal_handler_thread;
|
||||||
|
rv = pthread_create(&signal_handler_thread, NULL, signal_thread, NULL);
|
||||||
|
if (rv)
|
||||||
|
{
|
||||||
|
Log2(PCSC_LOG_CRITICAL, "pthread_create failed: %s", strerror(rv));
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If PCSCLITE_IPC_DIR does not exist then create it
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
int mode = S_IROTH | S_IXOTH | S_IRGRP | S_IXGRP | S_IRWXU;
|
||||||
|
|
||||||
|
rv = mkdir(PCSCLITE_IPC_DIR, mode);
|
||||||
|
if ((rv != 0) && (errno != EEXIST))
|
||||||
|
{
|
||||||
|
Log2(PCSC_LOG_CRITICAL,
|
||||||
|
"cannot create " PCSCLITE_IPC_DIR ": %s", strerror(errno));
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set mode so that the directory is world readable and
|
||||||
|
* executable even is umask is restrictive
|
||||||
|
* The directory containes files used by libpcsclite */
|
||||||
|
(void)chmod(PCSCLITE_IPC_DIR, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocate memory for reader structures
|
||||||
|
*/
|
||||||
|
rv = RFAllocateReaderSpace(customMaxReaderHandles);
|
||||||
|
if (SCARD_S_SUCCESS != rv)
|
||||||
|
at_exit();
|
||||||
|
|
||||||
|
#ifdef USE_SERIAL
|
||||||
|
/*
|
||||||
|
* Grab the information from the reader.conf
|
||||||
|
*/
|
||||||
|
if (newReaderConfig)
|
||||||
|
{
|
||||||
|
rv = RFStartSerialReaders(newReaderConfig);
|
||||||
|
if (rv != 0)
|
||||||
|
{
|
||||||
|
Log3(PCSC_LOG_CRITICAL, "invalid file %s: %s", newReaderConfig,
|
||||||
|
strerror(errno));
|
||||||
|
at_exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rv = RFStartSerialReaders(PCSCLITE_CONFIG_DIR);
|
||||||
|
if (rv == -1)
|
||||||
|
at_exit();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Log1(PCSC_LOG_INFO, "pcsc-lite " VERSION " daemon ready.");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Record our pid to make it easier
|
||||||
|
* to kill the correct pcscd
|
||||||
|
*
|
||||||
|
* Do not fork after this point or the stored pid will be wrong
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
int f;
|
||||||
|
int mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
|
||||||
|
|
||||||
|
f = open(PCSCLITE_RUN_PID, O_RDWR | O_CREAT, mode);
|
||||||
|
if (f != -1)
|
||||||
|
{
|
||||||
|
char pid[PID_ASCII_SIZE];
|
||||||
|
ssize_t rr;
|
||||||
|
|
||||||
|
(void)snprintf(pid, sizeof(pid), "%u\n", (unsigned) getpid());
|
||||||
|
rr = write(f, pid, strlen(pid) + 1);
|
||||||
|
if (rr < 0)
|
||||||
|
{
|
||||||
|
Log2(PCSC_LOG_CRITICAL,
|
||||||
|
"writing " PCSCLITE_RUN_PID " failed: %s",
|
||||||
|
strerror(errno));
|
||||||
|
}
|
||||||
|
(void)close(f);
|
||||||
|
|
||||||
|
/* set mode so that the file is world readable even is umask is
|
||||||
|
* restrictive
|
||||||
|
* The file is used by libpcsclite */
|
||||||
|
(void)chmod(PCSCLITE_RUN_PID, mode);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Log2(PCSC_LOG_CRITICAL, "cannot create " PCSCLITE_RUN_PID ": %s",
|
||||||
|
strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* post initialistion
|
||||||
|
*/
|
||||||
|
Init = FALSE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Hotplug rescan
|
||||||
|
*/
|
||||||
|
(void)signal(SIGUSR1, signal_trap);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize the comm structure
|
||||||
|
*/
|
||||||
|
if (SocketActivated)
|
||||||
|
rv = ListenExistingSocket(SD_LISTEN_FDS_START + 0);
|
||||||
|
else
|
||||||
|
rv = InitializeSocket();
|
||||||
|
|
||||||
|
if (rv)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_CRITICAL, "Error initializing pcscd.");
|
||||||
|
at_exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize the contexts structure
|
||||||
|
*/
|
||||||
|
rv = ContextsInitialize(customMaxThreadCounter, customMaxThreadCardHandles);
|
||||||
|
|
||||||
|
if (rv == -1)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_CRITICAL, "Error initializing pcscd.");
|
||||||
|
at_exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
(void)signal(SIGPIPE, SIG_IGN);
|
||||||
|
(void)signal(SIGHUP, SIG_IGN); /* needed for Solaris. The signal is sent
|
||||||
|
* when the shell is existed */
|
||||||
|
|
||||||
|
#if !defined(PCSCLITE_STATIC_DRIVER) && defined(USE_USB)
|
||||||
|
/*
|
||||||
|
* Set up the search for USB/PCMCIA devices
|
||||||
|
*/
|
||||||
|
rv = HPSearchHotPluggables();
|
||||||
|
#ifndef USE_SERIAL
|
||||||
|
if (rv)
|
||||||
|
at_exit();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
rv = HPRegisterForHotplugEvents();
|
||||||
|
if (rv)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_ERROR, "HPRegisterForHotplugEvents failed");
|
||||||
|
at_exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
RFWaitForReaderInit();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* initialisation succeeded */
|
||||||
|
if (pipefd[1] >= 0)
|
||||||
|
{
|
||||||
|
char buf = 0;
|
||||||
|
ssize_t rr;
|
||||||
|
|
||||||
|
/* write a 0 (success) to father process */
|
||||||
|
rr = write(pipefd[1], &buf, 1);
|
||||||
|
if (rr < 0)
|
||||||
|
{
|
||||||
|
Log2(PCSC_LOG_ERROR, "write() failed: %s", strerror(errno));
|
||||||
|
}
|
||||||
|
close(pipefd[1]);
|
||||||
|
pipefd[1] = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
SVCServiceRunLoop();
|
||||||
|
|
||||||
|
Log1(PCSC_LOG_ERROR, "SVCServiceRunLoop returned");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void at_exit(void)
|
||||||
|
{
|
||||||
|
Log1(PCSC_LOG_INFO, "cleaning " PCSCLITE_IPC_DIR);
|
||||||
|
|
||||||
|
clean_temp_files();
|
||||||
|
|
||||||
|
if (pipefd[1] >= 0)
|
||||||
|
{
|
||||||
|
char buf;
|
||||||
|
ssize_t r;
|
||||||
|
|
||||||
|
/* write the error code to father process */
|
||||||
|
buf = ExitValue;
|
||||||
|
r = write(pipefd[1], &buf, 1);
|
||||||
|
if (r < 0)
|
||||||
|
{
|
||||||
|
Log2(PCSC_LOG_ERROR, "write() failed: %s", strerror(errno));
|
||||||
|
}
|
||||||
|
close(pipefd[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
exit(ExitValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void clean_temp_files(void)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
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)
|
||||||
|
Log2(PCSC_LOG_ERROR, "Cannot remove " PCSCLITE_RUN_PID ": %s",
|
||||||
|
strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void signal_trap(int sig)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
|
||||||
|
r = write(signal_handler_fd[1], &sig, sizeof sig);
|
||||||
|
if (r < 0)
|
||||||
|
Log2(PCSC_LOG_ERROR, "write failed: %s", strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_version(void)
|
||||||
|
{
|
||||||
|
printf("%s version %s.\n", PACKAGE, VERSION);
|
||||||
|
printf("Copyright (C) 1999-2002 by David Corcoran <corcoran@musclecard.com>.\n");
|
||||||
|
printf("Copyright (C) 2001-2015 by Ludovic Rousseau <ludovic.rousseau@free.fr>.\n");
|
||||||
|
printf("Copyright (C) 2003-2004 by Damien Sauveron <sauveron@labri.fr>.\n");
|
||||||
|
printf("Report bugs to <pcsclite-muscle@lists.alioth.debian.org>.\n");
|
||||||
|
|
||||||
|
printf ("Enabled features:%s\n", PCSCLITE_FEATURES);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_usage(char const * const progname)
|
||||||
|
{
|
||||||
|
printf("Usage: %s options\n", progname);
|
||||||
|
printf("Options:\n");
|
||||||
|
#ifdef HAVE_GETOPT_LONG
|
||||||
|
printf(" -a, --apdu log APDU commands and results\n");
|
||||||
|
printf(" -c, --config path to reader.conf\n");
|
||||||
|
printf(" -f, --foreground run in foreground (no daemon),\n");
|
||||||
|
printf(" send logs to stdout instead of syslog\n");
|
||||||
|
printf(" -T, --color force use of colored logs\n");
|
||||||
|
printf(" -h, --help display usage information\n");
|
||||||
|
printf(" -H, --hotplug ask the daemon to rescan the available readers\n");
|
||||||
|
printf(" -v, --version display the program version number\n");
|
||||||
|
printf(" -d, --debug display lower level debug messages\n");
|
||||||
|
printf(" -i, --info display info level debug messages\n");
|
||||||
|
printf(" -e --error display error level debug messages (default level)\n");
|
||||||
|
printf(" -C --critical display critical only level debug messages\n");
|
||||||
|
printf(" --force-reader-polling ignore the IFD_GENERATE_HOTPLUG reader capability\n");
|
||||||
|
printf(" -t, --max-thread maximum number of threads (default %d)\n", PCSC_MAX_CONTEXT_THREADS);
|
||||||
|
printf(" -s, --max-card-handle-per-thread maximum number of card handle per thread (default: %d)\n", PCSC_MAX_CONTEXT_CARD_HANDLES);
|
||||||
|
printf(" -r, --max-card-handle-per-reader maximum number of card handle per reader (default: %d)\n", PCSC_MAX_READER_HANDLES);
|
||||||
|
printf(" -x, --auto-exit pcscd will quit after %d seconds of inactivity\n", TIME_BEFORE_SUICIDE);
|
||||||
|
printf(" -S, --reader-name-no-serial do not include the USB serial number in the name\n");
|
||||||
|
printf(" -I, --reader-name-no-interface do not include the USB interface name in the name\n");
|
||||||
|
#else
|
||||||
|
printf(" -a log APDU commands and results\n");
|
||||||
|
printf(" -c path to reader.conf\n");
|
||||||
|
printf(" -f run in foreground (no daemon), send logs to stdout instead of syslog\n");
|
||||||
|
printf(" -T force use of colored logs\n");
|
||||||
|
printf(" -d display debug messages.\n");
|
||||||
|
printf(" -i display info messages.\n");
|
||||||
|
printf(" -e display error messages (default level).\n");
|
||||||
|
printf(" -C display critical messages.\n");
|
||||||
|
printf(" -h display usage information\n");
|
||||||
|
printf(" -H ask the daemon to rescan the available readers\n");
|
||||||
|
printf(" -v display the program version number\n");
|
||||||
|
printf(" -t maximum number of threads\n");
|
||||||
|
printf(" -s maximum number of card handle per thread\n");
|
||||||
|
printf(" -r maximum number of card handle per reader\n");
|
||||||
|
printf(" -x pcscd will quit after %d seconds of inactivity\n", TIME_BEFORE_SUICIDE);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,135 @@
|
||||||
|
/*
|
||||||
|
* MUSCLE SmartCard Development ( http://pcsclite.alioth.debian.org/pcsclite.html )
|
||||||
|
*
|
||||||
|
* Copyright (C) 1999
|
||||||
|
* David Corcoran <corcoran@musclecard.com>
|
||||||
|
* Copyright (C) 2004-2011
|
||||||
|
* Ludovic Rousseau <ludovic.rousseau@free.fr>
|
||||||
|
*
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. The name of the author may not be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief This handles protocol defaults, PTS, etc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "misc.h"
|
||||||
|
#include "pcscd.h"
|
||||||
|
#include "debuglog.h"
|
||||||
|
#include "readerfactory.h"
|
||||||
|
#include "prothandler.h"
|
||||||
|
#include "atrhandler.h"
|
||||||
|
#include "ifdwrapper.h"
|
||||||
|
#include "eventhandler.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine which protocol to use.
|
||||||
|
*
|
||||||
|
* SCardConnect has a DWORD dwPreferredProtocols that is a bitmask of what
|
||||||
|
* protocols to use. Basically, if T=N where N is not zero will be used
|
||||||
|
* first if it is available in ucAvailable. Otherwise it will always
|
||||||
|
* default to T=0.
|
||||||
|
*
|
||||||
|
* IFDSetPTS() is _always_ called so that the driver can initialise its data
|
||||||
|
*/
|
||||||
|
DWORD PHSetProtocol(struct ReaderContext * rContext,
|
||||||
|
DWORD dwPreferred, UCHAR ucAvailable, UCHAR ucDefault)
|
||||||
|
{
|
||||||
|
DWORD protocol;
|
||||||
|
LONG rv;
|
||||||
|
UCHAR ucChosen;
|
||||||
|
|
||||||
|
/* App has specified no protocol */
|
||||||
|
if (dwPreferred == 0)
|
||||||
|
return SET_PROTOCOL_WRONG_ARGUMENT;
|
||||||
|
|
||||||
|
/* requested protocol is not available */
|
||||||
|
if (! (dwPreferred & ucAvailable))
|
||||||
|
{
|
||||||
|
/* Note:
|
||||||
|
* dwPreferred must be either SCARD_PROTOCOL_T0 or SCARD_PROTOCOL_T1
|
||||||
|
* if dwPreferred == SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1 the test
|
||||||
|
* (SCARD_PROTOCOL_T0 == dwPreferred) will not work as expected
|
||||||
|
* and the debug message will not be correct.
|
||||||
|
*
|
||||||
|
* This case may only occur if
|
||||||
|
* dwPreferred == SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1
|
||||||
|
* and ucAvailable == 0 since we have (dwPreferred & ucAvailable) == 0
|
||||||
|
* and the case ucAvailable == 0 should never occur (the card is at
|
||||||
|
* least T=0 or T=1)
|
||||||
|
*/
|
||||||
|
Log2(PCSC_LOG_ERROR, "Protocol T=%d requested but unsupported by the card",
|
||||||
|
(SCARD_PROTOCOL_T0 == dwPreferred) ? 0 : 1);
|
||||||
|
return SET_PROTOCOL_WRONG_ARGUMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set default value */
|
||||||
|
protocol = ucDefault;
|
||||||
|
|
||||||
|
/* keep only the available protocols */
|
||||||
|
dwPreferred &= ucAvailable;
|
||||||
|
|
||||||
|
/* we try to use T=1 first */
|
||||||
|
if (dwPreferred & SCARD_PROTOCOL_T1)
|
||||||
|
ucChosen = SCARD_PROTOCOL_T1;
|
||||||
|
else
|
||||||
|
if (dwPreferred & SCARD_PROTOCOL_T0)
|
||||||
|
ucChosen = SCARD_PROTOCOL_T0;
|
||||||
|
else
|
||||||
|
/* App wants unsupported protocol */
|
||||||
|
return SET_PROTOCOL_WRONG_ARGUMENT;
|
||||||
|
|
||||||
|
Log2(PCSC_LOG_INFO, "Attempting PTS to T=%d",
|
||||||
|
(SCARD_PROTOCOL_T0 == ucChosen ? 0 : 1));
|
||||||
|
rv = IFDSetPTS(rContext, ucChosen, 0x00, 0x00, 0x00, 0x00);
|
||||||
|
|
||||||
|
if (IFD_SUCCESS == rv)
|
||||||
|
protocol = ucChosen;
|
||||||
|
else
|
||||||
|
if (IFD_NOT_SUPPORTED == rv)
|
||||||
|
Log2(PCSC_LOG_INFO, "PTS not supported by driver, using T=%d",
|
||||||
|
(SCARD_PROTOCOL_T0 == protocol) ? 0 : 1);
|
||||||
|
else
|
||||||
|
if (IFD_PROTOCOL_NOT_SUPPORTED == rv)
|
||||||
|
Log2(PCSC_LOG_INFO, "PTS protocol not supported, using T=%d",
|
||||||
|
(SCARD_PROTOCOL_T0 == protocol) ? 0 : 1);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log3(PCSC_LOG_INFO, "PTS failed (%ld), using T=%d", rv,
|
||||||
|
(SCARD_PROTOCOL_T0 == protocol) ? 0 : 1);
|
||||||
|
|
||||||
|
/* ISO 7816-3:1997 ch. 7.2 PPS protocol page 14
|
||||||
|
* - If the PPS exchange is unsuccessful, then the interface device
|
||||||
|
* shall either reset or reject the card.
|
||||||
|
*/
|
||||||
|
return SET_PROTOCOL_PPS_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return protocol;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* MUSCLE SmartCard Development ( http://pcsclite.alioth.debian.org/pcsclite.html )
|
||||||
|
*
|
||||||
|
* Copyright (C) 1999
|
||||||
|
* David Corcoran <corcoran@musclecard.com>
|
||||||
|
* Copyright (C) 2004
|
||||||
|
* Ludovic Rousseau <ludovic.rousseau@free.fr>
|
||||||
|
*
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. The name of the author may not be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief This handles protocol defaults, PTS, etc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __prothandler_h__
|
||||||
|
#define __prothandler_h__
|
||||||
|
|
||||||
|
DWORD PHSetProtocol(struct ReaderContext *, DWORD, UCHAR, UCHAR);
|
||||||
|
|
||||||
|
#define SET_PROTOCOL_WRONG_ARGUMENT -1
|
||||||
|
#define SET_PROTOCOL_PPS_FAILED -2
|
||||||
|
|
||||||
|
#endif /* __prothandler_h__ */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,177 @@
|
||||||
|
/*
|
||||||
|
* MUSCLE SmartCard Development ( http://pcsclite.alioth.debian.org/pcsclite.html )
|
||||||
|
*
|
||||||
|
* Copyright (C) 1999
|
||||||
|
* David Corcoran <corcoran@musclecard.com>
|
||||||
|
* Copyright (C) 2002-2011
|
||||||
|
* Ludovic Rousseau <ludovic.rousseau@free.fr>
|
||||||
|
*
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. The name of the author may not be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief This keeps track of a list of currently available reader structures.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __readerfactory_h__
|
||||||
|
#define __readerfactory_h__
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
#include "ifdhandler.h"
|
||||||
|
#include "pcscd.h"
|
||||||
|
#include "simclist.h"
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char *pcFriendlyname; /**< FRIENDLYNAME */
|
||||||
|
char *pcDevicename; /**< DEVICENAME */
|
||||||
|
char *pcLibpath; /**< LIBPATH */
|
||||||
|
int channelId; /**< CHANNELID */
|
||||||
|
} SerialReader;
|
||||||
|
|
||||||
|
struct FctMap_V2
|
||||||
|
{
|
||||||
|
/* shared with API 3.0 */
|
||||||
|
RESPONSECODE (*pvfCreateChannel)(DWORD, DWORD);
|
||||||
|
RESPONSECODE (*pvfCloseChannel)(DWORD);
|
||||||
|
RESPONSECODE (*pvfGetCapabilities)(DWORD, DWORD, PDWORD, PUCHAR);
|
||||||
|
RESPONSECODE (*pvfSetCapabilities)(DWORD, DWORD, DWORD, PUCHAR);
|
||||||
|
RESPONSECODE (*pvfSetProtocolParameters)(DWORD, DWORD, UCHAR, UCHAR,
|
||||||
|
UCHAR, UCHAR);
|
||||||
|
RESPONSECODE (*pvfPowerICC)(DWORD, DWORD, PUCHAR, PDWORD);
|
||||||
|
RESPONSECODE (*pvfTransmitToICC)(DWORD, SCARD_IO_HEADER, PUCHAR,
|
||||||
|
DWORD, PUCHAR, PDWORD, PSCARD_IO_HEADER);
|
||||||
|
RESPONSECODE (*pvfICCPresence)(DWORD);
|
||||||
|
|
||||||
|
/* API v2.0 only */
|
||||||
|
RESPONSECODE (*pvfControl)(DWORD, PUCHAR, DWORD, PUCHAR, PDWORD);
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct FctMap_V2 FCT_MAP_V2;
|
||||||
|
|
||||||
|
struct FctMap_V3
|
||||||
|
{
|
||||||
|
/* the common fields SHALL be in the same order as in FctMap_V2 */
|
||||||
|
RESPONSECODE (*pvfCreateChannel)(DWORD, DWORD);
|
||||||
|
RESPONSECODE (*pvfCloseChannel)(DWORD);
|
||||||
|
RESPONSECODE (*pvfGetCapabilities)(DWORD, DWORD, PDWORD, PUCHAR);
|
||||||
|
RESPONSECODE (*pvfSetCapabilities)(DWORD, DWORD, DWORD, PUCHAR);
|
||||||
|
RESPONSECODE (*pvfSetProtocolParameters)(DWORD, DWORD, UCHAR, UCHAR,
|
||||||
|
UCHAR, UCHAR);
|
||||||
|
RESPONSECODE (*pvfPowerICC)(DWORD, DWORD, PUCHAR, PDWORD);
|
||||||
|
RESPONSECODE (*pvfTransmitToICC)(DWORD, SCARD_IO_HEADER, PUCHAR,
|
||||||
|
DWORD, PUCHAR, PDWORD, PSCARD_IO_HEADER);
|
||||||
|
RESPONSECODE (*pvfICCPresence)(DWORD);
|
||||||
|
|
||||||
|
/* API V3.0 only */
|
||||||
|
RESPONSECODE (*pvfControl)(DWORD, DWORD, LPCVOID, DWORD, LPVOID,
|
||||||
|
DWORD, LPDWORD);
|
||||||
|
RESPONSECODE (*pvfCreateChannelByName)(DWORD, LPSTR);
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct FctMap_V3 FCT_MAP_V3;
|
||||||
|
|
||||||
|
struct RdrCliHandles
|
||||||
|
{
|
||||||
|
SCARDHANDLE hCard; /**< hCard for this connection */
|
||||||
|
DWORD dwEventStatus; /**< Recent event that must be sent */
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct RdrCliHandles RDR_CLIHANDLES;
|
||||||
|
|
||||||
|
struct ReaderContext
|
||||||
|
{
|
||||||
|
char *library; /**< Library Path */
|
||||||
|
char *device; /**< Device Name */
|
||||||
|
pthread_t pthThread; /**< Event polling thread */
|
||||||
|
RESPONSECODE (*pthCardEvent)(DWORD, int); /**< Card Event sync */
|
||||||
|
pthread_mutex_t *mMutex; /**< Mutex for this connection */
|
||||||
|
list_t handlesList;
|
||||||
|
pthread_mutex_t handlesList_lock; /**< lock for the above list */
|
||||||
|
/**< Structure of connected handles */
|
||||||
|
union
|
||||||
|
{
|
||||||
|
FCT_MAP_V2 psFunctions_v2; /**< API V2.0 */
|
||||||
|
FCT_MAP_V3 psFunctions_v3; /**< API V3.0 */
|
||||||
|
} psFunctions; /**< driver functions */
|
||||||
|
|
||||||
|
LPVOID vHandle; /**< Dlopen handle */
|
||||||
|
int version; /**< IFD Handler version number */
|
||||||
|
int port; /**< Port ID */
|
||||||
|
int slot; /**< Current Reader Slot */
|
||||||
|
volatile SCARDHANDLE hLockId; /**< Lock Id */
|
||||||
|
int LockCount; /**< number of recursive locks */
|
||||||
|
int32_t contexts; /**< Number of open contexts */
|
||||||
|
int * pFeeds; /**< Number of shared client to lib */
|
||||||
|
int * pMutex; /**< Number of client to mutex */
|
||||||
|
int powerState; /**< auto power off state */
|
||||||
|
pthread_mutex_t powerState_lock; /**< powerState mutex */
|
||||||
|
int reference; /**< number of users of the structure */
|
||||||
|
pthread_mutex_t reference_lock; /**< reference mutex */
|
||||||
|
|
||||||
|
struct pubReaderStatesList *readerState; /**< link to the reader state */
|
||||||
|
/* we can't use READER_STATE * here since eventhandler.h can't be
|
||||||
|
* included because of circular dependencies */
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct ReaderContext READER_CONTEXT;
|
||||||
|
|
||||||
|
LONG _RefReader(READER_CONTEXT * sReader);
|
||||||
|
LONG _UnrefReader(READER_CONTEXT * sReader);
|
||||||
|
|
||||||
|
#define REF_READER(reader) { LONG rv; Log2(PCSC_LOG_DEBUG, "RefReader() count was: %d", reader->reference); rv = _RefReader(reader); if (rv != SCARD_S_SUCCESS) return rv; }
|
||||||
|
#define UNREF_READER(reader) {Log2(PCSC_LOG_DEBUG, "UnrefReader() count was: %d", reader->reference); _UnrefReader(reader);}
|
||||||
|
|
||||||
|
LONG RFAllocateReaderSpace(unsigned int);
|
||||||
|
LONG RFAddReader(const char *, int, const char *, const char *);
|
||||||
|
LONG RFRemoveReader(const char *, int);
|
||||||
|
LONG RFSetReaderName(READER_CONTEXT *, const char *, const char *, int);
|
||||||
|
LONG RFReaderInfo(const char *, /*@out@*/ struct ReaderContext **);
|
||||||
|
LONG RFReaderInfoById(SCARDHANDLE, /*@out@*/ struct ReaderContext **);
|
||||||
|
LONG RFCheckSharing(SCARDHANDLE, READER_CONTEXT *);
|
||||||
|
LONG RFLockSharing(SCARDHANDLE, READER_CONTEXT *);
|
||||||
|
LONG RFUnlockSharing(SCARDHANDLE, READER_CONTEXT *);
|
||||||
|
LONG RFUnlockAllSharing(SCARDHANDLE, READER_CONTEXT *);
|
||||||
|
LONG RFLoadReader(READER_CONTEXT *);
|
||||||
|
LONG RFBindFunctions(READER_CONTEXT *);
|
||||||
|
LONG RFUnBindFunctions(READER_CONTEXT *);
|
||||||
|
LONG RFUnloadReader(READER_CONTEXT *);
|
||||||
|
LONG RFInitializeReader(READER_CONTEXT *);
|
||||||
|
void RFUnInitializeReader(READER_CONTEXT *);
|
||||||
|
SCARDHANDLE RFCreateReaderHandle(READER_CONTEXT *);
|
||||||
|
LONG RFAddReaderHandle(READER_CONTEXT *, SCARDHANDLE);
|
||||||
|
LONG RFRemoveReaderHandle(READER_CONTEXT *, SCARDHANDLE);
|
||||||
|
void RFSetReaderEventState(READER_CONTEXT *, DWORD);
|
||||||
|
LONG RFCheckReaderEventState(READER_CONTEXT *, SCARDHANDLE);
|
||||||
|
LONG RFClearReaderEventState(READER_CONTEXT *, SCARDHANDLE);
|
||||||
|
LONG RFCheckReaderStatus(READER_CONTEXT *);
|
||||||
|
void RFCleanupReaders(void);
|
||||||
|
void RFWaitForReaderInit(void);
|
||||||
|
int RFStartSerialReaders(const char *readerconf);
|
||||||
|
void RFReCheckReaderConf(void);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,526 @@
|
||||||
|
/*-*- 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)
|
||||||
|
#ifdef SD_EXPORT_SYMBOLS
|
||||||
|
/* Export symbols */
|
||||||
|
#define _sd_export_ __attribute__ ((visibility("default")))
|
||||||
|
#else
|
||||||
|
/* Don't export the symbols */
|
||||||
|
#define _sd_export_ __attribute__ ((visibility("hidden")))
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define _sd_export_
|
||||||
|
#endif
|
||||||
|
|
||||||
|
_sd_export_ 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_export_ 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_export_ 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_export_ 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_export_ 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_export_ 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_export_ 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_export_ 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_export_ 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_export_ 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
|
||||||
|
}
|
|
@ -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
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue