New upstream version 1.8.22

This commit is contained in:
Ludovic Rousseau 2017-12-09 18:15:20 +01:00
parent 8030f65243
commit acc3243be1
124 changed files with 131806 additions and 0 deletions

9
AUTHORS Normal file
View File

@ -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

119
COPYING Normal file
View File

@ -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.

1800
ChangeLog Normal file

File diff suppressed because it is too large Load Diff

43502
ChangeLog.git Normal file

File diff suppressed because it is too large Load Diff

28
DRIVERS Normal file
View File

@ -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.

674
GPL-3.0.txt Normal file
View File

@ -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>.

12
HELP Normal file
View File

@ -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

370
INSTALL Normal file
View File

@ -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.

24
Makefile.am Normal file
View File

@ -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 > $@

868
Makefile.in Normal file
View File

@ -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:

1
NEWS Normal file
View File

@ -0,0 +1 @@
Read the ChangeLog file for news.

114
README Normal file
View File

@ -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"

16
SECURITY Normal file
View File

@ -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.

11
TODO Normal file
View File

@ -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

1549
aclocal.m4 vendored Normal file

File diff suppressed because it is too large Load Diff

270
ar-lib Executable file
View File

@ -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

16
bootstrap Executable file
View File

@ -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

347
compile Executable file
View File

@ -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:

1462
config.guess vendored Executable file

File diff suppressed because it is too large Load Diff

244
config.h.in Normal file
View File

@ -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

1825
config.sub vendored Executable file

File diff suppressed because it is too large Load Diff

17841
configure vendored Executable file

File diff suppressed because it is too large Load Diff

460
configure.ac Normal file
View File

@ -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

791
depcomp Executable file
View File

@ -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:

25
doc/Makefile.am Normal file
View File

@ -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

834
doc/Makefile.in Normal file
View File

@ -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:

15
doc/README.DAEMON Normal file
View File

@ -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 )

39
doc/README.polkit Normal file
View File

@ -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".

2313
doc/doxygen.conf.in Normal file

File diff suppressed because it is too large Load Diff

6
doc/example/Makefile.am Normal file
View File

@ -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

638
doc/example/Makefile.in Normal file
View File

@ -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:

285
doc/example/pcsc_demo.c Normal file
View File

@ -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 */

39
doc/formaticc.1 Normal file
View File

@ -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)

View File

@ -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>

131
doc/pcscd.8.in Normal file
View File

@ -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>

78
doc/reader.conf.5.in Normal file
View File

@ -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)

9
etc/Makefile.am Normal file
View File

@ -0,0 +1,9 @@
if HAVE_SYSTEMD
SCRIPT_IN_FILES = \
pcscd.service.in \
pcscd.socket.in
systemdsystemunit_DATA = \
pcscd.service \
pcscd.socket
endif

538
etc/Makefile.in Normal file
View File

@ -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:

10
etc/pcscd.service.in Normal file
View File

@ -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

8
etc/pcscd.socket.in Normal file
View File

@ -0,0 +1,8 @@
[Unit]
Description=PC/SC Smart Card Daemon Activation Socket
[Socket]
ListenStream=@ipcdir@/pcscd.comm
[Install]
WantedBy=sockets.target

527
install-sh Executable file
View File

@ -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:

11156
ltmain.sh Normal file

File diff suppressed because it is too large Load Diff

43
m4/as-ac-expand.m4 Normal file
View File

@ -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
])

309
m4/ax_pthread.m4 Normal file
View File

@ -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

8387
m4/libtool.m4 vendored Normal file

File diff suppressed because it is too large Load Diff

437
m4/ltoptions.m4 vendored Normal file
View File

@ -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])])

123
m4/ltsugar.m4 vendored Normal file
View File

@ -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
])

23
m4/ltversion.m4 vendored Normal file
View File

@ -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)
])

98
m4/lt~obsolete.m4 vendored Normal file
View File

@ -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])])

215
missing Executable file
View File

@ -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:

153
src/Makefile.am Normal file
View File

@ -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

1618
src/Makefile.in Normal file

File diff suppressed because it is too large Load Diff

133
src/PCSC/debuglog.h Normal file
View File

@ -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__ */

827
src/PCSC/ifdhandler.h Normal file
View File

@ -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

309
src/PCSC/pcsclite.h Normal file
View File

@ -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

309
src/PCSC/pcsclite.h.in Normal file
View File

@ -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

271
src/PCSC/reader.h Normal file
View File

@ -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

123
src/PCSC/winscard.h Normal file
View File

@ -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

115
src/PCSC/wintypes.h Normal file
View File

@ -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

231
src/README_INTERNALS.txt Normal file
View File

@ -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>

226
src/atrhandler.c Normal file
View File

@ -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 */
}

48
src/atrhandler.h Normal file
View File

@ -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__ */

160
src/auth.c Normal file
View File

@ -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

35
src/auth.h Normal file
View File

@ -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);

2124
src/configfile.c Normal file

File diff suppressed because it is too large Load Diff

53
src/configfile.h Normal file
View File

@ -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__ */

396
src/configfile.l Normal file
View File

@ -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 */

155
src/debug.c Normal file
View File

@ -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

357
src/debuglog.c Normal file
View File

@ -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 */

45
src/dyn_generic.h Normal file
View File

@ -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

108
src/dyn_hpux.c Normal file
View File

@ -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 */

133
src/dyn_macosx.c Normal file
View File

@ -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__ */

115
src/dyn_unix.c Normal file
View File

@ -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__ */

243
src/error.c Normal file
View File

@ -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

508
src/eventhandler.c Normal file
View File

@ -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);
}
}
}

82
src/eventhandler.h Normal file
View File

@ -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__ */

59
src/hotplug.h Normal file
View File

@ -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

72
src/hotplug_generic.c Normal file
View File

@ -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

788
src/hotplug_libudev.c Normal file
View File

@ -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

660
src/hotplug_libusb.c Normal file
View File

@ -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

472
src/hotplug_linux.c Normal file
View File

@ -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 */

855
src/hotplug_macosx.c Normal file
View File

@ -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__ */

554
src/ifdwrapper.c Normal file
View File

@ -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;
}
}

56
src/ifdwrapper.h Normal file
View File

@ -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__ */

64
src/lassert.h Normal file
View File

@ -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 */

13
src/libpcsclite.pc.in Normal file
View File

@ -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@

85
src/misc.h Normal file
View File

@ -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__ */

53
src/parser.h Normal file
View File

@ -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

367
src/pcsc-wirecheck-dist.c Normal file
View File

@ -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;
}

282
src/pcsc-wirecheck-gen.c Normal file
View File

@ -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;
}

15
src/pcsc-wirecheck-main.c Normal file
View File

@ -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;
}

86
src/pcscd.h Normal file
View File

@ -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

86
src/pcscd.h.in Normal file
View File

@ -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

881
src/pcscdaemon.c Normal file
View File

@ -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
}

135
src/prothandler.c Normal file
View File

@ -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;
}

46
src/prothandler.h Normal file
View File

@ -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__ */

1555
src/readerfactory.c Normal file

File diff suppressed because it is too large Load Diff

177
src/readerfactory.h Normal file
View File

@ -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

526
src/sd-daemon.c Normal file
View File

@ -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
}

277
src/sd-daemon.h Normal file
View File

@ -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